From 64156cfa69923528bd2fcb0e79288947a0a272eb Mon Sep 17 00:00:00 2001 From: lotodore Date: Thu, 29 Dec 2011 21:19:06 +0000 Subject: [PATCH] Use generic PlayerData objects for no-longer-connected players when rejoining a game. This fixes ticket #88 (client patch only). --- src/net/clientthread.h | 1 + src/net/common/clientstate.cpp | 43 ++++++++++++--------------------- src/net/common/clientthread.cpp | 31 ++++++++++++++++++++++++ 3 files changed, 47 insertions(+), 28 deletions(-) diff --git a/src/net/clientthread.h b/src/net/clientthread.h index 2a8373c2..b6424cc5 100644 --- a/src/net/clientthread.h +++ b/src/net/clientthread.h @@ -175,6 +175,7 @@ protected: QtToolsInterface &GetQtToolsInterface(); + boost::shared_ptr CreatePlayerData(unsigned playerId, bool isGameAdmin); void AddPlayerData(boost::shared_ptr playerData); void RemovePlayerData(unsigned playerId, int removeReason); void ClearPlayerDataList(); diff --git a/src/net/common/clientstate.cpp b/src/net/common/clientstate.cpp index 1c255b53..da0ac7c9 100644 --- a/src/net/common/clientstate.cpp +++ b/src/net/common/clientstate.cpp @@ -34,6 +34,7 @@ #include #include +#include #include #include #include @@ -692,31 +693,7 @@ AbstractClientStateReceiving::HandlePacket(boost::shared_ptr clien // Another player joined the network game. GamePlayerJoined_t *netPlayerJoined = &netGamePlayer->gamePlayerNotification.choice.gamePlayerJoined; - boost::shared_ptr playerData; - PlayerInfo info; - if (client->GetCachedPlayerInfo(netPlayerJoined->playerId, info)) { - playerData.reset( - new PlayerData(netPlayerJoined->playerId, 0, info.ptype, - info.isGuest ? PLAYER_RIGHTS_GUEST : PLAYER_RIGHTS_NORMAL, netPlayerJoined->isGameAdmin)); - playerData->SetName(info.playerName); - if (info.hasAvatar) { - string avatarFile; - if (client->GetAvatarManager().GetAvatarFileName(info.avatar, avatarFile)) - playerData->SetAvatarFile(client->GetQtToolsInterface().stringToUtf8(avatarFile)); - else - client->RetrieveAvatarIfNeeded(netPlayerJoined->playerId, info); - } - } else { - ostringstream name; - name << "#" << netPlayerJoined->playerId; - - // Request player info. - client->RequestPlayerInfo(netPlayerJoined->playerId, true); - // Use temporary data until the PlayerInfo request is completed. - playerData.reset( - new PlayerData(netPlayerJoined->playerId, 0, PLAYER_TYPE_HUMAN, PLAYER_RIGHTS_NORMAL, netPlayerJoined->isGameAdmin)); - playerData->SetName(name.str()); - } + boost::shared_ptr playerData = client->CreatePlayerData(netPlayerJoined->playerId, netPlayerJoined->isGameAdmin != 0); client->AddPlayerData(playerData); } } else if (tmpPacket->GetMsg()->present == PokerTHMessage_PR_timeoutWarningMessage) { @@ -1527,6 +1504,7 @@ ClientStateWaitStart::InternalHandlePacket(boost::shared_ptr clien unsigned tmpHandId = 0; StartData startData; + PlayerIdList tmpPlayerList; startData.startDealerPlayerId = netGameStart->startDealerPlayerId; if (netGameStart->gameStartMode.present == gameStartMode_PR_gameStartModeInitial) { GameStartModeInitial_t *netStartModeInitial = &netGameStart->gameStartMode.choice.gameStartModeInitial; @@ -1541,7 +1519,7 @@ ClientStateWaitStart::InternalHandlePacket(boost::shared_ptr clien for (unsigned i = 0; i < numPlayers; i++) { unsigned playerId = *playerIds[i]; boost::shared_ptr tmpPlayer = client->GetPlayerDataByUniqueId(playerId); - if (!tmpPlayer.get()) + if (!tmpPlayer) throw ClientException(__FILE__, __LINE__, ERR_NET_UNKNOWN_PLAYER_ID, 0); tmpPlayer->SetNumber(i); } @@ -1561,8 +1539,13 @@ ClientStateWaitStart::InternalHandlePacket(boost::shared_ptr clien for (unsigned i = 0; i < numPlayers; i++) { RejoinPlayerData_t *playerData = playerInfos[i]; boost::shared_ptr tmpPlayer = client->GetPlayerDataByUniqueId(playerData->playerId); - if (!tmpPlayer.get()) - throw ClientException(__FILE__, __LINE__, ERR_NET_UNKNOWN_PLAYER_ID, 0); + if (!tmpPlayer) { + // If the player is not found: The corresponding session left. We need to create a generic player object. + // In order to have a complete seat list, we need all players, even those who left. + tmpPlayer = client->CreatePlayerData(playerData->playerId, false); + client->AddPlayerData(tmpPlayer); + tmpPlayerList.push_back(playerData->playerId); + } tmpPlayer->SetNumber(i); tmpPlayer->SetStartCash(playerData->playerMoney); } @@ -1573,6 +1556,10 @@ ClientStateWaitStart::InternalHandlePacket(boost::shared_ptr clien } client->InitGame(); client->GetGame()->setCurrentHandID(tmpHandId); + // We need to remove the temporary player data objects after creating the game. + BOOST_FOREACH(unsigned tmpPlayerId, tmpPlayerList) { + client->RemovePlayerData(tmpPlayerId, gamePlayerLeftReason_leftOnRequest); + } client->GetCallback().SignalNetClientGameInfo(MSG_NET_GAME_CLIENT_START); client->SetState(ClientStateWaitHand::Instance()); } diff --git a/src/net/common/clientthread.cpp b/src/net/common/clientthread.cpp index fde75674..b021651d 100644 --- a/src/net/common/clientthread.cpp +++ b/src/net/common/clientthread.cpp @@ -1044,6 +1044,37 @@ ClientThread::GetQtToolsInterface() return *myQtToolsInterface; } +boost::shared_ptr +ClientThread::CreatePlayerData(unsigned playerId, bool isGameAdmin) +{ + boost::shared_ptr playerData; + PlayerInfo info; + if (GetCachedPlayerInfo(playerId, info)) { + playerData.reset( + new PlayerData(playerId, 0, info.ptype, + info.isGuest ? PLAYER_RIGHTS_GUEST : PLAYER_RIGHTS_NORMAL, isGameAdmin)); + playerData->SetName(info.playerName); + if (info.hasAvatar) { + string avatarFile; + if (GetAvatarManager().GetAvatarFileName(info.avatar, avatarFile)) + playerData->SetAvatarFile(GetQtToolsInterface().stringToUtf8(avatarFile)); + else + RetrieveAvatarIfNeeded(playerId, info); + } + } else { + ostringstream name; + name << "#" << playerId; + + // Request player info. + RequestPlayerInfo(playerId, true); + // Use temporary data until the PlayerInfo request is completed. + playerData.reset( + new PlayerData(playerId, 0, PLAYER_TYPE_HUMAN, PLAYER_RIGHTS_NORMAL, isGameAdmin)); + playerData->SetName(name.str()); + } + return playerData; +} + void ClientThread::AddPlayerData(boost::shared_ptr playerData) {