From b1531139c00b5d7f8afa0d5b345a45b748f414e6 Mon Sep 17 00:00:00 2001 From: Martin Michelsen Date: Sun, 9 Jul 2023 16:22:11 -0700 Subject: [PATCH] implement player records command --- src/Main.cc | 5 +- src/PSOEncryption.cc | 40 +++++--- src/PSOEncryption.hh | 32 ++++++- src/Player.cc | 137 ++++++++++++++++++++++++--- src/Player.hh | 119 +++++++++++++---------- src/ProxyCommands.cc | 2 + src/ReceiveCommands.cc | 15 +-- src/SendCommands.cc | 70 ++++++++++---- src/SendCommands.hh | 1 + system/players/default_player_0.nsc | Bin 8072 -> 8072 bytes system/players/default_player_1.nsc | Bin 8072 -> 8072 bytes system/players/default_player_10.nsc | Bin 8072 -> 8072 bytes system/players/default_player_11.nsc | Bin 8072 -> 8072 bytes system/players/default_player_2.nsc | Bin 8072 -> 8072 bytes system/players/default_player_3.nsc | Bin 8072 -> 8072 bytes system/players/default_player_4.nsc | Bin 8072 -> 8072 bytes system/players/default_player_5.nsc | Bin 8072 -> 8072 bytes system/players/default_player_6.nsc | Bin 8072 -> 8072 bytes system/players/default_player_7.nsc | Bin 8072 -> 8072 bytes system/players/default_player_8.nsc | Bin 8072 -> 8072 bytes system/players/default_player_9.nsc | Bin 8072 -> 8072 bytes tests/DCv2-GameSmokeTest.test.txt | 39 ++++++++ tests/GC-Episode3Battle.test.txt | 38 ++++++++ tests/GC-ForestGame.test.txt | 57 +++++++++++ tests/PC-BasicGame.test.txt | 34 +++++++ 25 files changed, 478 insertions(+), 111 deletions(-) diff --git a/src/Main.cc b/src/Main.cc index 907305e4..14cc6faf 100644 --- a/src/Main.cc +++ b/src/Main.cc @@ -829,10 +829,9 @@ int main(int argc, char** argv) { case Behavior::ENCRYPT_CHALLENGE_DATA: case Behavior::DECRYPT_CHALLENGE_DATA: { string data = read_input_data(); - const uint8_t* u8data = reinterpret_cast(data.data()); string result = (behavior == Behavior::DECRYPT_CHALLENGE_DATA) - ? decrypt_challenge_rank_text(u8data, data.size()) - : encrypt_challenge_rank_text(u8data, data.size()); + ? decrypt_challenge_rank_text(data) + : encrypt_challenge_rank_text(data); write_output_data(result.data(), result.size()); break; } diff --git a/src/PSOEncryption.cc b/src/PSOEncryption.cc index 9111532c..92c5a191 100644 --- a/src/PSOEncryption.cc +++ b/src/PSOEncryption.cc @@ -887,13 +887,13 @@ void decrypt_trivial_gci_data(void* data, size_t size, uint8_t basis) { } template -StringT crypt_challenge_rank_text(const void* src, size_t size) { - if (size == 0) { +StringT crypt_challenge_rank_text(const void* src, size_t count) { + if (count == 0) { return StringT(); } StringT ret; - StringReader r(src, size); + StringReader r(src, count * sizeof(typename StringT::value_type)); typename StringT::value_type prev = 0; while (!r.eof()) { typename StringT::value_type ch = r.get(); @@ -903,7 +903,7 @@ StringT crypt_challenge_rank_text(const void* src, size_t size) { if (ret.empty()) { ret.push_back(ch ^ 0x7F); } else { - ret.push_back(IsEncrypt ? ((ch - prev) ^ 0x7F) : ((ch ^ 0x7F) + ret.back())); + ret.push_back((IsEncrypt ? ((ch - prev) ^ 0x7F) : ((ch ^ 0x7F) + ret.back())) & 0xFF); } prev = ch; } @@ -911,18 +911,34 @@ StringT crypt_challenge_rank_text(const void* src, size_t size) { return ret; } -string encrypt_challenge_rank_text(const uint8_t* src, size_t size) { - return crypt_challenge_rank_text(src, size); +string encrypt_challenge_rank_text(const char* src, size_t count) { + return crypt_challenge_rank_text(src, count); } -string decrypt_challenge_rank_text(const uint8_t* src, size_t size) { - return crypt_challenge_rank_text(src, size); +string decrypt_challenge_rank_text(const char* src, size_t count) { + return crypt_challenge_rank_text(src, count); } -u16string encrypt_challenge_rank_text(const char16_t* src, size_t size) { - return crypt_challenge_rank_text(src, size); +u16string encrypt_challenge_rank_text(const char16_t* src, size_t count) { + return crypt_challenge_rank_text(src, count); } -u16string decrypt_challenge_rank_text(const char16_t* src, size_t size) { - return crypt_challenge_rank_text(src, size); +u16string decrypt_challenge_rank_text(const char16_t* src, size_t count) { + return crypt_challenge_rank_text(src, count); +} + +std::string decrypt_challenge_rank_text(const std::string& data) { + return decrypt_challenge_rank_text(data.data(), data.size()); +} + +std::string encrypt_challenge_rank_text(const std::string& data) { + return encrypt_challenge_rank_text(data.data(), data.size()); +} + +std::u16string decrypt_challenge_rank_text(const std::u16string& data) { + return decrypt_challenge_rank_text(data.data(), data.size()); +} + +std::u16string encrypt_challenge_rank_text(const std::u16string& data) { + return encrypt_challenge_rank_text(data.data(), data.size()); } diff --git a/src/PSOEncryption.hh b/src/PSOEncryption.hh index 62f92998..cd14fb43 100644 --- a/src/PSOEncryption.hh +++ b/src/PSOEncryption.hh @@ -241,7 +241,31 @@ private: void decrypt_trivial_gci_data(void* data, size_t size, uint8_t basis); -std::string decrypt_challenge_rank_text(const uint8_t* data, size_t size); -std::string encrypt_challenge_rank_text(const uint8_t* data, size_t size); -std::u16string decrypt_challenge_rank_text(const le_uint16_t* data, size_t size); -std::u16string encrypt_challenge_rank_text(const le_uint16_t* data, size_t size); +std::string decrypt_challenge_rank_text(const char* data, size_t count); +std::string decrypt_challenge_rank_text(const std::string& data); +std::string encrypt_challenge_rank_text(const char* data, size_t count); +std::string encrypt_challenge_rank_text(const std::string& data); +std::u16string decrypt_challenge_rank_text(const char16_t* data, size_t count); +std::u16string decrypt_challenge_rank_text(const std::u16string& data); +std::u16string encrypt_challenge_rank_text(const char16_t* data, size_t count); +std::u16string encrypt_challenge_rank_text(const std::u16string& data); + +template +std::string decrypt_challenge_rank_text(const ptext& data) { + return decrypt_challenge_rank_text(data.data(), data.size()); +} + +template +std::u16string decrypt_challenge_rank_text(const ptext& data) { + return decrypt_challenge_rank_text(data.data(), data.size()); +} + +template +std::string encrypt_challenge_rank_text(const ptext& data) { + return encrypt_challenge_rank_text(data.data(), data.size()); +} + +template +std::u16string encrypt_challenge_rank_text(const ptext& data) { + return encrypt_challenge_rank_text(data.data(), data.size()); +} diff --git a/src/Player.cc b/src/Player.cc index 6a6c644e..19786b43 100644 --- a/src/Player.cc +++ b/src/Player.cc @@ -11,6 +11,7 @@ #include "FileContentsCache.hh" #include "ItemData.hh" #include "Loggers.hh" +#include "PSOEncryption.hh" #include "StaticGameData.hh" #include "Text.hh" #include "Version.hh" @@ -18,10 +19,8 @@ using namespace std; // Originally there was going to be a language-based header, but then I decided -// against it. These strings were already in use for that parser, so I didn't -// bother changing them. -static const string PLAYER_FILE_SIGNATURE = - "newserv player file format; 10 sections present; sequential;"; +// against it. This string was already in use for that parser, so I didn't +// bother changing it. static const string ACCOUNT_FILE_SIGNATURE = "newserv account file format; 7 sections present; sequential;"; @@ -226,7 +225,6 @@ shared_ptr ClientGameData::player(bool should_load) { if (!this->player_data.get() && should_load) { if (this->bb_username.empty()) { this->player_data.reset(new SavedPlayerDataBB()); - this->player_data->signature = PLAYER_FILE_SIGNATURE; } else { this->load_player_data(); } @@ -273,9 +271,7 @@ void ClientGameData::create_player( shared_ptr level_table) { shared_ptr data(new SavedPlayerDataBB( load_object_file(player_template_filename(preview.visual.char_class)))); - if (data->signature != PLAYER_FILE_SIGNATURE) { - throw runtime_error("player data header is incorrect"); - } + data->update_to_latest_version(); try { data->disp.apply_preview(preview); @@ -335,13 +331,15 @@ void ClientGameData::save_account_data() const { void ClientGameData::load_player_data() { this->last_play_time_update = now(); string filename = this->player_data_filename(); - shared_ptr data(new SavedPlayerDataBB( + this->player_data.reset(new SavedPlayerDataBB( player_files_cache.get_obj_or_load(filename).obj)); - if (data->signature != PLAYER_FILE_SIGNATURE) { + try { + this->player_data->update_to_latest_version(); + } catch (const exception&) { + this->player_data.reset(); player_files_cache.delete_key(filename); - throw runtime_error("player data header is incorrect"); + throw; } - this->player_data = data; player_data_log.info("Loaded player data file %s", filename.c_str()); } @@ -412,7 +410,108 @@ void PlayerLobbyDataBB::clear() { this->unknown_a2 = 0; } -//////////////////////////////////////////////////////////////////////////////// +PlayerRecordsBB_Challenge::PlayerRecordsBB_Challenge(const PlayerRecordsDC_Challenge& rec) + : title_color(rec.title_color), + unknown_u0(rec.unknown_u0), + times_ep1_online(rec.times_ep1_online), + times_ep2_online(0), + times_ep1_offline(0), + unknown_g3(rec.unknown_g3), + grave_deaths(rec.grave_deaths), + unknown_u4(0), + grave_coords_time(rec.grave_coords_time), + grave_team(rec.grave_team), + grave_message(rec.grave_message), + unknown_m5(0), + unknown_t6(0), + rank_title(encrypt_challenge_rank_text(decode_sjis(decrypt_challenge_rank_text(rec.rank_title)))), + unknown_l7(0) {} + +PlayerRecordsBB_Challenge::PlayerRecordsBB_Challenge(const PlayerRecordsPC_Challenge& rec) + : title_color(rec.title_color), + unknown_u0(rec.unknown_u0), + times_ep1_online(rec.times_ep1_online), + times_ep2_online(0), + times_ep1_offline(0), + unknown_g3(rec.unknown_g3), + grave_deaths(rec.grave_deaths), + unknown_u4(0), + grave_coords_time(rec.grave_coords_time), + grave_team(rec.grave_team), + grave_message(rec.grave_message), + unknown_m5(0), + unknown_t6(0), + rank_title(rec.rank_title), + unknown_l7(0) {} + +PlayerRecordsBB_Challenge::PlayerRecordsBB_Challenge(const PlayerRecordsV3_Challenge& rec) + : title_color(rec.title_color), + unknown_u0(rec.unknown_u0), + times_ep1_online(rec.times_ep1_online), + times_ep2_online(rec.times_ep2_online), + times_ep1_offline(rec.times_ep1_offline), + unknown_g3(rec.unknown_g3), + grave_deaths(rec.grave_deaths), + unknown_u4(rec.unknown_u4), + grave_coords_time(rec.grave_coords_time), + grave_team(rec.grave_team), + grave_message(rec.grave_message), + unknown_m5(rec.unknown_m5), + unknown_t6(rec.unknown_t6), + rank_title(encrypt_challenge_rank_text(decode_sjis(decrypt_challenge_rank_text(rec.rank_title)))), + unknown_l7(rec.unknown_l7) {} + +PlayerRecordsBB_Challenge::operator PlayerRecordsDC_Challenge() const { + PlayerRecordsDC_Challenge ret; + ret.title_color = this->title_color; + ret.unknown_u0 = this->unknown_u0; + ret.rank_title = encrypt_challenge_rank_text(encode_sjis(decrypt_challenge_rank_text(this->rank_title))); + ret.times_ep1_online = this->times_ep1_online; + ret.unknown_g3 = 0; + ret.grave_deaths = this->grave_deaths; + ret.grave_coords_time = this->grave_coords_time; + ret.grave_team = this->grave_team; + ret.grave_message = this->grave_message; + ret.times_ep1_offline = this->times_ep1_offline; + ret.unknown_l4.clear(0); + return ret; +} + +PlayerRecordsBB_Challenge::operator PlayerRecordsPC_Challenge() const { + PlayerRecordsPC_Challenge ret; + ret.title_color = this->title_color; + ret.unknown_u0 = this->unknown_u0; + ret.rank_title = this->rank_title; + ret.times_ep1_online = this->times_ep1_online; + ret.unknown_g3 = 0; + ret.grave_deaths = this->grave_deaths; + ret.grave_coords_time = this->grave_coords_time; + ret.grave_team = this->grave_team; + ret.grave_message = this->grave_message; + ret.times_ep1_offline = this->times_ep1_offline; + ret.unknown_l4.clear(0); + return ret; +} + +PlayerRecordsBB_Challenge::operator PlayerRecordsV3_Challenge() const { + PlayerRecordsV3_Challenge ret; + ret.title_color = this->title_color; + ret.unknown_u0 = this->unknown_u0; + ret.times_ep1_online = this->times_ep1_online; + ret.times_ep2_online = this->times_ep2_online; + ret.times_ep1_offline = this->times_ep1_offline; + ret.unknown_g3 = this->unknown_g3; + ret.grave_deaths = this->grave_deaths; + ret.unknown_u4 = this->unknown_u4; + ret.grave_coords_time = this->grave_coords_time; + ret.grave_team = this->grave_team; + ret.grave_message = this->grave_message; + ret.unknown_m5 = this->unknown_m5; + ret.unknown_t6 = this->unknown_t6; + ret.rank_title = encrypt_challenge_rank_text(encode_sjis(decrypt_challenge_rank_text(this->rank_title))); + ret.unknown_l7 = this->unknown_l7; + return ret; +} PlayerInventoryItem::PlayerInventoryItem() { this->clear(); @@ -454,6 +553,18 @@ PlayerInventory::PlayerInventory() tp_materials_used(0), language(0) {} +void SavedPlayerDataBB::update_to_latest_version() { + if (this->signature == PLAYER_FILE_SIGNATURE_V0) { + this->signature = PLAYER_FILE_SIGNATURE_V1; + this->unused.clear(); + this->battle_records.place_counts.clear(0); + this->battle_records.disconnect_count = 0; + this->battle_records.unknown_a1.clear(0); + } else if (this->signature != PLAYER_FILE_SIGNATURE_V1) { + throw runtime_error("player data has incorrect signature"); + } +} + // TODO: Eliminate duplication between this function and the parallel function // in PlayerBank void SavedPlayerDataBB::add_item(const PlayerInventoryItem& item) { diff --git a/src/Player.hh b/src/Player.hh index 23050cd1..4f5bc0f3 100644 --- a/src/Player.hh +++ b/src/Player.hh @@ -167,15 +167,15 @@ struct PlayerDispDataDCPCV3 { PlayerDispDataBB to_bb() const; } __attribute__((packed)); -// BB player preview format struct PlayerDispDataBBPreview { - le_uint32_t experience; - le_uint32_t level; + /* 00 */ le_uint32_t experience; + /* 04 */ le_uint32_t level; // The name field in this structure is used for the player's Guild Card // number, apparently (possibly because it's a char array and this is BB) - PlayerVisualConfig visual; - ptext name; - uint32_t play_time; + /* 08 */ PlayerVisualConfig visual; + /* 58 */ ptext name; + /* 78 */ uint32_t play_time; + /* 7C */ PlayerDispDataBBPreview() noexcept; } __attribute__((packed)); @@ -329,24 +329,24 @@ struct PlayerLobbyDataBB { template struct PlayerRecordsDCPC_Challenge { using CharT = typename std::conditional::type; - using CharBinT = typename std::conditional::type; - /* 00 */ le_uint16_t title_color; - /* 02 */ parray unknown_a0; - /* 04 */ parray rank_title; // Encrypted; see decrypt_challenge_rank_text - /* 10 */ parray unknown_a1; // TODO: This might be online or offline times - /* 34 */ le_uint16_t unknown_a2; - /* 36 */ le_uint16_t grave_deaths; + /* 00 */ le_uint16_t title_color = 0x7FFF; + /* 02 */ parray unknown_u0; + /* 04 */ ptext rank_title; // Encrypted; see decrypt_challenge_rank_text + /* 10 */ parray times_ep1_online; // TODO: This might be offline times + /* 34 */ le_uint16_t unknown_g3 = 0; + /* 36 */ le_uint16_t grave_deaths = 0; /* 38 */ parray grave_coords_time; /* 4C */ ptext grave_team; /* 60 */ ptext grave_message; - /* 78 */ parray times_ep1; // TODO: This might be offline times - /* 9C */ parray unknown_a3; + /* 78 */ parray times_ep1_offline; // TODO: This might be online times + /* 9C */ parray unknown_l4; /* A0 */ } __attribute__((packed)); struct PlayerRecordsDC_Challenge : PlayerRecordsDCPC_Challenge { } __attribute__((packed)); + struct PlayerRecordsPC_Challenge : PlayerRecordsDCPC_Challenge { } __attribute__((packed)); @@ -357,43 +357,53 @@ struct PlayerRecordsV3_Challenge { // Offsets are (1) relative to start of C5 entry, and (2) relative to start // of save file structure - /* 0000:001C */ U16T title_color; // XRGB1555 - /* 0002:001E */ parray unknown_a2; // Probably actually unused + /* 0000:001C */ U16T title_color = 0x7FFF; // XRGB1555 + /* 0002:001E */ parray unknown_u0; /* 0004:0020 */ parray times_ep1_online; /* 0028:0044 */ parray times_ep2_online; /* 003C:0058 */ parray times_ep1_offline; - /* 0060:007C */ parray unknown_a3; - /* 0064:0080 */ U16T grave_deaths; - /* 0066:0082 */ parray unknown_a4; // Probably actually unused + /* 0060:007C */ parray unknown_g3; + /* 0064:0080 */ U16T grave_deaths = 0; + /* 0066:0082 */ parray unknown_u4; /* 0068:0084 */ parray grave_coords_time; /* 007C:0098 */ ptext grave_team; /* 0090:00AC */ ptext grave_message; - /* 00B0:00CC */ parray unknown_a5; - /* 00B4:00D0 */ parray unknown_a6; - /* 00D8:00F4 */ parray rank_title; // Encrypted; see decrypt_challenge_rank_text - /* 00E4:0100 */ parray unknown_a7; + /* 00B0:00CC */ parray unknown_m5; + /* 00B4:00D0 */ parray unknown_t6; + /* 00D8:00F4 */ ptext rank_title; // Encrypted; see decrypt_challenge_rank_text + /* 00E4:0100 */ parray unknown_l7; /* 0100:011C */ } __attribute__((packed)); struct PlayerRecordsBB_Challenge { - // TODO: Figure out the rest of this structure. Probably it's very similar to - // the V3 structure, but it's a bit larger due to various text fields. - /* 0000 */ le_uint16_t title_color; // XRGB1555 - /* 0002 */ parray unknown_a2; // Probably actually unused - /* 0004 */ parray times_ep1; - /* 0028 */ parray times_ep2; + /* 0000 */ le_uint16_t title_color = 0x7FFF; // XRGB1555 + /* 0002 */ parray unknown_u0; + /* 0004 */ parray times_ep1_online; + /* 0028 */ parray times_ep2_online; /* 003C */ parray times_ep1_offline; - /* 0060 */ parray unknown_a3; - /* 0064 */ le_uint16_t grave_deaths; - /* 0066 */ parray unknown_a4; // Probably actually unused + /* 0060 */ parray unknown_g3; + /* 0064 */ le_uint16_t grave_deaths = 0; + /* 0066 */ parray unknown_u4; /* 0068 */ parray grave_coords_time; /* 007C */ ptext grave_team; /* 00A4 */ ptext grave_message; - /* 00E4 */ parray unknown_a5; - /* 00E8 */ parray unknown_a6; - /* 010C */ parray rank_title; // Encrypted; see decrypt_challenge_rank_text - /* 0124 */ parray unknown_a7; + /* 00E4 */ parray unknown_m5; + /* 00E8 */ parray unknown_t6; + /* 010C */ ptext rank_title; // Encrypted; see decrypt_challenge_rank_text + /* 0124 */ parray unknown_l7; /* 0140 */ + + PlayerRecordsBB_Challenge() = default; + PlayerRecordsBB_Challenge(const PlayerRecordsBB_Challenge& other) = default; + PlayerRecordsBB_Challenge& operator=(const PlayerRecordsBB_Challenge& other) = default; + + PlayerRecordsBB_Challenge(const PlayerRecordsDC_Challenge& rec); + PlayerRecordsBB_Challenge(const PlayerRecordsPC_Challenge& rec); + PlayerRecordsBB_Challenge(const PlayerRecordsV3_Challenge& rec); + + operator PlayerRecordsDC_Challenge() const; + operator PlayerRecordsPC_Challenge() const; + operator PlayerRecordsV3_Challenge() const; } __attribute__((packed)); template @@ -417,22 +427,27 @@ struct ChoiceSearchConfig { parray entries; } __attribute__((packed)); +constexpr uint64_t PLAYER_FILE_SIGNATURE_V0 = 0x6E65777365727620; +constexpr uint64_t PLAYER_FILE_SIGNATURE_V1 = 0xA904332D5CEF0296; + struct SavedPlayerDataBB { // .nsc file format - ptext signature; - PlayerDispDataBBPreview preview; - ptext auto_reply; - PlayerBank bank; - PlayerRecordsBB_Challenge challenge_records; - PlayerDispDataBB disp; - ptext guild_card_description; - ptext info_board; - PlayerInventory inventory; - parray quest_data1; - parray quest_data2; - parray tech_menu_config; - // TODO: We don't save battle records in this structure, which is wrong. - // Make a new save file format that doesn't have the super-long signature, - // and also can save battle records. + /* 0000 */ be_uint64_t signature = PLAYER_FILE_SIGNATURE_V1; + /* 0008 */ parray unused; + /* 0028 */ PlayerRecords_Battle battle_records; + /* 0040 */ PlayerDispDataBBPreview preview; + /* 00BC */ ptext auto_reply; + /* 0214 */ PlayerBank bank; + /* 14DC */ PlayerRecordsBB_Challenge challenge_records; + /* 161C */ PlayerDispDataBB disp; + /* 17AC */ ptext guild_card_description; + /* 185C */ ptext info_board; + /* 19B4 */ PlayerInventory inventory; + /* 1D00 */ parray quest_data1; + /* 1F08 */ parray quest_data2; + /* 1F60 */ parray tech_menu_config; + /* 1F88 */ + + void update_to_latest_version(); void add_item(const PlayerInventoryItem& item); PlayerInventoryItem remove_item( diff --git a/src/ProxyCommands.cc b/src/ProxyCommands.cc index fa8e2035..1978d148 100644 --- a/src/ProxyCommands.cc +++ b/src/ProxyCommands.cc @@ -1027,6 +1027,7 @@ static HandlerResult C_GXB_61(shared_ptr, } if (session.options.red_name && pd.disp.visual.name_color != 0xFFFF0000) { pd.disp.visual.name_color = 0xFFFF0000; + pd.records.challenge.title_color = 0x7C00; modified = true; } else if (session.options.blank_name && pd.disp.visual.name_color != 0x00000000) { pd.disp.visual.name_color = 0x00000000; @@ -1059,6 +1060,7 @@ static HandlerResult C_GXB_61(shared_ptr, } if (session.options.red_name && pd->disp.visual.name_color != 0xFFFF0000) { pd->disp.visual.name_color = 0xFFFF0000; + pd->records.challenge.title_color = 0x7C00; modified = true; } else if (session.options.blank_name && pd->disp.visual.name_color != 0x00000000) { pd->disp.visual.name_color = 0x00000000; diff --git a/src/ReceiveCommands.cc b/src/ReceiveCommands.cc index 53afae28..56ab60aa 100644 --- a/src/ReceiveCommands.cc +++ b/src/ReceiveCommands.cc @@ -74,7 +74,7 @@ static shared_ptr proxy_options_menu_for_client( } if (s->proxy_enable_login_options) { add_option(ProxyOptionsMenuItemID::RED_NAME, c->options.red_name, - u"Red name", u"Set your name\ncolor to red"); + u"Red name", u"Set the colors\nof your name and\nChallenge Mode\nrank to red"); add_option(ProxyOptionsMenuItemID::BLANK_NAME, c->options.blank_name, u"Blank name", u"Suppress your\ncharacter name\nduring login"); add_option(ProxyOptionsMenuItemID::SUPPRESS_LOGIN, c->options.suppress_remote_login, @@ -2446,7 +2446,8 @@ static void on_61_98(shared_ptr s, shared_ptr c, auto player = c->game_data.player(); player->inventory = pd.inventory; player->disp = pd.disp.to_bb(); - // TODO: Parse pd.records and send C5 at an appropriate time + player->battle_records = pd.records.battle; + player->challenge_records = pd.records.challenge; // TODO: Parse choice search config } break; @@ -2457,7 +2458,8 @@ static void on_61_98(shared_ptr s, shared_ptr c, auto account = c->game_data.account(); player->inventory = pd.inventory; player->disp = pd.disp.to_bb(); - // TODO: Parse pd.records and send C5 at an appropriate time + player->battle_records = pd.records.battle; + player->challenge_records = pd.records.challenge; // TODO: Parse choice search config account->blocked_senders = pd.blocked_senders; if (pd.auto_reply_enabled) { @@ -2490,7 +2492,8 @@ static void on_61_98(shared_ptr s, shared_ptr c, } } player->disp = cmd->disp.to_bb(); - // TODO: Parse cmd->records and send C5 at an appropriate time + player->battle_records = cmd->records.battle; + player->challenge_records = cmd->records.challenge; // TODO: Parse choice search config player->info_board = cmd->info_board; account->blocked_senders = cmd->blocked_senders; @@ -2499,7 +2502,6 @@ static void on_61_98(shared_ptr s, shared_ptr c, } else { player->auto_reply.clear(0); } - break; } case GameVersion::BB: { @@ -2508,7 +2510,8 @@ static void on_61_98(shared_ptr s, shared_ptr c, auto player = c->game_data.player(); // Note: we don't copy the inventory and disp here because we already have // them (we sent the player data to the client in the first place) - // TODO: Parse pd.records and send C5 at an appropriate time + player->battle_records = cmd.records.battle; + player->challenge_records = cmd.records.challenge; // TODO: Parse choice search config player->info_board = cmd.info_board; account->blocked_senders = cmd.blocked_senders; diff --git a/src/SendCommands.cc b/src/SendCommands.cc index 858cb26a..375b97e4 100644 --- a/src/SendCommands.cc +++ b/src/SendCommands.cc @@ -632,10 +632,8 @@ void send_complete_player_bb(shared_ptr c) { cmd.shortcuts = account->shortcuts; cmd.auto_reply = player->auto_reply; cmd.info_board = player->info_board; - cmd.battle_records.place_counts.clear(0); - cmd.battle_records.disconnect_count = 0; - cmd.battle_records.unknown_a1.clear(0); - cmd.unknown_a4 = 0; + cmd.battle_records = player->battle_records; + cmd.unknown_a4.clear(0); cmd.challenge_records = player->challenge_records; cmd.tech_menu_config = player->tech_menu_config; cmd.unknown_a6.clear(0); @@ -1383,6 +1381,30 @@ void send_lobby_list(shared_ptr c, shared_ptr s) { //////////////////////////////////////////////////////////////////////////////// // lobby joining +template +void send_player_records(shared_ptr c, shared_ptr l, shared_ptr joining_client) { + vector entries; + auto add_client = [&](shared_ptr lc) -> void { + auto lp = lc->game_data.player(); + auto& e = entries.emplace_back(); + e.client_id = lc->lobby_client_id; + e.challenge = lp->challenge_records; + e.battle = lp->battle_records; + }; + + if (joining_client) { + add_client(joining_client); + } else { + entries.reserve(12); + for (auto lc : l->clients) { + if (lc) { + add_client(lc); + } + } + } + send_command_vt(c->channel, 0xC5, entries.size(), entries); +} + static void send_join_spectator_team(shared_ptr c, shared_ptr l) { if (!(c->flags & Client::Flag::IS_EPISODE_3)) { throw runtime_error("lobby is not Episode 3"); @@ -1598,7 +1620,7 @@ void send_join_game_dc_nte(shared_ptr c, shared_ptr l) { send_command_t(c, 0x64, player_count, cmd); } -template +template void send_join_lobby_t(shared_ptr c, shared_ptr l, shared_ptr joining_client = nullptr) { uint8_t command; @@ -1612,6 +1634,10 @@ void send_join_lobby_t(shared_ptr c, shared_ptr l, command = joining_client ? 0x68 : 0x67; } + if ((c->version() != GameVersion::DC) || !(c->flags & Client::Flag::IS_DC_V1)) { + send_player_records(c, l, joining_client); + } + uint8_t lobby_type = (l->type > 14) ? (l->block - 1) : l->type; // Allow non-canonical lobby types on GC. They may work on other versions too, // but I haven't verified which values don't crash on each version. @@ -1745,23 +1771,24 @@ void send_join_lobby(shared_ptr c, shared_ptr l) { } } else { switch (c->version()) { - case GameVersion::PC: - send_join_lobby_t(c, l); - break; case GameVersion::DC: if (c->flags & (Client::Flag::IS_TRIAL_EDITION | Client::Flag::IS_DC_V1_PROTOTYPE)) { send_join_lobby_dc_nte(c, l); - break; + } else { + send_join_lobby_t(c, l); } - [[fallthrough]]; + break; + case GameVersion::PC: + send_join_lobby_t(c, l); + break; case GameVersion::GC: - send_join_lobby_t(c, l); + send_join_lobby_t(c, l); break; case GameVersion::XB: - send_join_lobby_t(c, l); + send_join_lobby_t(c, l); break; case GameVersion::BB: - send_join_lobby_t(c, l); + send_join_lobby_t(c, l); break; default: throw logic_error("unimplemented versioned command"); @@ -1779,23 +1806,24 @@ void send_join_lobby(shared_ptr c, shared_ptr l) { void send_player_join_notification(shared_ptr c, shared_ptr l, shared_ptr joining_client) { switch (c->version()) { - case GameVersion::PC: - send_join_lobby_t(c, l, joining_client); - break; case GameVersion::DC: if (c->flags & (Client::Flag::IS_TRIAL_EDITION | Client::Flag::IS_DC_V1_PROTOTYPE)) { send_join_lobby_dc_nte(c, l, joining_client); - break; + } else { + send_join_lobby_t(c, l, joining_client); } - [[fallthrough]]; + break; + case GameVersion::PC: + send_join_lobby_t(c, l, joining_client); + break; case GameVersion::GC: - send_join_lobby_t(c, l, joining_client); + send_join_lobby_t(c, l, joining_client); break; case GameVersion::XB: - send_join_lobby_t(c, l, joining_client); + send_join_lobby_t(c, l, joining_client); break; case GameVersion::BB: - send_join_lobby_t(c, l, joining_client); + send_join_lobby_t(c, l, joining_client); break; default: throw logic_error("unimplemented versioned command"); diff --git a/src/SendCommands.hh b/src/SendCommands.hh index 59c6d012..c06a49c8 100644 --- a/src/SendCommands.hh +++ b/src/SendCommands.hh @@ -264,6 +264,7 @@ void send_quest_menu(std::shared_ptr c, uint32_t menu_id, std::shared_ptr category_index, uint8_t flags); void send_lobby_list(std::shared_ptr c, std::shared_ptr s); +void send_player_records(std::shared_ptr c, std::shared_ptr l, std::shared_ptr joining_client = nullptr); void send_join_lobby(std::shared_ptr c, std::shared_ptr l); void send_player_join_notification(std::shared_ptr c, std::shared_ptr l, std::shared_ptr joining_client); diff --git a/system/players/default_player_0.nsc b/system/players/default_player_0.nsc index f8800a641571249bb624ff5e50e330cefe47ffee..1246b6ed7b4bfa57712c4e0439489b976f5bb6b4 100644 GIT binary patch delta 21 ccmeCM@37}s$zrS<^PXwiEhxP+rxun18JUSW)*EenHz diff --git a/system/players/default_player_1.nsc b/system/players/default_player_1.nsc index cf5364a67b7e785df1ed9e88a39a370c30497178..d9efe707dd03ee799de6e59431dcde8caa85ad7b 100644 GIT binary patch delta 21 ccmeCM@37}s$zrS<^PXwiEhxP+rxun18JUSW)*EenHz diff --git a/system/players/default_player_10.nsc b/system/players/default_player_10.nsc index e67621e6bc044a13ae0ef86cba512f7dceaa834f..5b708a5391a62746cd356f9bda0e4f119a4d1b82 100644 GIT binary patch delta 21 ccmeCM@37}s$zrS<^PXwiEhxP+rxun18JUSW)*EenHz diff --git a/system/players/default_player_11.nsc b/system/players/default_player_11.nsc index 6d8c838f79b4748439f4f59904049da76958766a..bd0e62b1da9739fa1cf97568a998799e52d24574 100644 GIT binary patch delta 21 ccmeCM@37}s$zrS<^PXwiEhxP+rxun18JUSW)*EenHz diff --git a/system/players/default_player_2.nsc b/system/players/default_player_2.nsc index 991c065ecfde91cd9e911d275c6a86e535a2f65c..e4ce0b2459830d496dde33e0f85c5a29d9f8a46c 100644 GIT binary patch delta 21 ccmeCM@37}s$zrS<^PXwiEhxP+rxun18JUSW)*EenHz diff --git a/system/players/default_player_3.nsc b/system/players/default_player_3.nsc index fba974a615675510fa3cde2c6e39f3506a195cbd..e3bca578eb58184ea8a95bf8c3e7c71a118a1210 100644 GIT binary patch delta 21 ccmeCM@37}s$zrS<^PXwiEhxP+rxun18JUSW)*EenHz diff --git a/system/players/default_player_4.nsc b/system/players/default_player_4.nsc index 10446d00b903ae286c64d5983e8e235ef1d873d0..1bcd511a54cc35c2644ee521570d44e5c5521cce 100644 GIT binary patch delta 21 ccmeCM@37}s$zrS<^PXwiEhxP+rxun18JUSW)*EenHz diff --git a/system/players/default_player_5.nsc b/system/players/default_player_5.nsc index 409b03107556726f0c7fe642392359de974ad859..d858d82708fb307caff16efb2647637974f6e2b0 100644 GIT binary patch delta 21 ccmeCM@37}s$zrS<^PXwiEhxP+rxun18JUSW)*EenHz diff --git a/system/players/default_player_6.nsc b/system/players/default_player_6.nsc index 0437f50df81a74239dd11c8553bfdee972170dd4..f913377b1801a831636b0ab304a9af8d6d63bab6 100644 GIT binary patch delta 21 ccmeCM@37}s$zrS<^PXwiEhxP+rxun18JUSW)*EenHz diff --git a/system/players/default_player_7.nsc b/system/players/default_player_7.nsc index 3062f234cfa1fffda68c9f3753ca87a46931e8b9..c81e632ac508aec22252b163ca1cdb79226013ea 100644 GIT binary patch delta 21 ccmeCM@37}s$zrS<^PXwiEhxP+rxun18JUSW)*EenHz diff --git a/system/players/default_player_8.nsc b/system/players/default_player_8.nsc index aef18d3a2591da60835e1b6bb523797078e7591c..4ec70d0caa0f53dcf23a69646ccdef92bcc4da6a 100644 GIT binary patch delta 21 ccmeCM@37}s$zrS<^PXwiEhxP+rxun18JUSW)*EenHz diff --git a/system/players/default_player_9.nsc b/system/players/default_player_9.nsc index 99bb8a254ad3cda859997d70dea796e8564826bd..b12ac1b92ccd2aff84863a71733c6543d4a55fdb 100644 GIT binary patch delta 21 ccmeCM@37}s$zrS<^PXwiEhxP+rxun18JUSW)*EenHz diff --git a/tests/DCv2-GameSmokeTest.test.txt b/tests/DCv2-GameSmokeTest.test.txt index d2408ff3..32d45826 100644 --- a/tests/DCv2-GameSmokeTest.test.txt +++ b/tests/DCv2-GameSmokeTest.test.txt @@ -231,6 +231,19 @@ I 40992 2023-05-26 10:52:57 - [Commands] Received from C-2 (version=DC command=6 04E0 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | 04F0 | 00 00 00 00 | I 40992 2023-05-26 10:52:57 - [Commands] Sending to C-2 (Tali) (version=DC command=67 flag=01) +0000 | C5 01 C0 00 00 00 00 00 00 00 00 00 00 00 00 00 | +0010 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +0020 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +0030 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +0040 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +0050 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +0060 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +0070 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +0080 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +0090 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +00A0 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +00B0 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +I 40992 2023-05-26 10:52:57 - [Commands] Sending to C-2 (Tali) (version=DC command=67 flag=01) 0000 | 67 01 4C 04 00 00 01 00 01 00 00 00 00 00 00 00 | g L 0010 | 00 00 01 00 77 77 77 77 7F 00 00 01 00 00 00 00 | wwww 0020 | 09 4A 54 61 6C 69 00 00 00 00 00 00 00 00 00 00 | JTali @@ -365,6 +378,19 @@ I 40992 2023-05-26 10:53:04 - [Commands] Received from C-2 (Tali) (version=DC co I 40992 2023-05-26 10:53:08 - [Commands] Received from C-2 (Tali) (version=DC command=84 flag=00) 0000 | 84 00 0C 00 33 00 00 33 0C 00 00 00 | 3 3 I 40992 2023-05-26 10:53:08 - [Commands] Sending to C-2 (Tali) (version=DC command=67 flag=01) +0000 | C5 01 C0 00 00 00 00 00 00 00 00 00 00 00 00 00 | +0010 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +0020 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +0030 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +0040 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +0050 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +0060 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +0070 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +0080 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +0090 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +00A0 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +00B0 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +I 40992 2023-05-26 10:53:08 - [Commands] Sending to C-2 (Tali) (version=DC command=67 flag=01) 0000 | 67 01 4C 04 00 00 01 0B 0C 00 00 00 00 00 00 00 | g L 0010 | 00 00 01 00 77 77 77 77 7F 00 00 01 00 00 00 00 | wwww 0020 | 09 4A 54 61 6C 69 00 00 00 00 00 00 00 00 00 00 | JTali @@ -1326,6 +1352,19 @@ I 40992 2023-05-26 10:55:21 - [Lobby/15] Deleted lobby I 40992 2023-05-26 10:55:24 - [Commands] Received from C-2 (Tali) (version=DC command=84 flag=00) 0000 | 84 00 0C 00 33 00 00 33 0C 00 00 00 | 3 3 I 40992 2023-05-26 10:55:24 - [Commands] Sending to C-2 (Tali) (version=DC command=67 flag=01) +0000 | C5 01 C0 00 00 00 00 00 00 00 00 00 00 00 00 00 | +0010 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +0020 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +0030 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +0040 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +0050 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +0060 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +0070 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +0080 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +0090 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +00A0 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +00B0 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +I 40992 2023-05-26 10:55:24 - [Commands] Sending to C-2 (Tali) (version=DC command=67 flag=01) 0000 | 67 01 4C 04 00 00 01 0B 0C 00 00 00 00 00 00 00 | g L 0010 | 00 00 01 00 77 77 77 77 7F 00 00 01 00 00 00 00 | wwww 0020 | 09 4A 54 61 6C 69 00 00 00 00 00 00 00 00 00 00 | JTali diff --git a/tests/GC-Episode3Battle.test.txt b/tests/GC-Episode3Battle.test.txt index f8931898..686d21c0 100644 --- a/tests/GC-Episode3Battle.test.txt +++ b/tests/GC-Episode3Battle.test.txt @@ -2859,6 +2859,25 @@ I 48349 2023-05-26 15:59:03 - [Commands] Received from C-4 (version=GC command=6 2A60 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | 2A70 | 00 00 00 00 00 00 00 00 | I 48349 2023-05-26 15:59:03 - [Commands] Sending to C-4 (Tali) (version=GC command=67 flag=01) +0000 | C5 01 20 01 00 00 00 00 FF 7F 00 00 00 00 00 00 | +0010 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +0020 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +0030 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +0040 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +0050 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +0060 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +0070 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +0080 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +0090 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +00A0 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +00B0 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +00C0 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +00D0 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +00E0 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +00F0 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +0100 | 00 00 00 00 00 00 00 00 8E 00 0A 00 00 00 00 00 | +0110 | 1D 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +I 48349 2023-05-26 15:59:03 - [Commands] Sending to C-4 (Tali) (version=GC command=67 flag=01) 0000 | 67 01 4C 04 00 00 01 0F 10 00 00 00 00 00 00 00 | g L 0010 | 00 00 01 00 11 11 11 11 7F 00 00 01 00 00 00 00 | 0020 | 09 4A 54 61 6C 69 00 00 00 00 00 00 00 00 00 00 | JTali @@ -25901,6 +25920,25 @@ I 48349 2023-05-26 16:04:50 - [Commands] Sending to C-4 (Tali) (version=GC comma I 48349 2023-05-26 16:04:50 - [Commands] Received from C-4 (Tali) (version=GC command=84 flag=00) 0000 | 84 00 0C 00 33 00 00 33 10 00 00 00 | 3 3 I 48349 2023-05-26 16:04:50 - [Commands] Sending to C-4 (Tali) (version=GC command=67 flag=01) +0000 | C5 01 20 01 00 00 00 00 FF 7F 00 00 00 00 00 00 | +0010 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +0020 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +0030 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +0040 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +0050 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +0060 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +0070 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +0080 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +0090 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +00A0 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +00B0 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +00C0 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +00D0 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +00E0 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +00F0 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +0100 | 00 00 00 00 00 00 00 00 8F 00 0A 00 00 00 00 00 | +0110 | 1D 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +I 48349 2023-05-26 16:04:50 - [Commands] Sending to C-4 (Tali) (version=GC command=67 flag=01) 0000 | 67 01 4C 04 00 00 01 0F 10 00 00 00 00 00 00 00 | g L 0010 | 00 00 01 00 11 11 11 11 7F 00 00 01 00 00 00 00 | 0020 | 09 4A 54 61 6C 69 00 00 00 00 00 00 00 00 00 00 | JTali diff --git a/tests/GC-ForestGame.test.txt b/tests/GC-ForestGame.test.txt index a47361d4..3ec49c40 100644 --- a/tests/GC-ForestGame.test.txt +++ b/tests/GC-ForestGame.test.txt @@ -275,6 +275,25 @@ I 49108 2023-05-26 16:18:08 - [Commands] Received from C-2 (version=GC command=6 0660 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | 0670 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | I 49108 2023-05-26 16:18:08 - [Commands] Sending to C-2 (Jess) (version=GC command=67 flag=01) +0000 | C5 01 20 01 00 00 00 00 00 00 00 00 00 00 00 00 | +0010 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +0020 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +0030 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +0040 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +0050 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +0060 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +0070 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +0080 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +0090 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +00A0 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +00B0 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +00C0 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +00D0 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +00E0 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +00F0 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +0100 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +0110 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +I 49108 2023-05-26 16:18:08 - [Commands] Sending to C-2 (Jess) (version=GC command=67 flag=01) 0000 | 67 01 4C 04 00 00 01 00 01 00 00 00 00 00 00 00 | g L 0010 | 00 00 01 00 11 11 11 11 7F 00 00 01 00 00 00 00 | 0020 | 09 4A 4A 65 73 73 00 00 00 00 00 00 00 00 00 00 | JJess @@ -465,6 +484,25 @@ I 49108 2023-05-26 16:18:18 - [Commands] Received from C-2 (Jess) (version=GC co I 49108 2023-05-26 16:18:21 - [Commands] Received from C-2 (Jess) (version=GC command=84 flag=00) 0000 | 84 00 0C 00 33 00 00 33 05 00 00 00 | 3 3 I 49108 2023-05-26 16:18:21 - [Commands] Sending to C-2 (Jess) (version=GC command=67 flag=01) +0000 | C5 01 20 01 00 00 00 00 00 00 00 00 00 00 00 00 | +0010 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +0020 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +0030 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +0040 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +0050 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +0060 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +0070 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +0080 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +0090 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +00A0 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +00B0 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +00C0 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +00D0 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +00E0 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +00F0 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +0100 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +0110 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +I 49108 2023-05-26 16:18:21 - [Commands] Sending to C-2 (Jess) (version=GC command=67 flag=01) 0000 | 67 01 4C 04 00 00 01 04 05 00 00 00 00 00 00 00 | g L 0010 | 00 00 01 00 11 11 11 11 7F 00 00 01 00 00 00 00 | 0020 | 09 4A 4A 65 73 73 00 00 00 00 00 00 00 00 00 00 | JJess @@ -9872,6 +9910,25 @@ I 49108 2023-05-26 16:28:04 - [Lobby/15] Deleted lobby I 49108 2023-05-26 16:28:09 - [Commands] Received from C-2 (Jess) (version=GC command=84 flag=00) 0000 | 84 00 0C 00 33 00 00 33 05 00 00 00 | 3 3 I 49108 2023-05-26 16:28:09 - [Commands] Sending to C-2 (Jess) (version=GC command=67 flag=01) +0000 | C5 01 20 01 00 00 00 00 00 00 00 00 00 00 00 00 | +0010 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +0020 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +0030 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +0040 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +0050 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +0060 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +0070 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +0080 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +0090 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +00A0 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +00B0 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +00C0 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +00D0 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +00E0 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +00F0 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +0100 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +0110 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +I 49108 2023-05-26 16:28:09 - [Commands] Sending to C-2 (Jess) (version=GC command=67 flag=01) 0000 | 67 01 4C 04 00 00 01 04 05 00 00 00 00 00 00 00 | g L 0010 | 00 00 01 00 11 11 11 11 7F 00 00 01 00 00 00 00 | 0020 | 09 4A 4A 65 73 73 00 00 00 00 00 00 00 00 00 00 | JJess diff --git a/tests/PC-BasicGame.test.txt b/tests/PC-BasicGame.test.txt index 6f9d0320..1454f18f 100644 --- a/tests/PC-BasicGame.test.txt +++ b/tests/PC-BasicGame.test.txt @@ -249,6 +249,23 @@ I 49484 2023-05-26 16:35:14 - [Commands] Received from C-3 (version=PC command=6 0590 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | 05A0 | 00 00 00 00 00 00 00 00 00 00 00 00 | I 49484 2023-05-26 16:35:14 - [Commands] Sending to C-3 (Tali) (version=PC command=67 flag=01) +0000 | F8 00 C5 01 00 00 00 00 00 00 00 00 00 00 00 00 | +0010 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +0020 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +0030 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +0040 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +0050 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +0060 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +0070 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +0080 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +0090 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +00A0 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +00B0 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +00C0 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +00D0 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +00E0 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +00F0 | 00 00 00 00 00 00 00 00 | +I 49484 2023-05-26 16:35:14 - [Commands] Sending to C-3 (Tali) (version=PC command=67 flag=01) 0000 | 5C 04 67 01 00 00 01 00 01 00 00 00 00 00 00 00 | \ g 0010 | 00 00 01 00 11 11 11 11 7F 00 00 01 00 00 00 00 | 0020 | 09 00 4A 00 54 00 61 00 6C 00 69 00 00 00 00 00 | J T a l i @@ -972,6 +989,23 @@ I 49484 2023-05-26 16:36:57 - [Lobby/15] Deleted lobby I 49484 2023-05-26 16:36:57 - [Commands] Received from C-3 (Tali) (version=PC command=84 flag=00) 0000 | 0C 00 84 00 33 00 00 33 01 00 00 00 | 3 3 I 49484 2023-05-26 16:36:57 - [Commands] Sending to C-3 (Tali) (version=PC command=67 flag=01) +0000 | F8 00 C5 01 00 00 00 00 00 00 00 00 00 00 00 00 | +0010 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +0020 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +0030 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +0040 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +0050 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +0060 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +0070 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +0080 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +0090 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +00A0 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +00B0 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +00C0 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +00D0 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +00E0 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | +00F0 | 00 00 00 00 00 00 00 00 | +I 49484 2023-05-26 16:36:57 - [Commands] Sending to C-3 (Tali) (version=PC command=67 flag=01) 0000 | 5C 04 67 01 00 00 01 00 01 00 00 00 00 00 00 00 | \ g 0010 | 00 00 01 00 11 11 11 11 7F 00 00 01 00 00 00 00 | 0020 | 09 00 4A 00 54 00 61 00 6C 00 69 00 00 00 00 00 | J T a l i