send tournament bracket updates when any match is complete

This commit is contained in:
Martin Michelsen
2022-12-12 21:54:53 -08:00
parent e858b2101d
commit 391a70f68d
5 changed files with 67 additions and 31 deletions
+11 -7
View File
@@ -2103,15 +2103,18 @@ struct C_SetBlockedSenders_BB_C6 : C_SetBlockedSenders_C6<28> { } __packed__;
struct S_ConfirmTournamentEntry_GC_Ep3_CC {
ptext<char, 0x40> tournament_name;
parray<le_uint16_t, 4> 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<char, 0x20> server_name;
ptext<char, 0x20> 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<char, 0x20> team_name;
struct TeamEntry {
le_uint16_t win_count = 0;
le_uint16_t is_active = 0;
ptext<char, 0x20> name;
} __packed__;
parray<Entry, 0x20> entries;
parray<TeamEntry, 0x20> team_entries;
} __packed__;
// CD: Invalid command
@@ -2365,7 +2368,8 @@ struct S_TournamentList_GC_Ep3_E0 {
ptext<char, 0x20> name;
le_uint16_t num_teams = 0;
le_uint16_t max_teams = 0;
parray<le_uint16_t, 2> unknown_a3;
le_uint16_t unknown_a3 = 0;
le_uint16_t unknown_a4 = 0;
} __packed__;
parray<Entry, 0x20> entries;
} __packed__;
+4
View File
@@ -515,6 +515,10 @@ shared_ptr<Tournament::Team> Tournament::team_for_serial_number(
throw logic_error("serial number registered in tournament but not in any team");
}
const set<uint32_t>& 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");
+1
View File
@@ -107,6 +107,7 @@ public:
std::shared_ptr<Match> next_match_for_team(std::shared_ptr<Team> team) const;
std::shared_ptr<Match> get_final_match() const;
std::shared_ptr<Team> team_for_serial_number(uint32_t serial_number) const;
const std::set<uint32_t>& get_all_player_serial_numbers() const;
void start();
+46 -21
View File
@@ -215,8 +215,15 @@ void on_connect(std::shared_ptr<ServerState> s, std::shared_ptr<Client> c) {
void on_login_complete(shared_ptr<ServerState> s, shared_ptr<Client> 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<ServerState> s, shared_ptr<Client> c
}
}
static void on_tournament_bracket_updated(
shared_ptr<ServerState> s, shared_ptr<const Episode3::Tournament> 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<ServerState> s, shared_ptr<Client> 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<ServerState> s, shared_ptr<Cli
}
send_ep3_tournament_match_result(l, l->tournament_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<ServerState> s, shared_ptr<const Episode3::Tournament> 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<ServerState> s, shared_ptr<Client> c,
uint16_t, uint32_t flag, const string&) { // E2
switch (flag) {
@@ -1164,9 +1191,7 @@ static void on_ep3_tournament_control(shared_ptr<ServerState> s, shared_ptr<Clie
if (tourn) {
if (tourn->get_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();
}
+5 -3
View File
@@ -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<size_t>(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);