From 3c1c63f24e21d6807111c4d39f59abf826b57adc Mon Sep 17 00:00:00 2001 From: Martin Michelsen Date: Sun, 17 Sep 2023 12:36:05 -0700 Subject: [PATCH] make spectator joining more robust --- src/Episode3/PlayerState.cc | 24 +++++++++++++++--------- src/Episode3/PlayerState.hh | 2 ++ src/Episode3/Server.cc | 29 ++++++++++++++++++++++++----- src/Episode3/Server.hh | 1 + 4 files changed, 42 insertions(+), 14 deletions(-) diff --git a/src/Episode3/PlayerState.cc b/src/Episode3/PlayerState.cc index 5b77284f..c83acd1d 100644 --- a/src/Episode3/PlayerState.cc +++ b/src/Episode3/PlayerState.cc @@ -1451,10 +1451,7 @@ void PlayerState::subtract_atk_points(uint8_t cost) { this->atk_points2 = min(this->atk_points, this->atk_points2_max); } -void PlayerState::update_hand_and_equip_state_and_send_6xB4x02_if_needed( - bool always_send) { - auto s = this->server(); - +G_UpdateHand_GC_Ep3_6xB4x02 PlayerState::prepare_6xB4x02() const { G_UpdateHand_GC_Ep3_6xB4x02 cmd; cmd.client_id = this->client_id; cmd.state.dice_results = this->dice_results; @@ -1463,7 +1460,7 @@ void PlayerState::update_hand_and_equip_state_and_send_6xB4x02_if_needed( cmd.state.atk_points2 = this->atk_points2; cmd.state.unknown_a1 = this->unknown_a14; cmd.state.total_set_cards_cost = this->total_set_cards_cost; - cmd.state.is_cpu_player = s->presence_entries[this->client_id].is_cpu_player; + cmd.state.is_cpu_player = this->server()->presence_entries[this->client_id].is_cpu_player; cmd.state.assist_flags = this->assist_flags; for (size_t z = 0; z < 6; z++) { cmd.state.hand_card_refs[z] = this->card_refs[z]; @@ -1484,9 +1481,15 @@ void PlayerState::update_hand_and_equip_state_and_send_6xB4x02_if_needed( cmd.state.assist_delay_turns = this->assist_delay_turns; cmd.state.atk_bonuses = this->atk_bonuses; cmd.state.def_bonuses = this->def_bonuses; + return cmd; +} + +void PlayerState::update_hand_and_equip_state_and_send_6xB4x02_if_needed( + bool always_send) { + auto cmd = this->prepare_6xB4x02(); if (always_send || memcmp(&this->hand_and_equip, &cmd.state, sizeof(this->hand_and_equip))) { *this->hand_and_equip = cmd.state; - s->send(cmd); + this->server()->send(cmd); } this->send_6xB4x04_if_needed(always_send); } @@ -1512,9 +1515,7 @@ void PlayerState::set_random_assist_card_from_hand_for_free() { } } -void PlayerState::send_6xB4x04_if_needed(bool always_send) { - auto s = this->server(); - +G_UpdateShortStatuses_GC_Ep3_6xB4x04 PlayerState::prepare_6xB4x04() const { G_UpdateShortStatuses_GC_Ep3_6xB4x04 cmd; cmd.client_id = this->client_id; // Note: The original code calls memset to clear all the short status structs @@ -1550,8 +1551,13 @@ void PlayerState::send_6xB4x04_if_needed(bool always_send) { } cmd.card_statuses[15].card_ref = this->card_refs[6]; + return cmd; +} +void PlayerState::send_6xB4x04_if_needed(bool always_send) { + auto cmd = this->prepare_6xB4x04(); if (always_send || (cmd.card_statuses != *this->card_short_statuses)) { + auto s = this->server(); *this->card_short_statuses = cmd.card_statuses; if (!s->get_should_copy_prev_states_to_current_states()) { s->send(cmd); diff --git a/src/Episode3/PlayerState.hh b/src/Episode3/PlayerState.hh index 24a335af..178ba9c3 100644 --- a/src/Episode3/PlayerState.hh +++ b/src/Episode3/PlayerState.hh @@ -122,9 +122,11 @@ public: bool subtract_or_check_atk_or_def_points_for_action( const ActionState& pa, bool deduct_points); void subtract_atk_points(uint8_t cost); + G_UpdateHand_GC_Ep3_6xB4x02 prepare_6xB4x02() const; void update_hand_and_equip_state_and_send_6xB4x02_if_needed( bool always_send = false); void set_random_assist_card_from_hand_for_free(); + G_UpdateShortStatuses_GC_Ep3_6xB4x04 prepare_6xB4x04() const; void send_6xB4x04_if_needed(bool always_send = false); std::vector get_card_refs_within_range_from_all_players( const parray& range, diff --git a/src/Episode3/Server.cc b/src/Episode3/Server.cc index 62be061c..85370d23 100644 --- a/src/Episode3/Server.cc +++ b/src/Episode3/Server.cc @@ -271,18 +271,33 @@ void Server::send_commands_for_joining_spectator(Channel& c, bool is_trial) cons } if (should_send_state) { - c.send(0xC9, 0x00, this->prepare_6xB4x07_decks_update()); - c.send(0xC9, 0x00, this->prepare_6xB4x1C_names_update()); + c.send(0xC9, 0x00, this->prepare_6xB4x03()); + for (uint8_t client_id = 0; client_id < 4; client_id++) { + auto ps = this->player_states[client_id]; + if (ps) { + c.send(0xC9, 0x00, ps->prepare_6xB4x02()); + c.send(0xC9, 0x00, ps->prepare_6xB4x04()); + } + } { G_UpdateMap_GC_Ep3_6xB4x05 cmd_05; cmd_05.state = *this->map_and_rules; this->send(cmd_05); } + // TODO: Sega does something like this; do we have to do this too? + // for (uint8_t client_id = 0; client_id < 4; client_id++) { + // (send 6xB4x4E, 6xB4x4C, 6xB4x4D for each set card) + // (send 6xB4x4F for client_id) + // } + c.send(0xC9, 0x00, this->prepare_6xB4x07_decks_update()); + // TODO: Sega sends 6xB4x05 here again; why? Is that necessary? They also + // send 6xB4x02 again for each player after that (but not 6xB4x04) + c.send(0xC9, 0x00, this->prepare_6xB4x1C_names_update()); + c.send(0xC9, 0x00, this->prepare_6xB4x50_trap_tile_locations()); { G_LoadCurrentEnvironment_GC_Ep3_6xB4x05 cmd_3B; c.send(0xC9, 0x00, &cmd_3B, sizeof(cmd_3B)); } - c.send(0xC9, 0x00, this->prepare_6xB4x50_trap_tile_locations()); } } @@ -1503,8 +1518,7 @@ void Server::setup_and_start_battle() { this->send_6xB4x46(); } -void Server::update_battle_state_flags_and_send_6xB4x03_if_needed( - bool always_send) { +G_SetStateFlags_GC_Ep3_6xB4x03 Server::prepare_6xB4x03() const { G_SetStateFlags_GC_Ep3_6xB4x03 cmd; cmd.state.turn_num = this->round_num; cmd.state.battle_phase = this->battle_phase; @@ -1527,6 +1541,11 @@ void Server::update_battle_state_flags_and_send_6xB4x03_if_needed( cmd.state.client_sc_card_types[z] = ps->get_sc_card_type(); } } + return cmd; +} + +void Server::update_battle_state_flags_and_send_6xB4x03_if_needed(bool always_send) { + G_SetStateFlags_GC_Ep3_6xB4x03 cmd = this->prepare_6xB4x03(); if (always_send || (*this->state_flags != cmd.state)) { *this->state_flags = cmd.state; this->send(cmd); diff --git a/src/Episode3/Server.hh b/src/Episode3/Server.hh index ea063323..80ba6981 100644 --- a/src/Episode3/Server.hh +++ b/src/Episode3/Server.hh @@ -166,6 +166,7 @@ public: void move_phase_before(); void set_player_deck_valid(uint8_t client_id); void setup_and_start_battle(); + G_SetStateFlags_GC_Ep3_6xB4x03 prepare_6xB4x03() const; void update_battle_state_flags_and_send_6xB4x03_if_needed( bool always_send = false); bool update_registration_phase();