The console server can now be fully used for a single game. The first player to join the game is admin, he can start the game and kick players.
However, if the admin player leaves, a new game can only be started if all players have left before (this is a bug, admin status should be passed to another player).
This commit is contained in:
@@ -23,6 +23,7 @@
|
||||
|
||||
#include <string>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <playerdata.h>
|
||||
|
||||
class Game;
|
||||
|
||||
@@ -36,7 +37,8 @@ public:
|
||||
virtual void SignalNetClientError(int errorID, int osErrorID) = 0;
|
||||
|
||||
virtual void SignalNetClientGameStart(boost::shared_ptr<Game> game) = 0;
|
||||
virtual void SignalNetClientPlayerJoined(const std::string &playerName) = 0;
|
||||
virtual void SignalNetClientSelfJoined(const std::string &playerName, PlayerRights rights) = 0;
|
||||
virtual void SignalNetClientPlayerJoined(const std::string &playerName, PlayerRights rights) = 0;
|
||||
virtual void SignalNetClientPlayerLeft(const std::string &playerName) = 0;
|
||||
|
||||
virtual void SignalNetClientChatMsg(const std::string &playerName, const std::string &msg) = 0;
|
||||
|
||||
@@ -52,6 +52,8 @@ public:
|
||||
const std::string &pwd,
|
||||
const std::string &playerName);
|
||||
|
||||
void SendKickPlayer(const std::string &playerName);
|
||||
void SendStartEvent();
|
||||
void SendPlayerAction();
|
||||
void SendChatMessage(const std::string &msg);
|
||||
|
||||
@@ -89,6 +91,7 @@ protected:
|
||||
void MapPlayerDataList();
|
||||
const PlayerDataList &GetPlayerDataList() const;
|
||||
boost::shared_ptr<PlayerData> GetPlayerDataByUniqueId(unsigned id);
|
||||
boost::shared_ptr<PlayerData> GetPlayerDataByName(const std::string &name);
|
||||
|
||||
void RemoveDisconnectedPlayers();
|
||||
|
||||
|
||||
@@ -447,7 +447,7 @@ ClientStateWaitSession::InternalProcess(ClientThread &client, boost::shared_ptr<
|
||||
// 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, 0, PLAYER_TYPE_HUMAN));
|
||||
new PlayerData(joinGameAckData.yourPlayerUniqueId, 0, joinGameAckData.ptype, joinGameAckData.prights));
|
||||
playerData->SetName(context.GetPlayerName());
|
||||
client.AddPlayerData(playerData);
|
||||
|
||||
@@ -516,7 +516,7 @@ ClientStateWaitGame::InternalProcess(ClientThread &client, boost::shared_ptr<Net
|
||||
packet->ToNetPacketPlayerJoined()->GetData(netPlayerData);
|
||||
|
||||
boost::shared_ptr<PlayerData> playerData(
|
||||
new PlayerData(netPlayerData.playerId, 0, netPlayerData.ptype));
|
||||
new PlayerData(netPlayerData.playerId, 0, netPlayerData.ptype, netPlayerData.prights));
|
||||
playerData->SetName(netPlayerData.playerName);
|
||||
client.AddPlayerData(playerData);
|
||||
}
|
||||
|
||||
@@ -85,6 +85,30 @@ ClientThread::Init(
|
||||
context.SetPlayerName(playerName);
|
||||
}
|
||||
|
||||
void
|
||||
ClientThread::SendKickPlayer(const string &playerName)
|
||||
{
|
||||
boost::shared_ptr<PlayerData> tmpPlayer = GetPlayerDataByName(playerName);
|
||||
if (tmpPlayer.get())
|
||||
{
|
||||
boost::shared_ptr<NetPacket> request(new NetPacketKickPlayer);
|
||||
NetPacketKickPlayer::Data requestData;
|
||||
requestData.playerId = tmpPlayer->GetUniqueId();
|
||||
static_cast<NetPacketKickPlayer *>(request.get())->SetData(requestData);
|
||||
GetSender().Send(GetContext().GetSocket(), request);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ClientThread::SendStartEvent()
|
||||
{
|
||||
// Warning: This function is called in the context of the GUI thread.
|
||||
// Create a network packet for the server start event.
|
||||
boost::shared_ptr<NetPacket> startEvent(new NetPacketStartEvent);
|
||||
// The sender is thread-safe, so just dump the packet.
|
||||
GetSender().Send(GetContext().GetSocket(), startEvent);
|
||||
}
|
||||
|
||||
void
|
||||
ClientThread::SendPlayerAction()
|
||||
{
|
||||
@@ -274,7 +298,10 @@ ClientThread::AddPlayerData(boost::shared_ptr<PlayerData> playerData)
|
||||
if (playerData.get() && !playerData->GetName().empty())
|
||||
{
|
||||
m_playerDataList.push_back(playerData);
|
||||
GetCallback().SignalNetClientPlayerJoined(playerData->GetName());
|
||||
if (playerData->GetUniqueId() == GetGuiPlayerId())
|
||||
GetCallback().SignalNetClientSelfJoined(playerData->GetName(), playerData->GetRights());
|
||||
else
|
||||
GetCallback().SignalNetClientPlayerJoined(playerData->GetName(), playerData->GetRights());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -360,6 +387,29 @@ ClientThread::GetPlayerDataByUniqueId(unsigned id)
|
||||
return tmpPlayer;
|
||||
}
|
||||
|
||||
boost::shared_ptr<PlayerData>
|
||||
ClientThread::GetPlayerDataByName(const std::string &name)
|
||||
{
|
||||
boost::shared_ptr<PlayerData> tmpPlayer;
|
||||
|
||||
if (!name.empty())
|
||||
{
|
||||
PlayerDataList::const_iterator i = m_playerDataList.begin();
|
||||
PlayerDataList::const_iterator end = m_playerDataList.end();
|
||||
|
||||
while (i != end)
|
||||
{
|
||||
if ((*i)->GetName() == name)
|
||||
{
|
||||
tmpPlayer = *i;
|
||||
break;
|
||||
}
|
||||
++i;
|
||||
}
|
||||
}
|
||||
return tmpPlayer;
|
||||
}
|
||||
|
||||
void
|
||||
ClientThread::RemoveDisconnectedPlayers()
|
||||
{
|
||||
|
||||
+140
-13
@@ -31,19 +31,21 @@ using namespace std;
|
||||
#define NET_TYPE_JOIN_GAME_ACK 0x0002
|
||||
#define NET_TYPE_PLAYER_JOINED 0x0003
|
||||
#define NET_TYPE_PLAYER_LEFT 0x0004
|
||||
#define NET_TYPE_GAME_START 0x0005
|
||||
#define NET_TYPE_HAND_START 0x0006
|
||||
#define NET_TYPE_PLAYERS_TURN 0x0007
|
||||
#define NET_TYPE_PLAYERS_ACTION 0x0008
|
||||
#define NET_TYPE_PLAYERS_ACTION_DONE 0x0009
|
||||
#define NET_TYPE_PLAYERS_ACTION_REJECTED 0x000A
|
||||
#define NET_TYPE_DEAL_FLOP_CARDS 0x000B
|
||||
#define NET_TYPE_DEAL_TURN_CARD 0x000C
|
||||
#define NET_TYPE_DEAL_RIVER_CARD 0x000D
|
||||
#define NET_TYPE_ALL_IN_SHOW_CARDS 0x000E
|
||||
#define NET_TYPE_END_OF_HAND_SHOW_CARDS 0x000F
|
||||
#define NET_TYPE_END_OF_HAND_HIDE_CARDS 0x0010
|
||||
#define NET_TYPE_END_OF_GAME 0x0011
|
||||
#define NET_TYPE_KICK_PLAYER 0x0005
|
||||
#define NET_TYPE_START_EVENT 0x0006
|
||||
#define NET_TYPE_GAME_START 0x0007
|
||||
#define NET_TYPE_HAND_START 0x0008
|
||||
#define NET_TYPE_PLAYERS_TURN 0x0009
|
||||
#define NET_TYPE_PLAYERS_ACTION 0x000A
|
||||
#define NET_TYPE_PLAYERS_ACTION_DONE 0x000B
|
||||
#define NET_TYPE_PLAYERS_ACTION_REJECTED 0x000C
|
||||
#define NET_TYPE_DEAL_FLOP_CARDS 0x000D
|
||||
#define NET_TYPE_DEAL_TURN_CARD 0x000E
|
||||
#define NET_TYPE_DEAL_RIVER_CARD 0x000F
|
||||
#define NET_TYPE_ALL_IN_SHOW_CARDS 0x0010
|
||||
#define NET_TYPE_END_OF_HAND_SHOW_CARDS 0x0011
|
||||
#define NET_TYPE_END_OF_HAND_HIDE_CARDS 0x0012
|
||||
#define NET_TYPE_END_OF_GAME 0x0013
|
||||
|
||||
#define NET_TYPE_SEND_CHAT_TEXT 0x0200
|
||||
#define NET_TYPE_CHAT_TEXT 0x0201
|
||||
@@ -126,6 +128,18 @@ struct GCC_PACKED NetPacketPlayerLeftData
|
||||
u_int16_t reserved;
|
||||
};
|
||||
|
||||
struct GCC_PACKED NetPacketKickPlayerData
|
||||
{
|
||||
NetPacketHeader head;
|
||||
u_int16_t playerId;
|
||||
u_int16_t reserved;
|
||||
};
|
||||
|
||||
struct GCC_PACKED NetPacketStartEventData
|
||||
{
|
||||
NetPacketHeader head;
|
||||
};
|
||||
|
||||
struct GCC_PACKED NetPacketGameStartData
|
||||
{
|
||||
NetPacketHeader head;
|
||||
@@ -324,6 +338,12 @@ NetPacket::Create(char *data, unsigned &dataSize)
|
||||
case NET_TYPE_PLAYER_LEFT:
|
||||
tmpPacket = boost::shared_ptr<NetPacket>(new NetPacketPlayerLeft);
|
||||
break;
|
||||
case NET_TYPE_KICK_PLAYER:
|
||||
tmpPacket = boost::shared_ptr<NetPacket>(new NetPacketKickPlayer);
|
||||
break;
|
||||
case NET_TYPE_START_EVENT:
|
||||
tmpPacket = boost::shared_ptr<NetPacket>(new NetPacketStartEvent);
|
||||
break;
|
||||
case NET_TYPE_GAME_START:
|
||||
tmpPacket = boost::shared_ptr<NetPacket>(new NetPacketGameStart);
|
||||
break;
|
||||
@@ -480,6 +500,18 @@ NetPacket::ToNetPacketPlayerLeft() const
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const NetPacketKickPlayer *
|
||||
NetPacket::ToNetPacketKickPlayer() const
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const NetPacketStartEvent *
|
||||
NetPacket::ToNetPacketStartEvent() const
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const NetPacketGameStart *
|
||||
NetPacket::ToNetPacketGameStart() const
|
||||
{
|
||||
@@ -983,6 +1015,101 @@ NetPacketPlayerLeft::InternalCheck(const NetPacketHeader* data) const
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
NetPacketKickPlayer::NetPacketKickPlayer()
|
||||
: NetPacket(NET_TYPE_KICK_PLAYER, sizeof(NetPacketKickPlayerData), sizeof(NetPacketKickPlayerData))
|
||||
{
|
||||
}
|
||||
|
||||
NetPacketKickPlayer::~NetPacketKickPlayer()
|
||||
{
|
||||
}
|
||||
|
||||
boost::shared_ptr<NetPacket>
|
||||
NetPacketKickPlayer::Clone() const
|
||||
{
|
||||
boost::shared_ptr<NetPacket> newPacket(new NetPacketKickPlayer);
|
||||
try
|
||||
{
|
||||
newPacket->SetRawData(GetRawData());
|
||||
} catch (const NetException &)
|
||||
{
|
||||
// Need to return the new packet anyway.
|
||||
}
|
||||
return newPacket;
|
||||
}
|
||||
|
||||
void
|
||||
NetPacketKickPlayer::SetData(const NetPacketKickPlayer::Data &inData)
|
||||
{
|
||||
NetPacketKickPlayerData *tmpData = (NetPacketKickPlayerData *)GetRawData();
|
||||
|
||||
// Set the data.
|
||||
tmpData->playerId = htons(inData.playerId);
|
||||
|
||||
// Check the packet - just in case.
|
||||
Check(GetRawData());
|
||||
}
|
||||
|
||||
void
|
||||
NetPacketKickPlayer::GetData(NetPacketKickPlayer::Data &outData) const
|
||||
{
|
||||
// We assume that the data is valid. Validity has already been checked.
|
||||
NetPacketKickPlayerData *tmpData = (NetPacketKickPlayerData *)GetRawData();
|
||||
|
||||
outData.playerId = ntohs(tmpData->playerId);
|
||||
}
|
||||
|
||||
const NetPacketKickPlayer *
|
||||
NetPacketKickPlayer::ToNetPacketKickPlayer() const
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
void
|
||||
NetPacketKickPlayer::InternalCheck(const NetPacketHeader* data) const
|
||||
{
|
||||
// Nothing to do.
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
NetPacketStartEvent::NetPacketStartEvent()
|
||||
: NetPacket(NET_TYPE_START_EVENT, sizeof(NetPacketStartEventData), sizeof(NetPacketStartEventData))
|
||||
{
|
||||
}
|
||||
|
||||
NetPacketStartEvent::~NetPacketStartEvent()
|
||||
{
|
||||
}
|
||||
|
||||
boost::shared_ptr<NetPacket>
|
||||
NetPacketStartEvent::Clone() const
|
||||
{
|
||||
boost::shared_ptr<NetPacket> newPacket(new NetPacketStartEvent);
|
||||
try
|
||||
{
|
||||
newPacket->SetRawData(GetRawData());
|
||||
} catch (const NetException &)
|
||||
{
|
||||
// Need to return the new packet anyway.
|
||||
}
|
||||
return newPacket;
|
||||
}
|
||||
|
||||
const NetPacketStartEvent *
|
||||
NetPacketStartEvent::ToNetPacketStartEvent() const
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
void
|
||||
NetPacketStartEvent::InternalCheck(const NetPacketHeader* data) const
|
||||
{
|
||||
// Nothing to do.
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
NetPacketGameStart::NetPacketGameStart()
|
||||
: NetPacket(NET_TYPE_GAME_START, sizeof(NetPacketGameStartData), MAX_PACKET_SIZE)
|
||||
{
|
||||
|
||||
+118
-102
@@ -232,109 +232,129 @@ ServerRecvStateInit::InternalProcess(ServerRecvThread &server, SessionWrapper se
|
||||
{
|
||||
int retVal = MSG_SOCK_INIT_DONE;
|
||||
|
||||
// Session should be in initial state.
|
||||
if (session.sessionData->GetState() != SessionData::Init)
|
||||
if (packet->ToNetPacketJoinGame())
|
||||
{
|
||||
server.SessionError(session, ERR_SOCK_INVALID_STATE);
|
||||
return retVal;
|
||||
}
|
||||
// Session should be in initial state.
|
||||
if (session.sessionData->GetState() != SessionData::Init)
|
||||
{
|
||||
server.SessionError(session, ERR_SOCK_INVALID_STATE);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
// Only accept join game packets.
|
||||
const NetPacketJoinGame *tmpPacket = packet->ToNetPacketJoinGame();
|
||||
if (!tmpPacket)
|
||||
const NetPacketJoinGame *tmpPacket = packet->ToNetPacketJoinGame();
|
||||
|
||||
NetPacketJoinGame::Data joinGameData;
|
||||
tmpPacket->GetData(joinGameData);
|
||||
|
||||
// Check the protocol version.
|
||||
if (joinGameData.versionMajor != NET_VERSION_MAJOR)
|
||||
{
|
||||
server.SessionError(session, ERR_NET_VERSION_NOT_SUPPORTED);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
size_t curNumPlayers = server.GetCurNumberOfPlayers();
|
||||
|
||||
// Check the number of players.
|
||||
if (curNumPlayers >= (size_t)server.GetGameData().maxNumberOfPlayers)
|
||||
{
|
||||
server.SessionError(session, ERR_NET_SERVER_FULL);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
// Check the server password.
|
||||
if (!server.CheckPassword(joinGameData.password))
|
||||
{
|
||||
server.SessionError(session, ERR_NET_INVALID_PASSWORD);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
// Check whether the player name is correct.
|
||||
// Paranoia check, this is also done in netpacket.
|
||||
if (joinGameData.playerName.empty() || joinGameData.playerName.size() > MAX_NAME_SIZE)
|
||||
{
|
||||
server.SessionError(session, ERR_NET_INVALID_PLAYER_NAME);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
// Check whether this player is already connected.
|
||||
if (server.IsPlayerConnected(joinGameData.playerName))
|
||||
{
|
||||
server.SessionError(session, ERR_NET_PLAYER_NAME_IN_USE);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
// Create player data object.
|
||||
// TODO HACK first player is admin
|
||||
PlayerRights rights = PLAYER_RIGHTS_NORMAL;
|
||||
if (server.GetCurNumberOfPlayers() == 0)
|
||||
rights = PLAYER_RIGHTS_ADMIN;
|
||||
boost::shared_ptr<PlayerData> tmpPlayerData(
|
||||
new PlayerData(m_curUniquePlayerId++, 0, PLAYER_TYPE_HUMAN, rights));
|
||||
tmpPlayerData->SetName(joinGameData.playerName);
|
||||
tmpPlayerData->SetNetSessionData(session.sessionData);
|
||||
|
||||
// Send ACK to client.
|
||||
boost::shared_ptr<NetPacket> answer(new NetPacketJoinGameAck);
|
||||
NetPacketJoinGameAck::Data joinGameAckData;
|
||||
joinGameAckData.sessionId = session.sessionData->GetId(); // TODO: currently unused.
|
||||
joinGameAckData.yourPlayerUniqueId = tmpPlayerData->GetUniqueId();
|
||||
joinGameAckData.gameData = server.GetGameData();
|
||||
joinGameAckData.ptype = tmpPlayerData->GetType();
|
||||
joinGameAckData.prights = tmpPlayerData->GetRights();
|
||||
static_cast<NetPacketJoinGameAck *>(answer.get())->SetData(joinGameAckData);
|
||||
server.GetSender().Send(session.sessionData->GetSocket(), answer);
|
||||
|
||||
// Send notifications for connected players to client.
|
||||
PlayerDataList tmpPlayerList = server.GetPlayerDataList();
|
||||
PlayerDataList::iterator player_i = tmpPlayerList.begin();
|
||||
PlayerDataList::iterator player_end = tmpPlayerList.end();
|
||||
while (player_i != player_end)
|
||||
{
|
||||
boost::shared_ptr<NetPacket> otherPlayerJoined(new NetPacketPlayerJoined);
|
||||
NetPacketPlayerJoined::Data otherPlayerJoinedData;
|
||||
otherPlayerJoinedData.playerId = (*player_i)->GetUniqueId();
|
||||
otherPlayerJoinedData.playerName = (*player_i)->GetName();
|
||||
otherPlayerJoinedData.ptype = (*player_i)->GetType();
|
||||
static_cast<NetPacketPlayerJoined *>(otherPlayerJoined.get())->SetData(otherPlayerJoinedData);
|
||||
server.GetSender().Send(session.sessionData->GetSocket(), otherPlayerJoined);
|
||||
|
||||
++player_i;
|
||||
}
|
||||
|
||||
// Send "Player Joined" to other fully connected clients.
|
||||
boost::shared_ptr<NetPacket> thisPlayerJoined(new NetPacketPlayerJoined);
|
||||
NetPacketPlayerJoined::Data thisPlayerJoinedData;
|
||||
thisPlayerJoinedData.playerId = tmpPlayerData->GetUniqueId();
|
||||
thisPlayerJoinedData.playerName = tmpPlayerData->GetName();
|
||||
thisPlayerJoinedData.ptype = tmpPlayerData->GetType();
|
||||
thisPlayerJoinedData.prights = tmpPlayerData->GetRights();
|
||||
static_cast<NetPacketPlayerJoined *>(thisPlayerJoined.get())->SetData(thisPlayerJoinedData);
|
||||
server.SendToAllPlayers(thisPlayerJoined);
|
||||
|
||||
// Set player data for session.
|
||||
server.SetSessionPlayerData(session.sessionData, tmpPlayerData);
|
||||
|
||||
// Session is now established.
|
||||
session.sessionData->SetState(SessionData::Established);
|
||||
}
|
||||
else if (packet->ToNetPacketStartEvent())
|
||||
{
|
||||
server.InternalStartGame();
|
||||
server.SetState(SERVER_START_GAME_STATE::Instance());
|
||||
}
|
||||
else if (packet->ToNetPacketKickPlayer())
|
||||
{
|
||||
NetPacketKickPlayer::Data kickPlayerData;
|
||||
packet->ToNetPacketKickPlayer()->GetData(kickPlayerData);
|
||||
|
||||
server.InternalKickPlayer(kickPlayerData.playerId);
|
||||
}
|
||||
else
|
||||
{
|
||||
server.SessionError(session, ERR_SOCK_INVALID_PACKET);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
NetPacketJoinGame::Data joinGameData;
|
||||
tmpPacket->GetData(joinGameData);
|
||||
|
||||
// Check the protocol version.
|
||||
if (joinGameData.versionMajor != NET_VERSION_MAJOR)
|
||||
{
|
||||
server.SessionError(session, ERR_NET_VERSION_NOT_SUPPORTED);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
size_t curNumPlayers = server.GetCurNumberOfPlayers();
|
||||
|
||||
// Check the number of players.
|
||||
if (curNumPlayers >= (size_t)server.GetGameData().maxNumberOfPlayers)
|
||||
{
|
||||
server.SessionError(session, ERR_NET_SERVER_FULL);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
// Check the server password.
|
||||
if (!server.CheckPassword(joinGameData.password))
|
||||
{
|
||||
server.SessionError(session, ERR_NET_INVALID_PASSWORD);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
// Check whether the player name is correct.
|
||||
// Paranoia check, this is also done in netpacket.
|
||||
if (joinGameData.playerName.empty() || joinGameData.playerName.size() > MAX_NAME_SIZE)
|
||||
{
|
||||
server.SessionError(session, ERR_NET_INVALID_PLAYER_NAME);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
// Check whether this player is already connected.
|
||||
if (server.IsPlayerConnected(joinGameData.playerName))
|
||||
{
|
||||
server.SessionError(session, ERR_NET_PLAYER_NAME_IN_USE);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
// Create player data object.
|
||||
boost::shared_ptr<PlayerData> tmpPlayerData(
|
||||
new PlayerData(m_curUniquePlayerId++, 0, PLAYER_TYPE_HUMAN));
|
||||
tmpPlayerData->SetName(joinGameData.playerName);
|
||||
tmpPlayerData->SetNetSessionData(session.sessionData);
|
||||
|
||||
// Send ACK to client.
|
||||
boost::shared_ptr<NetPacket> answer(new NetPacketJoinGameAck);
|
||||
NetPacketJoinGameAck::Data joinGameAckData;
|
||||
joinGameAckData.sessionId = session.sessionData->GetId(); // TODO: currently unused.
|
||||
joinGameAckData.yourPlayerUniqueId = tmpPlayerData->GetUniqueId();
|
||||
joinGameAckData.gameData = server.GetGameData();
|
||||
static_cast<NetPacketJoinGameAck *>(answer.get())->SetData(joinGameAckData);
|
||||
server.GetSender().Send(session.sessionData->GetSocket(), answer);
|
||||
|
||||
// Send notifications for connected players to client.
|
||||
PlayerDataList tmpPlayerList = server.GetPlayerDataList();
|
||||
PlayerDataList::iterator player_i = tmpPlayerList.begin();
|
||||
PlayerDataList::iterator player_end = tmpPlayerList.end();
|
||||
while (player_i != player_end)
|
||||
{
|
||||
boost::shared_ptr<NetPacket> otherPlayerJoined(new NetPacketPlayerJoined);
|
||||
NetPacketPlayerJoined::Data otherPlayerJoinedData;
|
||||
otherPlayerJoinedData.playerId = (*player_i)->GetUniqueId();
|
||||
otherPlayerJoinedData.playerName = (*player_i)->GetName();
|
||||
otherPlayerJoinedData.ptype = (*player_i)->GetType();
|
||||
static_cast<NetPacketPlayerJoined *>(otherPlayerJoined.get())->SetData(otherPlayerJoinedData);
|
||||
server.GetSender().Send(session.sessionData->GetSocket(), otherPlayerJoined);
|
||||
|
||||
++player_i;
|
||||
}
|
||||
|
||||
// Send "Player Joined" to other fully connected clients.
|
||||
boost::shared_ptr<NetPacket> thisPlayerJoined(new NetPacketPlayerJoined);
|
||||
NetPacketPlayerJoined::Data thisPlayerJoinedData;
|
||||
thisPlayerJoinedData.playerId = tmpPlayerData->GetUniqueId();
|
||||
thisPlayerJoinedData.playerName = tmpPlayerData->GetName();
|
||||
thisPlayerJoinedData.ptype = tmpPlayerData->GetType();
|
||||
static_cast<NetPacketPlayerJoined *>(thisPlayerJoined.get())->SetData(thisPlayerJoinedData);
|
||||
server.SendToAllPlayers(thisPlayerJoined);
|
||||
|
||||
// Set player data for session.
|
||||
server.SetSessionPlayerData(session.sessionData, tmpPlayerData);
|
||||
|
||||
// Session is now established.
|
||||
session.sessionData->SetState(SessionData::Established);
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
@@ -1039,11 +1059,7 @@ ServerRecvStateNextGameDelay::Process(ServerRecvThread &server)
|
||||
|
||||
server.SendToAllPlayers(endGame);
|
||||
|
||||
// Switch back to the GUI, wait for the start of a new game.
|
||||
// Luckily, the names are still in the GUI dialog.
|
||||
// We just need to show the proper dialog, and people can
|
||||
// join or leave as usual.
|
||||
server.GetCallback().SignalNetServerStartDialog();
|
||||
// Wait for the start of a new game.
|
||||
server.SetState(ServerRecvStateInit::Instance());
|
||||
}
|
||||
|
||||
|
||||
@@ -140,15 +140,10 @@ ServerRecvThread::NotificationLoop()
|
||||
Notification notification = m_notificationQueue.front();
|
||||
m_notificationQueue.pop_front();
|
||||
|
||||
switch(notification.message)
|
||||
{
|
||||
case NOTIFY_GAME_START:
|
||||
InternalStartGame();
|
||||
break;
|
||||
case NOTIFY_KICK_PLAYER:
|
||||
InternalKickPlayer(notification.param);
|
||||
break;
|
||||
}
|
||||
// switch(notification.message)
|
||||
// {
|
||||
// break;
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -249,8 +244,6 @@ ServerRecvThread::CleanupSessionMap()
|
||||
void
|
||||
ServerRecvThread::InternalStartGame()
|
||||
{
|
||||
SetState(SERVER_START_GAME_STATE::Instance());
|
||||
|
||||
// Kick all players which are not fully connected.
|
||||
RemoveNotEstablishedSessions();
|
||||
// Set order of players.
|
||||
@@ -295,14 +288,10 @@ ServerRecvThread::InternalStartGame()
|
||||
}
|
||||
|
||||
void
|
||||
ServerRecvThread::InternalKickPlayer(const string playerName)
|
||||
ServerRecvThread::InternalKickPlayer(unsigned uniqueId)
|
||||
{
|
||||
if (!playerName.empty())
|
||||
{
|
||||
SessionWrapper tmpSession = GetSessionByPlayerName(playerName);
|
||||
|
||||
SessionError(tmpSession, ERR_NET_PLAYER_KICKED);
|
||||
}
|
||||
SessionWrapper tmpSession = GetSessionByUniquePlayerId(uniqueId);
|
||||
SessionError(tmpSession, ERR_NET_PLAYER_KICKED);
|
||||
}
|
||||
|
||||
SessionWrapper
|
||||
@@ -394,9 +383,11 @@ ServerRecvThread::AddSession(boost::shared_ptr<SessionData> sessionData)
|
||||
void
|
||||
ServerRecvThread::SessionError(SessionWrapper session, int errorCode)
|
||||
{
|
||||
assert(session.sessionData.get());
|
||||
SendError(session.sessionData->GetSocket(), errorCode);
|
||||
CloseSessionDelayed(session);
|
||||
if (session.sessionData.get())
|
||||
{
|
||||
SendError(session.sessionData->GetSocket(), errorCode);
|
||||
CloseSessionDelayed(session);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -57,26 +57,6 @@ ServerThread::Init(unsigned serverPort, bool ipv6, bool sctp, const std::string
|
||||
GetRecvThread().Init(pwd, gameData);
|
||||
}
|
||||
|
||||
void
|
||||
ServerThread::StartGame()
|
||||
{
|
||||
if (!IsRunning())
|
||||
return; // TODO: throw exception
|
||||
|
||||
// Thread-safe notification.
|
||||
GetRecvThread().AddNotification(NOTIFY_GAME_START, "");
|
||||
}
|
||||
|
||||
void
|
||||
ServerThread::KickPlayer(const string &playerName)
|
||||
{
|
||||
if (!IsRunning())
|
||||
return; // TODO: throw exception
|
||||
|
||||
// Thread-safe notification.
|
||||
GetRecvThread().AddNotification(NOTIFY_KICK_PLAYER, playerName);
|
||||
}
|
||||
|
||||
ServerCallback &
|
||||
ServerThread::GetCallback()
|
||||
{
|
||||
|
||||
@@ -44,6 +44,8 @@ class NetPacketJoinGame;
|
||||
class NetPacketJoinGameAck;
|
||||
class NetPacketPlayerJoined;
|
||||
class NetPacketPlayerLeft;
|
||||
class NetPacketKickPlayer;
|
||||
class NetPacketStartEvent;
|
||||
class NetPacketGameStart;
|
||||
class NetPacketHandStart;
|
||||
class NetPacketPlayersTurn;
|
||||
@@ -82,6 +84,8 @@ public:
|
||||
virtual const NetPacketJoinGameAck *ToNetPacketJoinGameAck() const;
|
||||
virtual const NetPacketPlayerJoined *ToNetPacketPlayerJoined() const;
|
||||
virtual const NetPacketPlayerLeft *ToNetPacketPlayerLeft() const;
|
||||
virtual const NetPacketKickPlayer *ToNetPacketKickPlayer() const;
|
||||
virtual const NetPacketStartEvent *ToNetPacketStartEvent() const;
|
||||
virtual const NetPacketGameStart *ToNetPacketGameStart() const;
|
||||
virtual const NetPacketHandStart *ToNetPacketHandStart() const;
|
||||
virtual const NetPacketPlayersTurn *ToNetPacketPlayersTurn() const;
|
||||
@@ -215,6 +219,45 @@ protected:
|
||||
virtual void InternalCheck(const NetPacketHeader* data) const;
|
||||
};
|
||||
|
||||
class NetPacketKickPlayer : public NetPacket
|
||||
{
|
||||
public:
|
||||
struct Data
|
||||
{
|
||||
u_int16_t playerId;
|
||||
};
|
||||
|
||||
NetPacketKickPlayer();
|
||||
virtual ~NetPacketKickPlayer();
|
||||
|
||||
virtual boost::shared_ptr<NetPacket> Clone() const;
|
||||
|
||||
void SetData(const Data &inData);
|
||||
void GetData(Data &outData) const;
|
||||
|
||||
virtual const NetPacketKickPlayer *ToNetPacketKickPlayer() const;
|
||||
|
||||
protected:
|
||||
|
||||
virtual void InternalCheck(const NetPacketHeader* data) const;
|
||||
};
|
||||
|
||||
class NetPacketStartEvent : public NetPacket
|
||||
{
|
||||
public:
|
||||
|
||||
NetPacketStartEvent();
|
||||
virtual ~NetPacketStartEvent();
|
||||
|
||||
virtual boost::shared_ptr<NetPacket> Clone() const;
|
||||
|
||||
virtual const NetPacketStartEvent *ToNetPacketStartEvent() const;
|
||||
|
||||
protected:
|
||||
|
||||
virtual void InternalCheck(const NetPacketHeader* data) const;
|
||||
};
|
||||
|
||||
class NetPacketGameStart : public NetPacket
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -33,8 +33,6 @@ public:
|
||||
|
||||
virtual void SignalNetServerPlayerJoined(const std::string &playerName) = 0;
|
||||
virtual void SignalNetServerPlayerLeft(const std::string &playerName) = 0;
|
||||
|
||||
virtual void SignalNetServerStartDialog() = 0;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -36,9 +36,6 @@
|
||||
|
||||
#define RECEIVER_THREAD_TERMINATE_TIMEOUT 200
|
||||
|
||||
// Notifications
|
||||
#define NOTIFY_GAME_START 1
|
||||
#define NOTIFY_KICK_PLAYER 2
|
||||
|
||||
class ServerRecvState;
|
||||
class SenderThread;
|
||||
@@ -103,7 +100,7 @@ protected:
|
||||
void CleanupSessionMap();
|
||||
|
||||
void InternalStartGame();
|
||||
void InternalKickPlayer(const std::string playerName);
|
||||
void InternalKickPlayer(unsigned uniqueId);
|
||||
|
||||
SessionWrapper GetSession(SOCKET sock) const;
|
||||
SessionWrapper GetSessionByPlayerName(const std::string playerName) const;
|
||||
|
||||
@@ -43,8 +43,6 @@ public:
|
||||
// Set the parameters.
|
||||
void Init(unsigned serverPort, bool ipv6, bool sctp, const std::string &pwd,
|
||||
const GameData &gameData);
|
||||
void StartGame();
|
||||
void KickPlayer(const std::string &playerName);
|
||||
|
||||
ServerCallback &GetCallback();
|
||||
GuiInterface &GetGui();
|
||||
|
||||
Reference in New Issue
Block a user