From cdfe0e030126fd2342ff5e697424c48ec32bf6b3 Mon Sep 17 00:00:00 2001 From: Max-Wilhelm Bruker Date: Mon, 14 Sep 2009 18:43:47 +0200 Subject: [PATCH] initial commit of spectator code --- servatrice/src/returnmessage.cpp | 1 + servatrice/src/returnmessage.h | 2 +- servatrice/src/server.cpp | 27 ++------- servatrice/src/server.h | 4 +- servatrice/src/servergame.cpp | 62 +++++++++++++------ servatrice/src/servergame.h | 9 ++- servatrice/src/serversocket.cpp | 100 ++++++++++++++++++------------- servatrice/src/serversocket.h | 6 +- 8 files changed, 121 insertions(+), 90 deletions(-) diff --git a/servatrice/src/returnmessage.cpp b/servatrice/src/returnmessage.cpp index 14d1eca3..d8825ac9 100644 --- a/servatrice/src/returnmessage.cpp +++ b/servatrice/src/returnmessage.cpp @@ -15,6 +15,7 @@ bool ReturnMessage::send(ReturnCode code) case ReturnSyntaxError: returnCodeString = "syntax"; break; case ReturnContextError: returnCodeString = "context"; break; case ReturnPasswordWrong: returnCodeString = "password"; break; + case ReturnSpectatorsNotAllowed: returnCodeString = "spectators_not_allowed"; break; } s->msg(QString("resp|%1|%2").arg(msg_id) .arg(returnCodeString)); diff --git a/servatrice/src/returnmessage.h b/servatrice/src/returnmessage.h index 58a464a1..2cfd9a30 100644 --- a/servatrice/src/returnmessage.h +++ b/servatrice/src/returnmessage.h @@ -9,7 +9,7 @@ private: unsigned int msg_id; QString cmd; public: - enum ReturnCode { ReturnNothing, ReturnOk, ReturnNameNotFound, ReturnLoginNeeded, ReturnSyntaxError, ReturnContextError, ReturnPasswordWrong }; + enum ReturnCode { ReturnNothing, ReturnOk, ReturnNameNotFound, ReturnLoginNeeded, ReturnSyntaxError, ReturnContextError, ReturnPasswordWrong, ReturnSpectatorsNotAllowed }; ReturnMessage(QObject *parent = 0) : QObject(parent), msg_id(0) { } unsigned int getMsgId() const { return msg_id; } void setMsgId(unsigned int _msg_id) { msg_id = _msg_id; } diff --git a/servatrice/src/server.cpp b/servatrice/src/server.cpp index 990503cd..3459848d 100644 --- a/servatrice/src/server.cpp +++ b/servatrice/src/server.cpp @@ -85,12 +85,12 @@ bool Server::openDatabase() return true; } -void Server::addGame(const QString description, const QString password, const int maxPlayers, ServerSocket *creator) +void Server::addGame(const QString description, const QString password, int maxPlayers, bool spectatorsAllowed, ServerSocket *creator) { - ServerGame *newGame = new ServerGame(creator, nextGameId++, description, password, maxPlayers, this); + ServerGame *newGame = new ServerGame(creator, nextGameId++, description, password, maxPlayers, spectatorsAllowed, this); games << newGame; connect(newGame, SIGNAL(gameClosing()), this, SLOT(gameClosing())); - newGame->addPlayer(creator); + newGame->addPlayer(creator, false); broadcastGameListUpdate(newGame); } @@ -99,8 +99,8 @@ void Server::incomingConnection(int socketId) { ServerSocket *socket = new ServerSocket(this); socket->setSocketDescriptor(socketId); - connect(socket, SIGNAL(createGame(const QString, const QString, const int, ServerSocket *)), this, SLOT(addGame(const QString, const QString, const int, ServerSocket *))); - connect(socket, SIGNAL(joinGame(int, ServerSocket *)), this, SLOT(addClientToGame(int, ServerSocket *))); + connect(socket, SIGNAL(createGame(const QString, const QString, int, bool, ServerSocket *)), this, SLOT(addGame(const QString, const QString, int, bool, ServerSocket *))); + connect(socket, SIGNAL(joinGame(int, bool, ServerSocket *)), this, SLOT(addClientToGame(int, bool, ServerSocket *))); socket->initConnection(); players << socket; } @@ -156,16 +156,6 @@ QList Server::listOpenGames() return result; } -bool Server::checkGamePassword(int gameId, const QString &password) -{ - ServerGame *tmp; - if ((tmp = getGame(gameId))) { - if ((!tmp->getGameStarted()) && (tmp->getPassword() == password) && (tmp->getPlayerCount() < tmp->getMaxPlayers())) - return true; - } - return false; -} - void Server::broadcastGameListUpdate(ServerGame *game) { qDebug(QString("broadcastGameListUpdate() to %1 players").arg(players.size()).toLatin1()); @@ -183,13 +173,6 @@ void Server::broadcastChannelUpdate() players[i]->msg(line); } -void Server::addClientToGame(int gameId, ServerSocket *client) -{ - ServerGame *game = getGame(gameId); - game->addPlayer(client); - broadcastGameListUpdate(game); -} - void Server::gameClosing() { qDebug("Server::gameClosing"); diff --git a/servatrice/src/server.h b/servatrice/src/server.h index bccdb292..03225bb9 100644 --- a/servatrice/src/server.h +++ b/servatrice/src/server.h @@ -36,8 +36,7 @@ class Server : public QTcpServer { Q_OBJECT private slots: - void addGame(const QString description, const QString password, const int maxPlayers, ServerSocket *creator); - void addClientToGame(int gameId, ServerSocket *client); + void addGame(const QString description, const QString password, int maxPlayers, bool spectatorsAllowed, ServerSocket *creator); void gameClosing(); void broadcastChannelUpdate(); public: @@ -45,7 +44,6 @@ public: ~Server(); QSettings *settings; bool openDatabase(); - bool checkGamePassword(int gameId, const QString &password); AuthenticationResult checkUserPassword(const QString &user, const QString &password); QList listOpenGames(); QList getChatChannelList() { return chatChannelList; } diff --git a/servatrice/src/servergame.cpp b/servatrice/src/servergame.cpp index b57d8c32..bfb3f7b3 100644 --- a/servatrice/src/servergame.cpp +++ b/servatrice/src/servergame.cpp @@ -22,8 +22,8 @@ #include "serversocket.h" #include -ServerGame::ServerGame(ServerSocket *_creator, int _gameId, const QString &_description, const QString &_password, int _maxPlayers, QObject *parent) - : QObject(parent), creator(_creator), gameStarted(false), gameId(_gameId), description(_description), password(_password), maxPlayers(_maxPlayers) +ServerGame::ServerGame(ServerSocket *_creator, int _gameId, const QString &_description, const QString &_password, int _maxPlayers, bool _spectatorsAllowed, QObject *parent) + : QObject(parent), creator(_creator), gameStarted(false), gameId(_gameId), description(_description), password(_password), maxPlayers(_maxPlayers), spectatorsAllowed(_spectatorsAllowed) { } @@ -36,14 +36,16 @@ ServerGame::~ServerGame() QString ServerGame::getGameListLine() const { if (players.isEmpty()) - return QString("list_games|%1|||0|%2|").arg(gameId).arg(maxPlayers); + return QString("list_games|%1|||0|%2||0").arg(gameId).arg(maxPlayers); else - return QString("list_games|%1|%2|%3|%4|%5|%6").arg(gameId) + return QString("list_games|%1|%2|%3|%4|%5|%6|%7|%8").arg(gameId) .arg(description) .arg(password.isEmpty() ? 0 : 1) .arg(players.size()) .arg(maxPlayers) - .arg(creator->getPlayerName()); + .arg(creator->getPlayerName()) + .arg(spectatorsAllowed ? 0 : 1) + .arg(spectators.size()); } QStringList ServerGame::getPlayerNames() const @@ -113,29 +115,53 @@ void ServerGame::startGameIfReady() setActivePlayer(0); } -void ServerGame::addPlayer(ServerSocket *player) +ReturnMessage::ReturnCode ServerGame::checkJoin(const QString &_password, bool spectator) { - int max = -1; - QListIterator i(players); - while (i.hasNext()) { - int tmp = i.next()->getPlayerId(); - if (tmp > max) - max = tmp; - } - player->setPlayerId(max + 1); + if (_password != password) + return ReturnMessage::ReturnPasswordWrong; + if (spectator) { + if (!spectatorsAllowed) + return ReturnMessage::ReturnSpectatorsNotAllowed; + } else if (gameStarted || (getPlayerCount() >= getMaxPlayers())) + return ReturnMessage::ReturnContextError; + + return ReturnMessage::ReturnOk; +} + +void ServerGame::addPlayer(ServerSocket *player, bool spectator) +{ + if (!spectator) { + int max = -1; + QListIterator i(players); + while (i.hasNext()) { + int tmp = i.next()->getPlayerId(); + if (tmp > max) + max = tmp; + } + player->setPlayerId(max + 1); + player->msg(QString("private|||player_id|%1|%2").arg(max + 1).arg(player->getPlayerName())); + } else + player->setPlayerId(-1); player->setGame(this); - player->msg(QString("private|||player_id|%1|%2").arg(max + 1).arg(player->getPlayerName())); - broadcastEvent("join", player); + broadcastEvent(QString("join|%1").arg(spectator ? 1 : 0), player); - players << player; + if (spectator) + spectators << player; + else + players << player; connect(player, SIGNAL(broadcastEvent(const QString &, ServerSocket *)), this, SLOT(broadcastEvent(const QString &, ServerSocket *))); + + qobject_cast(parent())->broadcastGameListUpdate(this); } void ServerGame::removePlayer(ServerSocket *player) { - players.removeAt(players.indexOf(player)); + if (player->getSpectator()) + spectators.removeAt(spectators.indexOf(player)); + else + players.removeAt(players.indexOf(player)); broadcastEvent("leave", player); if (!players.size()) deleteLater(); diff --git a/servatrice/src/servergame.h b/servatrice/src/servergame.h index 675239c6..21c13c3c 100644 --- a/servatrice/src/servergame.h +++ b/servatrice/src/servergame.h @@ -21,6 +21,7 @@ #define SERVERGAME_H #include +#include "returnmessage.h" class ServerSocket; @@ -29,18 +30,20 @@ class ServerGame : public QObject { private: ServerSocket *creator; QList players; + QList spectators; bool gameStarted; int gameId; QString description; QString password; int maxPlayers; int activePlayer, activePhase; + bool spectatorsAllowed; signals: void gameClosing(); public slots: void broadcastEvent(const QString &event, ServerSocket *player); public: - ServerGame(ServerSocket *_creator, int _gameId, const QString &_description, const QString &_password, int _maxPlayers, QObject *parent = 0); + ServerGame(ServerSocket *_creator, int _gameId, const QString &_description, const QString &_password, int _maxPlayers, bool _spectatorsAllowed, QObject *parent = 0); ~ServerGame(); ServerSocket *getCreator() const { return creator; } bool getGameStarted() const { return gameStarted; } @@ -49,10 +52,12 @@ public: QString getDescription() const { return description; } QString getPassword() const { return password; } int getMaxPlayers() const { return maxPlayers; } + bool getSpectatorsAllowed() const { return spectatorsAllowed; } QString getGameListLine() const; QStringList getPlayerNames() const; ServerSocket *getPlayer(int player_id); - void addPlayer(ServerSocket *player); + ReturnMessage::ReturnCode checkJoin(const QString &_password, bool spectator); + void addPlayer(ServerSocket *player, bool spectator); void removePlayer(ServerSocket *player); void startGameIfReady(); void msg(const QString &s); diff --git a/servatrice/src/serversocket.cpp b/servatrice/src/serversocket.cpp index 92d8105d..ae7d1b0d 100644 --- a/servatrice/src/serversocket.cpp +++ b/servatrice/src/serversocket.cpp @@ -31,7 +31,7 @@ #include "chatchannel.h" ServerSocket::ServerSocket(Server *_server, QObject *parent) - : QTcpSocket(parent), server(_server), game(0), PlayerStatus(StatusNormal), authState(PasswordWrong), acceptsGameListChanges(false) + : QTcpSocket(parent), server(_server), game(0), spectator(false), PlayerStatus(StatusNormal), authState(PasswordWrong), acceptsGameListChanges(false) { remsg = new ReturnMessage(this); connect(this, SIGNAL(readyRead()), this, SLOT(readClient())); @@ -166,62 +166,64 @@ void ServerSocket::readClient() } const ServerSocket::CommandProperties ServerSocket::commandList[ServerSocket::numberCommands] = { - {"ping", false, false, false, QList(), &ServerSocket::cmdPing}, - {"login", false, false, false, QList() << QVariant::String + {"ping", false, false, false, true, QList(), &ServerSocket::cmdPing}, + {"login", false, false, false, true, QList() << QVariant::String << QVariant::String, &ServerSocket::cmdLogin}, - {"chat_list_channels", true, false, false, QList(), &ServerSocket::cmdChatListChannels}, - {"chat_join_channel", true, false, false, QList() << QVariant::String, &ServerSocket::cmdChatJoinChannel}, - {"chat_leave_channel", true, false, false, QList() << QVariant::String, &ServerSocket::cmdChatLeaveChannel}, - {"chat_say", true, false, false, QList() << QVariant::String + {"chat_list_channels", true, false, false, true, QList(), &ServerSocket::cmdChatListChannels}, + {"chat_join_channel", true, false, false, true, QList() << QVariant::String, &ServerSocket::cmdChatJoinChannel}, + {"chat_leave_channel", true, false, false, true, QList() << QVariant::String, &ServerSocket::cmdChatLeaveChannel}, + {"chat_say", true, false, false, true, QList() << QVariant::String << QVariant::String, &ServerSocket::cmdChatSay}, - {"list_games", true, false, false, QList(), &ServerSocket::cmdListGames}, - {"create_game", true, false, false, QList() << QVariant::String + {"list_games", true, false, false, true, QList(), &ServerSocket::cmdListGames}, + {"create_game", true, false, false, true, QList() << QVariant::String << QVariant::String - << QVariant::Int, &ServerSocket::cmdCreateGame}, - {"join_game", true, false, false, QList() << QVariant::Int - << QVariant::String, &ServerSocket::cmdJoinGame}, - {"leave_game", true, true, false, QList(), &ServerSocket::cmdLeaveGame}, - {"list_players", true, true, false, QList(), &ServerSocket::cmdListPlayers}, - {"say", true, true, false, QList() << QVariant::String, &ServerSocket::cmdSay}, - {"submit_deck", true, true, false, QList(), &ServerSocket::cmdSubmitDeck}, - {"ready_start", true, true, false, QList(), &ServerSocket::cmdReadyStart}, - {"shuffle", true, true, true, QList(), &ServerSocket::cmdShuffle}, - {"draw_cards", true, true, true, QList() << QVariant::Int, &ServerSocket::cmdDrawCards}, - {"reveal_card", true, true, true, QList() << QVariant::Int + << QVariant::Int + << QVariant::Bool, &ServerSocket::cmdCreateGame}, + {"join_game", true, false, false, true, QList() << QVariant::Int + << QVariant::String + << QVariant::Bool, &ServerSocket::cmdJoinGame}, + {"leave_game", true, true, false, true, QList(), &ServerSocket::cmdLeaveGame}, + {"list_players", true, true, false, true, QList(), &ServerSocket::cmdListPlayers}, + {"say", true, true, false, false, QList() << QVariant::String, &ServerSocket::cmdSay}, + {"submit_deck", true, true, false, false, QList(), &ServerSocket::cmdSubmitDeck}, + {"ready_start", true, true, false, false, QList(), &ServerSocket::cmdReadyStart}, + {"shuffle", true, true, true, false, QList(), &ServerSocket::cmdShuffle}, + {"draw_cards", true, true, true, false, QList() << QVariant::Int, &ServerSocket::cmdDrawCards}, + {"reveal_card", true, true, true, false, QList() << QVariant::Int << QVariant::String, &ServerSocket::cmdRevealCard}, - {"move_card", true, true, true, QList() << QVariant::Int + {"move_card", true, true, true, false, QList() << QVariant::Int << QVariant::String << QVariant::String << QVariant::Int << QVariant::Int << QVariant::Bool, &ServerSocket::cmdMoveCard}, - {"create_token", true, true, true, QList() << QVariant::String + {"create_token", true, true, true, false, QList() << QVariant::String << QVariant::String << QVariant::String << QVariant::Int << QVariant::Int, &ServerSocket::cmdCreateToken}, - {"set_card_attr", true, true, true, QList() << QVariant::String + {"set_card_attr", true, true, true, false, QList() << QVariant::String << QVariant::Int << QVariant::String << QVariant::String, &ServerSocket::cmdSetCardAttr}, - {"inc_counter", true, true, true, QList() << QVariant::String + {"inc_counter", true, true, true, false, QList() << QVariant::String << QVariant::Int, &ServerSocket::cmdIncCounter}, - {"add_counter", true, true, true, QList() << QVariant::String + {"add_counter", true, true, true, false, QList() << QVariant::String << QVariant::Int << QVariant::Int, &ServerSocket::cmdAddCounter}, - {"set_counter", true, true, true, QList() << QVariant::String + {"set_counter", true, true, true, false, QList() << QVariant::String << QVariant::Int, &ServerSocket::cmdSetCounter}, - {"del_counter", true, true, true, QList() << QVariant::String, &ServerSocket::cmdDelCounter}, - {"list_counters", true, true, true, QList() << QVariant::Int, &ServerSocket::cmdListCounters}, - {"list_zones", true, true, true, QList() << QVariant::Int, &ServerSocket::cmdListZones}, - {"dump_zone", true, true, true, QList() << QVariant::Int + {"del_counter", true, true, true, false, QList() << QVariant::String, &ServerSocket::cmdDelCounter}, + {"list_counters", true, true, true, true, QList() << QVariant::Int, &ServerSocket::cmdListCounters}, + {"list_zones", true, true, true, true, QList() << QVariant::Int, &ServerSocket::cmdListZones}, + {"dump_zone", true, true, true, true, QList() << QVariant::Int << QVariant::String << QVariant::Int, &ServerSocket::cmdDumpZone}, - {"stop_dump_zone", true, true, true, QList() << QVariant::Int + {"stop_dump_zone", true, true, true, true, QList() << QVariant::Int << QVariant::String, &ServerSocket::cmdStopDumpZone}, - {"roll_die", true, true, true, QList() << QVariant::Int, &ServerSocket::cmdRollDie}, - {"next_turn", true, true, true, QList(), &ServerSocket::cmdNextTurn}, - {"set_active_phase", true, true, true, QList() << QVariant::Int, &ServerSocket::cmdSetActivePhase} + {"roll_die", true, true, true, false, QList() << QVariant::Int, &ServerSocket::cmdRollDie}, + {"next_turn", true, true, true, false, QList(), &ServerSocket::cmdNextTurn}, + {"set_active_phase", true, true, true, false, QList() << QVariant::Int, &ServerSocket::cmdSetActivePhase} }; ReturnMessage::ReturnCode ServerSocket::cmdPing(const QList &/*params*/) @@ -311,10 +313,14 @@ ReturnMessage::ReturnCode ServerSocket::cmdCreateGame(const QList &par QString description = params[0].toString(); QString password = params[1].toString(); int maxPlayers = params[2].toInt(); + bool spectatorsAllowed = params[3].toBool(); + acceptsGameListChanges = false; acceptsChatChannelListChanges = false; + spectator = false; leaveGame(); - emit createGame(description, password, maxPlayers, this); + emit createGame(description, password, maxPlayers, spectatorsAllowed, this); + return ReturnMessage::ReturnOk; } @@ -322,13 +328,21 @@ ReturnMessage::ReturnCode ServerSocket::cmdJoinGame(const QList ¶m { int gameId = params[0].toInt(); QString password = params[1].toString(); - if (!server->checkGamePassword(gameId, password)) - return ReturnMessage::ReturnPasswordWrong; - acceptsGameListChanges = false; - acceptsChatChannelListChanges = false; - leaveGame(); - emit joinGame(gameId, this); - return ReturnMessage::ReturnOk; + bool _spectator = params[2].toBool(); + + ServerGame *g = server->getGame(gameId); + if (!g) + return ReturnMessage::ReturnNameNotFound; + + ReturnMessage::ReturnCode result = g->checkJoin(password, _spectator); + if (result == ReturnMessage::ReturnOk) { + acceptsGameListChanges = false; + acceptsChatChannelListChanges = false; + leaveGame(); + spectator = _spectator; + g->addPlayer(this, spectator); + } + return result; } ReturnMessage::ReturnCode ServerSocket::cmdLeaveGame(const QList &/*params*/) @@ -716,6 +730,8 @@ bool ServerSocket::parseCommand(QString line) if (commandList[i].needsLogin && (authState == PasswordWrong)) return remsg->send(ReturnMessage::ReturnLoginNeeded); // Check context + if (!commandList[i].allowedToSpectator && spectator) + return remsg->send(ReturnMessage::ReturnContextError); if (commandList[i].needsGame && !game) return remsg->send(ReturnMessage::ReturnContextError); if (commandList[i].needsStartedGame && !game->getGameStarted()) diff --git a/servatrice/src/serversocket.h b/servatrice/src/serversocket.h index 40396d39..7d4ebaee 100644 --- a/servatrice/src/serversocket.h +++ b/servatrice/src/serversocket.h @@ -40,8 +40,7 @@ private slots: void readClient(); void catchSocketError(QAbstractSocket::SocketError socketError); signals: - void createGame(const QString description, const QString password, const int maxPlayers, ServerSocket *creator); - void joinGame(int gameId, ServerSocket *player); + void createGame(const QString description, const QString password, int maxPlayers, bool spectatorsAllowed, ServerSocket *creator); void commandReceived(QString cmd, ServerSocket *player); void broadcastEvent(const QString &event, ServerSocket *player); void startGameIfReady(); @@ -52,6 +51,7 @@ private: bool needsLogin; bool needsGame; bool needsStartedGame; + bool allowedToSpectator; QList paramTypes; CommandHandler handler; }; @@ -99,6 +99,7 @@ private: QList counters; int playerId; QString playerName; + bool spectator; int nextCardId; int newCardId(); PlayerZone *getZone(const QString &name) const; @@ -121,6 +122,7 @@ public: void initConnection(); int getPlayerId() const { return playerId; } void setPlayerId(int _id) { playerId = _id; } + bool getSpectator() const { return spectator; } QString getPlayerName() const { return playerName; } bool getAcceptsGameListChanges() const { return acceptsGameListChanges; } bool getAcceptsChatChannelListChanges() const { return acceptsChatChannelListChanges; }