diff --git a/docs/net_protocol.txt b/docs/net_protocol.txt index 575668f0..3f76952a 100644 --- a/docs/net_protocol.txt +++ b/docs/net_protocol.txt @@ -194,12 +194,14 @@ Server Notification: Game List New +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Message Type = 16 | Message Length | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Game ID | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Admin Player ID | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Game Mode | Game Name Length | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Current Number of Players | Game Flags | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Game ID | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | | \ Game Info Block / | + @@ -266,6 +268,19 @@ Server Notification: Game List Player Left +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +Server Notification: Game List Admin Changed + + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Message Type = 20 | Message Length = 12 | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Game ID | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | New Admin Player ID | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + + Client Request: Retrieve Player Info 0 1 2 3 diff --git a/src/gamedata.h b/src/gamedata.h index 5ecce178..17f48174 100644 --- a/src/gamedata.h +++ b/src/gamedata.h @@ -69,10 +69,11 @@ struct GameData struct GameInfo { - GameInfo() : mode(GAME_MODE_CREATED), isPasswordProtected(false) {} + GameInfo() : mode(GAME_MODE_CREATED), adminPlayerId(0), isPasswordProtected(false) {} std::string name; GameData data; GameMode mode; + unsigned adminPlayerId; PlayerIdList players; bool isPasswordProtected; }; diff --git a/src/gui/generic/serverguiwrapper.cpp b/src/gui/generic/serverguiwrapper.cpp index 1ae6df7f..31e59d1f 100644 --- a/src/gui/generic/serverguiwrapper.cpp +++ b/src/gui/generic/serverguiwrapper.cpp @@ -122,6 +122,7 @@ void ServerGuiWrapper::SignalNetClientNewGameAdmin(unsigned playerId, const stri void ServerGuiWrapper::SignalNetClientGameListNew(unsigned gameId) { if (myClientcb) myClientcb->SignalNetClientGameListNew(gameId); } void ServerGuiWrapper::SignalNetClientGameListRemove(unsigned gameId) { if (myClientcb) myClientcb->SignalNetClientGameListRemove(gameId); } void ServerGuiWrapper::SignalNetClientGameListUpdateMode(unsigned gameId, GameMode mode) { if (myClientcb) myClientcb->SignalNetClientGameListUpdateMode(gameId, mode); } +void ServerGuiWrapper::SignalNetClientGameListUpdateAdmin(unsigned gameId, unsigned adminPlayerId) { if (myClientcb) myClientcb->SignalNetClientGameListUpdateAdmin(gameId, adminPlayerId); } void ServerGuiWrapper::SignalNetClientGameListPlayerJoined(unsigned gameId, unsigned playerId) { if (myClientcb) myClientcb->SignalNetClientGameListPlayerJoined(gameId, playerId); } void ServerGuiWrapper::SignalNetClientGameListPlayerLeft(unsigned gameId, unsigned playerId) { if (myClientcb) myClientcb->SignalNetClientGameListPlayerLeft(gameId, playerId); } void ServerGuiWrapper::SignalNetClientGameStart(boost::shared_ptr game) { if (myClientcb) myClientcb->SignalNetClientGameStart(game); } diff --git a/src/gui/generic/serverguiwrapper.h b/src/gui/generic/serverguiwrapper.h index c2c32c8a..315d8f43 100644 --- a/src/gui/generic/serverguiwrapper.h +++ b/src/gui/generic/serverguiwrapper.h @@ -108,6 +108,7 @@ public: void SignalNetClientGameListNew(unsigned gameId); void SignalNetClientGameListRemove(unsigned gameId); void SignalNetClientGameListUpdateMode(unsigned gameId, GameMode mode); + void SignalNetClientGameListUpdateAdmin(unsigned gameId, unsigned adminPlayerId); void SignalNetClientGameListPlayerJoined(unsigned gameId, unsigned playerId); void SignalNetClientGameListPlayerLeft(unsigned gameId, unsigned playerId); void SignalNetClientGameStart(boost::shared_ptr game); diff --git a/src/gui/qt/gamelobbydialog/gamelobbydialogimpl.cpp b/src/gui/qt/gamelobbydialog/gamelobbydialogimpl.cpp index 9d182b2e..f0fb2c11 100644 --- a/src/gui/qt/gamelobbydialog/gamelobbydialogimpl.cpp +++ b/src/gui/qt/gamelobbydialog/gamelobbydialogimpl.cpp @@ -199,8 +199,9 @@ void gameLobbyDialogImpl::gameSelected(QTreeWidgetItem* item, QTreeWidgetItem*) PlayerIdList::const_iterator end = info.players.end(); while (i != end) { - PlayerInfo info(mySession->getClientPlayerInfo(*i)); - addConnectedPlayer(*i, QString::fromUtf8(info.playerName.c_str()), PLAYER_RIGHTS_NORMAL); + PlayerRights tmpRights = info.adminPlayerId == *i ? PLAYER_RIGHTS_ADMIN : PLAYER_RIGHTS_NORMAL; + PlayerInfo playerInfo(mySession->getClientPlayerInfo(*i)); + addConnectedPlayer(*i, QString::fromUtf8(playerInfo.playerName.c_str()), tmpRights); ++i; } } @@ -247,6 +248,11 @@ void gameLobbyDialogImpl::updateGameMode(unsigned gameId, int /*newMode*/) } } +void gameLobbyDialogImpl::updateGameAdmin(unsigned /*gameId*/, unsigned adminPlayerId) +{ + newGameAdmin(adminPlayerId, ""); +} + void gameLobbyDialogImpl::removeGame(unsigned gameId) { QTreeWidgetItemIterator it(treeWidget_GameList); @@ -268,8 +274,11 @@ void gameLobbyDialogImpl::gameAddPlayer(unsigned gameId, unsigned playerId) if (item && item->data(0, Qt::UserRole) == gameId) { assert(mySession); - PlayerInfo info(mySession->getClientPlayerInfo(playerId)); - addConnectedPlayer(playerId, QString::fromUtf8(info.playerName.c_str()), PLAYER_RIGHTS_NORMAL); + GameInfo info(mySession->getClientGameInfo(gameId)); + PlayerRights tmpRights = info.adminPlayerId == playerId ? PLAYER_RIGHTS_ADMIN : PLAYER_RIGHTS_NORMAL; + PlayerInfo playerInfo(mySession->getClientPlayerInfo(playerId)); + + addConnectedPlayer(playerId, QString::fromUtf8(playerInfo.playerName.c_str()), tmpRights); } } @@ -437,7 +446,7 @@ void gameLobbyDialogImpl::newGameAdmin(unsigned playerId, QString) ++it; } - if (myPlayerId == playerId) + if (inGame && myPlayerId == playerId) { isAdmin = true; checkPlayerQuantity(); diff --git a/src/gui/qt/gamelobbydialog/gamelobbydialogimpl.h b/src/gui/qt/gamelobbydialog/gamelobbydialogimpl.h index 066b0b2c..692a541f 100644 --- a/src/gui/qt/gamelobbydialog/gamelobbydialogimpl.h +++ b/src/gui/qt/gamelobbydialog/gamelobbydialogimpl.h @@ -57,6 +57,7 @@ public slots: void addGame(unsigned gameId); void updateGameMode(unsigned gameId, int newMode); + void updateGameAdmin(unsigned gameId, unsigned adminPlayerId); void removeGame(unsigned gameId); void gameAddPlayer(unsigned gameId, unsigned playerId); void gameRemovePlayer(unsigned gameId, unsigned playerId); diff --git a/src/gui/qt/guiwrapper.cpp b/src/gui/qt/guiwrapper.cpp index 6521ec09..48e178b7 100644 --- a/src/gui/qt/guiwrapper.cpp +++ b/src/gui/qt/guiwrapper.cpp @@ -135,6 +135,7 @@ void GuiWrapper::SignalNetClientNewGameAdmin(unsigned playerId, const string &pl void GuiWrapper::SignalNetClientGameListNew(unsigned gameId) { myW->signalNetClientGameListNew(gameId); } void GuiWrapper::SignalNetClientGameListRemove(unsigned gameId) { myW->signalNetClientGameListRemove(gameId); } void GuiWrapper::SignalNetClientGameListUpdateMode(unsigned gameId, GameMode mode) { myW->signalNetClientGameListUpdateMode(gameId, mode); } +void GuiWrapper::SignalNetClientGameListUpdateAdmin(unsigned gameId, unsigned adminPlayerId) {myW->signalNetClientGameListUpdateAdmin(gameId, adminPlayerId); } void GuiWrapper::SignalNetClientGameListPlayerJoined(unsigned gameId, unsigned playerId) { myW->signalNetClientGameListPlayerJoined(gameId, playerId); } void GuiWrapper::SignalNetClientGameListPlayerLeft(unsigned gameId, unsigned playerId) { myW->signalNetClientGameListPlayerLeft(gameId, playerId); } @@ -142,7 +143,7 @@ void GuiWrapper::SignalNetClientGameStart(boost::shared_ptr game) { myW->s 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->signalShowClientDialog(); } -void GuiWrapper::SignalNetServerSuccess(int actionID) { } +void GuiWrapper::SignalNetServerSuccess(int /*actionID*/) { } void GuiWrapper::SignalNetServerError(int errorID, int osErrorID) { myW->signalNetServerError(errorID, osErrorID); } void GuiWrapper::SignalIrcConnect(const string &server) { myW->signalIrcConnect(QString::fromUtf8(server.c_str())); } diff --git a/src/gui/qt/guiwrapper.h b/src/gui/qt/guiwrapper.h index d14eef9b..ee17b80b 100644 --- a/src/gui/qt/guiwrapper.h +++ b/src/gui/qt/guiwrapper.h @@ -115,6 +115,7 @@ public: void SignalNetClientGameListNew(unsigned gameId); void SignalNetClientGameListRemove(unsigned gameId); void SignalNetClientGameListUpdateMode(unsigned gameId, GameMode mode); + void SignalNetClientGameListUpdateAdmin(unsigned gameId, unsigned adminPlayerId); void SignalNetClientGameListPlayerJoined(unsigned gameId, unsigned playerId); void SignalNetClientGameListPlayerLeft(unsigned gameId, unsigned playerId); diff --git a/src/gui/qt/mainwindow/mainwindowimpl.cpp b/src/gui/qt/mainwindow/mainwindowimpl.cpp index 69202baa..e66e3f76 100755 --- a/src/gui/qt/mainwindow/mainwindowimpl.cpp +++ b/src/gui/qt/mainwindow/mainwindowimpl.cpp @@ -671,6 +671,7 @@ mainWindowImpl::mainWindowImpl(ConfigFile *c, QMainWindow *parent) connect(this, SIGNAL(signalNetClientGameListNew(unsigned)), myGameLobbyDialog, SLOT(addGame(unsigned))); connect(this, SIGNAL(signalNetClientGameListRemove(unsigned)), myGameLobbyDialog, SLOT(removeGame(unsigned))); connect(this, SIGNAL(signalNetClientGameListUpdateMode(unsigned, int)), myGameLobbyDialog, SLOT(updateGameMode(unsigned, int))); + connect(this, SIGNAL(signalNetClientGameListUpdateAdmin(unsigned, unsigned)), myGameLobbyDialog, SLOT(updateGameAdmin(unsigned, unsigned))); connect(this, SIGNAL(signalNetClientGameListPlayerJoined(unsigned, unsigned)), myGameLobbyDialog, SLOT(gameAddPlayer(unsigned, unsigned))); connect(this, SIGNAL(signalNetClientGameListPlayerLeft(unsigned, unsigned)), myGameLobbyDialog, SLOT(gameRemovePlayer(unsigned, unsigned))); connect(this, SIGNAL(signalNetClientRemovedFromGame(int)), myGameLobbyDialog, SLOT(removedFromGame(int))); diff --git a/src/gui/qt/mainwindow/mainwindowimpl.h b/src/gui/qt/mainwindow/mainwindowimpl.h index 578e615c..cbe529ec 100755 --- a/src/gui/qt/mainwindow/mainwindowimpl.h +++ b/src/gui/qt/mainwindow/mainwindowimpl.h @@ -136,6 +136,7 @@ signals: void signalNetClientGameListNew(unsigned gameId); void signalNetClientGameListRemove(unsigned gameId); void signalNetClientGameListUpdateMode(unsigned gameId, int mode); + void signalNetClientGameListUpdateAdmin(unsigned gameId, unsigned adminPlayerId); void signalNetClientGameListPlayerJoined(unsigned gameId, unsigned playerId); void signalNetClientGameListPlayerLeft(unsigned gameId, unsigned playerId); void signalNetClientGameStart(boost::shared_ptr game); diff --git a/src/net/clientcallback.h b/src/net/clientcallback.h index c7576baa..c2fd999e 100644 --- a/src/net/clientcallback.h +++ b/src/net/clientcallback.h @@ -42,6 +42,7 @@ public: virtual void SignalNetClientGameListNew(unsigned gameId) = 0; virtual void SignalNetClientGameListRemove(unsigned gameId) = 0; virtual void SignalNetClientGameListUpdateMode(unsigned gameId, GameMode mode) = 0; + virtual void SignalNetClientGameListUpdateAdmin(unsigned gameId, unsigned adminPlayerId) = 0; virtual void SignalNetClientGameListPlayerJoined(unsigned gameId, unsigned playerId) = 0; virtual void SignalNetClientGameListPlayerLeft(unsigned gameId, unsigned playerId) = 0; diff --git a/src/net/clientthread.h b/src/net/clientthread.h index 5aa42483..24eff246 100644 --- a/src/net/clientthread.h +++ b/src/net/clientthread.h @@ -128,6 +128,7 @@ protected: unsigned GetGameIdByName(const std::string &name) const; void AddGameInfo(unsigned gameId, const GameInfo &info); void UpdateGameInfoMode(unsigned gameId, GameMode mode); + void UpdateGameInfoAdmin(unsigned gameId, unsigned adminPlayerId); void RemoveGameInfo(unsigned gameId); void ModifyGameInfoAddPlayer(unsigned gameId, unsigned playerId); void ModifyGameInfoRemovePlayer(unsigned gameId, unsigned playerId); diff --git a/src/net/common/clientstate.cpp b/src/net/common/clientstate.cpp index 8047e494..eb39a7aa 100644 --- a/src/net/common/clientstate.cpp +++ b/src/net/common/clientstate.cpp @@ -488,6 +488,12 @@ AbstractClientStateReceiving::Process(ClientThread &client) tmpPacket->ToNetPacketGameListPlayerLeft()->GetData(playerLeftData); client.ModifyGameInfoRemovePlayer(playerLeftData.gameId, playerLeftData.playerId); } + else if (tmpPacket->ToNetPacketGameListAdminChanged()) + { + NetPacketGameListAdminChanged::Data adminChangedData; + tmpPacket->ToNetPacketGameListAdminChanged()->GetData(adminChangedData); + client.UpdateGameInfoAdmin(adminChangedData.gameId, adminChangedData.newAdminplayerId); + } else if (tmpPacket->ToNetPacketAvatarHeader()) { NetPacketAvatarHeader::Data headerData; diff --git a/src/net/common/clientthread.cpp b/src/net/common/clientthread.cpp index 6d951135..4d3ca4fa 100644 --- a/src/net/common/clientthread.cpp +++ b/src/net/common/clientthread.cpp @@ -784,6 +784,23 @@ ClientThread::UpdateGameInfoMode(unsigned gameId, GameMode mode) GetCallback().SignalNetClientGameListUpdateMode(gameId, mode); } +void +ClientThread::UpdateGameInfoAdmin(unsigned gameId, unsigned adminPlayerId) +{ + bool found = false; + { + boost::mutex::scoped_lock lock(m_gameInfoMapMutex); + GameInfoMap::iterator pos = m_gameInfoMap.find(gameId); + if (pos != m_gameInfoMap.end()) + { + found = true; + (*pos).second.adminPlayerId = adminPlayerId; + } + } + if (found) + GetCallback().SignalNetClientGameListUpdateAdmin(gameId, adminPlayerId); +} + void ClientThread::RemoveGameInfo(unsigned gameId) { diff --git a/src/net/common/netpacket.cpp b/src/net/common/netpacket.cpp index 91ef1eea..e79351f0 100644 --- a/src/net/common/netpacket.cpp +++ b/src/net/common/netpacket.cpp @@ -38,6 +38,7 @@ using namespace std; #define NET_TYPE_GAME_LIST_UPDATE 0x0011 #define NET_TYPE_GAME_LIST_PLAYER_JOINED 0x0012 #define NET_TYPE_GAME_LIST_PLAYER_LEFT 0x0013 +#define NET_TYPE_GAME_LIST_ADMIN_CHANGED 0x0014 #define NET_TYPE_RETRIEVE_PLAYER_INFO 0x0020 #define NET_TYPE_PLAYER_INFO 0x0021 #define NET_TYPE_UNKNOWN_PLAYER_ID 0x0022 @@ -197,6 +198,7 @@ struct GCC_PACKED NetPacketGameListNewData { NetPacketHeader head; u_int32_t gameId; + u_int32_t adminPlayerId; u_int16_t gameMode; u_int16_t gameNameLength; u_int16_t curNumberOfPlayers; @@ -226,6 +228,13 @@ struct GCC_PACKED NetPacketGameListPlayerLeftData u_int32_t playerId; }; +struct GCC_PACKED NetPacketGameListAdminChangedData +{ + NetPacketHeader head; + u_int32_t gameId; + u_int32_t newAdminPlayerId; +}; + struct GCC_PACKED NetPacketRetrievePlayerInfoData { NetPacketHeader head; @@ -638,6 +647,9 @@ NetPacket::Create(char *data, unsigned &dataSize) case NET_TYPE_GAME_LIST_PLAYER_LEFT: tmpPacket = boost::shared_ptr(new NetPacketGameListPlayerLeft); break; + case NET_TYPE_GAME_LIST_ADMIN_CHANGED: + tmpPacket = boost::shared_ptr(new NetPacketGameListAdminChanged); + break; case NET_TYPE_RETRIEVE_PLAYER_INFO: tmpPacket = boost::shared_ptr(new NetPacketRetrievePlayerInfo); break; @@ -881,6 +893,12 @@ NetPacket::ToNetPacketGameListPlayerLeft() const return NULL; } +const NetPacketGameListAdminChanged * +NetPacket::ToNetPacketGameListAdminChanged() const +{ + return NULL; +} + const NetPacketRetrievePlayerInfo * NetPacket::ToNetPacketRetrievePlayerInfo() const { @@ -1668,6 +1686,7 @@ NetPacketGameListNew::SetData(const NetPacketGameListNew::Data &inData) // Set the data. tmpData->gameId = htonl(inData.gameId); + tmpData->adminPlayerId = htonl(inData.gameInfo.adminPlayerId); tmpData->gameMode = htons(inData.gameInfo.mode); tmpData->gameNameLength = htons(gameNameLen); tmpData->curNumberOfPlayers = htons(curNumPlayers); @@ -1705,6 +1724,7 @@ NetPacketGameListNew::GetData(NetPacketGameListNew::Data &outData) const int manualBlindsSize = numManualBlinds * sizeof(u_int32_t); outData.gameId = ntohl(tmpData->gameId); + outData.gameInfo.adminPlayerId = ntohl(tmpData->adminPlayerId); outData.gameInfo.mode = static_cast(ntohs(tmpData->gameMode)); u_int16_t gameNameLen = ntohs(tmpData->gameNameLength); u_int16_t curNumPlayers = ntohs(tmpData->curNumberOfPlayers); @@ -1949,6 +1969,66 @@ NetPacketGameListPlayerLeft::InternalCheck(const NetPacketHeader*) const //----------------------------------------------------------------------------- +NetPacketGameListAdminChanged::NetPacketGameListAdminChanged() +: NetPacket(NET_TYPE_GAME_LIST_ADMIN_CHANGED, sizeof(NetPacketGameListAdminChangedData), sizeof(NetPacketGameListAdminChangedData)) +{ +} + +NetPacketGameListAdminChanged::~NetPacketGameListAdminChanged() +{ +} + +boost::shared_ptr +NetPacketGameListAdminChanged::Clone() const +{ + boost::shared_ptr newPacket(new NetPacketGameListAdminChanged); + try + { + newPacket->SetRawData(GetRawData()); + } catch (const NetException &) + { + // Need to return the new packet anyway. + } + return newPacket; +} + +void +NetPacketGameListAdminChanged::SetData(const NetPacketGameListAdminChanged::Data &inData) +{ + NetPacketGameListAdminChangedData *tmpData = (NetPacketGameListAdminChangedData *)GetRawData(); + + // Set the data. + tmpData->gameId = htonl(inData.gameId); + tmpData->newAdminPlayerId = htonl(inData.newAdminplayerId); + + // Check the packet - just in case. + Check(GetRawData()); +} + +void +NetPacketGameListAdminChanged::GetData(NetPacketGameListAdminChanged::Data &outData) const +{ + // We assume that the data is valid. Validity has already been checked. + NetPacketGameListAdminChangedData *tmpData = (NetPacketGameListAdminChangedData *)GetRawData(); + + outData.gameId = ntohl(tmpData->gameId); + outData.newAdminplayerId = ntohl(tmpData->newAdminPlayerId); +} + +const NetPacketGameListAdminChanged * +NetPacketGameListAdminChanged::ToNetPacketGameListAdminChanged() const +{ + return this; +} + +void +NetPacketGameListAdminChanged::InternalCheck(const NetPacketHeader*) const +{ + // Nothing to do. +} + +//----------------------------------------------------------------------------- + NetPacketRetrievePlayerInfo::NetPacketRetrievePlayerInfo() : NetPacket(NET_TYPE_RETRIEVE_PLAYER_INFO, sizeof(NetPacketRetrievePlayerInfoData), sizeof(NetPacketRetrievePlayerInfoData)) { diff --git a/src/net/common/servergamestate.cpp b/src/net/common/servergamestate.cpp index eeeb9f10..38121861 100644 --- a/src/net/common/servergamestate.cpp +++ b/src/net/common/servergamestate.cpp @@ -247,9 +247,9 @@ ServerGameStateInit::HandleNewSession(ServerGameThread &server, SessionWrapper s } else { - if (curNumPlayers == 0) + if (session.playerData->GetUniqueId() == server.GetAdminPlayerId()) { - // First player is admin. + // This is the admin player. session.playerData->SetRights(PLAYER_RIGHTS_ADMIN); } diff --git a/src/net/common/servergamethread.cpp b/src/net/common/servergamethread.cpp index bd9f104f..d0783558 100644 --- a/src/net/common/servergamethread.cpp +++ b/src/net/common/servergamethread.cpp @@ -52,8 +52,9 @@ private: }; -ServerGameThread::ServerGameThread(ServerLobbyThread &lobbyThread, u_int32_t id, const string &name, const string &pwd, GuiInterface &gui, ConfigFile *playerConfig) -: m_lobbyThread(lobbyThread), m_gui(gui), m_id(id), m_name(name), m_password(pwd), m_playerConfig(playerConfig), m_curState(NULL), m_gameNum(1) +ServerGameThread::ServerGameThread(ServerLobbyThread &lobbyThread, u_int32_t id, const string &name, const string &pwd, unsigned adminPlayerId, GuiInterface &gui, ConfigFile *playerConfig) +: m_lobbyThread(lobbyThread), m_adminPlayerId(adminPlayerId), m_gui(gui), m_id(id), + m_name(name), m_password(pwd), m_playerConfig(playerConfig), m_curState(NULL), m_gameNum(1) { m_senderCallback.reset(new ServerSenderCallback(*this)); m_sender.reset(new SenderThread(GetSenderCallback())); @@ -277,6 +278,20 @@ ServerGameThread::IsRunning() const return m_game.get() != NULL; } +unsigned +ServerGameThread::GetAdminPlayerId() const +{ + boost::mutex::scoped_lock lock(m_adminPlayerIdMutex); + return m_adminPlayerId; +} + +void +ServerGameThread::SetAdminPlayerId(unsigned playerId) +{ + boost::mutex::scoped_lock lock(m_adminPlayerIdMutex); + m_adminPlayerId = playerId; +} + void ServerGameThread::AddComputerPlayer(boost::shared_ptr player) { @@ -321,13 +336,6 @@ ServerGameThread::GracefulRemoveSession(SessionWrapper session) void ServerGameThread::RemovePlayerData(boost::shared_ptr player) { - // Send "Player Left" to clients. - boost::shared_ptr thisPlayerLeft(new NetPacketPlayerLeft); - NetPacketPlayerLeft::Data thisPlayerLeftData; - thisPlayerLeftData.playerId = player->GetUniqueId(); - static_cast(thisPlayerLeft.get())->SetData(thisPlayerLeftData); - GetSessionManager().SendToAllSessions(GetSender(), thisPlayerLeft, SessionData::Game); - if (player->GetRights() == PLAYER_RIGHTS_ADMIN) { // Find new admin for the game @@ -335,6 +343,7 @@ ServerGameThread::RemovePlayerData(boost::shared_ptr player) if (!playerList.empty()) { boost::shared_ptr newAdmin = playerList.front(); + SetAdminPlayerId(newAdmin->GetUniqueId()); newAdmin->SetRights(PLAYER_RIGHTS_ADMIN); // Send "Game Admin Changed" to clients. boost::shared_ptr adminChanged(new NetPacketGameAdminChanged); @@ -342,11 +351,20 @@ ServerGameThread::RemovePlayerData(boost::shared_ptr player) adminChangedData.playerId = newAdmin->GetUniqueId(); // Choose next player as admin. static_cast(adminChanged.get())->SetData(adminChangedData); GetSessionManager().SendToAllSessions(GetSender(), adminChanged, SessionData::Game); + + GetLobbyThread().NotifyGameAdminChanged(GetId(), newAdmin->GetUniqueId()); } } // Reset player rights. player->SetRights(PLAYER_RIGHTS_NORMAL); + // Send "Player Left" to clients. + boost::shared_ptr thisPlayerLeft(new NetPacketPlayerLeft); + NetPacketPlayerLeft::Data thisPlayerLeftData; + thisPlayerLeftData.playerId = player->GetUniqueId(); + static_cast(thisPlayerLeft.get())->SetData(thisPlayerLeftData); + GetSessionManager().SendToAllSessions(GetSender(), thisPlayerLeft, SessionData::Game); + GetLobbyThread().NotifyPlayerLeftGame(GetId(), player->GetUniqueId()); } diff --git a/src/net/common/serverlobbythread.cpp b/src/net/common/serverlobbythread.cpp index f313da28..bed37461 100644 --- a/src/net/common/serverlobbythread.cpp +++ b/src/net/common/serverlobbythread.cpp @@ -154,6 +154,19 @@ ServerLobbyThread::NotifyPlayerLeftGame(unsigned gameId, unsigned playerId) m_gameSessionManager.SendToAllSessions(GetSender(), packet, SessionData::Game); } +void +ServerLobbyThread::NotifyGameAdminChanged(unsigned gameId, unsigned newAdminPlayerId) +{ + // Send notification to players in lobby. + boost::shared_ptr packet(new NetPacketGameListAdminChanged); + NetPacketGameListAdminChanged::Data packetData; + packetData.gameId = gameId; + packetData.newAdminplayerId = newAdminPlayerId; + static_cast(packet.get())->SetData(packetData); + m_sessionManager.SendToAllSessions(GetSender(), packet, SessionData::Established); + m_gameSessionManager.SendToAllSessions(GetSender(), packet, SessionData::Game); +} + void ServerLobbyThread::NotifyStartingGame(unsigned gameId) { @@ -556,9 +569,11 @@ ServerLobbyThread::HandleNetPacketCreateGame(SessionWrapper session, const NetPa boost::shared_ptr game( new ServerGameThread( - *this, GetNextGameId(), + *this, + GetNextGameId(), createGameData.gameName, createGameData.password, + session.playerData->GetUniqueId(), GetGui(), m_playerConfig)); game->Init(createGameData.gameData); @@ -870,6 +885,7 @@ ServerLobbyThread::CreateNetPacketGameListNew(const ServerGameThread &game) boost::shared_ptr packet(new NetPacketGameListNew); NetPacketGameListNew::Data packetData; packetData.gameId = game.GetId(); + packetData.gameInfo.adminPlayerId = game.GetAdminPlayerId(); packetData.gameInfo.mode = game.IsRunning() ? GAME_MODE_STARTED : GAME_MODE_CREATED; packetData.gameInfo.name = game.GetName(); packetData.gameInfo.data = game.GetGameData(); diff --git a/src/net/netpacket.h b/src/net/netpacket.h index 9aa9938f..b0538b80 100644 --- a/src/net/netpacket.h +++ b/src/net/netpacket.h @@ -57,6 +57,7 @@ class NetPacketGameListNew; class NetPacketGameListUpdate; class NetPacketGameListPlayerJoined; class NetPacketGameListPlayerLeft; +class NetPacketGameListAdminChanged; class NetPacketRetrievePlayerInfo; class NetPacketPlayerInfo; class NetPacketUnknownPlayerId; @@ -117,6 +118,7 @@ public: virtual const NetPacketGameListUpdate *ToNetPacketGameListUpdate() const; virtual const NetPacketGameListPlayerJoined *ToNetPacketGameListPlayerJoined() const; virtual const NetPacketGameListPlayerLeft *ToNetPacketGameListPlayerLeft() const; + virtual const NetPacketGameListAdminChanged *ToNetPacketGameListAdminChanged() const; virtual const NetPacketRetrievePlayerInfo *ToNetPacketRetrievePlayerInfo() const; virtual const NetPacketPlayerInfo *ToNetPacketPlayerInfo() const; virtual const NetPacketUnknownPlayerId *ToNetPacketUnknownPlayerId() const; @@ -436,6 +438,30 @@ protected: virtual void InternalCheck(const NetPacketHeader* data) const; }; +class NetPacketGameListAdminChanged : public NetPacket +{ +public: + struct Data + { + u_int32_t gameId; + u_int32_t newAdminplayerId; + }; + + NetPacketGameListAdminChanged(); + virtual ~NetPacketGameListAdminChanged(); + + virtual boost::shared_ptr Clone() const; + + void SetData(const Data &inData); + void GetData(Data &outData) const; + + virtual const NetPacketGameListAdminChanged *ToNetPacketGameListAdminChanged() const; + +protected: + + virtual void InternalCheck(const NetPacketHeader* data) const; +}; + class NetPacketRetrievePlayerInfo : public NetPacket { public: diff --git a/src/net/servergamethread.h b/src/net/servergamethread.h index d0ff709d..b3e839f6 100644 --- a/src/net/servergamethread.h +++ b/src/net/servergamethread.h @@ -42,7 +42,8 @@ class Game; class ServerGameThread : public Thread { public: - ServerGameThread(ServerLobbyThread &lobbyThread, u_int32_t id, const std::string &name, const std::string &pwd, GuiInterface &gui, ConfigFile *playerConfig); + ServerGameThread( + ServerLobbyThread &lobbyThread, u_int32_t id, const std::string &name, const std::string &pwd, unsigned adminPlayerId, GuiInterface &gui, ConfigFile *playerConfig); virtual ~ServerGameThread(); void Init(const GameData &gameData); @@ -68,6 +69,9 @@ public: bool IsRunning() const; + unsigned GetAdminPlayerId() const; + void SetAdminPlayerId(unsigned playerId); + // should be protected, but is needed in function. const Game &GetGame() const; Game &GetGame(); @@ -127,6 +131,9 @@ private: PlayerDataList m_computerPlayerList; mutable boost::mutex m_computerPlayerListMutex; + unsigned m_adminPlayerId; + mutable boost::mutex m_adminPlayerIdMutex; + ServerLobbyThread &m_lobbyThread; std::auto_ptr m_receiver; std::auto_ptr m_sender; diff --git a/src/net/serverlobbythread.h b/src/net/serverlobbythread.h index 443dca99..b372b6d4 100644 --- a/src/net/serverlobbythread.h +++ b/src/net/serverlobbythread.h @@ -58,6 +58,7 @@ public: void SessionError(SessionWrapper session, int errorCode); void NotifyPlayerJoinedGame(unsigned gameId, unsigned playerId); void NotifyPlayerLeftGame(unsigned gameId, unsigned playerId); + void NotifyGameAdminChanged(unsigned gameId, unsigned newAdminPlayerId); void NotifyStartingGame(unsigned gameId); void NotifyReopeningGame(unsigned gameId);