From a8c45fda1a5d69aac15172300c81bfe98186d824 Mon Sep 17 00:00:00 2001 From: Max-Wilhelm Bruker Date: Sat, 24 Oct 2009 21:20:26 +0200 Subject: [PATCH] reworked protocol; only server code for now --- servatrice/servatrice.pro | 6 +- servatrice/src/abstractrng.h | 2 + servatrice/src/main.cpp | 6 +- servatrice/src/player.cpp | 149 +++++++ servatrice/src/player.h | 66 ++++ servatrice/src/playerzone.cpp | 6 +- servatrice/src/playerzone.h | 10 +- servatrice/src/server.cpp | 15 +- servatrice/src/server.h | 9 +- servatrice/src/servergame.cpp | 86 ++--- servatrice/src/servergame.h | 23 +- servatrice/src/serversocket.cpp | 662 ++++++++++++++------------------ servatrice/src/serversocket.h | 163 ++++---- 13 files changed, 669 insertions(+), 534 deletions(-) create mode 100644 servatrice/src/player.cpp create mode 100644 servatrice/src/player.h diff --git a/servatrice/servatrice.pro b/servatrice/servatrice.pro index 71dacbd9..f82fc240 100755 --- a/servatrice/servatrice.pro +++ b/servatrice/servatrice.pro @@ -23,7 +23,8 @@ HEADERS += src/server.h src/servergame.h src/serversocket.h \ src/abstractrng.h \ src/rng_qt.h \ src/returnmessage.h \ - src/chatchannel.h + src/chatchannel.h \ + src/player.h SOURCES += src/main.cpp \ src/server.cpp \ src/servergame.cpp \ @@ -33,4 +34,5 @@ SOURCES += src/main.cpp \ src/counter.cpp \ src/rng_qt.cpp \ src/returnmessage.cpp \ - src/chatchannel.cpp + src/chatchannel.cpp \ + src/player.cpp diff --git a/servatrice/src/abstractrng.h b/servatrice/src/abstractrng.h index 6cdc9783..d4350da0 100644 --- a/servatrice/src/abstractrng.h +++ b/servatrice/src/abstractrng.h @@ -10,4 +10,6 @@ public: virtual unsigned int getNumber(unsigned int min, unsigned int max) = 0; }; +extern AbstractRNG *rng; + #endif diff --git a/servatrice/src/main.cpp b/servatrice/src/main.cpp index bb649d6f..84a81c8a 100644 --- a/servatrice/src/main.cpp +++ b/servatrice/src/main.cpp @@ -18,10 +18,12 @@ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ - #include #include #include "server.h" +#include "rng_qt.h" + +AbstractRNG *rng; int main(int argc, char *argv[]) { @@ -31,6 +33,8 @@ int main(int argc, char *argv[]) QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8")); + rng = new RNG_Qt; + Server server; server.listen(QHostAddress::Any, 4747); diff --git a/servatrice/src/player.cpp b/servatrice/src/player.cpp new file mode 100644 index 00000000..c735a7f0 --- /dev/null +++ b/servatrice/src/player.cpp @@ -0,0 +1,149 @@ +#include "player.h" +#include "card.h" +#include "counter.h" +#include "arrow.h" +#include "playerzone.h" +#include "serversocket.h" +#include "servergame.h" + +Player::Player(ServerGame *_game, int _playerId, const QString &_playerName, bool _spectator) + : game(_game), socket(0), playerId(_playerId), playerName(_playerName), spectator(_spectator), nextCardId(0), PlayerStatus(StatusNormal) +{ +} + +int Player::newCardId() +{ + return nextCardId++; +} + +int Player::newCounterId() const +{ + int id = 0; + QMapIterator i(counters); + while (i.hasNext()) { + Counter *c = i.next().value(); + if (c->getId() > id) + id = c->getId(); + } + return id + 1; +} + +int Player::newArrowId() const +{ + int id = 0; + QMapIterator i(arrows); + while (i.hasNext()) { + Arrow *a = i.next().value(); + if (a->getId() > id) + id = a->getId(); + } + return id + 1; +} + +void Player::setupZones() +{ + // Delete existing zones and counters + clearZones(); + + // This may need to be customized according to the game rules. + // ------------------------------------------------------------------ + + // Create zones + PlayerZone *deck = new PlayerZone(this, "deck", false, PlayerZone::HiddenZone); + addZone(deck); + PlayerZone *sb = new PlayerZone(this, "sb", false, PlayerZone::HiddenZone); + addZone(sb); + addZone(new PlayerZone(this, "table", true, PlayerZone::PublicZone)); + addZone(new PlayerZone(this, "hand", false, PlayerZone::PrivateZone)); + addZone(new PlayerZone(this, "grave", false, PlayerZone::PublicZone)); + addZone(new PlayerZone(this, "rfg", false, PlayerZone::PublicZone)); + + // ------------------------------------------------------------------ + + // Assign card ids and create deck from decklist + QListIterator DeckIterator(DeckList); + int i = 0; + while (DeckIterator.hasNext()) + deck->cards.append(new Card(DeckIterator.next(), i++, 0, 0)); + deck->shuffle(); + + QListIterator SBIterator(SideboardList); + while (SBIterator.hasNext()) + sb->cards.append(new Card(SBIterator.next(), i++, 0, 0)); + + nextCardId = i; + + PlayerStatus = StatusPlaying; + game->broadcastEvent(QString("setup_zones|%1|%2").arg(deck->cards.size()) + .arg(sb->cards.size()), this); +} + +void Player::clearZones() +{ + QMapIterator zoneIterator(zones); + while (zoneIterator.hasNext()) + delete zoneIterator.next().value(); + zones.clear(); + + QMapIterator counterIterator(counters); + while (counterIterator.hasNext()) + delete counterIterator.next().value(); + counters.clear(); + + QMapIterator arrowIterator(arrows); + while (arrowIterator.hasNext()) + delete arrowIterator.next().value(); + arrows.clear(); +} + +void Player::addZone(PlayerZone *zone) +{ + zones.insert(zone->getName(), zone); +} + +void Player::addArrow(Arrow *arrow) +{ + arrows.insert(arrow->getId(), arrow); +} + +bool Player::deleteArrow(int arrowId) +{ + Arrow *arrow = arrows.value(arrowId, 0); + if (!arrow) + return false; + arrows.remove(arrowId); + delete arrow; + return true; +} + +void Player::addCounter(Counter *counter) +{ + counters.insert(counter->getId(), counter); +} + +bool Player::deleteCounter(int counterId) +{ + Counter *counter = counters.value(counterId, 0); + if (!counter) + return false; + counters.remove(counterId); + delete counter; + return true; +} + +void Player::privateEvent(const QString &line) +{ + if (!socket) + return; + socket->msg(QString("private|%1|%2|%3").arg(playerId).arg(playerName).arg(line)); +} + +void Player::publicEvent(const QString &line, Player *player) +{ + if (!socket) + return; + if (player) + socket->msg(QString("public|%1|%2|%3").arg(player->getPlayerId()).arg(player->getPlayerName()).arg(line)); + else + socket->msg(QString("public|||%1").arg(line)); +} diff --git a/servatrice/src/player.h b/servatrice/src/player.h new file mode 100644 index 00000000..ebdd88bc --- /dev/null +++ b/servatrice/src/player.h @@ -0,0 +1,66 @@ +#ifndef PLAYER_H +#define PLAYER_H + +#include +#include +#include +#include + +class ServerSocket; +class ServerGame; +class PlayerZone; +class Counter; +class Arrow; + +enum PlayerStatusEnum { StatusNormal, StatusSubmitDeck, StatusReadyStart, StatusPlaying }; + +class Player : public QObject { + Q_OBJECT +private: + ServerGame *game; + ServerSocket *socket; + QMap zones; + QMap counters; + QMap arrows; + int playerId; + QString playerName; + bool spectator; + int nextCardId; + void clearZones(); + PlayerStatusEnum PlayerStatus; +public: + // Pfusch + QList DeckList; + QList SideboardList; + // Pfusch Ende + + Player(ServerGame *_game, int _playerId, const QString &_playerName, bool _spectator); + void setSocket(ServerSocket *_socket) { socket = _socket; } + + void setStatus(PlayerStatusEnum _status) { PlayerStatus = _status; } + void setPlayerId(int _id) { playerId = _id; } + PlayerStatusEnum getStatus() { return PlayerStatus; } + int getPlayerId() const { return playerId; } + bool getSpectator() const { return spectator; } + QString getPlayerName() const { return playerName; } + const QMap &getZones() const { return zones; } + const QMap &getCounters() const { return counters; } + const QMap &getArrows() const { return arrows; } + + int newCardId(); + int newCounterId() const; + int newArrowId() const; + + void addZone(PlayerZone *zone); + void addArrow(Arrow *arrow); + bool deleteArrow(int arrowId); + void addCounter(Counter *counter); + bool deleteCounter(int counterId); + + void setupZones(); + + void privateEvent(const QString &line); + void publicEvent(const QString &line, Player *player = 0); +}; + +#endif diff --git a/servatrice/src/playerzone.cpp b/servatrice/src/playerzone.cpp index ba397376..1192cf8d 100644 --- a/servatrice/src/playerzone.cpp +++ b/servatrice/src/playerzone.cpp @@ -21,7 +21,7 @@ #include "abstractrng.h" #include "card.h" -PlayerZone::PlayerZone(ServerSocket *_player, const QString &_name, bool _has_coords, ZoneType _type) +PlayerZone::PlayerZone(Player *_player, const QString &_name, bool _has_coords, ZoneType _type) : player(_player), name(_name), has_coords(_has_coords), type(_type), cardsBeingLookedAt(0) { } @@ -32,11 +32,11 @@ PlayerZone::~PlayerZone() clear(); } -void PlayerZone::shuffle(AbstractRNG *rnd) +void PlayerZone::shuffle() { QList temp; for (int i = cards.size(); i; i--) - temp.append(cards.takeAt(rnd->getNumber(0, i - 1))); + temp.append(cards.takeAt(rng->getNumber(0, i - 1))); cards = temp; } diff --git a/servatrice/src/playerzone.h b/servatrice/src/playerzone.h index 2c418420..3814af36 100644 --- a/servatrice/src/playerzone.h +++ b/servatrice/src/playerzone.h @@ -25,7 +25,7 @@ class Card; class ServerSocket; -class AbstractRNG; +class Player; class PlayerZone { public: @@ -39,13 +39,13 @@ public: // list index, whereas cards in any other zone are referenced by their ids. enum ZoneType { PrivateZone, PublicZone, HiddenZone }; private: - ServerSocket *player; + Player *player; QString name; bool has_coords; ZoneType type; int cardsBeingLookedAt; public: - PlayerZone(ServerSocket *_player, const QString &_name, bool _has_coords, ZoneType _type); + PlayerZone(Player *_player, const QString &_name, bool _has_coords, ZoneType _type); ~PlayerZone(); Card *getCard(int id, bool remove, int *position = NULL); @@ -55,11 +55,11 @@ public: bool hasCoords() const { return has_coords; } ZoneType getType() const { return type; } QString getName() const { return name; } - ServerSocket *getPlayer() const { return player; } + Player *getPlayer() const { return player; } QList cards; void insertCard(Card *card, int x, int y); - void shuffle(AbstractRNG *rnd); + void shuffle(); void clear(); }; diff --git a/servatrice/src/server.cpp b/servatrice/src/server.cpp index 09eead6b..2491835b 100644 --- a/servatrice/src/server.cpp +++ b/servatrice/src/server.cpp @@ -21,7 +21,6 @@ #include "servergame.h" #include "serversocket.h" #include "counter.h" -#include "rng_qt.h" #include "chatchannel.h" #include #include @@ -29,8 +28,6 @@ Server::Server(QObject *parent) : QTcpServer(parent), nextGameId(0) { - rng = new RNG_Qt(this); - settings = new QSettings("servatrice.ini", QSettings::IniFormat, this); QString dbType = settings->value("database/type").toString(); @@ -40,16 +37,15 @@ Server::Server(QObject *parent) int size = settings->beginReadArray("chatchannels"); for (int i = 0; i < size; ++i) { settings->setArrayIndex(i); - chatChannelList << new ChatChannel(settings->value("name").toString(), + ChatChannel *newChannel = new ChatChannel(settings->value("name").toString(), settings->value("description").toString(), settings->value("autojoin").toBool(), settings->value("joinmessage").toStringList()); + chatChannels.insert(newChannel->getName(), newChannel); + connect(newChannel, SIGNAL(channelInfoChanged()), this, SLOT(broadcastChannelUpdate())); } settings->endArray(); - for (int i = 0; i < chatChannelList.size(); ++i) - connect(chatChannelList[i], SIGNAL(channelInfoChanged()), this, SLOT(broadcastChannelUpdate())); - loginMessage = settings->value("messages/login").toStringList(); } @@ -85,14 +81,15 @@ bool Server::openDatabase() return true; } -void Server::addGame(const QString description, const QString password, int maxPlayers, bool spectatorsAllowed, ServerSocket *creator) +ServerGame *Server::createGame(const QString &description, const QString &password, int maxPlayers, bool spectatorsAllowed, const QString &creator) { ServerGame *newGame = new ServerGame(creator, nextGameId++, description, password, maxPlayers, spectatorsAllowed, this); games.insert(newGame->getGameId(), newGame); connect(newGame, SIGNAL(gameClosing()), this, SLOT(gameClosing())); - newGame->addPlayer(creator, false); broadcastGameListUpdate(newGame); + + return newGame; } void Server::incomingConnection(int socketId) diff --git a/servatrice/src/server.h b/servatrice/src/server.h index 4e6df611..01a0d770 100644 --- a/servatrice/src/server.h +++ b/servatrice/src/server.h @@ -27,7 +27,6 @@ class ServerGame; class ServerSocket; class QSqlDatabase; class QSettings; -class AbstractRNG; class ChatChannel; enum AuthenticationResult { PasswordWrong = 0, PasswordRight = 1, UnknownUser = 2 }; @@ -36,7 +35,6 @@ class Server : public QTcpServer { Q_OBJECT private slots: - void addGame(const QString description, const QString password, int maxPlayers, bool spectatorsAllowed, ServerSocket *creator); void gameClosing(); void broadcastChannelUpdate(); public: @@ -47,19 +45,18 @@ public: AuthenticationResult checkUserPassword(const QString &user, const QString &password); QList getGames() const { return games.values(); } ServerGame *getGame(int gameId) const; - QList getChatChannelList() { return chatChannelList; } - AbstractRNG *getRNG() const { return rng; } + const QMap &getChatChannels() { return chatChannels; } void broadcastGameListUpdate(ServerGame *game); void removePlayer(ServerSocket *player); const QStringList &getLoginMessage() const { return loginMessage; } + ServerGame *createGame(const QString &description, const QString &password, int maxPlayers, bool spectatorsAllowed, const QString &playerName); private: void incomingConnection(int SocketId); QMap games; QList players; - QList chatChannelList; + QMap chatChannels; int nextGameId; QStringList loginMessage; - AbstractRNG *rng; }; #endif diff --git a/servatrice/src/servergame.cpp b/servatrice/src/servergame.cpp index f102e200..b65f176a 100644 --- a/servatrice/src/servergame.cpp +++ b/servatrice/src/servergame.cpp @@ -23,20 +23,22 @@ #include "arrow.h" #include -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) +ServerGame::ServerGame(const QString &_creator, int _gameId, const QString &_description, const QString &_password, int _maxPlayers, bool _spectatorsAllowed, QObject *parent) + : QObject(parent), gameStarted(false), gameId(_gameId), description(_description), password(_password), maxPlayers(_maxPlayers), spectatorsAllowed(_spectatorsAllowed) { + creator = addPlayer(_creator, false); } ServerGame::~ServerGame() { broadcastEvent("game_closed", 0); - for (int i = 0; i < players.size(); ++i) - players[i]->leaveGame(); + QMapIterator playerIterator(players); + while (playerIterator.hasNext()) + delete playerIterator.next().value(); players.clear(); for (int i = 0; i < spectators.size(); ++i) - spectators[i]->leaveGame(); + delete spectators[i]; spectators.clear(); emit gameClosing(); @@ -60,20 +62,9 @@ QString ServerGame::getGameListLine() const } } -ServerSocket *ServerGame::getPlayer(int playerId) +void ServerGame::broadcastEvent(const QString &eventStr, Player *player) { - QListIterator i(players); - while (i.hasNext()) { - ServerSocket *tmp = i.next(); - if (tmp->getPlayerId() == playerId) - return tmp; - } - return NULL; -} - -void ServerGame::broadcastEvent(const QString &eventStr, ServerSocket *player) -{ - QList allClients = QList() << players << spectators; + QList allClients = QList() << players.values() << spectators; for (int i = 0; i < allClients.size(); ++i) allClients[i]->publicEvent(eventStr, player); } @@ -82,8 +73,9 @@ void ServerGame::startGameIfReady() { if (players.size() < maxPlayers) return; - for (int i = 0; i < players.size(); i++) - if (players.at(i)->getStatus() != StatusReadyStart) + QMapIterator playerIterator(players); + while (playerIterator.hasNext()) + if (playerIterator.next().value()->getStatus() != StatusReadyStart) return; QSqlQuery query; @@ -93,16 +85,17 @@ void ServerGame::startGameIfReady() query.bindValue(":password", !password.isEmpty()); query.exec(); - for (int i = 0; i < players.size(); i++) { + QMapIterator playerIterator2(players); + while (playerIterator2.hasNext()) { + Player *player = playerIterator2.next().value(); query.prepare("insert into games_players (id_game, player) values(:id, :player)"); query.bindValue(":id", gameId); - query.bindValue(":player", players.at(i)->getPlayerName()); + query.bindValue(":player", player->getPlayerName()); query.exec(); + + player->setupZones(); } - for (int i = 0; i < players.size(); i++) - players.at(i)->setupZones(); - gameStarted = true; broadcastEvent("game_start", NULL); setActivePlayer(0); @@ -121,41 +114,42 @@ ReturnMessage::ReturnCode ServerGame::checkJoin(const QString &_password, bool s return ReturnMessage::ReturnOk; } -void ServerGame::addPlayer(ServerSocket *player, bool spectator) +Player *ServerGame::addPlayer(const QString &playerName, bool spectator) { + int playerId; if (!spectator) { int max = -1; - QListIterator i(players); + QMapIterator i(players); while (i.hasNext()) { - int tmp = i.next()->getPlayerId(); + int tmp = i.next().value()->getPlayerId(); if (tmp > max) max = tmp; } - player->setPlayerId(max + 1); + playerId = max + 1; } else - player->setPlayerId(-1); + playerId = -1; - player->setGame(this); - broadcastEvent(QString("join|%1").arg(spectator ? 1 : 0), player); + Player *newPlayer = new Player(this, playerId, playerName, spectator); + broadcastEvent(QString("join|%1").arg(spectator ? 1 : 0), newPlayer); if (spectator) - spectators << player; + spectators << newPlayer; else - players << player; - - connect(player, SIGNAL(broadcastEvent(const QString &, ServerSocket *)), this, SLOT(broadcastEvent(const QString &, ServerSocket *))); + players.insert(playerId, newPlayer); qobject_cast(parent())->broadcastGameListUpdate(this); + + return newPlayer; } -void ServerGame::removePlayer(ServerSocket *player) +void ServerGame::removePlayer(Player *player) { if (player->getSpectator()) spectators.removeAt(spectators.indexOf(player)); else - players.removeAt(players.indexOf(player)); + players.remove(player->getPlayerId()); broadcastEvent("leave", player); - disconnect(player, 0, this, 0); + delete player; if (!players.size()) deleteLater(); @@ -171,12 +165,14 @@ void ServerGame::setActivePlayer(int _activePlayer) void ServerGame::setActivePhase(int _activePhase) { - for (int i = 0; i < players.size(); ++i) { - QMapIterator arrowIterator(players[i]->getArrows()); - while (arrowIterator.hasNext()) { - Arrow *a = arrowIterator.next().value(); - broadcastEvent(QString("delete_arrow|%1").arg(a->getId()), players[i]); - players[i]->deleteArrow(a->getId()); + QMapIterator playerIterator(players); + while (playerIterator.hasNext()) { + Player *player = playerIterator.next().value(); + QList toDelete = player->getArrows().values(); + for (int i = 0; i < toDelete.size(); ++i) { + Arrow *a = toDelete[i]; + broadcastEvent(QString("delete_arrow|%1").arg(a->getId()), player); + player->deleteArrow(a->getId()); } } diff --git a/servatrice/src/servergame.h b/servatrice/src/servergame.h index 23bca6c4..04f8e1f5 100644 --- a/servatrice/src/servergame.h +++ b/servatrice/src/servergame.h @@ -22,15 +22,16 @@ #include #include +#include "player.h" #include "returnmessage.h" #include "serversocket.h" class ServerGame : public QObject { Q_OBJECT private: - QPointer creator; - QList players; - QList spectators; + QPointer creator; + QMap players; + QList spectators; bool gameStarted; int gameId; QString description; @@ -40,16 +41,14 @@ private: bool spectatorsAllowed; signals: void gameClosing(); -public slots: - void broadcastEvent(const QString &eventStr, ServerSocket *player); public: - ServerGame(ServerSocket *_creator, int _gameId, const QString &_description, const QString &_password, int _maxPlayers, bool _spectatorsAllowed, QObject *parent = 0); + ServerGame(const QString &_creator, int _gameId, const QString &_description, const QString &_password, int _maxPlayers, bool _spectatorsAllowed, QObject *parent = 0); ~ServerGame(); - ServerSocket *getCreator() const { return creator; } + Player *getCreator() const { return creator; } bool getGameStarted() const { return gameStarted; } int getPlayerCount() const { return players.size(); } - const QList &getPlayers() const { return players; } - ServerSocket *getPlayer(int playerId); + QList getPlayers() const { return players.values(); } + Player *getPlayer(int playerId) const { return players.value(playerId, 0); } int getGameId() const { return gameId; } QString getDescription() const { return description; } QString getPassword() const { return password; } @@ -57,13 +56,15 @@ public: bool getSpectatorsAllowed() const { return spectatorsAllowed; } QString getGameListLine() const; ReturnMessage::ReturnCode checkJoin(const QString &_password, bool spectator); - void addPlayer(ServerSocket *player, bool spectator); - void removePlayer(ServerSocket *player); + Player *addPlayer(const QString &playerName, bool spectator); + void removePlayer(Player *player); void startGameIfReady(); int getActivePlayer() const { return activePlayer; } int getActivePhase() const { return activePhase; } void setActivePlayer(int _activePlayer); void setActivePhase(int _activePhase); + + void broadcastEvent(const QString &eventStr, Player *player); }; #endif diff --git a/servatrice/src/serversocket.cpp b/servatrice/src/serversocket.cpp index 9d3e0aef..04a92d70 100644 --- a/servatrice/src/serversocket.cpp +++ b/servatrice/src/serversocket.cpp @@ -28,63 +28,64 @@ #include "counter.h" #include "card.h" #include "arrow.h" -#include "abstractrng.h" #include "chatchannel.h" +#include "player.h" +#include "abstractrng.h" -QHash ServerSocket::commandHash; +QHash ServerSocket::commandHash; ServerSocket::ServerSocket(Server *_server, QObject *parent) - : QTcpSocket(parent), server(_server), game(0), spectator(false), nextCardId(0), PlayerStatus(StatusNormal), authState(PasswordWrong), acceptsGameListChanges(false) + : QTcpSocket(parent), server(_server), authState(PasswordWrong), acceptsGameListChanges(false) { if (commandHash.isEmpty()) { - commandHash.insert("ping", CommandProperties(false, false, false, true, QList(), &ServerSocket::cmdPing)); - commandHash.insert("login", CommandProperties(false, false, false, true, QList() + commandHash.insert("ping", new GenericCommandProperties(false, QList(), &ServerSocket::cmdPing)); + commandHash.insert("login", new GenericCommandProperties(false, QList() << QVariant::String << QVariant::String, &ServerSocket::cmdLogin)); - commandHash.insert("chat_list_channels", CommandProperties(true, false, false, true, QList(), &ServerSocket::cmdChatListChannels)); - commandHash.insert("chat_join_channel", CommandProperties(true, false, false, true, QList() + commandHash.insert("chat_list_channels", new GenericCommandProperties(true, QList(), &ServerSocket::cmdChatListChannels)); + commandHash.insert("chat_join_channel", new GenericCommandProperties(true, QList() << QVariant::String, &ServerSocket::cmdChatJoinChannel)); - commandHash.insert("chat_leave_channel", CommandProperties(true, false, false, true, QList() - << QVariant::String, &ServerSocket::cmdChatLeaveChannel)); - commandHash.insert("chat_say", CommandProperties(true, false, false, true, QList() - << QVariant::String - << QVariant::String, &ServerSocket::cmdChatSay)); - commandHash.insert("list_games", CommandProperties(true, false, false, true, QList(), &ServerSocket::cmdListGames)); - commandHash.insert("create_game", CommandProperties(true, false, false, true, QList() + commandHash.insert("list_games", new GenericCommandProperties(true, QList(), &ServerSocket::cmdListGames)); + commandHash.insert("create_game", new GenericCommandProperties(true, QList() << QVariant::String << QVariant::String << QVariant::Int << QVariant::Bool, &ServerSocket::cmdCreateGame)); - commandHash.insert("join_game", CommandProperties(true, false, false, true, QList() + commandHash.insert("join_game", new GenericCommandProperties(true, QList() << QVariant::Int << QVariant::String << QVariant::Bool, &ServerSocket::cmdJoinGame)); - commandHash.insert("leave_game", CommandProperties(true, true, false, true, QList(), &ServerSocket::cmdLeaveGame)); - commandHash.insert("list_players", CommandProperties(true, true, false, true, QList(), &ServerSocket::cmdListPlayers)); - commandHash.insert("say", CommandProperties(true, true, false, false, QList() + + commandHash.insert("chat_leave_channel", new ChatCommandProperties(QList(), &ServerSocket::cmdChatLeaveChannel)); + commandHash.insert("chat_say", new ChatCommandProperties(QList() + << QVariant::String, &ServerSocket::cmdChatSay)); + + commandHash.insert("leave_game", new GameCommandProperties(false, true, QList(), &ServerSocket::cmdLeaveGame)); + commandHash.insert("list_players", new GameCommandProperties(false, true, QList(), &ServerSocket::cmdListPlayers)); + commandHash.insert("say", new GameCommandProperties(false, false, QList() << QVariant::String, &ServerSocket::cmdSay)); - commandHash.insert("submit_deck", CommandProperties(true, true, false, false, QList(), &ServerSocket::cmdSubmitDeck)); - commandHash.insert("ready_start", CommandProperties(true, true, false, false, QList(), &ServerSocket::cmdReadyStart)); - commandHash.insert("shuffle", CommandProperties(true, true, true, false, QList(), &ServerSocket::cmdShuffle)); - commandHash.insert("draw_cards", CommandProperties(true, true, true, false, QList() + commandHash.insert("submit_deck", new GameCommandProperties(false, false, QList(), &ServerSocket::cmdSubmitDeck)); + commandHash.insert("ready_start", new GameCommandProperties(false, false, QList(), &ServerSocket::cmdReadyStart)); + commandHash.insert("shuffle", new GameCommandProperties(true, false, QList(), &ServerSocket::cmdShuffle)); + commandHash.insert("draw_cards", new GameCommandProperties(true, false, QList() << QVariant::Int, &ServerSocket::cmdDrawCards)); - commandHash.insert("reveal_card", CommandProperties(true, true, true, false, QList() + commandHash.insert("reveal_card", new GameCommandProperties(true, false, QList() << QVariant::Int << QVariant::String, &ServerSocket::cmdRevealCard)); - commandHash.insert("move_card", CommandProperties(true, true, true, false, QList() + commandHash.insert("move_card", new GameCommandProperties(true, false, QList() << QVariant::Int << QVariant::String << QVariant::String << QVariant::Int << QVariant::Int << QVariant::Bool, &ServerSocket::cmdMoveCard)); - commandHash.insert("create_token", CommandProperties(true, true, true, false, QList() + commandHash.insert("create_token", new GameCommandProperties(true, false, QList() << QVariant::String << QVariant::String << QVariant::String << QVariant::Int << QVariant::Int, &ServerSocket::cmdCreateToken)); - commandHash.insert("create_arrow", CommandProperties(true, true, true, false, QList() + commandHash.insert("create_arrow", new GameCommandProperties(true, false, QList() << QVariant::Int << QVariant::String << QVariant::Int @@ -92,43 +93,43 @@ ServerSocket::ServerSocket(Server *_server, QObject *parent) << QVariant::String << QVariant::Int << QVariant::Int, &ServerSocket::cmdCreateArrow)); - commandHash.insert("delete_arrow", CommandProperties(true, true, true, false, QList() + commandHash.insert("delete_arrow", new GameCommandProperties(true, false, QList() << QVariant::Int, &ServerSocket::cmdDeleteArrow)); - commandHash.insert("set_card_attr", CommandProperties(true, true, true, false, QList() + commandHash.insert("set_card_attr", new GameCommandProperties(true, false, QList() << QVariant::String << QVariant::Int << QVariant::String << QVariant::String, &ServerSocket::cmdSetCardAttr)); - commandHash.insert("inc_counter", CommandProperties(true, true, true, false, QList() + commandHash.insert("inc_counter", new GameCommandProperties(true, false, QList() << QVariant::String << QVariant::Int, &ServerSocket::cmdIncCounter)); - commandHash.insert("add_counter", CommandProperties(true, true, true, false, QList() + commandHash.insert("add_counter", new GameCommandProperties(true, false, QList() << QVariant::String << QVariant::Int << QVariant::Int << QVariant::Int, &ServerSocket::cmdAddCounter)); - commandHash.insert("set_counter", CommandProperties(true, true, true, false, QList() + commandHash.insert("set_counter", new GameCommandProperties(true, false, QList() << QVariant::Int << QVariant::Int, &ServerSocket::cmdSetCounter)); - commandHash.insert("del_counter", CommandProperties(true, true, true, false, QList() + commandHash.insert("del_counter", new GameCommandProperties(true, false, QList() << QVariant::Int, &ServerSocket::cmdDelCounter)); - commandHash.insert("list_counters", CommandProperties(true, true, true, true, QList() + commandHash.insert("list_counters", new GameCommandProperties(true, true, QList() << QVariant::Int, &ServerSocket::cmdListCounters)); - commandHash.insert("list_zones", CommandProperties(true, true, true, true, QList() + commandHash.insert("list_zones", new GameCommandProperties(true, true, QList() << QVariant::Int, &ServerSocket::cmdListZones)); - commandHash.insert("dump_zone", CommandProperties(true, true, true, true, QList() + commandHash.insert("dump_zone", new GameCommandProperties(true, true, QList() << QVariant::Int << QVariant::String << QVariant::Int, &ServerSocket::cmdDumpZone)); - commandHash.insert("stop_dump_zone", CommandProperties(true, true, true, true, QList() + commandHash.insert("stop_dump_zone", new GameCommandProperties(true, true, QList() << QVariant::Int << QVariant::String, &ServerSocket::cmdStopDumpZone)); - commandHash.insert("roll_die", CommandProperties(true, true, true, false, QList() + commandHash.insert("roll_die", new GameCommandProperties(true, false, QList() << QVariant::Int, &ServerSocket::cmdRollDie)); - commandHash.insert("next_turn", CommandProperties(true, true, true, false, QList(), &ServerSocket::cmdNextTurn)); - commandHash.insert("set_active_phase", CommandProperties(true, true, true, false, QList() + commandHash.insert("next_turn", new GameCommandProperties(true, false, QList(), &ServerSocket::cmdNextTurn)); + commandHash.insert("set_active_phase", new GameCommandProperties(true, false, QList() << QVariant::Int, &ServerSocket::cmdSetActivePhase)); - commandHash.insert("dump_all", CommandProperties(true, true, false, true, QList(), &ServerSocket::cmdDumpAll)); + commandHash.insert("dump_all", new GameCommandProperties(false, true, QList(), &ServerSocket::cmdDumpAll)); } remsg = new ReturnMessage(this); @@ -141,7 +142,7 @@ ServerSocket::ServerSocket(Server *_server, QObject *parent) ServerSocket::~ServerSocket() { qDebug("ServerSocket destructor"); - clearZones(); +/* clearZones(); // The socket has to be removed from the server's list before it is removed from the game's list // so it will not receive the game update event. server->removePlayer(this); @@ -149,122 +150,7 @@ ServerSocket::~ServerSocket() game->removePlayer(this); for (int i = 0; i < chatChannels.size(); ++i) chatChannels[i]->removePlayer(this); -} - -int ServerSocket::newCardId() -{ - return nextCardId++; -} - -int ServerSocket::newCounterId() const -{ - int id = 0; - QMapIterator i(counters); - while (i.hasNext()) { - Counter *c = i.next().value(); - if (c->getId() > id) - id = c->getId(); - } - return id + 1; -} - -int ServerSocket::newArrowId() const -{ - int id = 0; - QMapIterator i(arrows); - while (i.hasNext()) { - Arrow *a = i.next().value(); - if (a->getId() > id) - id = a->getId(); - } - return id + 1; -} - -PlayerZone *ServerSocket::getZone(const QString &name) const -{ - QListIterator ZoneIterator(zones); - while (ZoneIterator.hasNext()) { - PlayerZone *temp = ZoneIterator.next(); - if (temp->getName() == name) - return temp; - } - return NULL; -} - -void ServerSocket::setupZones() -{ - // Delete existing zones and counters - clearZones(); - - // This may need to be customized according to the game rules. - // ------------------------------------------------------------------ - - // Create zones - PlayerZone *deck = new PlayerZone(this, "deck", false, PlayerZone::HiddenZone); - zones << deck; - PlayerZone *sb = new PlayerZone(this, "sb", false, PlayerZone::HiddenZone); - zones << sb; - zones << new PlayerZone(this, "table", true, PlayerZone::PublicZone); - zones << new PlayerZone(this, "hand", false, PlayerZone::PrivateZone); - zones << new PlayerZone(this, "grave", false, PlayerZone::PublicZone); - zones << new PlayerZone(this, "rfg", false, PlayerZone::PublicZone); - - // ------------------------------------------------------------------ - - // Assign card ids and create deck from decklist - QListIterator DeckIterator(DeckList); - int i = 0; - while (DeckIterator.hasNext()) - deck->cards.append(new Card(DeckIterator.next(), i++, 0, 0)); - deck->shuffle(server->getRNG()); - - QListIterator SBIterator(SideboardList); - while (SBIterator.hasNext()) - sb->cards.append(new Card(SBIterator.next(), i++, 0, 0)); - - nextCardId = i; - - PlayerStatus = StatusPlaying; - broadcastEvent(QString("setup_zones|%1|%2").arg(deck->cards.size()) - .arg(sb->cards.size()), this); -} - -void ServerSocket::clearZones() -{ - for (int i = 0; i < zones.size(); i++) - delete zones.at(i); - zones.clear(); - - QMapIterator counterIterator(counters); - while (counterIterator.hasNext()) - delete counterIterator.next().value(); - counters.clear(); - - QMapIterator arrowIterator(arrows); - while (arrowIterator.hasNext()) - delete arrowIterator.next().value(); - arrows.clear(); -} - -void ServerSocket::leaveGame() -{ - if (!game) - return; - game->removePlayer(this); - game = 0; - PlayerStatus = StatusNormal; - clearZones(); -} - -bool ServerSocket::deleteArrow(int arrowId) -{ - Arrow *arrow = arrows.value(arrowId, 0); - if (!arrow) - return false; - arrows.remove(arrowId); - delete arrow; - return true; -} +*/} void ServerSocket::readClient() { @@ -274,7 +160,7 @@ void ServerSocket::readClient() break; qDebug(QString("<<< %1").arg(line).toLatin1()); - switch (PlayerStatus) { +/* switch (PlayerStatus) { case StatusNormal: case StatusReadyStart: case StatusPlaying: @@ -290,7 +176,7 @@ void ServerSocket::readClient() else DeckList << card; } - } +*/ } } ReturnMessage::ReturnCode ServerSocket::cmdPing(const QList &/*params*/) @@ -316,9 +202,11 @@ ReturnMessage::ReturnCode ServerSocket::cmdLogin(const QList ¶ms) ReturnMessage::ReturnCode ServerSocket::cmdChatListChannels(const QList &/*params*/) { - QList chatChannelList = server->getChatChannelList(); - for (int i = 0; i < chatChannelList.size(); ++i) - msg(chatChannelList[i]->getChannelListLine()); + QMapIterator channelIterator(server->getChatChannels()); + while (channelIterator.hasNext()) { + ChatChannel *c = channelIterator.next().value(); + msg(c->getChannelListLine()); + } acceptsChatChannelListChanges = true; return ReturnMessage::ReturnOk; @@ -326,42 +214,32 @@ ReturnMessage::ReturnCode ServerSocket::cmdChatListChannels(const QList ¶ms) { - for (int i = 0; i < chatChannels.size(); ++i) - if (chatChannels[i]->getName() == params[0]) - return ReturnMessage::ReturnContextError; - - QList allChannels = server->getChatChannelList(); - for (int i = 0; i < allChannels.size(); ++i) - if (allChannels[i]->getName() == params[0]) { - remsg->send(ReturnMessage::ReturnOk); - allChannels[i]->addPlayer(this); - chatChannels << allChannels[i]; - return ReturnMessage::ReturnNothing; - } - return ReturnMessage::ReturnNameNotFound; + QString channelName = params[0].toString(); + if (chatChannels.contains(channelName)) + return ReturnMessage::ReturnContextError; + + QMap allChannels = server->getChatChannels(); + ChatChannel *c = allChannels.value(channelName, 0); + if (!c) + return ReturnMessage::ReturnNameNotFound; + + remsg->send(ReturnMessage::ReturnOk); + c->addPlayer(this); + chatChannels.insert(channelName, c); + return ReturnMessage::ReturnNothing; } -ReturnMessage::ReturnCode ServerSocket::cmdChatLeaveChannel(const QList ¶ms) +ReturnMessage::ReturnCode ServerSocket::cmdChatLeaveChannel(ChatChannel *channel, const QList & /*params*/) { - for (int i = 0; i < chatChannels.size(); ++i) { - ChatChannel *c = chatChannels[i]; - if (c->getName() == params[0]) { - chatChannels.removeAt(i); - c->removePlayer(this); - return ReturnMessage::ReturnOk; - } - } - return ReturnMessage::ReturnNameNotFound; + chatChannels.remove(channel->getName()); + channel->removePlayer(this); + return ReturnMessage::ReturnOk; } -ReturnMessage::ReturnCode ServerSocket::cmdChatSay(const QList ¶ms) +ReturnMessage::ReturnCode ServerSocket::cmdChatSay(ChatChannel *channel, const QList ¶ms) { - for (int i = 0; i < chatChannels.size(); ++i) - if (chatChannels[i]->getName() == params[0]) { - chatChannels[i]->say(this, params[1].toString()); - return ReturnMessage::ReturnOk; - } - return ReturnMessage::ReturnNameNotFound; + channel->say(this, params[0].toString()); + return ReturnMessage::ReturnOk; } ReturnMessage::ReturnCode ServerSocket::cmdListGames(const QList &/*params*/) @@ -381,11 +259,8 @@ ReturnMessage::ReturnCode ServerSocket::cmdCreateGame(const QList &par int maxPlayers = params[2].toInt(); bool spectatorsAllowed = params[3].toBool(); - acceptsGameListChanges = false; - acceptsChatChannelListChanges = false; - spectator = false; - leaveGame(); - emit createGame(description, password, maxPlayers, spectatorsAllowed, this); + ServerGame *game = server->createGame(description, password, maxPlayers, spectatorsAllowed, playerName); + games.insert(game->getGameId(), QPair(game, game->getCreator())); return ReturnMessage::ReturnOk; } @@ -394,78 +269,75 @@ ReturnMessage::ReturnCode ServerSocket::cmdJoinGame(const QList ¶m { int gameId = params[0].toInt(); QString password = params[1].toString(); - bool _spectator = params[2].toBool(); + bool spectator = params[2].toBool(); ServerGame *g = server->getGame(gameId); if (!g) return ReturnMessage::ReturnNameNotFound; - ReturnMessage::ReturnCode result = g->checkJoin(password, _spectator); + ReturnMessage::ReturnCode result = g->checkJoin(password, spectator); if (result == ReturnMessage::ReturnOk) { - acceptsGameListChanges = false; - acceptsChatChannelListChanges = false; - leaveGame(); - spectator = _spectator; - g->addPlayer(this, spectator); + Player *player = g->addPlayer(playerName, spectator); + games.insert(gameId, QPair(g, player)); } return result; } -ReturnMessage::ReturnCode ServerSocket::cmdLeaveGame(const QList &/*params*/) +ReturnMessage::ReturnCode ServerSocket::cmdLeaveGame(ServerGame *game, Player *player, const QList &/*params*/) { - leaveGame(); + game->removePlayer(player); return ReturnMessage::ReturnOk; } -QStringList ServerSocket::listPlayersHelper() +QStringList ServerSocket::listPlayersHelper(ServerGame *game, Player *player) { QStringList result; - const QList &players = game->getPlayers(); + const QList &players = game->getPlayers(); for (int i = 0; i < players.size(); ++i) - result << QString("%1|%2|%3").arg(players[i]->getPlayerId()).arg(players[i]->getPlayerName()).arg(players[i] == this ? 1 : 0); + result << QString("%1|%2|%3").arg(players[i]->getPlayerId()).arg(players[i]->getPlayerName()).arg(players[i] == player ? 1 : 0); return result; } -ReturnMessage::ReturnCode ServerSocket::cmdListPlayers(const QList &/*params*/) +ReturnMessage::ReturnCode ServerSocket::cmdListPlayers(ServerGame *game, Player *player, const QList &/*params*/) { - remsg->sendList(listPlayersHelper()); + remsg->sendList(listPlayersHelper(game, player)); return ReturnMessage::ReturnOk; } -ReturnMessage::ReturnCode ServerSocket::cmdSay(const QList ¶ms) +ReturnMessage::ReturnCode ServerSocket::cmdSay(ServerGame *game, Player *player, const QList ¶ms) { - emit broadcastEvent(QString("say|%1").arg(params[0].toString()), this); + game->broadcastEvent(QString("say|%1").arg(params[0].toString()), player); return ReturnMessage::ReturnOk; } -ReturnMessage::ReturnCode ServerSocket::cmdSubmitDeck(const QList &/*params*/) +ReturnMessage::ReturnCode ServerSocket::cmdSubmitDeck(ServerGame * /*game*/, Player *player, const QList &/*params*/) { - PlayerStatus = StatusSubmitDeck; - DeckList.clear(); - SideboardList.clear(); + player->setStatus(StatusSubmitDeck); + player->DeckList.clear(); + player->SideboardList.clear(); return ReturnMessage::ReturnNothing; } -ReturnMessage::ReturnCode ServerSocket::cmdReadyStart(const QList &/*params*/) +ReturnMessage::ReturnCode ServerSocket::cmdReadyStart(ServerGame *game, Player *player, const QList &/*params*/) { - PlayerStatus = StatusReadyStart; - emit broadcastEvent(QString("ready_start"), this); + player->setStatus(StatusReadyStart); + game->broadcastEvent(QString("ready_start"), player); game->startGameIfReady(); return ReturnMessage::ReturnOk; } -ReturnMessage::ReturnCode ServerSocket::cmdShuffle(const QList &/*params*/) +ReturnMessage::ReturnCode ServerSocket::cmdShuffle(ServerGame *game, Player *player, const QList &/*params*/) { - getZone("deck")->shuffle(server->getRNG()); - emit broadcastEvent("shuffle", this); + player->getZones().value("deck")->shuffle(); + game->broadcastEvent("shuffle", player); return ReturnMessage::ReturnOk; } -ReturnMessage::ReturnCode ServerSocket::cmdDrawCards(const QList ¶ms) +ReturnMessage::ReturnCode ServerSocket::cmdDrawCards(ServerGame *game, Player *player, const QList ¶ms) { int number = params[0].toInt(); - PlayerZone *deck = getZone("deck"); - PlayerZone *hand = getZone("hand"); + PlayerZone *deck = player->getZones().value("deck"); + PlayerZone *hand = player->getZones().value("hand"); if (deck->cards.size() < number) return ReturnMessage::ReturnContextError; @@ -473,16 +345,16 @@ ReturnMessage::ReturnCode ServerSocket::cmdDrawCards(const QList ¶ Card *card = deck->cards.first(); deck->cards.removeFirst(); hand->cards.append(card); - privateEvent(QString("draw|%1|%2").arg(card->getId()).arg(card->getName())); + player->privateEvent(QString("draw|%1|%2").arg(card->getId()).arg(card->getName())); } - emit broadcastEvent(QString("draw|%1").arg(number), this); + game->broadcastEvent(QString("draw|%1").arg(number), player); return ReturnMessage::ReturnOk; } -ReturnMessage::ReturnCode ServerSocket::cmdRevealCard(const QList ¶ms) +ReturnMessage::ReturnCode ServerSocket::cmdRevealCard(ServerGame *game, Player *player, const QList ¶ms) { - int cardid = params[0].toInt(); +/* int cardid = params[0].toInt(); PlayerZone *zone = getZone(params[1].toString()); if (!zone) return ReturnMessage::ReturnContextError; @@ -491,15 +363,15 @@ ReturnMessage::ReturnCode ServerSocket::cmdRevealCard(const QList &par if (!card) return ReturnMessage::ReturnContextError; emit broadcastEvent(QString("reveal_card|%1|%2|%3").arg(cardid).arg(zone->getName()).arg(card->getName()), this); - return ReturnMessage::ReturnOk; +*/ return ReturnMessage::ReturnOk; } -ReturnMessage::ReturnCode ServerSocket::cmdMoveCard(const QList ¶ms) +ReturnMessage::ReturnCode ServerSocket::cmdMoveCard(ServerGame *game, Player *player, const QList ¶ms) { // ID Karte, Startzone, Zielzone, Koordinaten X, Y, Facedown int cardid = params[0].toInt(); - PlayerZone *startzone = getZone(params[1].toString()); - PlayerZone *targetzone = getZone(params[2].toString()); + PlayerZone *startzone = player->getZones().value(params[1].toString()); + PlayerZone *targetzone = player->getZones().value(params[2].toString()); if ((!startzone) || (!targetzone)) return ReturnMessage::ReturnContextError; @@ -532,7 +404,7 @@ ReturnMessage::ReturnCode ServerSocket::cmdMoveCard(const QList ¶m publicCardName = card->getName(); if (facedown) - card->setId(newCardId()); + card->setId(player->newCardId()); card->setFaceDown(facedown); // The player does not get to see which card he moved if it moves between two parts of hidden zones which @@ -542,7 +414,7 @@ ReturnMessage::ReturnCode ServerSocket::cmdMoveCard(const QList ¶m privateCardId = QString(); privateCardName = QString(); } - privateEvent(QString("move_card|%1|%2|%3|%4|%5|%6|%7|%8").arg(privateCardId) + player->privateEvent(QString("move_card|%1|%2|%3|%4|%5|%6|%7|%8").arg(privateCardId) .arg(privateCardName) .arg(startzone->getName()) .arg(position) @@ -560,24 +432,24 @@ ReturnMessage::ReturnCode ServerSocket::cmdMoveCard(const QList ¶m x = -1; if ((startzone->getType() == PlayerZone::PublicZone) || (targetzone->getType() == PlayerZone::PublicZone)) - emit broadcastEvent(QString("move_card|%1|%2|%3|%4|%5|%6|%7|%8").arg(card->getId()) + game->broadcastEvent(QString("move_card|%1|%2|%3|%4|%5|%6|%7|%8").arg(card->getId()) .arg(publicCardName) .arg(startzone->getName()) .arg(position) .arg(targetzone->getName()) .arg(x) .arg(y) - .arg(facedown ? 1 : 0), this); + .arg(facedown ? 1 : 0), player); else - emit broadcastEvent(QString("move_card|||%1|%2|%3|%4|%5|0").arg(startzone->getName()) + game->broadcastEvent(QString("move_card|||%1|%2|%3|%4|%5|0").arg(startzone->getName()) .arg(position) .arg(targetzone->getName()) .arg(x) - .arg(y), this); + .arg(y), player); // If the card was moved to another zone, delete all arrows from and to the card if (startzone != targetzone) { - const QList &players = game->getPlayers(); + const QList &players = game->getPlayers(); for (int i = 0; i < players.size(); ++i) { QList arrowsToDelete; QMapIterator arrowIterator(players[i]->getArrows()); @@ -594,45 +466,45 @@ ReturnMessage::ReturnCode ServerSocket::cmdMoveCard(const QList ¶m return ReturnMessage::ReturnOk; } -ReturnMessage::ReturnCode ServerSocket::cmdCreateToken(const QList ¶ms) +ReturnMessage::ReturnCode ServerSocket::cmdCreateToken(ServerGame *game, Player *player, const QList ¶ms) { // zone, cardname, powtough, x, y // powtough wird erst mal ignoriert - PlayerZone *zone = getZone(params[0].toString()); + PlayerZone *zone = player->getZones().value(params[0].toString()); if (!zone) return ReturnMessage::ReturnContextError; QString cardname = params[1].toString(); QString powtough = params[2].toString(); int x = params[3].toInt(); int y = params[4].toInt(); - int cardid = newCardId(); + int cardid = player->newCardId(); Card *card = new Card(cardname, cardid, x, y); zone->insertCard(card, x, y); - emit broadcastEvent(QString("create_token|%1|%2|%3|%4|%5|%6").arg(zone->getName()) + game->broadcastEvent(QString("create_token|%1|%2|%3|%4|%5|%6").arg(zone->getName()) .arg(cardid) .arg(cardname) .arg(powtough) .arg(x) - .arg(y), this); + .arg(y), player); return ReturnMessage::ReturnOk; } -ReturnMessage::ReturnCode ServerSocket::cmdCreateArrow(const QList ¶ms) +ReturnMessage::ReturnCode ServerSocket::cmdCreateArrow(ServerGame *game, Player *player, const QList ¶ms) { - ServerSocket *startPlayer = game->getPlayer(params[0].toInt()); - ServerSocket *targetPlayer = game->getPlayer(params[3].toInt()); + Player *startPlayer = game->getPlayer(params[0].toInt()); + Player *targetPlayer = game->getPlayer(params[3].toInt()); if (!startPlayer || !targetPlayer) return ReturnMessage::ReturnContextError; - PlayerZone *startZone = startPlayer->getZone(params[1].toString()); - PlayerZone *targetZone = targetPlayer->getZone(params[4].toString()); + PlayerZone *startZone = startPlayer->getZones().value(params[1].toString()); + PlayerZone *targetZone = targetPlayer->getZones().value(params[4].toString()); if (!startZone || !targetZone) return ReturnMessage::ReturnContextError; Card *startCard = startZone->getCard(params[2].toInt(), false); Card *targetCard = targetZone->getCard(params[5].toInt(), false); if (!startCard || !targetCard || (startCard == targetCard)) return ReturnMessage::ReturnContextError; - QMapIterator arrowIterator(arrows); + QMapIterator arrowIterator(player->getArrows()); while (arrowIterator.hasNext()) { Arrow *temp = arrowIterator.next().value(); if ((temp->getStartCard() == startCard) && (temp->getTargetCard() == targetCard)) @@ -640,9 +512,9 @@ ReturnMessage::ReturnCode ServerSocket::cmdCreateArrow(const QList &pa } int color = params[6].toInt(); - Arrow *arrow = new Arrow(newArrowId(), startCard, targetCard, color); - arrows.insert(arrow->getId(), arrow); - emit broadcastEvent(QString("create_arrow|%1|%2|%3|%4|%5|%6|%7|%8") + Arrow *arrow = new Arrow(player->newArrowId(), startCard, targetCard, color); + player->addArrow(arrow); + game->broadcastEvent(QString("create_arrow|%1|%2|%3|%4|%5|%6|%7|%8") .arg(arrow->getId()) .arg(startPlayer->getPlayerId()) .arg(startZone->getName()) @@ -650,26 +522,26 @@ ReturnMessage::ReturnCode ServerSocket::cmdCreateArrow(const QList &pa .arg(targetPlayer->getPlayerId()) .arg(targetZone->getName()) .arg(targetCard->getId()) - .arg(color), this + .arg(color), player ); return ReturnMessage::ReturnOk; } -ReturnMessage::ReturnCode ServerSocket::cmdDeleteArrow(const QList ¶ms) +ReturnMessage::ReturnCode ServerSocket::cmdDeleteArrow(ServerGame *game, Player *player, const QList ¶ms) { int arrowId = params[0].toInt(); - if (!deleteArrow(arrowId)) + if (!player->deleteArrow(arrowId)) return ReturnMessage::ReturnContextError; - emit broadcastEvent(QString("delete_arrow|%1").arg(arrowId), this); + game->broadcastEvent(QString("delete_arrow|%1").arg(arrowId), player); return ReturnMessage::ReturnOk; } -ReturnMessage::ReturnCode ServerSocket::cmdSetCardAttr(const QList ¶ms) +ReturnMessage::ReturnCode ServerSocket::cmdSetCardAttr(ServerGame *game, Player *player, const QList ¶ms) { // zone, card id, attr name, attr value // card id = -1 => affects all cards in the specified zone - PlayerZone *zone = getZone(params[0].toString()); + PlayerZone *zone = player->getZones().value(params[0].toString()); if (!zone) return ReturnMessage::ReturnContextError; int cardid = params[1].toInt(); @@ -688,61 +560,60 @@ ReturnMessage::ReturnCode ServerSocket::cmdSetCardAttr(const QList &pa if (!card->setAttribute(aname, avalue, false)) return ReturnMessage::ReturnSyntaxError; } - emit broadcastEvent(QString("set_card_attr|%1|%2|%3|%4").arg(zone->getName()).arg(cardid).arg(aname).arg(avalue), this); + game->broadcastEvent(QString("set_card_attr|%1|%2|%3|%4").arg(zone->getName()).arg(cardid).arg(aname).arg(avalue), player); return ReturnMessage::ReturnOk; } -ReturnMessage::ReturnCode ServerSocket::cmdIncCounter(const QList ¶ms) +ReturnMessage::ReturnCode ServerSocket::cmdIncCounter(ServerGame *game, Player *player, const QList ¶ms) { + const QMap counters = player->getCounters(); Counter *c = counters.value(params[0].toInt(), 0); if (!c) return ReturnMessage::ReturnContextError; int delta = params[1].toInt(); c->setCount(c->getCount() + delta); - emit broadcastEvent(QString("set_counter|%1|%2").arg(c->getId()).arg(c->getCount()), this); + game->broadcastEvent(QString("set_counter|%1|%2").arg(c->getId()).arg(c->getCount()), player); return ReturnMessage::ReturnOk; } -ReturnMessage::ReturnCode ServerSocket::cmdAddCounter(const QList ¶ms) +ReturnMessage::ReturnCode ServerSocket::cmdAddCounter(ServerGame *game, Player *player, const QList ¶ms) { QString name = params[0].toString(); int color = params[1].toInt(); int radius = params[2].toInt(); int count = params[3].toInt(); - Counter *c = new Counter(newCounterId(), name, color, radius, count); - counters.insert(c->getId(), c); - emit broadcastEvent(QString("add_counter|%1|%2|%3|%4|%5").arg(c->getId()).arg(c->getName()).arg(color).arg(radius).arg(count), this); + Counter *c = new Counter(player->newCounterId(), name, color, radius, count); + player->addCounter(c); + game->broadcastEvent(QString("add_counter|%1|%2|%3|%4|%5").arg(c->getId()).arg(c->getName()).arg(color).arg(radius).arg(count), player); return ReturnMessage::ReturnOk; } -ReturnMessage::ReturnCode ServerSocket::cmdSetCounter(const QList ¶ms) +ReturnMessage::ReturnCode ServerSocket::cmdSetCounter(ServerGame *game, Player *player, const QList ¶ms) { + const QMap counters = player->getCounters(); Counter *c = counters.value(params[0].toInt(), 0); if (!c) return ReturnMessage::ReturnContextError; int count = params[1].toInt(); c->setCount(count); - emit broadcastEvent(QString("set_counter|%1|%2").arg(c->getId()).arg(count), this); + game->broadcastEvent(QString("set_counter|%1|%2").arg(c->getId()).arg(count), player); return ReturnMessage::ReturnOk; } -ReturnMessage::ReturnCode ServerSocket::cmdDelCounter(const QList ¶ms) +ReturnMessage::ReturnCode ServerSocket::cmdDelCounter(ServerGame *game, Player *player, const QList ¶ms) { int counterId = params[0].toInt(); - Counter *c = counters.value(counterId, 0); - if (!c) + if (!player->deleteCounter(counterId)) return ReturnMessage::ReturnContextError; - counters.remove(counterId); - delete c; - emit broadcastEvent(QString("del_counter|%1").arg(counterId), this); + game->broadcastEvent(QString("del_counter|%1").arg(counterId), player); return ReturnMessage::ReturnOk; } -QStringList ServerSocket::listCountersHelper(ServerSocket *player) +QStringList ServerSocket::listCountersHelper(Player *player) { QStringList result; QMapIterator i(player->getCounters()); @@ -753,10 +624,10 @@ QStringList ServerSocket::listCountersHelper(ServerSocket *player) return result; } -ReturnMessage::ReturnCode ServerSocket::cmdListCounters(const QList ¶ms) +ReturnMessage::ReturnCode ServerSocket::cmdListCounters(ServerGame *game, Player * /*player*/, const QList ¶ms) { int player_id = params[0].toInt(); - ServerSocket *player = game->getPlayer(player_id); + Player *player = game->getPlayer(player_id); if (!player) return ReturnMessage::ReturnContextError; @@ -764,27 +635,28 @@ ReturnMessage::ReturnCode ServerSocket::cmdListCounters(const QList &p return ReturnMessage::ReturnOk; } -QStringList ServerSocket::listZonesHelper(ServerSocket *player) +QStringList ServerSocket::listZonesHelper(Player *player) { QStringList result; - const QList &zoneList = player->getZones(); - for (int i = 0; i < zoneList.size(); ++i) { + QMapIterator zoneIterator(player->getZones()); + while (zoneIterator.hasNext()) { + PlayerZone *zone = zoneIterator.next().value(); QString typeStr; - switch (zoneList[i]->getType()) { + switch (zone->getType()) { case PlayerZone::PublicZone: typeStr = "public"; break; case PlayerZone::PrivateZone: typeStr = "private"; break; case PlayerZone::HiddenZone: typeStr = "hidden"; break; default: ; } - result << QString("%1|%2|%3|%4|%5").arg(player->getPlayerId()).arg(zoneList[i]->getName()).arg(typeStr).arg(zoneList[i]->hasCoords()).arg(zoneList[i]->cards.size()); + result << QString("%1|%2|%3|%4|%5").arg(player->getPlayerId()).arg(zone->getName()).arg(typeStr).arg(zone->hasCoords()).arg(zone->cards.size()); } return result; } -ReturnMessage::ReturnCode ServerSocket::cmdListZones(const QList ¶ms) +ReturnMessage::ReturnCode ServerSocket::cmdListZones(ServerGame *game, Player * /*player*/, const QList ¶ms) { int player_id = params[0].toInt(); - ServerSocket *player = game->getPlayer(player_id); + Player *player = game->getPlayer(player_id); if (!player) return ReturnMessage::ReturnContextError; @@ -792,7 +664,7 @@ ReturnMessage::ReturnCode ServerSocket::cmdListZones(const QList ¶ return ReturnMessage::ReturnOk; } -QStringList ServerSocket::dumpZoneHelper(ServerSocket *player, PlayerZone *zone, int number_cards) +QStringList ServerSocket::dumpZoneHelper(Player *player, PlayerZone *zone, int number_cards) { QStringList result; for (int i = 0; (i < zone->cards.size()) && (i < number_cards || number_cards == -1); i++) { @@ -818,50 +690,50 @@ QStringList ServerSocket::dumpZoneHelper(ServerSocket *player, PlayerZone *zone, return result; } -ReturnMessage::ReturnCode ServerSocket::cmdDumpZone(const QList ¶ms) +ReturnMessage::ReturnCode ServerSocket::cmdDumpZone(ServerGame *game, Player *player, const QList ¶ms) { int player_id = params[0].toInt(); int number_cards = params[2].toInt(); - ServerSocket *player = game->getPlayer(player_id); - if (!player) + Player *otherPlayer = game->getPlayer(player_id); + if (!otherPlayer) return ReturnMessage::ReturnContextError; - PlayerZone *zone = player->getZone(params[1].toString()); + PlayerZone *zone = otherPlayer->getZones().value(params[1].toString()); if (!zone) return ReturnMessage::ReturnContextError; - if (!((zone->getType() == PlayerZone::PublicZone) || (player_id == playerId))) + if (!((zone->getType() == PlayerZone::PublicZone) || (player == otherPlayer))) return ReturnMessage::ReturnContextError; if (zone->getType() == PlayerZone::HiddenZone) - emit broadcastEvent(QString("dump_zone|%1|%2|%3").arg(player_id).arg(zone->getName()).arg(number_cards), this); + game->broadcastEvent(QString("dump_zone|%1|%2|%3").arg(player_id).arg(zone->getName()).arg(number_cards), player); - remsg->sendList(dumpZoneHelper(player, zone, number_cards)); + remsg->sendList(dumpZoneHelper(otherPlayer, zone, number_cards)); return ReturnMessage::ReturnOk; } -ReturnMessage::ReturnCode ServerSocket::cmdStopDumpZone(const QList ¶ms) +ReturnMessage::ReturnCode ServerSocket::cmdStopDumpZone(ServerGame *game, Player *player, const QList ¶ms) { - ServerSocket *player = game->getPlayer(params[0].toInt()); - if (!player) + Player *otherPlayer = game->getPlayer(params[0].toInt()); + if (!otherPlayer) return ReturnMessage::ReturnContextError; - PlayerZone *zone = player->getZone(params[1].toString()); + PlayerZone *zone = otherPlayer->getZones().value(params[1].toString()); if (!zone) return ReturnMessage::ReturnContextError; if (zone->getType() == PlayerZone::HiddenZone) { zone->setCardsBeingLookedAt(0); - emit broadcastEvent(QString("stop_dump_zone|%1|%2").arg(player->getPlayerId()).arg(zone->getName()), this); + game->broadcastEvent(QString("stop_dump_zone|%1|%2").arg(otherPlayer->getPlayerId()).arg(zone->getName()), player); } return ReturnMessage::ReturnOk; } -ReturnMessage::ReturnCode ServerSocket::cmdRollDie(const QList ¶ms) +ReturnMessage::ReturnCode ServerSocket::cmdRollDie(ServerGame *game, Player *player, const QList ¶ms) { int sides = params[0].toInt(); - emit broadcastEvent(QString("roll_die|%1|%2").arg(sides).arg(server->getRNG()->getNumber(1, sides)), this); + game->broadcastEvent(QString("roll_die|%1|%2").arg(sides).arg(rng->getNumber(1, sides)), player); return ReturnMessage::ReturnOk; } -ReturnMessage::ReturnCode ServerSocket::cmdNextTurn(const QList &/*params*/) +ReturnMessage::ReturnCode ServerSocket::cmdNextTurn(ServerGame *game, Player * /*player*/, const QList &/*params*/) { int activePlayer = game->getActivePlayer(); if (++activePlayer == game->getPlayerCount()) @@ -870,17 +742,17 @@ ReturnMessage::ReturnCode ServerSocket::cmdNextTurn(const QList &/*par return ReturnMessage::ReturnOk; } -ReturnMessage::ReturnCode ServerSocket::cmdSetActivePhase(const QList ¶ms) +ReturnMessage::ReturnCode ServerSocket::cmdSetActivePhase(ServerGame *game, Player *player, const QList ¶ms) { int active_phase = params[0].toInt(); // XXX Überprüfung, ob die Phase existiert... - if (game->getActivePlayer() != playerId) + if (game->getActivePlayer() != player->getPlayerId()) return ReturnMessage::ReturnContextError; game->setActivePhase(active_phase); return ReturnMessage::ReturnOk; } -QStringList ServerSocket::listArrowsHelper(ServerSocket *player) +QStringList ServerSocket::listArrowsHelper(Player *player) { QStringList result; QMapIterator arrowIterator(player->getArrows()); @@ -891,27 +763,29 @@ QStringList ServerSocket::listArrowsHelper(ServerSocket *player) Card *targetCard = arrow->getTargetCard(); PlayerZone *startZone = startCard->getZone(); PlayerZone *targetZone = targetCard->getZone(); - ServerSocket *startPlayer = startZone->getPlayer(); - ServerSocket *targetPlayer = targetZone->getPlayer(); + Player *startPlayer = startZone->getPlayer(); + Player *targetPlayer = targetZone->getPlayer(); result << QString("%1|%2|%3|%4|%5|%6|%7|%8|%9").arg(player->getPlayerId()).arg(arrow->getId()).arg(startPlayer->getPlayerId()).arg(startZone->getName()).arg(startCard->getId()).arg(targetPlayer->getPlayerId()).arg(targetZone->getName()).arg(targetCard->getId()).arg(arrow->getColor()); } return result; } -ReturnMessage::ReturnCode ServerSocket::cmdDumpAll(const QList &/*params*/) +ReturnMessage::ReturnCode ServerSocket::cmdDumpAll(ServerGame *game, Player *player, const QList &/*params*/) { - remsg->sendList(listPlayersHelper(), "list_players"); + remsg->sendList(listPlayersHelper(game, player), "list_players"); if (game->getGameStarted()) { - const QList &players = game->getPlayers(); + const QList &players = game->getPlayers(); for (int i = 0; i < players.size(); ++i) { remsg->sendList(listZonesHelper(players[i]), "list_zones"); - const QList &zones = players[i]->getZones(); - for (int j = 0; j < zones.size(); ++j) - if ((zones[j]->getType() == PlayerZone::PublicZone) || ((zones[j]->getType() == PlayerZone::PrivateZone) && (playerId == players[i]->getPlayerId()))) - remsg->sendList(dumpZoneHelper(players[i], zones[j], -1), "dump_zone"); + QMapIterator zoneIterator(players[i]->getZones()); + while (zoneIterator.hasNext()) { + PlayerZone *zone = zoneIterator.next().value(); + if ((zone->getType() == PlayerZone::PublicZone) || ((zone->getType() == PlayerZone::PrivateZone) && (player == players[i]))) + remsg->sendList(dumpZoneHelper(players[i], zone, -1), "dump_zone"); + } remsg->sendList(listCountersHelper(players[i]), "list_counters"); remsg->sendList(listArrowsHelper(players[i]), "list_arrows"); @@ -919,14 +793,99 @@ ReturnMessage::ReturnCode ServerSocket::cmdDumpAll(const QList &/*para } remsg->send(ReturnMessage::ReturnOk); if (game->getGameStarted()) { - publicEvent(QString("set_active_player|%1").arg(game->getActivePlayer())); - publicEvent(QString("set_active_phase|%1").arg(game->getActivePhase())); + player->publicEvent(QString("set_active_player|%1").arg(game->getActivePlayer())); + player->publicEvent(QString("set_active_phase|%1").arg(game->getActivePhase())); } return ReturnMessage::ReturnNothing; } -bool ServerSocket::parseCommand(QString line) +QList ServerSocket::CommandProperties::getParamList(const QStringList ¶ms) const +{ + QList paramList; + if (paramList.size() != params.size()) + throw ReturnMessage::ReturnSyntaxError; + for (int j = 0; j < paramTypes.size(); j++) + switch (paramTypes[j]) { + case QVariant::String: { + paramList << QVariant(params[j]); + break; + } + case QVariant::Int: { + bool ok; + int temp = params[j].toInt(&ok); + if (!ok) + throw ReturnMessage::ReturnSyntaxError; + paramList << QVariant(temp); + break; + } + case QVariant::Bool: { + if (params[j] == "1") + paramList << QVariant(true); + else if (params[j] == "0") + paramList << QVariant(false); + else + throw ReturnMessage::ReturnSyntaxError; + break; + } + default: + paramList << QVariant(params[j]); + } + return paramList; +} + +ReturnMessage::ReturnCode ServerSocket::GenericCommandProperties::exec(ServerSocket *s, QStringList ¶ms) +{ + QList paramList; + try { paramList = getParamList(params); } + catch (ReturnMessage::ReturnCode rc) { return rc; } + + return (s->*handler)(paramList); +} + +ReturnMessage::ReturnCode ServerSocket::ChatCommandProperties::exec(ServerSocket *s, QStringList ¶ms) +{ + if (params.isEmpty()) + return ReturnMessage::ReturnSyntaxError; + QString channelName = params.takeFirst(); + ChatChannel *channel = s->getServer()->getChatChannels().value(channelName, 0); + if (!channel) + return ReturnMessage::ReturnNameNotFound; + + QList paramList; + try { paramList = getParamList(params); } + catch (ReturnMessage::ReturnCode rc) { return rc; } + + return (s->*handler)(channel, paramList); +} + +ReturnMessage::ReturnCode ServerSocket::GameCommandProperties::exec(ServerSocket *s, QStringList ¶ms) +{ + if (params.isEmpty()) + return ReturnMessage::ReturnSyntaxError; + bool ok; + int gameId = params.takeFirst().toInt(&ok); + if (!ok) + return ReturnMessage::ReturnSyntaxError; + QPair pair = s->getGame(gameId); + ServerGame *game = pair.first; + Player *player = pair.second; + if (!game) + return ReturnMessage::ReturnNameNotFound; + + if (!allowedToSpectator && player->getSpectator()) + return ReturnMessage::ReturnContextError; + if (needsStartedGame && !game->getGameStarted()) + return ReturnMessage::ReturnContextError; + + QList paramList; + try { paramList = getParamList(params); } + catch (ReturnMessage::ReturnCode rc) { return rc; } + + return (s->*handler)(game, player, paramList); +} + +bool ServerSocket::parseCommand(const QString &line) { QStringList params = line.split("|"); @@ -946,72 +905,22 @@ bool ServerSocket::parseCommand(QString line) // Extract command QString cmd = params.takeFirst(); - if (!commandHash.contains(cmd)) + CommandProperties *cp = commandHash.value(cmd, 0); + if (!cp) return remsg->send(ReturnMessage::ReturnSyntaxError); remsg->setCmd(cmd); - const CommandProperties &cp = commandHash[cmd]; - // Check login - if (cp.getNeedsLogin() && (authState == PasswordWrong)) + if (cp->getNeedsLogin() && (authState == PasswordWrong)) return remsg->send(ReturnMessage::ReturnLoginNeeded); - // Check context - if (!cp.getAllowedToSpectator() && spectator) - return remsg->send(ReturnMessage::ReturnContextError); - if (cp.getNeedsGame() && !game) - return remsg->send(ReturnMessage::ReturnContextError); - if (cp.getNeedsStartedGame() && !game->getGameStarted()) - return remsg->send(ReturnMessage::ReturnContextError); - // Validate parameters - if (cp.getParamTypes().size() != params.size()) - return remsg->send(ReturnMessage::ReturnSyntaxError); - QList paramList; - for (int j = 0; j < cp.getParamTypes().size(); j++) - switch (cp.getParamTypes()[j]) { - case QVariant::String: { - paramList << QVariant(params[j]); - break; - } - case QVariant::Int: { - bool ok; - int temp = params[j].toInt(&ok); - if (!ok) - return remsg->send(ReturnMessage::ReturnSyntaxError); - paramList << QVariant(temp); - break; - } - case QVariant::Bool: { - if (params[j] == "1") - paramList << QVariant(true); - else if (params[j] == "0") - paramList << QVariant(false); - else - return remsg->send(ReturnMessage::ReturnSyntaxError); - break; - } - default: - paramList << QVariant(params[j]); - } - // Call handler function - return remsg->send((this->*(cp.getHandler()))(paramList)); -} -void ServerSocket::privateEvent(const QString &line) -{ - msg(QString("private|%1|%2|%3").arg(playerId).arg(playerName).arg(line)); -} - -void ServerSocket::publicEvent(const QString &line, ServerSocket *player) -{ - if (player) - msg(QString("public|%1|%2|%3").arg(player->getPlayerId()).arg(player->getPlayerName()).arg(line)); - else - msg(QString("public|||%1").arg(line)); + // Validate parameters and call handler function + return remsg->send(cp->exec(this, params)); } void ServerSocket::msg(const QString &s) { - qDebug(QString("OUT id=%1 name=%2 >>> %3").arg(playerId).arg(playerName).arg(s).toLatin1()); + qDebug(QString("OUT >>> %3").arg(s).toLatin1()); QTextStream stream(this); stream.setCodec("UTF-8"); stream << s << endl; @@ -1030,3 +939,10 @@ void ServerSocket::catchSocketError(QAbstractSocket::SocketError socketError) deleteLater(); } + +QPair ServerSocket::getGame(int gameId) const +{ + if (games.contains(gameId)) + return games.value(gameId); + return QPair(0, 0); +} diff --git a/servatrice/src/serversocket.h b/servatrice/src/serversocket.h index 8b06047b..6526bbcc 100644 --- a/servatrice/src/serversocket.h +++ b/servatrice/src/serversocket.h @@ -28,12 +28,11 @@ class Server; class ServerGame; +class Player; class PlayerZone; class Counter; class Arrow; -enum PlayerStatusEnum { StatusNormal, StatusSubmitDeck, StatusReadyStart, StatusPlaying }; - class ServerSocket : public QTcpSocket { Q_OBJECT @@ -41,92 +40,112 @@ private slots: void readClient(); void catchSocketError(QAbstractSocket::SocketError socketError); signals: - 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(); private: - typedef ReturnMessage::ReturnCode (ServerSocket::*CommandHandler)(const QList &); + typedef ReturnMessage::ReturnCode (ServerSocket::*GameCommandHandler)(ServerGame *game, Player *player, const QList &); + typedef ReturnMessage::ReturnCode (ServerSocket::*ChatCommandHandler)(ChatChannel *channel, const QList &); + typedef ReturnMessage::ReturnCode (ServerSocket::*GenericCommandHandler)(const QList &); + class CommandProperties { + public: + enum CommandType { ChatCommand, GameCommand, GenericCommand }; private: + CommandType type; bool needsLogin; - bool needsGame; + QList paramTypes; + protected: + QList getParamList(const QStringList ¶ms) const; + public: + CommandProperties(CommandType _type, bool _needsLogin, const QList &_paramTypes) + : type(_type), needsLogin(_needsLogin), paramTypes(_paramTypes) { } + bool getNeedsLogin() const { return needsLogin; } + CommandType getType() const { return type; } + const QList &getParamTypes() const { return paramTypes; } + virtual ReturnMessage::ReturnCode exec(ServerSocket *s, QStringList ¶ms) = 0; + }; + class ChatCommandProperties : public CommandProperties { + private: + ChatCommandHandler handler; + public: + ChatCommandProperties(const QList &_paramTypes, ChatCommandHandler _handler) + : CommandProperties(ChatCommand, true, _paramTypes), handler(_handler) { } + ReturnMessage::ReturnCode exec(ServerSocket *s, QStringList ¶ms); + }; + class GameCommandProperties : public CommandProperties { + private: bool needsStartedGame; bool allowedToSpectator; - QList paramTypes; - CommandHandler handler; + GameCommandHandler handler; public: - CommandProperties(bool _needsLogin = false, bool _needsGame = false, bool _needsStartedGame = false, bool _allowedToSpectator = false, const QList &_paramTypes = QList(), CommandHandler _handler = 0) - : needsLogin(_needsLogin), needsGame(_needsGame), needsStartedGame(_needsStartedGame), allowedToSpectator(_allowedToSpectator), paramTypes(_paramTypes), handler(_handler) { } - bool getNeedsLogin() const { return needsLogin; } - bool getNeedsGame() const { return needsGame; } + GameCommandProperties(bool _needsStartedGame, bool _allowedToSpectator, const QList &_paramTypes, GameCommandHandler _handler) + : CommandProperties(GameCommand, true, _paramTypes), needsStartedGame(_needsStartedGame), allowedToSpectator(_allowedToSpectator), handler(_handler) { } bool getNeedsStartedGame() const { return needsStartedGame; } bool getAllowedToSpectator() const { return allowedToSpectator; } - const QList &getParamTypes() const { return paramTypes; } - CommandHandler getHandler() const { return handler; } + ReturnMessage::ReturnCode exec(ServerSocket *s, QStringList ¶ms); }; - static QHash commandHash; + class GenericCommandProperties : public CommandProperties { + private: + GenericCommandHandler handler; + public: + GenericCommandProperties(bool _needsLogin, const QList &_paramTypes, GenericCommandHandler _handler) + : CommandProperties(GenericCommand, _needsLogin, _paramTypes), handler(_handler) { } + ReturnMessage::ReturnCode exec(ServerSocket *s, QStringList ¶ms); + }; + static QHash commandHash; - QStringList listPlayersHelper(); - QStringList listZonesHelper(ServerSocket *player); - QStringList dumpZoneHelper(ServerSocket *player, PlayerZone *zone, int numberCards); - QStringList listCountersHelper(ServerSocket *player); - QStringList listArrowsHelper(ServerSocket *player); + QStringList listPlayersHelper(ServerGame *game, Player *player); + QStringList listZonesHelper(Player *player); + QStringList dumpZoneHelper(Player *player, PlayerZone *zone, int numberCards); + QStringList listCountersHelper(Player *player); + QStringList listArrowsHelper(Player *player); ReturnMessage::ReturnCode cmdPing(const QList ¶ms); ReturnMessage::ReturnCode cmdLogin(const QList ¶ms); ReturnMessage::ReturnCode cmdChatListChannels(const QList ¶ms); ReturnMessage::ReturnCode cmdChatJoinChannel(const QList ¶ms); - ReturnMessage::ReturnCode cmdChatLeaveChannel(const QList ¶ms); - ReturnMessage::ReturnCode cmdChatSay(const QList ¶ms); ReturnMessage::ReturnCode cmdListGames(const QList ¶ms); ReturnMessage::ReturnCode cmdCreateGame(const QList ¶ms); ReturnMessage::ReturnCode cmdJoinGame(const QList ¶ms); - ReturnMessage::ReturnCode cmdLeaveGame(const QList ¶ms); - ReturnMessage::ReturnCode cmdListPlayers(const QList ¶ms); - ReturnMessage::ReturnCode cmdSay(const QList ¶ms); - ReturnMessage::ReturnCode cmdSubmitDeck(const QList ¶ms); - ReturnMessage::ReturnCode cmdReadyStart(const QList ¶ms); - ReturnMessage::ReturnCode cmdShuffle(const QList ¶ms); - ReturnMessage::ReturnCode cmdDrawCards(const QList ¶ms); - ReturnMessage::ReturnCode cmdRevealCard(const QList ¶ms); - ReturnMessage::ReturnCode cmdMoveCard(const QList ¶ms); - ReturnMessage::ReturnCode cmdCreateToken(const QList ¶ms); - ReturnMessage::ReturnCode cmdCreateArrow(const QList ¶ms); - ReturnMessage::ReturnCode cmdDeleteArrow(const QList ¶ms); - ReturnMessage::ReturnCode cmdSetCardAttr(const QList ¶ms); - ReturnMessage::ReturnCode cmdIncCounter(const QList ¶ms); - ReturnMessage::ReturnCode cmdAddCounter(const QList ¶ms); - ReturnMessage::ReturnCode cmdSetCounter(const QList ¶ms); - ReturnMessage::ReturnCode cmdDelCounter(const QList ¶ms); - ReturnMessage::ReturnCode cmdListCounters(const QList ¶ms); - ReturnMessage::ReturnCode cmdListZones(const QList ¶ms); - ReturnMessage::ReturnCode cmdDumpZone(const QList ¶ms); - ReturnMessage::ReturnCode cmdStopDumpZone(const QList ¶ms); - ReturnMessage::ReturnCode cmdRollDie(const QList ¶ms); - ReturnMessage::ReturnCode cmdNextTurn(const QList ¶ms); - ReturnMessage::ReturnCode cmdSetActivePhase(const QList ¶ms); - ReturnMessage::ReturnCode cmdDumpAll(const QList ¶ms); + + ReturnMessage::ReturnCode cmdChatLeaveChannel(ChatChannel *channel, const QList ¶ms); + ReturnMessage::ReturnCode cmdChatSay(ChatChannel *channel, const QList ¶ms); + + ReturnMessage::ReturnCode cmdLeaveGame(ServerGame *game, Player *player, const QList ¶ms); + ReturnMessage::ReturnCode cmdListPlayers(ServerGame *game, Player *player, const QList ¶ms); + ReturnMessage::ReturnCode cmdSay(ServerGame *game, Player *player, const QList ¶ms); + ReturnMessage::ReturnCode cmdSubmitDeck(ServerGame *game, Player *player, const QList ¶ms); + ReturnMessage::ReturnCode cmdReadyStart(ServerGame *game, Player *player, const QList ¶ms); + ReturnMessage::ReturnCode cmdShuffle(ServerGame *game, Player *player, const QList ¶ms); + ReturnMessage::ReturnCode cmdDrawCards(ServerGame *game, Player *player, const QList ¶ms); + ReturnMessage::ReturnCode cmdRevealCard(ServerGame *game, Player *player, const QList ¶ms); + ReturnMessage::ReturnCode cmdMoveCard(ServerGame *game, Player *player, const QList ¶ms); + ReturnMessage::ReturnCode cmdCreateToken(ServerGame *game, Player *player, const QList ¶ms); + ReturnMessage::ReturnCode cmdCreateArrow(ServerGame *game, Player *player, const QList ¶ms); + ReturnMessage::ReturnCode cmdDeleteArrow(ServerGame *game, Player *player, const QList ¶ms); + ReturnMessage::ReturnCode cmdSetCardAttr(ServerGame *game, Player *player, const QList ¶ms); + ReturnMessage::ReturnCode cmdIncCounter(ServerGame *game, Player *player, const QList ¶ms); + ReturnMessage::ReturnCode cmdAddCounter(ServerGame *game, Player *player, const QList ¶ms); + ReturnMessage::ReturnCode cmdSetCounter(ServerGame *game, Player *player, const QList ¶ms); + ReturnMessage::ReturnCode cmdDelCounter(ServerGame *game, Player *player, const QList ¶ms); + ReturnMessage::ReturnCode cmdListCounters(ServerGame *game, Player *player, const QList ¶ms); + ReturnMessage::ReturnCode cmdListZones(ServerGame *game, Player *player, const QList ¶ms); + ReturnMessage::ReturnCode cmdDumpZone(ServerGame *game, Player *player, const QList ¶ms); + ReturnMessage::ReturnCode cmdStopDumpZone(ServerGame *game, Player *player, const QList ¶ms); + ReturnMessage::ReturnCode cmdRollDie(ServerGame *game, Player *player, const QList ¶ms); + ReturnMessage::ReturnCode cmdNextTurn(ServerGame *game, Player *player, const QList ¶ms); + ReturnMessage::ReturnCode cmdSetActivePhase(ServerGame *game, Player *player, const QList ¶ms); + ReturnMessage::ReturnCode cmdDumpAll(ServerGame *game, Player *player, const QList ¶ms); Server *server; - ServerGame *game; - QList chatChannels; - QList DeckList; - QList SideboardList; - QList zones; - QMap counters; - QMap arrows; - int playerId; + QMap > games; + QMap chatChannels; QString playerName; - bool spectator; - int nextCardId; - int newCardId(); - int newCounterId() const; - int newArrowId() const; - PlayerZone *getZone(const QString &name) const; - void clearZones(); - bool parseCommand(QString line); - PlayerStatusEnum PlayerStatus; + + Server *getServer() const { return server; } + QPair getGame(int gameId) const; + + bool parseCommand(const QString &line); ReturnMessage *remsg; AuthenticationResult authState; bool acceptsGameListChanges; @@ -135,24 +154,10 @@ public: ServerSocket(Server *_server, QObject *parent = 0); ~ServerSocket(); void msg(const QString &s); - void privateEvent(const QString &line); - void publicEvent(const QString &line, ServerSocket *player = 0); - void setGame(ServerGame *g) { game = g; } - void leaveGame(); - PlayerStatusEnum getStatus() { return PlayerStatus; } - void setStatus(PlayerStatusEnum _status) { PlayerStatus = _status; } 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; } - const QList &getZones() const { return zones; } - const QMap &getCounters() const { return counters; } - const QMap &getArrows() const { return arrows; } - bool deleteArrow(int arrowId); - void setupZones(); + const QString &getPlayerName() const { return playerName; } }; #endif