(Hopefully) solved the player number problem, when players join and leave an existing game. Numbers are now assigned on game start, not before. Note: Network play is not compatible to the current official version.
This commit is contained in:
@@ -77,8 +77,8 @@ protected:
|
||||
void SetGameData(const GameData &gameData);
|
||||
const StartData &GetStartData() const;
|
||||
void SetStartData(const StartData &startData);
|
||||
int GetGuiPlayerNum() const;
|
||||
void SetGuiPlayerNum(int guiPlayerNum);
|
||||
int GetGuiPlayerId() const;
|
||||
void SetGuiPlayerId(int guiPlayerId);
|
||||
|
||||
boost::shared_ptr<Game> GetGame();
|
||||
|
||||
@@ -109,7 +109,7 @@ private:
|
||||
boost::shared_ptr<Game> m_game;
|
||||
|
||||
unsigned m_curGameId;
|
||||
int m_guiPlayerNum;
|
||||
unsigned m_guiPlayerId;
|
||||
|
||||
friend class AbstractClientStateReceiving;
|
||||
friend class ClientStateInit;
|
||||
|
||||
@@ -443,11 +443,12 @@ ClientStateWaitSession::InternalProcess(ClientThread &client, boost::shared_ptr<
|
||||
NetPacketJoinGameAck::Data joinGameAckData;
|
||||
packet->ToNetPacketJoinGameAck()->GetData(joinGameAckData);
|
||||
client.SetGameData(joinGameAckData.gameData);
|
||||
client.SetGuiPlayerNum(joinGameAckData.yourPlayerNum);
|
||||
client.SetGuiPlayerId(joinGameAckData.yourPlayerUniqueId);
|
||||
|
||||
// TODO: Type Human is fixed here.
|
||||
// Player number is 0 on join. Will be set when the game starts.
|
||||
boost::shared_ptr<PlayerData> playerData(
|
||||
new PlayerData(joinGameAckData.yourPlayerUniqueId, joinGameAckData.yourPlayerNum, PLAYER_TYPE_HUMAN));
|
||||
new PlayerData(joinGameAckData.yourPlayerUniqueId, 0, PLAYER_TYPE_HUMAN));
|
||||
playerData->SetName(context.GetPlayerName());
|
||||
client.AddPlayerData(playerData);
|
||||
|
||||
@@ -489,6 +490,23 @@ ClientStateWaitGame::InternalProcess(ClientThread &client, boost::shared_ptr<Net
|
||||
|
||||
client.SetStartData(gameStartData.startData);
|
||||
|
||||
// Set player numbers using the game start data slots.
|
||||
NetPacketGameStart::PlayerSlotList::const_iterator slot_i = gameStartData.playerSlots.begin();
|
||||
NetPacketGameStart::PlayerSlotList::const_iterator slot_end = gameStartData.playerSlots.end();
|
||||
int num = 0;
|
||||
|
||||
while (slot_i != slot_end)
|
||||
{
|
||||
unsigned playerId = (*slot_i).playerId;
|
||||
boost::shared_ptr<PlayerData> tmpPlayer = client.GetPlayerDataByUniqueId(playerId);
|
||||
if (!tmpPlayer.get())
|
||||
throw ClientException(ERR_NET_UNKNOWN_PLAYER_ID, 0);
|
||||
tmpPlayer->SetNumber(num);
|
||||
|
||||
++num;
|
||||
++slot_i;
|
||||
}
|
||||
|
||||
client.SetState(ClientStateWaitHand::Instance());
|
||||
retVal = MSG_NET_GAME_CLIENT_START;
|
||||
}
|
||||
@@ -499,11 +517,10 @@ ClientStateWaitGame::InternalProcess(ClientThread &client, boost::shared_ptr<Net
|
||||
packet->ToNetPacketPlayerJoined()->GetData(netPlayerData);
|
||||
|
||||
boost::shared_ptr<PlayerData> playerData(
|
||||
new PlayerData(netPlayerData.playerId, netPlayerData.playerNumber, netPlayerData.ptype));
|
||||
new PlayerData(netPlayerData.playerId, 0, netPlayerData.ptype));
|
||||
playerData->SetName(netPlayerData.playerName);
|
||||
client.AddPlayerData(playerData);
|
||||
}
|
||||
// TODO: handle error packet (kicked from server)
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
@@ -53,7 +53,7 @@ private:
|
||||
|
||||
|
||||
ClientThread::ClientThread(GuiInterface &gui)
|
||||
: m_curState(NULL), m_gui(gui), m_curGameId(1), m_guiPlayerNum(0)
|
||||
: m_curState(NULL), m_gui(gui), m_curGameId(1), m_guiPlayerId(0)
|
||||
{
|
||||
m_context.reset(new ClientContext);
|
||||
m_senderCallback.reset(new ClientSenderCallback(*this));
|
||||
@@ -244,15 +244,15 @@ ClientThread::SetStartData(const StartData &startData)
|
||||
}
|
||||
|
||||
int
|
||||
ClientThread::GetGuiPlayerNum() const
|
||||
ClientThread::GetGuiPlayerId() const
|
||||
{
|
||||
return m_guiPlayerNum;
|
||||
return m_guiPlayerId;
|
||||
}
|
||||
|
||||
void
|
||||
ClientThread::SetGuiPlayerNum(int guiPlayerNum)
|
||||
ClientThread::SetGuiPlayerId(int guiPlayerId)
|
||||
{
|
||||
m_guiPlayerNum = guiPlayerNum;
|
||||
m_guiPlayerId = guiPlayerId;
|
||||
}
|
||||
|
||||
boost::shared_ptr<Game>
|
||||
@@ -303,21 +303,27 @@ ClientThread::RemovePlayerData(unsigned playerId)
|
||||
void
|
||||
ClientThread::MapPlayerDataList()
|
||||
{
|
||||
// Retrieve the GUI player.
|
||||
boost::shared_ptr<PlayerData> guiPlayer = GetPlayerDataByUniqueId(GetGuiPlayerId());
|
||||
assert(guiPlayer.get());
|
||||
int guiPlayerNum = guiPlayer->GetNumber();
|
||||
|
||||
// Create a copy of the player list so that the GUI player
|
||||
// is player 0. This is mapped because the GUI depends on it.
|
||||
PlayerDataList mappedList;
|
||||
|
||||
PlayerDataList::const_iterator i = m_playerDataList.begin();
|
||||
PlayerDataList::const_iterator end = m_playerDataList.end();
|
||||
int numPlayers = GetStartData().numberOfPlayers;
|
||||
|
||||
// Create a copy of the player list so that the GUI player
|
||||
// is player 0. This is mapped because the GUI depends on it.
|
||||
while (i != end)
|
||||
{
|
||||
boost::shared_ptr<PlayerData> tmpData(new PlayerData(*(*i)));
|
||||
int numberDiff = tmpData->GetNumber() - GetGuiPlayerNum();
|
||||
int numberDiff = tmpData->GetNumber() - guiPlayerNum;
|
||||
if (numberDiff >= 0)
|
||||
tmpData->SetNumber(numberDiff);
|
||||
else
|
||||
tmpData->SetNumber(GetStartData().numberOfPlayers + numberDiff);
|
||||
tmpData->SetNumber(numPlayers + numberDiff);
|
||||
mappedList.push_back(tmpData);
|
||||
++i;
|
||||
}
|
||||
@@ -326,7 +332,6 @@ ClientThread::MapPlayerDataList()
|
||||
mappedList.sort(*boost::lambda::_1 < *boost::lambda::_2);
|
||||
|
||||
m_playerDataList = mappedList;
|
||||
SetGuiPlayerNum(0);
|
||||
}
|
||||
|
||||
const PlayerDataList &
|
||||
|
||||
@@ -93,13 +93,11 @@ struct GCC_PACKED NetPacketJoinGameAckData
|
||||
NetPacketHeader head;
|
||||
u_int32_t sessionId;
|
||||
u_int16_t playerId;
|
||||
u_int16_t playerNumber;
|
||||
u_int16_t maxNumberOfPlayers;
|
||||
u_int16_t smallBlind;
|
||||
u_int16_t handsBeforeRaise;
|
||||
u_int16_t proposedGuiSpeed;
|
||||
u_int16_t playerActionTimeout;
|
||||
u_int16_t reserved;
|
||||
u_int32_t startMoney;
|
||||
};
|
||||
|
||||
@@ -114,9 +112,9 @@ struct GCC_PACKED NetPacketPlayerJoinedData
|
||||
{
|
||||
NetPacketHeader head;
|
||||
u_int16_t playerId;
|
||||
u_int16_t playerNumber;
|
||||
u_int16_t playerFlags;
|
||||
u_int16_t playerNameLength;
|
||||
u_int16_t reserved;
|
||||
};
|
||||
|
||||
struct GCC_PACKED NetPacketPlayerLeftData
|
||||
@@ -133,6 +131,11 @@ struct GCC_PACKED NetPacketGameStartData
|
||||
u_int16_t numberOfPlayers;
|
||||
};
|
||||
|
||||
struct GCC_PACKED PlayerSlotData
|
||||
{
|
||||
u_int16_t playerId;
|
||||
};
|
||||
|
||||
struct GCC_PACKED NetPacketHandStartData
|
||||
{
|
||||
NetPacketHeader head;
|
||||
@@ -736,7 +739,6 @@ NetPacketJoinGameAck::SetData(const NetPacketJoinGameAck::Data &inData)
|
||||
|
||||
tmpData->sessionId = htonl(inData.sessionId);
|
||||
tmpData->playerId = htons(inData.yourPlayerUniqueId);
|
||||
tmpData->playerNumber = htons(inData.yourPlayerNum);
|
||||
tmpData->maxNumberOfPlayers = htons(inData.gameData.maxNumberOfPlayers);
|
||||
tmpData->smallBlind = htons(inData.gameData.smallBlind);
|
||||
tmpData->handsBeforeRaise = htons(inData.gameData.handsBeforeRaise);
|
||||
@@ -753,7 +755,6 @@ NetPacketJoinGameAck::GetData(NetPacketJoinGameAck::Data &outData) const
|
||||
|
||||
outData.sessionId = ntohl(tmpData->sessionId);
|
||||
outData.yourPlayerUniqueId = ntohs(tmpData->playerId);
|
||||
outData.yourPlayerNum = ntohs(tmpData->playerNumber);
|
||||
outData.gameData.maxNumberOfPlayers = ntohs(tmpData->maxNumberOfPlayers);
|
||||
outData.gameData.smallBlind = ntohs(tmpData->smallBlind);
|
||||
outData.gameData.handsBeforeRaise = ntohs(tmpData->handsBeforeRaise);
|
||||
@@ -824,7 +825,6 @@ NetPacketPlayerJoined::SetData(const NetPacketPlayerJoined::Data &inData)
|
||||
// Set the data.
|
||||
tmpData->playerFlags = htons((inData.ptype == PLAYER_TYPE_HUMAN) ? NET_PLAYER_FLAG_HUMAN : 0);
|
||||
tmpData->playerId = htons(inData.playerId);
|
||||
tmpData->playerNumber = htons(inData.playerNumber);
|
||||
tmpData->playerNameLength = htons(playerNameLen);
|
||||
char *namePtr = (char *)tmpData + sizeof(NetPacketPlayerJoinedData);
|
||||
memcpy(namePtr, inData.playerName.c_str(), playerNameLen);
|
||||
@@ -839,7 +839,6 @@ NetPacketPlayerJoined::GetData(NetPacketPlayerJoined::Data &outData) const
|
||||
|
||||
outData.ptype = (ntohs(tmpData->playerFlags) & NET_PLAYER_FLAG_HUMAN) ? PLAYER_TYPE_HUMAN : PLAYER_TYPE_COMPUTER;
|
||||
outData.playerId = ntohs(tmpData->playerId);
|
||||
outData.playerNumber = ntohs(tmpData->playerNumber);
|
||||
char *namePtr = (char *)tmpData + sizeof(NetPacketPlayerJoinedData);
|
||||
outData.playerName = string(namePtr, ntohs(tmpData->playerNameLength));
|
||||
}
|
||||
@@ -969,11 +968,33 @@ NetPacketGameStart::Clone() const
|
||||
void
|
||||
NetPacketGameStart::SetData(const NetPacketGameStart::Data &inData)
|
||||
{
|
||||
u_int16_t numPlayers = (u_int16_t)inData.playerSlots.size();
|
||||
|
||||
if (!numPlayers || numPlayers > MAX_NUMBER_OF_PLAYERS || numPlayers != inData.startData.numberOfPlayers)
|
||||
throw NetException(ERR_NET_INVALID_PLAYER_COUNT, 0);
|
||||
|
||||
// Resize the packet so that the data fits in.
|
||||
Resize((u_int16_t)
|
||||
(sizeof(NetPacketGameStartData) + ADD_PADDING(numPlayers * sizeof(PlayerSlotData))));
|
||||
|
||||
NetPacketGameStartData *tmpData = (NetPacketGameStartData *)GetRawData();
|
||||
assert(tmpData);
|
||||
|
||||
tmpData->startDealerPlayerId = htons(inData.startData.startDealerPlayerId);
|
||||
tmpData->numberOfPlayers = htons(inData.startData.numberOfPlayers);
|
||||
tmpData->numberOfPlayers = htons(numPlayers);
|
||||
|
||||
PlayerSlotList::const_iterator i = inData.playerSlots.begin();
|
||||
PlayerSlotList::const_iterator end = inData.playerSlots.end();
|
||||
|
||||
// Copy the player slot data to continous memory
|
||||
PlayerSlotData *curPlayerSlotData =
|
||||
(PlayerSlotData *)((char *)tmpData + sizeof(NetPacketGameStartData));
|
||||
while (i != end)
|
||||
{
|
||||
curPlayerSlotData->playerId = htons((*i).playerId);
|
||||
++curPlayerSlotData;
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@@ -983,7 +1004,21 @@ NetPacketGameStart::GetData(NetPacketGameStart::Data &outData) const
|
||||
assert(tmpData);
|
||||
|
||||
outData.startData.startDealerPlayerId = ntohs(tmpData->startDealerPlayerId);
|
||||
outData.startData.numberOfPlayers = ntohs(tmpData->numberOfPlayers);
|
||||
u_int16_t numPlayers = ntohs(tmpData->numberOfPlayers);
|
||||
outData.startData.numberOfPlayers = numPlayers;
|
||||
|
||||
PlayerSlotData *curPlayerSlotData =
|
||||
(PlayerSlotData *)((char *)tmpData + sizeof(NetPacketGameStartData));
|
||||
|
||||
// Store all available player slots.
|
||||
for (int i = 0; i < numPlayers; i++)
|
||||
{
|
||||
PlayerSlot tmpPlayerSlot;
|
||||
tmpPlayerSlot.playerId = ntohs(curPlayerSlotData->playerId);
|
||||
|
||||
outData.playerSlots.push_back(tmpPlayerSlot);
|
||||
++curPlayerSlotData;
|
||||
}
|
||||
}
|
||||
|
||||
const NetPacketGameStart *
|
||||
@@ -998,10 +1033,11 @@ NetPacketGameStart::Check(const NetPacketHeader* data) const
|
||||
assert(data);
|
||||
|
||||
u_int16_t dataLen = ntohs(data->length);
|
||||
if (dataLen != sizeof(NetPacketGameStartData))
|
||||
if (dataLen < sizeof(NetPacketGameStartData))
|
||||
{
|
||||
throw NetException(ERR_SOCK_INVALID_PACKET, 0);
|
||||
}
|
||||
// TODO additional checking
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
@@ -290,7 +290,7 @@ ServerRecvStateInit::InternalProcess(ServerRecvThread &server, SessionWrapper se
|
||||
|
||||
// Create player data object.
|
||||
boost::shared_ptr<PlayerData> tmpPlayerData(
|
||||
new PlayerData(m_curUniquePlayerId++, server.GetNextPlayerNumber(), joinGameData.ptype));
|
||||
new PlayerData(m_curUniquePlayerId++, 0, joinGameData.ptype));
|
||||
tmpPlayerData->SetName(joinGameData.playerName);
|
||||
tmpPlayerData->SetNetSessionData(session.sessionData);
|
||||
|
||||
@@ -299,7 +299,6 @@ ServerRecvStateInit::InternalProcess(ServerRecvThread &server, SessionWrapper se
|
||||
NetPacketJoinGameAck::Data joinGameAckData;
|
||||
joinGameAckData.sessionId = session.sessionData->GetId(); // TODO: currently unused.
|
||||
joinGameAckData.yourPlayerUniqueId = tmpPlayerData->GetUniqueId();
|
||||
joinGameAckData.yourPlayerNum = tmpPlayerData->GetNumber();
|
||||
joinGameAckData.gameData = server.GetGameData();
|
||||
static_cast<NetPacketJoinGameAck *>(answer.get())->SetData(joinGameAckData);
|
||||
server.GetSender().Send(session.sessionData->GetSocket(), answer);
|
||||
@@ -314,7 +313,6 @@ ServerRecvStateInit::InternalProcess(ServerRecvThread &server, SessionWrapper se
|
||||
NetPacketPlayerJoined::Data otherPlayerJoinedData;
|
||||
otherPlayerJoinedData.playerId = (*player_i)->GetUniqueId();
|
||||
otherPlayerJoinedData.playerName = (*player_i)->GetName();
|
||||
otherPlayerJoinedData.playerNumber = (*player_i)->GetNumber();
|
||||
otherPlayerJoinedData.ptype = (*player_i)->GetType();
|
||||
static_cast<NetPacketPlayerJoined *>(otherPlayerJoined.get())->SetData(otherPlayerJoinedData);
|
||||
server.GetSender().Send(session.sessionData->GetSocket(), otherPlayerJoined);
|
||||
@@ -327,7 +325,6 @@ ServerRecvStateInit::InternalProcess(ServerRecvThread &server, SessionWrapper se
|
||||
NetPacketPlayerJoined::Data thisPlayerJoinedData;
|
||||
thisPlayerJoinedData.playerId = tmpPlayerData->GetUniqueId();
|
||||
thisPlayerJoinedData.playerName = tmpPlayerData->GetName();
|
||||
thisPlayerJoinedData.playerNumber = tmpPlayerData->GetNumber();
|
||||
thisPlayerJoinedData.ptype = tmpPlayerData->GetType();
|
||||
static_cast<NetPacketPlayerJoined *>(thisPlayerJoined.get())->SetData(thisPlayerJoinedData);
|
||||
server.SendToAllPlayers(thisPlayerJoined);
|
||||
@@ -382,6 +379,20 @@ ServerRecvStateStartGame::Process(ServerRecvThread &server)
|
||||
|
||||
NetPacketGameStart::Data gameStartData;
|
||||
gameStartData.startData = server.GetStartData();
|
||||
|
||||
// Assign player numbers. Assume Player List is sorted by number.
|
||||
PlayerDataList tmpPlayerList = server.GetPlayerDataList();
|
||||
PlayerDataList::iterator player_i = tmpPlayerList.begin();
|
||||
PlayerDataList::iterator player_end = tmpPlayerList.end();
|
||||
while (player_i != player_end)
|
||||
{
|
||||
NetPacketGameStart::PlayerSlot tmpPlayerSlot;
|
||||
tmpPlayerSlot.playerId = (*player_i)->GetUniqueId();
|
||||
gameStartData.playerSlots.push_back(tmpPlayerSlot);
|
||||
|
||||
++player_i;
|
||||
}
|
||||
|
||||
static_cast<NetPacketGameStart *>(answer.get())->SetData(gameStartData);
|
||||
|
||||
server.SendToAllPlayers(answer);
|
||||
|
||||
@@ -253,6 +253,8 @@ ServerRecvThread::InternalStartGame()
|
||||
|
||||
// Kick all players which are not fully connected.
|
||||
RemoveNotEstablishedSessions();
|
||||
// Set order of players.
|
||||
AssignPlayerNumbers();
|
||||
|
||||
// Initialize the game.
|
||||
GuiInterface &gui = GetGui();
|
||||
@@ -559,31 +561,24 @@ ServerRecvThread::GetPlayerDataList() const
|
||||
}
|
||||
++session_i;
|
||||
}
|
||||
// Sort the list by player number.
|
||||
playerList.sort(*boost::lambda::_1 < *boost::lambda::_2);
|
||||
return playerList;
|
||||
}
|
||||
|
||||
int
|
||||
ServerRecvThread::GetNextPlayerNumber() const
|
||||
void
|
||||
ServerRecvThread::AssignPlayerNumbers()
|
||||
{
|
||||
int playerNumber = 0;
|
||||
|
||||
PlayerDataList playerList = GetPlayerDataList();
|
||||
PlayerDataList::const_iterator player_i = playerList.begin();
|
||||
PlayerDataList::const_iterator player_end = playerList.end();
|
||||
PlayerDataList::iterator player_i = playerList.begin();
|
||||
PlayerDataList::iterator player_end = playerList.end();
|
||||
|
||||
// Assume the player list is sorted by player number.
|
||||
while (player_i != player_end)
|
||||
{
|
||||
if ((*player_i)->GetNumber() == playerNumber)
|
||||
playerNumber++;
|
||||
else
|
||||
break;
|
||||
(*player_i)->SetNumber(playerNumber);
|
||||
++playerNumber;
|
||||
++player_i;
|
||||
}
|
||||
|
||||
return playerNumber;
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
+11
-4
@@ -26,7 +26,7 @@
|
||||
#include <gamedata.h>
|
||||
#include <net/socket_helper.h>
|
||||
|
||||
#define NET_VERSION_MAJOR 1
|
||||
#define NET_VERSION_MAJOR 2
|
||||
#define NET_VERSION_MINOR 0
|
||||
|
||||
#define MIN_PACKET_SIZE 4
|
||||
@@ -143,7 +143,6 @@ public:
|
||||
struct Data
|
||||
{
|
||||
u_int32_t sessionId;
|
||||
int16_t yourPlayerNum;
|
||||
u_int16_t yourPlayerUniqueId;
|
||||
GameData gameData;
|
||||
};
|
||||
@@ -169,7 +168,6 @@ public:
|
||||
struct Data
|
||||
{
|
||||
u_int16_t playerId;
|
||||
u_int16_t playerNumber;
|
||||
PlayerType ptype;
|
||||
std::string playerName;
|
||||
};
|
||||
@@ -215,9 +213,18 @@ protected:
|
||||
class NetPacketGameStart : public NetPacket
|
||||
{
|
||||
public:
|
||||
|
||||
struct PlayerSlot
|
||||
{
|
||||
unsigned playerId;
|
||||
};
|
||||
|
||||
typedef std::list<PlayerSlot> PlayerSlotList;
|
||||
|
||||
struct Data
|
||||
{
|
||||
StartData startData;
|
||||
StartData startData;
|
||||
PlayerSlotList playerSlots;
|
||||
};
|
||||
|
||||
NetPacketGameStart();
|
||||
|
||||
@@ -121,7 +121,7 @@ protected:
|
||||
void SetSessionPlayerData(boost::shared_ptr<SessionData> sessionData, boost::shared_ptr<PlayerData> playerData);
|
||||
PlayerDataList GetPlayerDataList() const;
|
||||
|
||||
int GetNextPlayerNumber() const;
|
||||
void AssignPlayerNumbers();
|
||||
|
||||
ServerRecvState &GetState();
|
||||
void SetState(ServerRecvState &newState);
|
||||
|
||||
@@ -55,6 +55,7 @@
|
||||
#define ERR_NET_INVALID_ROUND 112
|
||||
#define ERR_NET_PLAYER_KICKED 113
|
||||
#define ERR_NET_INVALID_PLAYER_COUNT 114
|
||||
#define ERR_NET_PLAYER_NOT_IN_GAME 115
|
||||
|
||||
// This is an internal message which is not reported.
|
||||
#define MSG_SOCK_INTERNAL_PENDING 0
|
||||
|
||||
Reference in New Issue
Block a user