diff --git a/src/Client.cc b/src/Client.cc index 94708227..abba4c07 100644 --- a/src/Client.cc +++ b/src/Client.cc @@ -63,6 +63,7 @@ Client::Client( switch_assist(false), can_chat(true), pending_bb_save_player_index(0), + proxy_block_events(false), proxy_save_files(false), proxy_suppress_remote_login(false), proxy_zero_remote_guild_card(false), diff --git a/src/Client.hh b/src/Client.hh index f9f8a5e8..5bf680c9 100644 --- a/src/Client.hh +++ b/src/Client.hh @@ -120,6 +120,7 @@ struct Client { std::string pending_bb_save_username; uint8_t pending_bb_save_player_index; + bool proxy_block_events; bool proxy_save_files; bool proxy_suppress_remote_login; bool proxy_zero_remote_guild_card; diff --git a/src/Menu.hh b/src/Menu.hh index 2c68aad3..607370e5 100644 --- a/src/Menu.hh +++ b/src/Menu.hh @@ -58,9 +58,10 @@ namespace ProxyOptionsMenuItemID { constexpr uint32_t INFINITE_HP = 0xAA1111AA; constexpr uint32_t INFINITE_TP = 0xAA2222AA; constexpr uint32_t SWITCH_ASSIST = 0xAA3333AA; - constexpr uint32_t SAVE_FILES = 0xAA4444AA; - constexpr uint32_t SUPPRESS_LOGIN = 0xAA5555AA; - constexpr uint32_t SKIP_CARD = 0xAA6666AA; + constexpr uint32_t BLOCK_EVENTS = 0xAA4444AA; + constexpr uint32_t SAVE_FILES = 0xAA5555AA; + constexpr uint32_t SUPPRESS_LOGIN = 0xAA6666AA; + constexpr uint32_t SKIP_CARD = 0xAA7777AA; } diff --git a/src/ProxyCommands.cc b/src/ProxyCommands.cc index 5f8075ec..4fd21cd0 100644 --- a/src/ProxyCommands.cc +++ b/src/ProxyCommands.cc @@ -830,6 +830,18 @@ static HandlerResult S_V3_1A_D5(shared_ptr, return HandlerResult::Type::FORWARD; } +static HandlerResult S_V3_BB_DA(shared_ptr, + ProxyServer::LinkedSession& session, uint16_t, uint32_t flag, string&) { + if ((session.version == GameVersion::GC) && + (session.newserv_client_config.cfg.flags & Client::Flag::IS_TRIAL_EDITION)) { + return HandlerResult::Type::SUPPRESS; + } else if (session.override_lobby_event >= 0 && static_cast(flag) != session.override_lobby_event) { + return HandlerResult(HandlerResult::Type::MODIFIED, 0xDA, session.override_lobby_event); + } else { + return HandlerResult::Type::FORWARD; + } +} + static HandlerResult S_6x(shared_ptr, ProxyServer::LinkedSession& session, uint16_t, uint32_t, string& data) { check_implemented_subcommand(session, data); @@ -1572,7 +1584,7 @@ static on_command_t handlers[0x100][6][2] = { /* D7 */ {{S_invalid, nullptr}, {S_invalid, nullptr}, {S_invalid, nullptr}, {nullptr, nullptr}, {nullptr, nullptr}, {nullptr, nullptr}}, /* D8 */ {{S_invalid, nullptr}, {S_invalid, nullptr}, {S_invalid, nullptr}, {nullptr, nullptr}, {nullptr, nullptr}, {nullptr, nullptr}}, /* D9 */ {{S_invalid, nullptr}, {S_invalid, nullptr}, {S_invalid, nullptr}, {S_invalid, nullptr}, {S_invalid, nullptr}, {S_invalid, nullptr}}, -/* DA */ {{S_invalid, nullptr}, {S_invalid, nullptr}, {S_invalid, nullptr}, {nullptr, nullptr}, {nullptr, nullptr}, {nullptr, nullptr}}, +/* DA */ {{S_invalid, nullptr}, {S_invalid, nullptr}, {S_invalid, nullptr}, {S_V3_BB_DA, nullptr}, {S_V3_BB_DA, nullptr}, {S_V3_BB_DA, nullptr}}, /* DB */ {{S_invalid, nullptr}, {S_invalid, nullptr}, {S_invalid, nullptr}, {S_invalid, nullptr}, {S_invalid, nullptr}, {S_invalid, nullptr}}, /* DC */ {{S_invalid, nullptr}, {S_invalid, nullptr}, {S_invalid, nullptr}, {nullptr, nullptr}, {S_invalid, nullptr}, {nullptr, nullptr}}, /* DD */ {{S_invalid, nullptr}, {S_invalid, nullptr}, {S_invalid, nullptr}, {S_invalid, nullptr}, {S_invalid, nullptr}, {nullptr, nullptr}}, diff --git a/src/ProxyServer.cc b/src/ProxyServer.cc index 43a9886c..ce9883ff 100644 --- a/src/ProxyServer.cc +++ b/src/ProxyServer.cc @@ -651,6 +651,15 @@ void ProxyServer::LinkedSession::on_error(Channel& ch, short events) { if (events & BEV_EVENT_CONNECTED) { session->log.info("%s channel connected", is_server_stream ? "Server" : "Client"); + + if (is_server_stream && (session->override_lobby_event >= 0) && + ( + ((session->version == GameVersion::GC) && !(session->newserv_client_config.cfg.flags & Client::Flag::IS_TRIAL_EDITION)) || + (session->version == GameVersion::XB) || + (session->version == GameVersion::BB) + )) { + session->client_channel.send(0xDA, session->override_lobby_event); + } } if (events & BEV_EVENT_ERROR) { int err = EVUTIL_SOCKET_ERROR(); diff --git a/src/ReceiveCommands.cc b/src/ReceiveCommands.cc index 0f94787e..ddd4318b 100644 --- a/src/ReceiveCommands.cc +++ b/src/ReceiveCommands.cc @@ -62,6 +62,44 @@ vector quest_download_menu({ MenuItem(static_cast(QuestCategory::DOWNLOAD), u"Download", u"$E$C6Quests to download\nto your Memory Card", 0), }); +static const unordered_map proxy_options_menu_descriptions({ + {ProxyOptionsMenuItemID::GO_BACK, u"Return to the\nproxy menu"}, + {ProxyOptionsMenuItemID::INFINITE_HP, u"If enabled, the proxy\nwill restore your HP\nwhen you are hit by\nan enemy or trap,\nbut cannot revive\nyou from one-hit\nkills"}, + {ProxyOptionsMenuItemID::INFINITE_TP, u"If enabled, the proxy\nwill restore your TP\nwhen you cast any\ntechnique"}, + {ProxyOptionsMenuItemID::SWITCH_ASSIST, u"If enabled, the proxy\nwill attempt to\nunlock 2-player\ndoors when you step\non both switches\nsequentially"}, + {ProxyOptionsMenuItemID::BLOCK_EVENTS, u"If enabled, season\nevents in the lobby\nand in games are\ndisabled."}, + {ProxyOptionsMenuItemID::SAVE_FILES, u"If enabled, the proxy\nwill save local\ncopies of files from\nthe remote server\n(quests, etc.)"}, + {ProxyOptionsMenuItemID::SUPPRESS_LOGIN, u"If enabled, the proxy\nwill use an alternate\nlogin sequence"}, + {ProxyOptionsMenuItemID::SKIP_CARD, u"If enabled, the proxy\nwill use an alternate\nvalue for your initial\nGuild Card"}, +}); + +static vector proxy_options_menu_for_client( + shared_ptr c) { + vector ret; + // Note: The descriptions are instead in the map above, because this menu is + // dynamically created every time it's sent to the client. This is just one + // way in which the menu abstraction is currently insufficient (there is a + // TODO about this in README.md). + ret.emplace_back(ProxyOptionsMenuItemID::GO_BACK, u"Go back", u"", 0); + if (!(c->flags & Client::Flag::IS_EPISODE_3)) { + ret.emplace_back(ProxyOptionsMenuItemID::INFINITE_HP, + c->infinite_hp ? u"Infinite HP ON" : u"Infinite HP OFF", u"", 0); + ret.emplace_back(ProxyOptionsMenuItemID::INFINITE_TP, + c->infinite_tp ? u"Infinite TP ON" : u"Infinite TP OFF", u"", 0); + ret.emplace_back(ProxyOptionsMenuItemID::SWITCH_ASSIST, + c->switch_assist ? u"Switch assist ON" : u"Switch assist OFF", u"", 0); + } + ret.emplace_back(ProxyOptionsMenuItemID::BLOCK_EVENTS, + c->proxy_block_events ? u"Block events ON" : u"Block events OFF", u"", 0); + ret.emplace_back(ProxyOptionsMenuItemID::SAVE_FILES, + c->proxy_save_files ? u"Save files ON" : u"Save files OFF", u"", 0); + ret.emplace_back(ProxyOptionsMenuItemID::SUPPRESS_LOGIN, + c->proxy_suppress_remote_login ? u"Skip login ON" : u"Skip login OFF", u"", 0); + ret.emplace_back(ProxyOptionsMenuItemID::SKIP_CARD, + c->proxy_zero_remote_guild_card ? u"Skip card ON" : u"Skip card OFF", u"", 0); + return ret; +} + static void send_client_to_lobby_server(shared_ptr s, shared_ptr c) { @@ -86,6 +124,9 @@ static void send_client_to_proxy_server(shared_ptr s, shared_ptrswitch_assist = c->switch_assist; session->save_files = c->proxy_save_files; session->suppress_remote_login = c->proxy_suppress_remote_login; + if (c->proxy_block_events) { + session->override_lobby_event = 0; + } if (c->proxy_zero_remote_guild_card) { session->remote_guild_card_number = 0; } else { @@ -981,28 +1022,11 @@ static void on_menu_item_info_request(shared_ptr s, shared_ptr s, shared_ptr proxy_options_menu_for_client( - shared_ptr c) { - vector ret; - ret.emplace_back(ProxyOptionsMenuItemID::GO_BACK, u"Go back", - u"Return to the\nproxy menu", 0); - ret.emplace_back(ProxyOptionsMenuItemID::INFINITE_HP, - c->infinite_hp ? u"Infinite HP ON" : u"Infinite HP OFF", - u"Enable or disable\ninfinite HP", 0); - ret.emplace_back(ProxyOptionsMenuItemID::INFINITE_TP, - c->infinite_tp ? u"Infinite TP ON" : u"Infinite TP OFF", - u"Enable or disable\ninfinite TP", 0); - ret.emplace_back(ProxyOptionsMenuItemID::SWITCH_ASSIST, - c->switch_assist ? u"Switch assist ON" : u"Switch assist OFF", - u"Enable or disable\nswitch assist", 0); - ret.emplace_back(ProxyOptionsMenuItemID::SAVE_FILES, - c->proxy_save_files ? u"Save files ON" : u"Save files OFF", - u"Enable or disable\nsaving of files from\nthe remote server\n(quests, etc.)", 0); - ret.emplace_back(ProxyOptionsMenuItemID::SUPPRESS_LOGIN, - c->proxy_suppress_remote_login ? u"Skip login ON" : u"Skip login OFF", - u"Enable or disable\nalternate login\nsequence", 0); - ret.emplace_back(ProxyOptionsMenuItemID::SKIP_CARD, - c->proxy_zero_remote_guild_card ? u"Skip card ON" : u"Skip card OFF", - u"Enable or disable\nGuild Card reset", 0); - return ret; -} - static void on_menu_selection(shared_ptr s, shared_ptr c, uint16_t, uint32_t, const string& data) { // 10 bool uses_unicode = ((c->version() == GameVersion::PC) || (c->version() == GameVersion::BB)); @@ -1281,6 +1279,9 @@ static void on_menu_selection(shared_ptr s, shared_ptr c, case ProxyOptionsMenuItemID::SWITCH_ASSIST: c->switch_assist = !c->switch_assist; goto resend_proxy_options_menu; + case ProxyOptionsMenuItemID::BLOCK_EVENTS: + c->proxy_block_events = !c->proxy_block_events; + goto resend_proxy_options_menu; case ProxyOptionsMenuItemID::SAVE_FILES: c->proxy_save_files = !c->proxy_save_files; goto resend_proxy_options_menu;