implement redirect destinations
This commit is contained in:
@@ -20,6 +20,7 @@ constexpr uint32_t GAME = 0x44000044;
|
|||||||
constexpr uint32_t QUEST = 0x55000055;
|
constexpr uint32_t QUEST = 0x55000055;
|
||||||
constexpr uint32_t QUEST_FILTER = 0x66000066;
|
constexpr uint32_t QUEST_FILTER = 0x66000066;
|
||||||
constexpr uint32_t PROXY_DESTINATIONS = 0x77000077;
|
constexpr uint32_t PROXY_DESTINATIONS = 0x77000077;
|
||||||
|
constexpr uint32_t REDIRECT_DESTINATIONS = 0x78000078;
|
||||||
constexpr uint32_t PROGRAMS = 0x88000088;
|
constexpr uint32_t PROGRAMS = 0x88000088;
|
||||||
constexpr uint32_t PATCHES = 0x99000099;
|
constexpr uint32_t PATCHES = 0x99000099;
|
||||||
constexpr uint32_t PROXY_OPTIONS = 0xAA0000AA;
|
constexpr uint32_t PROXY_OPTIONS = 0xAA0000AA;
|
||||||
@@ -33,6 +34,7 @@ constexpr uint32_t GO_TO_LOBBY = 0x11222211;
|
|||||||
constexpr uint32_t INFORMATION = 0x11333311;
|
constexpr uint32_t INFORMATION = 0x11333311;
|
||||||
constexpr uint32_t DOWNLOAD_QUESTS = 0x11444411;
|
constexpr uint32_t DOWNLOAD_QUESTS = 0x11444411;
|
||||||
constexpr uint32_t PROXY_DESTINATIONS = 0x11555511;
|
constexpr uint32_t PROXY_DESTINATIONS = 0x11555511;
|
||||||
|
constexpr uint32_t REDIRECT_DESTINATIONS = 0x11565611;
|
||||||
constexpr uint32_t PATCHES = 0x11666611;
|
constexpr uint32_t PATCHES = 0x11666611;
|
||||||
constexpr uint32_t PROGRAMS = 0x11777711;
|
constexpr uint32_t PROGRAMS = 0x11777711;
|
||||||
constexpr uint32_t DISCONNECT = 0x11888811;
|
constexpr uint32_t DISCONNECT = 0x11888811;
|
||||||
@@ -48,6 +50,11 @@ constexpr uint32_t GO_BACK = 0x77FFFF77;
|
|||||||
constexpr uint32_t OPTIONS = 0x77EEEE77;
|
constexpr uint32_t OPTIONS = 0x77EEEE77;
|
||||||
} // namespace ProxyDestinationsMenuItemID
|
} // namespace ProxyDestinationsMenuItemID
|
||||||
|
|
||||||
|
namespace RedirectDestinationsMenuItemID {
|
||||||
|
constexpr uint32_t GO_BACK = 0x78FFFF78;
|
||||||
|
constexpr uint32_t OPTIONS = 0x78EEEE78;
|
||||||
|
} // namespace RedirectDestinationsMenuItemID
|
||||||
|
|
||||||
namespace ProgramsMenuItemID {
|
namespace ProgramsMenuItemID {
|
||||||
constexpr uint32_t GO_BACK = 0x88FFFF88;
|
constexpr uint32_t GO_BACK = 0x88FFFF88;
|
||||||
}
|
}
|
||||||
|
|||||||
+58
-1
@@ -119,6 +119,11 @@ static void send_proxy_destinations_menu(shared_ptr<Client> c) {
|
|||||||
send_menu(c, s->proxy_destinations_menu_for_version(c->version()));
|
send_menu(c, s->proxy_destinations_menu_for_version(c->version()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void send_redirect_destinations_menu(shared_ptr<Client> c) {
|
||||||
|
auto s = c->require_server_state();
|
||||||
|
send_menu(c, s->redirect_destinations_menu_for_version(c->version()));
|
||||||
|
}
|
||||||
|
|
||||||
static bool send_enable_send_function_call_if_applicable(shared_ptr<Client> c) {
|
static bool send_enable_send_function_call_if_applicable(shared_ptr<Client> c) {
|
||||||
auto s = c->require_server_state();
|
auto s = c->require_server_state();
|
||||||
if (function_compiler_available() &&
|
if (function_compiler_available() &&
|
||||||
@@ -206,6 +211,7 @@ static void send_main_menu(shared_ptr<Client> c) {
|
|||||||
0);
|
0);
|
||||||
main_menu->items.emplace_back(MainMenuItemID::INFORMATION, u"Information",
|
main_menu->items.emplace_back(MainMenuItemID::INFORMATION, u"Information",
|
||||||
u"View server\ninformation", MenuItem::Flag::INVISIBLE_ON_DCNTE | MenuItem::Flag::REQUIRES_MESSAGE_BOXES);
|
u"View server\ninformation", MenuItem::Flag::INVISIBLE_ON_DCNTE | MenuItem::Flag::REQUIRES_MESSAGE_BOXES);
|
||||||
|
|
||||||
uint32_t proxy_destinations_menu_item_flags =
|
uint32_t proxy_destinations_menu_item_flags =
|
||||||
// DCNTE doesn't support multiple ship select menus without changing
|
// DCNTE doesn't support multiple ship select menus without changing
|
||||||
// servers (via a 19 command) apparently :(
|
// servers (via a 19 command) apparently :(
|
||||||
@@ -216,7 +222,24 @@ static void send_main_menu(shared_ptr<Client> c) {
|
|||||||
(s->proxy_destinations_xb.empty() ? MenuItem::Flag::INVISIBLE_ON_XB : 0) |
|
(s->proxy_destinations_xb.empty() ? MenuItem::Flag::INVISIBLE_ON_XB : 0) |
|
||||||
MenuItem::Flag::INVISIBLE_ON_BB;
|
MenuItem::Flag::INVISIBLE_ON_BB;
|
||||||
main_menu->items.emplace_back(MainMenuItemID::PROXY_DESTINATIONS, u"Proxy server",
|
main_menu->items.emplace_back(MainMenuItemID::PROXY_DESTINATIONS, u"Proxy server",
|
||||||
u"Connect to another\nserver", proxy_destinations_menu_item_flags);
|
u"Connect to another\nserver through the\nproxy", proxy_destinations_menu_item_flags);
|
||||||
|
|
||||||
|
// If the client is on a virtual connection, redirecting will not work
|
||||||
|
// properly (they'll just be reconencted to newserv), so hide the option
|
||||||
|
if (!c->channel.is_virtual_connection) {
|
||||||
|
uint32_t redirect_destinations_menu_item_flags =
|
||||||
|
// DCNTE doesn't support multiple ship select menus without changing
|
||||||
|
// servers (via a 19 command) apparently :(
|
||||||
|
MenuItem::Flag::INVISIBLE_ON_DCNTE |
|
||||||
|
(s->redirect_destinations_dc.empty() ? MenuItem::Flag::INVISIBLE_ON_DC : 0) |
|
||||||
|
(s->redirect_destinations_pc.empty() ? MenuItem::Flag::INVISIBLE_ON_PC : 0) |
|
||||||
|
(s->redirect_destinations_gc.empty() ? MenuItem::Flag::INVISIBLE_ON_GC : 0) |
|
||||||
|
(s->redirect_destinations_xb.empty() ? MenuItem::Flag::INVISIBLE_ON_XB : 0) |
|
||||||
|
MenuItem::Flag::INVISIBLE_ON_BB;
|
||||||
|
main_menu->items.emplace_back(MainMenuItemID::REDIRECT_DESTINATIONS, u"Other servers",
|
||||||
|
u"Connect to another\nserver directly", redirect_destinations_menu_item_flags);
|
||||||
|
}
|
||||||
|
|
||||||
main_menu->items.emplace_back(MainMenuItemID::DOWNLOAD_QUESTS, u"Download quests",
|
main_menu->items.emplace_back(MainMenuItemID::DOWNLOAD_QUESTS, u"Download quests",
|
||||||
u"Download quests", MenuItem::Flag::INVISIBLE_ON_DCNTE | MenuItem::Flag::INVISIBLE_ON_BB);
|
u"Download quests", MenuItem::Flag::INVISIBLE_ON_DCNTE | MenuItem::Flag::INVISIBLE_ON_BB);
|
||||||
if (!s->is_replay) {
|
if (!s->is_replay) {
|
||||||
@@ -1702,6 +1725,10 @@ static void on_10(shared_ptr<Client> c, uint16_t, uint32_t, const string& data)
|
|||||||
send_proxy_destinations_menu(c);
|
send_proxy_destinations_menu(c);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case MainMenuItemID::REDIRECT_DESTINATIONS:
|
||||||
|
send_redirect_destinations_menu(c);
|
||||||
|
break;
|
||||||
|
|
||||||
case MainMenuItemID::DOWNLOAD_QUESTS: {
|
case MainMenuItemID::DOWNLOAD_QUESTS: {
|
||||||
auto s = c->require_server_state();
|
auto s = c->require_server_state();
|
||||||
if (c->flags & Client::Flag::IS_EPISODE_3) {
|
if (c->flags & Client::Flag::IS_EPISODE_3) {
|
||||||
@@ -1907,6 +1934,36 @@ static void on_10(shared_ptr<Client> c, uint16_t, uint32_t, const string& data)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case MenuID::REDIRECT_DESTINATIONS: {
|
||||||
|
if (item_id == RedirectDestinationsMenuItemID::GO_BACK) {
|
||||||
|
send_main_menu(c);
|
||||||
|
|
||||||
|
} else if (item_id == RedirectDestinationsMenuItemID::OPTIONS) {
|
||||||
|
send_menu(c, proxy_options_menu_for_client(c));
|
||||||
|
|
||||||
|
} else {
|
||||||
|
auto s = c->require_server_state();
|
||||||
|
const pair<string, uint16_t>* dest = nullptr;
|
||||||
|
try {
|
||||||
|
dest = &s->redirect_destinations_for_version(c->version()).at(item_id);
|
||||||
|
} catch (const out_of_range&) {
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!dest) {
|
||||||
|
send_message_box(c, u"$C6No such destination exists.");
|
||||||
|
c->should_disconnect = true;
|
||||||
|
} else {
|
||||||
|
// Clear Check Tactics menu so client won't see newserv tournament
|
||||||
|
// state while logically on another server
|
||||||
|
if ((c->flags & Client::Flag::IS_EPISODE_3) && !(c->flags & Client::Flag::IS_EP3_TRIAL_EDITION)) {
|
||||||
|
send_ep3_confirm_tournament_entry(c, nullptr);
|
||||||
|
}
|
||||||
|
send_reconnect(c, resolve_ipv4(dest->first), dest->second);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case MenuID::GAME: {
|
case MenuID::GAME: {
|
||||||
auto s = c->require_server_state();
|
auto s = c->require_server_state();
|
||||||
auto game = s->find_lobby(item_id);
|
auto game = s->find_lobby(item_id);
|
||||||
|
|||||||
+64
-8
@@ -353,6 +353,21 @@ shared_ptr<const Menu> ServerState::proxy_destinations_menu_for_version(GameVers
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
shared_ptr<const Menu> ServerState::redirect_destinations_menu_for_version(GameVersion version) const {
|
||||||
|
switch (version) {
|
||||||
|
case GameVersion::DC:
|
||||||
|
return this->redirect_destinations_menu_dc;
|
||||||
|
case GameVersion::PC:
|
||||||
|
return this->redirect_destinations_menu_pc;
|
||||||
|
case GameVersion::GC:
|
||||||
|
return this->redirect_destinations_menu_gc;
|
||||||
|
case GameVersion::XB:
|
||||||
|
return this->redirect_destinations_menu_xb;
|
||||||
|
default:
|
||||||
|
throw out_of_range("no redirect destinations menu exists for this version");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const vector<pair<string, uint16_t>>& ServerState::proxy_destinations_for_version(GameVersion version) const {
|
const vector<pair<string, uint16_t>>& ServerState::proxy_destinations_for_version(GameVersion version) const {
|
||||||
switch (version) {
|
switch (version) {
|
||||||
case GameVersion::DC:
|
case GameVersion::DC:
|
||||||
@@ -368,6 +383,21 @@ const vector<pair<string, uint16_t>>& ServerState::proxy_destinations_for_versio
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const vector<pair<string, uint16_t>>& ServerState::redirect_destinations_for_version(GameVersion version) const {
|
||||||
|
switch (version) {
|
||||||
|
case GameVersion::DC:
|
||||||
|
return this->redirect_destinations_dc;
|
||||||
|
case GameVersion::PC:
|
||||||
|
return this->redirect_destinations_pc;
|
||||||
|
case GameVersion::GC:
|
||||||
|
return this->redirect_destinations_gc;
|
||||||
|
case GameVersion::XB:
|
||||||
|
return this->redirect_destinations_xb;
|
||||||
|
default:
|
||||||
|
throw out_of_range("no redirect destinations menu exists for this version");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ServerState::set_port_configuration(
|
void ServerState::set_port_configuration(
|
||||||
const vector<PortConfiguration>& port_configs) {
|
const vector<PortConfiguration>& port_configs) {
|
||||||
this->name_to_port_config.clear();
|
this->name_to_port_config.clear();
|
||||||
@@ -735,6 +765,36 @@ void ServerState::parse_config(const JSON& json, bool is_reload) {
|
|||||||
this->information_menu_v3 = information_menu_v3;
|
this->information_menu_v3 = information_menu_v3;
|
||||||
this->information_contents = information_contents;
|
this->information_contents = information_contents;
|
||||||
|
|
||||||
|
auto generate_redirect_destinations_menu = [&](vector<pair<string, uint16_t>>& ret_pds, const char* key) -> shared_ptr<const Menu> {
|
||||||
|
shared_ptr<Menu> ret(new Menu(MenuID::REDIRECT_DESTINATIONS, u"Other servers"));
|
||||||
|
ret_pds.clear();
|
||||||
|
|
||||||
|
try {
|
||||||
|
map<string, const JSON&> sorted_jsons;
|
||||||
|
for (const auto& it : json.at(key).as_dict()) {
|
||||||
|
sorted_jsons.emplace(it.first, *it.second);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret->items.emplace_back(RedirectDestinationsMenuItemID::GO_BACK, u"Go back", u"Return to the\nmain menu", 0);
|
||||||
|
|
||||||
|
uint32_t item_id = 0;
|
||||||
|
for (const auto& item : sorted_jsons) {
|
||||||
|
const string& netloc_str = item.second.as_string();
|
||||||
|
const string& description = "$C7Remote server:\n$C6" + netloc_str;
|
||||||
|
ret->items.emplace_back(item_id, decode_sjis(item.first), decode_sjis(description), 0);
|
||||||
|
ret_pds.emplace_back(parse_netloc(netloc_str));
|
||||||
|
item_id++;
|
||||||
|
}
|
||||||
|
} catch (const out_of_range&) {
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
};
|
||||||
|
|
||||||
|
this->redirect_destinations_menu_dc = generate_redirect_destinations_menu(this->redirect_destinations_dc, "RedirectDestinations-DC");
|
||||||
|
this->redirect_destinations_menu_pc = generate_redirect_destinations_menu(this->redirect_destinations_pc, "RedirectDestinations-PC");
|
||||||
|
this->redirect_destinations_menu_gc = generate_redirect_destinations_menu(this->redirect_destinations_gc, "RedirectDestinations-GC");
|
||||||
|
this->redirect_destinations_menu_xb = generate_redirect_destinations_menu(this->redirect_destinations_xb, "RedirectDestinations-XB");
|
||||||
|
|
||||||
auto generate_proxy_destinations_menu = [&](vector<pair<string, uint16_t>>& ret_pds, const char* key) -> shared_ptr<const Menu> {
|
auto generate_proxy_destinations_menu = [&](vector<pair<string, uint16_t>>& ret_pds, const char* key) -> shared_ptr<const Menu> {
|
||||||
shared_ptr<Menu> ret(new Menu(MenuID::PROXY_DESTINATIONS, u"Proxy server"));
|
shared_ptr<Menu> ret(new Menu(MenuID::PROXY_DESTINATIONS, u"Proxy server"));
|
||||||
ret_pds.clear();
|
ret_pds.clear();
|
||||||
@@ -763,14 +823,10 @@ void ServerState::parse_config(const JSON& json, bool is_reload) {
|
|||||||
return ret;
|
return ret;
|
||||||
};
|
};
|
||||||
|
|
||||||
this->proxy_destinations_menu_dc = generate_proxy_destinations_menu(
|
this->proxy_destinations_menu_dc = generate_proxy_destinations_menu(this->proxy_destinations_dc, "ProxyDestinations-DC");
|
||||||
this->proxy_destinations_dc, "ProxyDestinations-DC");
|
this->proxy_destinations_menu_pc = generate_proxy_destinations_menu(this->proxy_destinations_pc, "ProxyDestinations-PC");
|
||||||
this->proxy_destinations_menu_pc = generate_proxy_destinations_menu(
|
this->proxy_destinations_menu_gc = generate_proxy_destinations_menu(this->proxy_destinations_gc, "ProxyDestinations-GC");
|
||||||
this->proxy_destinations_pc, "ProxyDestinations-PC");
|
this->proxy_destinations_menu_xb = generate_proxy_destinations_menu(this->proxy_destinations_xb, "ProxyDestinations-XB");
|
||||||
this->proxy_destinations_menu_gc = generate_proxy_destinations_menu(
|
|
||||||
this->proxy_destinations_gc, "ProxyDestinations-GC");
|
|
||||||
this->proxy_destinations_menu_xb = generate_proxy_destinations_menu(
|
|
||||||
this->proxy_destinations_xb, "ProxyDestinations-XB");
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const string& netloc_str = json.get_string("ProxyDestination-Patch");
|
const string& netloc_str = json.get_string("ProxyDestination-Patch");
|
||||||
|
|||||||
@@ -124,6 +124,14 @@ struct ServerState : public std::enable_shared_from_this<ServerState> {
|
|||||||
std::shared_ptr<const Menu> information_menu_v2;
|
std::shared_ptr<const Menu> information_menu_v2;
|
||||||
std::shared_ptr<const Menu> information_menu_v3;
|
std::shared_ptr<const Menu> information_menu_v3;
|
||||||
std::shared_ptr<std::vector<std::u16string>> information_contents;
|
std::shared_ptr<std::vector<std::u16string>> information_contents;
|
||||||
|
std::shared_ptr<const Menu> redirect_destinations_menu_dc;
|
||||||
|
std::shared_ptr<const Menu> redirect_destinations_menu_pc;
|
||||||
|
std::shared_ptr<const Menu> redirect_destinations_menu_gc;
|
||||||
|
std::shared_ptr<const Menu> redirect_destinations_menu_xb;
|
||||||
|
std::vector<std::pair<std::string, uint16_t>> redirect_destinations_dc;
|
||||||
|
std::vector<std::pair<std::string, uint16_t>> redirect_destinations_pc;
|
||||||
|
std::vector<std::pair<std::string, uint16_t>> redirect_destinations_gc;
|
||||||
|
std::vector<std::pair<std::string, uint16_t>> redirect_destinations_xb;
|
||||||
std::shared_ptr<const Menu> proxy_destinations_menu_dc;
|
std::shared_ptr<const Menu> proxy_destinations_menu_dc;
|
||||||
std::shared_ptr<const Menu> proxy_destinations_menu_pc;
|
std::shared_ptr<const Menu> proxy_destinations_menu_pc;
|
||||||
std::shared_ptr<const Menu> proxy_destinations_menu_gc;
|
std::shared_ptr<const Menu> proxy_destinations_menu_gc;
|
||||||
@@ -189,6 +197,8 @@ struct ServerState : public std::enable_shared_from_this<ServerState> {
|
|||||||
uint32_t connect_address_for_client(std::shared_ptr<Client> c) const;
|
uint32_t connect_address_for_client(std::shared_ptr<Client> c) const;
|
||||||
|
|
||||||
std::shared_ptr<const Menu> information_menu_for_version(GameVersion version) const;
|
std::shared_ptr<const Menu> information_menu_for_version(GameVersion version) const;
|
||||||
|
std::shared_ptr<const Menu> redirect_destinations_menu_for_version(GameVersion version) const;
|
||||||
|
const std::vector<std::pair<std::string, uint16_t>>& redirect_destinations_for_version(GameVersion version) const;
|
||||||
std::shared_ptr<const Menu> proxy_destinations_menu_for_version(GameVersion version) const;
|
std::shared_ptr<const Menu> proxy_destinations_menu_for_version(GameVersion version) const;
|
||||||
const std::vector<std::pair<std::string, uint16_t>>& proxy_destinations_for_version(GameVersion version) const;
|
const std::vector<std::pair<std::string, uint16_t>>& proxy_destinations_for_version(GameVersion version) const;
|
||||||
|
|
||||||
|
|||||||
@@ -136,6 +136,21 @@
|
|||||||
// connect to 127.0.0.1:5059.
|
// connect to 127.0.0.1:5059.
|
||||||
"IPStackListen": [],
|
"IPStackListen": [],
|
||||||
|
|
||||||
|
// Other servers to support redirecting to. If this is empty for any game
|
||||||
|
// version, the "Other servers" menu does not appear for that version. Entries
|
||||||
|
// in these dictionaries should be of the form "name": "address:port"; the
|
||||||
|
// names are used in the "Other servers" menu. Note that if you connect via
|
||||||
|
// the IP stack simulator on Dolphin, you cannot redirect your connection to
|
||||||
|
// another server and the "Other servers" menu will not appear for you (but
|
||||||
|
// you can still use the proxy server).
|
||||||
|
// Unlike ProxyDestinations (below), when a client chooses an item from the
|
||||||
|
// "Other servers" menu, they are redirected to connect directly to that
|
||||||
|
// server, and their connection no longer goes through newserv.
|
||||||
|
"RedirectDestinations-DC": {},
|
||||||
|
"RedirectDestinations-PC": {},
|
||||||
|
"RedirectDestinations-GC": {},
|
||||||
|
"RedirectDestinations-XB": {},
|
||||||
|
|
||||||
// Other servers to support proxying to. If this is empty for any game
|
// Other servers to support proxying to. If this is empty for any game
|
||||||
// version, the proxy server is disabled for that version. Entries in these
|
// version, the proxy server is disabled for that version. Entries in these
|
||||||
// dictionaries should be of the form "name": "address:port"; the names are
|
// dictionaries should be of the form "name": "address:port"; the names are
|
||||||
|
|||||||
+2
-2
@@ -55,11 +55,11 @@
|
|||||||
},
|
},
|
||||||
|
|
||||||
"ProxyDestinations-GC": {
|
"ProxyDestinations-GC": {
|
||||||
"Schtserv": "149.56.167.128:9103",
|
"Schtserv": "psobb.dyndns.org:9103",
|
||||||
"Sylverant": "sylverant.net:9103",
|
"Sylverant": "sylverant.net:9103",
|
||||||
},
|
},
|
||||||
"ProxyDestinations-PC": {
|
"ProxyDestinations-PC": {
|
||||||
"Schtserv": "149.56.167.128:9100",
|
"Schtserv": "psobb.dyndns.org:9100",
|
||||||
"Sylverant": "sylverant.net:9100",
|
"Sylverant": "sylverant.net:9100",
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user