From afdb385770a299854b865f532b66044f3fdd4fda Mon Sep 17 00:00:00 2001 From: ebbit1q Date: Sat, 24 Jan 2026 18:54:29 +0100 Subject: [PATCH] move returning cards to server_game (#6561) lock the game mutex instead of player mutex when returning cards --- .../remote/game/server_abstract_player.cpp | 45 +------------------ .../server/remote/game/server_game.cpp | 45 +++++++++++++++++++ .../network/server/remote/game/server_game.h | 1 + 3 files changed, 47 insertions(+), 44 deletions(-) diff --git a/libcockatrice_network/libcockatrice/network/server/remote/game/server_abstract_player.cpp b/libcockatrice_network/libcockatrice/network/server/remote/game/server_abstract_player.cpp index a5bb16d13..b08495bad 100644 --- a/libcockatrice_network/libcockatrice/network/server/remote/game/server_abstract_player.cpp +++ b/libcockatrice_network/libcockatrice/network/server/remote/game/server_abstract_player.cpp @@ -575,51 +575,8 @@ Server_AbstractPlayer::cmdConcede(const Command_Concede & /*cmd*/, ResponseConta setConceded(true); game->removeArrowsRelatedToPlayer(ges, this); game->unattachCards(ges, this); + game->returnCardsFromPlayer(ges, this); - playerMutex.lock(); - - // Return cards to their rightful owners before conceding the game - static const QRegularExpression ownerRegex{"Owner: ?([^\n]+)"}; - for (const auto &card : zones.value("table")->getCards()) { - if (card == nullptr) { - continue; - } - - const auto ®exResult = ownerRegex.match(card->getAnnotation()); - if (!regexResult.hasMatch()) { - continue; - } - - CardToMove cardToMove; - cardToMove.set_card_id(card->getId()); - - for (const auto *player : game->getPlayers()) { - if (player == nullptr || player->getUserInfo() == nullptr) { - continue; - } - - const auto &ownerToReturnTo = regexResult.captured(1); - const auto &correctOwner = QString::compare(QString::fromStdString(player->getUserInfo()->name()), - ownerToReturnTo, Qt::CaseInsensitive) == 0; - if (!correctOwner) { - continue; - } - - const auto &startZone = zones.value("table"); - const auto &targetZone = player->getZones().value("table"); - - if (startZone == nullptr || targetZone == nullptr) { - continue; - } - - moveCard(ges, startZone, QList() << &cardToMove, targetZone, 0, 0, false); - break; - } - } - - playerMutex.unlock(); - - // All borrowed cards have been returned, can now continue cleanup process clearZones(); Event_PlayerPropertiesChanged event; diff --git a/libcockatrice_network/libcockatrice/network/server/remote/game/server_game.cpp b/libcockatrice_network/libcockatrice/network/server/remote/game/server_game.cpp index c04876696..eae23dacf 100644 --- a/libcockatrice_network/libcockatrice/network/server/remote/game/server_game.cpp +++ b/libcockatrice_network/libcockatrice/network/server/remote/game/server_game.cpp @@ -23,6 +23,7 @@ #include "../server_database_interface.h" #include "../server_protocolhandler.h" #include "../server_room.h" +#include "libcockatrice/protocol/pb/command_move_card.pb.h" #include "server_abstract_player.h" #include "server_arrow.h" #include "server_card.h" @@ -31,6 +32,7 @@ #include "server_spectator.h" #include +#include #include #include #include @@ -824,3 +826,46 @@ void Server_Game::getInfo(ServerInfo_Game &result) const result.set_start_time(startTime.toSecsSinceEpoch()); } } + +void Server_Game::returnCardsFromPlayer(GameEventStorage &ges, Server_AbstractPlayer *player) +{ + QMutexLocker locker(&gameMutex); + // Return cards to their rightful owners before conceding the game + static const QRegularExpression ownerRegex{"Owner: ?([^\n]+)"}; + const auto &playerTable = player->getZones().value("table"); + for (const auto &card : playerTable->getCards()) { + if (card == nullptr) { + continue; + } + + const auto ®exResult = ownerRegex.match(card->getAnnotation()); + if (!regexResult.hasMatch()) { + continue; + } + + CardToMove cardToMove; + cardToMove.set_card_id(card->getId()); + + for (const auto *otherPlayer : getPlayers()) { + if (otherPlayer == nullptr || otherPlayer->getUserInfo() == nullptr) { + continue; + } + + const auto &ownerToReturnTo = regexResult.captured(1); + const auto &correctOwner = QString::compare(QString::fromStdString(otherPlayer->getUserInfo()->name()), + ownerToReturnTo, Qt::CaseInsensitive) == 0; + if (!correctOwner) { + continue; + } + + const auto &targetZone = otherPlayer->getZones().value("table"); + + if (playerTable == nullptr || targetZone == nullptr) { + continue; + } + + player->moveCard(ges, playerTable, QList() << &cardToMove, targetZone, 0, 0, false); + break; + } + } +} diff --git a/libcockatrice_network/libcockatrice/network/server/remote/game/server_game.h b/libcockatrice_network/libcockatrice/network/server/remote/game/server_game.h index 64374019c..1c658f2ba 100644 --- a/libcockatrice_network/libcockatrice/network/server/remote/game/server_game.h +++ b/libcockatrice_network/libcockatrice/network/server/remote/game/server_game.h @@ -218,6 +218,7 @@ public: GameEventStorageItem::EventRecipients recipients = GameEventStorageItem::SendToPrivate | GameEventStorageItem::SendToOthers, int privatePlayerId = -1); + void returnCardsFromPlayer(GameEventStorage &ges, Server_AbstractPlayer *player); }; #endif