From f5d4d08b15119bc0c109f65259834b4a173d8fd6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lukas=20Br=C3=BCbach?= Date: Wed, 1 Jul 2026 09:21:59 -0400 Subject: [PATCH] [Networking] Doxygen Took 49 seconds --- .../network/game_event_handler.md | 170 +++++++++++++++ .../network/player_event_handler.md | 199 ++++++++++++++++++ .../remote/game/server_abstract_player.cpp | 7 +- 3 files changed, 372 insertions(+), 4 deletions(-) create mode 100644 doc/doxygen/extra-pages/developer_documentation/network/game_event_handler.md create mode 100644 doc/doxygen/extra-pages/developer_documentation/network/player_event_handler.md diff --git a/doc/doxygen/extra-pages/developer_documentation/network/game_event_handler.md b/doc/doxygen/extra-pages/developer_documentation/network/game_event_handler.md new file mode 100644 index 000000000..fbb298d3a --- /dev/null +++ b/doc/doxygen/extra-pages/developer_documentation/network/game_event_handler.md @@ -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 diff --git a/doc/doxygen/extra-pages/developer_documentation/network/player_event_handler.md b/doc/doxygen/extra-pages/developer_documentation/network/player_event_handler.md new file mode 100644 index 000000000..6878758da --- /dev/null +++ b/doc/doxygen/extra-pages/developer_documentation/network/player_event_handler.md @@ -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 player’s 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 player’s 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 diff --git a/libcockatrice_network/libcockatrice/network/server/remote/game/server_abstract_player.cpp b/libcockatrice_network/libcockatrice/network/server/remote/game/server_abstract_player.cpp index 157fa6441..5ef24bb84 100644 --- a/libcockatrice_network/libcockatrice/network/server/remote/game/server_abstract_player.cpp +++ b/libcockatrice_network/libcockatrice/network/server/remote/game/server_abstract_player.cpp @@ -1629,10 +1629,9 @@ void Server_AbstractPlayer::getInfo(ServerInfo_Player *info, bool withUserInfo) { getProperties(*info->mutable_properties(), withUserInfo); - if (recipient == this) { - if (deck) { - info->set_deck_list(deck->writeToString_Native().toStdString()); - } + + if (deck) { + info->set_deck_list(deck->writeToString_Native().toStdString()); } for (Server_Arrow *arrow : arrows) {