From d1ce010d06ec47f1f4f709eebb18389a9977ce61 Mon Sep 17 00:00:00 2001 From: Martin Michelsen Date: Wed, 29 Nov 2023 17:19:37 -0800 Subject: [PATCH] make user flag that allows cheating even if cheats are disabled --- src/ChatCommands.cc | 48 +++++++++++++++++++-------------------- src/License.hh | 3 ++- src/ReceiveCommands.cc | 2 +- src/ReceiveSubcommands.cc | 9 +++++--- 4 files changed, 33 insertions(+), 29 deletions(-) diff --git a/src/ChatCommands.cc b/src/ChatCommands.cc index 3812910e..0f7cebe1 100644 --- a/src/ChatCommands.cc +++ b/src/ChatCommands.cc @@ -70,20 +70,20 @@ static void check_is_ep3(shared_ptr c, bool is_ep3) { } } -static void check_cheats_enabled(shared_ptr l) { - if (!l->check_flag(Lobby::Flag::CHEATS_ENABLED)) { +static void check_cheats_enabled(shared_ptr l, shared_ptr c) { + if (!l->check_flag(Lobby::Flag::CHEATS_ENABLED) && !(c->license->flags & License::Flag::CHEAT_ANYWHERE)) { throw precondition_failed("$C6This command can\nonly be used in\ncheat mode."); } } -static void check_cheats_allowed(shared_ptr s) { - if (s->cheat_mode_behavior == ServerState::BehaviorSwitch::OFF) { +static void check_cheats_allowed(shared_ptr s, shared_ptr c) { + if ((s->cheat_mode_behavior == ServerState::BehaviorSwitch::OFF) && !(c->license->flags & License::Flag::CHEAT_ANYWHERE)) { throw precondition_failed("$C6Cheats are disabled\non this server."); } } -static void check_proxy_cheats_allowed(shared_ptr s) { - if (s->cheat_mode_behavior == ServerState::BehaviorSwitch::OFF) { +static void check_cheats_allowed(shared_ptr s, shared_ptr ses) { + if ((s->cheat_mode_behavior == ServerState::BehaviorSwitch::OFF) && (!ses->license || !(ses->license->flags & License::Flag::CHEAT_ANYWHERE))) { throw precondition_failed("$C6Cheats are disabled\non this proxy."); } } @@ -740,7 +740,7 @@ static void server_command_meseta(shared_ptr c, const std::string& args) static void server_command_secid(shared_ptr c, const std::string& args) { auto l = c->require_lobby(); check_is_game(l, false); - check_cheats_allowed(c->require_server_state()); + check_cheats_allowed(c->require_server_state(), c); if (!args[0]) { c->config.override_section_id = 0xFF; @@ -757,7 +757,7 @@ static void server_command_secid(shared_ptr c, const std::string& args) } static void proxy_command_secid(shared_ptr ses, const std::string& args) { - check_cheats_allowed(ses->require_server_state()); + check_cheats_allowed(ses->require_server_state(), ses); if (!args[0]) { ses->config.override_section_id = 0xFF; send_text_message(ses->client_channel, "$C6Override section ID\nremoved"); @@ -776,7 +776,7 @@ static void server_command_rand(shared_ptr c, const std::string& args) { auto s = c->require_server_state(); auto l = c->require_lobby(); check_is_game(l, false); - check_cheats_allowed(s); + check_cheats_allowed(s, c); if (!args[0]) { c->config.clear_flag(Client::Flag::USE_OVERRIDE_RANDOM_SEED); @@ -790,7 +790,7 @@ static void server_command_rand(shared_ptr c, const std::string& args) { } static void proxy_command_rand(shared_ptr ses, const std::string& args) { - check_proxy_cheats_allowed(ses->require_server_state()); + check_cheats_allowed(ses->require_server_state(), ses); if (!args[0]) { ses->config.clear_flag(Client::Flag::USE_OVERRIDE_RANDOM_SEED); ses->config.override_random_seed = 0; @@ -885,7 +885,7 @@ static void server_command_edit(shared_ptr c, const std::string& args) { check_is_game(l, false); check_version(c, Version::BB_V4); - if (s->cheat_mode_behavior == ServerState::BehaviorSwitch::OFF) { + if ((s->cheat_mode_behavior == ServerState::BehaviorSwitch::OFF) && !(c->license->flags & License::Flag::CHEAT_ANYWHERE)) { send_text_message(l, "$C6Cheats are disabled\non this server"); return; } @@ -1164,7 +1164,7 @@ static void server_command_warp(shared_ptr c, const std::string& args, b auto s = c->require_server_state(); auto l = c->require_lobby(); check_is_game(l, true); - check_cheats_enabled(l); + check_cheats_enabled(l, c); uint32_t floor = stoul(args, nullptr, 0); if (c->floor == floor) { @@ -1196,7 +1196,7 @@ static void server_command_warpall(shared_ptr c, const std::string& args static void proxy_command_warp(shared_ptr ses, const std::string& args, bool is_warpall) { auto s = ses->require_server_state(); - check_proxy_cheats_allowed(s); + check_cheats_allowed(s, ses); if (!ses->is_in_game) { send_text_message(ses->client_channel, "$C6You must be in a\ngame to use this\ncommand"); return; @@ -1221,7 +1221,7 @@ static void server_command_next(shared_ptr c, const std::string&) { auto s = c->require_server_state(); auto l = c->require_lobby(); check_is_game(l, true); - check_cheats_enabled(l); + check_cheats_enabled(l, c); size_t limit = floor_limit_for_episode(l->episode); if (limit == 0) { @@ -1232,7 +1232,7 @@ static void server_command_next(shared_ptr c, const std::string&) { static void proxy_command_next(shared_ptr ses, const std::string&) { auto s = ses->require_server_state(); - check_proxy_cheats_allowed(s); + check_cheats_allowed(s, ses); if (!ses->is_in_game) { send_text_message(ses->client_channel, "$C6You must be in a\ngame to use this\ncommand"); return; @@ -1298,7 +1298,7 @@ static void server_command_infinite_hp(shared_ptr c, const std::string&) auto s = c->require_server_state(); auto l = c->require_lobby(); check_is_game(l, true); - check_cheats_enabled(l); + check_cheats_enabled(l, c); c->config.toggle_flag(Client::Flag::INFINITE_HP_ENABLED); send_text_message_printf(c, "$C6Infinite HP %s", c->config.check_flag(Client::Flag::INFINITE_HP_ENABLED) ? "enabled" : "disabled"); @@ -1306,7 +1306,7 @@ static void server_command_infinite_hp(shared_ptr c, const std::string&) static void proxy_command_infinite_hp(shared_ptr ses, const std::string&) { auto s = ses->require_server_state(); - check_proxy_cheats_allowed(s); + check_cheats_allowed(s, ses); ses->config.toggle_flag(Client::Flag::INFINITE_HP_ENABLED); send_text_message_printf(ses->client_channel, "$C6Infinite HP %s", ses->config.check_flag(Client::Flag::INFINITE_HP_ENABLED) ? "enabled" : "disabled"); @@ -1316,7 +1316,7 @@ static void server_command_infinite_tp(shared_ptr c, const std::string&) auto s = c->require_server_state(); auto l = c->require_lobby(); check_is_game(l, true); - check_cheats_enabled(l); + check_cheats_enabled(l, c); c->config.toggle_flag(Client::Flag::INFINITE_TP_ENABLED); send_text_message_printf(c, "$C6Infinite TP %s", c->config.check_flag(Client::Flag::INFINITE_TP_ENABLED) ? "enabled" : "disabled"); @@ -1324,7 +1324,7 @@ static void server_command_infinite_tp(shared_ptr c, const std::string&) static void proxy_command_infinite_tp(shared_ptr ses, const std::string&) { auto s = ses->require_server_state(); - check_proxy_cheats_allowed(s); + check_cheats_allowed(s, ses); ses->config.toggle_flag(Client::Flag::INFINITE_TP_ENABLED); send_text_message_printf(ses->client_channel, "$C6Infinite TP %s", ses->config.check_flag(Client::Flag::INFINITE_TP_ENABLED) ? "enabled" : "disabled"); @@ -1334,7 +1334,7 @@ static void server_command_switch_assist(shared_ptr c, const std::string auto s = c->require_server_state(); auto l = c->require_lobby(); check_is_game(l, true); - check_cheats_enabled(l); + check_cheats_enabled(l, c); c->config.toggle_flag(Client::Flag::SWITCH_ASSIST_ENABLED); send_text_message_printf(c, "$C6Switch assist %s", @@ -1343,7 +1343,7 @@ static void server_command_switch_assist(shared_ptr c, const std::string static void proxy_command_switch_assist(shared_ptr ses, const std::string&) { auto s = ses->require_server_state(); - check_proxy_cheats_allowed(s); + check_cheats_allowed(s, ses); ses->config.toggle_flag(Client::Flag::SWITCH_ASSIST_ENABLED); send_text_message_printf(ses->client_channel, "$C6Switch assist %s", ses->config.check_flag(Client::Flag::SWITCH_ASSIST_ENABLED) ? "enabled" : "disabled"); @@ -1385,7 +1385,7 @@ static void server_command_item(shared_ptr c, const std::string& args) { auto s = c->require_server_state(); auto l = c->require_lobby(); check_is_game(l, true); - check_cheats_enabled(l); + check_cheats_enabled(l, c); ItemData item = s->item_name_index->parse_item_description(c->version(), args); item.id = l->generate_item_id(c->lobby_client_id); @@ -1399,7 +1399,7 @@ static void server_command_item(shared_ptr c, const std::string& args) { static void proxy_command_item(shared_ptr ses, const std::string& args) { auto s = ses->require_server_state(); - check_proxy_cheats_allowed(s); + check_cheats_allowed(s, ses); if (ses->version() == Version::BB_V4) { send_text_message(ses->client_channel, "$C6This command cannot\nbe used on the proxy\nserver in BB games"); return; @@ -1538,7 +1538,7 @@ static void server_command_ep3_unset_field_character(shared_ptr c, const auto l = c->require_lobby(); check_is_game(l, true); check_is_ep3(c, true); - check_cheats_enabled(l); + check_cheats_enabled(l, c); if (l->episode != Episode::EP3) { throw logic_error("non-Ep3 client in Ep3 game"); diff --git a/src/License.hh b/src/License.hh index f1207550..d89735eb 100644 --- a/src/License.hh +++ b/src/License.hh @@ -22,11 +22,12 @@ struct License { FREE_JOIN_GAMES = 0x00000040, UNLOCK_GAMES = 0x00000080, DEBUG = 0x01000000, + CHEAT_ANYWHERE = 0x02000000, MODERATOR = 0x00000007, ADMINISTRATOR = 0x000000FF, ROOT = 0x7FFFFFFF, - UNUSED_BITS = 0x7EFFFF00, + UNUSED_BITS = 0x7CFFFF00, // clang-format on }; diff --git a/src/ReceiveCommands.cc b/src/ReceiveCommands.cc index b1941bbc..cdcaeb70 100644 --- a/src/ReceiveCommands.cc +++ b/src/ReceiveCommands.cc @@ -55,7 +55,7 @@ static shared_ptr proxy_options_menu_for_client(shared_ptrcheat_mode_behavior != ServerState::BehaviorSwitch::OFF) { + if ((s->cheat_mode_behavior != ServerState::BehaviorSwitch::OFF) || (c->license->flags & License::Flag::CHEAT_ANYWHERE)) { if (!is_ep3(c->version())) { add_option(ProxyOptionsMenuItemID::INFINITE_HP, Client::Flag::INFINITE_HP_ENABLED, "Infinite HP", "Enable automatic HP\nrestoration when\nyou are hit by an\nenemy or trap\n\nCannot revive you\nfrom one-hit kills"); diff --git a/src/ReceiveSubcommands.cc b/src/ReceiveSubcommands.cc index dfe4630e..7cef4498 100644 --- a/src/ReceiveSubcommands.cc +++ b/src/ReceiveSubcommands.cc @@ -738,7 +738,8 @@ static void on_hit_by_enemy(shared_ptr c, uint8_t command, uint8_t flag, auto l = c->require_lobby(); if (l->is_game() && (cmd.client_id == c->lobby_client_id)) { forward_subcommand(c, command, flag, data, size); - if (l->check_flag(Lobby::Flag::CHEATS_ENABLED) && c->config.check_flag(Client::Flag::INFINITE_HP_ENABLED)) { + bool player_cheats_enabled = l->check_flag(Lobby::Flag::CHEATS_ENABLED) || (c->license->flags & License::Flag::CHEAT_ANYWHERE); + if (player_cheats_enabled && c->config.check_flag(Client::Flag::INFINITE_HP_ENABLED)) { send_player_stats_change(c, PlayerStatsChange::ADD_HP, 2550); } } @@ -751,7 +752,8 @@ static void on_cast_technique_finished(shared_ptr c, uint8_t command, ui auto l = c->require_lobby(); if (l->is_game() && (cmd.header.client_id == c->lobby_client_id)) { forward_subcommand(c, command, flag, data, size); - if (l->check_flag(Lobby::Flag::CHEATS_ENABLED) && c->config.check_flag(Client::Flag::INFINITE_TP_ENABLED)) { + bool player_cheats_enabled = l->check_flag(Lobby::Flag::CHEATS_ENABLED) || (c->license->flags & License::Flag::CHEAT_ANYWHERE); + if (player_cheats_enabled && c->config.check_flag(Client::Flag::INFINITE_TP_ENABLED)) { send_player_stats_change(c, PlayerStatsChange::ADD_TP, 255); } } @@ -798,7 +800,8 @@ static void on_switch_state_changed(shared_ptr c, uint8_t command, uint8 forward_subcommand(c, command, flag, data, size); if (cmd.flags && cmd.header.object_id != 0xFFFF) { - if (l->check_flag(Lobby::Flag::CHEATS_ENABLED) && + bool player_cheats_enabled = l->check_flag(Lobby::Flag::CHEATS_ENABLED) || (c->license->flags & License::Flag::CHEAT_ANYWHERE); + if (player_cheats_enabled && c->config.check_flag(Client::Flag::SWITCH_ASSIST_ENABLED) && (c->last_switch_enabled_command.header.subcommand == 0x05)) { c->log.info("[Switch assist] Replaying previous enable command");