Fixed some small server issues. Players in the process of establishing a session are now kicked on game start.
If someone tries to join a game which is already running, a proper error message is shown. When sending a message to all or all but one players, the players which do not have the session established are now correctly ignored.
This commit is contained in:
@@ -120,6 +120,15 @@ ServerRecvStateInit::Process(ServerRecvThread &server)
|
|||||||
return retVal;
|
return retVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t curNumPlayers = server.GetCurNumberOfPlayers();
|
||||||
|
|
||||||
|
// Check the number of players.
|
||||||
|
if (curNumPlayers >= (size_t)server.GetGameData().numberOfPlayers)
|
||||||
|
{
|
||||||
|
server.SessionError(session, ERR_NET_SERVER_FULL);
|
||||||
|
return retVal;
|
||||||
|
}
|
||||||
|
|
||||||
// Check the server password.
|
// Check the server password.
|
||||||
if (!server.CheckPassword(joinGameData.password))
|
if (!server.CheckPassword(joinGameData.password))
|
||||||
{
|
{
|
||||||
@@ -127,12 +136,11 @@ ServerRecvStateInit::Process(ServerRecvThread &server)
|
|||||||
return retVal;
|
return retVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t curNumPlayers = server.GetCurNumberOfPlayers();
|
// Check whether the player name is correct.
|
||||||
|
// Paranoia check, this is also done in netpacket.
|
||||||
// Check the number of players.
|
if (joinGameData.playerName.empty() || joinGameData.playerName.size() > MAX_NAME_SIZE)
|
||||||
if (curNumPlayers >= (size_t)server.GetGameData().numberOfPlayers)
|
|
||||||
{
|
{
|
||||||
server.SessionError(session, ERR_NET_SERVER_FULL);
|
server.SessionError(session, ERR_NET_INVALID_PLAYER_NAME);
|
||||||
return retVal;
|
return retVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -177,7 +185,7 @@ ServerRecvStateInit::Process(ServerRecvThread &server)
|
|||||||
++player_i;
|
++player_i;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send "Player Joined" to other clients.
|
// Send "Player Joined" to other fully connected clients.
|
||||||
boost::shared_ptr<NetPacket> thisPlayerJoined(new NetPacketPlayerJoined);
|
boost::shared_ptr<NetPacket> thisPlayerJoined(new NetPacketPlayerJoined);
|
||||||
NetPacketPlayerJoined::Data thisPlayerJoinedData;
|
NetPacketPlayerJoined::Data thisPlayerJoinedData;
|
||||||
thisPlayerJoinedData.playerId = tmpPlayerData->GetUniqueId();
|
thisPlayerJoinedData.playerId = tmpPlayerData->GetUniqueId();
|
||||||
@@ -185,7 +193,7 @@ ServerRecvStateInit::Process(ServerRecvThread &server)
|
|||||||
thisPlayerJoinedData.playerNumber = tmpPlayerData->GetNumber();
|
thisPlayerJoinedData.playerNumber = tmpPlayerData->GetNumber();
|
||||||
thisPlayerJoinedData.ptype = tmpPlayerData->GetType();
|
thisPlayerJoinedData.ptype = tmpPlayerData->GetType();
|
||||||
static_cast<NetPacketPlayerJoined *>(thisPlayerJoined.get())->SetData(thisPlayerJoinedData);
|
static_cast<NetPacketPlayerJoined *>(thisPlayerJoined.get())->SetData(thisPlayerJoinedData);
|
||||||
server.SendToAllButOnePlayers(thisPlayerJoined, session.sessionData->GetSocket());
|
server.SendToAllPlayers(thisPlayerJoined);
|
||||||
|
|
||||||
// Set player data for session.
|
// Set player data for session.
|
||||||
server.SetSessionPlayerData(session.sessionData, tmpPlayerData);
|
server.SetSessionPlayerData(session.sessionData, tmpPlayerData);
|
||||||
@@ -217,7 +225,8 @@ ServerRecvStateStartGame::~ServerRecvStateStartGame()
|
|||||||
void
|
void
|
||||||
ServerRecvStateStartGame::HandleNewConnection(ServerRecvThread &server, boost::shared_ptr<ConnectData> connData)
|
ServerRecvStateStartGame::HandleNewConnection(ServerRecvThread &server, boost::shared_ptr<ConnectData> connData)
|
||||||
{
|
{
|
||||||
// TODO: send error msg
|
// Do not accept new connections in this state.
|
||||||
|
server.RejectNewConnection(connData);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
@@ -255,7 +264,8 @@ ServerRecvStateStartHand::~ServerRecvStateStartHand()
|
|||||||
void
|
void
|
||||||
ServerRecvStateStartHand::HandleNewConnection(ServerRecvThread &server, boost::shared_ptr<ConnectData> connData)
|
ServerRecvStateStartHand::HandleNewConnection(ServerRecvThread &server, boost::shared_ptr<ConnectData> connData)
|
||||||
{
|
{
|
||||||
// TODO: send error msg
|
// Do not accept new connections in this state.
|
||||||
|
server.RejectNewConnection(connData);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
@@ -271,24 +281,20 @@ ServerRecvStateStartHand::Process(ServerRecvThread &server)
|
|||||||
// Send cards to all players.
|
// Send cards to all players.
|
||||||
for (int i = 0; i < curGame.getActualQuantityPlayers(); i++)
|
for (int i = 0; i < curGame.getActualQuantityPlayers(); i++)
|
||||||
{
|
{
|
||||||
if (playerArray[i]->getNetSessionData().get()) // TODO: this is an assert.
|
assert(playerArray[i]->getNetSessionData().get()); // TODO throw exception
|
||||||
{
|
|
||||||
int cards[2];
|
|
||||||
playerArray[i]->getMyCards(cards);
|
|
||||||
boost::shared_ptr<NetPacket> notifyCards(new NetPacketHandStart);
|
|
||||||
NetPacketHandStart::Data handStartData;
|
|
||||||
handStartData.yourCards[0] = static_cast<unsigned>(cards[0]);
|
|
||||||
handStartData.yourCards[1] = static_cast<unsigned>(cards[1]);
|
|
||||||
static_cast<NetPacketHandStart *>(notifyCards.get())->SetData(handStartData);
|
|
||||||
|
|
||||||
server.GetSender().Send(playerArray[i]->getNetSessionData()->GetSocket(), notifyCards);
|
int cards[2];
|
||||||
}
|
playerArray[i]->getMyCards(cards);
|
||||||
|
boost::shared_ptr<NetPacket> notifyCards(new NetPacketHandStart);
|
||||||
|
NetPacketHandStart::Data handStartData;
|
||||||
|
handStartData.yourCards[0] = static_cast<unsigned>(cards[0]);
|
||||||
|
handStartData.yourCards[1] = static_cast<unsigned>(cards[1]);
|
||||||
|
static_cast<NetPacketHandStart *>(notifyCards.get())->SetData(handStartData);
|
||||||
|
|
||||||
|
server.GetSender().Send(playerArray[i]->getNetSessionData()->GetSocket(), notifyCards);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start hand.
|
// Auto small blind / big blind at the beginning of hand.
|
||||||
curGame.startHand();
|
|
||||||
|
|
||||||
// Auto small blind / big blind at the beginning of preflop.
|
|
||||||
for (int i = 0; i < curGame.getActualQuantityPlayers(); i++)
|
for (int i = 0; i < curGame.getActualQuantityPlayers(); i++)
|
||||||
{
|
{
|
||||||
if(playerArray[i]->getMyButton() == BUTTON_SMALL_BLIND)
|
if(playerArray[i]->getMyButton() == BUTTON_SMALL_BLIND)
|
||||||
@@ -320,6 +326,9 @@ ServerRecvStateStartHand::Process(ServerRecvThread &server)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Start hand.
|
||||||
|
curGame.startHand();
|
||||||
|
|
||||||
server.SetState(ServerRecvStateStartRound::Instance());
|
server.SetState(ServerRecvStateStartRound::Instance());
|
||||||
|
|
||||||
return MSG_NET_GAME_SERVER_HAND;
|
return MSG_NET_GAME_SERVER_HAND;
|
||||||
@@ -345,7 +354,8 @@ ServerRecvStateStartRound::~ServerRecvStateStartRound()
|
|||||||
void
|
void
|
||||||
ServerRecvStateStartRound::HandleNewConnection(ServerRecvThread &server, boost::shared_ptr<ConnectData> connData)
|
ServerRecvStateStartRound::HandleNewConnection(ServerRecvThread &server, boost::shared_ptr<ConnectData> connData)
|
||||||
{
|
{
|
||||||
// TODO: send error msg
|
// Do not accept new connections in this state.
|
||||||
|
server.RejectNewConnection(connData);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
@@ -403,7 +413,7 @@ ServerRecvStateStartRound::GameRun(Game &curGame, int state)
|
|||||||
curGame.getCurrentHand()->getRiver()->riverRun();
|
curGame.getCurrentHand()->getRiver()->riverRun();
|
||||||
} break;
|
} break;
|
||||||
default: {
|
default: {
|
||||||
// TODO
|
//
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -427,7 +437,7 @@ ServerRecvStateStartRound::GetCurrentPlayer(Game &curGame)
|
|||||||
curPlayerNum = curGame.getCurrentHand()->getRiver()->getPlayersTurn();
|
curPlayerNum = curGame.getCurrentHand()->getRiver()->getPlayersTurn();
|
||||||
} break;
|
} break;
|
||||||
default: {
|
default: {
|
||||||
// TODO
|
//
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
assert(curPlayerNum < curGame.getActualQuantityPlayers());
|
assert(curPlayerNum < curGame.getActualQuantityPlayers());
|
||||||
@@ -455,7 +465,8 @@ ServerRecvStateFinal::~ServerRecvStateFinal()
|
|||||||
void
|
void
|
||||||
ServerRecvStateFinal::HandleNewConnection(ServerRecvThread &server, boost::shared_ptr<ConnectData> connData)
|
ServerRecvStateFinal::HandleNewConnection(ServerRecvThread &server, boost::shared_ptr<ConnectData> connData)
|
||||||
{
|
{
|
||||||
// TODO: send error msg
|
// Do not accept new connections in this state.
|
||||||
|
server.RejectNewConnection(connData);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
|||||||
@@ -246,10 +246,16 @@ ServerRecvThread::CleanupSessionMap()
|
|||||||
void
|
void
|
||||||
ServerRecvThread::InternalStartGame()
|
ServerRecvThread::InternalStartGame()
|
||||||
{
|
{
|
||||||
|
SetState(SERVER_START_GAME_STATE::Instance());
|
||||||
|
|
||||||
|
// Kick all players which are not fully connected.
|
||||||
|
RemoveNotEstablishedSessions();
|
||||||
|
|
||||||
|
// Initialize the game.
|
||||||
GuiInterface &gui = GetGui();
|
GuiInterface &gui = GetGui();
|
||||||
PlayerDataList playerData = GetPlayerDataList();
|
PlayerDataList playerData = GetPlayerDataList();
|
||||||
|
|
||||||
// EngineFactory erstellen
|
// Create EngineFactory
|
||||||
boost::shared_ptr<EngineFactory> factory(new LocalEngineFactory(m_playerConfig)); // LocalEngine erstellen
|
boost::shared_ptr<EngineFactory> factory(new LocalEngineFactory(m_playerConfig)); // LocalEngine erstellen
|
||||||
|
|
||||||
// Set dealer pos.
|
// Set dealer pos.
|
||||||
@@ -274,12 +280,11 @@ ServerRecvThread::InternalStartGame()
|
|||||||
}
|
}
|
||||||
++player_i;
|
++player_i;
|
||||||
}
|
}
|
||||||
assert(randDealerFound);
|
assert(randDealerFound); // TODO: Throw exception.
|
||||||
|
|
||||||
SetStartData(startData);
|
SetStartData(startData);
|
||||||
|
|
||||||
m_game.reset(new Game(&gui, factory, playerData, GetGameData(), GetStartData(), m_curGameId++));
|
m_game.reset(new Game(&gui, factory, playerData, GetGameData(), GetStartData(), m_curGameId++));
|
||||||
SetState(SERVER_START_GAME_STATE::Instance());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SessionWrapper
|
SessionWrapper
|
||||||
@@ -320,6 +325,15 @@ ServerRecvThread::SessionError(SessionWrapper session, int errorCode)
|
|||||||
CloseSessionDelayed(session);
|
CloseSessionDelayed(session);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ServerRecvThread::RejectNewConnection(boost::shared_ptr<ConnectData> connData)
|
||||||
|
{
|
||||||
|
// Create a generic session with Id 0.
|
||||||
|
boost::shared_ptr<SessionData> sessionData(new SessionData(connData->ReleaseSocket(), 0));
|
||||||
|
// Gracefully close this session.
|
||||||
|
SessionError(SessionWrapper(sessionData, boost::shared_ptr<PlayerData>()), ERR_NET_GAME_ALREADY_RUNNING);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ServerRecvThread::CloseSessionDelayed(SessionWrapper session)
|
ServerRecvThread::CloseSessionDelayed(SessionWrapper session)
|
||||||
{
|
{
|
||||||
@@ -348,6 +362,39 @@ ServerRecvThread::CloseSessionDelayed(SessionWrapper session)
|
|||||||
m_closeSessionList.push_back(closeSessionData);
|
m_closeSessionList.push_back(closeSessionData);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ServerRecvThread::RemoveNotEstablishedSessions()
|
||||||
|
{
|
||||||
|
SessionList removeList;
|
||||||
|
|
||||||
|
SocketSessionMap::iterator session_i = m_sessionMap.begin();
|
||||||
|
SocketSessionMap::iterator session_end = m_sessionMap.end();
|
||||||
|
|
||||||
|
while (session_i != session_end)
|
||||||
|
{
|
||||||
|
// Remove all players which are not fully connected.
|
||||||
|
assert(session_i->second.sessionData.get());
|
||||||
|
if (session_i->second.sessionData->GetState() != SessionData::Established)
|
||||||
|
{
|
||||||
|
// Do not mess with the map within this loop.
|
||||||
|
// Just store what needs to be removed.
|
||||||
|
removeList.push_back(session_i->second);
|
||||||
|
}
|
||||||
|
++session_i;
|
||||||
|
}
|
||||||
|
|
||||||
|
SessionList::iterator remove_i = removeList.begin();
|
||||||
|
SessionList::iterator remove_end = removeList.end();
|
||||||
|
|
||||||
|
while (remove_i != remove_end)
|
||||||
|
{
|
||||||
|
// Inform the players that we are starting without them.
|
||||||
|
// Gracefully remove them from the server.
|
||||||
|
SessionError(*remove_i, ERR_NET_GAME_ALREADY_RUNNING);
|
||||||
|
++remove_i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
size_t
|
size_t
|
||||||
ServerRecvThread::GetCurNumberOfPlayers() const
|
ServerRecvThread::GetCurNumberOfPlayers() const
|
||||||
{
|
{
|
||||||
@@ -364,6 +411,7 @@ ServerRecvThread::IsPlayerConnected(const std::string &playerName) const
|
|||||||
PlayerDataList::const_iterator player_i = playerList.begin();
|
PlayerDataList::const_iterator player_i = playerList.begin();
|
||||||
PlayerDataList::const_iterator player_end = playerList.end();
|
PlayerDataList::const_iterator player_end = playerList.end();
|
||||||
|
|
||||||
|
// Check by name - the name is unique.
|
||||||
while (player_i != player_end)
|
while (player_i != player_end)
|
||||||
{
|
{
|
||||||
if ((*player_i)->GetName() == playerName)
|
if ((*player_i)->GetName() == playerName)
|
||||||
@@ -380,19 +428,19 @@ ServerRecvThread::IsPlayerConnected(const std::string &playerName) const
|
|||||||
void
|
void
|
||||||
ServerRecvThread::SetSessionPlayerData(boost::shared_ptr<SessionData> sessionData, boost::shared_ptr<PlayerData> playerData)
|
ServerRecvThread::SetSessionPlayerData(boost::shared_ptr<SessionData> sessionData, boost::shared_ptr<PlayerData> playerData)
|
||||||
{
|
{
|
||||||
if (playerData.get() && !playerData->GetName().empty())
|
assert(playerData.get());
|
||||||
|
assert(!playerData->GetName().empty());
|
||||||
|
assert(sessionData.get());
|
||||||
|
|
||||||
|
boost::mutex::scoped_lock lock(m_sessionMapMutex);
|
||||||
|
|
||||||
|
SocketSessionMap::iterator pos = m_sessionMap.find(sessionData->GetSocket());
|
||||||
|
if (pos != m_sessionMap.end())
|
||||||
{
|
{
|
||||||
assert(sessionData.get());
|
pos->second.playerData = playerData;
|
||||||
boost::mutex::scoped_lock lock(m_sessionMapMutex);
|
|
||||||
|
|
||||||
SocketSessionMap::iterator pos = m_sessionMap.find(sessionData->GetSocket());
|
// Signal joining player to GUI.
|
||||||
if (pos != m_sessionMap.end())
|
GetCallback().SignalNetServerPlayerJoined(playerData->GetName());
|
||||||
{
|
|
||||||
pos->second.playerData = playerData;
|
|
||||||
|
|
||||||
// Signal joining player to GUI.
|
|
||||||
GetCallback().SignalNetServerPlayerJoined(playerData->GetName());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -407,9 +455,14 @@ ServerRecvThread::GetPlayerDataList() const
|
|||||||
|
|
||||||
while (session_i != session_end)
|
while (session_i != session_end)
|
||||||
{
|
{
|
||||||
boost::shared_ptr<PlayerData> tmpPlayer(session_i->second.playerData);
|
// Get all players which are fully connected.
|
||||||
if (tmpPlayer.get() && !tmpPlayer->GetName().empty())
|
if (session_i->second.sessionData->GetState() == SessionData::Established)
|
||||||
|
{
|
||||||
|
boost::shared_ptr<PlayerData> tmpPlayer(session_i->second.playerData);
|
||||||
|
assert(tmpPlayer.get());
|
||||||
|
assert(!tmpPlayer->GetName().empty());
|
||||||
playerList.push_back(tmpPlayer);
|
playerList.push_back(tmpPlayer);
|
||||||
|
}
|
||||||
++session_i;
|
++session_i;
|
||||||
}
|
}
|
||||||
// Sort the list by player number.
|
// Sort the list by player number.
|
||||||
@@ -460,8 +513,11 @@ ServerRecvThread::SendToAllPlayers(boost::shared_ptr<NetPacket> packet)
|
|||||||
|
|
||||||
while (i != end)
|
while (i != end)
|
||||||
{
|
{
|
||||||
// Send each client a copy of the packet.
|
assert(i->second.sessionData.get());
|
||||||
GetSender().Send(i->first, boost::shared_ptr<NetPacket>(packet->Clone()));
|
|
||||||
|
// Send each fully connected client a copy of the packet.
|
||||||
|
if (i->second.sessionData->GetState() == SessionData::Established)
|
||||||
|
GetSender().Send(i->first, boost::shared_ptr<NetPacket>(packet->Clone()));
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -477,9 +533,10 @@ ServerRecvThread::SendToAllButOnePlayers(boost::shared_ptr<NetPacket> packet, SO
|
|||||||
|
|
||||||
while (i != end)
|
while (i != end)
|
||||||
{
|
{
|
||||||
// Send each client but one a copy of the packet.
|
// Send each fully connected client but one a copy of the packet.
|
||||||
if (i->first != except)
|
if (i->second.sessionData->GetState() == SessionData::Established)
|
||||||
GetSender().Send(i->first, boost::shared_ptr<NetPacket>(packet->Clone()));
|
if (i->first != except)
|
||||||
|
GetSender().Send(i->first, boost::shared_ptr<NetPacket>(packet->Clone()));
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -83,6 +83,7 @@ protected:
|
|||||||
|
|
||||||
typedef std::deque<boost::shared_ptr<ConnectData> > ConnectQueue;
|
typedef std::deque<boost::shared_ptr<ConnectData> > ConnectQueue;
|
||||||
typedef std::map<SOCKET, SessionWrapper> SocketSessionMap;
|
typedef std::map<SOCKET, SessionWrapper> SocketSessionMap;
|
||||||
|
typedef std::list<SessionWrapper> SessionList;
|
||||||
typedef std::deque<Notification> NotificationQueue;
|
typedef std::deque<Notification> NotificationQueue;
|
||||||
typedef std::list<std::pair<boost::microsec_timer, boost::shared_ptr<SessionData> > > CloseSessionList;
|
typedef std::list<std::pair<boost::microsec_timer, boost::shared_ptr<SessionData> > > CloseSessionList;
|
||||||
|
|
||||||
@@ -102,7 +103,9 @@ protected:
|
|||||||
SessionWrapper GetSession(SOCKET sock);
|
SessionWrapper GetSession(SOCKET sock);
|
||||||
void AddSession(boost::shared_ptr<SessionData> sessionData); // new Sessions have no player data
|
void AddSession(boost::shared_ptr<SessionData> sessionData); // new Sessions have no player data
|
||||||
void SessionError(SessionWrapper session, int errorCode);
|
void SessionError(SessionWrapper session, int errorCode);
|
||||||
|
void RejectNewConnection(boost::shared_ptr<ConnectData> connData);
|
||||||
void CloseSessionDelayed(SessionWrapper session);
|
void CloseSessionDelayed(SessionWrapper session);
|
||||||
|
void RemoveNotEstablishedSessions();
|
||||||
|
|
||||||
size_t GetCurNumberOfPlayers() const;
|
size_t GetCurNumberOfPlayers() const;
|
||||||
bool IsPlayerConnected(const std::string &playerName) const;
|
bool IsPlayerConnected(const std::string &playerName) const;
|
||||||
@@ -163,6 +166,7 @@ friend class ServerRecvStateInit;
|
|||||||
friend class ServerRecvStateStartGame;
|
friend class ServerRecvStateStartGame;
|
||||||
friend class ServerRecvStateStartHand;
|
friend class ServerRecvStateStartHand;
|
||||||
friend class ServerRecvStateStartRound;
|
friend class ServerRecvStateStartRound;
|
||||||
|
friend class ServerRecvStateFinal;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user