The game logic now lives in libcockatrice_game, so the tab's relative
includes into cockatrice/src/game no longer resolve. Include the library
headers instead and pull in the complete types the tab dereferences.
The standalone hint label sat in the form layout's field column with an
empty label cell, which misaligned it against the row above. Per review,
drop the label and carry its text in the spinbox tooltip instead.
- Drop the in-game tournament-settings button: Command_TournamentSettingsSelect
has no server handler (RespContextError), the host-ness decision was evaluated
once at tab construction, and the button never received a label on first show.
The dialog can be re-added together with a working Server_Player override.
- Pass PlayerManager::isSpectator() to TournamentWidget instead of relying on
localPlayerId == -1, which never holds for spectators.
- Report games per match as the total series length (Best of %1) to match the
DlgTournamentSettings hint and the server's use of the value; the previous
gamesPerMatch * 2 - 1 mislabeled Bo3 as Best of 5.
- Block signals around read-only tournamentCheckBox setChecked so the disabled
settings button is not re-enabled, and seed Command_CreateGame through
mutable_tournament_settings() (field 15 became the settings message).
- return after closing a sub-game that routed to its parent tab.
Wires the tournament protocol into the client:
- DlgCreateGame gains a tournament checkbox with a games-per-match
settings sub-dialog; both values are sent with Command_CreateGame and
mirrored in the join-info variant of the dialog
- TournamentWidget renders live standings (with deck-submission state)
and pairings for the local player's perspective, and asks to open the
current match game via openMatchGameRequested()
- TournamentTabGameExtension attaches an overview page to TabGame's
stacked views, mirrors phase and submission progress onto a deck-view
status strip, and provides round-trip navigation between game view and
standings; hosts get an in-game settings dialog during deck building
- Open-match falls back to joining as spectator through TabSupervisor;
sub-games now return to their parent tab on close, falling back to
the normal leave-game flow when the parent is gone
The second PlayerLogic constructor taking a custom PlayerEventHandler was UB
(converting this to PlayerLogic* in the base initializer, and connecting a
freshly-built handler against a not-yet-constructed object), and its abstract
extension surface — virtual initializeZones, virtual getPlayerEventHandler,
virtual processGameEvent, protected player member — has no subclass consumer in
the stack. Revert to the single primary constructor.
Also:
- Drop the unused GameMetaInfo::setIsTournament setter. Tournament status is
authoritative from Event_GameJoined's ServerInfo_Game; the redundant
is_tournament field on Event_GameStateChanged is removed in [Protocol].
- Gate the parent-game routing on has_parent_game_id() instead of comparing the
proto default, so a future drop of the default keeps working.
Wires the client game layer for tournament state without touching
existing behavior:
- GameEventHandler dispatches Event_TournamentState (2027) to a new
tournamentStateChanged signal
- GameMetaInfo exposes isTournament and parentGameId over the new
ServerInfo_Game field
- PlayerEventHandler::processGameEvent is virtual and player is
protected; PlayerLogic gains a protected constructor accepting a
custom handler, so mode-specific subclasses can intercept events
Gate the host-only start on the hub object so match sub-games can
start, advance the round when a drop decides the last pairing (and on
late results), settle disconnected pairings instead of stalling, and
decide exhausted series by game wins.
Forward-declare GameConfig as struct to match its definition in
game_config.h; the class/struct mismatch trips -Werror
-Wmismatched-tags on macOS.
Also add the missing /// Server: annotations on the tournament
GameCommandType entries now that the Server_AbstractParticipant
handlers they point at exist in the tree.
The client learns tournament status from Event_GameJoined's ServerInfo_Game;
mirroring it on every Event_GameStateChanged was dead wire data. The field was
removed from the proto in [Protocol]; drop the now-invalidated setter.
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.
- read games per match from Command_CreateGame.tournament_settings after the
proto rework replaced the standalone games_per_match field
- use qWarning to match the surrounding file
- link match sub-games to the hub through QPointer so a finished match can
never dereference a torn-down parent game
- a player who leaves the hub is dropped: no longer paired, current
undecided match awarded to the opponent, absent from the bracket
- refuse to spawn a match game when either participant is disconnected, and
set disconnectRemovesPlayer on match games so a mid-match disconnect ends
it instead of leaving a half-present participant
- match winner is a strict majority (gamesPerMatch/2+1); an exhausted
series with no majority is recorded as a draw so the round always advances
- match games are started without force-start: a missing deck no longer
kicks the player; the game stays open for deck selection
- buyes are handed to every leftover player, worst-ranked first, at most one
per player over the tournament
- tournament hubs cannot start on mere 'everyone ready': host force-start is
required and fewer than two players never starts
- sub-game creator copies the real player user info instead of fabricating
IsAdmin
Adds the server-side tournament mode driven through the strategy and
factory interfaces from #7132:
- Server_Tournament runs greedy Swiss pairing with rematch avoidance,
byes, ceil(log2(n)) rounds, and best-of-N series via gamesPerMatch;
match sub-games are spawned through the parent game's
Server_MatchGameFactory implementation with players auto-joined and
their submitted decks installed
- Tournament lifecycle strategy gates the hub game start until all
decks are submitted; match result strategy reports sub-game outcomes
back to the parent tournament
- Server_Game gains tournament state (isTournament flag, settings,
parent link), protocol fields in getInfo/game state events, a
full-lobby bypass for tournament hubs, and disconnectRemovesPlayer
plumbing for upcoming draft modes
- Match-game creation is deferred to the owning thread's event loop so
room registration never nests lock orders; shared state is guarded by
the tournament mutex