From ad961de45d00b0d0d657d70c0431d6bfe392b7e7 Mon Sep 17 00:00:00 2001 From: lotodore Date: Sun, 23 Oct 2011 09:13:04 +0000 Subject: [PATCH] Polishing rejoin implementation. --- src/net/common/servergamestate.cpp | 260 ++++++++++++++--------------- src/net/servergamestate.h | 5 + 2 files changed, 132 insertions(+), 133 deletions(-) diff --git a/src/net/common/servergamestate.cpp b/src/net/common/servergamestate.cpp index 5a0f3848..a05f3862 100644 --- a/src/net/common/servergamestate.cpp +++ b/src/net/common/servergamestate.cpp @@ -371,6 +371,53 @@ AbstractServerGameStateReceiving::CreateNetPacketPlayerJoined(unsigned gameId, c return packet; } +boost::shared_ptr +AbstractServerGameStateReceiving::CreateNetPacketJoinGameAck(const ServerGame &server, const PlayerData &playerData) +{ + boost::shared_ptr packet(new NetPacket(NetPacket::Alloc)); + packet->GetMsg()->present = PokerTHMessage_PR_joinGameReplyMessage; + JoinGameReplyMessage_t *netJoinReply = &packet->GetMsg()->choice.joinGameReplyMessage; + netJoinReply->gameId = server.GetId(); + netJoinReply->joinGameResult.present = joinGameResult_PR_joinGameAck; + JoinGameAck_t *joinAck = &netJoinReply->joinGameResult.choice.joinGameAck; + joinAck->areYouGameAdmin = static_cast(playerData.IsGameAdmin()); + + NetPacket::SetGameData(server.GetGameData(), &joinAck->gameInfo); + OCTET_STRING_fromBuf( + &joinAck->gameInfo.gameName, + server.GetName().c_str(), + (int)server.GetName().length()); + return packet; +} + +void +AbstractServerGameStateReceiving::AcceptNewSession(boost::shared_ptr server, boost::shared_ptr session) +{ + // Set game admin, if applicable. + session->GetPlayerData()->SetGameAdmin(session->GetPlayerData()->GetUniqueId() == server->GetAdminPlayerId()); + + // Send ack to client. + server->GetLobbyThread().GetSender().Send(session, CreateNetPacketJoinGameAck(*server, *session->GetPlayerData())); + + // Send notifications for connected players to client. + PlayerDataList tmpPlayerList(server->GetFullPlayerDataList()); + PlayerDataList::iterator player_i = tmpPlayerList.begin(); + PlayerDataList::iterator player_end = tmpPlayerList.end(); + while (player_i != player_end) { + server->GetLobbyThread().GetSender().Send(session, CreateNetPacketPlayerJoined(server->GetId(), *(*player_i))); + ++player_i; + } + + // Send "Player Joined" to other fully connected clients. + server->SendToAllPlayers(CreateNetPacketPlayerJoined(server->GetId(), *session->GetPlayerData()), SessionData::Game); + + // Accept session. + server->GetSessionManager().AddSession(session); + + // Notify lobby. + server->GetLobbyThread().NotifyPlayerJoinedGame(server->GetId(), session->GetPlayerData()->GetUniqueId()); +} + //----------------------------------------------------------------------------- ServerGameStateInit ServerGameStateInit::s_state; @@ -424,41 +471,8 @@ ServerGameStateInit::HandleNewSession(boost::shared_ptr server, boos if (server->GetCurNumberOfPlayers() >= tmpGameData.maxNumberOfPlayers) { server->MoveSessionToLobby(session, NTF_NET_REMOVED_GAME_FULL); } else { - session->GetPlayerData()->SetGameAdmin(session->GetPlayerData()->GetUniqueId() == server->GetAdminPlayerId()); - // Send ack to client. - boost::shared_ptr packet(new NetPacket(NetPacket::Alloc)); - packet->GetMsg()->present = PokerTHMessage_PR_joinGameReplyMessage; - JoinGameReplyMessage_t *netJoinReply = &packet->GetMsg()->choice.joinGameReplyMessage; - netJoinReply->gameId = server->GetId(); - netJoinReply->joinGameResult.present = joinGameResult_PR_joinGameAck; - JoinGameAck_t *joinAck = &netJoinReply->joinGameResult.choice.joinGameAck; - joinAck->areYouGameAdmin = static_cast(session->GetPlayerData()->IsGameAdmin()); - - NetPacket::SetGameData(server->GetGameData(), &joinAck->gameInfo); - OCTET_STRING_fromBuf( - &joinAck->gameInfo.gameName, - server->GetName().c_str(), - (int)server->GetName().length()); - server->GetLobbyThread().GetSender().Send(session, packet); - - // Send notifications for connected players to client. - PlayerDataList tmpPlayerList(server->GetFullPlayerDataList()); - PlayerDataList::iterator player_i = tmpPlayerList.begin(); - PlayerDataList::iterator player_end = tmpPlayerList.end(); - while (player_i != player_end) { - server->GetLobbyThread().GetSender().Send(session, CreateNetPacketPlayerJoined(server->GetId(), *(*player_i))); - ++player_i; - } - - // Send "Player Joined" to other fully connected clients. - server->SendToAllPlayers(CreateNetPacketPlayerJoined(server->GetId(), *session->GetPlayerData()), SessionData::Game); - - // Accept session. - server->GetSessionManager().AddSession(session); - - // Notify lobby. - server->GetLobbyThread().NotifyPlayerJoinedGame(server->GetId(), session->GetPlayerData()->GetUniqueId()); + AcceptNewSession(server, session); if (server->GetCurNumberOfPlayers() == tmpGameData.maxNumberOfPlayers) { // Automatically start the game if it is full. @@ -755,50 +769,15 @@ AbstractServerGameStateRunning::HandleNewSession(boost::shared_ptr s { // Verify that the user is allowed to rejoin. - boost::shared_ptr tmpPlayer = server->GetPlayerInterfaceFromGame(session->GetPlayerData()->GetName()); - if (tmpPlayer && tmpPlayer->getMyGuid() == session->GetPlayerData()->GetOldGuid()) { - // Perform rejoin at hand start. - // Send ack to client. - // TODO this code is partly copy & paste. - { - boost::shared_ptr packet(new NetPacket(NetPacket::Alloc)); - packet->GetMsg()->present = PokerTHMessage_PR_joinGameReplyMessage; - JoinGameReplyMessage_t *netJoinReply = &packet->GetMsg()->choice.joinGameReplyMessage; - netJoinReply->gameId = server->GetId(); - netJoinReply->joinGameResult.present = joinGameResult_PR_joinGameAck; - JoinGameAck_t *joinAck = &netJoinReply->joinGameResult.choice.joinGameAck; - joinAck->areYouGameAdmin = static_cast(session->GetPlayerData()->IsGameAdmin()); + if (session && session->GetPlayerData()) { + boost::shared_ptr tmpPlayer = server->GetPlayerInterfaceFromGame(session->GetPlayerData()->GetName()); + if (tmpPlayer && tmpPlayer->getMyGuid() == session->GetPlayerData()->GetOldGuid()) { + // The player wants to rejoin. + AcceptNewSession(server, session); + // Remember: We need to initiate a rejoin when starting the next hand. + server->AddRejoinPlayer(session->GetPlayerData()->GetUniqueId()); - NetPacket::SetGameData(server->GetGameData(), &joinAck->gameInfo); - OCTET_STRING_fromBuf( - &joinAck->gameInfo.gameName, - server->GetName().c_str(), - (int)server->GetName().length()); - server->GetLobbyThread().GetSender().Send(session, packet); - } - - // Send notifications for connected players to client. - PlayerDataList tmpPlayerList = server->GetFullPlayerDataList(); - PlayerDataList::iterator player_i = tmpPlayerList.begin(); - PlayerDataList::iterator player_end = tmpPlayerList.end(); - while (player_i != player_end) { - server->GetLobbyThread().GetSender().Send(session, CreateNetPacketPlayerJoined(server->GetId(), *(*player_i))); - ++player_i; - } - - // Send "Player Joined" to other fully connected clients. - server->SendToAllPlayers(CreateNetPacketPlayerJoined(server->GetId(), *session->GetPlayerData()), SessionData::Game); - - // Accept session. - server->GetSessionManager().AddSession(session); - // Remember: We need to initiate a rejoin when starting the next hand. - server->AddRejoinPlayer(session->GetPlayerData()->GetUniqueId()); - - // Notify lobby. - server->GetLobbyThread().NotifyPlayerJoinedGame(server->GetId(), session->GetPlayerData()->GetUniqueId()); - - // Send start event right away. - { + // Send start event right away. boost::shared_ptr packet(new NetPacket(NetPacket::Alloc)); packet->GetMsg()->present = PokerTHMessage_PR_startEventMessage; StartEventMessage_t *netStartEvent = &packet->GetMsg()->choice.startEventMessage; @@ -807,10 +786,10 @@ AbstractServerGameStateRunning::HandleNewSession(boost::shared_ptr s // Wait for rejoining player to confirm start of game. server->GetLobbyThread().GetSender().Send(session, packet); + } else { + // Do not accept "new" sessions in this state, only rejoin is allowed. + server->MoveSessionToLobby(session, NTF_NET_REMOVED_ALREADY_RUNNING); } - } else { - // Do not accept "new" sessions in this state, only rejoin is allowed. - server->MoveSessionToLobby(session, NTF_NET_REMOVED_ALREADY_RUNNING); } } @@ -1136,59 +1115,8 @@ ServerGameStateHand::StartNewHand(boost::shared_ptr server) Game &curGame = server->GetGame(); // Initialize rejoining players. - { - PlayerIdList rejoinIdList(server->GetAndResetRejoinPlayers()); - PlayerIdList::iterator i = rejoinIdList.begin(); - PlayerIdList::iterator end = rejoinIdList.end(); - while (i != end) { - boost::shared_ptr session(server->GetSessionManager().GetSessionByUniquePlayerId(*i)); - if (session) { - // Set new player id. - boost::shared_ptr rejoinPlayer = curGame.getPlayerByName(session->GetPlayerData()->GetName()); - if (rejoinPlayer) { - // Notify other clients about id change. - boost::shared_ptr packet(new NetPacket(NetPacket::Alloc)); - packet->GetMsg()->present = PokerTHMessage_PR_playerIdChangedMessage; - PlayerIdChangedMessage_t *netIdChanged = &packet->GetMsg()->choice.playerIdChangedMessage; - netIdChanged->oldPlayerId = rejoinPlayer->getMyUniqueID(); - netIdChanged->newPlayerId = session->GetPlayerData()->GetUniqueId(); - server->SendToAllButOnePlayers(packet, session->GetId(), SessionData::Game); - - // Update the dealer, if necessary. - curGame.replaceDealer(rejoinPlayer->getMyUniqueID(), session->GetPlayerData()->GetUniqueId()); - // Change the Id in the poker engine. - rejoinPlayer->setMyUniqueID(session->GetPlayerData()->GetUniqueId()); - rejoinPlayer->setIsConnected(true); - - // Send game start notification to rejoining client. - packet.reset(new NetPacket(NetPacket::Alloc)); - packet->GetMsg()->present = PokerTHMessage_PR_gameStartMessage; - GameStartMessage_t *netGameStart = &packet->GetMsg()->choice.gameStartMessage; - netGameStart->gameId = server->GetId(); - netGameStart->startDealerPlayerId = curGame.getDealerPosition(); - netGameStart->gameStartMode.present = gameStartMode_PR_gameStartModeRejoin; - GameStartModeRejoin_t *netStartModeRejoin = &netGameStart->gameStartMode.choice.gameStartModeRejoin; - - netStartModeRejoin->handNum = curGame.getCurrentHandID(); - PlayerListIterator player_i = curGame.getSeatsList()->begin(); - PlayerListIterator player_end = curGame.getSeatsList()->end(); - while (player_i != player_end) { - boost::shared_ptr tmpPlayer = *player_i; - if (tmpPlayer->getMyActiveStatus()) { - RejoinPlayerData_t *playerSlot = (RejoinPlayerData_t *)calloc(1, sizeof(RejoinPlayerData_t)); - playerSlot->playerId = tmpPlayer->getMyUniqueID(); - playerSlot->playerMoney = tmpPlayer->getMyCash(); - ASN_SEQUENCE_ADD(&netStartModeRejoin->rejoinPlayerData.list, playerSlot); - } - ++player_i; - } - - server->GetLobbyThread().GetSender().Send(session, packet); - } - } - ++i; - } - } + // This has to be done before initialising the new hand, because there are side effects. + InitRejoiningPlayers(server); // Initialize hand. curGame.initHand(); @@ -1305,6 +1233,72 @@ ServerGameStateHand::StartNewHand(boost::shared_ptr server) } } +void +ServerGameStateHand::InitRejoiningPlayers(boost::shared_ptr server) +{ + PlayerIdList rejoinIdList(server->GetAndResetRejoinPlayers()); + PlayerIdList::iterator i = rejoinIdList.begin(); + PlayerIdList::iterator end = rejoinIdList.end(); + while (i != end) { + boost::shared_ptr session(server->GetSessionManager().GetSessionByUniquePlayerId(*i)); + if (session && session->GetPlayerData()) { + PerformRejoin(server, session); + } + ++i; + } +} + +void +ServerGameStateHand::PerformRejoin(boost::shared_ptr server, boost::shared_ptr session) +{ + Game &curGame = server->GetGame(); + // Set new player id. + boost::shared_ptr rejoinPlayer = curGame.getPlayerByName(session->GetPlayerData()->GetName()); + if (rejoinPlayer) { + // Notify other clients about id change. + boost::shared_ptr packet(new NetPacket(NetPacket::Alloc)); + packet->GetMsg()->present = PokerTHMessage_PR_playerIdChangedMessage; + PlayerIdChangedMessage_t *netIdChanged = &packet->GetMsg()->choice.playerIdChangedMessage; + netIdChanged->oldPlayerId = rejoinPlayer->getMyUniqueID(); + netIdChanged->newPlayerId = session->GetPlayerData()->GetUniqueId(); + server->SendToAllButOnePlayers(packet, session->GetId(), SessionData::Game); + + // Update the dealer, if necessary. + curGame.replaceDealer(rejoinPlayer->getMyUniqueID(), session->GetPlayerData()->GetUniqueId()); + // Change the Id in the poker engine. + rejoinPlayer->setMyUniqueID(session->GetPlayerData()->GetUniqueId()); + rejoinPlayer->setMyGuid(session->GetPlayerData()->GetGuid()); + rejoinPlayer->setIsConnected(true); + + // Send game start notification to rejoining client. + packet.reset(new NetPacket(NetPacket::Alloc)); + packet->GetMsg()->present = PokerTHMessage_PR_gameStartMessage; + GameStartMessage_t *netGameStart = &packet->GetMsg()->choice.gameStartMessage; + netGameStart->gameId = server->GetId(); + netGameStart->startDealerPlayerId = curGame.getDealerPosition(); + netGameStart->gameStartMode.present = gameStartMode_PR_gameStartModeRejoin; + GameStartModeRejoin_t *netStartModeRejoin = &netGameStart->gameStartMode.choice.gameStartModeRejoin; + + netStartModeRejoin->handNum = curGame.getCurrentHandID(); + PlayerListIterator player_i = curGame.getSeatsList()->begin(); + PlayerListIterator player_end = curGame.getSeatsList()->end(); + while (player_i != player_end) { + boost::shared_ptr tmpPlayer = *player_i; + if (tmpPlayer->getMyActiveStatus()) { + RejoinPlayerData_t *playerSlot = (RejoinPlayerData_t *)calloc(1, sizeof(RejoinPlayerData_t)); + playerSlot->playerId = tmpPlayer->getMyUniqueID(); + playerSlot->playerMoney = tmpPlayer->getMyCash(); + ASN_SEQUENCE_ADD(&netStartModeRejoin->rejoinPlayerData.list, playerSlot); + } + ++player_i; + } + + server->GetLobbyThread().GetSender().Send(session, packet); + } else { + server->SessionError(session, ERR_SOCK_INVALID_STATE); + } +} + //----------------------------------------------------------------------------- diff --git a/src/net/servergamestate.h b/src/net/servergamestate.h index bec099a8..f7e44fd5 100644 --- a/src/net/servergamestate.h +++ b/src/net/servergamestate.h @@ -65,6 +65,9 @@ public: virtual void ProcessPacket(boost::shared_ptr server, boost::shared_ptr session, boost::shared_ptr packet); static boost::shared_ptr CreateNetPacketPlayerJoined(unsigned gameId, const PlayerData &playerData); + static boost::shared_ptr CreateNetPacketJoinGameAck(const ServerGame &server, const PlayerData &playerData); + + static void AcceptNewSession(boost::shared_ptr server, boost::shared_ptr session); protected: @@ -162,6 +165,8 @@ protected: void TimerNextGame(const boost::system::error_code &ec, boost::shared_ptr server, unsigned winnerPlayerId); int GetDealCardsDelaySec(ServerGame &server); static void StartNewHand(boost::shared_ptr server); + static void InitRejoiningPlayers(boost::shared_ptr server); + static void PerformRejoin(boost::shared_ptr server, boost::shared_ptr session); private: static ServerGameStateHand s_state;