Support starting games with fewer than max players (#5338)

This commit is contained in:
Zach H 2024-12-26 18:32:20 -05:00 committed by GitHub
parent 956c12eb32
commit 6dfd354973
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 50 additions and 16 deletions

View file

@ -5,4 +5,5 @@ message Command_ReadyStart {
optional Command_ReadyStart ext = 1016;
}
optional bool ready = 1;
optional bool force_start = 2;
}

View file

@ -81,7 +81,7 @@ Server_Game::Server_Game(const ServerInfo_User &_creatorInfo,
currentReplay->set_replay_id(room->getServer()->getDatabaseInterface()->getNextReplayId());
description = _description.simplified();
connect(this, SIGNAL(sigStartGameIfReady()), this, SLOT(doStartGameIfReady()), Qt::QueuedConnection);
connect(this, &Server_Game::sigStartGameIfReady, this, &Server_Game::doStartGameIfReady, Qt::QueuedConnection);
getInfo(*currentReplay->mutable_game_info());
@ -311,20 +311,31 @@ void Server_Game::sendGameStateToPlayers()
}
}
void Server_Game::doStartGameIfReady()
void Server_Game::doStartGameIfReady(bool forceStartGame)
{
Server_DatabaseInterface *databaseInterface = room->getServer()->getDatabaseInterface();
QMutexLocker locker(&gameMutex);
if (getPlayerCount() < maxPlayers)
if (getPlayerCount() < maxPlayers && !forceStartGame) {
return;
for (Server_Player *player : players.values()) {
if (!player->getReadyStart() && !player->getSpectator())
return;
}
for (Server_Player *player : players.values()) {
if (!player->getSpectator())
if (!player->getReadyStart() && !player->getSpectator()) {
if (forceStartGame) {
// Player is not ready to start, so kick them
// TODO: Move them to Spectators instead
kickPlayer(player->getPlayerId());
} else {
return;
}
}
}
for (Server_Player *player : players.values()) {
if (!player->getSpectator()) {
player->setupZones();
}
}
gameStarted = true;
@ -369,9 +380,9 @@ void Server_Game::doStartGameIfReady()
emit gameInfoChanged(gameInfo);
}
void Server_Game::startGameIfReady()
void Server_Game::startGameIfReady(bool forceStartGame)
{
emit sigStartGameIfReady();
emit sigStartGameIfReady(forceStartGame);
}
void Server_Game::stopGameIfFinished()

View file

@ -82,11 +82,11 @@ private:
bool withUserInfo);
void storeGameInformation();
signals:
void sigStartGameIfReady();
void sigStartGameIfReady(bool override);
void gameInfoChanged(ServerInfo_Game gameInfo);
private slots:
void pingClockTimeout();
void doStartGameIfReady();
void doStartGameIfReady(bool forceStartGame = false);
public:
#if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0))
@ -180,7 +180,7 @@ public:
void removeArrowsRelatedToPlayer(GameEventStorage &ges, Server_Player *player);
void unattachCards(GameEventStorage &ges, Server_Player *player);
bool kickPlayer(int playerId);
void startGameIfReady();
void startGameIfReady(bool forceStartGame);
void stopGameIfFinished();
int getActivePlayer() const
{

View file

@ -944,7 +944,7 @@ Server_Player::cmdReadyStart(const Command_ReadyStart &cmd, ResponseContainer &
return Response::RespContextError;
}
if (readyStart == cmd.ready()) {
if (readyStart == cmd.ready() && !cmd.force_start()) {
return Response::RespContextError;
}
@ -955,8 +955,13 @@ Server_Player::cmdReadyStart(const Command_ReadyStart &cmd, ResponseContainer &
ges.enqueueGameEvent(event, playerId);
ges.setGameEventContext(Context_ReadyStart());
if (cmd.ready()) {
game->startGameIfReady();
if (cmd.force_start()) {
if (game->getHostId() != playerId) {
return Response::RespFunctionNotAllowed;
}
game->startGameIfReady(true);
} else if (cmd.ready()) {
game->startGameIfReady(false);
}
return Response::RespOk;