From e19f6c7471626f7e4fc9d306523d300125c1b78d Mon Sep 17 00:00:00 2001 From: lotodore Date: Fri, 15 Jun 2007 10:38:41 +0000 Subject: [PATCH] Rewrote the code which handles leaving of players during the network game. Some bug is still remaining. --- src/game.cpp | 2 +- src/gui/qt/guiwrapper.cpp | 14 ++--- src/net/clientthread.h | 2 + src/net/common/clientstate.cpp | 22 +------- src/net/common/clientthread.cpp | 22 ++++++++ src/net/common/serverrecvstate.cpp | 8 ++- src/net/common/serverrecvthread.cpp | 85 ++++++++++++++++++++++------- src/net/serverrecvthread.h | 5 +- 8 files changed, 110 insertions(+), 50 deletions(-) diff --git a/src/game.cpp b/src/game.cpp index 3a56058a..2e32d071 100755 --- a/src/game.cpp +++ b/src/game.cpp @@ -148,7 +148,7 @@ void Game::initHand() // Anzahl noch aktiver Spieler ermitteln actualQuantityPlayers = 0; for(i=0; igetMyActiveStatus() != 0) actualQuantityPlayers++; + if(playerArray[i]->getMyActiveStatus()) actualQuantityPlayers++; } //Spieler Action auf 0 setzen diff --git a/src/gui/qt/guiwrapper.cpp b/src/gui/qt/guiwrapper.cpp index 55609299..56099c78 100644 --- a/src/gui/qt/guiwrapper.cpp +++ b/src/gui/qt/guiwrapper.cpp @@ -108,7 +108,12 @@ void GuiWrapper::SignalNetClientConnect(int actionID) { myW->signalNetClientConn void GuiWrapper::SignalNetClientGameInfo(int actionID) { myW->signalNetClientGameInfo(actionID); } void GuiWrapper::SignalNetClientError(int errorID, int osErrorID) { myW->signalNetClientError(errorID, osErrorID); } void GuiWrapper::SignalNetClientPlayerJoined(const string &playerName) { myW->signalNetClientPlayerJoined(QString::fromUtf8(playerName.c_str())); } -void GuiWrapper::SignalNetClientPlayerLeft(const string &playerName) { myW->signalNetClientPlayerLeft(QString::fromUtf8(playerName.c_str())); } +void GuiWrapper::SignalNetClientPlayerLeft(const string &playerName) +{ + QString tmpName(QString::fromUtf8(playerName.c_str())); + myW->signalNetClientPlayerLeft(tmpName); + myLog->signalLogPlayerLeftMsg(tmpName); +} void GuiWrapper::SignalNetClientGameStart(boost::shared_ptr game) { myW->signalNetClientGameStart(game); } void GuiWrapper::SignalNetClientChatMsg(const string &playerName, const string &msg) { myChat->signalChatMessage(QString::fromUtf8(playerName.c_str()), QString::fromUtf8(msg.c_str())); } void GuiWrapper::SignalNetClientWaitDialog() { myW->signalShowClientWaitDialog(); } @@ -116,11 +121,6 @@ void GuiWrapper::SignalNetClientWaitDialog() { myW->signalShowClientWaitDialog() void GuiWrapper::SignalNetServerSuccess(int actionID) { } void GuiWrapper::SignalNetServerError(int errorID, int osErrorID) { myW->signalNetServerError(errorID, osErrorID); } void GuiWrapper::SignalNetServerPlayerJoined(const string &playerName) { myW->signalNetServerPlayerJoined(QString::fromUtf8(playerName.c_str())); } -void GuiWrapper::SignalNetServerPlayerLeft(const string &playerName) -{ - QString tmpName(QString::fromUtf8(playerName.c_str())); - myW->signalNetServerPlayerLeft(tmpName); - myLog->signalLogPlayerLeftMsg(tmpName); -} +void GuiWrapper::SignalNetServerPlayerLeft(const string &playerName) { myW->signalNetServerPlayerLeft(QString::fromUtf8(playerName.c_str())); } void GuiWrapper::SignalNetServerStartDialog() { myW->signalShowServerStartDialog(); } diff --git a/src/net/clientthread.h b/src/net/clientthread.h index 03046fc7..b8b1fcfe 100644 --- a/src/net/clientthread.h +++ b/src/net/clientthread.h @@ -90,6 +90,8 @@ protected: const PlayerDataList &GetPlayerDataList() const; boost::shared_ptr GetPlayerDataByUniqueId(unsigned id); + void RemoveDisconnectedPlayers(); + private: std::auto_ptr m_context; diff --git a/src/net/common/clientstate.cpp b/src/net/common/clientstate.cpp index 1fb2ec8f..22e2100b 100644 --- a/src/net/common/clientstate.cpp +++ b/src/net/common/clientstate.cpp @@ -403,26 +403,8 @@ AbstractClientStateReceiving::Process(ClientThread &client) NetPacketPlayerLeft::Data playerLeftData; tmpPacket->ToNetPacketPlayerLeft()->GetData(playerLeftData); - // Signal to GUI. + // Signal to GUI and remove from data list. client.RemovePlayerData(playerLeftData.playerId); - - // If the game is running, deactivate player. - boost::shared_ptr curGame = client.GetGame(); - if (curGame.get()) - { - PlayerInterface *tmpPlayer = curGame->getPlayerByUniqueId(playerLeftData.playerId); - if (!tmpPlayer) - throw ClientException(ERR_NET_UNKNOWN_PLAYER_ID, 0); - - // Reset his action and his cash. - tmpPlayer->setMyAction(PLAYER_ACTION_FOLD); - tmpPlayer->setMyCash(0); - // Player is now inactive. - tmpPlayer->setMyActiveStatus(false); - - client.GetGui().refreshAction(); - client.GetGui().refreshCash(); - } } else retVal = InternalProcess(client, tmpPacket); @@ -551,6 +533,8 @@ ClientStateWaitHand::InternalProcess(ClientThread &client, boost::shared_ptrToNetPacketHandStart()) { + // Remove all players which left the server. + client.RemoveDisconnectedPlayers(); // Hand was started. // These are the cards. Good luck. NetPacketHandStart::Data tmpData; diff --git a/src/net/common/clientthread.cpp b/src/net/common/clientthread.cpp index 66ec3bd5..c7fb5443 100644 --- a/src/net/common/clientthread.cpp +++ b/src/net/common/clientthread.cpp @@ -355,3 +355,25 @@ ClientThread::GetPlayerDataByUniqueId(unsigned id) return tmpPlayer; } +void +ClientThread::RemoveDisconnectedPlayers() +{ + // This should only be called between hands. + if (m_game.get()) + { + for (int i = 0; i < m_game->getStartQuantityPlayers(); i++) + { + PlayerInterface *tmpPlayer = m_game->getPlayerArray()[i]; + if (tmpPlayer->getMyActiveStatus()) + { + // If a player is not in the player data list, it was disconnected. + if (!GetPlayerDataByUniqueId(tmpPlayer->getMyUniqueID()).get()) + { + tmpPlayer->setMyCash(0); + tmpPlayer->setMyActiveStatus(false); + } + } + } + } +} + diff --git a/src/net/common/serverrecvstate.cpp b/src/net/common/serverrecvstate.cpp index 3ae3a8a0..613d1b56 100644 --- a/src/net/common/serverrecvstate.cpp +++ b/src/net/common/serverrecvstate.cpp @@ -637,6 +637,10 @@ ServerRecvStateStartRound::Process(ServerRecvThread &server) server.SendToAllPlayers(endHand); } + + // Remove disconnected players. This is the one and only place to do this. + server.RemoveDisconnectedPlayers(); + // Start next hand - if enough players are left. int playersPositiveCashCounter = 0; for (int i = 0; i < curGame.getStartQuantityPlayers(); i++) @@ -728,9 +732,9 @@ ServerRecvStateWaitPlayerAction::Process(ServerRecvThread &server) // If the player we are waiting for left, continue without him. PlayerInterface *tmpPlayer = GetCurrentPlayer(server.GetGame()); assert(tmpPlayer); - if (!tmpPlayer->getMyActiveStatus()) + assert(!tmpPlayer->getMyName().empty()); + if (!server.IsPlayerConnected(tmpPlayer->getMyName())) { - assert(tmpPlayer->getMyAction() == PLAYER_ACTION_FOLD && tmpPlayer->getMyCash() == 0); PerformPlayerAction(server, tmpPlayer, PLAYER_ACTION_FOLD, 0); server.SetState(ServerRecvStateStartRound::Instance()); diff --git a/src/net/common/serverrecvthread.cpp b/src/net/common/serverrecvthread.cpp index 1eeca157..6331014b 100644 --- a/src/net/common/serverrecvthread.cpp +++ b/src/net/common/serverrecvthread.cpp @@ -297,7 +297,7 @@ ServerRecvThread::InternalKickPlayer(const string playerName) { if (!playerName.empty()) { - SessionWrapper tmpSession = GetSession(playerName); + SessionWrapper tmpSession = GetSessionByPlayerName(playerName); SessionError(tmpSession, ERR_NET_PLAYER_KICKED); } @@ -318,7 +318,7 @@ ServerRecvThread::GetSession(SOCKET sock) const } SessionWrapper -ServerRecvThread::GetSession(const string playerName) const +ServerRecvThread::GetSessionByPlayerName(const string playerName) const { SessionWrapper tmpSession; boost::mutex::scoped_lock lock(m_sessionMapMutex); @@ -345,6 +345,34 @@ ServerRecvThread::GetSession(const string playerName) const return tmpSession; } +SessionWrapper +ServerRecvThread::GetSessionByUniquePlayerId(unsigned uniqueId) const +{ + SessionWrapper tmpSession; + boost::mutex::scoped_lock lock(m_sessionMapMutex); + + SocketSessionMap::const_iterator session_i = m_sessionMap.begin(); + SocketSessionMap::const_iterator session_end = m_sessionMap.end(); + + while (session_i != session_end) + { + // Check all players which are fully connected. + if (session_i->second.sessionData->GetState() == SessionData::Established) + { + boost::shared_ptr tmpPlayer(session_i->second.playerData); + assert(tmpPlayer.get()); + if (tmpPlayer->GetUniqueId() == uniqueId) + { + tmpSession = session_i->second; + break; + } + } + + ++session_i; + } + return tmpSession; +} + void ServerRecvThread::AddSession(boost::shared_ptr sessionData) { @@ -390,23 +418,6 @@ ServerRecvThread::CloseSessionDelayed(SessionWrapper session) boost::shared_ptr tmpPlayerData = session.playerData; if (tmpPlayerData.get() && !tmpPlayerData->GetName().empty()) { - // Set player inactive. - if (m_game.get()) - { - PlayerInterface *player = GetGame().getPlayerByUniqueId(tmpPlayerData->GetUniqueId()); - if (player) - { - // Deactivate player (if active). - if (player->getMyActiveStatus()) - { - if (player->getMyAction() != PLAYER_ACTION_FOLD) - player->setMyAction(PLAYER_ACTION_FOLD); - player->setMyCash(0); - player->setMyActiveStatus(false); - } - } - } - // Send "Player Left" to clients. boost::shared_ptr thisPlayerLeft(new NetPacketPlayerLeft); NetPacketPlayerLeft::Data thisPlayerLeftData; @@ -456,6 +467,27 @@ ServerRecvThread::RemoveNotEstablishedSessions() } } +void +ServerRecvThread::RemoveDisconnectedPlayers() +{ + // This should only be called between hands. + if (m_game.get()) + { + for (int i = 0; i < m_game->getStartQuantityPlayers(); i++) + { + PlayerInterface *tmpPlayer = m_game->getPlayerArray()[i]; + if (tmpPlayer->getMyActiveStatus()) + { + if (!IsPlayerConnected(tmpPlayer->getMyUniqueID())) + { + tmpPlayer->setMyCash(0); + tmpPlayer->setMyActiveStatus(false); + } + } + } + } +} + size_t ServerRecvThread::GetCurNumberOfPlayers() const { @@ -468,7 +500,20 @@ ServerRecvThread::IsPlayerConnected(const string &playerName) const { bool retVal = false; - SessionWrapper tmpSession = GetSession(playerName); + SessionWrapper tmpSession = GetSessionByPlayerName(playerName); + + if (tmpSession.sessionData.get() && tmpSession.playerData.get()) + retVal = true; + + return retVal; +} + +bool +ServerRecvThread::IsPlayerConnected(unsigned uniquePlayerId) const +{ + bool retVal = false; + + SessionWrapper tmpSession = GetSessionByUniquePlayerId(uniquePlayerId); if (tmpSession.sessionData.get() && tmpSession.playerData.get()) retVal = true; diff --git a/src/net/serverrecvthread.h b/src/net/serverrecvthread.h index 31350b08..1b977c88 100644 --- a/src/net/serverrecvthread.h +++ b/src/net/serverrecvthread.h @@ -106,15 +106,18 @@ protected: void InternalKickPlayer(const std::string playerName); SessionWrapper GetSession(SOCKET sock) const; - SessionWrapper GetSession(const std::string playerName) const; + SessionWrapper GetSessionByPlayerName(const std::string playerName) const; + SessionWrapper GetSessionByUniquePlayerId(unsigned uniqueId) const; void AddSession(boost::shared_ptr sessionData); // new Sessions have no player data void SessionError(SessionWrapper session, int errorCode); void RejectNewConnection(boost::shared_ptr connData); void CloseSessionDelayed(SessionWrapper session); void RemoveNotEstablishedSessions(); + void RemoveDisconnectedPlayers(); size_t GetCurNumberOfPlayers() const; bool IsPlayerConnected(const std::string &playerName) const; + bool IsPlayerConnected(unsigned uniquePlayerId) const; void SetSessionPlayerData(boost::shared_ptr sessionData, boost::shared_ptr playerData); PlayerDataList GetPlayerDataList() const;