This commit is contained in:
Lukas Brübach 2026-07-01 11:51:02 -04:00
parent 88e90c059a
commit 9feb583af7

View file

@ -9,7 +9,7 @@ Flow overview:
Client Client
→ GameCommand → GameCommand
→ Server_Game::handle* → Server command handler (`Server_Player`, `Server_AbstractParticipant`, or `Server_Game`)
→ GameEvent(s) → GameEvent(s)
→ PlayerEventHandler::event* → PlayerEventHandler::event*
@ -20,11 +20,15 @@ Client
**Purpose:** Send a chat message during a game. **Purpose:** Send a chat message during a game.
**Server:** **Server:**
- `Server_Game::handleGameSay` - `Server_AbstractParticipant::cmdGameSay`
- Validates spectator chat permissions
- Applies chat flood protection
- Emits `Event_GameSay` - Emits `Event_GameSay`
- Logs the message to the server database
**Client:** **Client:**
- `PlayerEventHandler::eventGameSay` - `PlayerEventHandler::eventGameSay`
- Adds the chat message to the game log
--- ---
@ -33,14 +37,19 @@ Client
**Purpose:** Shuffle a card zone (usually library). **Purpose:** Shuffle a card zone (usually library).
**Server:** **Server:**
- `Server_Game::handleShuffle` - `Server_Player::cmdShuffle`
- Reorders cards in zone - Only allows shuffling the deck zone
- Rejects if the game has not started or the player has conceded
- Supports partial-range shuffles (`start` / `end`)
- Emits `Event_Shuffle` - Emits `Event_Shuffle`
- Re-reveals the top card if the deck is being tracked
**Client:** **Client:**
- `PlayerEventHandler::eventShuffle` - `PlayerEventHandler::eventShuffle`
- Clears revealed top cards - Closes affected library views
- Closes affected zone views - Clears any revealed top card if necessary
- Updates deck graphics
- Logs the shuffle
--- ---
@ -49,12 +58,12 @@ Client
**Purpose:** Roll one or more dice. **Purpose:** Roll one or more dice.
**Server:** **Server:**
- `Server_Game::handleRollDie` - Computes random die results
- Computes random values
- Emits `Event_RollDie` - Emits `Event_RollDie`
**Client:** **Client:**
- `PlayerEventHandler::eventRollDie` - `PlayerEventHandler::eventRollDie`
- Displays the sorted roll results in the game log
--- ---
@ -63,12 +72,21 @@ Client
**Purpose:** Draw cards from deck. **Purpose:** Draw cards from deck.
**Server:** **Server:**
- `Server_Game::handleDrawCards` - `Server_Player::cmdDrawCards`
- Moves cards from deck → hand - Rejects if the game has not started or the player has conceded
- Moves cards from deck to hand
- Sends full card information privately to the drawing player
- Sends only the draw count to all other players
- Tracks drawn cards for undo
- Updates revealed-top-card state when necessary
- Emits `Event_DrawCards` - Emits `Event_DrawCards`
**Client:** **Client:**
- `PlayerEventHandler::eventDrawCards` - `PlayerEventHandler::eventDrawCards`
- Moves cards from library to hand
- Reveals card identities only when included in the event
- Updates both zones
- Logs the draw
--- ---
@ -77,13 +95,16 @@ Client
**Purpose:** Undo a previous draw. **Purpose:** Undo a previous draw.
**Server:** **Server:**
- `Server_Game::handleUndoDraw` - `Server_Player::cmdUndoDraw`
- Uses `Context_UndoDraw` - Rejects if the game has not started or the player has conceded
- Moves card(s) back to deck - Uses the tracked draw history (`lastDrawList`)
- Moves the most recently drawable card from hand back to the top of the deck
- Emits `Event_GameLogNotice` if undo is no longer possible
**Client:** **Client:**
- Handled via `PlayerEventHandler::eventMoveCard` - Processed as a normal `MOVE_CARD`
- Logged as undo-draw context - Detects `Context_UndoDraw`
- Logs the undo draw instead of a normal move
--- ---
@ -92,12 +113,16 @@ Client
**Purpose:** Flip a card face up or face down. **Purpose:** Flip a card face up or face down.
**Server:** **Server:**
- `Server_Game::handleFlipCard` - Updates the card's face-down state
- Updates card visibility - Reveals identity when turning face up
- Emits `Event_FlipCard` - Emits `Event_FlipCard`
**Client:** **Client:**
- `PlayerEventHandler::eventFlipCard` - `PlayerEventHandler::eventFlipCard`
- Updates the card identity when revealed
- Changes face-up / face-down state
- Updates card menus
- Logs the flip
--- ---
@ -106,12 +131,15 @@ Client
**Purpose:** Attach one card to another. **Purpose:** Attach one card to another.
**Server:** **Server:**
- `Server_Game::handleAttachCard` - Updates attachment relationships
- Updates attachment graph
- Emits `Event_AttachCard` - Emits `Event_AttachCard`
**Client:** **Client:**
- `PlayerEventHandler::eventAttachCard` - `PlayerEventHandler::eventAttachCard`
- Updates parent/child attachment links
- Reorganizes affected zones
- Logs attach or detach operations
- Refreshes card actions
--- ---
@ -120,12 +148,15 @@ Client
**Purpose:** Create a token card. **Purpose:** Create a token card.
**Server:** **Server:**
- `Server_Game::handleCreateToken` - Creates a new token card
- Allocates new card instance
- Emits `Event_CreateToken` - Emits `Event_CreateToken`
**Client:** **Client:**
- `PlayerEventHandler::eventCreateToken` - `PlayerEventHandler::eventCreateToken`
- Creates the token object
- Applies token properties (PT, color, annotation, face-down state)
- Adds it to the requested zone
- Logs token creation
--- ---
@ -134,12 +165,14 @@ Client
**Purpose:** Create a visual arrow. **Purpose:** Create a visual arrow.
**Server:** **Server:**
- `Server_Game::handleCreateArrow` - Creates a visual arrow
- Registers arrow ownership
- Emits `Event_CreateArrow` - Emits `Event_CreateArrow`
**Client:** **Client:**
- `PlayerEventHandler::eventCreateArrow` - `PlayerEventHandler::eventCreateArrow`
- Creates the arrow graphics
- Resolves endpoint card names
- Logs arrow creation
--- ---
@ -148,12 +181,12 @@ Client
**Purpose:** Remove a visual arrow. **Purpose:** Remove a visual arrow.
**Server:** **Server:**
- `Server_Game::handleDeleteArrow` - Removes an existing arrow
- Removes arrow
- Emits `Event_DeleteArrow` - Emits `Event_DeleteArrow`
**Client:** **Client:**
- `PlayerEventHandler::eventDeleteArrow` - `PlayerEventHandler::eventDeleteArrow`
- Removes the arrow graphics
--- ---
@ -162,11 +195,13 @@ Client
**Purpose:** Set a card attribute. **Purpose:** Set a card attribute.
**Server:** **Server:**
- `Server_Game::handleSetCardAttr` - Updates one or more card attributes
- Emits `Event_SetCardAttr` - Emits `Event_SetCardAttr`
**Client:** **Client:**
- `PlayerEventHandler::eventSetCardAttr` - `PlayerEventHandler::eventSetCardAttr`
- Updates tapped state, color, annotation, power/toughness, face-down state, attacking state, and related visuals
- Logs attribute changes where appropriate
--- ---
@ -175,11 +210,14 @@ Client
**Purpose:** Set a card counter. **Purpose:** Set a card counter.
**Server:** **Server:**
- `Server_Game::handleSetCardCounter` - Updates the specified card counter
- Emits `Event_SetCardCounter` - Emits `Event_SetCardCounter`
**Client:** **Client:**
- `PlayerEventHandler::eventSetCardCounter` - `PlayerEventHandler::eventSetCardCounter`
- Updates the displayed counter value
- Refreshes card actions
- Logs the counter change
--- ---
@ -188,12 +226,11 @@ Client
**Purpose:** Increment a card counter. **Purpose:** Increment a card counter.
**Server:** **Server:**
- `Server_Game::handleIncCardCounter` - Normalizes to a set-counter operation
- Normalized to set-counter
- Emits `Event_SetCardCounter` - Emits `Event_SetCardCounter`
**Client:** **Client:**
- `PlayerEventHandler::eventSetCardCounter` - Processed identically to `SET_CARD_COUNTER`
--- ---
@ -202,11 +239,11 @@ Client
**Purpose:** Mark player as ready. **Purpose:** Mark player as ready.
**Server:** **Server:**
- `Server_Game::handleReadyStart` - Marks the player as ready
- May call `doStartGameIfReady` - Starts the game once all required players are ready
**Client:** **Client:**
- Reflected via `Event_GameStateChanged` - Reflected through updated game state events
--- ---
@ -215,64 +252,79 @@ Client
**Purpose:** Concede the game. **Purpose:** Concede the game.
**Server:** **Server:**
- `Server_Game::handleConcede` - Marks the player as conceded
- Updates player state - Returns borrowed cards where appropriate
- May end game - Ends the game if only one player remains
**Client:** **Client:**
- Reflected via game state events - Reflected through updated game state events
--- ---
### `INC_COUNTER` (1018) ### `INC_COUNTER` (1018)
**Purpose:** Increment a global counter. **Purpose:** Increment a player counter.
**Server:** **Server:**
- `Server_Game::handleIncCounter` - `Server_Player::cmdIncCounter`
- Emits `Event_SetCounter` - Rejects if the game has not started or the player has conceded
- Updates the counter value
- Emits `Event_SetCounter` only if the value changed
**Client:** **Client:**
- `PlayerEventHandler::eventSetCounter` - `PlayerEventHandler::eventSetCounter`
- Updates the displayed player counter
- Logs the change
--- ---
### `CREATE_COUNTER` (1019) ### `CREATE_COUNTER` (1019)
**Purpose:** Create a global counter. **Purpose:** Create a player counter.
**Server:** **Server:**
- `Server_Game::handleCreateCounter` - `Server_Player::cmdCreateCounter`
- Rejects if the game has not started or the player has conceded
- Allocates a new counter ID
- Creates the counter
- Emits `Event_CreateCounter` - Emits `Event_CreateCounter`
**Client:** **Client:**
- `PlayerEventHandler::eventCreateCounter` - `PlayerEventHandler::eventCreateCounter`
- Creates the local player counter
--- ---
### `SET_COUNTER` (1020) ### `SET_COUNTER` (1020)
**Purpose:** Set a global counter value. **Purpose:** Set a player counter value.
**Server:** **Server:**
- `Server_Game::handleSetCounter` - `Server_Player::cmdSetCounter`
- Emits `Event_SetCounter` - Rejects if the game has not started or the player has conceded
- Updates the counter value
- Emits `Event_SetCounter` only if the value changed
**Client:** **Client:**
- `PlayerEventHandler::eventSetCounter` - `PlayerEventHandler::eventSetCounter`
- Updates the counter value
- Logs the change
--- ---
### `DEL_COUNTER` (1021) ### `DEL_COUNTER` (1021)
**Purpose:** Delete a global counter. **Purpose:** Delete a player counter.
**Server:** **Server:**
- `Server_Game::handleDelCounter` - `Server_Player::cmdDelCounter`
- Rejects if the game has not started or the player has conceded
- Deletes the counter
- Emits `Event_DelCounter` - Emits `Event_DelCounter`
**Client:** **Client:**
- `PlayerEventHandler::eventDelCounter` - `PlayerEventHandler::eventDelCounter`
- Removes the counter
--- ---
@ -281,13 +333,13 @@ Client
**Purpose:** Advance to the next turn. **Purpose:** Advance to the next turn.
**Server:** **Server:**
- `Server_Game::handleNextTurn` - `Server_Player::cmdNextTurn`
- Emits: - Rejects if the game has not started
- `Event_SetActivePlayer` - Conceded players cannot advance turns unless acting as a judge
- `Event_SetActivePhase` - Calls `Server_Game::nextTurn()`
**Client:** **Client:**
- Reflected via game state events - Reflected through subsequent active-player and active-phase events
--- ---
@ -296,11 +348,14 @@ Client
**Purpose:** Set active phase. **Purpose:** Set active phase.
**Server:** **Server:**
- `Server_Game::handleSetActivePhase` - `Server_Player::cmdSetActivePhase`
- Emits `Event_SetActivePhase` - Rejects if the game has not started
- Judges may change the phase at any time
- Normal players may only change the phase during their own active turn
- Calls `Server_Game::setActivePhase()`
**Client:** **Client:**
- Reflected via game state events - Reflected through updated phase events
--- ---
@ -309,11 +364,12 @@ Client
**Purpose:** Dump zone contents. **Purpose:** Dump zone contents.
**Server:** **Server:**
- `Server_Game::handleDumpZone` - Generates a zone summary
- Emits `Event_DumpZone` - Emits `Event_DumpZone`
**Client:** **Client:**
- `PlayerEventHandler::eventDumpZone` - `PlayerEventHandler::eventDumpZone`
- Logs the zone contents summary
--- ---
@ -322,11 +378,15 @@ Client
**Purpose:** Reveal specific cards. **Purpose:** Reveal specific cards.
**Server:** **Server:**
- `Server_Game::handleRevealCards` - Reveals cards to one or more players
- Emits `Event_RevealCards` - Emits `Event_RevealCards`
**Client:** **Client:**
- `PlayerEventHandler::eventRevealCards` - `PlayerEventHandler::eventRevealCards`
- Reveals cards in-place or in a reveal window
- Supports temporary peeks
- Updates revealed top cards
- Logs the reveal
--- ---
@ -335,12 +395,17 @@ Client
**Purpose:** Move a card between zones. **Purpose:** Move a card between zones.
**Server:** **Server:**
- `Server_Game::handleMoveCard` - Moves cards between zones
- Updates ownership and attachments as needed
- Emits `Event_MoveCard` - Emits `Event_MoveCard`
- May emit arrow cleanup events
**Client:** **Client:**
- `PlayerEventHandler::eventMoveCard` - `PlayerEventHandler::eventMoveCard`
- Moves the card between zones
- Updates ownership, attachments, IDs and revealed information
- Handles undo-draw context
- Refreshes menus and zone layouts
- Logs the move
--- ---
@ -349,11 +414,14 @@ Client
**Purpose:** Set sideboard configuration. **Purpose:** Set sideboard configuration.
**Server:** **Server:**
- `Server_Game::handleSetSideboardPlan` - `Server_Player::cmdSetSideboardPlan`
- Stored server-side only - Allowed only before readying for the game
- Requires a loaded deck
- Requires sideboarding to be unlocked
- Stores the current sideboard plan
**Client:** **Client:**
- Not forwarded as a game event - No game event is generated
--- ---
@ -362,10 +430,17 @@ Client
**Purpose:** Select a deck. **Purpose:** Select a deck.
**Server:** **Server:**
- `Server_Game::handleDeckSelect` - `Server_Player::cmdDeckSelect`
- Allowed only before the game starts
- Loads a deck from either the database or serialized deck data
- Locks sideboarding
- Updates player properties
- Emits `Event_PlayerPropertiesChanged`
- Attaches `Context_DeckSelect`
- Returns the selected deck in the command response
**Client:** **Client:**
- Reflected via lobby / game state - Reflected through updated player properties and command response
--- ---
@ -374,10 +449,15 @@ Client
**Purpose:** Lock or unlock sideboarding. **Purpose:** Lock or unlock sideboarding.
**Server:** **Server:**
- `Server_Game::handleSetSideboardLock` - `Server_Player::cmdSetSideboardLock`
- Allowed only before readying
- Toggles sideboard locking
- Clears pending sideboard plans when locking
- Emits `Event_PlayerPropertiesChanged`
- Attaches `Context_SetSideboardLock`
**Client:** **Client:**
- Reflected via game state - Reflected through updated player properties
--- ---
@ -386,11 +466,15 @@ Client
**Purpose:** Change zone properties. **Purpose:** Change zone properties.
**Server:** **Server:**
- `Server_Game::handleChangeZoneProperties` - `Server_Player::cmdChangeZoneProperties`
- Delegates to the abstract implementation
- Updates top-card revelation if required
- Emits `Event_ChangeZoneProperties` - Emits `Event_ChangeZoneProperties`
**Client:** **Client:**
- `PlayerEventHandler::eventChangeZoneProperties` - `PlayerEventHandler::eventChangeZoneProperties`
- Updates always-reveal-top-card and always-look-at-top-card settings
- Logs property changes
--- ---
@ -399,24 +483,25 @@ Client
**Purpose:** Undo a concede. **Purpose:** Undo a concede.
**Server:** **Server:**
- `Server_Game::handleUnconcede` - Restores the player's active status
**Client:** **Client:**
- Reflected via game state - Reflected through updated game state events
--- ---
### `JUDGE` (1033) ### `JUDGE` (1033)
**Purpose:** Execute a command on behalf of another player. **Purpose:** Execute commands on behalf of another player.
**Server:** **Server:**
- `Server_Game::handleJudge` - `Server_AbstractParticipant::cmdJudge`
- Unwraps `Command_Judge` - Requires judge privileges
- Dispatches embedded `GameCommand` - Executes embedded commands as the selected player
- Marks resulting events as judge-forced
**Client:** **Client:**
- Transparent; handled as normal commands - Transparent; resulting events are processed normally
--- ---
@ -425,16 +510,20 @@ Client
**Purpose:** Reverse turn order. **Purpose:** Reverse turn order.
**Server:** **Server:**
- `Server_Game::handleReverseTurn` - `Server_Player::cmdReverseTurn`
- Toggles turn order flag - Conceded non-judge players cannot use the command
- Delegates to `Server_AbstractParticipant::cmdReverseTurn`
- Toggles turn order
- Emits `Event_ReverseTurn`
**Client:** **Client:**
- Reflected via subsequent turn events - Reflected by subsequent active-player progression
--- ---
## Notes ## Notes
- Only commands emitting `GameEvent`s appear in `PlayerEventHandler` - Game commands are handled by `Server_Player`, `Server_AbstractParticipant`, or `Server_Game`, depending on the command.
- Some commands affect game state without direct client events - Only commands that emit `GameEvent`s produce corresponding `PlayerEventHandler` callbacks.
- Judge commands are transport-level wrappers, not gameplay primitives - Some commands modify server state without generating a dedicated client event.
- Judge commands are transport wrappers that execute other game commands on behalf of another player.