More work on rejoin. This is still broken because the player id is not yet updated on client side, and the server still does not activate the rejoining player.

This commit is contained in:
lotodore
2011-09-11 20:38:18 +00:00
parent 945a8f4588
commit 2488ea43cd
6 changed files with 177 additions and 48 deletions
+42 -21
View File
@@ -1500,28 +1500,49 @@ ClientStateWaitStart::InternalHandlePacket(boost::shared_ptr<ClientThread> clien
StartData startData;
startData.startDealerPlayerId = netGameStart->startDealerPlayerId;
if (netGameStart->gameStartMode.present != gameStartMode_PR_gameStartModeInitial)
if (netGameStart->gameStartMode.present == gameStartMode_PR_gameStartModeInitial)
{
GameStartModeInitial_t *netStartModeInitial = &netGameStart->gameStartMode.choice.gameStartModeInitial;
startData.numberOfPlayers = netStartModeInitial->playerSeats.list.count;
client->SetStartData(startData);
// Set player numbers using the game start data slots.
NonZeroId_t **playerIds = netStartModeInitial->playerSeats.list.array;
unsigned numPlayers = netStartModeInitial->playerSeats.list.count;
// Request player info for players if needed.
if (numPlayers && playerIds && *playerIds) {
for (unsigned i = 0; i < numPlayers; i++) {
unsigned playerId = *playerIds[i];
boost::shared_ptr<PlayerData> tmpPlayer = client->GetPlayerDataByUniqueId(playerId);
if (!tmpPlayer.get())
throw ClientException(__FILE__, __LINE__, ERR_NET_UNKNOWN_PLAYER_ID, 0);
tmpPlayer->SetNumber(i);
}
} else
throw ClientException(__FILE__, __LINE__, ERR_NET_INVALID_PLAYER_COUNT, 0);
} else if (netGameStart->gameStartMode.present == gameStartMode_PR_gameStartModeRejoin) {
GameStartModeRejoin_t *netStartModeRejoin = &netGameStart->gameStartMode.choice.gameStartModeRejoin;
startData.numberOfPlayers = netStartModeRejoin->rejoinPlayerData.list.count;
client->SetStartData(startData);
// Set player numbers using the game start data slots.
RejoinPlayerData_t **playerInfos = netStartModeRejoin->rejoinPlayerData.list.array;
unsigned numPlayers = netStartModeRejoin->rejoinPlayerData.list.count;
// Request player info for players if needed.
if (numPlayers && playerInfos && *playerInfos) {
for (unsigned i = 0; i < numPlayers; i++) {
RejoinPlayerData_t *playerData = playerInfos[i];
boost::shared_ptr<PlayerData> tmpPlayer = client->GetPlayerDataByUniqueId(playerData->playerId);
if (!tmpPlayer.get())
throw ClientException(__FILE__, __LINE__, ERR_NET_UNKNOWN_PLAYER_ID, 0);
tmpPlayer->SetNumber(i);
// TODO set money
}
} else
throw ClientException(__FILE__, __LINE__, ERR_NET_INVALID_PLAYER_COUNT, 0);
} else {
throw ClientException(__FILE__, __LINE__, ERR_NET_INTERNAL_GAME_ERROR, 0);
GameStartModeInitial_t *netStartModeInitial = &netGameStart->gameStartMode.choice.gameStartModeInitial;
startData.numberOfPlayers = netStartModeInitial->playerSeats.list.count;
client->SetStartData(startData);
// Set player numbers using the game start data slots.
NonZeroId_t **playerIds = netStartModeInitial->playerSeats.list.array;
unsigned numPlayers = netStartModeInitial->playerSeats.list.count;
// Request player info for players if needed.
if (numPlayers && playerIds && *playerIds) {
for (unsigned i = 0; i < numPlayers; i++) {
unsigned playerId = *playerIds[i];
boost::shared_ptr<PlayerData> tmpPlayer = client->GetPlayerDataByUniqueId(playerId);
if (!tmpPlayer.get())
throw ClientException(__FILE__, __LINE__, ERR_NET_UNKNOWN_PLAYER_ID, 0);
tmpPlayer->SetNumber(i);
}
} else
throw ClientException(__FILE__, __LINE__, ERR_NET_INVALID_PLAYER_COUNT, 0);
}
client->InitGame();
client->GetCallback().SignalNetClientGameInfo(MSG_NET_GAME_CLIENT_START);
client->SetState(ClientStateWaitHand::Instance());
+16
View File
@@ -627,6 +627,22 @@ ServerGame::SetPlayerAutoLeaveOnFinish(unsigned playerId)
m_autoLeavePlayerList.push_back(playerId);
}
void
ServerGame::AddRejoinPlayer(unsigned playerId)
{
boost::mutex::scoped_lock lock(m_rejoinPlayerListMutex);
m_rejoinPlayerList.push_back(playerId);
}
PlayerIdList
ServerGame::GetAndResetRejoinPlayers()
{
boost::mutex::scoped_lock lock(m_rejoinPlayerListMutex);
PlayerIdList tmpList(m_rejoinPlayerList);
m_rejoinPlayerList.clear();
return tmpList;
}
void
ServerGame::AddComputerPlayer(boost::shared_ptr<PlayerData> player)
{
+110 -18
View File
@@ -357,6 +357,20 @@ AbstractServerGameStateReceiving::ProcessPacket(boost::shared_ptr<ServerGame> se
}
}
boost::shared_ptr<NetPacket>
AbstractServerGameStateReceiving::CreateNetPacketPlayerJoined(unsigned gameId, const PlayerData &playerData)
{
boost::shared_ptr<NetPacket> packet(new NetPacket(NetPacket::Alloc));
packet->GetMsg()->present = PokerTHMessage_PR_gamePlayerMessage;
GamePlayerMessage_t *netGamePlayer = &packet->GetMsg()->choice.gamePlayerMessage;
netGamePlayer->gameId = gameId;
netGamePlayer->gamePlayerNotification.present = gamePlayerNotification_PR_gamePlayerJoined;
GamePlayerJoined_t *playerJoined = &netGamePlayer->gamePlayerNotification.choice.gamePlayerJoined;
playerJoined->playerId = playerData.GetUniqueId();
playerJoined->isGameAdmin = playerData.IsGameAdmin();
return packet;
}
//-----------------------------------------------------------------------------
ServerGameStateInit ServerGameStateInit::s_state;
@@ -429,7 +443,7 @@ ServerGameStateInit::HandleNewSession(boost::shared_ptr<ServerGame> server, boos
server->GetLobbyThread().GetSender().Send(session, packet);
// Send notifications for connected players to client.
PlayerDataList tmpPlayerList = server->GetFullPlayerDataList();
PlayerDataList tmpPlayerList(server->GetFullPlayerDataList());
PlayerDataList::iterator player_i = tmpPlayerList.begin();
PlayerDataList::iterator player_end = tmpPlayerList.end();
while (player_i != player_end) {
@@ -624,20 +638,6 @@ ServerGameStateInit::InternalProcessPacket(boost::shared_ptr<ServerGame> server,
}
}
boost::shared_ptr<NetPacket>
ServerGameStateInit::CreateNetPacketPlayerJoined(unsigned gameId, const PlayerData &playerData)
{
boost::shared_ptr<NetPacket> packet(new NetPacket(NetPacket::Alloc));
packet->GetMsg()->present = PokerTHMessage_PR_gamePlayerMessage;
GamePlayerMessage_t *netGamePlayer = &packet->GetMsg()->choice.gamePlayerMessage;
netGamePlayer->gameId = gameId;
netGamePlayer->gamePlayerNotification.present = gamePlayerNotification_PR_gamePlayerJoined;
GamePlayerJoined_t *playerJoined = &netGamePlayer->gamePlayerNotification.choice.gamePlayerJoined;
playerJoined->playerId = playerData.GetUniqueId();
playerJoined->isGameAdmin = playerData.IsGameAdmin();
return packet;
}
//-----------------------------------------------------------------------------
ServerGameStateStartGame ServerGameStateStartGame::s_state;
@@ -753,8 +753,65 @@ AbstractServerGameStateRunning::~AbstractServerGameStateRunning()
void
AbstractServerGameStateRunning::HandleNewSession(boost::shared_ptr<ServerGame> server, boost::shared_ptr<SessionData> session)
{
// Do not accept new sessions in this state.
server->MoveSessionToLobby(session, NTF_NET_REMOVED_ALREADY_RUNNING);
// Verify that the user is allowed to rejoin.
boost::shared_ptr<PlayerInterface> 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<NetPacket> 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<PlayerInfoRights>(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);
// 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.
{
boost::shared_ptr<NetPacket> packet(new NetPacket(NetPacket::Alloc));
packet->GetMsg()->present = PokerTHMessage_PR_startEventMessage;
StartEventMessage_t *netStartEvent = &packet->GetMsg()->choice.startEventMessage;
netStartEvent->gameId = server->GetId();
netStartEvent->fillWithComputerPlayers = false;
// 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);
}
}
//-----------------------------------------------------------------------------
@@ -963,7 +1020,7 @@ ServerGameStateHand::EngineLoop(boost::shared_ptr<ServerGame> server)
// Remove disconnected players. This is the one and only place to do this.
server->RemoveDisconnectedPlayers();
// Update rankings of all remaining players.
// Update rankings of all remaining players
server->UpdateRankingMap();
// Start next hand - if enough players are left.
@@ -1079,6 +1136,41 @@ ServerGameStateHand::StartNewHand(boost::shared_ptr<ServerGame> server)
// Initialize hand.
Game &curGame = server->GetGame();
curGame.initHand();
// Initialize rejoining players.
{
PlayerIdList rejoinIdList(server->GetAndResetRejoinPlayers());
PlayerIdList::iterator i = rejoinIdList.begin();
PlayerIdList::iterator end = rejoinIdList.end();
while (i != end) {
boost::shared_ptr<SessionData> session(server->GetSessionManager().GetSessionByUniquePlayerId(*i));
if (session) {
boost::shared_ptr<NetPacket> packet(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;
// Send player data to client.
PlayerListIterator player_i = curGame.getSeatsList()->begin();
PlayerListIterator player_end = curGame.getSeatsList()->end();
while (player_i != player_end) {
boost::shared_ptr<PlayerInterface> 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;
}
}
// HACK: Skip GUI notification run
curGame.getCurrentHand()->getFlop()->skipFirstRunGui();
+1 -7
View File
@@ -1314,13 +1314,7 @@ ServerLobbyThread::HandleNetPacketRejoinGame(boost::shared_ptr<SessionData> sess
if (pos != m_gameMap.end()) {
boost::shared_ptr<ServerGame> game = pos->second;
// Verify that the user is allowed to rejoin.
boost::shared_ptr<PlayerInterface> tmpPlayer = game->GetPlayerInterfaceFromGame(session->GetPlayerData()->GetName());
if (tmpPlayer && tmpPlayer->getMyGuid() == session->GetPlayerData()->GetOldGuid()) {
MoveSessionToGame(game, session, autoLeave);
} else {
SendJoinGameFailed(session, rejoinGame.gameId, NTF_NET_JOIN_REJOIN_FAILED);
}
MoveSessionToGame(game, session, autoLeave);
} else {
SendJoinGameFailed(session, rejoinGame.gameId, NTF_NET_JOIN_GAME_INVALID);
}
+6
View File
@@ -87,6 +87,9 @@ public:
void SetPlayerAutoLeaveOnFinish(unsigned playerId);
void AddRejoinPlayer(unsigned playerId);
PlayerIdList GetAndResetRejoinPlayers();
unsigned GetSmallDelaySec() const;
// should be protected, but is needed in function.
@@ -173,6 +176,9 @@ private:
PlayerIdList m_autoLeavePlayerList;
mutable boost::mutex m_autoLeavePlayerListMutex;
PlayerIdList m_rejoinPlayerList;
mutable boost::mutex m_rejoinPlayerListMutex;
PlayerIdList m_reportedAvatarList;
RankingMap m_rankingMap;
+2 -2
View File
@@ -64,6 +64,8 @@ public:
// Calls InternalProcess if packet has not been processed.
virtual void ProcessPacket(boost::shared_ptr<ServerGame> server, boost::shared_ptr<SessionData> session, boost::shared_ptr<NetPacket> packet);
static boost::shared_ptr<NetPacket> CreateNetPacketPlayerJoined(unsigned gameId, const PlayerData &playerData);
protected:
virtual void InternalProcessPacket(boost::shared_ptr<ServerGame> server, boost::shared_ptr<SessionData> session, boost::shared_ptr<NetPacket> packet) = 0;
@@ -98,8 +100,6 @@ protected:
virtual void InternalProcessPacket(boost::shared_ptr<ServerGame> server, boost::shared_ptr<SessionData> session, boost::shared_ptr<NetPacket> packet);
static boost::shared_ptr<NetPacket> CreateNetPacketPlayerJoined(unsigned gameId, const PlayerData &playerData);
private:
static ServerGameStateInit s_state;
};