[Server] Replay tournament state to late joiners

The bracket, phase and standings live in Event_TournamentState, which only
flows on mutation. Without a copy a player or spectator joining after round
one would sit on an empty bracket until the next advance, so the current
state is now enqueued as part of the join snapshot.

Extracts Event_TournamentState building into buildStateEvent() so both the
broadcast path and the join path share one source of truth.
This commit is contained in:
Lukas Brübach 2026-09-02 09:49:53 +02:00 committed by GitHub
parent 99a409de09
commit 80703adbbb
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 18 additions and 2 deletions

View file

@ -812,6 +812,15 @@ void Server_Game::createGameJoinedEvent(Server_AbstractParticipant *joiningParti
}
rc.enqueuePostResponseItem(ServerMessage::GAME_EVENT_CONTAINER, prepareGameEvent(event2, -1));
// A tournament's bracket/phase/standings live in Event_TournamentState, which
// normally only flows on mutation. Without a copy here a late joiner would sit
// on an empty bracket until the next round advances, so replay the current
// state as part of the join snapshot.
if (tournament) {
rc.enqueuePostResponseItem(ServerMessage::GAME_EVENT_CONTAINER,
prepareGameEvent(tournament->buildStateEvent(), -1));
}
}
void Server_Game::sendGameEventContainer(GameEventContainer *cont,

View file

@ -635,7 +635,7 @@ void Server_Tournament::checkAndAdvanceRound(GameEventStorage &ges)
}
}
void Server_Tournament::broadcastTournamentState(GameEventStorage &ges)
Event_TournamentState Server_Tournament::buildStateEvent() const
{
QMutexLocker locker(&tournamentMutex);
@ -682,5 +682,10 @@ void Server_Tournament::broadcastTournamentState(GameEventStorage &ges)
p->set_player2_match_wins(pairing.player2MatchWins);
}
ges.enqueueGameEvent(state, -1);
return state;
}
void Server_Tournament::broadcastTournamentState(GameEventStorage &ges)
{
ges.enqueueGameEvent(buildStateEvent(), -1);
}

View file

@ -36,6 +36,8 @@ public:
void recordMatchResult(int playerId1, int playerId2, int winnerId, GameEventStorage &ges);
bool recordMatchResultByGameId(int gameId, int winnerId, GameEventStorage &ges);
void broadcastTournamentState(GameEventStorage &ges);
// Current tournament state message, for replaying to a participant joining late.
Event_TournamentState buildStateEvent() const;
bool isStarted() const
{