Game list in Lobby is now shown and updated even after joining or creating a game. Game updates will be sent by the server at all times (even during the game).

This commit is contained in:
lotodore
2007-09-29 14:05:41 +00:00
parent 390837f332
commit 3c88ba8bbe
19 changed files with 407 additions and 197 deletions
@@ -18,7 +18,7 @@
#include <net/socket_msg.h> #include <net/socket_msg.h>
gameLobbyDialogImpl::gameLobbyDialogImpl(QWidget *parent, ConfigFile *c) gameLobbyDialogImpl::gameLobbyDialogImpl(QWidget *parent, ConfigFile *c)
: QDialog(parent), myW(NULL), myConfig(c), mySession(NULL), currentGameName(""), isAdmin(false), myChat(NULL) : QDialog(parent), myW(NULL), myConfig(c), mySession(NULL), currentGameName(""), isAdmin(false), inGame(false), myChat(NULL)
{ {
setupUi(this); setupUi(this);
@@ -50,7 +50,6 @@ void gameLobbyDialogImpl::exec()
mySession->startIrcClient(); mySession->startIrcClient();
QDialog::exec(); QDialog::exec();
mySession->terminateIrcClient(); mySession->terminateIrcClient();
clearDialog();
} }
@@ -162,12 +161,14 @@ void gameLobbyDialogImpl::refresh(int actionID) {
void gameLobbyDialogImpl::removedFromGame(int reason) void gameLobbyDialogImpl::removedFromGame(int reason)
{ {
clearDialog(); inGame = false;
isAdmin = false;
leftGameDialogUpdate();
} }
void gameLobbyDialogImpl::gameSelected(QTreeWidgetItem* item, QTreeWidgetItem*) void gameLobbyDialogImpl::gameSelected(QTreeWidgetItem* item, QTreeWidgetItem*)
{ {
if (item) if (!inGame && item)
{ {
pushButton_JoinGame->setEnabled(true); pushButton_JoinGame->setEnabled(true);
@@ -234,6 +235,8 @@ void gameLobbyDialogImpl::removeGame(unsigned gameId)
void gameLobbyDialogImpl::gameAddPlayer(unsigned gameId, unsigned playerId) void gameLobbyDialogImpl::gameAddPlayer(unsigned gameId, unsigned playerId)
{ {
if (!inGame)
{
QTreeWidgetItem *item = treeWidget_GameList->currentItem(); QTreeWidgetItem *item = treeWidget_GameList->currentItem();
if (item && item->data(0, Qt::UserRole) == gameId) if (item && item->data(0, Qt::UserRole) == gameId)
{ {
@@ -241,6 +244,7 @@ void gameLobbyDialogImpl::gameAddPlayer(unsigned gameId, unsigned playerId)
PlayerInfo info(mySession->getClientPlayerInfo(playerId)); PlayerInfo info(mySession->getClientPlayerInfo(playerId));
addConnectedPlayer(playerId, QString::fromUtf8(info.playerName.c_str()), PLAYER_RIGHTS_NORMAL); addConnectedPlayer(playerId, QString::fromUtf8(info.playerName.c_str()), PLAYER_RIGHTS_NORMAL);
} }
}
QTreeWidgetItemIterator it(treeWidget_GameList); QTreeWidgetItemIterator it(treeWidget_GameList);
while (*it) { while (*it) {
@@ -255,6 +259,8 @@ void gameLobbyDialogImpl::gameAddPlayer(unsigned gameId, unsigned playerId)
void gameLobbyDialogImpl::gameRemovePlayer(unsigned gameId, unsigned playerId) void gameLobbyDialogImpl::gameRemovePlayer(unsigned gameId, unsigned playerId)
{ {
if (!inGame)
{
QTreeWidgetItem *item = treeWidget_GameList->currentItem(); QTreeWidgetItem *item = treeWidget_GameList->currentItem();
if (item && item->data(0, Qt::UserRole) == gameId) if (item && item->data(0, Qt::UserRole) == gameId)
{ {
@@ -262,6 +268,7 @@ void gameLobbyDialogImpl::gameRemovePlayer(unsigned gameId, unsigned playerId)
PlayerInfo info(mySession->getClientPlayerInfo(playerId)); PlayerInfo info(mySession->getClientPlayerInfo(playerId));
removePlayer(playerId, QString::fromUtf8(info.playerName.c_str())); removePlayer(playerId, QString::fromUtf8(info.playerName.c_str()));
} }
}
QTreeWidgetItemIterator it(treeWidget_GameList); QTreeWidgetItemIterator it(treeWidget_GameList);
while (*it) { while (*it) {
@@ -307,6 +314,8 @@ void gameLobbyDialogImpl::clearDialog()
pushButton_CreateGame->clearFocus(); pushButton_CreateGame->clearFocus();
lineEdit_ChatInput->setFocus(); lineEdit_ChatInput->setFocus();
myChat->clearChat(); myChat->clearChat();
inGame = false;
isAdmin = false;
} }
void gameLobbyDialogImpl::checkPlayerQuantity() { void gameLobbyDialogImpl::checkPlayerQuantity() {
@@ -328,7 +337,8 @@ void gameLobbyDialogImpl::checkPlayerQuantity() {
void gameLobbyDialogImpl::joinedNetworkGame(unsigned playerId, QString playerName, int rights) { void gameLobbyDialogImpl::joinedNetworkGame(unsigned playerId, QString playerName, int rights) {
// Update dialog // Update dialog
gameModeDialogUpdate(); inGame = true;
joinedGameDialogUpdate();
isAdmin = rights == PLAYER_RIGHTS_ADMIN; isAdmin = rights == PLAYER_RIGHTS_ADMIN;
addConnectedPlayer(playerId, playerName, rights); addConnectedPlayer(playerId, playerName, rights);
@@ -382,17 +392,43 @@ void gameLobbyDialogImpl::removePlayer(unsigned playerId, QString) {
checkPlayerQuantity(); checkPlayerQuantity();
} }
void gameLobbyDialogImpl::gameModeDialogUpdate() { void gameLobbyDialogImpl::joinedGameDialogUpdate() {
groupBox_GameInfo->setEnabled(true); groupBox_GameInfo->setEnabled(true);
groupBox_GameInfo->setTitle(currentGameName); groupBox_GameInfo->setTitle(currentGameName);
treeWidget_GameList->clear();
treeWidget_GameList->hide();
treeWidget_connectedPlayers->clear(); treeWidget_connectedPlayers->clear();
pushButton_CreateGame->hide(); pushButton_CreateGame->hide();
pushButton_JoinGame->hide(); pushButton_JoinGame->hide();
pushButton_Leave->show(); pushButton_Leave->show();
} }
void gameLobbyDialogImpl::leftGameDialogUpdate() {
// un-select current game.
treeWidget_GameList->clearSelection();
groupBox_GameInfo->setTitle(tr("Game Info"));
groupBox_GameInfo->setEnabled(false);
currentGameName = "";
label_SmallBlind->setText("");
label_StartCash->setText("");
label_MaximumNumberOfPlayers->setText("");
label_HandsToRaiseSmallBlind->setText("");
label_TimeoutForPlayerAction->setText("");
treeWidget_connectedPlayers->clear();
pushButton_StartGame->hide();
pushButton_Leave->hide();
pushButton_Kick->hide();
pushButton_Kick->setEnabled(false);
checkBox_fillUpWithComputerOpponents->hide();
pushButton_CreateGame->show();
pushButton_JoinGame->show();
pushButton_JoinGame->setEnabled(false);
lineEdit_ChatInput->setFocus();
}
void gameLobbyDialogImpl::playerSelected(QTreeWidgetItem* item, QTreeWidgetItem*) { void gameLobbyDialogImpl::playerSelected(QTreeWidgetItem* item, QTreeWidgetItem*) {
if (item) if (item)
@@ -82,7 +82,8 @@ public slots:
void leaveGame(); void leaveGame();
void kickPlayer(); void kickPlayer();
void gameModeDialogUpdate(); void joinedGameDialogUpdate();
void leftGameDialogUpdate();
void clearDialog(); void clearDialog();
void sendChatMessage(); void sendChatMessage();
@@ -98,6 +99,7 @@ private:
createInternetGameDialogImpl *myCreateInternetGameDialog; createInternetGameDialogImpl *myCreateInternetGameDialog;
QString currentGameName; QString currentGameName;
bool isAdmin; bool isAdmin;
bool inGame;
LobbyChat *myChat; LobbyChat *myChat;
}; };
@@ -59,7 +59,6 @@ void LobbyChat::selfJoined(QString ownName, QString channel)
myNick = ownName; myNick = ownName;
myLobby->textBrowser_ChatDisplay->append(tr("Joined channel:") + " " + channel + " " + tr("as user") + " " + ownName + "."); myLobby->textBrowser_ChatDisplay->append(tr("Joined channel:") + " " + channel + " " + tr("as user") + " " + ownName + ".");
myLobby->textBrowser_ChatDisplay->append(""); myLobby->textBrowser_ChatDisplay->append("");
playerJoined(ownName);
myLobby->lineEdit_ChatInput->setEnabled(true); myLobby->lineEdit_ChatInput->setEnabled(true);
myLobby->lineEdit_ChatInput->setFocus(); myLobby->lineEdit_ChatInput->setFocus();
} }
+7
View File
@@ -884,6 +884,9 @@ void mainWindowImpl::callCreateNetworkGameDialog() {
myGameLobbyDialog->setSession(&getSession()); myGameLobbyDialog->setSession(&getSession());
myStartNetworkGameDialog->setSession(&getSession()); myStartNetworkGameDialog->setSession(&getSession());
// Clear network game dialog.
myStartNetworkGameDialog->clearDialog();
myServerGuiInterface->getSession().startNetworkServer(); myServerGuiInterface->getSession().startNetworkServer();
mySession->startNetworkClientForLocalServer(gameData); mySession->startNetworkClientForLocalServer(gameData);
@@ -908,6 +911,8 @@ void mainWindowImpl::callJoinNetworkGameDialog() {
myGameLobbyDialog->setSession(&getSession()); myGameLobbyDialog->setSession(&getSession());
myStartNetworkGameDialog->setSession(&getSession()); myStartNetworkGameDialog->setSession(&getSession());
// Clear network game dialog
myStartNetworkGameDialog->clearDialog();
// Maybe use QUrl::toPunycode. // Maybe use QUrl::toPunycode.
mySession->startNetworkClient( mySession->startNetworkClient(
myJoinNetworkGameDialog->lineEdit_ipAddress->text().toUtf8().constData(), myJoinNetworkGameDialog->lineEdit_ipAddress->text().toUtf8().constData(),
@@ -958,6 +963,8 @@ void mainWindowImpl::joinGameLobby() {
myGameLobbyDialog->setSession(&getSession()); myGameLobbyDialog->setSession(&getSession());
myStartNetworkGameDialog->setSession(&getSession()); myStartNetworkGameDialog->setSession(&getSession());
// Clear Lobby dialog.
myGameLobbyDialog->clearDialog();
// Start client for dedicated server. // Start client for dedicated server.
mySession->startInternetClient(); mySession->startInternetClient();
@@ -43,7 +43,6 @@ void startNetworkGameDialogImpl::exec() {
label_maxPlayerNumber->setText(QString::number(info.data.maxNumberOfPlayers)); label_maxPlayerNumber->setText(QString::number(info.data.maxNumberOfPlayers));
QDialog::exec(); QDialog::exec();
clearDialog();
} }
void startNetworkGameDialogImpl::startGame() { void startNetworkGameDialogImpl::startGame() {
+49 -50
View File
@@ -399,7 +399,6 @@ AbstractClientStateReceiving::Process(ClientThread &client)
NetPacketRemovedFromGame::Data removedData; NetPacketRemovedFromGame::Data removedData;
tmpPacket->ToNetPacketRemovedFromGame()->GetData(removedData); tmpPacket->ToNetPacketRemovedFromGame()->GetData(removedData);
client.ClearPlayerDataList(); client.ClearPlayerDataList();
client.ClearGameInfoMap();
client.GetCallback().SignalNetClientRemovedFromGame(removedData.removeReason); client.GetCallback().SignalNetClientRemovedFromGame(removedData.removeReason);
client.SetState(ClientStateWaitJoin::Instance()); client.SetState(ClientStateWaitJoin::Instance());
} }
@@ -430,6 +429,54 @@ AbstractClientStateReceiving::Process(ClientThread &client)
// Signal to GUI and remove from data list. // Signal to GUI and remove from data list.
client.RemovePlayerData(playerLeftData.playerId); client.RemovePlayerData(playerLeftData.playerId);
} }
else if (tmpPacket->ToNetPacketGameListNew())
{
// A new game was created on the server.
NetPacketGameListNew::Data gameListNewData;
tmpPacket->ToNetPacketGameListNew()->GetData(gameListNewData);
// Request player info for players if needed.
PlayerIdList::const_iterator i = gameListNewData.gameInfo.players.begin();
PlayerIdList::const_iterator end = gameListNewData.gameInfo.players.end();
while (i != end)
{
PlayerInfo info;
if (!client.GetCachedPlayerInfo(*i, info))
{
// Request player info.
client.RequestPlayerInfo(*i);
}
++i;
}
client.AddGameInfo(gameListNewData.gameId, gameListNewData.gameInfo);
}
else if (tmpPacket->ToNetPacketGameListUpdate())
{
// An existing game was updated on the server.
NetPacketGameListUpdate::Data gameListUpdateData;
tmpPacket->ToNetPacketGameListUpdate()->GetData(gameListUpdateData);
if (gameListUpdateData.gameMode == GAME_MODE_CLOSED)
client.RemoveGameInfo(gameListUpdateData.gameId);
}
else if (tmpPacket->ToNetPacketGameListPlayerJoined())
{
NetPacketGameListPlayerJoined::Data playerJoinedData;
tmpPacket->ToNetPacketGameListPlayerJoined()->GetData(playerJoinedData);
client.ModifyGameInfoAddPlayer(playerJoinedData.gameId, playerJoinedData.playerId);
// Request player info if needed.
PlayerInfo info;
if (!client.GetCachedPlayerInfo(playerJoinedData.playerId, info))
{
client.RequestPlayerInfo(playerJoinedData.playerId);
}
}
else if (tmpPacket->ToNetPacketGameListPlayerLeft())
{
NetPacketGameListPlayerLeft::Data playerLeftData;
tmpPacket->ToNetPacketGameListPlayerLeft()->GetData(playerLeftData);
client.ModifyGameInfoRemovePlayer(playerLeftData.gameId, playerLeftData.playerId);
}
else else
retVal = InternalProcess(client, tmpPacket); retVal = InternalProcess(client, tmpPacket);
} }
@@ -497,55 +544,7 @@ ClientStateWaitJoin::InternalProcess(ClientThread &client, boost::shared_ptr<Net
int retVal = MSG_SOCK_INTERNAL_PENDING; int retVal = MSG_SOCK_INTERNAL_PENDING;
ClientContext &context = client.GetContext(); ClientContext &context = client.GetContext();
if (packet->ToNetPacketGameListNew()) if (packet->ToNetPacketJoinGameAck())
{
// A new game was created on the server.
NetPacketGameListNew::Data gameListNewData;
packet->ToNetPacketGameListNew()->GetData(gameListNewData);
// Request player info for players if needed.
PlayerIdList::const_iterator i = gameListNewData.gameInfo.players.begin();
PlayerIdList::const_iterator end = gameListNewData.gameInfo.players.end();
while (i != end)
{
PlayerInfo info;
if (!client.GetCachedPlayerInfo(*i, info))
{
// Request player info.
client.RequestPlayerInfo(*i);
}
++i;
}
client.AddGameInfo(gameListNewData.gameId, gameListNewData.gameInfo);
}
else if (packet->ToNetPacketGameListUpdate())
{
// An existing game was updated on the server.
NetPacketGameListUpdate::Data gameListUpdateData;
packet->ToNetPacketGameListUpdate()->GetData(gameListUpdateData);
if (gameListUpdateData.gameMode == GAME_MODE_CLOSED)
client.RemoveGameInfo(gameListUpdateData.gameId);
}
else if (packet->ToNetPacketGameListPlayerJoined())
{
NetPacketGameListPlayerJoined::Data playerJoinedData;
packet->ToNetPacketGameListPlayerJoined()->GetData(playerJoinedData);
client.ModifyGameInfoAddPlayer(playerJoinedData.gameId, playerJoinedData.playerId);
// Request player info if needed.
PlayerInfo info;
if (!client.GetCachedPlayerInfo(playerJoinedData.playerId, info))
{
client.RequestPlayerInfo(playerJoinedData.playerId);
}
}
else if (packet->ToNetPacketGameListPlayerLeft())
{
NetPacketGameListPlayerLeft::Data playerLeftData;
packet->ToNetPacketGameListPlayerLeft()->GetData(playerLeftData);
client.ModifyGameInfoRemovePlayer(playerLeftData.gameId, playerLeftData.playerId);
}
else if (packet->ToNetPacketJoinGameAck())
{ {
// Successfully joined a game. // Successfully joined a game.
NetPacketJoinGameAck::Data joinGameAckData; NetPacketJoinGameAck::Data joinGameAckData;
-1
View File
@@ -70,7 +70,6 @@ void irc_notify_player_list(irc_session_t *session, const char *players)
input >> name; input >> name;
while (!input.fail() && !input.eof()) while (!input.fail() && !input.eof())
{ {
if (name != context->nick)
context->ircThread.GetCallback().SignalIrcPlayerJoined(name); context->ircThread.GetCallback().SignalIrcPlayerJoined(name);
input >> name; input >> name;
} }
+3 -22
View File
@@ -141,7 +141,7 @@ AbstractServerGameStateReceiving::Process(ServerGameThread &server)
packet = server.GetReceiver().Recv(session.sessionData->GetSocket(), session.sessionData->GetReceiveBuffer()); packet = server.GetReceiver().Recv(session.sessionData->GetSocket(), session.sessionData->GetReceiveBuffer());
} catch (const NetException &) } catch (const NetException &)
{ {
server.RemoveSession(session); server.ErrorRemoveSession(session);
return retVal; return retVal;
} }
@@ -150,25 +150,8 @@ AbstractServerGameStateReceiving::Process(ServerGameThread &server)
{ {
if (packet->ToNetPacketRetrievePlayerInfo()) if (packet->ToNetPacketRetrievePlayerInfo())
{ {
NetPacketRetrievePlayerInfo::Data reqData; // Delegate to Lobby.
packet->ToNetPacketRetrievePlayerInfo()->GetData(reqData); server.GetLobbyThread().HandleGameRetrievePlayerInfo(session, *packet->ToNetPacketRetrievePlayerInfo());
SessionWrapper tmpSession = server.GetSessionManager().GetSessionByUniquePlayerId(reqData.playerId);
if (tmpSession.sessionData.get() && tmpSession.playerData.get())
{
// Send player info to client.
// TODO this is a copy and paste
boost::shared_ptr<NetPacket> info(new NetPacketPlayerInfo);
NetPacketPlayerInfo::Data infoData;
infoData.playerId = tmpSession.playerData->GetUniqueId();
infoData.playerInfo.ptype = tmpSession.playerData->GetType();
infoData.playerInfo.playerName = tmpSession.playerData->GetName();
infoData.playerInfo.hasAvatar = !tmpSession.playerData->GetAvatarFile().empty();
if (infoData.playerInfo.hasAvatar)
infoData.playerInfo.avatar.FromString(tmpSession.playerData->GetAvatarFile());
static_cast<NetPacketPlayerInfo *>(info.get())->SetData(infoData);
server.GetSender().Send(session.sessionData->GetSocket(), info);
}
} }
else if (packet->ToNetPacketLeaveCurrentGame()) else if (packet->ToNetPacketLeaveCurrentGame())
{ {
@@ -282,8 +265,6 @@ ServerGameStateInit::HandleNewSession(ServerGameThread &server, SessionWrapper s
// Send "Player Joined" to other fully connected clients. // Send "Player Joined" to other fully connected clients.
server.SendToAllPlayers(CreateNetPacketPlayerJoined(*session.playerData), SessionData::Game); server.SendToAllPlayers(CreateNetPacketPlayerJoined(*session.playerData), SessionData::Game);
// Session is now in game state.
session.sessionData->SetState(SessionData::Game);
// Accept session. // Accept session.
server.GetSessionManager().AddSession(session); server.GetSessionManager().AddSession(session);
+28 -3
View File
@@ -29,6 +29,8 @@
#include <localenginefactory.h> #include <localenginefactory.h>
#include <tools.h> #include <tools.h>
#include <boost/bind.hpp>
using namespace std; using namespace std;
@@ -100,6 +102,22 @@ ServerGameThread::SendToAllPlayers(boost::shared_ptr<NetPacket> packet, SessionD
GetSessionManager().SendToAllSessions(GetSender(), packet, state); GetSessionManager().SendToAllSessions(GetSender(), packet, state);
} }
void
ServerGameThread::RemoveAllSessions()
{
// Called from lobby thread.
// Clean up ALL sessions which are left.
ServerLobbyThread &lobbyThread = GetLobbyThread();
boost::mutex::scoped_lock lock(m_sessionQueueMutex);
while (!m_sessionQueue.empty())
{
SessionWrapper tmpSession = m_sessionQueue.front();
m_sessionQueue.pop_front();
lobbyThread.RemoveSessionFromGame(tmpSession);
}
GetSessionManager().ForEach(boost::bind(&ServerLobbyThread::RemoveSessionFromGame, boost::ref(lobbyThread), _1));
}
void void
ServerGameThread::Main() ServerGameThread::Main()
{ {
@@ -262,7 +280,7 @@ ServerGameThread::ResetComputerPlayerList()
} }
void void
ServerGameThread::RemoveSession(SessionWrapper session) ServerGameThread::GracefulRemoveSession(SessionWrapper session)
{ {
assert(session.sessionData.get()); assert(session.sessionData.get());
GetSessionManager().RemoveSession(session.sessionData->GetSocket()); GetSessionManager().RemoveSession(session.sessionData->GetSocket());
@@ -281,18 +299,25 @@ ServerGameThread::RemoveSession(SessionWrapper session)
} }
} }
void
ServerGameThread::ErrorRemoveSession(SessionWrapper session)
{
GetLobbyThread().RemoveSessionFromGame(session);
GracefulRemoveSession(session);
}
void void
ServerGameThread::SessionError(SessionWrapper session, int errorCode) ServerGameThread::SessionError(SessionWrapper session, int errorCode)
{ {
assert(session.sessionData.get()); assert(session.sessionData.get());
RemoveSession(session); ErrorRemoveSession(session);
GetLobbyThread().SessionError(session, errorCode); GetLobbyThread().SessionError(session, errorCode);
} }
void void
ServerGameThread::MoveSessionToLobby(SessionWrapper session, int reason) ServerGameThread::MoveSessionToLobby(SessionWrapper session, int reason)
{ {
RemoveSession(session); GracefulRemoveSession(session);
GetLobbyThread().ReAddSession(session, reason); GetLobbyThread().ReAddSession(session, reason);
} }
+45 -48
View File
@@ -29,7 +29,7 @@
#include <boost/lambda/lambda.hpp> #include <boost/lambda/lambda.hpp>
#define SERVER_CLOSE_SESSION_DELAY_SEC 10 #define SERVER_CLOSE_SESSION_DELAY_SEC 10
#define SERVER_MAX_NUM_SESSIONS 64 // Maximum number of idle users in lobby. #define SERVER_MAX_NUM_SESSIONS 512 // Maximum number of idle users in lobby.
#define SERVER_COMPUTER_PLAYER_NAME "Computer" #define SERVER_COMPUTER_PLAYER_NAME "Computer"
@@ -93,10 +93,31 @@ ServerLobbyThread::ReAddSession(SessionWrapper session, int reason)
m_sessionQueue.push_back(session); m_sessionQueue.push_back(session);
} }
void
ServerLobbyThread::MoveSessionToGame(ServerGameThread &game, SessionWrapper session)
{
// Remove session from the lobby.
m_sessionManager.RemoveSession(session.sessionData->GetSocket());
// Session is now in game state.
session.sessionData->SetState(SessionData::Game);
// Store it in the list of game sessions.
m_gameSessionManager.AddSession(session);
// Add session to the game.
game.AddSession(session);
}
void
ServerLobbyThread::RemoveSessionFromGame(SessionWrapper session)
{
// Just remove the session. Only for fatal errors.
m_gameSessionManager.RemoveSession(session.sessionData->GetSocket());
}
void void
ServerLobbyThread::CloseSessionDelayed(SessionWrapper session) ServerLobbyThread::CloseSessionDelayed(SessionWrapper session)
{ {
m_sessionManager.RemoveSession(session.sessionData->GetSocket()); m_sessionManager.RemoveSession(session.sessionData->GetSocket());
m_gameSessionManager.RemoveSession(session.sessionData->GetSocket());
boost::timers::portable::microsec_timer closeTimer; boost::timers::portable::microsec_timer closeTimer;
closeTimer.start(); closeTimer.start();
@@ -116,6 +137,7 @@ ServerLobbyThread::NotifyPlayerJoinedGame(unsigned gameId, unsigned playerId)
packetData.playerId = playerId; packetData.playerId = playerId;
static_cast<NetPacketGameListPlayerJoined *>(packet.get())->SetData(packetData); static_cast<NetPacketGameListPlayerJoined *>(packet.get())->SetData(packetData);
m_sessionManager.SendToAllSessions(GetSender(), packet, SessionData::Established); m_sessionManager.SendToAllSessions(GetSender(), packet, SessionData::Established);
m_gameSessionManager.SendToAllSessions(GetSender(), packet, SessionData::Game);
} }
void void
@@ -128,6 +150,14 @@ ServerLobbyThread::NotifyPlayerLeftGame(unsigned gameId, unsigned playerId)
packetData.playerId = playerId; packetData.playerId = playerId;
static_cast<NetPacketGameListPlayerLeft *>(packet.get())->SetData(packetData); static_cast<NetPacketGameListPlayerLeft *>(packet.get())->SetData(packetData);
m_sessionManager.SendToAllSessions(GetSender(), packet, SessionData::Established); m_sessionManager.SendToAllSessions(GetSender(), packet, SessionData::Established);
m_gameSessionManager.SendToAllSessions(GetSender(), packet, SessionData::Game);
}
void
ServerLobbyThread::HandleGameRetrievePlayerInfo(SessionWrapper session, const NetPacketRetrievePlayerInfo &tmpPacket)
{
// Someone within a game requested player info.
HandleNetPacketRetrievePlayerInfo(session, tmpPacket);
} }
void void
@@ -185,7 +215,7 @@ ServerLobbyThread::Main()
} }
} }
if (tmpSession.sessionData.get() && tmpSession.playerData.get()) if (tmpSession.sessionData.get() && tmpSession.playerData.get())
HandleNewSession(tmpSession); HandleReAddedSession(tmpSession);
} }
// Process loop. // Process loop.
ProcessLoop(); ProcessLoop();
@@ -205,7 +235,6 @@ ServerLobbyThread::Main()
GetSender().Join(SENDER_THREAD_TERMINATE_TIMEOUT); GetSender().Join(SENDER_THREAD_TERMINATE_TIMEOUT);
CleanupConnectQueue(); CleanupConnectQueue();
m_sessionManager.Clear();
} }
void void
@@ -326,17 +355,7 @@ ServerLobbyThread::HandleNetPacketRetrievePlayerInfo(SessionWrapper session, con
// Find player in lobby or in a game. // Find player in lobby or in a game.
boost::shared_ptr<PlayerData> tmpPlayer = m_sessionManager.GetSessionByUniquePlayerId(request.playerId).playerData; boost::shared_ptr<PlayerData> tmpPlayer = m_sessionManager.GetSessionByUniquePlayerId(request.playerId).playerData;
if (!tmpPlayer.get()) if (!tmpPlayer.get())
{ tmpPlayer = m_gameSessionManager.GetSessionByUniquePlayerId(request.playerId).playerData;
GameMap::const_iterator game_i = m_gameMap.begin();
GameMap::const_iterator game_end = m_gameMap.end();
while (game_i != game_end)
{
tmpPlayer = game_i->second->GetPlayerDataByUniqueId(request.playerId);
if (tmpPlayer.get())
break;
++game_i;
}
}
if (tmpPlayer.get()) if (tmpPlayer.get())
{ {
@@ -371,10 +390,7 @@ ServerLobbyThread::HandleNetPacketCreateGame(SessionWrapper session, const NetPa
m_playerConfig)); m_playerConfig));
game->Init(createGameData.gameData); game->Init(createGameData.gameData);
// Remove session from the lobby. MoveSessionToGame(*game, session);
m_sessionManager.RemoveSession(session.sessionData->GetSocket());
// Add session to the game.
game->AddSession(session);
// Add game to list of games. // Add game to list of games.
InternalAddGame(game); InternalAddGame(game);
@@ -397,10 +413,7 @@ ServerLobbyThread::HandleNetPacketJoinGame(SessionWrapper session, const NetPack
ServerGameThread &game = *pos->second; ServerGameThread &game = *pos->second;
if (game.CheckPassword(joinGameData.password)) if (game.CheckPassword(joinGameData.password))
{ {
// Remove session from the lobby. MoveSessionToGame(game, session);
m_sessionManager.RemoveSession(session.sessionData->GetSocket());
// Add session to the game.
game.AddSession(session);
} }
else else
{ {
@@ -461,6 +474,7 @@ ServerLobbyThread::InternalAddGame(boost::shared_ptr<ServerGameThread> game)
m_gameMap.insert(GameMap::value_type(game->GetId(), game)); m_gameMap.insert(GameMap::value_type(game->GetId(), game));
// Notify all players. // Notify all players.
m_sessionManager.SendToAllSessions(GetSender(), CreateNetPacketGameListNew(*game), SessionData::Established); m_sessionManager.SendToAllSessions(GetSender(), CreateNetPacketGameListNew(*game), SessionData::Established);
m_gameSessionManager.SendToAllSessions(GetSender(), CreateNetPacketGameListNew(*game), SessionData::Game);
} }
void void
@@ -468,8 +482,11 @@ ServerLobbyThread::InternalRemoveGame(boost::shared_ptr<ServerGameThread> game)
{ {
// Remove game from list. // Remove game from list.
m_gameMap.erase(game->GetId()); m_gameMap.erase(game->GetId());
// Remove all sessions left in the game.
game->RemoveAllSessions();
// Notify all players. // Notify all players.
m_sessionManager.SendToAllSessions(GetSender(), CreateNetPacketGameListUpdate(*game, GAME_MODE_CLOSED), SessionData::Established); m_sessionManager.SendToAllSessions(GetSender(), CreateNetPacketGameListUpdate(*game, GAME_MODE_CLOSED), SessionData::Established);
m_gameSessionManager.SendToAllSessions(GetSender(), CreateNetPacketGameListUpdate(*game, GAME_MODE_CLOSED), SessionData::Game);
} }
void void
@@ -517,28 +534,19 @@ ServerLobbyThread::HandleNewConnection(boost::shared_ptr<ConnectData> connData)
} }
void void
ServerLobbyThread::HandleNewSession(SessionWrapper session) ServerLobbyThread::HandleReAddedSession(SessionWrapper session)
{ {
// Remove session from game session list.
m_gameSessionManager.RemoveSession(session.sessionData->GetSocket());
if (m_sessionManager.GetRawSessionCount() <= SERVER_MAX_NUM_SESSIONS) 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. // Set state (back) to established.
session.sessionData->SetState(SessionData::Established); session.sessionData->SetState(SessionData::Established);
// Add session to lobby list. // Add session to lobby list.
m_sessionManager.AddSession(session); m_sessionManager.AddSession(session);
} }
else else
{
// Gracefully close this session.
SessionError(session, ERR_NET_PLAYER_NAME_IN_USE);
}
}
else
{ {
// Gracefully close this session. // Gracefully close this session.
SessionError(session, ERR_NET_SERVER_FULL); SessionError(session, ERR_NET_SERVER_FULL);
@@ -643,19 +651,8 @@ ServerLobbyThread::IsPlayerConnected(const string &name)
retVal = m_sessionManager.IsPlayerConnected(name); retVal = m_sessionManager.IsPlayerConnected(name);
if (!retVal) if (!retVal)
{ retVal = m_gameSessionManager.IsPlayerConnected(name);
GameMap::const_iterator game_i = m_gameMap.begin();
GameMap::const_iterator game_end = m_gameMap.end();
while (game_i != game_end)
{
if (game_i->second->IsPlayerConnected(name))
{
retVal = true;
break;
}
++game_i;
}
}
return retVal; return retVal;
} }
+49
View File
@@ -30,3 +30,52 @@ SessionData::~SessionData()
CLOSESOCKET(m_sockfd); CLOSESOCKET(m_sockfd);
} }
unsigned
SessionData::GetId() const
{
// const value - no mutex needed.
return m_id;
}
SessionData::State
SessionData::GetState() const
{
boost::mutex::scoped_lock lock(m_dataMutex);
return m_state;
}
void
SessionData::SetState(SessionData::State state)
{
boost::mutex::scoped_lock lock(m_dataMutex);
m_state = state;
}
SOCKET
SessionData::GetSocket() const
{
// value never modified - no mutex needed.
return m_sockfd;
}
const std::string &
SessionData::GetClientAddr() const
{
boost::mutex::scoped_lock lock(m_dataMutex);
return m_clientAddr;
}
void
SessionData::SetClientAddr(const std::string &addr)
{
boost::mutex::scoped_lock lock(m_dataMutex);
m_clientAddr = addr;
}
ReceiveBuffer &
SessionData::GetReceiveBuffer()
{
// mutex protection, if needed, within buffer.
return m_receiveBuffer;
}
+15
View File
@@ -277,6 +277,21 @@ SessionManager::IsPlayerConnected(unsigned uniqueId) const
return retVal; return retVal;
} }
void
SessionManager::ForEach(boost::function<void (SessionWrapper)> func)
{
boost::mutex::scoped_lock lock(m_sessionMapMutex);
SessionMap::iterator i = m_sessionMap.begin();
SessionMap::iterator end = m_sessionMap.end();
while (i != end)
{
func((*i).second);
++i;
}
}
void void
SessionManager::Clear() SessionManager::Clear()
{ {
+1
View File
@@ -21,6 +21,7 @@
#define _GENERICSOCKET_H_ #define _GENERICSOCKET_H_
#ifdef _WIN32 #ifdef _WIN32
#define FD_SETSIZE 512
#include <winsock2.h> #include <winsock2.h>
#include <ws2tcpip.h> #include <ws2tcpip.h>
#else #else
+3 -1
View File
@@ -56,6 +56,7 @@ public:
GameState GetCurRound() const; GameState GetCurRound() const;
void SendToAllPlayers(boost::shared_ptr<NetPacket> packet, SessionData::State state); void SendToAllPlayers(boost::shared_ptr<NetPacket> packet, SessionData::State state);
void RemoveAllSessions();
bool IsPasswordProtected() const; bool IsPasswordProtected() const;
bool CheckPassword(const std::string &password) const; bool CheckPassword(const std::string &password) const;
@@ -80,7 +81,8 @@ protected:
void AddComputerPlayer(boost::shared_ptr<PlayerData> player); void AddComputerPlayer(boost::shared_ptr<PlayerData> player);
void ResetComputerPlayerList(); void ResetComputerPlayerList();
void RemoveSession(SessionWrapper session); void GracefulRemoveSession(SessionWrapper session);
void ErrorRemoveSession(SessionWrapper session);
void SessionError(SessionWrapper session, int errorCode); void SessionError(SessionWrapper session, int errorCode);
void MoveSessionToLobby(SessionWrapper session, int reason); void MoveSessionToLobby(SessionWrapper session, int reason);
+6 -1
View File
@@ -52,10 +52,14 @@ public:
void AddConnection(boost::shared_ptr<ConnectData> data); void AddConnection(boost::shared_ptr<ConnectData> data);
void ReAddSession(SessionWrapper session, int reason); void ReAddSession(SessionWrapper session, int reason);
void MoveSessionToGame(ServerGameThread &game, SessionWrapper session);
void RemoveSessionFromGame(SessionWrapper session);
void SessionError(SessionWrapper session, int errorCode); void SessionError(SessionWrapper session, int errorCode);
void NotifyPlayerJoinedGame(unsigned gameId, unsigned playerId); void NotifyPlayerJoinedGame(unsigned gameId, unsigned playerId);
void NotifyPlayerLeftGame(unsigned gameId, unsigned playerId); void NotifyPlayerLeftGame(unsigned gameId, unsigned playerId);
void HandleGameRetrievePlayerInfo(SessionWrapper session, const NetPacketRetrievePlayerInfo &tmpPacket);
void RemoveGame(unsigned id); void RemoveGame(unsigned id);
u_int32_t GetNextUniquePlayerId(); u_int32_t GetNextUniquePlayerId();
@@ -88,7 +92,7 @@ protected:
void TerminateGames(); void TerminateGames();
void HandleNewConnection(boost::shared_ptr<ConnectData> connData); void HandleNewConnection(boost::shared_ptr<ConnectData> connData);
void HandleNewSession(SessionWrapper session); void HandleReAddedSession(SessionWrapper session);
SOCKET Select(); SOCKET Select();
@@ -122,6 +126,7 @@ private:
mutable boost::mutex m_sessionQueueMutex; mutable boost::mutex m_sessionQueueMutex;
SessionManager m_sessionManager; SessionManager m_sessionManager;
SessionManager m_gameSessionManager;
CloseSessionList m_closeSessionList; CloseSessionList m_closeSessionList;
mutable boost::mutex m_closeSessionListMutex; mutable boost::mutex m_closeSessionListMutex;
+11 -15
View File
@@ -24,6 +24,7 @@
#include <net/socket_helper.h> #include <net/socket_helper.h>
#include <net/receivebuffer.h> #include <net/receivebuffer.h>
#include <string> #include <string>
#include <boost/thread.hpp>
#define SESSION_ID_INIT 0 #define SESSION_ID_INIT 0
@@ -35,30 +36,25 @@ public:
SessionData(SOCKET sockfd, unsigned id); SessionData(SOCKET sockfd, unsigned id);
~SessionData(); ~SessionData();
unsigned GetId() const unsigned GetId() const;
{return m_id;} State GetState() const;
State GetState() const void SetState(State state);
{return m_state;}
void SetState(State state)
{m_state = state;}
SOCKET GetSocket() const SOCKET GetSocket() const;
{return m_sockfd;}
const std::string &GetClientAddr() const const std::string &GetClientAddr() const;
{return m_clientAddr;} void SetClientAddr(const std::string &addr);
void SetClientAddr(const std::string &addr)
{m_clientAddr = addr;}
ReceiveBuffer &GetReceiveBuffer() ReceiveBuffer &GetReceiveBuffer();
{return m_receiveBuffer;}
private: private:
SOCKET m_sockfd; SOCKET m_sockfd;
unsigned m_id; const unsigned m_id;
State m_state; State m_state;
std::string m_clientAddr; std::string m_clientAddr;
ReceiveBuffer m_receiveBuffer; ReceiveBuffer m_receiveBuffer;
mutable boost::mutex m_dataMutex;
}; };
#endif #endif
+3
View File
@@ -25,6 +25,7 @@
#include <playerdata.h> #include <playerdata.h>
#include <core/thread.h> #include <core/thread.h>
#include <boost/function.hpp>
#include <map> #include <map>
#include <string> #include <string>
@@ -62,6 +63,8 @@ public:
bool IsPlayerConnected(const std::string &playerName) const; bool IsPlayerConnected(const std::string &playerName) const;
bool IsPlayerConnected(unsigned uniqueId) const; bool IsPlayerConnected(unsigned uniqueId) const;
void ForEach(boost::function<void (SessionWrapper)> func);
void Clear(); void Clear();
unsigned GetRawSessionCount(); unsigned GetRawSessionCount();
+105
View File
@@ -24,7 +24,112 @@ PlayerData::PlayerData(unsigned uniqueId, int number, PlayerType type, PlayerRig
{ {
} }
PlayerData::PlayerData(const PlayerData &other)
: m_uniqueId(other.GetUniqueId()), m_number(other.GetNumber()), m_name(other.GetName()),
m_avatarFile(other.GetAvatarFile()), m_type(other.GetType()), m_rights(other.GetRights()),
m_netSessionData(other.GetNetSessionData())
{
}
PlayerData::~PlayerData() PlayerData::~PlayerData()
{ {
} }
const std::string &
PlayerData::GetName() const
{
boost::mutex::scoped_lock lock(m_dataMutex);
return m_name;
}
void
PlayerData::SetName(const std::string &name)
{
boost::mutex::scoped_lock lock(m_dataMutex);
m_name = name;
}
const std::string &
PlayerData::GetAvatarFile() const
{
boost::mutex::scoped_lock lock(m_dataMutex);
return m_avatarFile;
}
void
PlayerData::SetAvatarFile(const std::string &avatarFile)
{
boost::mutex::scoped_lock lock(m_dataMutex);
m_avatarFile = avatarFile;
}
boost::shared_ptr<SessionData>
PlayerData::GetNetSessionData() const
{
boost::mutex::scoped_lock lock(m_dataMutex);
return m_netSessionData;
}
void
PlayerData::SetNetSessionData(boost::shared_ptr<SessionData> session)
{
boost::mutex::scoped_lock lock(m_dataMutex);
m_netSessionData = session;
}
PlayerType
PlayerData::GetType() const
{
boost::mutex::scoped_lock lock(m_dataMutex);
return m_type;
}
void
PlayerData::SetType(PlayerType type)
{
boost::mutex::scoped_lock lock(m_dataMutex);
m_type = type;
}
PlayerRights
PlayerData::GetRights() const
{
boost::mutex::scoped_lock lock(m_dataMutex);
return m_rights;
}
void
PlayerData::SetRights(PlayerRights rights)
{
boost::mutex::scoped_lock lock(m_dataMutex);
m_rights = rights;
}
unsigned
PlayerData::GetUniqueId() const
{
// const value - no mutex needed.
return m_uniqueId;
}
int
PlayerData::GetNumber() const
{
boost::mutex::scoped_lock lock(m_dataMutex);
return m_number;
}
void
PlayerData::SetNumber(int number)
{
boost::mutex::scoped_lock lock(m_dataMutex);
m_number = number;
}
bool
PlayerData::operator<(const PlayerData &other) const
{
boost::mutex::scoped_lock lock(m_dataMutex);
return m_number < other.GetNumber();
}
+19 -29
View File
@@ -26,6 +26,7 @@
#include <list> #include <list>
#include <map> #include <map>
#include <boost/shared_ptr.hpp> #include <boost/shared_ptr.hpp>
#include <boost/thread.hpp>
class SessionData; class SessionData;
@@ -54,46 +55,35 @@ class PlayerData
{ {
public: public:
PlayerData(unsigned uniqueId, int number, PlayerType type, PlayerRights rights); PlayerData(unsigned uniqueId, int number, PlayerType type, PlayerRights rights);
PlayerData(const PlayerData &other);
~PlayerData(); ~PlayerData();
const std::string &GetName() const const std::string &GetName() const;
{return m_name;} void SetName(const std::string &name);
void SetName(const std::string &name) const std::string &GetAvatarFile() const;
{m_name = name;} void SetAvatarFile(const std::string &avatarFile);
const std::string &GetAvatarFile() const boost::shared_ptr<SessionData> GetNetSessionData() const;
{return m_avatarFile;} void SetNetSessionData(boost::shared_ptr<SessionData> session);
void SetAvatarFile(const std::string &avatarFile) PlayerType GetType() const;
{m_avatarFile = avatarFile;} void SetType(PlayerType type);
boost::shared_ptr<SessionData> GetNetSessionData() PlayerRights GetRights() const;
{return m_netSessionData;} void SetRights(PlayerRights rights);
void SetNetSessionData(boost::shared_ptr<SessionData> session) unsigned GetUniqueId() const;
{m_netSessionData = session;} int GetNumber() const;
PlayerType GetType() const void SetNumber(int number);
{return m_type;}
void SetType(PlayerType type)
{m_type = type;}
PlayerRights GetRights() const
{return m_rights;}
void SetRights(PlayerRights rights)
{m_rights = rights;}
unsigned GetUniqueId() const
{return m_uniqueId;}
int GetNumber() const
{return m_number;}
void SetNumber(int number)
{m_number = number;}
bool operator<(const PlayerData &other) bool operator<(const PlayerData &other) const;
{return m_number < other.GetNumber();}
private: private:
unsigned m_uniqueId; const unsigned m_uniqueId;
int m_number; int m_number;
std::string m_name; std::string m_name;
std::string m_avatarFile; std::string m_avatarFile;
PlayerType m_type; PlayerType m_type;
PlayerRights m_rights; PlayerRights m_rights;
boost::shared_ptr<SessionData> m_netSessionData; boost::shared_ptr<SessionData> m_netSessionData;
mutable boost::mutex m_dataMutex;
}; };
typedef std::list<unsigned> PlayerIdList; typedef std::list<unsigned> PlayerIdList;