diff --git a/docs/net_protocol.txt b/docs/net_protocol.txt index da37e4eb..64e6bd18 100644 --- a/docs/net_protocol.txt +++ b/docs/net_protocol.txt @@ -85,6 +85,8 @@ Server Notification: Game List New +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Game Mode | Game Name Length | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Current Number of Players | Game Flags | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Game ID | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Max Number of Players | Small Blind | @@ -100,6 +102,12 @@ Server Notification: Game List New | +-------------------------------+ / | padding | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Player ID Slot #1 | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | \ + \ Additional Player Slots / + / | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ Game List notifications will be automatically sent if the player is in the lobby. If a game is joined/started, no more messages will be sent. As soon as the player leaves a game without @@ -109,6 +117,8 @@ Game Mode: 1: Game Created 2: Game Started 3: Game Closed (only for Game List Update) +Game Flags: + 0x01 set: Game is password protected Server Notification: Game List Update diff --git a/src/gamedata.h b/src/gamedata.h index 9092d072..eeadd962 100644 --- a/src/gamedata.h +++ b/src/gamedata.h @@ -21,7 +21,7 @@ #ifndef _GAMEDATA_H_ #define _GAMEDATA_H_ -#include +#include enum GameMode { @@ -49,6 +49,7 @@ struct GameInfo std::string name; GameData data; GameMode mode; + PlayerIdList players; bool isPasswordProtected; }; diff --git a/src/net/common/netpacket.cpp b/src/net/common/netpacket.cpp index 4d53fa14..e7e285a2 100644 --- a/src/net/common/netpacket.cpp +++ b/src/net/common/netpacket.cpp @@ -61,6 +61,8 @@ using namespace std; #define NET_TYPE_ERROR 0x0400 +#define NET_GAME_FLAG_PASSWORD_PROTECTED 0x01 + #define NET_PLAYER_FLAG_HUMAN 0x01 #define NET_PLAYER_FLAG_ADMIN 0x02 @@ -112,6 +114,8 @@ struct GCC_PACKED NetPacketGameListNewData u_int32_t gameId; u_int16_t gameMode; u_int16_t gameNameLength; + u_int16_t curNumberOfPlayers; + u_int16_t gameFlags; u_int16_t maxNumberOfPlayers; u_int16_t smallBlind; u_int16_t handsBeforeRaise; @@ -1011,6 +1015,7 @@ void NetPacketGameListNew::SetData(const NetPacketGameListNew::Data &inData) { u_int16_t gameNameLen = (u_int16_t)inData.gameInfo.name.length(); + u_int16_t curNumPlayers = (u_int16_t)inData.gameInfo.players.size(); // Some basic checks, so we don't use up too much memory. // The constructed packet will also be checked. @@ -1019,7 +1024,10 @@ NetPacketGameListNew::SetData(const NetPacketGameListNew::Data &inData) // Resize the packet so that the data fits in. Resize((u_int16_t) - (sizeof(NetPacketGameListNewData) + ADD_PADDING(gameNameLen))); + (sizeof(NetPacketGameListNewData) + + ADD_PADDING(gameNameLen) + + curNumPlayers * sizeof(unsigned) + )); NetPacketGameListNewData *tmpData = (NetPacketGameListNewData *)GetRawData(); @@ -1027,6 +1035,8 @@ NetPacketGameListNew::SetData(const NetPacketGameListNew::Data &inData) tmpData->gameId = htonl(inData.gameId); tmpData->gameMode = htons(inData.gameInfo.mode); tmpData->gameNameLength = htons(gameNameLen); + tmpData->curNumberOfPlayers = htons(curNumPlayers); + tmpData->gameFlags = htons(inData.gameInfo.isPasswordProtected ? NET_GAME_FLAG_PASSWORD_PROTECTED : 0); tmpData->maxNumberOfPlayers = htons(inData.gameInfo.data.maxNumberOfPlayers); tmpData->smallBlind = htons(inData.gameInfo.data.smallBlind); tmpData->handsBeforeRaise = htons(inData.gameInfo.data.handsBeforeRaise); @@ -1037,6 +1047,19 @@ NetPacketGameListNew::SetData(const NetPacketGameListNew::Data &inData) char *gameNamePtr = (char *)tmpData + sizeof(NetPacketGameListNewData); memcpy(gameNamePtr, inData.gameInfo.name.c_str(), gameNameLen); + PlayerIdList::const_iterator i = inData.gameInfo.players.begin(); + PlayerIdList::const_iterator end = inData.gameInfo.players.end(); + + // Copy the player list to continous memory + unsigned *tmpPlayer = + (unsigned *)((char *)tmpData + sizeof(NetPacketGameListNewData) + ADD_PADDING(gameNameLen)); + while (i != end) + { + *tmpPlayer = htonl(*i); + ++tmpPlayer; + ++i; + } + // Check the packet - just in case. Check(GetRawData()); } @@ -1050,6 +1073,8 @@ NetPacketGameListNew::GetData(NetPacketGameListNew::Data &outData) const outData.gameId = ntohl(tmpData->gameId); outData.gameInfo.mode = static_cast(ntohs(tmpData->gameMode)); u_int16_t gameNameLen = ntohs(tmpData->gameNameLength); + u_int16_t curNumPlayers = ntohs(tmpData->curNumberOfPlayers); + outData.gameInfo.isPasswordProtected = ntohs(tmpData->gameFlags) == NET_GAME_FLAG_PASSWORD_PROTECTED; outData.gameInfo.data.maxNumberOfPlayers = ntohs(tmpData->maxNumberOfPlayers); outData.gameInfo.data.smallBlind = ntohs(tmpData->smallBlind); outData.gameInfo.data.handsBeforeRaise = ntohs(tmpData->handsBeforeRaise); @@ -1059,6 +1084,16 @@ NetPacketGameListNew::GetData(NetPacketGameListNew::Data &outData) const char *gameNamePtr = (char *)tmpData + sizeof(NetPacketGameListNewData); outData.gameInfo.name = string(gameNamePtr, gameNameLen); + + unsigned *tmpPlayer = + (unsigned *)((char *)tmpData + sizeof(NetPacketGameListNewData) + ADD_PADDING(gameNameLen)); + + // Store all available players. + for (int i = 0; i < curNumPlayers; i++) + { + outData.gameInfo.players.push_back(*tmpPlayer); + ++tmpPlayer; + } } const NetPacketGameListNew * @@ -1073,10 +1108,12 @@ NetPacketGameListNew::InternalCheck(const NetPacketHeader* data) const u_int16_t dataLen = ntohs(data->length); NetPacketGameListNewData *tmpData = (NetPacketGameListNewData *)data; int gameNameLength = ntohs(tmpData->gameNameLength); + int curNumPlayers = ntohs(tmpData->curNumberOfPlayers); // Exact checking of dynamic packet size. if (dataLen != sizeof(NetPacketGameListNewData) - + ADD_PADDING(gameNameLength)) + + ADD_PADDING(gameNameLength) + + curNumPlayers * sizeof(unsigned)) { throw NetException(ERR_SOCK_INVALID_PACKET, 0); } diff --git a/src/net/common/serverlobbythread.cpp b/src/net/common/serverlobbythread.cpp index 761b98a6..e5f96c69 100644 --- a/src/net/common/serverlobbythread.cpp +++ b/src/net/common/serverlobbythread.cpp @@ -556,6 +556,7 @@ ServerLobbyThread::CreateNetPacketGameListNew(const ServerGameThread &game) packetData.gameInfo.mode = GAME_MODE_CREATED; packetData.gameInfo.name = game.GetName(); packetData.gameInfo.data = game.GetGameData(); + packetData.gameInfo.players = game.GetSessionManager().GetPlayerIdList(); static_cast(packet.get())->SetData(packetData); return packet; } diff --git a/src/net/common/sessionmanager.cpp b/src/net/common/sessionmanager.cpp index cf2f6406..eabc8c4b 100644 --- a/src/net/common/sessionmanager.cpp +++ b/src/net/common/sessionmanager.cpp @@ -219,6 +219,27 @@ SessionManager::GetPlayerDataList() const return playerList; } +PlayerIdList +SessionManager::GetPlayerIdList() const +{ + PlayerIdList playerList; + boost::mutex::scoped_lock lock(m_sessionMapMutex); + + SessionMap::const_iterator session_i = m_sessionMap.begin(); + SessionMap::const_iterator session_end = m_sessionMap.end(); + + while (session_i != session_end) + { + // Get all players in the game. + if (session_i->second.sessionData->GetState() == SessionData::Game) + { + playerList.push_back(session_i->second.playerData->GetUniqueId()); + } + ++session_i; + } + return playerList; +} + bool SessionManager::IsPlayerConnected(const string &playerName) const { diff --git a/src/net/sessionmanager.h b/src/net/sessionmanager.h index 9ef49ce4..9debe541 100644 --- a/src/net/sessionmanager.h +++ b/src/net/sessionmanager.h @@ -58,6 +58,7 @@ public: SessionWrapper GetSessionByUniquePlayerId(unsigned uniqueId) const; PlayerDataList GetPlayerDataList() const; + PlayerIdList GetPlayerIdList() const; bool IsPlayerConnected(const std::string &playerName) const; bool IsPlayerConnected(unsigned uniqueId) const; diff --git a/src/playerdata.h b/src/playerdata.h index 7bec57a8..ccafc09a 100644 --- a/src/playerdata.h +++ b/src/playerdata.h @@ -93,6 +93,7 @@ private: boost::shared_ptr m_netSessionData; }; +typedef std::list PlayerIdList; typedef std::list > PlayerDataList; typedef std::map > PlayerDataMap;