From a39881fa89e1c829b42f92faddccfb5da6e5f7f6 Mon Sep 17 00:00:00 2001 From: Martin Michelsen Date: Fri, 8 Mar 2024 21:19:56 -0800 Subject: [PATCH] change game section ID on leader change --- src/ChatCommands.cc | 21 ++++++++----- src/HTTPServer.cc | 4 +-- src/ItemCreator.cc | 12 ++++++++ src/ItemCreator.hh | 2 ++ src/Lobby.cc | 31 ++++++++++++++++++-- src/Lobby.hh | 4 ++- src/ReceiveCommands.cc | 6 ++-- src/SendCommands.cc | 4 +-- tests/GC-HeartSymbol.test.txt | 2 +- tests/PC-DCv1-CrossplayPrivateDrops.test.txt | 2 +- 10 files changed, 67 insertions(+), 21 deletions(-) diff --git a/src/ChatCommands.cc b/src/ChatCommands.cc index e6ae370a..1e5a76d9 100644 --- a/src/ChatCommands.cc +++ b/src/ChatCommands.cc @@ -119,7 +119,7 @@ static void server_command_lobby_info(shared_ptr c, const std::string&) } else { lines.emplace_back(string_printf("$C6%08X$C7 L$C6%d-%d$C7", l->lobby_id, l->min_level + 1, l->max_level + 1)); } - lines.emplace_back(string_printf("$C7Section ID: $C6%s$C7", name_for_section_id(l->section_id))); + lines.emplace_back(string_printf("$C7Section ID: $C6%s$C7", name_for_section_id(l->effective_section_id()))); switch (l->drop_mode) { case Lobby::DropMode::DISABLED: @@ -927,21 +927,28 @@ 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(), c); + uint8_t new_override_section_id; + if (!args[0]) { - c->config.override_section_id = 0xFF; + new_override_section_id = 0xFF; send_text_message(c, "$C6Override section ID\nremoved"); } else { - uint8_t new_secid = section_id_for_name(args); - if (new_secid == 0xFF) { + new_override_section_id = section_id_for_name(args); + if (new_override_section_id == 0xFF) { send_text_message(c, "$C6Invalid section ID"); + return; } else { - c->config.override_section_id = new_secid; - send_text_message_printf(c, "$C6Override section ID\nset to %s", name_for_section_id(new_secid)); + send_text_message_printf(c, "$C6Override section ID\nset to %s", name_for_section_id(new_override_section_id)); } } + + c->config.override_section_id = new_override_section_id; + if (l->is_game() && (l->leader_id == c->lobby_client_id)) { + l->override_section_id = new_override_section_id; + l->change_section_id(); + } } static void proxy_command_secid(shared_ptr ses, const std::string& args) { diff --git a/src/HTTPServer.cc b/src/HTTPServer.cc index 43025c4d..caf94e98 100644 --- a/src/HTTPServer.cc +++ b/src/HTTPServer.cc @@ -539,7 +539,7 @@ JSON HTTPServer::generate_lobby_json_st(shared_ptr l, shared_ptrvariations[z].load()); } ret.emplace("Variations", std::move(variations_json)); - ret.emplace("SectionID", name_for_section_id(l->section_id)); + ret.emplace("SectionID", name_for_section_id(l->effective_section_id())); ret.emplace("Mode", name_for_mode(l->mode)); ret.emplace("Difficulty", name_for_difficulty(l->difficulty)); ret.emplace("BaseEXPMultiplier", l->base_exp_multiplier); @@ -809,7 +809,7 @@ JSON HTTPServer::generate_summary_json() const { } else { game_json.emplace("QuestInProgress", l->check_flag(Lobby::Flag::QUEST_IN_PROGRESS)); game_json.emplace("JoinableQuestInProgress", l->check_flag(Lobby::Flag::JOINABLE_QUEST_IN_PROGRESS)); - game_json.emplace("SectionID", name_for_section_id(l->section_id)); + game_json.emplace("SectionID", name_for_section_id(l->effective_section_id())); game_json.emplace("Mode", name_for_mode(l->mode)); game_json.emplace("Difficulty", name_for_difficulty(l->difficulty)); game_json.emplace("Quest", this->generate_quest_json_st(l->quest)); diff --git a/src/ItemCreator.cc b/src/ItemCreator.cc index 600d35d7..54fc4f52 100644 --- a/src/ItemCreator.cc +++ b/src/ItemCreator.cc @@ -38,6 +38,7 @@ ItemCreator::ItemCreator( weapon_random_set(weapon_random_set), tekker_adjustment_set(tekker_adjustment_set), item_parameter_table(item_parameter_table), + common_item_set(common_item_set), pt(common_item_set->get_table(this->episode, this->mode, this->difficulty, this->section_id)), restrictions(restrictions), opt_rand_crypt(opt_rand_crypt ? make_shared(opt_rand_crypt->seed()) : nullptr) { @@ -48,6 +49,17 @@ void ItemCreator::set_random_crypt(shared_ptr new_random_crypt this->opt_rand_crypt = new_random_crypt; } +void ItemCreator::set_section_id(uint8_t new_section_id) { + this->section_id = new_section_id; + this->log.prefix = string_printf("[ItemCreator:%s/%s/%s/%c/%hhu] ", + name_for_enum(stack_limits->version), + abbreviation_for_episode(episode), + abbreviation_for_mode(mode), + abbreviation_for_difficulty(difficulty), + this->section_id); + this->pt = common_item_set->get_table(this->episode, this->mode, this->difficulty, this->section_id); +} + bool ItemCreator::are_rare_drops_allowed() const { // Note: The client has an additional check here, which appears to be a subtle // anti-cheating measure. There is a flag on the client, initially zero, which diff --git a/src/ItemCreator.hh b/src/ItemCreator.hh index 24cf5f30..7c6c3533 100644 --- a/src/ItemCreator.hh +++ b/src/ItemCreator.hh @@ -52,6 +52,7 @@ public: inline void set_restrictions(std::shared_ptr restrictions) { this->restrictions = restrictions; } + void set_section_id(uint8_t new_section_id); private: PrefixedLogger log; @@ -67,6 +68,7 @@ private: std::shared_ptr weapon_random_set; std::shared_ptr tekker_adjustment_set; std::shared_ptr item_parameter_table; + std::shared_ptr common_item_set; std::shared_ptr pt; std::shared_ptr restrictions; diff --git a/src/Lobby.cc b/src/Lobby.cc index 519c2794..f1af79b6 100644 --- a/src/Lobby.cc +++ b/src/Lobby.cc @@ -144,7 +144,7 @@ Lobby::Lobby(shared_ptr s, uint32_t id, bool is_game) next_game_item_id(0xCC000000), base_version(Version::GC_V3), allowed_versions(0x0000), - section_id(0), + override_section_id(0xFF), episode(Episode::NONE), mode(GameMode::NORMAL), difficulty(0), @@ -256,11 +256,34 @@ void Lobby::create_item_creator() { this->episode, (this->mode == GameMode::SOLO) ? GameMode::NORMAL : this->mode, this->difficulty, - this->section_id, + this->effective_section_id(), this->opt_rand_crypt, this->quest ? this->quest->battle_rules : nullptr); } +void Lobby::change_section_id() { + if (this->item_creator) { + uint8_t new_section_id = this->effective_section_id(); + this->item_creator->set_section_id(new_section_id); + for (const auto& c : this->clients) { + if (c && c->config.check_flag(Client::Flag::DEBUG_ENABLED)) { + send_text_message_printf(c, "$C5Section ID changed\nto %s (%hhu)", name_for_section_id(new_section_id), new_section_id); + } + } + } +} + +uint8_t Lobby::effective_section_id() const { + if (this->override_section_id != 0xFF) { + return this->override_section_id; + } + auto leader = this->clients.at(this->leader_id); + if (leader) { + return leader->character()->disp.visual.section_id; + } + return 0; +} + shared_ptr Lobby::load_maps( Version version, Episode episode, @@ -470,8 +493,9 @@ void Lobby::reassign_leader_on_client_departure(size_t leaving_client_index) { if (x == leaving_client_index) { continue; } - if (this->clients[x].get()) { + if (this->clients[x]) { this->leader_id = x; + this->change_section_id(); return; } } @@ -558,6 +582,7 @@ void Lobby::add_client(shared_ptr c, ssize_t required_client_id) { } if (leader_index >= this->max_clients) { this->leader_id = c->lobby_client_id; + this->change_section_id(); } // If this is a lobby or no one was here before this, reassign all the floor diff --git a/src/Lobby.hh b/src/Lobby.hh index a3ae20b8..62bc65ee 100644 --- a/src/Lobby.hh +++ b/src/Lobby.hh @@ -107,7 +107,7 @@ struct Lobby : public std::enable_shared_from_this { // bits are indexed as (1 << version), where version is a value from the // Version enum. uint16_t allowed_versions; - uint8_t section_id; + uint8_t override_section_id; Episode episode; GameMode mode; uint8_t difficulty; // 0-3 @@ -195,6 +195,8 @@ struct Lobby : public std::enable_shared_from_this { std::shared_ptr require_challenge_params() const; void set_drop_mode(DropMode new_mode); void create_item_creator(); + void change_section_id(); + uint8_t effective_section_id() const; static std::shared_ptr load_maps( Version version, Episode episode, diff --git a/src/ReceiveCommands.cc b/src/ReceiveCommands.cc index 30ced422..77634745 100644 --- a/src/ReceiveCommands.cc +++ b/src/ReceiveCommands.cc @@ -1901,7 +1901,7 @@ static void on_09(shared_ptr c, uint16_t, uint32_t, string& data) { abbreviation_for_episode(game->episode), abbreviation_for_difficulty(game->difficulty), abbreviation_for_mode(game->mode), - abbreviation_for_section_id(game->section_id)); + abbreviation_for_section_id(game->effective_section_id())); if (c->config.check_flag(Client::Flag::DEBUG_ENABLED)) { vector flags_tokens; @@ -4183,9 +4183,7 @@ shared_ptr create_game_generic( } game->password = password; - game->section_id = (c->config.override_section_id != 0xFF) - ? c->config.override_section_id - : p->disp.visual.section_id; + game->override_section_id = c->config.override_section_id; game->episode = episode; game->mode = mode; if (game->mode == GameMode::CHALLENGE) { diff --git a/src/SendCommands.cc b/src/SendCommands.cc index 39881b12..a8b0c73e 100644 --- a/src/SendCommands.cc +++ b/src/SendCommands.cc @@ -1671,7 +1671,7 @@ static void send_join_spectator_team(shared_ptr c, shared_ptr l) cmd.variations.clear(0); cmd.client_id = c->lobby_client_id; cmd.event = l->event; - cmd.section_id = l->section_id; + cmd.section_id = l->effective_section_id(); cmd.rare_seed = l->random_seed; cmd.episode = 0xFF; @@ -1811,7 +1811,7 @@ void send_join_game(shared_ptr c, shared_ptr l) { cmd.difficulty = l->difficulty; cmd.battle_mode = (l->mode == GameMode::BATTLE) ? 1 : 0; cmd.event = l->event; - cmd.section_id = l->section_id; + cmd.section_id = l->effective_section_id(); cmd.challenge_mode = (l->mode == GameMode::CHALLENGE) ? 1 : 0; cmd.rare_seed = l->random_seed; return populate_lobby_data(cmd); diff --git a/tests/GC-HeartSymbol.test.txt b/tests/GC-HeartSymbol.test.txt index 9acbdfb5..1060d683 100644 --- a/tests/GC-HeartSymbol.test.txt +++ b/tests/GC-HeartSymbol.test.txt @@ -5282,7 +5282,7 @@ I 23921 2024-03-03 21:21:19 - [Commands] Received from C-2 (Jess) (version=GC_V3 0000 | 09 00 0C 00 44 00 00 44 15 00 00 00 | D D I 23921 2024-03-03 21:21:19 - [Commands] Sending to C-2 (Jess) (version=GC_V3 command=11 flag=00) 0000 | 11 00 2C 00 00 00 00 00 00 00 00 00 45 70 32 20 | , Ep2 -0010 | 4E 20 4E 6D 6C 20 50 6E 6B 0A 09 43 36 43 68 65 | N Nml Pnk C6Che +0010 | 4E 20 4E 6D 6C 20 56 69 72 0A 09 43 36 43 68 65 | N Nml Vir C6Che 0020 | 61 74 73 20 6F 6E 09 43 37 00 00 00 | ats on C7 I 23921 2024-03-03 21:21:22 - [Commands] Received from C-2 (Jess) (version=GC_V3 command=60 flag=00) 0000 | 60 00 10 00 52 03 00 00 00 00 00 00 00 80 FF FF | ` R diff --git a/tests/PC-DCv1-CrossplayPrivateDrops.test.txt b/tests/PC-DCv1-CrossplayPrivateDrops.test.txt index 3bc8d459..c457ffa4 100644 --- a/tests/PC-DCv1-CrossplayPrivateDrops.test.txt +++ b/tests/PC-DCv1-CrossplayPrivateDrops.test.txt @@ -5252,7 +5252,7 @@ I 97037 2023-12-29 15:59:32 - [Commands] Sending to C-3 (Tali) (version=PC_V2 co 0110 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | 0120 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | 0130 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | -0140 | 00 00 00 00 00 01 01 00 00 00 04 00 52 52 7A 09 | RRz +0140 | 00 00 00 00 00 01 01 00 00 00 08 00 52 52 7A 09 | RRz I 97037 2023-12-29 15:59:32 - [C-3] Creating game join command queue I 97037 2023-12-29 15:59:32 - [Commands] Sending to C-3 (Tali) (version=PC_V2 command=1D flag=00) 0000 | 04 00 1D 00 |