mirror of
https://github.com/Cockatrice/Cockatrice.git
synced 2026-01-15 14:34:04 -08:00
Create game as spectator (#4281)
* refactoring * allow for creation of games as spectator allow setting the amount of games per user to none remove limit on amount of games when creating a game as judge as spectator * refactor common/server_player.cpp * do not close games with spectating host automatically * remove check that filters out 0 player games this check didn't really do anything, deleted games are removed before it would be reached * don't transfer host to spectators this seems to cause a bug, also present on master
This commit is contained in:
@@ -93,9 +93,9 @@ Server_Game::~Server_Game()
|
||||
|
||||
gameClosed = true;
|
||||
sendGameEventContainer(prepareGameEvent(Event_GameClosed(), -1));
|
||||
QMapIterator<int, Server_Player *> playerIterator(players);
|
||||
while (playerIterator.hasNext())
|
||||
playerIterator.next().value()->prepareDestroy();
|
||||
for (Server_Player *player : players.values()) {
|
||||
player->prepareDestroy();
|
||||
}
|
||||
players.clear();
|
||||
|
||||
room->removeGame(this);
|
||||
@@ -131,9 +131,9 @@ void Server_Game::storeGameInformation()
|
||||
for (int i = gameInfo.game_types_size() - 1; i >= 0; --i)
|
||||
gameTypes.append(allGameTypes[gameInfo.game_types(i)]);
|
||||
|
||||
QSetIterator<QString> playerIterator(allPlayersEver);
|
||||
while (playerIterator.hasNext())
|
||||
replayMatchInfo->add_player_names(playerIterator.next().toStdString());
|
||||
for (auto playerName : allPlayersEver) {
|
||||
replayMatchInfo->add_player_names(playerName.toStdString());
|
||||
}
|
||||
|
||||
for (int i = 0; i < replayList.size(); ++i) {
|
||||
ServerInfo_Replay *replayInfo = replayMatchInfo->add_replay_list();
|
||||
@@ -142,23 +142,21 @@ void Server_Game::storeGameInformation()
|
||||
replayInfo->set_duration(replayList[i]->duration_seconds());
|
||||
}
|
||||
|
||||
QSet<QString> allUsersInGame = allPlayersEver + allSpectatorsEver;
|
||||
QSetIterator<QString> allUsersIterator(allUsersInGame);
|
||||
|
||||
SessionEvent *sessionEvent = Server_ProtocolHandler::prepareSessionEvent(replayEvent);
|
||||
Server *server = room->getServer();
|
||||
server->clientsLock.lockForRead();
|
||||
while (allUsersIterator.hasNext()) {
|
||||
Server_AbstractUserInterface *userHandler = server->findUser(allUsersIterator.next());
|
||||
for (auto userName : allPlayersEver + allSpectatorsEver) {
|
||||
Server_AbstractUserInterface *userHandler = server->findUser(userName);
|
||||
if (userHandler && server->getStoreReplaysEnabled())
|
||||
userHandler->sendProtocolItem(*sessionEvent);
|
||||
}
|
||||
server->clientsLock.unlock();
|
||||
delete sessionEvent;
|
||||
|
||||
if (server->getStoreReplaysEnabled())
|
||||
if (server->getStoreReplaysEnabled()) {
|
||||
server->getDatabaseInterface()->storeGameInformation(room->getName(), gameTypes, gameInfo, allPlayersEver,
|
||||
allSpectatorsEver, replayList);
|
||||
}
|
||||
}
|
||||
|
||||
void Server_Game::pingClockTimeout()
|
||||
@@ -175,20 +173,22 @@ void Server_Game::pingClockTimeout()
|
||||
if (player == nullptr)
|
||||
continue;
|
||||
|
||||
if (!player->getSpectator())
|
||||
if (!player->getSpectator()) {
|
||||
++playerCount;
|
||||
}
|
||||
|
||||
int oldPingTime = player->getPingTime();
|
||||
int newPingTime;
|
||||
player->playerMutex.lock();
|
||||
if (player->getUserInterface()) {
|
||||
newPingTime = player->getUserInterface()->getLastCommandTime();
|
||||
} else {
|
||||
newPingTime = -1;
|
||||
{
|
||||
QMutexLocker playerMutexLocker(&player->playerMutex);
|
||||
if (player->getUserInterface()) {
|
||||
newPingTime = player->getUserInterface()->getLastCommandTime();
|
||||
} else {
|
||||
newPingTime = -1;
|
||||
}
|
||||
}
|
||||
player->playerMutex.unlock();
|
||||
|
||||
if ((newPingTime != -1) && !player->getSpectator()) {
|
||||
if ((newPingTime != -1) && (!player->getSpectator() || player->getPlayerId() == hostId)) {
|
||||
allPlayersInactive = false;
|
||||
}
|
||||
|
||||
@@ -217,11 +217,11 @@ int Server_Game::getPlayerCount() const
|
||||
{
|
||||
QMutexLocker locker(&gameMutex);
|
||||
|
||||
QMapIterator<int, Server_Player *> playerIterator(players);
|
||||
int result = 0;
|
||||
while (playerIterator.hasNext())
|
||||
if (!playerIterator.next().value()->getSpectator())
|
||||
for (Server_Player *player : players.values()) {
|
||||
if (!player->getSpectator())
|
||||
++result;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -229,11 +229,11 @@ int Server_Game::getSpectatorCount() const
|
||||
{
|
||||
QMutexLocker locker(&gameMutex);
|
||||
|
||||
QMapIterator<int, Server_Player *> playerIterator(players);
|
||||
int result = 0;
|
||||
while (playerIterator.hasNext())
|
||||
if (playerIterator.next().value()->getSpectator())
|
||||
for (Server_Player *player : players.values()) {
|
||||
if (player->getSpectator())
|
||||
++result;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -250,9 +250,9 @@ void Server_Game::createGameStateChangedEvent(Event_GameStateChanged *event,
|
||||
} else
|
||||
event->set_game_started(false);
|
||||
|
||||
QMapIterator<int, Server_Player *> playerIterator(players);
|
||||
while (playerIterator.hasNext())
|
||||
playerIterator.next().value()->getInfo(event->add_player_list(), playerWhosAsking, omniscient, withUserInfo);
|
||||
for (Server_Player *otherPlayer : players.values()) {
|
||||
otherPlayer->getInfo(event->add_player_list(), playerWhosAsking, omniscient, withUserInfo);
|
||||
}
|
||||
}
|
||||
|
||||
void Server_Game::sendGameStateToPlayers()
|
||||
@@ -277,9 +277,7 @@ void Server_Game::sendGameStateToPlayers()
|
||||
createGameStateChangedEvent(&spectatorEvent, 0, false, false);
|
||||
|
||||
// send game state info to clients according to their role in the game
|
||||
QMapIterator<int, Server_Player *> playerIterator(players);
|
||||
while (playerIterator.hasNext()) {
|
||||
Server_Player *player = playerIterator.next().value();
|
||||
for (Server_Player *player : players.values()) {
|
||||
GameEventContainer *gec;
|
||||
if (player->getSpectator())
|
||||
gec = prepareGameEvent(spectatorEvent, -1);
|
||||
@@ -301,23 +299,17 @@ void Server_Game::doStartGameIfReady()
|
||||
|
||||
if (getPlayerCount() < maxPlayers)
|
||||
return;
|
||||
QMapIterator<int, Server_Player *> playerIterator(players);
|
||||
while (playerIterator.hasNext()) {
|
||||
Server_Player *p = playerIterator.next().value();
|
||||
if (!p->getReadyStart() && !p->getSpectator())
|
||||
for (Server_Player *player : players.values()) {
|
||||
if (!player->getReadyStart() && !player->getSpectator())
|
||||
return;
|
||||
}
|
||||
playerIterator.toFront();
|
||||
while (playerIterator.hasNext()) {
|
||||
Server_Player *p = playerIterator.next().value();
|
||||
if (!p->getSpectator())
|
||||
p->setupZones();
|
||||
for (Server_Player *player : players.values()) {
|
||||
if (!player->getSpectator())
|
||||
player->setupZones();
|
||||
}
|
||||
|
||||
gameStarted = true;
|
||||
playerIterator.toFront();
|
||||
while (playerIterator.hasNext()) {
|
||||
Server_Player *player = playerIterator.next().value();
|
||||
for (Server_Player *player : players.values()) {
|
||||
player->setConceded(false);
|
||||
player->setReadyStart(false);
|
||||
}
|
||||
@@ -367,11 +359,9 @@ void Server_Game::stopGameIfFinished()
|
||||
{
|
||||
QMutexLocker locker(&gameMutex);
|
||||
|
||||
QMapIterator<int, Server_Player *> playerIterator(players);
|
||||
int playing = 0;
|
||||
while (playerIterator.hasNext()) {
|
||||
Server_Player *p = playerIterator.next().value();
|
||||
if (!p->getConceded() && !p->getSpectator())
|
||||
for (Server_Player *player : players.values()) {
|
||||
if (!player->getConceded() && !player->getSpectator())
|
||||
++playing;
|
||||
}
|
||||
if (playing > 1)
|
||||
@@ -379,11 +369,9 @@ void Server_Game::stopGameIfFinished()
|
||||
|
||||
gameStarted = false;
|
||||
|
||||
playerIterator.toFront();
|
||||
while (playerIterator.hasNext()) {
|
||||
Server_Player *p = playerIterator.next().value();
|
||||
p->clearZones();
|
||||
p->setConceded(false);
|
||||
for (Server_Player *player : players.values()) {
|
||||
player->clearZones();
|
||||
player->setConceded(false);
|
||||
}
|
||||
|
||||
sendGameStateToPlayers();
|
||||
@@ -404,11 +392,9 @@ Response::ResponseCode Server_Game::checkJoin(ServerInfo_User *user,
|
||||
bool asJudge)
|
||||
{
|
||||
Server_DatabaseInterface *databaseInterface = room->getServer()->getDatabaseInterface();
|
||||
{
|
||||
QMapIterator<int, Server_Player *> playerIterator(players);
|
||||
while (playerIterator.hasNext())
|
||||
if (playerIterator.next().value()->getUserInfo()->name() == user->name())
|
||||
return Response::RespContextError;
|
||||
for (Server_Player *player : players.values()) {
|
||||
if (player->getUserInfo()->name() == user->name())
|
||||
return Response::RespContextError;
|
||||
}
|
||||
|
||||
if (asJudge && !(user->user_level() & ServerInfo_User::IsJudge)) {
|
||||
@@ -441,10 +427,10 @@ bool Server_Game::containsUser(const QString &userName) const
|
||||
{
|
||||
QMutexLocker locker(&gameMutex);
|
||||
|
||||
QMapIterator<int, Server_Player *> playerIterator(players);
|
||||
while (playerIterator.hasNext())
|
||||
if (playerIterator.next().value()->getUserInfo()->name() == userName.toStdString())
|
||||
for (Server_Player *player : players.values()) {
|
||||
if (player->getUserInfo()->name() == userName.toStdString())
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -466,14 +452,18 @@ void Server_Game::addPlayer(Server_AbstractUserInterface *userInterface,
|
||||
sendGameEventContainer(prepareGameEvent(joinEvent, -1));
|
||||
|
||||
const QString playerName = QString::fromStdString(newPlayer->getUserInfo()->name());
|
||||
if (spectator)
|
||||
allSpectatorsEver.insert(playerName);
|
||||
else
|
||||
allPlayersEver.insert(playerName);
|
||||
players.insert(newPlayer->getPlayerId(), newPlayer);
|
||||
if (newPlayer->getUserInfo()->name() == creatorInfo->name()) {
|
||||
hostId = newPlayer->getPlayerId();
|
||||
sendGameEventContainer(prepareGameEvent(Event_GameHostChanged(), hostId));
|
||||
if (spectator) {
|
||||
allSpectatorsEver.insert(playerName);
|
||||
} else {
|
||||
allPlayersEver.insert(playerName);
|
||||
|
||||
// if the original creator of the game joins, give them host status back
|
||||
// FIXME: transferring host to spectators has side effects
|
||||
if (newPlayer->getUserInfo()->name() == creatorInfo->name()) {
|
||||
hostId = newPlayer->getPlayerId();
|
||||
sendGameEventContainer(prepareGameEvent(Event_GameHostChanged(), hostId));
|
||||
}
|
||||
}
|
||||
|
||||
if (broadcastUpdate) {
|
||||
@@ -513,26 +503,24 @@ void Server_Game::removePlayer(Server_Player *player, Event_Leave::LeaveReason r
|
||||
bool spectator = player->getSpectator();
|
||||
player->prepareDestroy();
|
||||
|
||||
if (!getPlayerCount()) {
|
||||
gameClosed = true;
|
||||
deleteLater();
|
||||
return;
|
||||
} else if (!spectator) {
|
||||
if (playerHost) {
|
||||
int newHostId = -1;
|
||||
QMapIterator<int, Server_Player *> playerIterator(players);
|
||||
while (playerIterator.hasNext()) {
|
||||
Server_Player *p = playerIterator.next().value();
|
||||
if (!p->getSpectator()) {
|
||||
newHostId = p->getPlayerId();
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (newHostId != -1) {
|
||||
hostId = newHostId;
|
||||
sendGameEventContainer(prepareGameEvent(Event_GameHostChanged(), hostId));
|
||||
if (playerHost) {
|
||||
int newHostId = -1;
|
||||
for (Server_Player *otherPlayer : players.values()) {
|
||||
if (!otherPlayer->getSpectator()) {
|
||||
newHostId = otherPlayer->getPlayerId();
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (newHostId != -1) {
|
||||
hostId = newHostId;
|
||||
sendGameEventContainer(prepareGameEvent(Event_GameHostChanged(), hostId));
|
||||
} else {
|
||||
gameClosed = true;
|
||||
deleteLater();
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (!spectator) {
|
||||
stopGameIfFinished();
|
||||
if (gameStarted && playerActive)
|
||||
nextTurn();
|
||||
@@ -553,10 +541,8 @@ void Server_Game::removeArrowsRelatedToPlayer(GameEventStorage &ges, Server_Play
|
||||
// Remove all arrows of other players pointing to the player being removed or to one of his cards.
|
||||
// Also remove all arrows starting at one of his cards. This is necessary since players can create
|
||||
// arrows that start at another person's cards.
|
||||
QMapIterator<int, Server_Player *> playerIterator(players);
|
||||
while (playerIterator.hasNext()) {
|
||||
Server_Player *p = playerIterator.next().value();
|
||||
QList<Server_Arrow *> arrows = p->getArrows().values();
|
||||
for (Server_Player *otherPlayer : players.values()) {
|
||||
QList<Server_Arrow *> arrows = otherPlayer->getArrows().values();
|
||||
QList<Server_Arrow *> toDelete;
|
||||
for (int i = 0; i < arrows.size(); ++i) {
|
||||
Server_Arrow *a = arrows[i];
|
||||
@@ -574,9 +560,9 @@ void Server_Game::removeArrowsRelatedToPlayer(GameEventStorage &ges, Server_Play
|
||||
for (int i = 0; i < toDelete.size(); ++i) {
|
||||
Event_DeleteArrow event;
|
||||
event.set_arrow_id(toDelete[i]->getId());
|
||||
ges.enqueueGameEvent(event, p->getPlayerId());
|
||||
ges.enqueueGameEvent(event, otherPlayer->getPlayerId());
|
||||
|
||||
p->deleteArrow(toDelete[i]->getId());
|
||||
otherPlayer->deleteArrow(toDelete[i]->getId());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -586,15 +572,13 @@ void Server_Game::unattachCards(GameEventStorage &ges, Server_Player *player)
|
||||
QMutexLocker locker(&gameMutex);
|
||||
|
||||
QMapIterator<QString, Server_CardZone *> zoneIterator(player->getZones());
|
||||
while (zoneIterator.hasNext()) {
|
||||
Server_CardZone *zone = zoneIterator.next().value();
|
||||
for (int i = 0; i < zone->getCards().size(); ++i) {
|
||||
Server_Card *card = zone->getCards().at(i);
|
||||
|
||||
for (Server_CardZone *zone : player->getZones()) {
|
||||
for (Server_Card *card : zone->getCards()) {
|
||||
// Make a copy of the list because the original one gets modified during the loop
|
||||
QList<Server_Card *> attachedCards = card->getAttachedCards();
|
||||
for (int i = 0; i < attachedCards.size(); ++i)
|
||||
attachedCards[i]->getZone()->getPlayer()->unattachCard(ges, attachedCards[i]);
|
||||
for (Server_Card *attachedCard : attachedCards) {
|
||||
attachedCard->getZone()->getPlayer()->unattachCard(ges, attachedCard);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -633,9 +617,7 @@ void Server_Game::setActivePhase(int _activePhase)
|
||||
{
|
||||
QMutexLocker locker(&gameMutex);
|
||||
|
||||
QMapIterator<int, Server_Player *> playerIterator(players);
|
||||
while (playerIterator.hasNext()) {
|
||||
Server_Player *player = playerIterator.next().value();
|
||||
for (Server_Player *player : players.values()) {
|
||||
QList<Server_Arrow *> toDelete = player->getArrows().values();
|
||||
for (int i = 0; i < toDelete.size(); ++i) {
|
||||
Server_Arrow *a = toDelete[i];
|
||||
@@ -705,10 +687,9 @@ void Server_Game::createGameJoinedEvent(Server_Player *player, ResponseContainer
|
||||
event2.set_active_player_id(activePlayer);
|
||||
event2.set_active_phase(activePhase);
|
||||
|
||||
QMapIterator<int, Server_Player *> playerIterator(players);
|
||||
while (playerIterator.hasNext())
|
||||
playerIterator.next().value()->getInfo(event2.add_player_list(), player,
|
||||
player->getSpectator() && spectatorsSeeEverything, true);
|
||||
for (Server_Player *player : players.values()) {
|
||||
player->getInfo(event2.add_player_list(), player, player->getSpectator() && spectatorsSeeEverything, true);
|
||||
}
|
||||
|
||||
rc.enqueuePostResponseItem(ServerMessage::GAME_EVENT_CONTAINER, prepareGameEvent(event2, -1));
|
||||
}
|
||||
@@ -720,14 +701,12 @@ void Server_Game::sendGameEventContainer(GameEventContainer *cont,
|
||||
QMutexLocker locker(&gameMutex);
|
||||
|
||||
cont->set_game_id(gameId);
|
||||
QMapIterator<int, Server_Player *> playerIterator(players);
|
||||
while (playerIterator.hasNext()) {
|
||||
Server_Player *p = playerIterator.next().value();
|
||||
for (Server_Player *player : players.values()) {
|
||||
const bool playerPrivate =
|
||||
(p->getPlayerId() == privatePlayerId) || (p->getSpectator() && spectatorsSeeEverything);
|
||||
(player->getPlayerId() == privatePlayerId) || (player->getSpectator() && spectatorsSeeEverything);
|
||||
if ((recipients.testFlag(GameEventStorageItem::SendToPrivate) && playerPrivate) ||
|
||||
(recipients.testFlag(GameEventStorageItem::SendToOthers) && !playerPrivate))
|
||||
p->sendGameEvent(*cont);
|
||||
player->sendGameEvent(*cont);
|
||||
}
|
||||
if (recipients.testFlag(GameEventStorageItem::SendToPrivate)) {
|
||||
cont->set_seconds_elapsed(secondsElapsed - startTimeOfThisGame);
|
||||
@@ -760,11 +739,12 @@ void Server_Game::getInfo(ServerInfo_Game &result) const
|
||||
|
||||
result.set_room_id(room->getId());
|
||||
result.set_game_id(gameId);
|
||||
if (gameClosed)
|
||||
if (gameClosed) {
|
||||
result.set_closed(true);
|
||||
else {
|
||||
for (int i = 0; i < gameTypes.size(); ++i)
|
||||
result.add_game_types(gameTypes[i]);
|
||||
} else {
|
||||
for (auto type : gameTypes) {
|
||||
result.add_game_types(type);
|
||||
}
|
||||
|
||||
result.set_max_players(getMaxPlayers());
|
||||
result.set_description(getDescription().toStdString());
|
||||
|
||||
Reference in New Issue
Block a user