From 6368ebcd71c028f99a5c0effce4e4ce01b30b379 Mon Sep 17 00:00:00 2001 From: Martin Michelsen Date: Thu, 5 Oct 2023 00:00:03 -0700 Subject: [PATCH] use spectator text field for something --- src/Lobby.cc | 8 +- src/ReceiveCommands.cc | 24 +++- src/SendCommands.cc | 66 +++++++--- src/SendCommands.hh | 2 +- src/Text.hh | 6 + tests/GC-Episode3BattleWithSpectator.test.txt | 120 ++++++++++++------ 6 files changed, 158 insertions(+), 68 deletions(-) diff --git a/src/Lobby.cc b/src/Lobby.cc index 779893ac..9acdedc9 100644 --- a/src/Lobby.cc +++ b/src/Lobby.cc @@ -153,10 +153,10 @@ void Lobby::add_client(shared_ptr c, ssize_t required_client_id) { if (this->flags & Lobby::Flag::IS_SPECTATOR_TEAM) { auto watched_l = this->watched_lobby.lock(); if (watched_l) { - send_ep3_update_spectator_count(watched_l); + send_ep3_update_game_metadata(watched_l); } } else { - send_ep3_update_spectator_count(this->shared_from_this()); + send_ep3_update_game_metadata(this->shared_from_this()); } } } @@ -194,10 +194,10 @@ void Lobby::remove_client(shared_ptr c) { if (this->flags & Lobby::Flag::IS_SPECTATOR_TEAM) { auto watched_l = this->watched_lobby.lock(); if (watched_l) { - send_ep3_update_spectator_count(watched_l); + send_ep3_update_game_metadata(watched_l); } } else { - send_ep3_update_spectator_count(this->shared_from_this()); + send_ep3_update_game_metadata(this->shared_from_this()); } } } diff --git a/src/ReceiveCommands.cc b/src/ReceiveCommands.cc index 0b2e4556..0a006173 100644 --- a/src/ReceiveCommands.cc +++ b/src/ReceiveCommands.cc @@ -3568,7 +3568,7 @@ static void on_6F(shared_ptr c, uint16_t, uint32_t, const string& data) watched_lobby->ep3_server->send_commands_for_joining_spectator( c->channel, c->flags & Client::Flag::IS_EP3_TRIAL_EDITION); } - send_ep3_update_spectator_count(watched_lobby); + send_ep3_update_game_metadata(watched_lobby); } // If there are more players to bring in, try to do so @@ -3576,6 +3576,26 @@ static void on_6F(shared_ptr c, uint16_t, uint32_t, const string& data) add_next_game_client(l); } +static void on_99_GC(shared_ptr c, uint16_t, uint32_t, const string& data) { + check_size_v(data.size(), 0); + + // This is an odd place to send 6xB4x52, but there's a reason for it. If the + // client receives 6xB4x52 while it's loading the battlefield, it won't set + // the spectator count or top-bar text. But the client doesn't send anything + // when it's done loading the battlefield, so we have to have some other way + // of knowing when it's ready. We do this by sending a B1 (server time) + // command immediately after the E8 (join spectator team) command, which + // allows us to delay sending the 6xB4x52 until the server responds with a 99 + // command after loading is done. + auto l = c->lobby.lock(); + if (l && l->is_game() && (l->episode == Episode::EP3) && (l->flags & Lobby::Flag::IS_SPECTATOR_TEAM)) { + auto watched_l = l->watched_lobby.lock(); + if (watched_l) { + send_ep3_update_game_metadata(watched_l); + } + } +} + static void on_D0_V3_BB(shared_ptr c, uint16_t, uint32_t, const string& data) { const auto& cmd = check_size_t(data); @@ -4129,7 +4149,7 @@ static on_command_t handlers[0x100][6] = { /* 96 */ {nullptr, on_96, on_96, on_96, on_96, nullptr}, /* 97 */ {nullptr, nullptr, nullptr, nullptr, nullptr, nullptr}, /* 98 */ {nullptr, on_61_98, on_61_98, on_61_98, on_61_98, on_61_98}, - /* 99 */ {nullptr, on_ignored, on_ignored, on_ignored, on_ignored, on_ignored}, + /* 99 */ {nullptr, on_ignored, on_ignored, on_99_GC, on_ignored, on_ignored}, /* 9A */ {nullptr, on_9A, on_9A, on_9A, nullptr, nullptr}, /* 9B */ {nullptr, nullptr, nullptr, nullptr, nullptr, nullptr}, /* 9C */ {nullptr, on_9C, on_9C, on_9C, on_9C, nullptr}, diff --git a/src/SendCommands.cc b/src/SendCommands.cc index 226121d9..d6e51100 100644 --- a/src/SendCommands.cc +++ b/src/SendCommands.cc @@ -2645,38 +2645,64 @@ void send_ep3_tournament_match_result(shared_ptr l, uint32_t meseta_rewar } } -void send_ep3_update_spectator_count(shared_ptr l) { - G_SetGameMetadata_GC_Ep3_6xB4x52 cmd; +void send_ep3_update_game_metadata(shared_ptr l) { + size_t total_spectators = 0; for (auto watcher_l : l->watcher_lobbies) { for (auto c : watcher_l->clients) { - cmd.total_spectators += (c.get() != nullptr); + total_spectators += (c.get() != nullptr); } } - // TODO: Make s available here so we can apply masking if needed (perhaps by - // adding a weak_ptr in Lobby... it'd be dumb to require s to be passed in to - // this function just to check a behavior flag) + auto s = l->require_server_state(); - // Note: We can't use send_command_t(l, ...) here because that would send the - // same command to l and to all watcher lobbies. The commands should have - // different values depending on who's in each watcher lobby, so we have to - // manually send to each client here. - for (auto c : l->clients) { - if (c) { - send_command_t(c, 0xC9, 0x00, cmd); + { + G_SetGameMetadata_GC_Ep3_6xB4x52 cmd; + cmd.total_spectators = total_spectators; + if (!(s->ep3_behavior_flags & Episode3::BehaviorFlag::DISABLE_MASKING)) { + uint8_t mask_key = (random_object() % 0xFF) + 1; + set_mask_for_ep3_game_command(&cmd, sizeof(cmd), mask_key); } - } - for (auto watcher_l : l->watcher_lobbies) { - cmd.local_spectators = 0; - for (auto c : watcher_l->clients) { - cmd.local_spectators += (c.get() != nullptr); - } - for (auto c : watcher_l->clients) { + // Note: We can't use send_command_t(l, ...) here because that would send + // the same command to l and to all watcher lobbies. The commands should + // have different values depending on who's in each watcher lobby, so we + // have to manually send to each client here. + for (auto c : l->clients) { if (c) { send_command_t(c, 0xC9, 0x00, cmd); } } } + if (!l->watcher_lobbies.empty()) { + string text; + auto tourn = l->tournament_match ? l->tournament_match->tournament.lock() : 0; + if (l->tournament_match && tourn) { + if (tourn->get_final_match() == l->tournament_match) { + text = string_printf("Viewing final match of tournament %s", tourn->get_name().c_str()); + } else { + text = string_printf( + "Viewing match in round %zu of tournament %s", + l->tournament_match->round_num, tourn->get_name().c_str()); + } + } else { + text = "Viewing battle in game " + encode_sjis(l->name); + } + add_color_inplace(text); + for (auto watcher_l : l->watcher_lobbies) { + G_SetGameMetadata_GC_Ep3_6xB4x52 cmd; + cmd.local_spectators = 0; + for (auto c : watcher_l->clients) { + cmd.local_spectators += (c.get() != nullptr); + } + cmd.total_spectators = total_spectators; + cmd.text_size = text.size(); + cmd.text = text; + if (!(s->ep3_behavior_flags & Episode3::BehaviorFlag::DISABLE_MASKING)) { + uint8_t mask_key = (random_object() % 0xFF) + 1; + set_mask_for_ep3_game_command(&cmd, sizeof(cmd), mask_key); + } + send_command_t(watcher_l, 0xC9, 0x00, cmd); + } + } } void set_mask_for_ep3_game_command(void* vdata, size_t size, uint8_t mask_key) { diff --git a/src/SendCommands.hh b/src/SendCommands.hh index 89627a23..9fffb03e 100644 --- a/src/SendCommands.hh +++ b/src/SendCommands.hh @@ -338,7 +338,7 @@ void send_ep3_tournament_details( std::shared_ptr t); void send_ep3_game_details( std::shared_ptr c, std::shared_ptr l); -void send_ep3_update_spectator_count(std::shared_ptr l); +void send_ep3_update_game_metadata(std::shared_ptr l); void send_ep3_card_auction(std::shared_ptr l); void send_ep3_disband_watcher_lobbies(std::shared_ptr primary_l); diff --git a/src/Text.hh b/src/Text.hh index 8b859741..873e513e 100644 --- a/src/Text.hh +++ b/src/Text.hh @@ -613,6 +613,12 @@ size_t add_color_inplace(T* a, size_t max_chars) { return d - orig_d; } +template +void add_color_inplace(std::basic_string& s) { + size_t new_size = add_color_inplace(s.data(), s.size()); + s.resize(new_size); +} + template void add_color(StringWriter& w, const T* src, size_t max_input_chars) { for (size_t x = 0; (x < max_input_chars) && *src; x++) { diff --git a/tests/GC-Episode3BattleWithSpectator.test.txt b/tests/GC-Episode3BattleWithSpectator.test.txt index 19c3aa91..b2c7fb6f 100644 --- a/tests/GC-Episode3BattleWithSpectator.test.txt +++ b/tests/GC-Episode3BattleWithSpectator.test.txt @@ -9466,9 +9466,9 @@ I 17097 2023-09-19 21:54:07 - [Commands] Sending to C-2 (Tali) (version=GC comma 0110 | 00 00 00 00 | I 17097 2023-09-19 21:54:07 - [Commands] Sending to C-4 (Tali) (version=GC command=C9 flag=00) 0000 | C9 00 14 01 B4 44 00 00 52 00 00 00 01 00 01 00 | D R -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 | +0010 | 00 00 1D 00 56 69 65 77 69 6E 67 20 62 61 74 74 | Viewing batt +0020 | 6C 65 20 69 6E 20 67 61 6D 65 20 09 45 31 31 31 | le in game E111 +0030 | 31 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | 1 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 | @@ -10356,44 +10356,6 @@ I 17097 2023-09-19 21:54:08 - [Commands] Received from C-4 (Tali) (version=GC co I 17097 2023-09-19 21:54:08 - [Commands] Sending to C-4 (Tali) (version=GC command=B1 flag=00) 0000 | B1 00 1C 00 32 30 32 33 3A 30 39 3A 32 30 3A 20 | 2023:09:20: 0010 | 30 34 3A 35 34 3A 30 38 2E 30 30 30 | 04:54:08.000 -I 17097 2023-09-19 21:54:08 - [Commands] Sending to C-2 (Tali) (version=GC command=C9 flag=00) -0000 | C9 00 14 01 B4 44 00 00 52 00 00 00 00 00 01 00 | D R -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 | -I 17097 2023-09-19 21:54:08 - [Commands] Sending to C-4 (Tali) (version=GC command=C9 flag=00) -0000 | C9 00 14 01 B4 44 00 00 52 00 00 00 01 00 01 00 | D R -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 | I 17097 2023-09-19 21:54:08 - [Commands] Sending to C-4 (Tali) (version=GC command=6C flag=00) 0000 | 6C 00 1C 04 B6 00 00 00 18 04 00 00 41 00 00 00 | l A 0010 | F9 01 00 00 03 04 00 00 07 00 00 01 FD F8 FC F9 | @@ -10463,6 +10425,44 @@ I 17097 2023-09-19 21:54:08 - [Commands] Sending to C-4 (Tali) (version=GC comma 0410 | 7C E4 0C FF F4 05 00 FE 3B 00 00 00 | | ; I 17097 2023-09-19 21:54:08 - [Commands] Received from C-4 (Tali) (version=GC command=99 flag=00) 0000 | 99 00 04 00 | +I 17097 2023-09-19 21:54:57 - [Commands] Sending to C-2 (Tali) (version=GC command=C9 flag=00) +0000 | C9 00 14 01 B4 44 00 00 52 00 00 00 00 00 01 00 | D R +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 | +I 17097 2023-09-19 21:54:57 - [Commands] Sending to C-4 (Tali) (version=GC command=C9 flag=00) +0000 | C9 00 14 01 B4 44 00 00 52 00 00 00 01 00 01 00 | D R +0010 | 00 00 1D 00 56 69 65 77 69 6E 67 20 62 61 74 74 | Viewing batt +0020 | 6C 65 20 69 6E 20 67 61 6D 65 20 09 45 31 31 31 | le in game E111 +0030 | 31 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | 1 +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 | I 17097 2023-09-19 21:54:10 - [Commands] Received from C-2 (Tali) (version=GC command=C9 flag=00) 0000 | C9 00 18 00 B5 05 00 00 32 00 00 00 01 00 FF FF | 2 0010 | 00 01 02 00 01 E6 DE 50 | P @@ -10660,6 +10660,44 @@ I 17097 2023-09-19 21:54:57 - [Commands] Received from C-2 (Tali) (version=GC co 0290 | FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF | 02A0 | FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF | 02B0 | FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF | +I 17097 2023-09-19 21:54:57 - [Commands] Sending to C-2 (Tali) (version=GC command=C9 flag=00) +0000 | C9 00 14 01 B4 44 00 00 52 00 00 00 00 00 01 00 | D R +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 | +I 17097 2023-09-19 21:54:57 - [Commands] Sending to C-4 (Tali) (version=GC command=C9 flag=00) +0000 | C9 00 14 01 B4 44 00 00 52 00 00 00 01 00 01 00 | D R +0010 | 00 00 1D 00 56 69 65 77 69 6E 67 20 62 61 74 74 | Viewing batt +0020 | 6C 65 20 69 6E 20 67 61 6D 65 20 09 45 31 31 31 | le in game E111 +0030 | 31 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | 1 +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 | I 17097 2023-09-19 21:54:57 - [Commands] Sending to C-2 (Tali) (version=GC command=B0 flag=00) 0000 | B0 00 24 00 00 00 00 00 00 00 00 00 09 43 35 2A | $ C5* 0010 | 2F 43 41 78 31 33 20 55 50 44 41 54 45 20 4D 41 | /CAx13 UPDATE MA