mirror of
https://github.com/Cockatrice/Cockatrice.git
synced 2026-09-21 09:05:10 -07:00
PR 0: introduce GameConfig, strategy pattern, and refactor Server_Game constructor
- Add GameConfig struct consolidating 14 construction parameters - Add strategy interfaces for deck validation, game lifecycle, and match results - Add Server_MatchGameFactory abstract factory (forward-looking for tournaments) - Replace 15-arg Server_Game constructor with (GameConfig, Server_Room*) - Wire default strategies into Server_Game with lifecycle/match hooks - Update server_protocolhandler to build GameConfig from protobuf - Update reverse_card_move_test to use new constructor - Update CMakeLists.txt with new headers Took 7 minutes Took 2 minutes
This commit is contained in:
parent
be6a783c12
commit
1c62588c38
10 changed files with 219 additions and 44 deletions
|
|
@ -10,7 +10,11 @@ set(HEADERS
|
|||
game/server_card.h
|
||||
game/server_cardzone.h
|
||||
game/server_counter.h
|
||||
game/game_config.h
|
||||
game/server_deck_validation_strategy.h
|
||||
game/server_game.h
|
||||
game/server_game_lifecycle_strategy.h
|
||||
game/server_match_result_strategy.h
|
||||
game/server_player.h
|
||||
game/server_spectator.h
|
||||
server.h
|
||||
|
|
|
|||
|
|
@ -0,0 +1,27 @@
|
|||
#ifndef GAME_CONFIG_H
|
||||
#define GAME_CONFIG_H
|
||||
|
||||
#include <QList>
|
||||
#include <QString>
|
||||
#include <libcockatrice/protocol/pb/serverinfo_user.pb.h>
|
||||
|
||||
class GameConfig
|
||||
{
|
||||
public:
|
||||
ServerInfo_User creatorInfo;
|
||||
int gameId = -1;
|
||||
QString description;
|
||||
QString password;
|
||||
int maxPlayers = 2;
|
||||
QList<int> gameTypes;
|
||||
bool onlyBuddies = false;
|
||||
bool onlyRegistered = false;
|
||||
bool spectatorsAllowed = false;
|
||||
bool spectatorsNeedPassword = false;
|
||||
bool spectatorsCanTalk = true;
|
||||
bool spectatorsSeeEverything = true;
|
||||
int startingLifeTotal = 20;
|
||||
bool shareDecklistsOnLoad = true;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
#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;
|
||||
|
||||
class Server_DeckValidationStrategy
|
||||
{
|
||||
public:
|
||||
virtual ~Server_DeckValidationStrategy() = default;
|
||||
|
||||
virtual Response::ResponseCode
|
||||
validate(Server_Game *game, Server_Player *player, DeckList *deck, ResponseContainer &rc) = 0;
|
||||
};
|
||||
|
||||
class Server_DefaultDeckValidationStrategy : public Server_DeckValidationStrategy
|
||||
{
|
||||
public:
|
||||
Response::ResponseCode validate(Server_Game *, Server_Player *, DeckList *, ResponseContainer &) override
|
||||
{
|
||||
return Response::RespOk;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -53,34 +53,22 @@
|
|||
#include <libcockatrice/protocol/pb/game_replay.pb.h>
|
||||
#include <libcockatrice/utility/zone_names.h>
|
||||
|
||||
Server_Game::Server_Game(const ServerInfo_User &_creatorInfo,
|
||||
int _gameId,
|
||||
const QString &_description,
|
||||
const QString &_password,
|
||||
int _maxPlayers,
|
||||
const QList<int> &_gameTypes,
|
||||
bool _onlyBuddies,
|
||||
bool _onlyRegistered,
|
||||
bool _spectatorsAllowed,
|
||||
bool _spectatorsNeedPassword,
|
||||
bool _spectatorsCanTalk,
|
||||
bool _spectatorsSeeEverything,
|
||||
int _startingLifeTotal,
|
||||
bool _shareDecklistsOnLoad,
|
||||
Server_Room *_room)
|
||||
: QObject(), room(_room), nextPlayerId(0), hostId(0), creatorInfo(new ServerInfo_User(_creatorInfo)),
|
||||
gameStarted(false), gameClosed(false), gameId(_gameId), password(_password), maxPlayers(_maxPlayers),
|
||||
gameTypes(_gameTypes), activePlayer(-1), activePhase(-1), onlyBuddies(_onlyBuddies),
|
||||
onlyRegistered(_onlyRegistered), spectatorsAllowed(_spectatorsAllowed),
|
||||
spectatorsNeedPassword(_spectatorsNeedPassword), spectatorsCanTalk(_spectatorsCanTalk),
|
||||
spectatorsSeeEverything(_spectatorsSeeEverything), startingLifeTotal(_startingLifeTotal),
|
||||
shareDecklistsOnLoad(_shareDecklistsOnLoad), inactivityCounter(0), startTimeOfThisGame(0), secondsElapsed(0),
|
||||
firstGameStarted(false), turnOrderReversed(false), startTime(QDateTime::currentDateTime()), pingClock(nullptr),
|
||||
Server_Game::Server_Game(const GameConfig &config, Server_Room *_room)
|
||||
: QObject(), room(_room), nextPlayerId(0), hostId(0), creatorInfo(new ServerInfo_User(config.creatorInfo)),
|
||||
gameStarted(false), gameClosed(false), gameId(config.gameId), description(config.description.simplified()),
|
||||
password(config.password), maxPlayers(config.maxPlayers), gameTypes(config.gameTypes), activePlayer(-1),
|
||||
activePhase(-1), onlyBuddies(config.onlyBuddies), onlyRegistered(config.onlyRegistered),
|
||||
spectatorsAllowed(config.spectatorsAllowed), spectatorsNeedPassword(config.spectatorsNeedPassword),
|
||||
spectatorsCanTalk(config.spectatorsCanTalk), spectatorsSeeEverything(config.spectatorsSeeEverything),
|
||||
startingLifeTotal(config.startingLifeTotal), shareDecklistsOnLoad(config.shareDecklistsOnLoad),
|
||||
inactivityCounter(0), startTimeOfThisGame(0), secondsElapsed(0), firstGameStarted(false),
|
||||
turnOrderReversed(false), startTime(QDateTime::currentDateTime()), pingClock(nullptr),
|
||||
deckValidationStrategy(new Server_DefaultDeckValidationStrategy),
|
||||
matchResultStrategy(new Server_NullMatchResultStrategy), lifecycleStrategy(new Server_DefaultLifecycleStrategy),
|
||||
gameMutex()
|
||||
{
|
||||
currentReplay = new GameReplay;
|
||||
currentReplay->set_replay_id(room->getServer()->getDatabaseInterface()->getNextReplayId());
|
||||
description = _description.simplified();
|
||||
|
||||
connect(this, &Server_Game::sigStartGameIfReady, this, &Server_Game::doStartGameIfReady, Qt::QueuedConnection);
|
||||
|
||||
|
|
@ -118,6 +106,10 @@ Server_Game::~Server_Game()
|
|||
for (auto *replay : replayList) {
|
||||
delete replay;
|
||||
}
|
||||
|
||||
delete deckValidationStrategy;
|
||||
delete matchResultStrategy;
|
||||
delete lifecycleStrategy;
|
||||
replayList.clear();
|
||||
|
||||
room = nullptr;
|
||||
|
|
@ -343,6 +335,13 @@ void Server_Game::doStartGameIfReady(bool forceStartGame)
|
|||
}
|
||||
|
||||
players = getPlayers(); // players could have been kicked, get new list of players
|
||||
|
||||
// Delegate pre-start logic (draft/tournament) to lifecycle strategy
|
||||
if (lifecycleStrategy->onGameStarting(this) == Server_GameLifecycleStrategy::StartAction::Handled) {
|
||||
locker.unlock();
|
||||
return;
|
||||
}
|
||||
|
||||
for (Server_AbstractPlayer *player : players.values()) {
|
||||
player->setupZones();
|
||||
}
|
||||
|
|
@ -400,10 +399,12 @@ void Server_Game::stopGameIfFinished()
|
|||
QMutexLocker locker(&gameMutex);
|
||||
|
||||
int playing = 0;
|
||||
Server_AbstractPlayer *lastPlayer = nullptr;
|
||||
auto players = getPlayers();
|
||||
for (auto *player : players.values()) {
|
||||
if (!player->getConceded()) {
|
||||
++playing;
|
||||
lastPlayer = player;
|
||||
}
|
||||
}
|
||||
if (playing > 1) {
|
||||
|
|
@ -419,6 +420,17 @@ void Server_Game::stopGameIfFinished()
|
|||
|
||||
sendGameStateToPlayers();
|
||||
|
||||
// Delegate post-game actions (e.g., tournament reporting) to the match result strategy
|
||||
bool matchDecided = matchResultStrategy->onGameFinished(this, playing, lastPlayer);
|
||||
if (matchDecided) {
|
||||
locker.unlock();
|
||||
|
||||
sendGameEventContainer(prepareGameEvent(Event_GameClosed(), -1));
|
||||
gameClosed = true;
|
||||
deleteLater();
|
||||
return;
|
||||
}
|
||||
|
||||
locker.unlock();
|
||||
|
||||
ServerInfo_Game gameInfo;
|
||||
|
|
@ -901,3 +913,11 @@ void Server_Game::returnCardsFromPlayer(GameEventStorage &ges, Server_AbstractPl
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Server_Game::setDeckValidationStrategy(Server_DeckValidationStrategy *strategy)
|
||||
{
|
||||
if (deckValidationStrategy) {
|
||||
delete deckValidationStrategy;
|
||||
}
|
||||
deckValidationStrategy = strategy;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,6 +21,10 @@
|
|||
#define SERVERGAME_H
|
||||
|
||||
#include "../server_response_containers.h"
|
||||
#include "game_config.h"
|
||||
#include "server_deck_validation_strategy.h"
|
||||
#include "server_game_lifecycle_strategy.h"
|
||||
#include "server_match_result_strategy.h"
|
||||
|
||||
#include <QDateTime>
|
||||
#include <QMap>
|
||||
|
|
@ -78,6 +82,10 @@ private:
|
|||
QList<GameReplay *> replayList;
|
||||
GameReplay *currentReplay;
|
||||
|
||||
Server_DeckValidationStrategy *deckValidationStrategy;
|
||||
Server_MatchResultStrategy *matchResultStrategy;
|
||||
Server_GameLifecycleStrategy *lifecycleStrategy;
|
||||
|
||||
void createGameStateChangedEvent(Event_GameStateChanged *event,
|
||||
Server_AbstractParticipant *recipient,
|
||||
bool omniscient,
|
||||
|
|
@ -92,21 +100,7 @@ private slots:
|
|||
|
||||
public:
|
||||
mutable QRecursiveMutex gameMutex;
|
||||
Server_Game(const ServerInfo_User &_creatorInfo,
|
||||
int _gameId,
|
||||
const QString &_description,
|
||||
const QString &_password,
|
||||
int _maxPlayers,
|
||||
const QList<int> &_gameTypes,
|
||||
bool _onlyBuddies,
|
||||
bool _onlyRegistered,
|
||||
bool _spectatorsAllowed,
|
||||
bool _spectatorsNeedPassword,
|
||||
bool _spectatorsCanTalk,
|
||||
bool _spectatorsSeeEverything,
|
||||
int _startingLifeTotal,
|
||||
bool _shareDecklistsOnLoad,
|
||||
Server_Room *parent);
|
||||
Server_Game(const GameConfig &config, Server_Room *parent);
|
||||
~Server_Game() override;
|
||||
Server_Room *getRoom() const
|
||||
{
|
||||
|
|
@ -221,6 +215,16 @@ public:
|
|||
GameEventStorageItem::SendToOthers,
|
||||
int privatePlayerId = -1);
|
||||
void returnCardsFromPlayer(GameEventStorage &ges, Server_AbstractPlayer *player);
|
||||
|
||||
Server_DeckValidationStrategy *getDeckValidationStrategy() const
|
||||
{
|
||||
return deckValidationStrategy;
|
||||
}
|
||||
Server_GameLifecycleStrategy *getLifecycleStrategy() const
|
||||
{
|
||||
return lifecycleStrategy;
|
||||
}
|
||||
void setDeckValidationStrategy(Server_DeckValidationStrategy *strategy);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -0,0 +1,29 @@
|
|||
#ifndef SERVER_GAME_LIFECYCLE_STRATEGY_H
|
||||
#define SERVER_GAME_LIFECYCLE_STRATEGY_H
|
||||
|
||||
class Server_Game;
|
||||
|
||||
class Server_GameLifecycleStrategy
|
||||
{
|
||||
public:
|
||||
virtual ~Server_GameLifecycleStrategy() = default;
|
||||
|
||||
enum class StartAction
|
||||
{
|
||||
ProceedNormal,
|
||||
Handled,
|
||||
};
|
||||
|
||||
virtual StartAction onGameStarting(Server_Game *game) = 0;
|
||||
};
|
||||
|
||||
class Server_DefaultLifecycleStrategy : public Server_GameLifecycleStrategy
|
||||
{
|
||||
public:
|
||||
StartAction onGameStarting(Server_Game *) override
|
||||
{
|
||||
return StartAction::ProceedNormal;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
#ifndef SERVER_MATCH_GAME_FACTORY_H
|
||||
#define SERVER_MATCH_GAME_FACTORY_H
|
||||
|
||||
class GameConfig;
|
||||
class Server_Game;
|
||||
class Server_AbstractUserInterface;
|
||||
|
||||
class Server_MatchGameFactory
|
||||
{
|
||||
public:
|
||||
virtual ~Server_MatchGameFactory() = default;
|
||||
|
||||
virtual Server_Game *createMatchGame(const GameConfig &config, int &outGameId) = 0;
|
||||
virtual Server_AbstractUserInterface *getUserInterface(const QString &playerName) = 0;
|
||||
virtual void addGameToRoom(Server_Game *game) = 0;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
#ifndef SERVER_MATCH_RESULT_STRATEGY_H
|
||||
#define SERVER_MATCH_RESULT_STRATEGY_H
|
||||
|
||||
class Server_AbstractPlayer;
|
||||
class Server_Game;
|
||||
|
||||
class Server_MatchResultStrategy
|
||||
{
|
||||
public:
|
||||
virtual ~Server_MatchResultStrategy() = default;
|
||||
|
||||
virtual bool onGameFinished(Server_Game *game, int playing, Server_AbstractPlayer *lastPlayer) = 0;
|
||||
};
|
||||
|
||||
class Server_NullMatchResultStrategy : public Server_MatchResultStrategy
|
||||
{
|
||||
public:
|
||||
bool onGameFinished(Server_Game *, int, Server_AbstractPlayer *) override
|
||||
{
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
#include "server_protocolhandler.h"
|
||||
|
||||
#include "game/game_config.h"
|
||||
#include "game/server_game.h"
|
||||
#include "game/server_player.h"
|
||||
#include "server_database_interface.h"
|
||||
|
|
@ -885,10 +886,23 @@ Server_ProtocolHandler::cmdCreateGame(const Command_CreateGame &cmd, Server_Room
|
|||
|
||||
// When server doesn't permit registered users to exist, do not honor only-reg setting
|
||||
bool onlyRegisteredUsers = cmd.only_registered() && (server->permitUnregisteredUsers());
|
||||
auto *game = new Server_Game(copyUserInfo(false), gameId, description, QString::fromStdString(cmd.password()),
|
||||
cmd.max_players(), gameTypes, cmd.only_buddies(), onlyRegisteredUsers,
|
||||
cmd.spectators_allowed(), cmd.spectators_need_password(), cmd.spectators_can_talk(),
|
||||
cmd.spectators_see_everything(), startingLifeTotal, shareDecklistsOnLoad, room);
|
||||
GameConfig config;
|
||||
config.creatorInfo = copyUserInfo(false);
|
||||
config.gameId = gameId;
|
||||
config.description = description;
|
||||
config.password = QString::fromStdString(cmd.password());
|
||||
config.maxPlayers = cmd.max_players();
|
||||
config.gameTypes = gameTypes;
|
||||
config.onlyBuddies = cmd.only_buddies();
|
||||
config.onlyRegistered = onlyRegisteredUsers;
|
||||
config.spectatorsAllowed = cmd.spectators_allowed();
|
||||
config.spectatorsNeedPassword = cmd.spectators_need_password();
|
||||
config.spectatorsCanTalk = cmd.spectators_can_talk();
|
||||
config.spectatorsSeeEverything = cmd.spectators_see_everything();
|
||||
config.startingLifeTotal = startingLifeTotal;
|
||||
config.shareDecklistsOnLoad = shareDecklistsOnLoad;
|
||||
|
||||
auto *game = new Server_Game(config, room);
|
||||
|
||||
game->addPlayer(this, rc, asSpectator, asJudge, false);
|
||||
room->addGame(game);
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
#include "game/game_config.h"
|
||||
#include "game/server_abstract_player.h"
|
||||
#include "game/server_card.h"
|
||||
#include "game/server_cardzone.h"
|
||||
|
|
@ -22,7 +23,12 @@ TEST(ReverseCardMoveTest, MoveCardFromBottomTest)
|
|||
// instantiate a fake server instance
|
||||
FakeServer server;
|
||||
Server_Room room(0, 0, "", "", "", "", false, "", {}, &server);
|
||||
Server_Game game(user, 1, "", "", 2, QList<int>(), false, false, false, false, false, false, 20, false, &room);
|
||||
GameConfig config;
|
||||
config.creatorInfo = user;
|
||||
config.gameId = 1;
|
||||
config.maxPlayers = 2;
|
||||
config.startingLifeTotal = 20;
|
||||
Server_Game game(config, &room);
|
||||
Server_AbstractPlayer player(&game, 1, user, false, nullptr);
|
||||
Server_CardZone deckZone(&player, ZoneNames::DECK, true, ServerInfo_Zone::PublicZone);
|
||||
Server_CardZone exileZone(&player, ZoneNames::EXILE, true, ServerInfo_Zone::PublicZone);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue