diff --git a/cockatrice/src/game/game_event_handler.cpp b/cockatrice/src/game/game_event_handler.cpp index bc68d4d7c..3cff144a9 100644 --- a/cockatrice/src/game/game_event_handler.cpp +++ b/cockatrice/src/game/game_event_handler.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #include #include @@ -158,6 +159,9 @@ void GameEventHandler::processGameEventContainer(const GameEventContainer &cont, case GameEvent::REVERSE_TURN: eventReverseTurn(event.GetExtension(Event_ReverseTurn::ext), playerId, context); break; + case GameEvent::TOURNAMENT_STATE: + emit tournamentStateChanged(event.GetExtension(Event_TournamentState::ext)); + break; default: { PlayerLogic *player = game->getPlayerManager()->getPlayers().value(playerId, 0); @@ -260,9 +264,15 @@ void GameEventHandler::eventSpectatorLeave(const Event_Leave &event, } void GameEventHandler::eventGameStateChanged(const Event_GameStateChanged &event, - int /*eventPlayerId*/, - const GameEventContext & /*context*/) + int /*eventPlayerId*/, + const GameEventContext & /*context*/) { + // Sub-games of a tournament report their parent hub game so the client can + // route "close game" back to the parent tab. + if (event.parent_game_id() != -1) { + game->getGameMetaInfo()->setParentGameId(event.parent_game_id()); + } + const int playerListSize = event.player_list_size(); QVector>> opponentDecksToDisplay; diff --git a/cockatrice/src/game/game_event_handler.h b/cockatrice/src/game/game_event_handler.h index 99277abb7..7914a3228 100644 --- a/cockatrice/src/game/game_event_handler.h +++ b/cockatrice/src/game/game_event_handler.h @@ -43,6 +43,7 @@ class Event_SetActivePhase; class Event_GameSay; class Event_Kicked; class Event_ReverseTurn; +class Event_TournamentState; class Event_Ping; inline Q_LOGGING_CATEGORY(GameEventHandlerLog, "game_event_handler"); @@ -329,6 +330,7 @@ signals: void gameStopped(); void gameClosed(); + void tournamentStateChanged(const Event_TournamentState &state); void playerPropertiesChanged(const ServerInfo_PlayerProperties &prop, int playerId); void playerJoined(const ServerInfo_PlayerProperties &playerInfo); void playerLeft(int leavingPlayerId); diff --git a/cockatrice/src/game/game_meta_info.h b/cockatrice/src/game/game_meta_info.h index cdba1605f..8585238bd 100644 --- a/cockatrice/src/game/game_meta_info.h +++ b/cockatrice/src/game/game_meta_info.h @@ -84,6 +84,26 @@ public: return roomGameTypes.find(gameInfo_.game_types(index)).value(); } + bool isTournament() const + { + return gameInfo_.is_tournament(); + } + + void setIsTournament(bool t) + { + gameInfo_.set_is_tournament(t); + } + + int parentGameId() const + { + return parentGameId_; + } + + void setParentGameId(int id) + { + parentGameId_ = id; + } + public slots: void setStarted(bool s) { @@ -108,6 +128,7 @@ signals: private: ServerInfo_Game gameInfo_; + int parentGameId_ = -1; }; #endif // GAME_META_INFO_H diff --git a/cockatrice/src/game/player/player_event_handler.h b/cockatrice/src/game/player/player_event_handler.h index 48ad85e88..1e9814ddb 100644 --- a/cockatrice/src/game/player/player_event_handler.h +++ b/cockatrice/src/game/player/player_event_handler.h @@ -90,10 +90,10 @@ public: * @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); + virtual void processGameEvent(GameEvent::GameEventType type, + const GameEvent &event, + const GameEventContext &context, + EventProcessingOptions options); /** @} */ @@ -266,7 +266,7 @@ signals: void cardZoneChanged(CardItem *card, bool sameZone); void requestCardMenuUpdate(const CardItem *card); -private: +protected: /** Owning player instance. */ PlayerLogic *player; diff --git a/cockatrice/src/game/player/player_logic.cpp b/cockatrice/src/game/player/player_logic.cpp index 45ba09aac..084f3df30 100644 --- a/cockatrice/src/game/player/player_logic.cpp +++ b/cockatrice/src/game/player/player_logic.cpp @@ -37,6 +37,19 @@ PlayerLogic::PlayerLogic(const ServerInfo_User &info, int _id, bool _local, bool initializeZones(); } +PlayerLogic::PlayerLogic(const ServerInfo_User &info, + int _id, + bool _local, + bool _judge, + AbstractGame *_parent, + PlayerEventHandler *customEventHandler) + : QObject(_parent), game(_parent), playerInfo(new PlayerInfo(info, _id, _local, _judge)), + playerEventHandler(customEventHandler), playerActions(new PlayerActions(this)), active(false), conceded(false), + zoneId(0), dialogSemaphore(false) +{ + initializeZones(); +} + void PlayerLogic::initializeZones() { addZone(new PileZoneLogic(this, ZoneNames::DECK, false, true, false, this)); diff --git a/cockatrice/src/game/player/player_logic.h b/cockatrice/src/game/player/player_logic.h index 6923b3afe..26cd63f50 100644 --- a/cockatrice/src/game/player/player_logic.h +++ b/cockatrice/src/game/player/player_logic.h @@ -99,7 +99,30 @@ public: PlayerLogic(const ServerInfo_User &info, int _id, bool _local, bool _judge, AbstractGame *_parent); ~PlayerLogic() override; - void initializeZones(); +protected: + /** + * @brief Constructor for subclasses that need a custom event handler (e.g. DraftPlayerLogic). + * + * @p customEventHandler must be non-null and either QObject-parented to this PlayerLogic + * or deleted externally; it is not owned by PlayerLogic. The handler connects to @c player + * during its own constructor, so passing a freshly built subclass handler from an + * initializer list is safe. + */ + PlayerLogic(const ServerInfo_User &info, + int _id, + bool _local, + bool _judge, + AbstractGame *_parent, + PlayerEventHandler *customEventHandler); + +public: + /** + * @brief Creates the standard zone set. + * + * Not virtually dispatched from constructors — subclasses overriding this must add + * their extra zones in their own constructor body. + */ + virtual void initializeZones(); void updateZones(); void clear();