From a543c9b90c47c22901546fc574bd8d9c310ca960 Mon Sep 17 00:00:00 2001 From: Max-Wilhelm Bruker Date: Thu, 24 Sep 2009 20:12:44 +0200 Subject: [PATCH] final (?) spectator code, small bugfix --- cockatrice/src/carditem.cpp | 2 +- cockatrice/src/client.cpp | 124 +++++++++++++++++------- cockatrice/src/client.h | 65 +++++++++---- cockatrice/src/game.cpp | 80 ++++++++++++++-- cockatrice/src/game.h | 7 ++ cockatrice/src/gameselector.cpp | 22 ++++- cockatrice/src/gameselector.h | 7 +- cockatrice/src/gamesmodel.cpp | 59 ++++++++---- cockatrice/src/gamesmodel.h | 23 +++-- cockatrice/src/messagelogwidget.cpp | 6 ++ cockatrice/src/messagelogwidget.h | 1 + cockatrice/src/player.h | 4 +- cockatrice/src/window_main.cpp | 2 + cockatrice/src/zoneviewlayout.cpp | 2 +- servatrice/src/returnmessage.cpp | 5 +- servatrice/src/returnmessage.h | 2 +- servatrice/src/server.cpp | 27 +----- servatrice/src/server.h | 6 +- servatrice/src/servergame.cpp | 34 ++++--- servatrice/src/servergame.h | 9 +- servatrice/src/serversocket.cpp | 143 ++++++++++++++++++++-------- servatrice/src/serversocket.h | 13 ++- 22 files changed, 453 insertions(+), 190 deletions(-) diff --git a/cockatrice/src/carditem.cpp b/cockatrice/src/carditem.cpp index b75a86ee..ccb21a22 100644 --- a/cockatrice/src/carditem.cpp +++ b/cockatrice/src/carditem.cpp @@ -248,7 +248,7 @@ void CardItem::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event) if (zone->getName() == "table") ((TableZone *) zone)->toggleTapped(); else { - TableZone *table = (TableZone *) zone->getPlayer()->getZones()->findZone("table"); + TableZone *table = (TableZone *) zone->getPlayer()->getZones().findZone("table"); QPoint gridPoint = table->getFreeGridPoint(info->getTableRow()); table->handleDropEventByGrid(id, zone, gridPoint, false); } diff --git a/cockatrice/src/client.cpp b/cockatrice/src/client.cpp index 08a5247a..5885f249 100644 --- a/cockatrice/src/client.cpp +++ b/cockatrice/src/client.cpp @@ -11,9 +11,9 @@ ServerEventData::ServerEventData(const QString &line) if (eventHash.isEmpty()) { eventHash.insert("player_id", eventPlayerId); eventHash.insert("say", eventSay); - eventHash.insert("name", eventName); eventHash.insert("join", eventJoin); eventHash.insert("leave", eventLeave); + eventHash.insert("game_closed", eventGameClosed); eventHash.insert("ready_start", eventReadyStart); eventHash.insert("setup_zones", eventSetupZones); eventHash.insert("game_start", eventGameStart); @@ -35,7 +35,10 @@ ServerEventData::ServerEventData(const QString &line) QStringList values = line.split('|'); IsPublic = !values.takeFirst().compare("public"); - PlayerId = values.takeFirst().toInt(); + bool ok = false; + PlayerId = values.takeFirst().toInt(&ok); + if (!ok) + PlayerId = -1; PlayerName = values.takeFirst(); EventType = eventHash.value(values.takeFirst(), eventInvalid); EventData = values; @@ -84,11 +87,6 @@ void PendingCommand_ListPlayers::responseReceived(ServerResponse resp) PendingCommand::responseReceived(resp); } -void PendingCommand_ListPlayers::addPlayer(const ServerPlayer &player) -{ - playerList.append(player); -} - void PendingCommand_ListZones::responseReceived(ServerResponse resp) { if (resp == RespOk) @@ -96,11 +94,6 @@ void PendingCommand_ListZones::responseReceived(ServerResponse resp) PendingCommand::responseReceived(resp); } -void PendingCommand_ListZones::addZone(const ServerZone &zone) -{ - zoneList.append(zone); -} - void PendingCommand_DumpZone::responseReceived(ServerResponse resp) { if (resp == RespOk) @@ -108,11 +101,6 @@ void PendingCommand_DumpZone::responseReceived(ServerResponse resp) PendingCommand::responseReceived(resp); } -void PendingCommand_DumpZone::addCard(const ServerZoneCard &card) -{ - cardList.append(card); -} - void PendingCommand_ListCounters::responseReceived(ServerResponse resp) { if (resp == RespOk) @@ -120,9 +108,15 @@ void PendingCommand_ListCounters::responseReceived(ServerResponse resp) PendingCommand::responseReceived(resp); } -void PendingCommand_ListCounters::addCounter(const ServerCounter &counter) +void PendingCommand_DumpAll::responseReceived(ServerResponse resp) { - counterList.append(counter); + if (resp == RespOk) { + emit playerListReceived(playerList); + emit zoneListReceived(zoneList); + emit cardListReceived(cardList); + emit counterListReceived(counterList); + } + PendingCommand::responseReceived(resp); } Client::Client(QObject *parent) @@ -238,9 +232,11 @@ void Client::readLine() resp = RespErr; pc->responseReceived(resp); } else if (prefix == "list_games") { - if (values.size() != 8) + if (values.size() != 8) { + emit protocolError(); continue; - emit gameListEvent(new ServerGame(values[0].toInt(), values[5], values[1], values[2].toInt(), values[3].toInt(), values[4].toInt(), values[6].toInt(), values[7].toInt())); + } + emit gameListEvent(ServerGame(values[0].toInt(), values[5], values[1], values[2].toInt(), values[3].toInt(), values[4].toInt(), values[6].toInt(), values[7].toInt())); } else if (prefix == "welcome") { if (values.size() != 2) { emit protocolError(); @@ -259,37 +255,84 @@ void Client::readLine() continue; } int cmdid = values.takeFirst().toInt(); - PendingCommand_ListPlayers *pc = qobject_cast(pendingCommands.value(cmdid, 0)); - if (!pc) { - emit protocolError(); - continue; + PendingCommand *pc = pendingCommands.value(cmdid, 0); + ServerPlayer sp(values[0].toInt(), values[1], values[2].toInt()); + + PendingCommand_ListPlayers *pcLP = qobject_cast(pc); + if (pcLP) + pcLP->addPlayer(sp); + else { + PendingCommand_DumpAll *pcDA = qobject_cast(pc); + if (pcDA) + pcDA->addPlayer(sp); + else + emit protocolError(); } - pc->addPlayer(ServerPlayer(values[0].toInt(), values[1], values[2].toInt())); } else if (prefix == "dump_zone") { - if (values.size() != 9) { + if (values.size() != 11) { emit protocolError(); continue; } int cmdid = values.takeFirst().toInt(); - PendingCommand_DumpZone *pc = qobject_cast(pendingCommands.value(cmdid, 0)); - if (!pc) { + PendingCommand *pc = pendingCommands.value(cmdid, 0); + ServerZoneCard szc(values[0].toInt(), values[1], values[2].toInt(), values[3], values[4].toInt(), values[5].toInt(), values[6].toInt(), values[7] == "1", values[8] == "1", values[9]); + + PendingCommand_DumpZone *pcDZ = qobject_cast(pc); + if (pcDZ) + pcDZ->addCard(szc); + else { + PendingCommand_DumpAll *pcDA = qobject_cast(pc); + if (pcDA) + pcDA->addCard(szc); + else + emit protocolError(); + } + } else if (prefix == "list_zones") { + if (values.size() != 6) { emit protocolError(); continue; } - pc->addCard(ServerZoneCard(values[0].toInt(), values[1], values[2].toInt(), values[3].toInt(), values[4].toInt(), values[5] == "1", values[6] == "1", values[7])); - } else if (prefix == "list_zones") { + int cmdid = values.takeFirst().toInt(); + PendingCommand *pc = pendingCommands.value(cmdid, 0); + ServerZone::ZoneType type; + if (values[2] == "private") + type = ServerZone::PrivateZone; + else if (values[2] == "hidden") + type = ServerZone::HiddenZone; + else + type = ServerZone::PublicZone; + ServerZone sz(values[0].toInt(), values[1], type, values[3] == "1", values[4].toInt()); + + PendingCommand_ListZones *pcLZ = qobject_cast(pc); + if (pcLZ) + pcLZ->addZone(sz); + else { + PendingCommand_DumpAll *pcDA = qobject_cast(pc); + if (pcDA) + pcDA->addZone(sz); + else + emit protocolError(); + } + } else if (prefix == "list_counters") { if (values.size() != 5) { emit protocolError(); continue; } int cmdid = values.takeFirst().toInt(); - PendingCommand_ListZones *pc = qobject_cast(pendingCommands.value(cmdid, 0)); - if (!pc) { - emit protocolError(); - continue; + PendingCommand *pc = pendingCommands.value(cmdid, 0); + int colorValue = values[2].toInt(); + ServerCounter sc(values[0].toInt(), values[1], QColor(colorValue / 65536, (colorValue % 65536) / 256, colorValue % 256), values[3].toInt()); + + PendingCommand_ListCounters *pcLC = qobject_cast(pc); + if (pcLC) + pcLC->addCounter(sc); + else { + PendingCommand_DumpAll *pcDA = qobject_cast(pc); + if (pcDA) + pcDA->addCounter(sc); + else + emit protocolError(); } - pc->addZone(ServerZone(values[0], values[1] == "1", values[2] == "1", values[3].toInt())); - } else if (prefix == "list_counters") { } else emit protocolError(); } @@ -520,3 +563,10 @@ PendingCommand *Client::stopDumpZone(int player, const QString &zone) { return cmd(QString("stop_dump_zone|%1|%2").arg(player).arg(zone)); } + +PendingCommand_DumpAll *Client::dumpAll() +{ + PendingCommand_DumpAll *pc = new PendingCommand_DumpAll; + cmd("dump_all", pc); + return pc; +} diff --git a/cockatrice/src/client.h b/cockatrice/src/client.h index 869e294c..2ae447d8 100644 --- a/cockatrice/src/client.h +++ b/cockatrice/src/client.h @@ -28,9 +28,9 @@ enum ServerEventType { eventInvalid, eventPlayerId, eventSay, - eventName, eventJoin, eventLeave, + eventGameClosed, eventReadyStart, eventSetupZones, eventGameStart, @@ -100,7 +100,7 @@ private: bool spectatorsAllowed; unsigned int spectatorsCount; public: - ServerGame(int _gameId, const QString &_creator, const QString &_description, bool _hasPassword, unsigned char _playerCount, unsigned char _maxPlayers, bool _spectatorsAllowed, unsigned int _spectatorsCount) + ServerGame(int _gameId = -1, const QString &_creator = QString(), const QString &_description = QString(), bool _hasPassword = false, unsigned char _playerCount = 0, unsigned char _maxPlayers = 0, bool _spectatorsAllowed = false, unsigned int _spectatorsCount = 0) : gameId(_gameId), creator(_creator), description(_description), hasPassword(_hasPassword), playerCount(_playerCount), maxPlayers(_maxPlayers), spectatorsAllowed(_spectatorsAllowed), spectatorsCount(_spectatorsCount) { } int getGameId() const { return gameId; } QString getCreator() const { return creator; } @@ -127,6 +127,8 @@ public: class ServerZoneCard { private: + int playerId; + QString zoneName; int id; QString name; int x, y; @@ -135,8 +137,10 @@ private: bool attacking; QString annotation; public: - ServerZoneCard(int _id, const QString &_name, int _x, int _y, int _counters, bool _tapped, bool _attacking, const QString &_annotation) - : id(_id), name(_name), x(_x), y(_y), counters(_counters), tapped(_tapped), attacking(_attacking), annotation(_annotation) { } + ServerZoneCard(int _playerId, const QString &_zoneName, int _id, const QString &_name, int _x, int _y, int _counters, bool _tapped, bool _attacking, const QString &_annotation) + : playerId(_playerId), zoneName(_zoneName), id(_id), name(_name), x(_x), y(_y), counters(_counters), tapped(_tapped), attacking(_attacking), annotation(_annotation) { } + int getPlayerId() const { return playerId; } + QString getZoneName() const { return zoneName; } int getId() const { return id; } QString getName() const { return name; } int getX() const { return x; } @@ -148,30 +152,36 @@ public: }; class ServerZone { +public: + enum ZoneType { PrivateZone, PublicZone, HiddenZone }; private: + int playerId; QString name; - bool isPublic; + ZoneType type; bool hasCoords; int cardCount; public: - ServerZone(const QString &_name, bool _isPublic, bool _hasCoords, int _cardCount) - : name(_name), isPublic(_isPublic), hasCoords(_hasCoords), cardCount(_cardCount) { } + ServerZone(int _playerId, const QString &_name, ZoneType _type, bool _hasCoords, int _cardCount) + : playerId(_playerId), name(_name), type(_type), hasCoords(_hasCoords), cardCount(_cardCount) { } + int getPlayerId() const { return playerId; } QString getName() const { return name; } - bool getPublic() const { return isPublic; } + ZoneType getType() const { return type; } bool getHasCoords() const { return hasCoords; } int getCardCount() const { return cardCount; } }; class ServerCounter { private: + int playerId; QString name; - int color; + QColor color; int count; public: - ServerCounter(const QString &_name, int _color, int _count) - : name(_name), color(_color), count(_count) { } + ServerCounter(int _playerId, const QString &_name, QColor _color, int _count) + : playerId(_playerId), name(_name), color(_color), count(_count) { } + int getPlayerId() const { return playerId; } QString getName() const { return name; } - int getColor() const { return color; } + QColor getColor() const { return color; } int getCount() const { return count; } }; @@ -210,7 +220,7 @@ signals: void playerListReceived(QList _playerList); public: void responseReceived(ServerResponse resp); - void addPlayer(const ServerPlayer &player); + void addPlayer(const ServerPlayer &player) { playerList.append(player); } }; class PendingCommand_ListZones : public PendingCommand { @@ -224,7 +234,7 @@ public: PendingCommand_ListZones(int _playerId) : playerId(_playerId) { } void responseReceived(ServerResponse resp); - void addZone(const ServerZone &zone); + void addZone(const ServerZone &zone) { zoneList.append(zone); } int getPlayerId() const { return playerId; } }; @@ -241,7 +251,7 @@ public: PendingCommand_DumpZone(int _playerId, const QString &_zoneName, int _numberCards) : playerId(_playerId), zoneName(_zoneName), numberCards(_numberCards) { } void responseReceived(ServerResponse resp); - void addCard(const ServerZoneCard &card); + void addCard(const ServerZoneCard &card) { cardList.append(card); } int getPlayerId() const { return playerId; } QString getZoneName() const { return zoneName; } int getNumberCards() const { return numberCards; } @@ -258,16 +268,36 @@ public: PendingCommand_ListCounters(int _playerId) : playerId(_playerId) { } void responseReceived(ServerResponse resp); - void addCounter(const ServerCounter &counter); + void addCounter(const ServerCounter &counter) { counterList.append(counter); } int getPlayerId() const { return playerId; } }; +class PendingCommand_DumpAll : public PendingCommand { + Q_OBJECT +private: + QList playerList; + QList zoneList; + QList cardList; + QList counterList; +signals: + void playerListReceived(QList _playerList); + void zoneListReceived(QList _zoneList); + void cardListReceived(QList _cardList); + void counterListReceived(QList _counterList); +public: + void responseReceived(ServerResponse resp); + void addPlayer(const ServerPlayer &player) { playerList.append(player); } + void addZone(const ServerZone &zone) { zoneList.append(zone); } + void addCard(const ServerZoneCard &card) { cardList.append(card); } + void addCounter(const ServerCounter &counter) { counterList.append(counter); } +}; + class Client : public QObject { Q_OBJECT signals: void statusChanged(ProtocolStatus _status); void welcomeMsgReceived(QString welcomeMsg); - void gameListEvent(ServerGame *game); + void gameListEvent(const ServerGame &game); void playerIdReceived(int id, QString name); void gameEvent(const ServerEventData &msg); void chatEvent(const ChatEventData &msg); @@ -335,6 +365,7 @@ public slots: PendingCommand_ListZones *listZones(int playerId); PendingCommand_DumpZone *dumpZone(int player, const QString &zone, int numberCards); PendingCommand *stopDumpZone(int player, const QString &zone); + PendingCommand_DumpAll *dumpAll(); void submitDeck(const QStringList &deck); }; diff --git a/cockatrice/src/game.cpp b/cockatrice/src/game.cpp index a1260ed8..340cb143 100644 --- a/cockatrice/src/game.cpp +++ b/cockatrice/src/game.cpp @@ -78,9 +78,6 @@ Game::Game(CardDatabase *_db, Client *_client, GameScene *_scene, QMenuBar *menu connect(dlgStartGame, SIGNAL(finished(int)), this, SLOT(readyStart())); retranslateUi(); - - PendingCommand_ListPlayers *pc = client->listPlayers(); - connect(pc, SIGNAL(playerListReceived(QList)), this, SLOT(playerListReceived(QList))); } Game::~Game() @@ -141,6 +138,59 @@ Player *Game::addPlayer(int playerId, const QString &playerName, bool local) return newPlayer; } +void Game::cardListReceived(QList list) +{ + for (int i = 0; i < list.size(); ++i) { + Player *p = players.findPlayer(list[i].getPlayerId()); + if (!p) + continue; + CardZone *zone = p->getZones().findZone(list[i].getZoneName()); + if (!zone) + continue; + + CardItem *card = new CardItem(db, list[i].getName(), list[i].getId()); + zone->addCard(card, false, list[i].getX(), list[i].getY()); + + card->setCounters(list[i].getCounters()); + card->setTapped(list[i].getTapped()); + card->setAttacking(list[i].getAttacking()); + card->setAnnotation(list[i].getAnnotation()); + } +} + +void Game::zoneListReceived(QList list) +{ + for (int i = 0; i < list.size(); ++i) { + Player *p = players.findPlayer(list[i].getPlayerId()); + if (!p) + continue; + CardZone *zone = p->getZones().findZone(list[i].getName()); + if (!zone) + continue; + zone->clearContents(); + if ( + (list[i].getType() != ServerZone::PublicZone) + && !((list[i].getType() == ServerZone::PrivateZone) && p->getLocal()) + ) { + for (int j = 0; j < list[i].getCardCount(); ++j) + zone->addCard(new CardItem(db), false, -1); + zone->reorganizeCards(); + } + } +} + +void Game::counterListReceived(QList list) +{ + for (int i = 0; i < players.size(); ++i) + players[i]->clearCounters(); + + for (int i = 0; i < list.size(); ++i) { + Player *p = players.findPlayer(list[i].getPlayerId()); + if (p) + p->addCounter(list[i].getName(), list[i].getColor(), list[i].getCount()); + } +} + void Game::playerListReceived(QList playerList) { QStringList nameList; @@ -171,8 +221,9 @@ void Game::gameEvent(const ServerEventData &msg) return; p->gameEvent(msg); } else { - if ((!p) && (msg.getEventType() != eventJoin)) { - // XXX + if ((msg.getPlayerId() != -1) && (!p) && (msg.getEventType() != eventJoin) && (msg.getEventType() != eventLeave)) { + qDebug("Game::gameEvent: invalid player"); + return; } switch(msg.getEventType()) { @@ -206,6 +257,11 @@ void Game::gameEvent(const ServerEventData &msg) } break; } + case eventGameClosed: { + started = false; + emit logGameClosed(); + break; + } case eventReadyStart: if (started) { started = false; @@ -251,7 +307,6 @@ void Game::gameEvent(const ServerEventData &msg) break; } - case eventName: case eventCreateToken: case eventSetupZones: case eventSetCardAttr: @@ -267,7 +322,7 @@ void Game::gameEvent(const ServerEventData &msg) Player *zoneOwner = players.findPlayer(data[0].toInt()); if (!zoneOwner) break; - CardZone *zone = zoneOwner->getZones()->findZone(data[1]); + CardZone *zone = zoneOwner->getZones().findZone(data[1]); if (!zone) break; emit logDumpZone(p, zone, data[2].toInt()); @@ -278,7 +333,7 @@ void Game::gameEvent(const ServerEventData &msg) Player *zoneOwner = players.findPlayer(data[0].toInt()); if (!zoneOwner) break; - CardZone *zone = zoneOwner->getZones()->findZone(data[1]); + CardZone *zone = zoneOwner->getZones().findZone(data[1]); if (!zone) break; emit logStopDumpZone(p, zone); @@ -415,3 +470,12 @@ void Game::hoverCardEvent(CardItem *card) { emit hoverCard(card->getName()); } + +void Game::queryGameState() +{ + PendingCommand_DumpAll *pc = client->dumpAll(); + connect(pc, SIGNAL(playerListReceived(QList)), this, SLOT(playerListReceived(QList))); + connect(pc, SIGNAL(zoneListReceived(QList)), this, SLOT(zoneListReceived(QList))); + connect(pc, SIGNAL(cardListReceived(QList)), this, SLOT(cardListReceived(QList))); + connect(pc, SIGNAL(counterListReceived(QList)), this, SLOT(counterListReceived(QList))); +} diff --git a/cockatrice/src/game.h b/cockatrice/src/game.h index ee53d047..7ce5ee7a 100644 --- a/cockatrice/src/game.h +++ b/cockatrice/src/game.h @@ -55,7 +55,12 @@ private slots: void actMoveToExile(CardItem *card); void gameEvent(const ServerEventData &msg); + void playerListReceived(QList playerList); + void cardListReceived(QList list); + void zoneListReceived(QList list); + void counterListReceived(QList list); + void readyStart(); signals: void submitDecklist(); @@ -67,6 +72,7 @@ signals: void logPlayerListReceived(QStringList players); void logJoin(Player *player); void logLeave(Player *player); + void logGameClosed(); void logJoinSpectator(QString playerName); void logLeaveSpectator(QString playerName); void logReadyStart(Player *player); @@ -92,6 +98,7 @@ public: void restartGameDialog(); void hoverCardEvent(CardItem *card); Player *addPlayer(int playerId, const QString &playerName, bool local); + void queryGameState(); }; #endif diff --git a/cockatrice/src/gameselector.cpp b/cockatrice/src/gameselector.cpp index 82a8e48c..3892d7da 100644 --- a/cockatrice/src/gameselector.cpp +++ b/cockatrice/src/gameselector.cpp @@ -1,18 +1,23 @@ #include #include "gameselector.h" #include "dlg_creategame.h" +#include "gamesmodel.h" GameSelector::GameSelector(Client *_client, QWidget *parent) : QWidget(parent), client(_client) { gameListView = new QTreeView; gameListModel = new GamesModel(this); - gameListView->setModel(gameListModel); + gameListProxyModel = new GamesProxyModel(this); + gameListProxyModel->setSourceModel(gameListModel); + gameListView->setModel(gameListProxyModel); + showFullGamesCheckBox = new QCheckBox; createButton = new QPushButton; joinButton = new QPushButton; spectateButton = new QPushButton; QHBoxLayout *buttonLayout = new QHBoxLayout; + buttonLayout->addWidget(showFullGamesCheckBox); buttonLayout->addStretch(); buttonLayout->addWidget(createButton); buttonLayout->addWidget(joinButton); @@ -28,11 +33,17 @@ GameSelector::GameSelector(Client *_client, QWidget *parent) setMinimumWidth(gameListView->columnWidth(0) * gameListModel->columnCount()); setMinimumHeight(400); + connect(showFullGamesCheckBox, SIGNAL(stateChanged(int)), this, SLOT(showFullGamesChanged(int))); connect(createButton, SIGNAL(clicked()), this, SLOT(actCreate())); connect(joinButton, SIGNAL(clicked()), this, SLOT(actJoin())); connect(spectateButton, SIGNAL(clicked()), this, SLOT(actJoin())); } +void GameSelector::showFullGamesChanged(int state) +{ + gameListProxyModel->setFullGamesVisible(state); +} + void GameSelector::actCreate() { DlgCreateGame dlg(client, this); @@ -66,16 +77,16 @@ void GameSelector::actJoin() QModelIndex ind = gameListView->currentIndex(); if (!ind.isValid()) return; - ServerGame *game = gameListModel->getGame(ind.row()); + const ServerGame &game = gameListModel->getGame(ind.row()); QString password; - if (game->getHasPassword()) { + if (game.getHasPassword()) { bool ok; password = QInputDialog::getText(this, tr("Join game"), tr("Password:"), QLineEdit::Password, QString(), &ok); if (!ok) return; } - PendingCommand *joinCommand = client->joinGame(game->getGameId(), password, spectator); + PendingCommand *joinCommand = client->joinGame(game.getGameId(), password, spectator); connect(joinCommand, SIGNAL(finished(ServerResponse)), this, SLOT(checkResponse(ServerResponse))); createButton->setEnabled(false); joinButton->setEnabled(false); @@ -87,7 +98,7 @@ void GameSelector::enableGameList() if (isVisible()) return; - connect(client, SIGNAL(gameListEvent(ServerGame *)), gameListModel, SLOT(updateGameList(ServerGame *))); + connect(client, SIGNAL(gameListEvent(const ServerGame &)), gameListModel, SLOT(updateGameList(const ServerGame &))); client->listGames(); show(); } @@ -104,6 +115,7 @@ void GameSelector::disableGameList() void GameSelector::retranslateUi() { + showFullGamesCheckBox->setText(tr("&Show full games")); createButton->setText(tr("C&reate")); joinButton->setText(tr("&Join")); spectateButton->setText(tr("J&oin as spectator")); diff --git a/cockatrice/src/gameselector.h b/cockatrice/src/gameselector.h index ccca733d..7cc21d55 100644 --- a/cockatrice/src/gameselector.h +++ b/cockatrice/src/gameselector.h @@ -2,11 +2,13 @@ #define GAMESELECTOR_H #include -#include "gamesmodel.h" #include "client.h" class QPushButton; +class QCheckBox; class QTreeView; +class GamesModel; +class GamesProxyModel; class GameSelector : public QWidget { Q_OBJECT @@ -16,6 +18,7 @@ public: void disableGameList(); void retranslateUi(); private slots: + void showFullGamesChanged(int state); void actCreate(); void actRefresh(); void actJoin(); @@ -25,7 +28,9 @@ private: QTreeView *gameListView; GamesModel *gameListModel; + GamesProxyModel *gameListProxyModel; QPushButton *createButton, *joinButton, *spectateButton; + QCheckBox *showFullGamesCheckBox; }; #endif diff --git a/cockatrice/src/gamesmodel.cpp b/cockatrice/src/gamesmodel.cpp index 534c026f..0a76c0cf 100644 --- a/cockatrice/src/gamesmodel.cpp +++ b/cockatrice/src/gamesmodel.cpp @@ -13,13 +13,13 @@ QVariant GamesModel::data(const QModelIndex &index, int role) const if ((index.row() >= gameList.size()) || (index.column() >= columnCount())) return QVariant(); - ServerGame *g = gameList.at(index.row()); + const ServerGame &g = gameList[index.row()]; switch (index.column()) { - case 0: return g->getDescription(); - case 1: return g->getCreator(); - case 2: return g->getHasPassword() ? tr("yes") : tr("no"); - case 3: return QString("%1/%2").arg(g->getPlayerCount()).arg(g->getMaxPlayers()); - case 4: return g->getSpectatorsAllowed() ? QVariant(g->getSpectatorsCount()) : QVariant(tr("not allowed")); + case 0: return g.getDescription(); + case 1: return g.getCreator(); + case 2: return g.getHasPassword() ? tr("yes") : tr("no"); + case 3: return QString("%1/%2").arg(g.getPlayerCount()).arg(g.getMaxPlayers()); + case 4: return g.getSpectatorsAllowed() ? QVariant(g.getSpectatorsCount()) : QVariant(tr("not allowed")); default: return QVariant(); } } @@ -38,29 +38,27 @@ QVariant GamesModel::headerData(int section, Qt::Orientation orientation, int ro } } -ServerGame *GamesModel::getGame(int row) +const ServerGame &GamesModel::getGame(int row) { - if (row >= gameList.size()) - return 0; + Q_ASSERT(row < gameList.size()); return gameList[row]; } -void GamesModel::updateGameList(ServerGame *game) +void GamesModel::updateGameList(const ServerGame &game) { for (int i = 0; i < gameList.size(); i++) - if (gameList[i]->getGameId() == game->getGameId()) { - if ((game->getPlayerCount() == 0) || (game->getPlayerCount() == game->getMaxPlayers())) { + if (gameList[i].getGameId() == game.getGameId()) { + if (game.getPlayerCount() == 0) { beginRemoveRows(QModelIndex(), i, i); - delete gameList.takeAt(i); + gameList.removeAt(i); endRemoveRows(); } else { - delete gameList[i]; gameList[i] = game; emit dataChanged(index(i, 0), index(i, 4)); } return; } - if ((game->getPlayerCount() == 0) || (game->getPlayerCount() == game->getMaxPlayers())) + if (game.getPlayerCount() == 0) return; beginInsertRows(QModelIndex(), gameList.size(), gameList.size()); gameList << game; @@ -73,9 +71,34 @@ void GamesModel::cleanList() return; beginRemoveRows(QModelIndex(), 0, gameList.size() - 1); - QListIterator i(gameList); - while (i.hasNext()) - delete i.next(); gameList.clear(); endRemoveRows(); } + +GamesProxyModel::GamesProxyModel(QObject *parent) + : QSortFilterProxyModel(parent), fullGamesVisible(false) +{ + setDynamicSortFilter(true); +} + +void GamesProxyModel::setFullGamesVisible(bool _fullGamesVisible) +{ + fullGamesVisible = _fullGamesVisible; + invalidateFilter(); +} + +bool GamesProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex &/*sourceParent*/) const +{ + if (fullGamesVisible) + return true; + + GamesModel *model = qobject_cast(sourceModel()); + if (!model) + return false; + + const ServerGame &game = model->getGame(sourceRow); + if (game.getPlayerCount() == game.getMaxPlayers()) + return false; + + return true; +} diff --git a/cockatrice/src/gamesmodel.h b/cockatrice/src/gamesmodel.h index 57c603db..2cadc91a 100644 --- a/cockatrice/src/gamesmodel.h +++ b/cockatrice/src/gamesmodel.h @@ -1,10 +1,10 @@ #ifndef GAMESMODEL_H #define GAMESMODEL_H -#include +#include +#include #include - -class ServerGame; +#include "client.h" class GamesModel : public QAbstractTableModel { Q_OBJECT @@ -16,12 +16,23 @@ public: QVariant data(const QModelIndex &index, int role) const; QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; - ServerGame *getGame(int row); + const ServerGame &getGame(int row); void cleanList(); public slots: - void updateGameList(ServerGame *game); + void updateGameList(const ServerGame &game); private: - QList gameList; + QList gameList; +}; + +class GamesProxyModel : public QSortFilterProxyModel { + Q_OBJECT +private: + bool fullGamesVisible; +public: + GamesProxyModel(QObject *parent = 0); + void setFullGamesVisible(bool _fullGamesVisible); +protected: + bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const; }; #endif diff --git a/cockatrice/src/messagelogwidget.cpp b/cockatrice/src/messagelogwidget.cpp index 29bd5daa..492c702b 100644 --- a/cockatrice/src/messagelogwidget.cpp +++ b/cockatrice/src/messagelogwidget.cpp @@ -69,6 +69,11 @@ void MessageLogWidget::logLeave(Player *player) append(tr("%1 has left the game").arg(sanitizeHtml(player->getName()))); } +void MessageLogWidget::logGameClosed() +{ + append(tr("The game has been closed.")); +} + void MessageLogWidget::logJoinSpectator(QString name) { append(tr("%1 is now watching the game.").arg(sanitizeHtml(name))); @@ -264,6 +269,7 @@ void MessageLogWidget::connectToGame(Game *game) connect(game, SIGNAL(logPlayerListReceived(QStringList)), this, SLOT(logPlayerListReceived(QStringList))); connect(game, SIGNAL(logJoin(Player *)), this, SLOT(logJoin(Player *))); connect(game, SIGNAL(logLeave(Player *)), this, SLOT(logLeave(Player *))); + connect(game, SIGNAL(logGameClosed()), this, SLOT(logGameClosed())); connect(game, SIGNAL(logJoinSpectator(QString)), this, SLOT(logJoinSpectator(QString))); connect(game, SIGNAL(logLeaveSpectator(QString)), this, SLOT(logLeaveSpectator(QString))); connect(game, SIGNAL(logReadyStart(Player *)), this, SLOT(logReadyStart(Player *))); diff --git a/cockatrice/src/messagelogwidget.h b/cockatrice/src/messagelogwidget.h index d3c17b63..507ae575 100644 --- a/cockatrice/src/messagelogwidget.h +++ b/cockatrice/src/messagelogwidget.h @@ -27,6 +27,7 @@ private slots: void logPlayerListReceived(QStringList players); void logJoin(Player *player); void logLeave(Player *player); + void logGameClosed(); void logJoinSpectator(QString name); void logLeaveSpectator(QString name); void logReadyStart(Player *player); diff --git a/cockatrice/src/player.h b/cockatrice/src/player.h index 622d718d..142a6170 100644 --- a/cockatrice/src/player.h +++ b/cockatrice/src/player.h @@ -4,6 +4,7 @@ #include #include #include "zonelist.h" +#include "client.h" class Client; class CardDatabase; @@ -14,7 +15,6 @@ class Game; class Counter; class TableZone; class HandZone; -class ServerEventData; class Player : public QObject, public QGraphicsItem { Q_OBJECT @@ -103,7 +103,7 @@ public: int getId() const { return id; } QString getName() const { return name; } bool getLocal() const { return local; } - const ZoneList *getZones() const { return &zones; } + const ZoneList &getZones() const { return zones; } void gameEvent(const ServerEventData &event); CardDatabase *getDb() const { return db; } void showCardMenu(const QPoint &p); diff --git a/cockatrice/src/window_main.cpp b/cockatrice/src/window_main.cpp index fc37292d..8a81c755 100644 --- a/cockatrice/src/window_main.cpp +++ b/cockatrice/src/window_main.cpp @@ -97,6 +97,8 @@ void MainWindow::statusChanged(ProtocolStatus _status) aRestartGame->setEnabled(true); aLeaveGame->setEnabled(true); + game->queryGameState(); + phasesToolbar->show(); view->show(); break; diff --git a/cockatrice/src/zoneviewlayout.cpp b/cockatrice/src/zoneviewlayout.cpp index 48e70465..f3676c4c 100644 --- a/cockatrice/src/zoneviewlayout.cpp +++ b/cockatrice/src/zoneviewlayout.cpp @@ -45,7 +45,7 @@ void ZoneViewLayout::toggleZoneView(Player *player, const QString &zoneName, int } } - ZoneViewWidget *item = new ZoneViewWidget(db, player, player->getZones()->findZone(zoneName), numberCards, this); + ZoneViewWidget *item = new ZoneViewWidget(db, player, player->getZones().findZone(zoneName), numberCards, this); views.append(item); connect(item, SIGNAL(closePressed(ZoneViewWidget *)), this, SLOT(removeItem(ZoneViewWidget *))); connect(item, SIGNAL(sizeChanged()), this, SLOT(reorganize())); diff --git a/servatrice/src/returnmessage.cpp b/servatrice/src/returnmessage.cpp index b16a21ca..0d3c92f5 100644 --- a/servatrice/src/returnmessage.cpp +++ b/servatrice/src/returnmessage.cpp @@ -22,14 +22,15 @@ bool ReturnMessage::send(ReturnCode code) return (code == ReturnOk); } -bool ReturnMessage::sendList(const QStringList &args) +bool ReturnMessage::sendList(const QStringList &args, const QString &prefix) { ServerSocket *s = qobject_cast(parent()); if (!s) return false; + QString arg1 = prefix.isEmpty() ? cmd : prefix; for (int i = 0; i < args.size(); i++) - s->msg(QString("%1|%2|%3").arg(cmd) + s->msg(QString("%1|%2|%3").arg(arg1) .arg(msg_id) .arg(args[i])); return true; diff --git a/servatrice/src/returnmessage.h b/servatrice/src/returnmessage.h index 2cfd9a30..12f2b015 100644 --- a/servatrice/src/returnmessage.h +++ b/servatrice/src/returnmessage.h @@ -15,7 +15,7 @@ public: void setMsgId(unsigned int _msg_id) { msg_id = _msg_id; } void setCmd(const QString &_cmd) { cmd = _cmd; } bool send(ReturnCode code); - bool sendList(const QStringList &args); + bool sendList(const QStringList &args, const QString &prefix = QString()); }; #endif diff --git a/servatrice/src/server.cpp b/servatrice/src/server.cpp index 35624915..32aabfb4 100644 --- a/servatrice/src/server.cpp +++ b/servatrice/src/server.cpp @@ -88,7 +88,7 @@ bool Server::openDatabase() void Server::addGame(const QString description, const QString password, int maxPlayers, bool spectatorsAllowed, ServerSocket *creator) { ServerGame *newGame = new ServerGame(creator, nextGameId++, description, password, maxPlayers, spectatorsAllowed, this); - games << newGame; + games.insert(newGame->getGameId(), newGame); connect(newGame, SIGNAL(gameClosing()), this, SLOT(gameClosing())); newGame->addPlayer(creator, false); @@ -131,28 +131,9 @@ AuthenticationResult Server::checkUserPassword(const QString &user, const QStrin return UnknownUser; } -ServerGame *Server::getGame(int gameId) +ServerGame *Server::getGame(int gameId) const { - QListIterator i(games); - while (i.hasNext()) { - ServerGame *tmp = i.next(); - if ((tmp->getGameId() == gameId) && !tmp->getGameStarted()) - return tmp; - } - return NULL; -} - -QList Server::listOpenGames() -{ - QList result; - QListIterator i(games); - while (i.hasNext()) { - ServerGame *tmp = i.next(); - if ((!tmp->getGameStarted()) - && (tmp->getPlayerCount() < tmp->getMaxPlayers())) - result.append(tmp); - } - return result; + return games.value(gameId); } void Server::broadcastGameListUpdate(ServerGame *game) @@ -175,7 +156,7 @@ void Server::broadcastChannelUpdate() void Server::gameClosing() { qDebug("Server::gameClosing"); - games.removeAt(games.indexOf(static_cast(sender()))); + games.remove(games.key(static_cast(sender()))); } void Server::removePlayer(ServerSocket *player) diff --git a/servatrice/src/server.h b/servatrice/src/server.h index 03225bb9..4e6df611 100644 --- a/servatrice/src/server.h +++ b/servatrice/src/server.h @@ -45,16 +45,16 @@ public: QSettings *settings; bool openDatabase(); AuthenticationResult checkUserPassword(const QString &user, const QString &password); - QList listOpenGames(); + QList getGames() const { return games.values(); } + ServerGame *getGame(int gameId) const; QList getChatChannelList() { return chatChannelList; } - ServerGame *getGame(int gameId); AbstractRNG *getRNG() const { return rng; } void broadcastGameListUpdate(ServerGame *game); void removePlayer(ServerSocket *player); const QStringList &getLoginMessage() const { return loginMessage; } private: void incomingConnection(int SocketId); - QList games; + QMap games; QList players; QList chatChannelList; int nextGameId; diff --git a/servatrice/src/servergame.cpp b/servatrice/src/servergame.cpp index f9936a87..fd1cc506 100644 --- a/servatrice/src/servergame.cpp +++ b/servatrice/src/servergame.cpp @@ -29,6 +29,15 @@ ServerGame::ServerGame(ServerSocket *_creator, int _gameId, const QString &_desc ServerGame::~ServerGame() { + broadcastEvent("game_closed", 0); + + for (int i = 0; i < players.size(); ++i) + players[i]->leaveGame(); + players.clear(); + for (int i = 0; i < spectators.size(); ++i) + spectators[i]->leaveGame(); + spectators.clear(); + emit gameClosing(); qDebug("ServerGame destructor"); } @@ -37,15 +46,17 @@ QString ServerGame::getGameListLine() const { if (players.isEmpty()) return QString("list_games|%1|||0|%2||0").arg(gameId).arg(maxPlayers); - else + else { + QString creatorName = creator ? creator->getPlayerName() : QString(); 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(creatorName) .arg(spectatorsAllowed ? 1 : 0) .arg(spectators.size()); + } } ServerSocket *ServerGame::getPlayer(int playerId) @@ -59,20 +70,11 @@ ServerSocket *ServerGame::getPlayer(int playerId) return NULL; } -void ServerGame::msg(const QString &s) +void ServerGame::broadcastEvent(const QString &eventStr, ServerSocket *player) { - for (int i = 0; i < players.size(); ++i) - players[i]->msg(s); - for (int i = 0; i < spectators.size(); ++i) - spectators[i]->msg(s); -} - -void ServerGame::broadcastEvent(const QString &cmd, ServerSocket *player) -{ - if (player) - msg(QString("public|%1|%2|%3").arg(player->getPlayerId()).arg(player->getPlayerName()).arg(cmd)); - else - msg(QString("public|||%1").arg(cmd)); + QList allClients = QList() << players << spectators; + for (int i = 0; i < allClients.size(); ++i) + allClients[i]->publicEvent(eventStr, player); } void ServerGame::startGameIfReady() @@ -152,6 +154,8 @@ void ServerGame::removePlayer(ServerSocket *player) else players.removeAt(players.indexOf(player)); broadcastEvent("leave", player); + disconnect(player, 0, this, 0); + if (!players.size()) deleteLater(); if (!gameStarted) diff --git a/servatrice/src/servergame.h b/servatrice/src/servergame.h index f7f02953..7ba666ff 100644 --- a/servatrice/src/servergame.h +++ b/servatrice/src/servergame.h @@ -21,14 +21,14 @@ #define SERVERGAME_H #include +#include #include "returnmessage.h" - -class ServerSocket; +#include "serversocket.h" class ServerGame : public QObject { Q_OBJECT private: - ServerSocket *creator; + QPointer creator; QList players; QList spectators; bool gameStarted; @@ -41,7 +41,7 @@ private: signals: void gameClosing(); public slots: - void broadcastEvent(const QString &event, ServerSocket *player); + 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(); @@ -60,7 +60,6 @@ public: void addPlayer(ServerSocket *player, bool spectator); void removePlayer(ServerSocket *player); void startGameIfReady(); - void msg(const QString &s); int getActivePlayer() const { return activePlayer; } int getActivePhase() const { return activePhase; } void setActivePlayer(int _activePlayer); diff --git a/servatrice/src/serversocket.cpp b/servatrice/src/serversocket.cpp index ff75842b..20c42352 100644 --- a/servatrice/src/serversocket.cpp +++ b/servatrice/src/serversocket.cpp @@ -116,6 +116,7 @@ ServerSocket::ServerSocket(Server *_server, QObject *parent) commandHash.insert("next_turn", CommandProperties(true, true, true, false, QList(), &ServerSocket::cmdNextTurn)); commandHash.insert("set_active_phase", CommandProperties(true, true, true, false, QList() << QVariant::Int, &ServerSocket::cmdSetActivePhase)); + commandHash.insert("dump_all", CommandProperties(true, true, false, true, QList(), &ServerSocket::cmdDumpAll)); } remsg = new ReturnMessage(this); @@ -323,10 +324,9 @@ ReturnMessage::ReturnCode ServerSocket::cmdChatSay(const QList ¶ms ReturnMessage::ReturnCode ServerSocket::cmdListGames(const QList &/*params*/) { - QList gameList = server->listOpenGames(); - QListIterator gameListIterator(gameList); - while (gameListIterator.hasNext()) - msg(gameListIterator.next()->getGameListLine()); + const QList &gameList = server->getGames(); + for (int i = 0; i < gameList.size(); ++i) + msg(gameList[i]->getGameListLine()); acceptsGameListChanges = true; return ReturnMessage::ReturnOk; @@ -375,14 +375,18 @@ ReturnMessage::ReturnCode ServerSocket::cmdLeaveGame(const QList &/*pa return ReturnMessage::ReturnOk; } -ReturnMessage::ReturnCode ServerSocket::cmdListPlayers(const QList &/*params*/) +QStringList ServerSocket::listPlayersHelper() { QStringList result; 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); - - remsg->sendList(result); + return result; +} + +ReturnMessage::ReturnCode ServerSocket::cmdListPlayers(const QList &/*params*/) +{ + remsg->sendList(listPlayersHelper()); return ReturnMessage::ReturnOk; } @@ -632,6 +636,15 @@ ReturnMessage::ReturnCode ServerSocket::cmdDelCounter(const QList &par return ReturnMessage::ReturnOk; } +QStringList ServerSocket::listCountersHelper(ServerSocket *player) +{ + QStringList result; + const QList &counterList = player->getCounters(); + for (int i = 0; i < counterList.size(); ++i) + result << QString("%1|%2|%3|%4").arg(player->getPlayerId()).arg(counterList[i]->getName()).arg(counterList[i]->getColor()).arg(counterList[i]->getCount()); + return result; +} + ReturnMessage::ReturnCode ServerSocket::cmdListCounters(const QList ¶ms) { int player_id = params[0].toInt(); @@ -639,15 +652,27 @@ ReturnMessage::ReturnCode ServerSocket::cmdListCounters(const QList &p if (!player) return ReturnMessage::ReturnContextError; - QStringList result; - const QList &counterList = player->getCounters(); - for (int i = 0; i < counterList.size(); ++i) - result << QString("%1|%2|%3").arg(counterList[i]->getName()).arg(counterList[i]->getColor()).arg(counterList[i]->getCount()); - - remsg->sendList(result); + remsg->sendList(listCountersHelper(player)); return ReturnMessage::ReturnOk; } +QStringList ServerSocket::listZonesHelper(ServerSocket *player) +{ + QStringList result; + const QList &zoneList = player->getZones(); + for (int i = 0; i < zoneList.size(); ++i) { + QString typeStr; + switch (zoneList[i]->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()); + } + return result; +} + ReturnMessage::ReturnCode ServerSocket::cmdListZones(const QList ¶ms) { int player_id = params[0].toInt(); @@ -655,14 +680,36 @@ ReturnMessage::ReturnCode ServerSocket::cmdListZones(const QList ¶ if (!player) return ReturnMessage::ReturnContextError; - QStringList result; - const QList &zoneList = player->getZones(); - for (int i = 0; i < zoneList.size(); ++i) - result << QString("%1|%2|%3|%4").arg(zoneList[i]->getName()).arg(zoneList[i]->getType() == PlayerZone::PublicZone ? 1 : 0).arg(zoneList[i]->hasCoords()).arg(zoneList[i]->cards.size()); - remsg->sendList(result); + remsg->sendList(listZonesHelper(player)); return ReturnMessage::ReturnOk; } +QStringList ServerSocket::dumpZoneHelper(ServerSocket *player, PlayerZone *zone, int number_cards) +{ + QListIterator card_iterator(zone->cards); + QStringList result; + for (int i = 0; card_iterator.hasNext() && (i < number_cards || number_cards == -1); i++) { + Card *tmp = card_iterator.next(); + // XXX Face down cards + if (zone->getType() != PlayerZone::HiddenZone) + result << QString("%1|%2|%3|%4|%5|%6|%7|%8|%9|%10").arg(player->getPlayerId()) + .arg(zone->getName()) + .arg(tmp->getId()) + .arg(tmp->getName()) + .arg(tmp->getX()) + .arg(tmp->getY()) + .arg(tmp->getCounters()) + .arg(tmp->getTapped()) + .arg(tmp->getAttacking()) + .arg(tmp->getAnnotation()); + else { + zone->setCardsBeingLookedAt(number_cards); + result << QString("%1|%2|%3|%4||||||").arg(player->getPlayerId()).arg(zone->getName()).arg(i).arg(tmp->getName()); + } + } + return result; +} + ReturnMessage::ReturnCode ServerSocket::cmdDumpZone(const QList ¶ms) { int player_id = params[0].toInt(); @@ -675,28 +722,11 @@ ReturnMessage::ReturnCode ServerSocket::cmdDumpZone(const QList ¶m return ReturnMessage::ReturnContextError; if (!((zone->getType() == PlayerZone::PublicZone) || (player_id == playerId))) return ReturnMessage::ReturnContextError; - - QListIterator card_iterator(zone->cards); - QStringList result; - for (int i = 0; card_iterator.hasNext() && (i < number_cards || number_cards == -1); i++) { - Card *tmp = card_iterator.next(); - // XXX Face down cards - if (zone->getType() != PlayerZone::HiddenZone) - result << QString("%1|%2|%3|%4|%5|%6|%7|%8").arg(tmp->getId()) - .arg(tmp->getName()) - .arg(tmp->getX()) - .arg(tmp->getY()) - .arg(tmp->getCounters()) - .arg(tmp->getTapped()) - .arg(tmp->getAttacking()) - .arg(tmp->getAnnotation()); - else { - zone->setCardsBeingLookedAt(number_cards); - result << QString("%1|%2||||||").arg(i).arg(tmp->getName()); - } - } - emit broadcastEvent(QString("dump_zone|%1|%2|%3").arg(player_id).arg(zone->getName()).arg(number_cards), this); - remsg->sendList(result); + + if (zone->getType() == PlayerZone::HiddenZone) + emit broadcastEvent(QString("dump_zone|%1|%2|%3").arg(player_id).arg(zone->getName()).arg(number_cards), this); + + remsg->sendList(dumpZoneHelper(player, zone, number_cards)); return ReturnMessage::ReturnOk; } @@ -742,6 +772,32 @@ ReturnMessage::ReturnCode ServerSocket::cmdSetActivePhase(const QList return ReturnMessage::ReturnOk; } +ReturnMessage::ReturnCode ServerSocket::cmdDumpAll(const QList &/*params*/) +{ + remsg->sendList(listPlayersHelper(), "list_players"); + + if (game->getGameStarted()) { + 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"); + + remsg->sendList(listCountersHelper(players[i]), "list_counters"); + } + } + 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())); + } + + return ReturnMessage::ReturnNothing; +} + bool ServerSocket::parseCommand(QString line) { QStringList params = line.split("|"); @@ -817,9 +873,12 @@ void ServerSocket::privateEvent(const QString &line) msg(QString("private|%1|%2|%3").arg(playerId).arg(playerName).arg(line)); } -void ServerSocket::setGame(ServerGame *g) +void ServerSocket::publicEvent(const QString &line, ServerSocket *player) { - game = g; + if (player) + msg(QString("public|%1|%2|%3").arg(player->getPlayerId()).arg(player->getPlayerName()).arg(line)); + else + msg(QString("public|||%1").arg(line)); } void ServerSocket::msg(const QString &s) diff --git a/servatrice/src/serversocket.h b/servatrice/src/serversocket.h index 5cf73339..ed51df5b 100644 --- a/servatrice/src/serversocket.h +++ b/servatrice/src/serversocket.h @@ -66,6 +66,11 @@ private: }; static QHash commandHash; + QStringList listPlayersHelper(); + QStringList listZonesHelper(ServerSocket *player); + QStringList dumpZoneHelper(ServerSocket *player, PlayerZone *zone, int numberCards); + QStringList listCountersHelper(ServerSocket *player); + ReturnMessage::ReturnCode cmdPing(const QList ¶ms); ReturnMessage::ReturnCode cmdLogin(const QList ¶ms); ReturnMessage::ReturnCode cmdChatListChannels(const QList ¶ms); @@ -97,6 +102,7 @@ private: ReturnMessage::ReturnCode cmdRollDie(const QList ¶ms); ReturnMessage::ReturnCode cmdNextTurn(const QList ¶ms); ReturnMessage::ReturnCode cmdSetActivePhase(const QList ¶ms); + ReturnMessage::ReturnCode cmdDumpAll(const QList ¶ms); Server *server; ServerGame *game; @@ -113,9 +119,7 @@ private: PlayerZone *getZone(const QString &name) const; Counter *getCounter(const QString &name) const; void clearZones(); - void leaveGame(); bool parseCommand(QString line); - void privateEvent(const QString &line); PlayerStatusEnum PlayerStatus; ReturnMessage *remsg; AuthenticationResult authState; @@ -125,7 +129,10 @@ public: ServerSocket(Server *_server, QObject *parent = 0); ~ServerSocket(); void msg(const QString &s); - void setGame(ServerGame *g); + 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();