Major redesign: The game can not be left without disconnecting from the server. This happens if a player is kicked, if he wishes to leave, or for other reasons. Error packets from the server will always cause a disconnect, however.

If joining a game fails, there is a proper failure packet now.
This commit is contained in:
lotodore
2007-09-06 19:09:05 +00:00
parent 040aadda3c
commit 9d0edc5eee
24 changed files with 694 additions and 140 deletions
+81 -9
View File
@@ -80,6 +80,19 @@ ServerLobbyThread::AddConnection(boost::shared_ptr<ConnectData> data)
m_connectQueue.push_back(data);
}
void
ServerLobbyThread::ReAddSession(SessionWrapper session, int reason)
{
boost::shared_ptr<NetPacket> packet(new NetPacketRemovedFromGame);
NetPacketRemovedFromGame::Data removedData;
removedData.removeReason = reason;
static_cast<NetPacketRemovedFromGame *>(packet.get())->SetData(removedData);
GetSender().Send(session.sessionData->GetSocket(), packet);
boost::mutex::scoped_lock lock(m_sessionQueueMutex);
m_sessionQueue.push_back(session);
}
void
ServerLobbyThread::CloseSessionDelayed(SessionWrapper session)
{
@@ -160,6 +173,20 @@ ServerLobbyThread::Main()
if (tmpData.get())
HandleNewConnection(tmpData);
}
{
// Handle one incoming session at a time.
SessionWrapper tmpSession;
{
boost::mutex::scoped_lock lock(m_sessionQueueMutex);
if (!m_sessionQueue.empty())
{
tmpSession = m_sessionQueue.front();
m_sessionQueue.pop_front();
}
}
if (tmpSession.sessionData.get() && tmpSession.playerData.get())
HandleNewSession(tmpSession);
}
// Process loop.
ProcessLoop();
// Close sessions.
@@ -197,7 +224,7 @@ ServerLobbyThread::ProcessLoop()
} catch (const NetException &)
{
// On error: Close this session.
CloseSessionDelayed(session);
m_sessionManager.RemoveSession(session.sessionData->GetSocket());
return;
}
if (packet.get())
@@ -279,13 +306,7 @@ ServerLobbyThread::HandleNetPacketInit(SessionWrapper session, const NetPacketIn
GetSender().Send(session.sessionData->GetSocket(), initAck);
// Send the game list to the client.
GameMap::const_iterator game_i = m_gameMap.begin();
GameMap::const_iterator game_end = m_gameMap.end();
while (game_i != game_end)
{
GetSender().Send(session.sessionData->GetSocket(), CreateNetPacketGameListNew(*game_i->second));
++game_i;
}
SendGameList(session.sessionData->GetSocket());
// Set player data for session.
m_sessionManager.SetSessionPlayerData(session.sessionData->GetSocket(), tmpPlayerData);
@@ -378,7 +399,7 @@ ServerLobbyThread::HandleNetPacketJoinGame(SessionWrapper session, const NetPack
}
else
{
SessionError(session, ERR_NET_INVALID_PASSWORD);
SendJoinGameFailed(session.sessionData->GetSocket(), NTF_NET_JOIN_INVALID_PASSWORD);
}
}
else
@@ -485,6 +506,35 @@ ServerLobbyThread::HandleNewConnection(boost::shared_ptr<ConnectData> connData)
}
}
void
ServerLobbyThread::HandleNewSession(SessionWrapper session)
{
if (m_sessionManager.GetRawSessionCount() <= SERVER_MAX_NUM_SESSIONS)
{
// This session has been temporarily stored - check if no
// one else got the player name during that time.
if (!m_sessionManager.IsPlayerConnected(session.playerData->GetName()))
{
// Send the list of games.
SendGameList(session.sessionData->GetSocket());
// Set state (back) to established.
session.sessionData->SetState(SessionData::Established);
// Add session to lobby list.
m_sessionManager.AddSession(session);
}
else
{
// Gracefully close this session.
SessionError(session, ERR_NET_PLAYER_NAME_IN_USE);
}
}
else
{
// Gracefully close this session.
SessionError(session, ERR_NET_SERVER_FULL);
}
}
void
ServerLobbyThread::CleanupConnectQueue()
{
@@ -514,6 +564,28 @@ ServerLobbyThread::SendError(SOCKET s, int errorCode)
GetSender().Send(s, packet);
}
void
ServerLobbyThread::SendJoinGameFailed(SOCKET s, int reason)
{
boost::shared_ptr<NetPacket> packet(new NetPacketJoinGameFailed);
NetPacketJoinGameFailed::Data failedData;
failedData.failureCode = reason;
static_cast<NetPacketJoinGameFailed *>(packet.get())->SetData(failedData);
GetSender().Send(s, packet);
}
void
ServerLobbyThread::SendGameList(SOCKET s)
{
GameMap::const_iterator game_i = m_gameMap.begin();
GameMap::const_iterator game_end = m_gameMap.end();
while (game_i != game_end)
{
GetSender().Send(s, CreateNetPacketGameListNew(*game_i->second));
++game_i;
}
}
ServerCallback &
ServerLobbyThread::GetCallback()
{