From 391a70f68d17d5f2a64e3dce4843c92d99743e46 Mon Sep 17 00:00:00 2001 From: Martin Michelsen Date: Mon, 12 Dec 2022 21:54:53 -0800 Subject: [PATCH] send tournament bracket updates when any match is complete --- src/CommandFormats.hh | 18 ++++++---- src/Episode3/Tournament.cc | 4 +++ src/Episode3/Tournament.hh | 1 + src/ReceiveCommands.cc | 67 ++++++++++++++++++++++++++------------ src/SendCommands.cc | 8 +++-- 5 files changed, 67 insertions(+), 31 deletions(-) diff --git a/src/CommandFormats.hh b/src/CommandFormats.hh index 19094e1a..fb2862cd 100644 --- a/src/CommandFormats.hh +++ b/src/CommandFormats.hh @@ -2103,15 +2103,18 @@ struct C_SetBlockedSenders_BB_C6 : C_SetBlockedSenders_C6<28> { } __packed__; struct S_ConfirmTournamentEntry_GC_Ep3_CC { ptext tournament_name; - parray unknown_a2; + le_uint16_t num_teams = 0; + le_uint16_t unknown_a1 = 0; + le_uint16_t unknown_a2 = 0; + le_uint16_t unknown_a3 = 0; ptext server_name; ptext start_time; // e.g. "15:09:30" or "13:03 PST" - struct Entry { - le_uint16_t unknown_a1 = 0; - le_uint16_t present = 0; // 1 if team present, 0 otherwise - ptext team_name; + struct TeamEntry { + le_uint16_t win_count = 0; + le_uint16_t is_active = 0; + ptext name; } __packed__; - parray entries; + parray team_entries; } __packed__; // CD: Invalid command @@ -2365,7 +2368,8 @@ struct S_TournamentList_GC_Ep3_E0 { ptext name; le_uint16_t num_teams = 0; le_uint16_t max_teams = 0; - parray unknown_a3; + le_uint16_t unknown_a3 = 0; + le_uint16_t unknown_a4 = 0; } __packed__; parray entries; } __packed__; diff --git a/src/Episode3/Tournament.cc b/src/Episode3/Tournament.cc index 11e18d90..d6753b6a 100644 --- a/src/Episode3/Tournament.cc +++ b/src/Episode3/Tournament.cc @@ -515,6 +515,10 @@ shared_ptr Tournament::team_for_serial_number( throw logic_error("serial number registered in tournament but not in any team"); } +const set& Tournament::get_all_player_serial_numbers() const { + return this->all_player_serial_numbers; +} + void Tournament::start() { if (this->current_state != State::REGISTRATION) { throw runtime_error("tournament has already started"); diff --git a/src/Episode3/Tournament.hh b/src/Episode3/Tournament.hh index 981c0102..ed0671fe 100644 --- a/src/Episode3/Tournament.hh +++ b/src/Episode3/Tournament.hh @@ -107,6 +107,7 @@ public: std::shared_ptr next_match_for_team(std::shared_ptr team) const; std::shared_ptr get_final_match() const; std::shared_ptr team_for_serial_number(uint32_t serial_number) const; + const std::set& get_all_player_serial_numbers() const; void start(); diff --git a/src/ReceiveCommands.cc b/src/ReceiveCommands.cc index f6fda4b9..a1c0010c 100644 --- a/src/ReceiveCommands.cc +++ b/src/ReceiveCommands.cc @@ -215,8 +215,15 @@ void on_connect(std::shared_ptr s, std::shared_ptr c) { void on_login_complete(shared_ptr s, shared_ptr c) { if (c->flags & Client::Flag::IS_EPISODE_3) { - c->ep3_tournament_team = s->ep3_tournament_index->team_for_serial_number( + auto team = s->ep3_tournament_index->team_for_serial_number( c->license->serial_number); + if (team) { + auto tourn = team->tournament.lock(); + if (tourn) { + c->ep3_tournament_team = team; + send_ep3_confirm_tournament_entry(s, c, tourn); + } + } } // On the BB data server, this function is called only on the last connection @@ -1042,6 +1049,42 @@ static void on_ep3_counter_state(shared_ptr s, shared_ptr c } } +static void on_tournament_bracket_updated( + shared_ptr s, shared_ptr tourn) { + const auto& serial_numbers = tourn->get_all_player_serial_numbers(); + + for (const auto& l : s->all_lobbies()) { + for (const auto& c : l->clients) { + if (!c) { + continue; + } + if (!c->license || !serial_numbers.count(c->license->serial_number)) { + continue; + } + if (c->ep3_tournament_team.expired()) { + continue; + } + send_ep3_confirm_tournament_entry(s, c, tourn); + } + } + + if (tourn && (tourn->get_state() == Episode3::Tournament::State::COMPLETE)) { + s->ep3_tournament_index->delete_tournament(tourn->get_number()); + } + + if (tourn->get_state() == Episode3::Tournament::State::COMPLETE) { + auto team = tourn->get_winner_team(); + if (team->player_serial_numbers.empty()) { + send_ep3_text_message_printf(s, "$C7A CPU team won\nthe tournament\n$C6%s", tourn->get_name().c_str()); + } else { + send_ep3_text_message_printf(s, "$C6%s$C7\nwon the tournament\n$C6%s", team->name.c_str(), tourn->get_name().c_str()); + } + s->ep3_tournament_index->delete_tournament(tourn->get_number()); + } + + s->ep3_tournament_index->save(); +} + static void on_ep3_server_data_request(shared_ptr s, shared_ptr c, uint16_t, uint32_t, const string& data) { // CA auto l = s->find_lobby(c->lobby_id); @@ -1117,26 +1160,10 @@ static void on_ep3_server_data_request(shared_ptr s, shared_ptrtournament_match); - tourn->print_bracket(stderr); - if (tourn && (tourn->get_state() == Episode3::Tournament::State::COMPLETE)) { - s->ep3_tournament_index->delete_tournament(tourn->get_number()); - } - s->ep3_tournament_index->save(); + on_tournament_bracket_updated(s, tourn); } } -static void on_tournament_complete( - shared_ptr s, shared_ptr tourn) { - auto team = tourn->get_winner_team(); - if (team->player_serial_numbers.empty()) { - send_ep3_text_message_printf(s, "$C7A CPU team won\nthe tournament\n$C6%s", tourn->get_name().c_str()); - } else { - send_ep3_text_message_printf(s, "$C6%s$C7\nwon the tournament\n$C6%s", team->name.c_str(), tourn->get_name().c_str()); - } - s->ep3_tournament_index->delete_tournament(tourn->get_number()); - s->ep3_tournament_index->save(); -} - static void on_ep3_tournament_control(shared_ptr s, shared_ptr c, uint16_t, uint32_t flag, const string&) { // E2 switch (flag) { @@ -1164,9 +1191,7 @@ static void on_ep3_tournament_control(shared_ptr s, shared_ptrget_state() != Episode3::Tournament::State::COMPLETE) { team->unregister_player(c->license->serial_number); - if (tourn->get_state() == Episode3::Tournament::State::COMPLETE) { - on_tournament_complete(s, tourn); - } + on_tournament_bracket_updated(s, tourn); } c->ep3_tournament_team.reset(); } diff --git a/src/SendCommands.cc b/src/SendCommands.cc index 683ec862..0f0528f2 100644 --- a/src/SendCommands.cc +++ b/src/SendCommands.cc @@ -1953,8 +1953,9 @@ void send_ep3_confirm_tournament_entry( cmd.start_time = "Unknown"; auto& teams = tourn->all_teams(); for (size_t z = 0; z < min(teams.size(), 0x20); z++) { - cmd.entries[z].present = 1; - cmd.entries[z].team_name = teams[z]->name; + cmd.team_entries[z].win_count = teams[z]->num_rounds_cleared; + cmd.team_entries[z].is_active = teams[z]->is_active; + cmd.team_entries[z].name = teams[z]->name; } } send_command_t(c, 0xCC, tourn ? 0x01 : 0x00, cmd); @@ -1992,7 +1993,8 @@ void send_ep3_tournament_list( } } entry.max_teams = teams.size(); - entry.unknown_a3.clear(0xFFFF); + entry.unknown_a3 = 0xFFFF; + entry.unknown_a4 = 0xFFFF; z++; } send_command_t(c, 0xE0, z, cmd);