From 3a2f3255afcf21827a02eafe10ea34bde56a29b8 Mon Sep 17 00:00:00 2001 From: lotodore Date: Tue, 21 Aug 2007 17:27:13 +0000 Subject: [PATCH] More fixes. Using player name as base for game name now. Removing games which have no players left. Check collision of all player names on connect (kind of slow, but name needs to be unique). --- .../gamelobbydialog/gamelobbydialogimpl.cpp | 21 ++++-- .../qt/gamelobbydialog/gamelobbydialogimpl.h | 2 + .../startnetworkgamedialogimpl.cpp | 4 +- src/net/common/servergamestate.cpp | 10 ++- src/net/common/servergamethread.cpp | 6 +- src/net/common/serverlobbythread.cpp | 68 ++++++++++++++++++- src/net/common/sessionmanager.cpp | 7 ++ src/net/servergamethread.h | 5 +- src/net/serverlobbythread.h | 10 +++ src/net/sessionmanager.h | 2 + 10 files changed, 120 insertions(+), 15 deletions(-) diff --git a/src/gui/qt/gamelobbydialog/gamelobbydialogimpl.cpp b/src/gui/qt/gamelobbydialog/gamelobbydialogimpl.cpp index f6153ba5..f84b7309 100644 --- a/src/gui/qt/gamelobbydialog/gamelobbydialogimpl.cpp +++ b/src/gui/qt/gamelobbydialog/gamelobbydialogimpl.cpp @@ -21,6 +21,9 @@ gameLobbyDialogImpl::gameLobbyDialogImpl(QWidget *parent, ConfigFile *c) connect( pushButton_CreateGame, SIGNAL( clicked() ), this, SLOT( createGame() ) ); connect( pushButton_JoinGame, SIGNAL( clicked() ), this, SLOT( joinGame() ) ); + connect( treeWidget_GameList, SIGNAL( itemClicked ( QTreeWidgetItem*, int) ), this, SLOT( gameSelected(QTreeWidgetItem*, int) ) ); + + pushButton_JoinGame->setEnabled(false); } void gameLobbyDialogImpl::exec() @@ -53,18 +56,28 @@ void gameLobbyDialogImpl::createGame() //Speeds gameData.guiSpeed = myConfig->readConfigInt("GameSpeed"); - mySession->clientCreateGame(gameData, "default", ""); + mySession->clientCreateGame(gameData, myConfig->readConfigString("MyName") + "'s game", ""); accept(); } void gameLobbyDialogImpl::joinGame() { - assert(mySession); + QTreeWidgetItem *item = treeWidget_GameList->currentItem(); + if (item) + { + QString gameName = item->text(0); - mySession->clientJoinGame("default", ""); + assert(mySession); + mySession->clientJoinGame(gameName.toUtf8().constData(), ""); - accept(); + accept(); + } +} + +void gameLobbyDialogImpl::gameSelected(QTreeWidgetItem*, int) +{ + pushButton_JoinGame->setEnabled(true); } void gameLobbyDialogImpl::addGame(QString gameName) diff --git a/src/gui/qt/gamelobbydialog/gamelobbydialogimpl.h b/src/gui/qt/gamelobbydialog/gamelobbydialogimpl.h index aba56047..865b3a8e 100644 --- a/src/gui/qt/gamelobbydialog/gamelobbydialogimpl.h +++ b/src/gui/qt/gamelobbydialog/gamelobbydialogimpl.h @@ -39,6 +39,8 @@ public slots: void createGame(); void joinGame(); + void gameSelected(QTreeWidgetItem*, int); + void addGame(QString gameName); void removeGame(QString gameName); diff --git a/src/gui/qt/startnetworkgamedialog/startnetworkgamedialogimpl.cpp b/src/gui/qt/startnetworkgamedialog/startnetworkgamedialogimpl.cpp index 3374ec51..50f59995 100644 --- a/src/gui/qt/startnetworkgamedialog/startnetworkgamedialogimpl.cpp +++ b/src/gui/qt/startnetworkgamedialog/startnetworkgamedialogimpl.cpp @@ -32,8 +32,8 @@ startNetworkGameDialogImpl::startNetworkGameDialogImpl(QWidget *parent, ConfigFi connect( pushButton_Kick, SIGNAL( clicked() ), this, SLOT( kickPlayer() ) ); connect( treeWidget, SIGNAL( itemClicked ( QTreeWidgetItem*, int) ), this, SLOT( playerSelected(QTreeWidgetItem*, int) ) ); - pushButton_Kick->setEnabled(FALSE); - pushButton_startGame->setEnabled(FALSE); + pushButton_Kick->setEnabled(false); + pushButton_startGame->setEnabled(false); } void startNetworkGameDialogImpl::startGame() { diff --git a/src/net/common/servergamestate.cpp b/src/net/common/servergamestate.cpp index 92616710..b63ff315 100644 --- a/src/net/common/servergamestate.cpp +++ b/src/net/common/servergamestate.cpp @@ -655,9 +655,13 @@ ServerGameStateStartRound::Process(ServerGameThread &server) if (curGame.getCurrentHand()->getPlayerArray()[i]->getMyCash() > 0) playersPositiveCashCounter++; } - // TODO: this is not an assert - terminate game if true. - assert(playersPositiveCashCounter); - if (playersPositiveCashCounter == 1) + if (!playersPositiveCashCounter) + { + // No more players left - restart. + server.SetState(SERVER_INITIAL_STATE::Instance()); + retVal = MSG_NET_GAME_SERVER_END; + } + else if (playersPositiveCashCounter == 1) { // View a dialog for a new game - delayed. server.SetState(ServerGameStateNextGameDelay::Instance()); diff --git a/src/net/common/servergamethread.cpp b/src/net/common/servergamethread.cpp index 92c26e83..6d3139b9 100644 --- a/src/net/common/servergamethread.cpp +++ b/src/net/common/servergamethread.cpp @@ -109,7 +109,7 @@ ServerGameThread::Main() try { - while (!ShouldTerminate()) + do { { // Handle one new session at a time. @@ -127,13 +127,15 @@ ServerGameThread::Main() } // Process current state. GetState().Process(*this); - } + } while (!ShouldTerminate() && GetSessionManager().HasSessions()); } catch (const NetException &e) { GetCallback().SignalNetServerError(e.GetErrorId(), e.GetOsErrorCode()); } GetSender().SignalTermination(); GetSender().Join(SENDER_THREAD_TERMINATE_TIMEOUT); + + GetLobbyThread().RemoveGame(GetId()); } void diff --git a/src/net/common/serverlobbythread.cpp b/src/net/common/serverlobbythread.cpp index c0de1cae..3b6d7ba1 100644 --- a/src/net/common/serverlobbythread.cpp +++ b/src/net/common/serverlobbythread.cpp @@ -93,6 +93,13 @@ ServerLobbyThread::CloseSessionDelayed(SessionWrapper session) m_closeSessionList.push_back(closeSessionData); } +void +ServerLobbyThread::RemoveGame(unsigned id) +{ + boost::mutex::scoped_lock lock(m_removeGameListMutex); + m_removeGameList.push_back(id); +} + u_int32_t ServerLobbyThread::GetNextUniquePlayerId() { @@ -132,6 +139,8 @@ ServerLobbyThread::Main() ProcessLoop(); // Close sessions. CloseSessionLoop(); + // Remove games. + RemoveGameLoop(); } } catch (const NetException &e) { @@ -221,7 +230,7 @@ ServerLobbyThread::HandleNetPacketInit(SessionWrapper session, const NetPacketIn } // Check whether this player is already connected. - if (m_sessionManager.IsPlayerConnected(initData.playerName)) + if (IsPlayerConnected(initData.playerName)) { SessionError(session, ERR_NET_PLAYER_NAME_IN_USE); return; @@ -289,7 +298,6 @@ ServerLobbyThread::HandleNetPacketJoinGame(SessionWrapper session, const NetPack GameMap::iterator pos = m_gameMap.find(joinGameData.gameId); - // TODO: handle errors if (pos != m_gameMap.end()) { ServerGameThread &game = *pos->second; @@ -300,6 +308,14 @@ ServerLobbyThread::HandleNetPacketJoinGame(SessionWrapper session, const NetPack // Add session to the game. game.AddSession(session); } + else + { + SessionError(session, ERR_NET_INVALID_PASSWORD); + } + } + else + { + SessionError(session, ERR_NET_UNKNOWN_GAME); } } @@ -320,6 +336,30 @@ ServerLobbyThread::CloseSessionLoop() } } +void +ServerLobbyThread::RemoveGameLoop() +{ + boost::mutex::scoped_lock lock(m_removeGameListMutex); + + RemoveGameList::iterator i = m_removeGameList.begin(); + RemoveGameList::iterator end = m_removeGameList.end(); + + // Synchronously remove games which have been closed. + while (i != end) + { + GameMap::iterator pos = m_gameMap.find(*i); + if (pos != m_gameMap.end()) + { + boost::shared_ptr tmpGame = pos->second; + tmpGame->SignalTermination(); + tmpGame->Join(GAME_THREAD_TERMINATE_TIMEOUT); + m_gameMap.erase(pos); + } + ++i; + } + m_removeGameList.clear(); +} + void ServerLobbyThread::TerminateGames() { @@ -427,6 +467,30 @@ ServerLobbyThread::GetGui() return m_gui; } +bool +ServerLobbyThread::IsPlayerConnected(const string &name) +{ + bool retVal = false; + + retVal = m_sessionManager.IsPlayerConnected(name); + + if (!retVal) + { + GameMap::const_iterator game_i = m_gameMap.begin(); + GameMap::const_iterator game_end = m_gameMap.end(); + while (game_i != game_end) + { + if (game_i->second->GetSessionManager().IsPlayerConnected(name)) + { + retVal = true; + break; + } + ++game_i; + } + } + return retVal; +} + boost::shared_ptr ServerLobbyThread::CreateNetPacketGameListNew(const ServerGameThread &game) { diff --git a/src/net/common/sessionmanager.cpp b/src/net/common/sessionmanager.cpp index 3410b48c..cf2f6406 100644 --- a/src/net/common/sessionmanager.cpp +++ b/src/net/common/sessionmanager.cpp @@ -34,6 +34,13 @@ SessionManager::~SessionManager() Clear(); } +bool +SessionManager::HasSessions() const +{ + boost::mutex::scoped_lock lock(m_sessionMapMutex); + return !m_sessionMap.empty(); +} + void SessionManager::AddSession(boost::shared_ptr sessionData) { diff --git a/src/net/servergamethread.h b/src/net/servergamethread.h index 6f1090f6..b2d8a4b9 100644 --- a/src/net/servergamethread.h +++ b/src/net/servergamethread.h @@ -60,6 +60,9 @@ public: bool CheckPassword(const std::string &password) const; const GameData &GetGameData() const; + const SessionManager &GetSessionManager() const; + SessionManager &GetSessionManager(); + protected: typedef std::deque SessionQueue; @@ -82,8 +85,6 @@ protected: size_t GetCurNumberOfPlayers() const; void AssignPlayerNumbers(); - SessionManager &GetSessionManager(); - const SessionManager &GetSessionManager() const; ServerLobbyThread &GetLobbyThread(); ServerGameState &GetState(); diff --git a/src/net/serverlobbythread.h b/src/net/serverlobbythread.h index 5082ad54..b81a376b 100644 --- a/src/net/serverlobbythread.h +++ b/src/net/serverlobbythread.h @@ -53,6 +53,8 @@ public: void AddConnection(boost::shared_ptr data); void CloseSessionDelayed(SessionWrapper session); + void RemoveGame(unsigned id); + u_int32_t GetNextUniquePlayerId(); u_int32_t GetNextGameId(); ServerCallback &GetCallback(); @@ -63,6 +65,7 @@ protected: typedef std::list SessionList; typedef std::list > > CloseSessionList; typedef std::map > GameMap; + typedef std::list RemoveGameList; // Main function of the thread. virtual void Main(); @@ -72,6 +75,8 @@ protected: void HandleNetPacketCreateGame(SessionWrapper session, const NetPacketCreateGame &tmpPacket); void HandleNetPacketJoinGame(SessionWrapper session, const NetPacketJoinGame &tmpPacket); void CloseSessionLoop(); + void RemoveGameLoop(); + void TerminateGames(); void HandleNewConnection(boost::shared_ptr connData); @@ -92,6 +97,8 @@ protected: ServerSenderCallback &GetSenderCallback(); GuiInterface &GetGui(); + bool IsPlayerConnected(const std::string &name); + static boost::shared_ptr CreateNetPacketGameListNew(const ServerGameThread &game); private: @@ -104,6 +111,9 @@ private: CloseSessionList m_closeSessionList; mutable boost::mutex m_closeSessionListMutex; + RemoveGameList m_removeGameList; + mutable boost::mutex m_removeGameListMutex; + GameMap m_gameMap; std::auto_ptr m_receiver; diff --git a/src/net/sessionmanager.h b/src/net/sessionmanager.h index 7a5c03bb..9ef49ce4 100644 --- a/src/net/sessionmanager.h +++ b/src/net/sessionmanager.h @@ -46,6 +46,8 @@ public: SessionManager(); virtual ~SessionManager(); + bool HasSessions() const; + void AddSession(boost::shared_ptr sessionData); // new Sessions without player data void AddSession(SessionWrapper session); void SetSessionPlayerData(SOCKET session, boost::shared_ptr playerData);