[Networking] Doxygen (#7030)

* [Networking] Doxygen

* Lint cause my autolinter is broken lol

* Update.

* Update Doxyfile

Co-authored-by: tooomm <tooomm@users.noreply.github.com>

* Alphabetical ordering

Co-authored-by: tooomm <tooomm@users.noreply.github.com>

* Add new card art rule comment

* move filter program into doxygen folder

* [Networking] Doxygen


Took 49 seconds

* [Networking] Doxygen

Took 2 hours 0 minutes

Took 58 minutes

Took 8 seconds

Took 29 seconds

Took 4 minutes

Took 1 minute

Took 4 minutes

* [Networking] Fix Doxyfile

Took 2 hours 0 minutes

Took 58 minutes

Took 8 seconds

Took 29 seconds

Took 4 minutes

Took 1 minute

Took 6 minutes

* [Networking] Fix Doxyfile

Took 2 hours 0 minutes

Took 58 minutes

Took 8 seconds

Took 29 seconds

Took 4 minutes

Took 1 minute

Took 3 minutes

* [Networking] Fix Doxyfile again

Took 2 hours 0 minutes

Took 58 minutes

Took 8 seconds

Took 29 seconds

Took 4 minutes

Took 1 minute

Took 2 minutes

---------

Co-authored-by: Lukas Brübach <lukas.bruebach@bdosecurity.de>
Co-authored-by: tooomm <tooomm@users.noreply.github.com>
Co-authored-by: Lukas Brübach <Bruebach.Lukas@bdosecurity.de>
This commit is contained in:
BruebachL 2026-07-27 11:27:00 +02:00 committed by GitHub
parent 12f0f59453
commit 61b9d7abf6
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
20 changed files with 2642 additions and 129 deletions

View file

@ -8,4 +8,6 @@
- @subpage querying_the_card_database
- @subpage loading_card_pictures
- @subpage displaying_cards
- @subpage displaying_cards
- @subpage developer_reference_network_overview

View file

@ -0,0 +1,170 @@
@page game_event_handler GameEventHandler
## Overview
`GameEventHandler` is the central coordinator for **game-wide commands and events**.
It acts as the bridge between the networking layer (protobuf messages received from
the server) and the local game model and UI.
Unlike `PlayerEventHandler`, which is responsible for player-scoped state and zones,
`GameEventHandler` handles:
- Global game flow (turns, phases, host changes)
- Player and spectator lifecycle events
- Chat and logging events
- Dispatching incoming events to the appropriate subsystem
- Sending locally initiated commands to the server
In short, it is the **top-level event dispatcher** for an active game.
---
## Responsibilities
`GameEventHandler` has four primary responsibilities:
### 1. Sending game-wide commands
UI actions that affect the game as a whole (e.g. advancing the turn, changing phases,
sending chat messages) are translated into protobuf commands and sent to the server
via this class.
Examples include:
- Advancing or reversing the turn order
- Conceding or unconceding
- Changing the active phase
- Leaving the game
- Sending chat messages
These commands are wrapped in `PendingCommand` instances so their lifecycle and
responses can be tracked.
---
### 2. Processing incoming game events
Incoming server messages arrive as a `GameEventContainer`.
`GameEventHandler` is responsible for:
- Emitting lifecycle signals before and after processing
- Dispatching each event to the correct handler
- Forwarding player-scoped events to `PlayerEventHandler` instances
- Handling spectator-only and game-global events directly
This design keeps networking concerns isolated from game logic and UI code.
---
### 3. Managing global game state transitions
Certain events affect the entire game state and require coordinated updates across
multiple subsystems. Examples include:
- Full game state synchronization
- Active player or phase changes
- Game host changes
- Game closure
- Turn reversal
`GameEventHandler` ensures these events are processed in a consistent order and
that all interested systems are notified via Qt signals.
---
### 4. Emitting UI and logging signals
Rather than directly manipulating UI widgets, `GameEventHandler` emits
high-level signals that are consumed by:
- Game widgets
- Player and spectator lists
- Message and event logs
- Status indicators (ready state, deck selection, connection state)
This keeps the handler independent of concrete UI implementations.
---
## Relationship to PlayerEventHandler
`GameEventHandler` and `PlayerEventHandler` work together but have distinct roles:
| GameEventHandler | PlayerEventHandler |
|------------------|--------------------|
| Global game state | Per-player state |
| Turn / phase flow | Zones and cards |
| Player join/leave | Player actions |
| Spectator events | Player-specific events |
| Chat dispatch | Card and zone updates |
When a server event is associated with a specific player, `GameEventHandler`
routes it to the corresponding `PlayerEventHandler`. Events without a player
context are handled directly.
---
## Event Processing Flow
A typical incoming event flow looks like this:
1. `AbstractClient` receives a `GameEventContainer`
2. `GameEventHandler::processGameEventContainer()` is called
3. `containerProcessingStarted()` is emitted
4. Each event is:
- Handled directly **or**
- Forwarded to a `PlayerEventHandler`
5. Logging and UI signals are emitted as needed
6. `containerProcessingDone()` is emitted
This structured flow makes it easy to:
- Suppress UI updates during replays
- Handle reconnections cleanly
- Detect flood protection or error states
---
## Command Lifecycle
Outgoing commands follow a similar structured path:
1. UI action triggers a `handle*()` method
2. A protobuf command is constructed
3. The command is wrapped in a `PendingCommand`
4. `sendGameCommand()` sends it to the server
5. `commandFinished()` receives the response
6. Errors or flood conditions are handled centrally
This approach avoids duplicated error handling across UI code.
---
## Design Goals
`GameEventHandler` is designed to be:
- **Centralized** one entry point for all game-wide events
- **UI-agnostic** communicates via signals, not widgets
- **Predictable** well-defined event ordering and lifecycle
- **Composable** works in concert with `PlayerEventHandler`
- **Testable** logic is separated from rendering
---
## Related Classes
- @ref GameEventHandler
- @ref PlayerEventHandler
- `GameEventContainer`
- `PendingCommand`
- `AbstractClient`
- `AbstractGame`
---
## See Also
- @ref GameLogic
- @ref PlayerEventHandler
- @ref GameState

View file

@ -0,0 +1,11 @@
@page developer_reference_network_client Client Networking (Overview)
The clients response to various network protocol events and associated handling are described here.
For information about game scoped events, see:
- @subpage game_event_handler
Certain game scoped events may be forwarded to player based handlers. For more information, see:
- @subpage player_event_handler

View file

@ -0,0 +1,199 @@
@page player_event_handler PlayerEventHandler
## Overview
`PlayerEventHandler` is responsible for applying **player-scoped game events**
to a single `Player` instance. These events modify the players board state,
zones, cards, counters, arrows, and associated UI and logging output.
Each `PlayerEventHandler` instance is bound **1:1 to a Player** and is invoked
exclusively by @ref GameEventHandler after basic routing and validation of
incoming server events.
This class represents the lowest-level authoritative application of game state
changes on the client.
---
## Scope and Authority
`PlayerEventHandler` operates under the following guarantees:
- All incoming events are **authoritative** and already validated by the server
- Events refer to valid players, zones, and card identifiers
- Ordering is guaranteed by the server and preserved by `GameEventHandler`
As a result, the handler does **not** perform rule validation or permission
checks. Its responsibility is to *apply* state, not *decide* legality.
---
## Responsibilities
### 1. Applying player-specific state changes
The primary responsibility of `PlayerEventHandler` is to mutate player-owned
state, including:
- Cards (`CardItem`)
- Zones (`CardZoneLogic`)
- Counters (card-level and player-level)
- Attachments and arrows
- Zone configuration flags (reveal / peek behavior)
Many handlers update both **logical state** and **visual/UI state** in tandem.
---
### 2. Coordinating complex card movement
Some events—most notably card movement—require coordinated updates across
multiple systems. For example, `eventMoveCard()`:
- Removes the card from the source zone
- Updates ownership, visibility, and identity
- Handles attachments and arrow cleanup
- Emits undo-draw or move logs
- Inserts the card into the destination zone
- Updates menus, hover state, and graphics
This makes `PlayerEventHandler` intentionally stateful and tightly coupled to
the board implementation.
---
### 3. Emitting logging signals
Rather than writing directly to logs or widgets, `PlayerEventHandler` emits
structured Qt signals describing *what happened*, including:
- Chat messages
- Card movement
- Shuffles and randomization
- Reveals and peeks
- Counter and attribute changes
These signals are consumed by logging systems and UI components, keeping
presentation concerns out of the handler.
Logging signals may be emitted **before or after mutation**, depending on
whether later changes would invalidate log data (e.g. card identity).
---
### 4. Handling cross-player interactions
Although bound to a single player, some events necessarily affect other
players state, including:
- Moving cards between players
- Attaching cards to another players permanents
- Creating arrows targeting other players or cards
In these cases, `PlayerEventHandler` performs the minimal required mutation
while respecting ownership boundaries enforced elsewhere.
---
## Event Dispatch Model
`PlayerEventHandler` exposes a single public entry point:
- `processGameEvent()`
This method:
1. Receives a generic `GameEvent`
2. Switches on `GameEventType`
3. Extracts the appropriate protobuf extension
4. Forwards the event to a typed handler
This keeps the event routing centralized and makes it easy to audit coverage
when new game events are introduced.
Unhandled events are logged as warnings.
---
## Event Categories
For clarity, event handlers are grouped conceptually into:
- **Chat and randomization**
- Chat messages
- Shuffles
- Dice rolls
- **Arrows and targeting**
- Create / delete arrows
- **Card and token creation**
- Token generation
- Counter creation
- **Card attributes and counters**
- Tapped state
- Power/toughness
- Annotations
- Card- and player-level counters
- **Zone-level operations**
- Card movement
- Zone dumps
- Card destruction
- Attachments
- **Draw and reveal**
- Drawing cards
- Reveals, peeks, and reveal windows
- **Zone configuration**
- Always-reveal and always-look-at-top-card flags
This grouping mirrors the structure of the header file and reflects the
conceptual responsibilities of the class.
---
## Relationship to GameEventHandler
`PlayerEventHandler` is never instantiated or invoked directly by UI code.
Instead:
1. `GameEventHandler` receives a `GameEventContainer`
2. Player-scoped events are routed to the appropriate `PlayerEventHandler`
3. Global or spectator events are handled elsewhere
This separation keeps game-wide logic decoupled from player board state and
makes reconnection and replay handling simpler.
---
## Design Intent
`PlayerEventHandler` is designed to be:
- **Authoritative** applies server state exactly as received
- **Stateful** maintains consistency across cards, zones, and UI
- **Explicit** one handler per event type
- **UI-aware** updates views and menus as part of state mutation
- **Auditable** easy to trace what code handles which event
---
## Related Classes
- @ref PlayerEventHandler
- @ref GameEventHandler
- `Player`
- `CardItem`
- `CardZoneLogic`
- `GameEvent`
- `GameEventContext`
---
## See Also
- @ref GameLogicPlayers
- @ref GameLogic

View file

@ -0,0 +1,170 @@
@page game_event_handler GameEventHandler
## Overview
`GameEventHandler` is the central coordinator for **game-wide commands and events**.
It acts as the bridge between the networking layer (protobuf messages received from
the server) and the local game model and UI.
Unlike `PlayerEventHandler`, which is responsible for player-scoped state and zones,
`GameEventHandler` handles:
- Global game flow (turns, phases, host changes)
- Player and spectator lifecycle events
- Chat and logging events
- Dispatching incoming events to the appropriate subsystem
- Sending locally initiated commands to the server
In short, it is the **top-level event dispatcher** for an active game.
---
## Responsibilities
`GameEventHandler` has four primary responsibilities:
### 1. Sending game-wide commands
UI actions that affect the game as a whole (e.g. advancing the turn, changing phases,
sending chat messages) are translated into protobuf commands and sent to the server
via this class.
Examples include:
- Advancing or reversing the turn order
- Conceding or unconceding
- Changing the active phase
- Leaving the game
- Sending chat messages
These commands are wrapped in `PendingCommand` instances so their lifecycle and
responses can be tracked.
---
### 2. Processing incoming game events
Incoming server messages arrive as a `GameEventContainer`.
`GameEventHandler` is responsible for:
- Emitting lifecycle signals before and after processing
- Dispatching each event to the correct handler
- Forwarding player-scoped events to `PlayerEventHandler` instances
- Handling spectator-only and game-global events directly
This design keeps networking concerns isolated from game logic and UI code.
---
### 3. Managing global game state transitions
Certain events affect the entire game state and require coordinated updates across
multiple subsystems. Examples include:
- Full game state synchronization
- Active player or phase changes
- Game host changes
- Game closure
- Turn reversal
`GameEventHandler` ensures these events are processed in a consistent order and
that all interested systems are notified via Qt signals.
---
### 4. Emitting UI and logging signals
Rather than directly manipulating UI widgets, `GameEventHandler` emits
high-level signals that are consumed by:
- Game widgets
- Player and spectator lists
- Message and event logs
- Status indicators (ready state, deck selection, connection state)
This keeps the handler independent of concrete UI implementations.
---
## Relationship to PlayerEventHandler
`GameEventHandler` and `PlayerEventHandler` work together but have distinct roles:
| GameEventHandler | PlayerEventHandler |
|------------------|--------------------|
| Global game state | Per-player state |
| Turn / phase flow | Zones and cards |
| Player join/leave | Player actions |
| Spectator events | Player-specific events |
| Chat dispatch | Card and zone updates |
When a server event is associated with a specific player, `GameEventHandler`
routes it to the corresponding `PlayerEventHandler`. Events without a player
context are handled directly.
---
## Event Processing Flow
A typical incoming event flow looks like this:
1. `AbstractClient` receives a `GameEventContainer`
2. `GameEventHandler::processGameEventContainer()` is called
3. `containerProcessingStarted()` is emitted
4. Each event is:
- Handled directly **or**
- Forwarded to a `PlayerEventHandler`
5. Logging and UI signals are emitted as needed
6. `containerProcessingDone()` is emitted
This structured flow makes it easy to:
- Suppress UI updates during replays
- Handle reconnections cleanly
- Detect flood protection or error states
---
## Command Lifecycle
Outgoing commands follow a similar structured path:
1. UI action triggers a `handle*()` method
2. A protobuf command is constructed
3. The command is wrapped in a `PendingCommand`
4. `sendGameCommand()` sends it to the server
5. `commandFinished()` receives the response
6. Errors or flood conditions are handled centrally
This approach avoids duplicated error handling across UI code.
---
## Design Goals
`GameEventHandler` is designed to be:
- **Centralized** one entry point for all game-wide events
- **UI-agnostic** communicates via signals, not widgets
- **Predictable** well-defined event ordering and lifecycle
- **Composable** works in concert with `PlayerEventHandler`
- **Testable** logic is separated from rendering
---
## Related Classes
- @ref GameEventHandler
- @ref PlayerEventHandler
- `GameEventContainer`
- `PendingCommand`
- `AbstractClient`
- `AbstractGame`
---
## See Also
- @ref GameLogic
- @ref PlayerEventHandler
- @ref GameState

View file

@ -0,0 +1,7 @@
@page developer_reference_network_overview Network (Overview)
This page provides information about the networking performed by the client and server.
For information about the protocol, see @subpage developer_reference_protocol
For information about the clients response to and handling of protocol messages, see @subpage developer_reference_network_client

View file

@ -0,0 +1,199 @@
@page player_event_handler PlayerEventHandler
## Overview
`PlayerEventHandler` is responsible for applying **player-scoped game events**
to a single `Player` instance. These events modify the players board state,
zones, cards, counters, arrows, and associated UI and logging output.
Each `PlayerEventHandler` instance is bound **1:1 to a Player** and is invoked
exclusively by @ref GameEventHandler after basic routing and validation of
incoming server events.
This class represents the lowest-level authoritative application of game state
changes on the client.
---
## Scope and Authority
`PlayerEventHandler` operates under the following guarantees:
- All incoming events are **authoritative** and already validated by the server
- Events refer to valid players, zones, and card identifiers
- Ordering is guaranteed by the server and preserved by `GameEventHandler`
As a result, the handler does **not** perform rule validation or permission
checks. Its responsibility is to *apply* state, not *decide* legality.
---
## Responsibilities
### 1. Applying player-specific state changes
The primary responsibility of `PlayerEventHandler` is to mutate player-owned
state, including:
- Cards (`CardItem`)
- Zones (`CardZoneLogic`)
- Counters (card-level and player-level)
- Attachments and arrows
- Zone configuration flags (reveal / peek behavior)
Many handlers update both **logical state** and **visual/UI state** in tandem.
---
### 2. Coordinating complex card movement
Some events—most notably card movement—require coordinated updates across
multiple systems. For example, `eventMoveCard()`:
- Removes the card from the source zone
- Updates ownership, visibility, and identity
- Handles attachments and arrow cleanup
- Emits undo-draw or move logs
- Inserts the card into the destination zone
- Updates menus, hover state, and graphics
This makes `PlayerEventHandler` intentionally stateful and tightly coupled to
the board implementation.
---
### 3. Emitting logging signals
Rather than writing directly to logs or widgets, `PlayerEventHandler` emits
structured Qt signals describing *what happened*, including:
- Chat messages
- Card movement
- Shuffles and randomization
- Reveals and peeks
- Counter and attribute changes
These signals are consumed by logging systems and UI components, keeping
presentation concerns out of the handler.
Logging signals may be emitted **before or after mutation**, depending on
whether later changes would invalidate log data (e.g. card identity).
---
### 4. Handling cross-player interactions
Although bound to a single player, some events necessarily affect other
players state, including:
- Moving cards between players
- Attaching cards to another players permanents
- Creating arrows targeting other players or cards
In these cases, `PlayerEventHandler` performs the minimal required mutation
while respecting ownership boundaries enforced elsewhere.
---
## Event Dispatch Model
`PlayerEventHandler` exposes a single public entry point:
- `processGameEvent()`
This method:
1. Receives a generic `GameEvent`
2. Switches on `GameEventType`
3. Extracts the appropriate protobuf extension
4. Forwards the event to a typed handler
This keeps the event routing centralized and makes it easy to audit coverage
when new game events are introduced.
Unhandled events are logged as warnings.
---
## Event Categories
For clarity, event handlers are grouped conceptually into:
- **Chat and randomization**
- Chat messages
- Shuffles
- Dice rolls
- **Arrows and targeting**
- Create / delete arrows
- **Card and token creation**
- Token generation
- Counter creation
- **Card attributes and counters**
- Tapped state
- Power/toughness
- Annotations
- Card- and player-level counters
- **Zone-level operations**
- Card movement
- Zone dumps
- Card destruction
- Attachments
- **Draw and reveal**
- Drawing cards
- Reveals, peeks, and reveal windows
- **Zone configuration**
- Always-reveal and always-look-at-top-card flags
This grouping mirrors the structure of the header file and reflects the
conceptual responsibilities of the class.
---
## Relationship to GameEventHandler
`PlayerEventHandler` is never instantiated or invoked directly by UI code.
Instead:
1. `GameEventHandler` receives a `GameEventContainer`
2. Player-scoped events are routed to the appropriate `PlayerEventHandler`
3. Global or spectator events are handled elsewhere
This separation keeps game-wide logic decoupled from player board state and
makes reconnection and replay handling simpler.
---
## Design Intent
`PlayerEventHandler` is designed to be:
- **Authoritative** applies server state exactly as received
- **Stateful** maintains consistency across cards, zones, and UI
- **Explicit** one handler per event type
- **UI-aware** updates views and menus as part of state mutation
- **Auditable** easy to trace what code handles which event
---
## Related Classes
- @ref PlayerEventHandler
- @ref GameEventHandler
- `Player`
- `CardItem`
- `CardZoneLogic`
- `GameEvent`
- `GameEventContext`
---
## See Also
- @ref GameLogicPlayers
- @ref GameLogic

View file

@ -0,0 +1,15 @@
@page developer_reference_protocol Protocol (Overview)
For an overview of the protocol used by the Cockatrice client and server, see:
- @subpage developer_reference_protocol_overview
- @subpage protocol_game_command
For client → server communication, see:
- @subpage protocol_command_container
For server → client communication, see:
- @subpage protocol_server_message
- @subpage protocol_response

View file

@ -0,0 +1,114 @@
@page protocol_command_container CommandContainer (Protocol Concept)
@section cc_overview Overview
CommandContainer is the client-to-server message envelope used for all
client requests in the Cockatrice protocol.
Every client-initiated action is transmitted as a CommandContainer.
The server never sends CommandContainer messages.
This is a protocol-level abstraction and should not be confused with the
generated protobuf accessors or wire-level encoding.
@section cc_lifecycle Lifetime and Ownership
- CommandContainers are created by clients and consumed by the server.
- Each container represents one logical request.
- Containers are processed atomically and in order of arrival.
A container may generate:
- Exactly one RESPONSE message, and
- Zero or more EVENT messages.
@section cc_cmd_id Command Identification
The @c cmd_id field is a client-assigned identifier used to correlate
responses with requests.
Rules:
- @c cmd_id is optional but strongly recommended
- The server echoes @c cmd_id only in RESPONSE messages
- EVENT messages are never associated with a @c cmd_id
The server does not enforce uniqueness of @c cmd_id values.
@section cc_context Command Context
Certain command domains require additional context:
- Room commands require @c room_id
- Game commands require @c game_id
Context fields are ignored for command domains that do not require them.
If a required context field is missing or invalid, the server responds with
@c RespContextError.
@section cc_invariants Invariants
The following rules are enforced by the server:
- Exactly one command domain must be populated
- Commands may be batched only within the same domain
- Context fields must match the active command domain
Violations of these rules result in @c RespInvalidCommand.
@section cc_domains Command Domains
CommandContainer supports the following mutually exclusive command domains:
- Session commands
- Authentication
- User discovery
- Private messaging
- Room commands
- Chat
- Game creation
- Room membership management
- Game commands
- In-game actions
- State mutations
- Moderator commands
- User moderation
- Room moderation
- Admin commands
- Server administration
@section cc_batching Command Batching
A CommandContainer may contain multiple commands of the same domain.
Batching guarantees:
- Commands are processed in the order they appear in the container
- All commands in the batch share the same context
Partial failure behavior is implementation-defined and may vary by domain.
@section cc_dispatch Dispatch
CommandContainers are dispatched by
Server_ProtocolHandler::processCommandContainer().
Dispatch is performed by inspecting which command domain is populated.
Only the first populated domain is considered.
@section cc_errors Error Handling
Common error responses include:
- @c RespLoginNeeded client is not authenticated
- @c RespInvalidCommand malformed container or invalid domain usage
- @c RespContextError missing or invalid room/game context
@section cc_related Related Concepts
- @ref protocol_server_message "ServerMessage"
- @ref protocol_client_states "Client State Machine"
@see Server_ProtocolHandler::processCommandContainer

View file

@ -0,0 +1,529 @@
@page protocol_game_command GameCommand (Protocol Concept)
# Game Commands Reference
This document describes game-level commands (`GameCommandType`) and how they are
handled across the server and client.
Flow overview:
Client
→ GameCommand
→ Server command handler (`Server_Player`, `Server_AbstractParticipant`, or `Server_Game`)
→ GameEvent(s)
→ PlayerEventHandler::event*
## Command Mapping
### `GAME_SAY` (1002)
**Purpose:** Send a chat message during a game.
**Server:**
- `Server_AbstractParticipant::cmdGameSay`
- Validates spectator chat permissions
- Applies chat flood protection
- Emits `Event_GameSay`
- Logs the message to the server database
**Client:**
- `PlayerEventHandler::eventGameSay`
- Adds the chat message to the game log
---
### `SHUFFLE` (1003)
**Purpose:** Shuffle a card zone (usually library).
**Server:**
- `Server_Player::cmdShuffle`
- 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`
- Re-reveals the top card if the deck is being tracked
**Client:**
- `PlayerEventHandler::eventShuffle`
- Closes affected library views
- Clears any revealed top card if necessary
- Updates deck graphics
- Logs the shuffle
---
### `ROLL_DIE` (1005)
**Purpose:** Roll one or more dice.
**Server:**
- Computes random die results
- Emits `Event_RollDie`
**Client:**
- `PlayerEventHandler::eventRollDie`
- Displays the sorted roll results in the game log
---
### `DRAW_CARDS` (1006)
**Purpose:** Draw cards from deck.
**Server:**
- `Server_Player::cmdDrawCards`
- 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`
**Client:**
- `PlayerEventHandler::eventDrawCards`
- Moves cards from library to hand
- Reveals card identities only when included in the event
- Updates both zones
- Logs the draw
---
### `UNDO_DRAW` (1007)
**Purpose:** Undo a previous draw.
**Server:**
- `Server_Player::cmdUndoDraw`
- Rejects if the game has not started or the player has conceded
- 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:**
- Processed as a normal `MOVE_CARD`
- Detects `Context_UndoDraw`
- Logs the undo draw instead of a normal move
---
### `FLIP_CARD` (1008)
**Purpose:** Flip a card face up or face down.
**Server:**
- Updates the card's face-down state
- Reveals identity when turning face up
- Emits `Event_FlipCard`
**Client:**
- `PlayerEventHandler::eventFlipCard`
- Updates the card identity when revealed
- Changes face-up / face-down state
- Updates card menus
- Logs the flip
---
### `ATTACH_CARD` (1009)
**Purpose:** Attach one card to another.
**Server:**
- Updates attachment relationships
- Emits `Event_AttachCard`
**Client:**
- `PlayerEventHandler::eventAttachCard`
- Updates parent/child attachment links
- Reorganizes affected zones
- Logs attach or detach operations
- Refreshes card actions
---
### `CREATE_TOKEN` (1010)
**Purpose:** Create a token card.
**Server:**
- Creates a new token card
- Emits `Event_CreateToken`
**Client:**
- `PlayerEventHandler::eventCreateToken`
- Creates the token object
- Applies token properties (PT, color, annotation, face-down state)
- Adds it to the requested zone
- Logs token creation
---
### `CREATE_ARROW` (1011)
**Purpose:** Create a visual arrow.
**Server:**
- Creates a visual arrow
- Emits `Event_CreateArrow`
**Client:**
- `PlayerEventHandler::eventCreateArrow`
- Creates the arrow graphics
- Resolves endpoint card names
- Logs arrow creation
---
### `DELETE_ARROW` (1012)
**Purpose:** Remove a visual arrow.
**Server:**
- Removes an existing arrow
- Emits `Event_DeleteArrow`
**Client:**
- `PlayerEventHandler::eventDeleteArrow`
- Removes the arrow graphics
---
### `SET_CARD_ATTR` (1013)
**Purpose:** Set a card attribute.
**Server:**
- Updates one or more card attributes
- Emits `Event_SetCardAttr`
**Client:**
- `PlayerEventHandler::eventSetCardAttr`
- Updates tapped state, color, annotation, power/toughness, face-down state, attacking state, and related visuals
- Logs attribute changes where appropriate
---
### `SET_CARD_COUNTER` (1014)
**Purpose:** Set a card counter.
**Server:**
- Updates the specified card counter
- Emits `Event_SetCardCounter`
**Client:**
- `PlayerEventHandler::eventSetCardCounter`
- Updates the displayed counter value
- Refreshes card actions
- Logs the counter change
---
### `INC_CARD_COUNTER` (1015)
**Purpose:** Increment a card counter.
**Server:**
- Normalizes to a set-counter operation
- Emits `Event_SetCardCounter`
**Client:**
- Processed identically to `SET_CARD_COUNTER`
---
### `READY_START` (1016)
**Purpose:** Mark player as ready.
**Server:**
- Marks the player as ready
- Starts the game once all required players are ready
**Client:**
- Reflected through updated game state events
---
### `CONCEDE` (1017)
**Purpose:** Concede the game.
**Server:**
- Marks the player as conceded
- Returns borrowed cards where appropriate
- Ends the game if only one player remains
**Client:**
- Reflected through updated game state events
---
### `INC_COUNTER` (1018)
**Purpose:** Increment a player counter.
**Server:**
- `Server_Player::cmdIncCounter`
- 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:**
- `PlayerEventHandler::eventSetCounter`
- Updates the displayed player counter
- Logs the change
---
### `CREATE_COUNTER` (1019)
**Purpose:** Create a player counter.
**Server:**
- `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`
**Client:**
- `PlayerEventHandler::eventCreateCounter`
- Creates the local player counter
---
### `SET_COUNTER` (1020)
**Purpose:** Set a player counter value.
**Server:**
- `Server_Player::cmdSetCounter`
- 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:**
- `PlayerEventHandler::eventSetCounter`
- Updates the counter value
- Logs the change
---
### `DEL_COUNTER` (1021)
**Purpose:** Delete a player counter.
**Server:**
- `Server_Player::cmdDelCounter`
- Rejects if the game has not started or the player has conceded
- Deletes the counter
- Emits `Event_DelCounter`
**Client:**
- `PlayerEventHandler::eventDelCounter`
- Removes the counter
---
### `NEXT_TURN` (1022)
**Purpose:** Advance to the next turn.
**Server:**
- `Server_Player::cmdNextTurn`
- Rejects if the game has not started
- Conceded players cannot advance turns unless acting as a judge
- Calls `Server_Game::nextTurn()`
**Client:**
- Reflected through subsequent active-player and active-phase events
---
### `SET_ACTIVE_PHASE` (1023)
**Purpose:** Set active phase.
**Server:**
- `Server_Player::cmdSetActivePhase`
- 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:**
- Reflected through updated phase events
---
### `DUMP_ZONE` (1024)
**Purpose:** Dump zone contents.
**Server:**
- Generates a zone summary
- Emits `Event_DumpZone`
**Client:**
- `PlayerEventHandler::eventDumpZone`
- Logs the zone contents summary
---
### `REVEAL_CARDS` (1026)
**Purpose:** Reveal specific cards.
**Server:**
- Reveals cards to one or more players
- Emits `Event_RevealCards`
**Client:**
- `PlayerEventHandler::eventRevealCards`
- Reveals cards in-place or in a reveal window
- Supports temporary peeks
- Updates revealed top cards
- Logs the reveal
---
### `MOVE_CARD` (1027)
**Purpose:** Move a card between zones.
**Server:**
- Moves cards between zones
- Updates ownership and attachments as needed
- Emits `Event_MoveCard`
**Client:**
- `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
---
### `SET_SIDEBOARD_PLAN` (1028)
**Purpose:** Set sideboard configuration.
**Server:**
- `Server_Player::cmdSetSideboardPlan`
- Allowed only before readying for the game
- Requires a loaded deck
- Requires sideboarding to be unlocked
- Stores the current sideboard plan
**Client:**
- No game event is generated
---
### `DECK_SELECT` (1029)
**Purpose:** Select a deck.
**Server:**
- `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:**
- Reflected through updated player properties and command response
---
### `SET_SIDEBOARD_LOCK` (1030)
**Purpose:** Lock or unlock sideboarding.
**Server:**
- `Server_Player::cmdSetSideboardLock`
- Allowed only before readying
- Toggles sideboard locking
- Clears pending sideboard plans when locking
- Emits `Event_PlayerPropertiesChanged`
- Attaches `Context_SetSideboardLock`
**Client:**
- Reflected through updated player properties
---
### `CHANGE_ZONE_PROPERTIES` (1031)
**Purpose:** Change zone properties.
**Server:**
- `Server_Player::cmdChangeZoneProperties`
- Delegates to the abstract implementation
- Updates top-card revelation if required
- Emits `Event_ChangeZoneProperties`
**Client:**
- `PlayerEventHandler::eventChangeZoneProperties`
- Updates always-reveal-top-card and always-look-at-top-card settings
- Logs property changes
---
### `UNCONCEDE` (1032)
**Purpose:** Undo a concede.
**Server:**
- Restores the player's active status
**Client:**
- Reflected through updated game state events
---
### `JUDGE` (1033)
**Purpose:** Execute commands on behalf of another player.
**Server:**
- `Server_AbstractParticipant::cmdJudge`
- Requires judge privileges
- Executes embedded commands as the selected player
- Marks resulting events as judge-forced
**Client:**
- Transparent; resulting events are processed normally
---
### `REVERSE_TURN` (1034)
**Purpose:** Reverse turn order.
**Server:**
- `Server_Player::cmdReverseTurn`
- Conceded non-judge players cannot use the command
- Delegates to `Server_AbstractParticipant::cmdReverseTurn`
- Toggles turn order
- Emits `Event_ReverseTurn`
**Client:**
- Reflected by subsequent active-player progression
---
## Notes
- Game commands are handled by `Server_Player`, `Server_AbstractParticipant`, or `Server_Game`, depending on the command.
- Only commands that emit `GameEvent`s produce corresponding `PlayerEventHandler` callbacks.
- 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.

View file

@ -0,0 +1,76 @@
@page developer_reference_protocol_overview Protocol (Overview)
# Cockatrice Server Protocol Overview
## Purpose
This document describes the Cockatrice client/server protocol as implemented
by the Cockatrice server. It is intended for developers implementing clients
or modifying the server.
The protocol is **stateful**, **event-driven**, and **asynchronous**.
---
## High-Level Properties
- Encoding: Google Protocol Buffers
- Transport: TCP or WebSocket (transport-agnostic at protocol level)
- Directionality:
- Clients send `CommandContainer`
- Server sends `ServerMessage`
- Responses and events are interleaved
- Clients must handle unsolicited events at any time
---
## Message Envelopes
### Client → Server: CommandContainer
A `CommandContainer` represents one logical client request.
Protocol invariants:
- Exactly one command domain may be used per container
- Multiple commands of the same domain may be batched
- Context is provided via `room_id` or `game_id` when required
Command domains:
- Session commands
- Room commands
- Game commands
- Moderator commands
- Admin commands
---
### Server → Client: ServerMessage
A `ServerMessage` represents either:
- A response to a command (`RESPONSE`)
- An unsolicited event (`*_EVENT`)
Protocol invariants:
- Events may be delivered before or after responses
- Responses reference the original command via `cmd_id`
- Events are never correlated to a command
---
## Asynchronous Model
Clients MUST NOT assume request/response ordering.
Example valid sequence:
1. Client sends JOIN_ROOM
2. Server sends room chat history events
3. Server sends room join notifications
4. Server sends JOIN_ROOM response
---
## Versioning
The server reports a protocol version during connection initialization.
Clients MUST verify compatibility before sending commands.

View file

@ -0,0 +1,27 @@
@page protocol_response Response (Protocol Concept)
## Overview
`Response` is the server-to-client message sent immediately after a command, using the same `cmd_id` to link to the originating command.
It provides a `Response::ResponseCode` and optionally a `Response::ResponseType` to guide client handling.
## Fields
- **cmd_id** (`uint64`, required) — Command ID this response corresponds to
- **response_code** (`Response::ResponseCode`, optional) — Outcome of the command
## Response Codes
All possible outcome codes are defined in Response::ResponseCode
These describe the result of the command, e.g., success, failure, or special conditions like bans or registration requirements.
## Response Types
Responses are routed according to Response::ResponseType
Each `ResponseType` corresponds to a high-level category, like `JOIN_ROOM` or `DECK_UPLOAD`.
## Extensions
- Protobuf extensions from 100 to max are reserved for future use

View file

@ -0,0 +1,171 @@
@page protocol_server_message ServerMessage (Protocol Concept)
## Overview
`ServerMessage` is the server-to-client message envelope used for all
communication originating from the Cockatrice server.
The server never sends `CommandContainer` messages, and clients never send
`ServerMessage` messages.
A `ServerMessage` represents either:
- A direct response to a client command, or
- An unsolicited event emitted by the server
This document describes `ServerMessage` as a protocol-level concept.
It should not be confused with generated protobuf accessors or wire-level
encoding details.
---
## Lifetime and Delivery
`ServerMessage` instances are emitted by the server and delivered
asynchronously to clients.
Delivery guarantees:
- Messages are delivered in the order sent by the server
- Messages may be delivered at any time
- Events may be delivered before or after responses
Clients **must** be prepared to handle `ServerMessage` objects at all times,
regardless of pending requests.
---
## Message Type
Each `ServerMessage` contains **exactly one payload**, identified by the
`message_type` field.
The following message types are supported:
- `RESPONSE`
- `SESSION_EVENT`
- `ROOM_EVENT`
- `GAME_EVENT_CONTAINER`
A message containing multiple payloads or an unknown type is considered
malformed.
---
## RESPONSE
`RESPONSE` messages are direct replies to client-issued `CommandContainer`
messages.
Characteristics:
- Contain a `Response` payload
- Echo the client-assigned `cmd_id`
- Indicate success or failure of the request
A single `CommandContainer` results in **at most one** `RESPONSE`.
`RESPONSE` messages may be preceded or followed by event messages.
---
## Events
Event messages are unsolicited notifications emitted by the server.
Event message types include:
- `SESSION_EVENT`
- `ROOM_EVENT`
- `GAME_EVENT_CONTAINER`
Event messages:
- Are not correlated to a specific client command
- Do not include a `cmd_id`
- May be delivered at any time
Clients **must** process events independently of responses.
---
## Event Scopes
### Session Events
Session events are global to the client session and may include:
- Server notifications
- Private messages
- User status updates
---
### Room Events
Room events are scoped to a specific room and are delivered only to clients
currently present in that room.
---
### Game Events
Game events are scoped to a specific game and are delivered only to
participating clients.
Game events are grouped within a `GameEventContainer` to allow batching.
---
## Event Batching
Some `ServerMessage` types may contain multiple logical events.
- `GameEventContainer` may batch multiple game events
- Other event types represent a single logical event
Clients must process all contained events **in order**.
---
## Error Semantics
Errors are communicated **exclusively** via `RESPONSE` messages.
Event messages are never used to signal command failure.
Common error responses include:
- `RespInvalidCommand`
- `RespLoginNeeded`
- `RespContextError`
- `RespChatFlood`
---
## Related Concepts
- CommandContainer
- Client State Machine
- Response
---
## Reference Proto Definition
```proto
message ServerMessage {
enum MessageType {
RESPONSE = 0;
SESSION_EVENT = 1;
GAME_EVENT_CONTAINER = 2;
ROOM_EVENT = 3;
}
optional MessageType message_type = 1;
optional Response response = 2;
optional SessionEvent session_event = 3;
optional GameEventContainer game_event_container = 4;
optional RoomEvent room_event = 5;
}
```