[Server] Add match result strategy hook (#7131)

* [Server] Add match result strategy hook

Took 7 minutes

Took 18 minutes

* Rebase.

Took 2 minutes

Took 13 seconds

---------

Co-authored-by: Lukas Brübach <Bruebach.Lukas@bdosecurity.de>
This commit is contained in:
BruebachL
2026-08-23 18:37:15 +02:00
committed by GitHub
parent 25a9e37ff8
commit e2eb36f19f
4 changed files with 57 additions and 1 deletions

View File

@@ -14,6 +14,7 @@ set(HEADERS
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

View File

@@ -63,7 +63,9 @@ Server_Game::Server_Game(const GameConfig &config, Server_Room *_room)
startingLifeTotal(config.startingLifeTotal), shareDecklistsOnLoad(config.shareDecklistsOnLoad),
inactivityCounter(0), startTimeOfThisGame(0), secondsElapsed(0), firstGameStarted(false),
turnOrderReversed(false), startTime(QDateTime::currentDateTime()), pingClock(nullptr),
lifecycleStrategy(new Server_DefaultLifecycleStrategy), gameMutex()
deckValidationStrategy(new Server_DefaultDeckValidationStrategy),
lifecycleStrategy(new Server_DefaultLifecycleStrategy), matchResultStrategy(new Server_NullMatchResultStrategy),
gameMutex()
{
currentReplay = new GameReplay;
currentReplay->set_replay_id(room->getServer()->getDatabaseInterface()->getNextReplayId());
@@ -391,10 +393,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) {
@@ -410,6 +414,16 @@ void Server_Game::stopGameIfFinished()
sendGameStateToPlayers();
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;

View File

@@ -24,6 +24,7 @@
#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>
@@ -86,6 +87,8 @@ private:
QScopedPointer<Server_GameLifecycleStrategy> lifecycleStrategy;
QScopedPointer<Server_MatchResultStrategy> matchResultStrategy;
void createGameStateChangedEvent(Event_GameStateChanged *event,
Server_AbstractParticipant *recipient,
bool omniscient,

View File

@@ -0,0 +1,38 @@
#ifndef SERVER_MATCH_RESULT_STRATEGY_H
#define SERVER_MATCH_RESULT_STRATEGY_H
class Server_AbstractPlayer;
class Server_Game;
/**
* @brief Strategy hook invoked when a game has finished to decide the match result.
*
* Subclasses can report the match outcome (e.g. to a tournament backend) and decide
* whether the game should be closed permanently; the default implementation never
* closes the game, preserving the normal return-to-lobby behavior.
*/
class Server_MatchResultStrategy
{
public:
virtual ~Server_MatchResultStrategy() = default;
/**
* @brief Called when a game has finished.
* @return Whether the game has been decided and should be closed.
*/
virtual bool onGameFinished(Server_Game *game, int playing, Server_AbstractPlayer *lastPlayer) = 0;
};
/**
* @brief Default match result strategy that never closes the game.
*/
class Server_NullMatchResultStrategy : public Server_MatchResultStrategy
{
public:
bool onGameFinished(Server_Game *, int, Server_AbstractPlayer *) override
{
return false;
}
};
#endif