improved code for automatic joining of persistent games; disconnecting + reconnecting works as it should with ISL
This commit is contained in:
parent
5db0fcd6ae
commit
af8e357487
13 changed files with 215 additions and 135 deletions
|
@ -129,6 +129,24 @@ AuthenticationResult Server::loginUser(Server_ProtocolHandler *session, QString
|
||||||
return authState;
|
return authState;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Server::addPersistentPlayer(const QString &userName, int roomId, int gameId, int playerId)
|
||||||
|
{
|
||||||
|
QWriteLocker locker(&persistentPlayersLock);
|
||||||
|
persistentPlayers.insert(userName, PlayerReference(roomId, gameId, playerId));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Server::removePersistentPlayer(const QString &userName, int roomId, int gameId, int playerId)
|
||||||
|
{
|
||||||
|
QWriteLocker locker(&persistentPlayersLock);
|
||||||
|
persistentPlayers.remove(userName, PlayerReference(roomId, gameId, playerId));
|
||||||
|
}
|
||||||
|
|
||||||
|
QList<PlayerReference> Server::getPersistentPlayerReferences(const QString &userName) const
|
||||||
|
{
|
||||||
|
QReadLocker locker(&persistentPlayersLock);
|
||||||
|
return persistentPlayers.values(userName);
|
||||||
|
}
|
||||||
|
|
||||||
void Server::addClient(Server_ProtocolHandler *client)
|
void Server::addClient(Server_ProtocolHandler *client)
|
||||||
{
|
{
|
||||||
QWriteLocker locker(&clientsLock);
|
QWriteLocker locker(&clientsLock);
|
||||||
|
@ -181,24 +199,56 @@ void Server::externalUserJoined(const ServerInfo_User &userInfo)
|
||||||
if (clients[i]->getAcceptsUserListChanges())
|
if (clients[i]->getAcceptsUserListChanges())
|
||||||
clients[i]->sendProtocolItem(*se);
|
clients[i]->sendProtocolItem(*se);
|
||||||
delete se;
|
delete se;
|
||||||
|
clientsLock.unlock();
|
||||||
|
|
||||||
|
ResponseContainer rc(-1);
|
||||||
|
newUser->joinPersistentGames(rc);
|
||||||
|
newUser->sendResponseContainer(rc, Response::RespNothing);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Server::externalUserLeft(const QString &userName)
|
void Server::externalUserLeft(const QString &userName)
|
||||||
{
|
{
|
||||||
// This function is always called from the main thread via signal/slot.
|
// This function is always called from the main thread via signal/slot.
|
||||||
QWriteLocker locker(&clientsLock);
|
|
||||||
|
|
||||||
|
clientsLock.lockForWrite();
|
||||||
Server_AbstractUserInterface *user = externalUsers.take(userName);
|
Server_AbstractUserInterface *user = externalUsers.take(userName);
|
||||||
externalUsersBySessionId.remove(user->getUserInfo()->session_id());
|
externalUsersBySessionId.remove(user->getUserInfo()->session_id());
|
||||||
|
clientsLock.unlock();
|
||||||
|
|
||||||
|
QMap<int, QPair<int, int> > userGames(user->getGames());
|
||||||
|
QMapIterator<int, QPair<int, int> > userGamesIterator(userGames);
|
||||||
|
roomsLock.lockForRead();
|
||||||
|
while (userGamesIterator.hasNext()) {
|
||||||
|
userGamesIterator.next();
|
||||||
|
Server_Room *room = rooms.value(userGamesIterator.value().first);
|
||||||
|
if (!room)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
QMutexLocker roomGamesLocker(&room->gamesMutex);
|
||||||
|
Server_Game *game = room->getGames().value(userGamesIterator.key());
|
||||||
|
if (!game)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
QMutexLocker gameLocker(&game->gameMutex);
|
||||||
|
Server_Player *player = game->getPlayers().value(userGamesIterator.value().second);
|
||||||
|
if (!player)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
player->disconnectClient();
|
||||||
|
}
|
||||||
|
roomsLock.unlock();
|
||||||
|
|
||||||
delete user;
|
delete user;
|
||||||
|
|
||||||
Event_UserLeft event;
|
Event_UserLeft event;
|
||||||
event.set_name(userName.toStdString());
|
event.set_name(userName.toStdString());
|
||||||
|
|
||||||
SessionEvent *se = Server_ProtocolHandler::prepareSessionEvent(event);
|
SessionEvent *se = Server_ProtocolHandler::prepareSessionEvent(event);
|
||||||
|
clientsLock.lockForRead();
|
||||||
for (int i = 0; i < clients.size(); ++i)
|
for (int i = 0; i < clients.size(); ++i)
|
||||||
if (clients[i]->getAcceptsUserListChanges())
|
if (clients[i]->getAcceptsUserListChanges())
|
||||||
clients[i]->sendProtocolItem(*se);
|
clients[i]->sendProtocolItem(*se);
|
||||||
|
clientsLock.unlock();
|
||||||
delete se;
|
delete se;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,9 +4,11 @@
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QStringList>
|
#include <QStringList>
|
||||||
#include <QMap>
|
#include <QMap>
|
||||||
|
#include <QMultiMap>
|
||||||
#include <QMutex>
|
#include <QMutex>
|
||||||
#include <QReadWriteLock>
|
#include <QReadWriteLock>
|
||||||
#include "pb/serverinfo_user.pb.h"
|
#include "pb/serverinfo_user.pb.h"
|
||||||
|
#include "server_player_reference.h"
|
||||||
|
|
||||||
class Server_Game;
|
class Server_Game;
|
||||||
class Server_Room;
|
class Server_Room;
|
||||||
|
@ -77,6 +79,13 @@ public:
|
||||||
void addExternalUser(const ServerInfo_User &userInfo);
|
void addExternalUser(const ServerInfo_User &userInfo);
|
||||||
void removeExternalUser(const QString &userName);
|
void removeExternalUser(const QString &userName);
|
||||||
const QMap<QString, Server_AbstractUserInterface *> &getExternalUsers() const { return externalUsers; }
|
const QMap<QString, Server_AbstractUserInterface *> &getExternalUsers() const { return externalUsers; }
|
||||||
|
|
||||||
|
void addPersistentPlayer(const QString &userName, int roomId, int gameId, int playerId);
|
||||||
|
void removePersistentPlayer(const QString &userName, int roomId, int gameId, int playerId);
|
||||||
|
QList<PlayerReference> getPersistentPlayerReferences(const QString &userName) const;
|
||||||
|
private:
|
||||||
|
QMultiMap<QString, PlayerReference> persistentPlayers;
|
||||||
|
mutable QReadWriteLock persistentPlayersLock;
|
||||||
protected slots:
|
protected slots:
|
||||||
void externalUserJoined(const ServerInfo_User &userInfo);
|
void externalUserJoined(const ServerInfo_User &userInfo);
|
||||||
void externalUserLeft(const QString &userName);
|
void externalUserLeft(const QString &userName);
|
||||||
|
|
|
@ -1,7 +1,15 @@
|
||||||
#include <QList>
|
#include <QList>
|
||||||
#include <QPair>
|
#include <QPair>
|
||||||
|
#include <QDebug>
|
||||||
#include "server_abstractuserinterface.h"
|
#include "server_abstractuserinterface.h"
|
||||||
|
#include "server_game.h"
|
||||||
#include "server_response_containers.h"
|
#include "server_response_containers.h"
|
||||||
|
#include "server_player_reference.h"
|
||||||
|
#include "server.h"
|
||||||
|
#include "server_room.h"
|
||||||
|
#include "server_game.h"
|
||||||
|
#include "pb/event_game_joined.pb.h"
|
||||||
|
#include "pb/event_game_state_changed.pb.h"
|
||||||
#include <google/protobuf/descriptor.h>
|
#include <google/protobuf/descriptor.h>
|
||||||
|
|
||||||
void Server_AbstractUserInterface::sendProtocolItemByType(ServerMessage::MessageType type, const ::google::protobuf::Message &item)
|
void Server_AbstractUserInterface::sendProtocolItemByType(ServerMessage::MessageType type, const ::google::protobuf::Message &item)
|
||||||
|
@ -27,15 +35,61 @@ void Server_AbstractUserInterface::sendResponseContainer(const ResponseContainer
|
||||||
for (int i = 0; i < preResponseQueue.size(); ++i)
|
for (int i = 0; i < preResponseQueue.size(); ++i)
|
||||||
sendProtocolItemByType(preResponseQueue[i].first, *preResponseQueue[i].second);
|
sendProtocolItemByType(preResponseQueue[i].first, *preResponseQueue[i].second);
|
||||||
|
|
||||||
Response response;
|
if (responseCode != Response::RespNothing) {
|
||||||
response.set_cmd_id(responseContainer.getCmdId());
|
Response response;
|
||||||
response.set_response_code(responseCode);
|
response.set_cmd_id(responseContainer.getCmdId());
|
||||||
::google::protobuf::Message *responseExtension = responseContainer.getResponseExtension();
|
response.set_response_code(responseCode);
|
||||||
if (responseExtension)
|
::google::protobuf::Message *responseExtension = responseContainer.getResponseExtension();
|
||||||
response.GetReflection()->MutableMessage(&response, responseExtension->GetDescriptor()->FindExtensionByName("ext"))->CopyFrom(*responseExtension);
|
if (responseExtension)
|
||||||
sendProtocolItem(response);
|
response.GetReflection()->MutableMessage(&response, responseExtension->GetDescriptor()->FindExtensionByName("ext"))->CopyFrom(*responseExtension);
|
||||||
|
sendProtocolItem(response);
|
||||||
|
}
|
||||||
|
|
||||||
const QList<QPair<ServerMessage::MessageType, ::google::protobuf::Message *> > &postResponseQueue = responseContainer.getPostResponseQueue();
|
const QList<QPair<ServerMessage::MessageType, ::google::protobuf::Message *> > &postResponseQueue = responseContainer.getPostResponseQueue();
|
||||||
for (int i = 0; i < postResponseQueue.size(); ++i)
|
for (int i = 0; i < postResponseQueue.size(); ++i)
|
||||||
sendProtocolItemByType(postResponseQueue[i].first, *postResponseQueue[i].second);
|
sendProtocolItemByType(postResponseQueue[i].first, *postResponseQueue[i].second);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Server_AbstractUserInterface::playerRemovedFromGame(Server_Game *game)
|
||||||
|
{
|
||||||
|
qDebug() << "Server_AbstractUserInterface::playerRemovedFromGame(): gameId =" << game->getGameId();
|
||||||
|
|
||||||
|
QMutexLocker locker(&gameListMutex);
|
||||||
|
games.remove(game->getGameId());
|
||||||
|
}
|
||||||
|
|
||||||
|
void Server_AbstractUserInterface::playerAddedToGame(int gameId, int roomId, int playerId)
|
||||||
|
{
|
||||||
|
qDebug() << "Server_AbstractUserInterface::playerAddedToGame(): gameId =" << gameId;
|
||||||
|
|
||||||
|
QMutexLocker locker(&gameListMutex);
|
||||||
|
games.insert(gameId, QPair<int, int>(roomId, playerId));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Server_AbstractUserInterface::joinPersistentGames(ResponseContainer &rc)
|
||||||
|
{
|
||||||
|
QList<PlayerReference> gamesToJoin = server->getPersistentPlayerReferences(QString::fromStdString(userInfo->name()));
|
||||||
|
|
||||||
|
server->roomsLock.lockForRead();
|
||||||
|
for (int i = 0; i < gamesToJoin.size(); ++i) {
|
||||||
|
const PlayerReference &pr = gamesToJoin.at(i);
|
||||||
|
|
||||||
|
Server_Room *room = server->getRooms().value(pr.getRoomId());
|
||||||
|
if (!room)
|
||||||
|
continue;
|
||||||
|
QMutexLocker roomGamesLocker(&room->gamesMutex);
|
||||||
|
|
||||||
|
Server_Game *game = room->getGames().value(pr.getGameId());
|
||||||
|
if (!game)
|
||||||
|
continue;
|
||||||
|
QMutexLocker gameLocker(&game->gameMutex);
|
||||||
|
|
||||||
|
Server_Player *player = game->getPlayers().value(pr.getPlayerId());
|
||||||
|
|
||||||
|
player->setUserInterface(this);
|
||||||
|
playerAddedToGame(game->getGameId(), room->getId(), player->getPlayerId());
|
||||||
|
|
||||||
|
game->createGameJoinedEvent(player, rc, true);
|
||||||
|
}
|
||||||
|
server->roomsLock.unlock();
|
||||||
|
}
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
#ifndef SERVER_ABSTRACTUSERINTERFACE
|
#ifndef SERVER_ABSTRACTUSERINTERFACE
|
||||||
#define SERVER_ABSTRACTUSERINTERFACE
|
#define SERVER_ABSTRACTUSERINTERFACE
|
||||||
|
|
||||||
|
#include <QMutex>
|
||||||
|
#include <QMap>
|
||||||
|
#include <QPair>
|
||||||
#include "serverinfo_user_container.h"
|
#include "serverinfo_user_container.h"
|
||||||
#include "pb/server_message.pb.h"
|
#include "pb/server_message.pb.h"
|
||||||
#include "pb/response.pb.h"
|
#include "pb/response.pb.h"
|
||||||
|
@ -14,6 +17,9 @@ class Server;
|
||||||
class Server_Game;
|
class Server_Game;
|
||||||
|
|
||||||
class Server_AbstractUserInterface : public ServerInfo_User_Container {
|
class Server_AbstractUserInterface : public ServerInfo_User_Container {
|
||||||
|
private:
|
||||||
|
mutable QMutex gameListMutex;
|
||||||
|
QMap<int, QPair<int, int> > games; // gameId -> (roomId, playerId)
|
||||||
protected:
|
protected:
|
||||||
Server *server;
|
Server *server;
|
||||||
public:
|
public:
|
||||||
|
@ -23,8 +29,11 @@ public:
|
||||||
|
|
||||||
virtual int getLastCommandTime() const = 0;
|
virtual int getLastCommandTime() const = 0;
|
||||||
|
|
||||||
virtual void playerRemovedFromGame(Server_Game *game) = 0;
|
void playerRemovedFromGame(Server_Game *game);
|
||||||
virtual void playerAddedToGame(int gameId, int roomId, int playerId) = 0;
|
void playerAddedToGame(int gameId, int roomId, int playerId);
|
||||||
|
void joinPersistentGames(ResponseContainer &rc);
|
||||||
|
|
||||||
|
QMap<int, QPair<int, int> > getGames() const { QMutexLocker locker(&gameListMutex); return games; }
|
||||||
|
|
||||||
virtual void sendProtocolItem(const Response &item) = 0;
|
virtual void sendProtocolItem(const Response &item) = 0;
|
||||||
virtual void sendProtocolItem(const SessionEvent &item) = 0;
|
virtual void sendProtocolItem(const SessionEvent &item) = 0;
|
||||||
|
|
|
@ -48,6 +48,7 @@
|
||||||
Server_Game::Server_Game(const ServerInfo_User &_creatorInfo, int _gameId, const QString &_description, const QString &_password, int _maxPlayers, const QList<int> &_gameTypes, bool _onlyBuddies, bool _onlyRegistered, bool _spectatorsAllowed, bool _spectatorsNeedPassword, bool _spectatorsCanTalk, bool _spectatorsSeeEverything, Server_Room *_room)
|
Server_Game::Server_Game(const ServerInfo_User &_creatorInfo, int _gameId, const QString &_description, const QString &_password, int _maxPlayers, const QList<int> &_gameTypes, bool _onlyBuddies, bool _onlyRegistered, bool _spectatorsAllowed, bool _spectatorsNeedPassword, bool _spectatorsCanTalk, bool _spectatorsSeeEverything, Server_Room *_room)
|
||||||
: QObject(),
|
: QObject(),
|
||||||
room(_room),
|
room(_room),
|
||||||
|
nextPlayerId(0),
|
||||||
hostId(0),
|
hostId(0),
|
||||||
creatorInfo(new ServerInfo_User(_creatorInfo)),
|
creatorInfo(new ServerInfo_User(_creatorInfo)),
|
||||||
gameStarted(false),
|
gameStarted(false),
|
||||||
|
@ -371,58 +372,38 @@ void Server_Game::addPlayer(Server_AbstractUserInterface *userInterface, Respons
|
||||||
{
|
{
|
||||||
QMutexLocker locker(&gameMutex);
|
QMutexLocker locker(&gameMutex);
|
||||||
|
|
||||||
const QList<int> &keyList = players.keys();
|
Server_Player *newPlayer = new Server_Player(this, nextPlayerId++, userInterface->copyUserInfo(true), spectator, userInterface);
|
||||||
int playerId = keyList.isEmpty() ? 0 : (keyList.last() + 1);
|
|
||||||
|
|
||||||
Server_Player *newPlayer = new Server_Player(this, playerId, userInterface->copyUserInfo(true), spectator, userInterface);
|
|
||||||
newPlayer->moveToThread(thread());
|
newPlayer->moveToThread(thread());
|
||||||
|
|
||||||
Event_Join joinEvent;
|
Event_Join joinEvent;
|
||||||
joinEvent.mutable_player_properties()->CopyFrom(newPlayer->getProperties(true));
|
joinEvent.mutable_player_properties()->CopyFrom(newPlayer->getProperties(true));
|
||||||
sendGameEventContainer(prepareGameEvent(joinEvent, -1));
|
sendGameEventContainer(prepareGameEvent(joinEvent, -1));
|
||||||
|
|
||||||
|
const QString playerName = QString::fromStdString(newPlayer->getUserInfo()->name());
|
||||||
if (spectator)
|
if (spectator)
|
||||||
allSpectatorsEver.insert(QString::fromStdString(newPlayer->getUserInfo()->name()));
|
allSpectatorsEver.insert(playerName);
|
||||||
else
|
else
|
||||||
allPlayersEver.insert(QString::fromStdString(newPlayer->getUserInfo()->name()));
|
allPlayersEver.insert(playerName);
|
||||||
players.insert(playerId, newPlayer);
|
players.insert(newPlayer->getPlayerId(), newPlayer);
|
||||||
if (newPlayer->getUserInfo()->name() == creatorInfo->name()) {
|
if (newPlayer->getUserInfo()->name() == creatorInfo->name()) {
|
||||||
hostId = playerId;
|
hostId = newPlayer->getPlayerId();
|
||||||
sendGameEventContainer(prepareGameEvent(Event_GameHostChanged(), playerId));
|
sendGameEventContainer(prepareGameEvent(Event_GameHostChanged(), hostId));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (broadcastUpdate)
|
if (broadcastUpdate)
|
||||||
emit gameInfoChanged(getInfo());
|
emit gameInfoChanged(getInfo());
|
||||||
|
|
||||||
|
if ((newPlayer->getUserInfo()->user_level() & ServerInfo_User::IsRegistered) && !spectator)
|
||||||
|
room->getServer()->addPersistentPlayer(playerName, room->getId(), gameId, newPlayer->getPlayerId());
|
||||||
|
|
||||||
userInterface->playerAddedToGame(gameId, room->getId(), newPlayer->getPlayerId());
|
userInterface->playerAddedToGame(gameId, room->getId(), newPlayer->getPlayerId());
|
||||||
|
|
||||||
Event_GameJoined event1;
|
createGameJoinedEvent(newPlayer, rc, false);
|
||||||
event1.set_room_id(room->getId());
|
|
||||||
event1.set_game_id(gameId);
|
|
||||||
event1.set_game_description(description.toStdString());
|
|
||||||
event1.set_host_id(hostId);
|
|
||||||
event1.set_player_id(newPlayer->getPlayerId());
|
|
||||||
event1.set_spectator(newPlayer->getSpectator());
|
|
||||||
event1.set_spectators_can_talk(spectatorsCanTalk);
|
|
||||||
event1.set_spectators_see_everything(spectatorsSeeEverything);
|
|
||||||
event1.set_resuming(false);
|
|
||||||
rc.enqueuePostResponseItem(ServerMessage::SESSION_EVENT, Server_AbstractUserInterface::prepareSessionEvent(event1));
|
|
||||||
|
|
||||||
Event_GameStateChanged event2;
|
|
||||||
QListIterator<ServerInfo_Player> gameStateIterator(getGameState(newPlayer, false, true));
|
|
||||||
while (gameStateIterator.hasNext())
|
|
||||||
event2.add_player_list()->CopyFrom(gameStateIterator.next());
|
|
||||||
event2.set_seconds_elapsed(secondsElapsed);
|
|
||||||
event2.set_game_started(gameStarted);
|
|
||||||
event2.set_active_player_id(activePlayer);
|
|
||||||
event2.set_active_phase(activePhase);
|
|
||||||
rc.enqueuePostResponseItem(ServerMessage::GAME_EVENT_CONTAINER, prepareGameEvent(event2, -1));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Server_Game::removePlayer(Server_Player *player)
|
void Server_Game::removePlayer(Server_Player *player)
|
||||||
{
|
{
|
||||||
QMutexLocker locker(&gameMutex);
|
room->getServer()->removePersistentPlayer(QString::fromStdString(player->getUserInfo()->name()), room->getId(), gameId, player->getPlayerId());
|
||||||
|
|
||||||
players.remove(player->getPlayerId());
|
players.remove(player->getPlayerId());
|
||||||
|
|
||||||
GameEventStorage ges;
|
GameEventStorage ges;
|
||||||
|
@ -688,6 +669,31 @@ QList<ServerInfo_Player> Server_Game::getGameState(Server_Player *playerWhosAski
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Server_Game::createGameJoinedEvent(Server_Player *player, ResponseContainer &rc, bool resuming)
|
||||||
|
{
|
||||||
|
Event_GameJoined event1;
|
||||||
|
event1.set_room_id(room->getId());
|
||||||
|
event1.set_game_id(gameId);
|
||||||
|
event1.set_game_description(description.toStdString());
|
||||||
|
event1.set_host_id(hostId);
|
||||||
|
event1.set_player_id(player->getPlayerId());
|
||||||
|
event1.set_spectator(player->getSpectator());
|
||||||
|
event1.set_spectators_can_talk(spectatorsCanTalk);
|
||||||
|
event1.set_spectators_see_everything(spectatorsSeeEverything);
|
||||||
|
event1.set_resuming(resuming);
|
||||||
|
rc.enqueuePostResponseItem(ServerMessage::SESSION_EVENT, Server_AbstractUserInterface::prepareSessionEvent(event1));
|
||||||
|
|
||||||
|
Event_GameStateChanged event2;
|
||||||
|
QListIterator<ServerInfo_Player> gameStateIterator(getGameState(player, player->getSpectator() && spectatorsSeeEverything, true));
|
||||||
|
while (gameStateIterator.hasNext())
|
||||||
|
event2.add_player_list()->CopyFrom(gameStateIterator.next());
|
||||||
|
event2.set_seconds_elapsed(secondsElapsed);
|
||||||
|
event2.set_game_started(gameStarted);
|
||||||
|
event2.set_active_player_id(activePlayer);
|
||||||
|
event2.set_active_phase(activePhase);
|
||||||
|
rc.enqueuePostResponseItem(ServerMessage::GAME_EVENT_CONTAINER, prepareGameEvent(event2, -1));
|
||||||
|
}
|
||||||
|
|
||||||
void Server_Game::sendGameEventContainer(GameEventContainer *cont, GameEventStorageItem::EventRecipients recipients, int privatePlayerId)
|
void Server_Game::sendGameEventContainer(GameEventContainer *cont, GameEventStorageItem::EventRecipients recipients, int privatePlayerId)
|
||||||
{
|
{
|
||||||
QMutexLocker locker(&gameMutex);
|
QMutexLocker locker(&gameMutex);
|
||||||
|
|
|
@ -42,6 +42,7 @@ class Server_Game : public QObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
private:
|
private:
|
||||||
Server_Room *room;
|
Server_Room *room;
|
||||||
|
int nextPlayerId;
|
||||||
int hostId;
|
int hostId;
|
||||||
ServerInfo_User *creatorInfo;
|
ServerInfo_User *creatorInfo;
|
||||||
QMap<int, Server_Player *> players;
|
QMap<int, Server_Player *> players;
|
||||||
|
@ -108,6 +109,7 @@ public:
|
||||||
void nextTurn();
|
void nextTurn();
|
||||||
int getSecondsElapsed() const { return secondsElapsed; }
|
int getSecondsElapsed() const { return secondsElapsed; }
|
||||||
|
|
||||||
|
void createGameJoinedEvent(Server_Player *player, ResponseContainer &rc, bool resuming);
|
||||||
void sendGameStateToPlayers();
|
void sendGameStateToPlayers();
|
||||||
QList<ServerInfo_Player> getGameState(Server_Player *playerWhosAsking, bool omniscient = false, bool withUserInfo = false) const;
|
QList<ServerInfo_Player> getGameState(Server_Player *playerWhosAsking, bool omniscient = false, bool withUserInfo = false) const;
|
||||||
|
|
||||||
|
|
|
@ -1578,3 +1578,11 @@ void Server_Player::setUserInterface(Server_AbstractUserInterface *_userInterfac
|
||||||
ges.enqueueGameEvent(event, playerId);
|
ges.enqueueGameEvent(event, playerId);
|
||||||
ges.sendToGame(game);
|
ges.sendToGame(game);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Server_Player::disconnectClient()
|
||||||
|
{
|
||||||
|
if (!(userInfo->user_level() & ServerInfo_User::IsRegistered) || spectator)
|
||||||
|
game->removePlayer(this);
|
||||||
|
else
|
||||||
|
setUserInterface(0);
|
||||||
|
}
|
||||||
|
|
|
@ -83,6 +83,7 @@ public:
|
||||||
void prepareDestroy();
|
void prepareDestroy();
|
||||||
Server_AbstractUserInterface *getUserInterface() const { return userInterface; }
|
Server_AbstractUserInterface *getUserInterface() const { return userInterface; }
|
||||||
void setUserInterface(Server_AbstractUserInterface *_userInterface);
|
void setUserInterface(Server_AbstractUserInterface *_userInterface);
|
||||||
|
void disconnectClient();
|
||||||
|
|
||||||
void setPlayerId(int _id) { playerId = _id; }
|
void setPlayerId(int _id) { playerId = _id; }
|
||||||
bool getReadyStart() const { return readyStart; }
|
bool getReadyStart() const { return readyStart; }
|
||||||
|
|
17
common/server_player_reference.h
Normal file
17
common/server_player_reference.h
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
#ifndef SERVER_PLAYER_REFERENCE_H
|
||||||
|
#define SERVER_PLAYER_REFERENCE_H
|
||||||
|
|
||||||
|
class PlayerReference {
|
||||||
|
private:
|
||||||
|
int roomId;
|
||||||
|
int gameId;
|
||||||
|
int playerId;
|
||||||
|
public:
|
||||||
|
PlayerReference(int _roomId, int _gameId, int _playerId) : roomId(_roomId), gameId(_gameId), playerId(_playerId) { }
|
||||||
|
int getRoomId() const { return roomId; }
|
||||||
|
int getGameId() const { return gameId; }
|
||||||
|
int getPlayerId() const { return playerId; }
|
||||||
|
bool operator==(const PlayerReference &other) { return ((roomId == other.roomId) && (gameId == other.gameId) && (playerId == other.playerId)); }
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
|
@ -49,15 +49,11 @@ void Server_ProtocolHandler::prepareDestroy()
|
||||||
{
|
{
|
||||||
qDebug("Server_ProtocolHandler::prepareDestroy");
|
qDebug("Server_ProtocolHandler::prepareDestroy");
|
||||||
|
|
||||||
server->removeClient(this);
|
|
||||||
|
|
||||||
QMapIterator<int, Server_Room *> roomIterator(rooms);
|
QMapIterator<int, Server_Room *> roomIterator(rooms);
|
||||||
while (roomIterator.hasNext())
|
while (roomIterator.hasNext())
|
||||||
roomIterator.next().value()->removeClient(this);
|
roomIterator.next().value()->removeClient(this);
|
||||||
|
|
||||||
gameListMutex.lock();
|
QMap<int, QPair<int, int> > tempGames(getGames());
|
||||||
QMap<int, QPair<int, int> > tempGames(games);
|
|
||||||
gameListMutex.unlock();
|
|
||||||
|
|
||||||
server->roomsLock.lockForRead();
|
server->roomsLock.lockForRead();
|
||||||
QMapIterator<int, QPair<int, int> > gameIterator(tempGames);
|
QMapIterator<int, QPair<int, int> > gameIterator(tempGames);
|
||||||
|
@ -81,35 +77,18 @@ void Server_ProtocolHandler::prepareDestroy()
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((authState == UnknownUser) || p->getSpectator())
|
p->disconnectClient();
|
||||||
g->removePlayer(p);
|
|
||||||
else
|
|
||||||
p->setUserInterface(0);
|
|
||||||
|
|
||||||
g->gameMutex.unlock();
|
g->gameMutex.unlock();
|
||||||
r->gamesMutex.unlock();
|
r->gamesMutex.unlock();
|
||||||
}
|
}
|
||||||
server->roomsLock.unlock();
|
server->roomsLock.unlock();
|
||||||
|
|
||||||
|
server->removeClient(this);
|
||||||
|
|
||||||
deleteLater();
|
deleteLater();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Server_ProtocolHandler::playerRemovedFromGame(Server_Game *game)
|
|
||||||
{
|
|
||||||
qDebug() << "Server_ProtocolHandler::playerRemovedFromGame(): gameId =" << game->getGameId();
|
|
||||||
|
|
||||||
QMutexLocker locker(&gameListMutex);
|
|
||||||
games.remove(game->getGameId());
|
|
||||||
}
|
|
||||||
|
|
||||||
void Server_ProtocolHandler::playerAddedToGame(int gameId, int roomId, int playerId)
|
|
||||||
{
|
|
||||||
qDebug() << "Server_ProtocolHandler::playerAddedToGame(): gameId =" << gameId;
|
|
||||||
|
|
||||||
QMutexLocker locker(&gameListMutex);
|
|
||||||
games.insert(gameId, QPair<int, int>(roomId, playerId));
|
|
||||||
}
|
|
||||||
|
|
||||||
void Server_ProtocolHandler::sendProtocolItem(const Response &item)
|
void Server_ProtocolHandler::sendProtocolItem(const Response &item)
|
||||||
{
|
{
|
||||||
ServerMessage msg;
|
ServerMessage msg;
|
||||||
|
@ -217,13 +196,10 @@ Response::ResponseCode Server_ProtocolHandler::processGameCommandContainer(const
|
||||||
|
|
||||||
qDebug() << QString::fromStdString(cont.DebugString());
|
qDebug() << QString::fromStdString(cont.DebugString());
|
||||||
|
|
||||||
gameListMutex.lock();
|
QMap<int, QPair<int, int> > gameMap = getGames();
|
||||||
if (!games.contains(cont.game_id())) {
|
if (!gameMap.contains(cont.game_id()))
|
||||||
gameListMutex.unlock();
|
|
||||||
return Response::RespNotInRoom;
|
return Response::RespNotInRoom;
|
||||||
}
|
const QPair<int, int> roomIdAndPlayerId = gameMap.value(cont.game_id());
|
||||||
const QPair<int, int> roomIdAndPlayerId = games.value(cont.game_id());
|
|
||||||
gameListMutex.unlock();
|
|
||||||
|
|
||||||
QReadLocker roomsLocker(&server->roomsLock);
|
QReadLocker roomsLocker(&server->roomsLock);
|
||||||
Server_Room *room = server->getRooms().value(roomIdAndPlayerId.first);
|
Server_Room *room = server->getRooms().value(roomIdAndPlayerId.first);
|
||||||
|
@ -394,53 +370,7 @@ Response::ResponseCode Server_ProtocolHandler::cmdLogin(const Command_Login &cmd
|
||||||
re->add_ignore_list()->CopyFrom(ignoreIterator.next().value());
|
re->add_ignore_list()->CopyFrom(ignoreIterator.next().value());
|
||||||
}
|
}
|
||||||
|
|
||||||
server->roomsLock.lockForRead();
|
joinPersistentGames(rc);
|
||||||
|
|
||||||
QMapIterator<int, Server_Room *> roomIterator(server->getRooms());
|
|
||||||
while (roomIterator.hasNext()) {
|
|
||||||
Server_Room *room = roomIterator.next().value();
|
|
||||||
room->gamesMutex.lock();
|
|
||||||
QMapIterator<int, Server_Game *> gameIterator(room->getGames());
|
|
||||||
while (gameIterator.hasNext()) {
|
|
||||||
Server_Game *game = gameIterator.next().value();
|
|
||||||
QMutexLocker gameLocker(&game->gameMutex);
|
|
||||||
const QList<Server_Player *> &gamePlayers = game->getPlayers().values();
|
|
||||||
for (int j = 0; j < gamePlayers.size(); ++j)
|
|
||||||
if (gamePlayers[j]->getUserInfo()->name() == userInfo->name()) {
|
|
||||||
gamePlayers[j]->setUserInterface(this);
|
|
||||||
|
|
||||||
gameListMutex.lock();
|
|
||||||
games.insert(game->getGameId(), QPair<int, int>(room->getId(), gamePlayers[j]->getPlayerId()));
|
|
||||||
gameListMutex.unlock();
|
|
||||||
|
|
||||||
Event_GameJoined event1;
|
|
||||||
event1.set_room_id(room->getId());
|
|
||||||
event1.set_game_id(game->getGameId());
|
|
||||||
event1.set_game_description(game->getDescription().toStdString());
|
|
||||||
event1.set_host_id(game->getHostId());
|
|
||||||
event1.set_player_id(gamePlayers[j]->getPlayerId());
|
|
||||||
event1.set_spectator(gamePlayers[j]->getSpectator());
|
|
||||||
event1.set_spectators_can_talk(game->getSpectatorsCanTalk());
|
|
||||||
event1.set_spectators_see_everything(game->getSpectatorsSeeEverything());
|
|
||||||
event1.set_resuming(true);
|
|
||||||
rc.enqueuePostResponseItem(ServerMessage::SESSION_EVENT, prepareSessionEvent(event1));
|
|
||||||
|
|
||||||
Event_GameStateChanged event2;
|
|
||||||
QListIterator<ServerInfo_Player> gameStateIterator(game->getGameState(gamePlayers[j], gamePlayers[j]->getSpectator() && game->getSpectatorsSeeEverything(), true));
|
|
||||||
while (gameStateIterator.hasNext())
|
|
||||||
event2.add_player_list()->CopyFrom(gameStateIterator.next());
|
|
||||||
event2.set_seconds_elapsed(game->getSecondsElapsed());
|
|
||||||
event2.set_game_started(game->getGameStarted());
|
|
||||||
event2.set_active_player_id(game->getActivePlayer());
|
|
||||||
event2.set_active_phase(game->getActivePhase());
|
|
||||||
rc.enqueuePostResponseItem(ServerMessage::GAME_EVENT_CONTAINER, game->prepareGameEvent(event2, -1));
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
room->gamesMutex.unlock();
|
|
||||||
}
|
|
||||||
server->roomsLock.unlock();
|
|
||||||
|
|
||||||
rc.setResponseExtension(re);
|
rc.setResponseExtension(re);
|
||||||
return Response::RespOk;
|
return Response::RespOk;
|
||||||
|
|
|
@ -57,14 +57,12 @@ class Command_ShutdownServer;
|
||||||
class Server_ProtocolHandler : public QObject, public Server_AbstractUserInterface {
|
class Server_ProtocolHandler : public QObject, public Server_AbstractUserInterface {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
protected:
|
protected:
|
||||||
QMap<int, QPair<int, int> > games; // gameId -> (roomId, playerId)
|
|
||||||
QMap<int, Server_Room *> rooms;
|
QMap<int, Server_Room *> rooms;
|
||||||
|
|
||||||
AuthenticationResult authState;
|
AuthenticationResult authState;
|
||||||
bool acceptsUserListChanges;
|
bool acceptsUserListChanges;
|
||||||
bool acceptsRoomListChanges;
|
bool acceptsRoomListChanges;
|
||||||
private:
|
private:
|
||||||
QMutex gameListMutex;
|
|
||||||
|
|
||||||
QList<int> messageSizeOverTime, messageCountOverTime;
|
QList<int> messageSizeOverTime, messageCountOverTime;
|
||||||
int timeRunning, lastDataReceived;
|
int timeRunning, lastDataReceived;
|
||||||
|
@ -113,8 +111,6 @@ public slots:
|
||||||
public:
|
public:
|
||||||
Server_ProtocolHandler(Server *_server, QObject *parent = 0);
|
Server_ProtocolHandler(Server *_server, QObject *parent = 0);
|
||||||
~Server_ProtocolHandler();
|
~Server_ProtocolHandler();
|
||||||
void playerRemovedFromGame(Server_Game *game);
|
|
||||||
void playerAddedToGame(int gameId, int roomId, int playerId);
|
|
||||||
|
|
||||||
bool getAcceptsUserListChanges() const { return acceptsUserListChanges; }
|
bool getAcceptsUserListChanges() const { return acceptsUserListChanges; }
|
||||||
bool getAcceptsRoomListChanges() const { return acceptsRoomListChanges; }
|
bool getAcceptsRoomListChanges() const { return acceptsRoomListChanges; }
|
||||||
|
|
|
@ -9,9 +9,6 @@ public:
|
||||||
|
|
||||||
int getLastCommandTime() const { return 0; }
|
int getLastCommandTime() const { return 0; }
|
||||||
|
|
||||||
void playerRemovedFromGame(Server_Game * /*game*/) { }
|
|
||||||
void playerAddedToGame(int /*gameId*/, int /*roomId*/, int /*playerId*/) { }
|
|
||||||
|
|
||||||
void sendProtocolItem(const Response &item);
|
void sendProtocolItem(const Response &item);
|
||||||
void sendProtocolItem(const SessionEvent &item);
|
void sendProtocolItem(const SessionEvent &item);
|
||||||
void sendProtocolItem(const GameEventContainer &item);
|
void sendProtocolItem(const GameEventContainer &item);
|
||||||
|
|
|
@ -49,14 +49,6 @@ IslInterface::~IslInterface()
|
||||||
|
|
||||||
// As these signals are connected with Qt::QueuedConnection implicitly,
|
// As these signals are connected with Qt::QueuedConnection implicitly,
|
||||||
// we don't need to worry about them modifying the lists while we're iterating.
|
// we don't need to worry about them modifying the lists while we're iterating.
|
||||||
server->clientsLock.lockForRead();
|
|
||||||
QMapIterator<QString, Server_AbstractUserInterface *> extUsers(server->getExternalUsers());
|
|
||||||
while (extUsers.hasNext()) {
|
|
||||||
extUsers.next();
|
|
||||||
if (extUsers.value()->getUserInfo()->server_id() == serverId)
|
|
||||||
emit externalUserLeft(extUsers.key());
|
|
||||||
}
|
|
||||||
server->clientsLock.unlock();
|
|
||||||
|
|
||||||
server->roomsLock.lockForRead();
|
server->roomsLock.lockForRead();
|
||||||
QMapIterator<int, Server_Room *> roomIterator(server->getRooms());
|
QMapIterator<int, Server_Room *> roomIterator(server->getRooms());
|
||||||
|
@ -72,6 +64,15 @@ IslInterface::~IslInterface()
|
||||||
room->usersLock.unlock();
|
room->usersLock.unlock();
|
||||||
}
|
}
|
||||||
server->roomsLock.unlock();
|
server->roomsLock.unlock();
|
||||||
|
|
||||||
|
server->clientsLock.lockForRead();
|
||||||
|
QMapIterator<QString, Server_AbstractUserInterface *> extUsers(server->getExternalUsers());
|
||||||
|
while (extUsers.hasNext()) {
|
||||||
|
extUsers.next();
|
||||||
|
if (extUsers.value()->getUserInfo()->server_id() == serverId)
|
||||||
|
emit externalUserLeft(extUsers.key());
|
||||||
|
}
|
||||||
|
server->clientsLock.unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
void IslInterface::initServer()
|
void IslInterface::initServer()
|
||||||
|
|
Loading…
Reference in a new issue