[Server] Add deck validation strategy interface (#7129)
Some checks are pending
Build Desktop / Configure (push) Waiting to run
Build Desktop / Debian 13 (push) Blocked by required conditions
Build Desktop / Debian 12 (push) Blocked by required conditions
Build Desktop / Fedora 44 (push) Blocked by required conditions
Build Desktop / Fedora 43 (push) Blocked by required conditions
Build Desktop / Servatrice_Debian 12 (push) Blocked by required conditions
Build Desktop / Ubuntu 26.04 (push) Blocked by required conditions
Build Desktop / Ubuntu 24.04 (push) Blocked by required conditions
Build Desktop / Arch (push) Blocked by required conditions
Build Desktop / macOS 14 (push) Blocked by required conditions
Build Desktop / macOS 15 (push) Blocked by required conditions
Build Desktop / macOS 13 Intel (push) Blocked by required conditions
Build Desktop / macOS 15 Debug (push) Blocked by required conditions
Build Desktop / Windows 10 (push) Blocked by required conditions
Build Docker Image / amd64 & arm64 (push) Waiting to run

Co-authored-by: Lukas Brübach <Bruebach.Lukas@bdosecurity.de>
This commit is contained in:
BruebachL 2026-08-17 11:21:25 +02:00 committed by GitHub
parent a8bacc5296
commit 08d6b51db9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 65 additions and 1 deletions

View file

@ -11,6 +11,7 @@ set(HEADERS
game/server_cardzone.h game/server_cardzone.h
game/server_counter.h game/server_counter.h
game/game_config.h game/game_config.h
game/server_deck_validation_strategy.h
game/server_game.h game/server_game.h
game/server_player.h game/server_player.h
game/server_spectator.h game/server_spectator.h

View file

@ -0,0 +1,45 @@
#ifndef SERVER_DECK_VALIDATION_STRATEGY_H
#define SERVER_DECK_VALIDATION_STRATEGY_H
#include <libcockatrice/protocol/pb/response.pb.h>
class DeckList;
class Server_Game;
class Server_Player;
class ResponseContainer;
/**
* @brief Strategy for validating a player's deck before it is loaded into a game.
*
* Subclasses decide whether a deck may be accepted; the default implementation
* accepts every deck.
*/
class Server_DeckValidationStrategy
{
public:
virtual ~Server_DeckValidationStrategy() = default;
/**
* @brief Validate @p deck for @p player in @p game.
*
* @p rc is an out parameter used to attach the response details for a rejected
* deck (e.g. an error response extension via ResponseContainer::setResponseExtension).
* @return Response::RespOk when the deck is accepted, an error code otherwise.
*/
virtual Response::ResponseCode
validate(Server_Game *game, Server_Player *player, DeckList *deck, ResponseContainer &rc) = 0;
};
/**
* @brief Default deck validation strategy that accepts every deck.
*/
class Server_DefaultDeckValidationStrategy : public Server_DeckValidationStrategy
{
public:
Response::ResponseCode validate(Server_Game *, Server_Player *, DeckList *, ResponseContainer &) override
{
return Response::RespOk;
}
};
#endif

View file

@ -62,7 +62,8 @@ Server_Game::Server_Game(const GameConfig &config, Server_Room *_room)
spectatorsCanTalk(config.spectatorsCanTalk), spectatorsSeeEverything(config.spectatorsSeeEverything), spectatorsCanTalk(config.spectatorsCanTalk), spectatorsSeeEverything(config.spectatorsSeeEverything),
startingLifeTotal(config.startingLifeTotal), shareDecklistsOnLoad(config.shareDecklistsOnLoad), startingLifeTotal(config.startingLifeTotal), shareDecklistsOnLoad(config.shareDecklistsOnLoad),
inactivityCounter(0), startTimeOfThisGame(0), secondsElapsed(0), firstGameStarted(false), inactivityCounter(0), startTimeOfThisGame(0), secondsElapsed(0), firstGameStarted(false),
turnOrderReversed(false), startTime(QDateTime::currentDateTime()), pingClock(nullptr), gameMutex() turnOrderReversed(false), startTime(QDateTime::currentDateTime()), pingClock(nullptr),
deckValidationStrategy(new Server_DefaultDeckValidationStrategy), gameMutex()
{ {
currentReplay = new GameReplay; currentReplay = new GameReplay;
currentReplay->set_replay_id(room->getServer()->getDatabaseInterface()->getNextReplayId()); currentReplay->set_replay_id(room->getServer()->getDatabaseInterface()->getNextReplayId());
@ -886,3 +887,8 @@ void Server_Game::returnCardsFromPlayer(GameEventStorage &ges, Server_AbstractPl
} }
} }
} }
void Server_Game::setDeckValidationStrategy(Server_DeckValidationStrategy *strategy)
{
deckValidationStrategy.reset(strategy);
}

View file

@ -22,11 +22,13 @@
#include "../server_response_containers.h" #include "../server_response_containers.h"
#include "game_config.h" #include "game_config.h"
#include "server_deck_validation_strategy.h"
#include <QDateTime> #include <QDateTime>
#include <QMap> #include <QMap>
#include <QMutex> #include <QMutex>
#include <QObject> #include <QObject>
#include <QScopedPointer>
#include <QSet> #include <QSet>
#include <QStringList> #include <QStringList>
#include <libcockatrice/protocol/pb/event_leave.pb.h> #include <libcockatrice/protocol/pb/event_leave.pb.h>
@ -79,6 +81,8 @@ private:
QList<GameReplay *> replayList; QList<GameReplay *> replayList;
GameReplay *currentReplay; GameReplay *currentReplay;
QScopedPointer<Server_DeckValidationStrategy> deckValidationStrategy;
void createGameStateChangedEvent(Event_GameStateChanged *event, void createGameStateChangedEvent(Event_GameStateChanged *event,
Server_AbstractParticipant *recipient, Server_AbstractParticipant *recipient,
bool omniscient, bool omniscient,
@ -208,6 +212,14 @@ public:
GameEventStorageItem::SendToOthers, GameEventStorageItem::SendToOthers,
int privatePlayerId = -1); int privatePlayerId = -1);
void returnCardsFromPlayer(GameEventStorage &ges, Server_AbstractPlayer *player); void returnCardsFromPlayer(GameEventStorage &ges, Server_AbstractPlayer *player);
/** @brief Get the current deck validation strategy (non-owning). */
Server_DeckValidationStrategy *getDeckValidationStrategy() const
{
return deckValidationStrategy.data();
}
/** @brief Replace the deck validation strategy; takes ownership of @p strategy. */
void setDeckValidationStrategy(Server_DeckValidationStrategy *strategy);
}; };
#endif #endif