[Networking] Doxygen

This commit is contained in:
Lukas Brübach 2026-07-01 09:21:59 -04:00
parent 05ae6f47a6
commit 98cb71ab29
17 changed files with 2179 additions and 122 deletions

View file

@ -1,8 +1,16 @@
/**
* @file game_event_handler.h
* @ingroup GameLogic
* @brief Game-level command sender and event dispatcher.
*
* GameEventHandler sends commands initiated by the local client to the server
* and processes incoming game-wide events. It bridges the networking layer
* (protobuf events received via AbstractClient) with the game model and UI
* (GameState, PlayerManager, logging, widgets).
*
* Player-scoped events are forwarded to PlayerEventHandler instances, while
* spectator and global game events are handled directly here.
*/
//! \todo Document this file.
#ifndef COCKATRICE_GAME_EVENT_HANDLER_H
#define COCKATRICE_GAME_EVENT_HANDLER_H
@ -15,92 +23,310 @@
#include <libcockatrice/protocol/pb/serverinfo_player.pb.h>
class AbstractClient;
class Response;
class AbstractGame;
class CommandContainer;
class GameCommand;
class GameEventContainer;
class GameEventContext;
class GameCommand;
class GameState;
class MessageLogWidget;
class CommandContainer;
class Event_GameJoined;
class PendingCommand;
class PlayerLogic;
class Response;
class Event_GameStateChanged;
class Event_PlayerPropertiesChanged;
class Event_Join;
class Event_Leave;
class Event_GameHostChanged;
class Event_GameClosed;
class Event_GameStart;
class Event_SetActivePlayer;
class Event_SetActivePhase;
class Event_Ping;
class Event_GameSay;
class Event_Kicked;
class Event_ReverseTurn;
class AbstractGame;
class PendingCommand;
class PlayerLogic;
class Event_Ping;
inline Q_LOGGING_CATEGORY(GameEventHandlerLog, "game_event_handler");
/**
* @class GameEventHandler
* @brief Central dispatcher for game-wide commands and events.
*
* This class owns no game state itself. Instead, it:
* - Sends commands to the server on behalf of local players
* - Receives and dispatches server-side game events
* - Updates the game model indirectly via Player, GameState, and PlayerManager
* - Emits high-level signals for UI updates and logging
*/
class GameEventHandler : public QObject
{
Q_OBJECT
private:
/** Pointer to the owning game instance. */
AbstractGame *game;
public:
/** @name Construction
* Lifecycle and ownership.
* @{
*/
/**
* @brief Construct a GameEventHandler.
*
* The handler is owned by the AbstractGame instance and uses it to
* access the game state, players, and network clients.
*
* @param _game Owning game instance (also used as QObject parent).
*/
explicit GameEventHandler(AbstractGame *_game);
/** @} */
/** @name Outgoing game commands
* Commands initiated locally and sent to the server.
*
* These methods construct and send protobuf commands corresponding
* to user actions in the UI.
* @{
*/
/** @brief Request advancing the game to the next turn. */
void handleNextTurn();
/** @brief Request reversing the current turn order. */
void handleReverseTurn();
/** @brief Concede the game for the currently active local player. */
void handleActiveLocalPlayerConceded();
/** @brief Undo a previous concede for the active local player. */
void handleActiveLocalPlayerUnconceded();
/**
* @brief Set the active phase of the game.
*
* Typically triggered by the active player selecting a new phase.
*
* @param phase Phase identifier.
*/
void handleActivePhaseChanged(int phase);
/** @brief Leave the current game session. */
void handleGameLeft();
/**
* @brief Send a chat message to all players and spectators.
*
* @param chatMessage Message text.
*/
void handleChatMessageSent(const QString &chatMessage);
/**
* @brief Delete an existing arrow.
*
* @param arrowId Unique identifier of the arrow to delete.
*/
void handleArrowDeletion(int creatorId, int arrowId);
void handleArrowDeletionFinished(const Response &response, int creatorId, int arrowId);
/** @} */
/** @name Incoming event processing
* Entry points for server-sent events.
* @{
*/
/**
* @brief Process a container of game events received from the server.
*
* This is the main dispatch function for incoming game events.
* Events are routed to spectator handlers, game-level handlers,
* or forwarded to PlayerEventHandler instances as appropriate.
*
* @param cont Game event container from the server.
* @param client Client that received the container.
* @param options Processing flags (e.g. silent, replay).
*/
void
processGameEventContainer(const GameEventContainer &cont, AbstractClient *client, EventProcessingOptions options);
/** @} */
/** @name Command preparation helpers
* Internal helpers for building command containers.
* @{
*/
/**
* @brief Wrap a single protobuf command in a PendingCommand.
*
* @param cmd Protobuf command message.
* @return Newly allocated PendingCommand (caller takes ownership).
*/
PendingCommand *prepareGameCommand(const ::google::protobuf::Message &cmd);
/**
* @brief Wrap multiple protobuf commands in a single PendingCommand.
*
* Ownership of the messages in cmdList is transferred to the handler.
*
* @param cmdList List of protobuf command messages.
* @return Newly allocated PendingCommand.
*/
PendingCommand *prepareGameCommand(const QList<const ::google::protobuf::Message *> &cmdList);
/** @} */
/** @name Spectator event handlers
* Events originating from spectators.
* @{
*/
/**
* @brief Handle a spectator chat message.
*/
void eventSpectatorSay(const Event_GameSay &event, int eventPlayerId, const GameEventContext &context);
/**
* @brief Handle a spectator leaving the game.
*/
void eventSpectatorLeave(const Event_Leave &event, int eventPlayerId, const GameEventContext &context);
/** @} */
/** @name Game state event handlers
* Events that affect global game state.
* @{
*/
/**
* @brief Handle a full game state update from the server.
*
* Used during game startup, reconnection, and resynchronization.
*/
void eventGameStateChanged(const Event_GameStateChanged &event, int eventPlayerId, const GameEventContext &context);
/**
* @brief Update card attachment relationships for all players.
*
* Called after a game state update to ensure attachments are resolved
* consistently across all zones.
*/
void processCardAttachmentsForPlayers(const Event_GameStateChanged &event);
/** @brief Handle a change in game host. */
void eventGameHostChanged(const Event_GameHostChanged &event, int eventPlayerId, const GameEventContext &context);
/** @brief Handle the game being closed by the server. */
void eventGameClosed(const Event_GameClosed &event, int eventPlayerId, const GameEventContext &context);
/** @brief Handle a change of the active player. */
void eventSetActivePlayer(const Event_SetActivePlayer &event, int eventPlayerId, const GameEventContext &context);
/** @brief Handle a change of the active phase. */
void eventSetActivePhase(const Event_SetActivePhase &event, int eventPlayerId, const GameEventContext &context);
/** @brief Handle a turn reversal event. */
void eventReverseTurn(const Event_ReverseTurn &event, int eventPlayerId, const GameEventContext &context);
/** @brief Handle ping / latency updates. */
void eventPing(const Event_Ping &event, int eventPlayerId, const GameEventContext &context);
/** @} */
/** @name Player lifecycle and property handlers
* Events related to players joining, leaving, or changing state.
* @{
*/
/**
* @brief Handle updates to a player's properties.
*
* Includes readiness, concede state, deck selection, sideboard lock,
* and connection state changes.
*/
void eventPlayerPropertiesChanged(const Event_PlayerPropertiesChanged &event,
int eventPlayerId,
const GameEventContext &context);
/** @brief Handle a player or spectator joining the game. */
void eventJoin(const Event_Join &event, int eventPlayerId, const GameEventContext &context);
/** @brief Handle a player leaving the game. */
void eventLeave(const Event_Leave &event, int eventPlayerId, const GameEventContext &context);
QString getLeaveReason(Event_Leave::LeaveReason reason);
/** @brief Handle the local player being kicked from the game. */
void eventKicked(const Event_Kicked &event, int eventPlayerId, const GameEventContext &context);
void eventGameHostChanged(const Event_GameHostChanged &event, int eventPlayerId, const GameEventContext &context);
void eventGameClosed(const Event_GameClosed &event, int eventPlayerId, const GameEventContext &context);
void eventSetActivePlayer(const Event_SetActivePlayer &event, int eventPlayerId, const GameEventContext &context);
void eventSetActivePhase(const Event_SetActivePhase &event, int eventPlayerId, const GameEventContext &context);
void eventPing(const Event_Ping &event, int eventPlayerId, const GameEventContext &context);
void eventReverseTurn(const Event_ReverseTurn &event, int eventPlayerId, const GameEventContext & /*context*/);
/**
* @brief Convert a leave reason enum to a human-readable string.
*/
QString getLeaveReason(Event_Leave::LeaveReason reason);
void commandFinished(const Response &response);
/** @} */
void
processGameEventContainer(const GameEventContainer &cont, AbstractClient *client, EventProcessingOptions options);
PendingCommand *prepareGameCommand(const ::google::protobuf::Message &cmd);
PendingCommand *prepareGameCommand(const QList<const ::google::protobuf::Message *> &cmdList);
public slots:
/** @name Command dispatch slots
* Low-level command transmission.
* @{
*/
/**
* @brief Send a prepared PendingCommand.
*
* @param pend Pending command to send.
* @param playerId Player whose client should send the command.
*/
void sendGameCommand(PendingCommand *pend, int playerId = -1);
/**
* @brief Send a single protobuf command.
*
* @param command Protobuf command message.
* @param playerId Player whose client should send the command.
*/
void sendGameCommand(const ::google::protobuf::Message &command, int playerId = -1);
/**
* @brief Called when a PendingCommand finishes execution.
*
* Used to detect server-side errors such as chat flood protection.
*/
void commandFinished(const Response &response);
/** @} */
signals:
/** @name Core state signals
* @{
*/
void emitUserEvent();
void containerProcessingStarted(GameEventContext context);
void containerProcessingDone();
void gameFlooded();
void setContextJudgeName(QString judgeName);
/** @} */
/** @name Player and spectator signals
* @{
*/
void addPlayerToAutoCompleteList(QString playerName);
void localPlayerDeckSelected(PlayerLogic *localPlayer, int playerId, ServerInfo_Player playerInfo);
void remotePlayerDeckSelected(QString deckList, int playerId, QString playerName);
void remotePlayersDecksSelected(QVector<QPair<int, QPair<QString, QString>>> opponentDecks);
void localPlayerSideboardLocked(int playerId, bool sideboardLocked);
void localPlayerReadyStateChanged(int playerId, bool ready);
/** @} */
/** @name Game flow signals
* @{
*/
void gameStopped();
void gameClosed();
void playerPropertiesChanged(const ServerInfo_PlayerProperties &prop, int playerId);
@ -109,11 +335,15 @@ signals:
void playerKicked();
void spectatorJoined(const ServerInfo_PlayerProperties &spectatorInfo);
void spectatorLeft(int leavingSpectatorId);
void gameFlooded();
void containerProcessingStarted(GameEventContext context);
void setContextJudgeName(QString judgeName);
void containerProcessingDone();
void arrowDeleted(int creatorId, int arrowId);
/** @} */
/** @name Logging signals
* Signals consumed by MessageLogWidget.
* @{
*/
void logSpectatorSay(ServerInfo_User userInfo, QString message);
void logSpectatorLeave(QString name, QString reason);
void logGameStart();
@ -132,6 +362,8 @@ signals:
void logActivePhaseChanged(int activePhase);
void logConcede(int playerId);
void logUnconcede(int playerId);
/** @} */
};
#endif // COCKATRICE_GAME_EVENT_HANDLER_H

View file

@ -1,11 +1,24 @@
/**
* @file player_event_handler.h
* @ingroup GameLogicPlayers
* @brief Player-scoped game event handler.
*
* PlayerEventHandler applies game events that affect a single Players
* board state, zones, cards, counters, arrows, and related UI/log output.
*
* It is invoked by GameEventHandler after basic routing and validation.
* Each instance is bound 1:1 to a Player and must never mutate state
* belonging to other players except where explicitly required by events
* (e.g. moving cards between players, attaching cards, arrows).
*
* This class is intentionally stateful and tightly coupled to Player,
* PlayerActions, and the board/zones implementation. It performs both
* model mutation and UI-side bookkeeping (zone views, arrows, menus).
*/
//! \todo Document this file.
#ifndef COCKATRICE_PLAYER_EVENT_HANDLER_H
#define COCKATRICE_PLAYER_EVENT_HANDLER_H
#include "event_processing_options.h"
#include <QObject>
@ -16,6 +29,7 @@
class CardItem;
class CardZoneLogic;
class PlayerLogic;
class Event_AttachCard;
class Event_ChangeZoneProperties;
class Event_CreateArrow;
@ -37,11 +51,177 @@ class Event_SetCounter;
class Event_Shuffle;
class Event_GameLogNotice;
/**
* @class PlayerEventHandler
* @brief Applies player-specific game events and emits corresponding log signals.
*
* Design notes:
* - All event handlers assume events are authoritative and already validated
* by the server.
* - Most handlers mutate both logical state (CardItem, CardZoneLogic, counters)
* and visual/UI state (views, arrows, menus).
* - Logging signals are emitted *after* or *during* state mutation, depending
* on whether later mutations would invalidate log data.
*/
class PlayerEventHandler : public QObject
{
Q_OBJECT
public:
/**
* @brief Construct a PlayerEventHandler bound to a Player.
* @param player Owning player instance.
*/
explicit PlayerEventHandler(PlayerLogic *player);
/** @name Event dispatch
* @{
*/
/**
* @brief Dispatch a generic GameEvent to the appropriate handler.
*
* This is the single entry point used by GameEventHandler. It extracts
* the correct protobuf extension and forwards the event to a typed
* handler method.
*
* @param type Game event type enum.
* @param event Generic protobuf container.
* @param context Additional context (undo, judge, etc.).
* @param options Processing options (UI suppression, reveal behavior).
*/
void processGameEvent(GameEvent::GameEventType type,
const GameEvent &event,
const GameEventContext &context,
EventProcessingOptions options);
/** @} */
/** @name Chat and randomization events
* @{
*/
/// Handle in-game chat messages from this player.
void eventGameSay(const Event_GameSay &event);
/// Handle zone shuffle events (typically libraries).
void eventShuffle(const Event_Shuffle &event);
/// Handle die roll events.
void eventRollDie(const Event_RollDie &event);
/** @} */
/** @name Arrow and targeting events
* @{
*/
/// Create a visual arrow between cards or players.
void eventCreateArrow(const Event_CreateArrow &event);
/// Delete an existing arrow.
void eventDeleteArrow(const Event_DeleteArrow &event);
/** @} */
/** @name Token and card creation
* @{
*/
/// Create a token card in a target zone.
void eventCreateToken(const Event_CreateToken &event);
/** @} */
/** @name Card attribute and counter updates
* @{
*/
/**
* @brief Set a card attribute (tapped, PT, annotation, etc.).
*
* May apply to a single card or all cards in a zone if no card ID
* is provided by the event.
*/
void
eventSetCardAttr(const Event_SetCardAttr &event, const GameEventContext &context, EventProcessingOptions options);
/// Update a counter attached to a card.
void eventSetCardCounter(const Event_SetCardCounter &event);
/// Create a player-level counter.
void eventCreateCounter(const Event_CreateCounter &event);
/// Set a player-level counter value.
void eventSetCounter(const Event_SetCounter &event);
/// Delete a player-level counter.
void eventDelCounter(const Event_DelCounter &event);
/** @} */
/** @name Zone-level operations
* @{
*/
/// Log a zone dump (e.g. reveal graveyard/library contents).
void eventDumpZone(const Event_DumpZone &event);
/**
* @brief Move a card between zones and/or players.
*
* This is one of the most complex handlers:
* - Removes the card from the start zone
* - Updates card identity and ownership if needed
* - Handles attachments and arrows
* - Emits appropriate move or undo-draw logs
* - Inserts the card into the target zone
*/
void eventMoveCard(const Event_MoveCard &event, const GameEventContext &context);
/// Flip a card face up or face down.
void eventFlipCard(const Event_FlipCard &event);
/// Destroy a card and clean up attachments.
void eventDestroyCard(const Event_DestroyCard &event);
/// Attach or detach a card to/from another card.
void eventAttachCard(const Event_AttachCard &event);
/** @} */
/** @name Draw and reveal operations
* @{
*/
/// Draw one or more cards from the deck.
void eventDrawCards(const Event_DrawCards &event);
/**
* @brief Reveal cards from a zone.
*
* Handles peeking, in-place top-card reveals, full reveal windows,
* and write-access granting.
*/
void eventRevealCards(const Event_RevealCards &event, EventProcessingOptions options);
/** @} */
/** @name Zone configuration
* @{
*/
/// Update zone visibility and reveal behavior.
void eventChangeZoneProperties(const Event_ChangeZoneProperties &event);
/** @} */
void eventGameLogNotice(const Event_GameLogNotice &event);
signals:
/** @name Logging signals
* @{
*/
void logSay(PlayerLogic *player, QString message);
void logShuffle(PlayerLogic *player, CardZoneLogic *zone, int start, int end);
void logRollDie(PlayerLogic *player, int sides, const QList<uint> &rolls);
@ -82,40 +262,13 @@ signals:
bool isLentToAnotherPlayer = false);
void logAlwaysRevealTopCard(PlayerLogic *player, CardZoneLogic *zone, bool reveal);
void logAlwaysLookAtTopCard(PlayerLogic *player, CardZoneLogic *zone, bool reveal);
/** @} */
void cardZoneChanged(CardItem *card, bool sameZone);
void requestCardMenuUpdate(const CardItem *card);
public:
PlayerEventHandler(PlayerLogic *player);
void processGameEvent(GameEvent::GameEventType type,
const GameEvent &event,
const GameEventContext &context,
EventProcessingOptions options);
void eventGameSay(const Event_GameSay &event);
void eventShuffle(const Event_Shuffle &event);
void eventRollDie(const Event_RollDie &event);
void eventCreateArrow(const Event_CreateArrow &event);
void eventDeleteArrow(const Event_DeleteArrow &event);
void eventCreateToken(const Event_CreateToken &event);
void
eventSetCardAttr(const Event_SetCardAttr &event, const GameEventContext &context, EventProcessingOptions options);
void eventSetCardCounter(const Event_SetCardCounter &event);
void eventCreateCounter(const Event_CreateCounter &event);
void eventSetCounter(const Event_SetCounter &event);
void eventDelCounter(const Event_DelCounter &event);
void eventDumpZone(const Event_DumpZone &event);
void eventMoveCard(const Event_MoveCard &event, const GameEventContext &context);
void eventFlipCard(const Event_FlipCard &event);
void eventDestroyCard(const Event_DestroyCard &event);
void eventAttachCard(const Event_AttachCard &event);
void eventDrawCards(const Event_DrawCards &event);
void eventRevealCards(const Event_RevealCards &event, EventProcessingOptions options);
void eventChangeZoneProperties(const Event_ChangeZoneProperties &event);
void eventGameLogNotice(const Event_GameLogNotice &event);
private:
/** Owning player instance. */
PlayerLogic *player;
void setCardAttrHelper(const GameEventContext &context,