From c430340c9d222d560d2d095010a0ac32fa34c1ac Mon Sep 17 00:00:00 2001 From: Martin Michelsen Date: Fri, 8 Sep 2023 23:12:35 -0700 Subject: [PATCH] hide Ep3 maps that don't have enough player slots for the game --- src/Episode3/DataIndexes.cc | 38 ++++++++++++++++++++++++++++--------- src/Episode3/DataIndexes.hh | 9 +++------ src/Episode3/Server.cc | 2 +- 3 files changed, 33 insertions(+), 16 deletions(-) diff --git a/src/Episode3/DataIndexes.cc b/src/Episode3/DataIndexes.cc index c1bd5db6..f9c8423e 100644 --- a/src/Episode3/DataIndexes.cc +++ b/src/Episode3/DataIndexes.cc @@ -2026,12 +2026,31 @@ const string& MapIndex::MapEntry::compressed(bool is_trial) const { } } -const string& MapIndex::get_compressed_list() const { - if (this->compressed_map_list.empty()) { +const string& MapIndex::get_compressed_list(size_t num_players) const { + if (num_players == 0) { + throw runtime_error("cannot generate map list for no players"); + } + if (num_players > 4) { + throw logic_error("player count is too high in map list generation"); + } + string& compressed_map_list = this->compressed_map_lists.at(num_players - 1); + if (compressed_map_list.empty()) { StringWriter entries_w; StringWriter strings_w; + size_t num_maps = 0; for (const auto& map_it : this->maps) { + size_t map_num_players = 0; + for (size_t z = 0; z < 4; z++) { + uint8_t player_type = map_it.second->map.entry_states[z].player_type; + if (player_type == 0x00 || player_type == 0x01 || player_type == 0xFF) { + map_num_players++; + } + } + if (map_num_players < num_players) { + continue; + } + MapList::Entry e; const auto& map = map_it.second->map; e.map_x = map.map_x; @@ -2059,10 +2078,11 @@ const string& MapIndex::get_compressed_list() const { e.unknown_a1 = map_it.second->is_quest ? 0x00 : 0xFF; entries_w.put(e); + num_maps++; } MapList header; - header.num_maps = this->maps.size(); + header.num_maps = num_maps; header.unknown_a1 = 0; header.strings_offset = entries_w.size(); header.total_size = sizeof(MapList) + entries_w.size() + strings_w.size(); @@ -2075,15 +2095,15 @@ const string& MapIndex::get_compressed_list() const { StringWriter compressed_w; compressed_w.put_u32b(prs.input_size()); compressed_w.write(prs.close()); - this->compressed_map_list = std::move(compressed_w.str()); - if (this->compressed_map_list.size() > 0x7BEC) { - throw runtime_error("Episode 3 compressed map list is too large"); + compressed_map_list = std::move(compressed_w.str()); + if (compressed_map_list.size() > 0x7BEC) { + throw runtime_error(string_printf("compressed map list for %zu players is too large (0x%zX bytes)", num_players, compressed_map_list.size())); } size_t decompressed_size = sizeof(header) + entries_w.size() + strings_w.size(); - static_game_data_log.info("Generated Episode 3 compressed map list (0x%zX -> 0x%zX bytes)", - decompressed_size, this->compressed_map_list.size()); + static_game_data_log.info("Generated Episode 3 compressed map list for %zu player(s) (%zu maps; 0x%zX -> 0x%zX bytes)", + num_players, num_maps, decompressed_size, compressed_map_list.size()); } - return this->compressed_map_list; + return compressed_map_list; } shared_ptr MapIndex::definition_for_number(uint32_t id) const { diff --git a/src/Episode3/DataIndexes.hh b/src/Episode3/DataIndexes.hh index 733cd15a..8ea8d87d 100644 --- a/src/Episode3/DataIndexes.hh +++ b/src/Episode3/DataIndexes.hh @@ -1145,17 +1145,14 @@ public: mutable std::string compressed_trial_data; }; - const std::string& get_compressed_list() const; + const std::string& get_compressed_list(size_t num_players) const; std::shared_ptr definition_for_number(uint32_t id) const; std::shared_ptr definition_for_name(const std::string& name) const; std::set all_numbers() const; private: - // The compressed map list is generated on demand from the maps map below. - // It's marked mutable because the logical consistency of the MapIndex object - // is not violated from the caller's perspective even if we don't generate the - // compressed map list at load time. - mutable std::string compressed_map_list; + // The compressed map lists are generated on demand from the maps map below + mutable std::array compressed_map_lists; std::map> maps; std::unordered_map> maps_by_name; }; diff --git a/src/Episode3/Server.cc b/src/Episode3/Server.cc index dd61438b..1d4ebcf9 100644 --- a/src/Episode3/Server.cc +++ b/src/Episode3/Server.cc @@ -2168,7 +2168,7 @@ void Server::handle_6xB3x40_map_list_request(const string& data) { throw runtime_error("lobby is deleted"); } - const auto& list_data = this->base()->map_index->get_compressed_list(); + const auto& list_data = this->base()->map_index->get_compressed_list(l->count_clients()); StringWriter w; uint32_t subcommand_size = (list_data.size() + sizeof(G_MapList_GC_Ep3_6xB6x40) + 3) & (~3);