From 628f58cd564b9446c62fd4e3ef5509ab6634725c Mon Sep 17 00:00:00 2001 From: Max-Wilhelm Bruker Date: Wed, 26 May 2010 17:33:44 +0200 Subject: [PATCH 1/6] fixed bug #0000012 --- common/server_game.h | 2 +- common/server_protocolhandler.cpp | 20 ++++++++++++++------ 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/common/server_game.h b/common/server_game.h index 3cfbf542..50456cd0 100644 --- a/common/server_game.h +++ b/common/server_game.h @@ -54,7 +54,7 @@ public: bool getGameStarted() const { return gameStarted; } int getPlayerCount() const; int getSpectatorCount() const; - QList getPlayers() const { return players.values(); } + const QMap &getPlayers() const { return players; } Server_Player *getPlayer(int playerId) const { return players.value(playerId, 0); } int getGameId() const { return gameId; } QString getDescription() const { return description; } diff --git a/common/server_protocolhandler.cpp b/common/server_protocolhandler.cpp index 133dfba0..b4e5dc02 100644 --- a/common/server_protocolhandler.cpp +++ b/common/server_protocolhandler.cpp @@ -208,7 +208,7 @@ ResponseCode Server_ProtocolHandler::cmdLogin(Command_Login *cmd, CommandContain // This might not scale very well. Use an extra QMap if it becomes a problem. const QList &serverGames = server->getGames(); for (int i = 0; i < serverGames.size(); ++i) { - const QList &gamePlayers = serverGames[i]->getPlayers(); + const QList &gamePlayers = serverGames[i]->getPlayers().values(); for (int j = 0; j < gamePlayers.size(); ++j) if (gamePlayers[j]->getPlayerName() == playerName) { gamePlayers[j]->setProtocolHandler(this); @@ -530,7 +530,7 @@ ResponseCode Server_ProtocolHandler::moveCard(Server_Game *game, Server_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().values(); for (int i = 0; i < players.size(); ++i) { QList arrowsToDelete; QMapIterator arrowIterator(players[i]->getArrows()); @@ -709,11 +709,19 @@ ResponseCode Server_ProtocolHandler::cmdNextTurn(Command_NextTurn * /*cmd*/, Com { if (!game->getGameStarted()) return RespGameNotStarted; - + + const QMap &players = game->getPlayers(); + const QList keys = players.keys(); + int activePlayer = game->getActivePlayer(); - if (++activePlayer == game->getPlayerCount()) - activePlayer = 0; - game->setActivePlayer(activePlayer); + int listPos = keys.indexOf(activePlayer); + do { + ++listPos; + if (listPos == keys.size()) + listPos = 0; + } while (players.value(keys[listPos])->getSpectator()); + + game->setActivePlayer(keys[listPos]); return RespOk; } From befafa28ae6519e95b8225757bbcf9b460d24db8 Mon Sep 17 00:00:00 2001 From: Max-Wilhelm Bruker Date: Wed, 26 May 2010 21:36:54 +0200 Subject: [PATCH 2/6] Fixed elevation of spectator rights; added some spectator options; closes bug 0000005 --- cockatrice/src/dlg_creategame.cpp | 41 +++-- cockatrice/src/dlg_creategame.h | 9 +- cockatrice/src/gamesmodel.cpp | 4 +- cockatrice/src/handzone.cpp | 4 +- cockatrice/src/handzone.h | 2 +- cockatrice/src/messagelogwidget.cpp | 7 +- cockatrice/src/messagelogwidget.h | 1 + cockatrice/src/player.cpp | 2 +- cockatrice/src/tab_game.cpp | 25 ++- cockatrice/src/tab_game.h | 8 +- cockatrice/src/tab_server.cpp | 2 +- cockatrice/src/tab_supervisor.cpp | 2 +- cockatrice/translations/cockatrice_de.ts | 185 ++++++++++++---------- cockatrice/translations/cockatrice_en.ts | 187 +++++++++++++---------- common/protocol.cpp | 9 +- common/protocol.h | 3 + common/protocol_datastructures.cpp | 3 +- common/protocol_datastructures.h | 3 +- common/protocol_items.cpp | 9 +- common/protocol_items.dat | 4 +- common/protocol_items.h | 9 +- common/server.cpp | 5 +- common/server.h | 2 +- common/server_game.cpp | 23 ++- common/server_game.h | 11 +- common/server_protocolhandler.cpp | 90 +++++++++-- 26 files changed, 430 insertions(+), 220 deletions(-) diff --git a/cockatrice/src/dlg_creategame.cpp b/cockatrice/src/dlg_creategame.cpp index 76a1ce2e..fe59fefa 100644 --- a/cockatrice/src/dlg_creategame.cpp +++ b/cockatrice/src/dlg_creategame.cpp @@ -14,11 +14,25 @@ DlgCreateGame::DlgCreateGame(Client *_client, QWidget *parent) passwordLabel->setBuddy(passwordEdit); maxPlayersLabel = new QLabel(tr("P&layers:")); - maxPlayersEdit = new QLineEdit("2"); + maxPlayersEdit = new QSpinBox(); + maxPlayersEdit->setMinimum(1); + maxPlayersEdit->setMaximum(100); + maxPlayersEdit->setValue(2); maxPlayersLabel->setBuddy(maxPlayersEdit); spectatorsAllowedCheckBox = new QCheckBox(tr("&Spectators allowed")); spectatorsAllowedCheckBox->setChecked(true); + connect(spectatorsAllowedCheckBox, SIGNAL(stateChanged(int)), this, SLOT(spectatorsAllowedChanged(int))); + spectatorsNeedPasswordCheckBox = new QCheckBox(tr("Spectators &need a password to join")); + spectatorsCanTalkCheckBox = new QCheckBox(tr("Spectators can &talk")); + spectatorsSeeEverythingCheckBox = new QCheckBox(tr("Spectators see &everything")); + QVBoxLayout *spectatorsLayout = new QVBoxLayout; + spectatorsLayout->addWidget(spectatorsAllowedCheckBox); + spectatorsLayout->addWidget(spectatorsNeedPasswordCheckBox); + spectatorsLayout->addWidget(spectatorsCanTalkCheckBox); + spectatorsLayout->addWidget(spectatorsSeeEverythingCheckBox); + spectatorsGroupBox = new QGroupBox(tr("Spectators")); + spectatorsGroupBox->setLayout(spectatorsLayout); QGridLayout *grid = new QGridLayout; grid->addWidget(descriptionLabel, 0, 0); @@ -27,7 +41,7 @@ DlgCreateGame::DlgCreateGame(Client *_client, QWidget *parent) grid->addWidget(passwordEdit, 1, 1); grid->addWidget(maxPlayersLabel, 2, 0); grid->addWidget(maxPlayersEdit, 2, 1); - grid->addWidget(spectatorsAllowedCheckBox, 3, 0, 1, 2); + grid->addWidget(spectatorsGroupBox, 3, 0, 1, 2); okButton = new QPushButton(tr("&OK")); okButton->setDefault(true); @@ -53,13 +67,15 @@ DlgCreateGame::DlgCreateGame(Client *_client, QWidget *parent) void DlgCreateGame::actOK() { - bool ok; - int maxPlayers = maxPlayersEdit->text().toInt(&ok); - if (!ok) { - QMessageBox::critical(this, tr("Error"), tr("Invalid number of players.")); - return; - } - Command_CreateGame *createCommand = new Command_CreateGame(descriptionEdit->text(), passwordEdit->text(), maxPlayers, spectatorsAllowedCheckBox->isChecked()); + Command_CreateGame *createCommand = new Command_CreateGame( + descriptionEdit->text(), + passwordEdit->text(), + maxPlayersEdit->value(), + spectatorsAllowedCheckBox->isChecked(), + spectatorsNeedPasswordCheckBox->isChecked(), + spectatorsCanTalkCheckBox->isChecked(), + spectatorsSeeEverythingCheckBox->isChecked() + ); connect(createCommand, SIGNAL(finished(ResponseCode)), this, SLOT(checkResponse(ResponseCode))); client->sendCommand(createCommand); @@ -79,3 +95,10 @@ void DlgCreateGame::checkResponse(ResponseCode response) return; } } + +void DlgCreateGame::spectatorsAllowedChanged(int state) +{ + spectatorsNeedPasswordCheckBox->setEnabled(state); + spectatorsCanTalkCheckBox->setEnabled(state); + spectatorsSeeEverythingCheckBox->setEnabled(state); +} diff --git a/cockatrice/src/dlg_creategame.h b/cockatrice/src/dlg_creategame.h index 8ca34b77..529e4b22 100644 --- a/cockatrice/src/dlg_creategame.h +++ b/cockatrice/src/dlg_creategame.h @@ -8,6 +8,8 @@ class QLabel; class QLineEdit; class QPushButton; class QCheckBox; +class QGroupBox; +class QSpinBox; class DlgCreateGame : public QDialog { Q_OBJECT @@ -16,12 +18,15 @@ public: private slots: void actOK(); void checkResponse(ResponseCode response); + void spectatorsAllowedChanged(int state); private: Client *client; + QGroupBox *spectatorsGroupBox; QLabel *descriptionLabel, *passwordLabel, *maxPlayersLabel; - QLineEdit *descriptionEdit, *passwordEdit, *maxPlayersEdit; - QCheckBox *spectatorsAllowedCheckBox; + QLineEdit *descriptionEdit, *passwordEdit; + QSpinBox *maxPlayersEdit; + QCheckBox *spectatorsAllowedCheckBox, *spectatorsNeedPasswordCheckBox, *spectatorsCanTalkCheckBox, *spectatorsSeeEverythingCheckBox; QPushButton *okButton, *cancelButton; }; diff --git a/cockatrice/src/gamesmodel.cpp b/cockatrice/src/gamesmodel.cpp index 365d461f..14c45ea5 100644 --- a/cockatrice/src/gamesmodel.cpp +++ b/cockatrice/src/gamesmodel.cpp @@ -27,7 +27,7 @@ QVariant GamesModel::data(const QModelIndex &index, int role) const switch (index.column()) { case 0: return g->getDescription(); case 1: return g->getCreatorName(); - case 2: return g->getHasPassword() ? tr("yes") : tr("no"); + case 2: return g->getHasPassword() ? (g->getSpectatorsNeedPassword() ? tr("yes") : tr("yes, free for spectators")) : tr("no"); case 3: return QString("%1/%2").arg(g->getPlayerCount()).arg(g->getMaxPlayers()); case 4: return g->getSpectatorsAllowed() ? QVariant(g->getSpectatorCount()) : QVariant(tr("not allowed")); default: return QVariant(); @@ -56,7 +56,7 @@ ServerInfo_Game *GamesModel::getGame(int row) void GamesModel::updateGameList(ServerInfo_Game *_game) { - ServerInfo_Game *game = new ServerInfo_Game(_game->getGameId(), _game->getDescription(), _game->getHasPassword(), _game->getPlayerCount(), _game->getMaxPlayers(), _game->getCreatorName(), _game->getSpectatorsAllowed(), _game->getSpectatorCount()); + ServerInfo_Game *game = new ServerInfo_Game(_game->getGameId(), _game->getDescription(), _game->getHasPassword(), _game->getPlayerCount(), _game->getMaxPlayers(), _game->getCreatorName(), _game->getSpectatorsAllowed(), _game->getSpectatorsNeedPassword(), _game->getSpectatorCount()); for (int i = 0; i < gameList.size(); i++) if (gameList[i]->getGameId() == game->getGameId()) { if (game->getPlayerCount() == 0) { diff --git a/cockatrice/src/handzone.cpp b/cockatrice/src/handzone.cpp index 648464a0..3e1f269d 100644 --- a/cockatrice/src/handzone.cpp +++ b/cockatrice/src/handzone.cpp @@ -5,8 +5,8 @@ #include "protocol_items.h" #include "settingscache.h" -HandZone::HandZone(Player *_p, int _zoneHeight, QGraphicsItem *parent) - : CardZone(_p, "hand", false, false, _p->getLocal(), parent), zoneHeight(_zoneHeight) +HandZone::HandZone(Player *_p, bool _contentsKnown, int _zoneHeight, QGraphicsItem *parent) + : CardZone(_p, "hand", false, false, _contentsKnown, parent), zoneHeight(_zoneHeight) { connect(settingsCache, SIGNAL(handBgPathChanged()), this, SLOT(updateBgPixmap())); updateBgPixmap(); diff --git a/cockatrice/src/handzone.h b/cockatrice/src/handzone.h index 65d920e9..f784da56 100644 --- a/cockatrice/src/handzone.h +++ b/cockatrice/src/handzone.h @@ -11,7 +11,7 @@ private: private slots: void updateBgPixmap(); public: - HandZone(Player *_p, int _zoneHeight, QGraphicsItem *parent = 0); + HandZone(Player *_p, bool _contentsKnown, int _zoneHeight, QGraphicsItem *parent = 0); QRectF boundingRect() const; void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); void reorganizeCards(); diff --git a/cockatrice/src/messagelogwidget.cpp b/cockatrice/src/messagelogwidget.cpp index 9fec0356..443782c8 100644 --- a/cockatrice/src/messagelogwidget.cpp +++ b/cockatrice/src/messagelogwidget.cpp @@ -104,7 +104,12 @@ void MessageLogWidget::logGameStart() void MessageLogWidget::logSay(Player *player, QString message) { - append(QString("%1: %2").arg(sanitizeHtml(player->getName())).arg(sanitizeHtml(message))); + append(QString("%1: %2").arg(sanitizeHtml(player->getName())).arg(sanitizeHtml(message))); +} + +void MessageLogWidget::logSpectatorSay(QString spectatorName, QString message) +{ + append(QString("%1: %2").arg(sanitizeHtml(spectatorName)).arg(sanitizeHtml(message))); } void MessageLogWidget::logShuffle(Player *player) diff --git a/cockatrice/src/messagelogwidget.h b/cockatrice/src/messagelogwidget.h index 61af628b..f8ba59d2 100644 --- a/cockatrice/src/messagelogwidget.h +++ b/cockatrice/src/messagelogwidget.h @@ -33,6 +33,7 @@ public slots: void logConcede(Player *player); void logGameStart(); void logSay(Player *player, QString message); + void logSpectatorSay(QString spectatorName, QString message); void logShuffle(Player *player); void logRollDie(Player *player, int sides, int roll); void logDrawCards(Player *player, int number); diff --git a/cockatrice/src/player.cpp b/cockatrice/src/player.cpp index 311c9cf2..973872be 100644 --- a/cockatrice/src/player.cpp +++ b/cockatrice/src/player.cpp @@ -43,7 +43,7 @@ Player::Player(const QString &_name, int _id, bool _local, Client *_client, TabG table = new TableZone(this, this); connect(table, SIGNAL(sizeChanged()), this, SLOT(updateBoundingRect())); - hand = new HandZone(this, (int) table->boundingRect().height(), this); + hand = new HandZone(this, _local || (_parent->getSpectator() && _parent->getSpectatorsSeeEverything()), (int) table->boundingRect().height(), this); base = QPointF(deck->boundingRect().width() + counterAreaWidth + 5, 0); hand->setPos(base); diff --git a/cockatrice/src/tab_game.cpp b/cockatrice/src/tab_game.cpp index 9c15e915..9ebbe998 100644 --- a/cockatrice/src/tab_game.cpp +++ b/cockatrice/src/tab_game.cpp @@ -19,8 +19,8 @@ #include "arrowitem.h" #include "main.h" -TabGame::TabGame(Client *_client, int _gameId, const QString &_gameDescription, int _localPlayerId, bool _spectator, bool _resuming) - : Tab(), client(_client), gameId(_gameId), gameDescription(_gameDescription), localPlayerId(_localPlayerId), spectator(_spectator), started(false), resuming(_resuming), currentPhase(-1) +TabGame::TabGame(Client *_client, int _gameId, const QString &_gameDescription, int _localPlayerId, bool _spectator, bool _spectatorsCanTalk, bool _spectatorsSeeEverything, bool _resuming) + : Tab(), client(_client), gameId(_gameId), gameDescription(_gameDescription), localPlayerId(_localPlayerId), spectator(_spectator), spectatorsCanTalk(_spectatorsCanTalk), spectatorsSeeEverything(_spectatorsSeeEverything), started(false), resuming(_resuming), currentPhase(-1) { scene = new GameScene(this); gameView = new GameView(scene); @@ -74,8 +74,10 @@ TabGame::TabGame(Client *_client, int _gameId, const QString &_gameDescription, mainLayout->addLayout(verticalLayout); if (spectator) { - sayLabel->hide(); - sayEdit->hide(); + if (!spectatorsCanTalk) { + sayLabel->hide(); + sayEdit->hide(); + } loadLocalButton->hide(); loadRemoteButton->hide(); readyStartButton->hide(); @@ -226,7 +228,15 @@ void TabGame::processGameEventContainer(GameEventContainer *cont) for (int i = 0; i < eventList.size(); ++i) { GameEvent *event = eventList[i]; - switch (event->getItemId()) { + if (spectators.contains(event->getPlayerId())) { + switch (event->getItemId()) { + case ItemId_Event_Say: eventSpectatorSay(qobject_cast(event), context); break; + default: { + qDebug() << "unhandled spectator game event"; + break; + } + } + } else switch (event->getItemId()) { case ItemId_Event_GameStateChanged: eventGameStateChanged(qobject_cast(event), context); break; case ItemId_Event_PlayerPropertiesChanged: eventPlayerPropertiesChanged(qobject_cast(event), context); break; case ItemId_Event_Join: eventJoin(qobject_cast(event), context); break; @@ -289,6 +299,11 @@ void TabGame::stopGame() deckViewContainer->show(); } +void TabGame::eventSpectatorSay(Event_Say *event, GameEventContext * /*context*/) +{ + messageLog->logSpectatorSay(spectators.value(event->getPlayerId()), event->getMessage()); +} + void TabGame::eventGameStateChanged(Event_GameStateChanged *event, GameEventContext * /*context*/) { const QList &plList = event->getPlayerList(); diff --git a/cockatrice/src/tab_game.h b/cockatrice/src/tab_game.h index be557905..3f93b8e9 100644 --- a/cockatrice/src/tab_game.h +++ b/cockatrice/src/tab_game.h @@ -33,6 +33,7 @@ class Event_GameStart; class Event_SetActivePlayer; class Event_SetActivePhase; class Event_Ping; +class Event_Say; class Player; class CardZone; class AbstractCardItem; @@ -46,6 +47,7 @@ private: QString gameDescription; int localPlayerId; bool spectator; + bool spectatorsCanTalk, spectatorsSeeEverything; QMap players; QMap spectators; bool started; @@ -73,6 +75,7 @@ private: void startGame(); void stopGame(); + void eventSpectatorSay(Event_Say *event, GameEventContext *context); void eventGameStateChanged(Event_GameStateChanged *event, GameEventContext *context); void eventPlayerPropertiesChanged(Event_PlayerPropertiesChanged *event, GameEventContext *context); void eventJoin(Event_Join *event, GameEventContext *context); @@ -100,12 +103,15 @@ private slots: void actNextPhase(); void actNextTurn(); public: - TabGame(Client *_client, int _gameId, const QString &_gameDescription, int _localPlayerId, bool _spectator, bool _resuming); + TabGame(Client *_client, int _gameId, const QString &_gameDescription, int _localPlayerId, bool _spectator, bool _spectatorsCanTalk, bool _spectatorsSeeEverything, bool _resuming); ~TabGame(); void retranslateUi(); const QMap &getPlayers() const { return players; } int getGameId() const { return gameId; } QString getTabText() const { return tr("Game %1: %2").arg(gameId).arg(gameDescription); } + bool getSpectator() const { return spectator; } + bool getSpectatorsCanTalk() const { return spectatorsCanTalk; } + bool getSpectatorsSeeEverything() const { return spectatorsSeeEverything; } void processGameEventContainer(GameEventContainer *cont); public slots: diff --git a/cockatrice/src/tab_server.cpp b/cockatrice/src/tab_server.cpp index 76536028..6c626262 100644 --- a/cockatrice/src/tab_server.cpp +++ b/cockatrice/src/tab_server.cpp @@ -81,7 +81,7 @@ void GameSelector::actJoin() return; ServerInfo_Game *game = gameListModel->getGame(ind.data(Qt::UserRole).toInt()); QString password; - if (game->getHasPassword()) { + if (game->getHasPassword() && !(spectator && !game->getSpectatorsNeedPassword())) { bool ok; password = QInputDialog::getText(this, tr("Join game"), tr("Password:"), QLineEdit::Password, QString(), &ok); if (!ok) diff --git a/cockatrice/src/tab_supervisor.cpp b/cockatrice/src/tab_supervisor.cpp index 88d92224..5c45c301 100644 --- a/cockatrice/src/tab_supervisor.cpp +++ b/cockatrice/src/tab_supervisor.cpp @@ -103,7 +103,7 @@ void TabSupervisor::updatePingTime(int value, int max) void TabSupervisor::gameJoined(Event_GameJoined *event) { - TabGame *tab = new TabGame(client, event->getGameId(), event->getGameDescription(), event->getPlayerId(), event->getSpectator(), event->getResuming()); + TabGame *tab = new TabGame(client, event->getGameId(), event->getGameDescription(), event->getPlayerId(), event->getSpectator(), event->getSpectatorsCanTalk(), event->getSpectatorsSeeEverything(), event->getResuming()); connect(tab, SIGNAL(gameClosing(TabGame *)), this, SLOT(gameLeft(TabGame *))); myAddTab(tab); gameTabs.insert(event->getGameId(), tab); diff --git a/cockatrice/translations/cockatrice_de.ts b/cockatrice/translations/cockatrice_de.ts index 020549b4..328e0a44 100644 --- a/cockatrice/translations/cockatrice_de.ts +++ b/cockatrice/translations/cockatrice_de.ts @@ -476,38 +476,56 @@ &Spieler: - + &Spectators allowed &Zuschauer zugelassen - + + Spectators &need a password to join + Zuschauer brauchen &auch ein Passwort + + + + Spectators can &talk + Zuschauer können sp&rechen + + + + Spectators see &everything + Zuschauer sehen &alles + + + + Spectators + Zuschauer + + + &OK &OK - + &Cancel &Abbruch - + Create game Spiel erstellen - - + Error Fehler - Invalid number of players. - Ungültige Anzahl an Spielern. + Ungültige Anzahl an Spielern. - + Server error. Serverfehler. @@ -978,6 +996,11 @@ Description Beschreibung + + + yes, free for spectators + ja, außer für Zuschauer + not allowed @@ -1246,7 +1269,7 @@ %1 zieht %2 Karten - + a card eine Karte @@ -1308,7 +1331,7 @@ Das Spiel hat begonnen. - + %1 shuffles his library. %1 mischt seine Bibliothek. @@ -1385,122 +1408,122 @@ %1 hat das Spiel aufgegeben. - + %1 rolls a %2 with a %3-sided die. %1 würfelt eine %2 mit einem %3-seitigen Würfel. - + %1 draws a card. %1 zieht eine Karte. - + %1 draws %2 cards. %1 zieht %2 Karten. - + from table vom Spielfeld - + from graveyard aus dem Friedhof - + from exile aus dem Exil - + from hand von der Hand - + the bottom card of his library die unterste Karte seiner Bibliothek - + from the bottom of his library , die unterste Karte seiner Bibliothek, - + the top card of his library die oberste Karte seiner Bibliothek - + from the top of his library , die oberste Karte seiner Bibliothek, - + from library aus der Bibliothek - + from sideboard aus dem Sideboard - + %1 puts %2 into play%3. %1 bringt %2%3 ins Spiel. - + %1 puts %2%3 into graveyard. %1 legt %2%3 auf den Friedhof. - + %1 exiles %2%3. %1 schickt %2%3 ins Exil. - + %1 moves %2%3 to hand. %1 nimmt %2%3 auf die Hand. - + %1 puts %2%3 into his library. %1 legt %2%3 in seine Bibliothek. - + %1 puts %2%3 on bottom of his library. %1 legt %2%3 unter seine Bibliothek. - + %1 puts %2%3 on top of his library. %1 legt %2%3 auf die Bibliothek. - + %1 puts %2%3 into his library at position %4. %1 legt %2%3 in seine Bibliothek an %4. Stelle. - + %1 moves %2%3 to sideboard. %1 legt %2%3 in sein Sideboard. - + %1 points from %2's %3 to %4's %5. %1 zeigt von %2s %3 auf %4s %5. - + %1 is looking at the top %2 cards %3. %1 sieht sich die obersten %2 Karten %3 an. @@ -1585,27 +1608,27 @@ %1 legt %2%3in sein Sideboard. - + %1 creates token: %2. %1 erstellt Token: %2. - + %1 places %2 counters on %3 (now %4). %1 legt %2 Zählmarken auf %3 (jetzt %4). - + %1 removes %2 counters from %3 (now %4). %1 entfernt %2 Zählmarken von %3 (jetzt %4). - + %1 %2 %3. %1 %2 %3. - + %1 sets counter "%2" to %3 (%4%5). %1 setzt Zählmarke "%2" auf %3 (%4%5). @@ -1614,17 +1637,17 @@ %1 sieht sich die obersten %2 Karten %3 an. - + %1 is looking at %2. %1 sieht sich %2 an. - + %1 stops looking at %2. %1 sieht sich %2 nicht mehr an. - + ending phase die Zugendphase @@ -1653,57 +1676,57 @@ %1 sieht sich %2s %3 nicht mehr an - + It is now %1's turn. %1 ist am Zug. - + untap step das Enttappsegment - + upkeep step das Versorgungssegment - + draw step das Ziehsegment - + first main phase die erste Hauptphase - + beginning of combat step das Anfangssegment der Kampfphase - + declare attackers step das Angreifer-Deklarieren-Segment - + declare blockers step das Blocker-Deklarieren-Segment - + combat damage step das Kampfschadenssegment - + end of combat step das Endsegment der Kampfphase - + second main phase die zweite Hauptphase @@ -1712,7 +1735,7 @@ das Ende-des-Zuges-Segment - + It is now the %1. Es ist nun %1. @@ -1721,12 +1744,12 @@ %1 bewegt %2 %3 nach %4 - + taps tappt - + untaps enttappt @@ -1751,7 +1774,7 @@ %1 entfernt %2 Zählmarken von %3 (jetzt %4) - + his permanents seine bleibenden Karten @@ -1764,12 +1787,12 @@ %1 setzt Zähler "%2" auf %3 (%4%5) - + %1 sets %2 to not untap normally. %1 setzt %2 auf explizites Enttappen. - + %1 sets %2 to untap normally. %1 setzt %2 auf normales Enttappen. @@ -2447,77 +2470,77 @@ Bitte geben Sie einen Namen ein: TabGame - + &Game Spi&el - + Next &phase Nächste &Phase - + Ctrl+Space Ctrl+Space - + Next &turn Nächster &Zug - + Ctrl+Return Ctrl+Return - + Ctrl+Enter Ctrl+Enter - + &Remove all local arrows &Lokale Pfeile entfernen - + Ctrl+R Ctrl+R - + &Concede - + F2 F2 - + &Leave game Spiel ver&lassen - + Load &local deck &Lokales Deck laden - + Load d&eck from server Deck vom Server l&aden - + S&tart game Spiel s&tarten - + &Say: &Sagen: @@ -2530,32 +2553,32 @@ Bitte geben Sie einen Namen ein: Esc - + Concede Aufgeben - + Are you sure you want to concede this game? Sind Sie sicher, dass Sie das Spiel aufgeben möchten? - + Leave game Spiel verlassen - + Are you sure you want to leave this game? Sind Sie sicher, dass Sie das Spiel verlassen möchten? - + Load deck Deck laden - + Game %1: %2 Spiel %1: %2 diff --git a/cockatrice/translations/cockatrice_en.ts b/cockatrice/translations/cockatrice_en.ts index c0b2a4a3..2d9eba8b 100644 --- a/cockatrice/translations/cockatrice_en.ts +++ b/cockatrice/translations/cockatrice_en.ts @@ -396,38 +396,52 @@ - + &Spectators allowed - - &OK + + Spectators &need a password to join + + + + + Spectators can &talk + + + + + Spectators see &everything + Spectators + + + + + &OK + + + + &Cancel - + Create game - - + Error - - Invalid number of players. - - - - + Server error. @@ -601,6 +615,11 @@ Description + + + yes, free for spectators + + not allowed @@ -808,117 +827,117 @@ - + %1 rolls a %2 with a %3-sided die. - + from table - + from graveyard - + from exile - + from hand - + the bottom card of his library - + from the bottom of his library - + the top card of his library - + from the top of his library - + from library - + from sideboard - + %1 puts %2 into play%3. - + %1 puts %2%3 into graveyard. - + %1 exiles %2%3. - + %1 moves %2%3 to hand. - + %1 puts %2%3 into his library. - + %1 puts %2%3 on bottom of his library. - + %1 puts %2%3 on top of his library. - + %1 puts %2%3 into his library at position %4. - + %1 moves %2%3 to sideboard. - + a card - + %1 points from %2's %3 to %4's %5. - + %1 is looking at the top %2 cards %3. @@ -973,142 +992,142 @@ - + %1 draws a card. - + %1 draws %2 cards. - + %1 creates token: %2. - + %1 places %2 counters on %3 (now %4). - + %1 removes %2 counters from %3 (now %4). - + %1 %2 %3. - + %1 sets counter "%2" to %3 (%4%5). - + %1 is looking at %2. - + %1 stops looking at %2. - + ending phase - + It is now %1's turn. - + %1 shuffles his library. - + untap step - + upkeep step - + draw step - + first main phase - + beginning of combat step - + declare attackers step - + declare blockers step - + combat damage step - + end of combat step - + second main phase - + It is now the %1. - + taps - + untaps - + %1 sets %2 to not untap normally. - + %1 sets %2 to untap normally. - + his permanents @@ -1713,107 +1732,107 @@ Please enter a name: TabGame - + &Game - + Next &phase - + Ctrl+Space - + Next &turn - + Ctrl+Return - + Ctrl+Enter - + &Remove all local arrows - + Ctrl+R - + &Concede - + F2 - + &Leave game - + Load &local deck - + Load d&eck from server - + S&tart game - + &Say: - + Concede - + Are you sure you want to concede this game? - + Leave game - + Are you sure you want to leave this game? - + Load deck - + Game %1: %2 diff --git a/common/protocol.cpp b/common/protocol.cpp index 79be614a..ca8ab0ee 100644 --- a/common/protocol.cpp +++ b/common/protocol.cpp @@ -104,7 +104,7 @@ void Command::processResponse(ProtocolResponse *response) } CommandContainer::CommandContainer(const QList &_commandList, int _cmdId) - : ProtocolItem("container", "cmd"), ticks(0), resp(0), gameEventQueuePublic(0), gameEventQueuePrivate(0) + : ProtocolItem("container", "cmd"), ticks(0), resp(0), gameEventQueuePublic(0), gameEventQueueOmniscient(0), gameEventQueuePrivate(0) { if (_cmdId == -1) _cmdId = lastCmdId++; @@ -137,6 +137,13 @@ void CommandContainer::enqueueGameEventPublic(GameEvent *event, int gameId) gameEventQueuePublic->appendItem(event); } +void CommandContainer::enqueueGameEventOmniscient(GameEvent *event, int gameId) +{ + if (!gameEventQueueOmniscient) + gameEventQueueOmniscient = new GameEventContainer(QList(), gameId); + gameEventQueueOmniscient->appendItem(event); +} + void CommandContainer::enqueueGameEventPrivate(GameEvent *event, int gameId) { if (!gameEventQueuePrivate) diff --git a/common/protocol.h b/common/protocol.h index 337db848..5e1af53b 100644 --- a/common/protocol.h +++ b/common/protocol.h @@ -103,6 +103,7 @@ private: ProtocolResponse *resp; QList itemQueue; GameEventContainer *gameEventQueuePublic; + GameEventContainer *gameEventQueueOmniscient; GameEventContainer *gameEventQueuePrivate; public: CommandContainer(const QList &_commandList = QList(), int _cmdId = -1); @@ -119,6 +120,8 @@ public: void enqueueItem(ProtocolItem *item) { itemQueue.append(item); } GameEventContainer *getGameEventQueuePublic() const { return gameEventQueuePublic; } void enqueueGameEventPublic(GameEvent *event, int gameId); + GameEventContainer *getGameEventQueueOmniscient() const { return gameEventQueueOmniscient; } + void enqueueGameEventOmniscient(GameEvent *event, int gameId); GameEventContainer *getGameEventQueuePrivate() const { return gameEventQueuePrivate; } void enqueueGameEventPrivate(GameEvent *event, int gameId); }; diff --git a/common/protocol_datastructures.cpp b/common/protocol_datastructures.cpp index a3824b33..38971f78 100644 --- a/common/protocol_datastructures.cpp +++ b/common/protocol_datastructures.cpp @@ -18,7 +18,7 @@ ServerInfo_ChatUser::ServerInfo_ChatUser(const QString &_name) insertItem(new SerializableItem_String("name", _name)); } -ServerInfo_Game::ServerInfo_Game(int _gameId, const QString &_description, bool _hasPassword, int _playerCount, int _maxPlayers, const QString &_creatorName, bool _spectatorsAllowed, int _spectatorCount) +ServerInfo_Game::ServerInfo_Game(int _gameId, const QString &_description, bool _hasPassword, int _playerCount, int _maxPlayers, const QString &_creatorName, bool _spectatorsAllowed, bool _spectatorsNeedPassword, int _spectatorCount) : SerializableItem_Map("game") { insertItem(new SerializableItem_Int("game_id", _gameId)); @@ -28,6 +28,7 @@ ServerInfo_Game::ServerInfo_Game(int _gameId, const QString &_description, bool insertItem(new SerializableItem_Int("max_players", _maxPlayers)); insertItem(new SerializableItem_String("creator_name", _creatorName)); insertItem(new SerializableItem_Bool("spectators_allowed", _spectatorsAllowed)); + insertItem(new SerializableItem_Bool("spectators_need_password", _spectatorsNeedPassword)); insertItem(new SerializableItem_Int("spectator_count", _spectatorCount)); } diff --git a/common/protocol_datastructures.h b/common/protocol_datastructures.h index d9e589e3..7d331498 100644 --- a/common/protocol_datastructures.h +++ b/common/protocol_datastructures.h @@ -39,7 +39,7 @@ public: class ServerInfo_Game : public SerializableItem_Map { public: - ServerInfo_Game(int _gameId = -1, const QString &_description = QString(), bool _hasPassword = false, int _playerCount = -1, int _maxPlayers = -1, const QString &_creatorName = QString(), bool _spectatorsAllowed = false, int _spectatorCount = -1); + ServerInfo_Game(int _gameId = -1, const QString &_description = QString(), bool _hasPassword = false, int _playerCount = -1, int _maxPlayers = -1, const QString &_creatorName = QString(), bool _spectatorsAllowed = false, bool _spectatorsNeedPassword = false, int _spectatorCount = -1); static SerializableItem *newItem() { return new ServerInfo_Game; } int getGameId() const { return static_cast(itemMap.value("game_id"))->getData(); } QString getDescription() const { return static_cast(itemMap.value("description"))->getData(); } @@ -48,6 +48,7 @@ public: int getMaxPlayers() const { return static_cast(itemMap.value("max_players"))->getData(); } QString getCreatorName() const { return static_cast(itemMap.value("creator_name"))->getData(); } bool getSpectatorsAllowed() const { return static_cast(itemMap.value("spectators_allowed"))->getData(); } + bool getSpectatorsNeedPassword() const { return static_cast(itemMap.value("spectators_need_password"))->getData(); } int getSpectatorCount() const { return static_cast(itemMap.value("spectator_count"))->getData(); } }; diff --git a/common/protocol_items.cpp b/common/protocol_items.cpp index 6a9c6a4d..d0ed4cfa 100644 --- a/common/protocol_items.cpp +++ b/common/protocol_items.cpp @@ -58,13 +58,16 @@ Command_ListGames::Command_ListGames() : Command("list_games") { } -Command_CreateGame::Command_CreateGame(const QString &_description, const QString &_password, int _maxPlayers, bool _spectatorsAllowed) +Command_CreateGame::Command_CreateGame(const QString &_description, const QString &_password, int _maxPlayers, bool _spectatorsAllowed, bool _spectatorsNeedPassword, bool _spectatorsCanTalk, bool _spectatorsSeeEverything) : Command("create_game") { insertItem(new SerializableItem_String("description", _description)); insertItem(new SerializableItem_String("password", _password)); insertItem(new SerializableItem_Int("max_players", _maxPlayers)); insertItem(new SerializableItem_Bool("spectators_allowed", _spectatorsAllowed)); + insertItem(new SerializableItem_Bool("spectators_need_password", _spectatorsNeedPassword)); + insertItem(new SerializableItem_Bool("spectators_can_talk", _spectatorsCanTalk)); + insertItem(new SerializableItem_Bool("spectators_see_everything", _spectatorsSeeEverything)); } Command_JoinGame::Command_JoinGame(int _gameId, const QString &_password, bool _spectator) : Command("join_game") @@ -297,13 +300,15 @@ Event_ServerMessage::Event_ServerMessage(const QString &_message) { insertItem(new SerializableItem_String("message", _message)); } -Event_GameJoined::Event_GameJoined(int _gameId, const QString &_gameDescription, int _playerId, bool _spectator, bool _resuming) +Event_GameJoined::Event_GameJoined(int _gameId, const QString &_gameDescription, int _playerId, bool _spectator, bool _spectatorsCanTalk, bool _spectatorsSeeEverything, bool _resuming) : GenericEvent("game_joined") { insertItem(new SerializableItem_Int("game_id", _gameId)); insertItem(new SerializableItem_String("game_description", _gameDescription)); insertItem(new SerializableItem_Int("player_id", _playerId)); insertItem(new SerializableItem_Bool("spectator", _spectator)); + insertItem(new SerializableItem_Bool("spectators_can_talk", _spectatorsCanTalk)); + insertItem(new SerializableItem_Bool("spectators_see_everything", _spectatorsSeeEverything)); insertItem(new SerializableItem_Bool("resuming", _resuming)); } Event_ChatJoinChannel::Event_ChatJoinChannel(const QString &_channel, const QString &_playerName) diff --git a/common/protocol_items.dat b/common/protocol_items.dat index d7581f4d..1ff77468 100644 --- a/common/protocol_items.dat +++ b/common/protocol_items.dat @@ -10,7 +10,7 @@ 1:chat_leave_channel 1:chat_say:s,message 0:list_games -0:create_game:s,description:s,password:i,max_players:b,spectators_allowed +0:create_game:s,description:s,password:i,max_players:b,spectators_allowed:b,spectators_need_password:b,spectators_can_talk:b,spectators_see_everything 0:join_game:i,game_id:s,password:b,spectator 2:leave_game 2:say:s,message @@ -49,7 +49,7 @@ 3:dump_zone:i,zone_owner_id:s,zone:i,number_cards 3:stop_dump_zone:i,zone_owner_id:s,zone 4:server_message:s,message -4:game_joined:i,game_id:s,game_description:i,player_id:b,spectator:b,resuming +4:game_joined:i,game_id:s,game_description:i,player_id:b,spectator:b,spectators_can_talk:b,spectators_see_everything:b,resuming 5:chat_join_channel:s,player_name 5:chat_leave_channel:s,player_name 5:chat_say:s,player_name:s,message diff --git a/common/protocol_items.h b/common/protocol_items.h index 667d8249..feb67947 100644 --- a/common/protocol_items.h +++ b/common/protocol_items.h @@ -99,11 +99,14 @@ public: class Command_CreateGame : public Command { Q_OBJECT public: - Command_CreateGame(const QString &_description = QString(), const QString &_password = QString(), int _maxPlayers = -1, bool _spectatorsAllowed = false); + Command_CreateGame(const QString &_description = QString(), const QString &_password = QString(), int _maxPlayers = -1, bool _spectatorsAllowed = false, bool _spectatorsNeedPassword = false, bool _spectatorsCanTalk = false, bool _spectatorsSeeEverything = false); QString getDescription() const { return static_cast(itemMap.value("description"))->getData(); }; QString getPassword() const { return static_cast(itemMap.value("password"))->getData(); }; int getMaxPlayers() const { return static_cast(itemMap.value("max_players"))->getData(); }; bool getSpectatorsAllowed() const { return static_cast(itemMap.value("spectators_allowed"))->getData(); }; + bool getSpectatorsNeedPassword() const { return static_cast(itemMap.value("spectators_need_password"))->getData(); }; + bool getSpectatorsCanTalk() const { return static_cast(itemMap.value("spectators_can_talk"))->getData(); }; + bool getSpectatorsSeeEverything() const { return static_cast(itemMap.value("spectators_see_everything"))->getData(); }; static SerializableItem *newItem() { return new Command_CreateGame; } int getItemId() const { return ItemId_Command_CreateGame; } }; @@ -455,11 +458,13 @@ public: class Event_GameJoined : public GenericEvent { Q_OBJECT public: - Event_GameJoined(int _gameId = -1, const QString &_gameDescription = QString(), int _playerId = -1, bool _spectator = false, bool _resuming = false); + Event_GameJoined(int _gameId = -1, const QString &_gameDescription = QString(), int _playerId = -1, bool _spectator = false, bool _spectatorsCanTalk = false, bool _spectatorsSeeEverything = false, bool _resuming = false); int getGameId() const { return static_cast(itemMap.value("game_id"))->getData(); }; QString getGameDescription() const { return static_cast(itemMap.value("game_description"))->getData(); }; int getPlayerId() const { return static_cast(itemMap.value("player_id"))->getData(); }; bool getSpectator() const { return static_cast(itemMap.value("spectator"))->getData(); }; + bool getSpectatorsCanTalk() const { return static_cast(itemMap.value("spectators_can_talk"))->getData(); }; + bool getSpectatorsSeeEverything() const { return static_cast(itemMap.value("spectators_see_everything"))->getData(); }; bool getResuming() const { return static_cast(itemMap.value("resuming"))->getData(); }; static SerializableItem *newItem() { return new Event_GameJoined; } int getItemId() const { return ItemId_Event_GameJoined; } diff --git a/common/server.cpp b/common/server.cpp index 5410b348..ef5370c0 100644 --- a/common/server.cpp +++ b/common/server.cpp @@ -32,9 +32,9 @@ Server::~Server() { } -Server_Game *Server::createGame(const QString &description, const QString &password, int maxPlayers, bool spectatorsAllowed, Server_ProtocolHandler *creator) +Server_Game *Server::createGame(const QString &description, const QString &password, int maxPlayers, bool spectatorsAllowed, bool spectatorsNeedPassword, bool spectatorsCanTalk, bool spectatorsSeeEverything, Server_ProtocolHandler *creator) { - Server_Game *newGame = new Server_Game(creator, nextGameId++, description, password, maxPlayers, spectatorsAllowed, this); + Server_Game *newGame = new Server_Game(creator, nextGameId++, description, password, maxPlayers, spectatorsAllowed, spectatorsNeedPassword, spectatorsCanTalk, spectatorsSeeEverything, this); games.insert(newGame->getGameId(), newGame); connect(newGame, SIGNAL(gameClosing()), this, SLOT(gameClosing())); @@ -84,6 +84,7 @@ void Server::broadcastGameListUpdate(Server_Game *game) game->getMaxPlayers(), game->getCreatorName(), game->getSpectatorsAllowed(), + game->getSpectatorsNeedPassword(), game->getSpectatorCount() )); else diff --git a/common/server.h b/common/server.h index ec01de6c..461e516b 100644 --- a/common/server.h +++ b/common/server.h @@ -30,7 +30,7 @@ public: void removeClient(Server_ProtocolHandler *player); void closeOldSession(const QString &playerName); virtual QString getLoginMessage() const = 0; - Server_Game *createGame(const QString &description, const QString &password, int maxPlayers, bool spectatorsAllowed, Server_ProtocolHandler *creator); + Server_Game *createGame(const QString &description, const QString &password, int maxPlayers, bool spectatorsAllowed, bool spectatorsNeedPassword, bool spectatorsCanTalk, bool spectatorsSeeEverything, Server_ProtocolHandler *creator); virtual int getMaxGameInactivityTime() const = 0; virtual int getMaxPlayerInactivityTime() const = 0; diff --git a/common/server_game.cpp b/common/server_game.cpp index dea8bbf7..44a57088 100644 --- a/common/server_game.cpp +++ b/common/server_game.cpp @@ -27,8 +27,8 @@ #include #include -Server_Game::Server_Game(Server_ProtocolHandler *_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), activePlayer(-1), activePhase(-1), spectatorsAllowed(_spectatorsAllowed), inactivityCounter(0) +Server_Game::Server_Game(Server_ProtocolHandler *_creator, int _gameId, const QString &_description, const QString &_password, int _maxPlayers, bool _spectatorsAllowed, bool _spectatorsNeedPassword, bool _spectatorsCanTalk, bool _spectatorsSeeEverything, QObject *parent) + : QObject(parent), gameStarted(false), gameId(_gameId), description(_description), password(_password), maxPlayers(_maxPlayers), activePlayer(-1), activePhase(-1), spectatorsAllowed(_spectatorsAllowed), spectatorsNeedPassword(_spectatorsNeedPassword), spectatorsCanTalk(_spectatorsCanTalk), spectatorsSeeEverything(_spectatorsSeeEverything), inactivityCounter(0) { creator = addPlayer(_creator, false, false); @@ -168,7 +168,7 @@ void Server_Game::stopGameIfFinished() ResponseCode Server_Game::checkJoin(const QString &_password, bool spectator) { - if (_password != password) + if ((_password != password) && !(spectator && !spectatorsNeedPassword)) return RespWrongPassword; if (spectator) { if (!spectatorsAllowed) @@ -292,13 +292,26 @@ void Server_Game::sendGameEvent(GameEvent *event, GameEventContext *context, Ser sendGameEventContainer(new GameEventContainer(QList() << event, -1, context), exclude); } -void Server_Game::sendGameEventContainer(GameEventContainer *cont, Server_Player *exclude) +void Server_Game::sendGameEventContainer(GameEventContainer *cont, Server_Player *exclude, bool excludeOmniscient) { cont->setGameId(gameId); QMapIterator playerIterator(players); while (playerIterator.hasNext()) { Server_Player *p = playerIterator.next().value(); - if (p != exclude) + if ((p != exclude) && !(excludeOmniscient && p->getSpectator() && spectatorsSeeEverything)) + p->sendProtocolItem(cont, false); + } + + delete cont; +} + +void Server_Game::sendGameEventContainerOmniscient(GameEventContainer *cont, Server_Player *exclude) +{ + cont->setGameId(gameId); + QMapIterator playerIterator(players); + while (playerIterator.hasNext()) { + Server_Player *p = playerIterator.next().value(); + if ((p != exclude) && (p->getSpectator() && spectatorsSeeEverything)) p->sendProtocolItem(cont, false); } diff --git a/common/server_game.h b/common/server_game.h index 50456cd0..c6df423f 100644 --- a/common/server_game.h +++ b/common/server_game.h @@ -40,6 +40,9 @@ private: int maxPlayers; int activePlayer, activePhase; bool spectatorsAllowed; + bool spectatorsNeedPassword; + bool spectatorsCanTalk; + bool spectatorsSeeEverything; int inactivityCounter; QTimer *pingClock; signals: @@ -47,7 +50,7 @@ signals: private slots: void pingClockTimeout(); public: - Server_Game(Server_ProtocolHandler *_creator, int _gameId, const QString &_description, const QString &_password, int _maxPlayers, bool _spectatorsAllowed, QObject *parent = 0); + Server_Game(Server_ProtocolHandler *_creator, int _gameId, const QString &_description, const QString &_password, int _maxPlayers, bool _spectatorsAllowed, bool _spectatorsNeedPassword, bool _spectatorsCanTalk, bool _spectatorsSeeEverything, QObject *parent = 0); ~Server_Game(); Server_Player *getCreator() const { return creator; } QString getCreatorName() const { return creator ? creator->getPlayerName() : QString(); } @@ -61,6 +64,9 @@ public: QString getPassword() const { return password; } int getMaxPlayers() const { return maxPlayers; } bool getSpectatorsAllowed() const { return spectatorsAllowed; } + bool getSpectatorsNeedPassword() const { return spectatorsNeedPassword; } + bool getSpectatorsCanTalk() const { return spectatorsCanTalk; } + bool getSpectatorsSeeEverything() const { return spectatorsSeeEverything; } ResponseCode checkJoin(const QString &_password, bool spectator); Server_Player *addPlayer(Server_ProtocolHandler *handler, bool spectator, bool broadcastUpdate = true); void removePlayer(Server_Player *player); @@ -73,7 +79,8 @@ public: QList getGameState(Server_Player *playerWhosAsking) const; void sendGameEvent(GameEvent *event, GameEventContext *context = 0, Server_Player *exclude = 0); - void sendGameEventContainer(GameEventContainer *cont, Server_Player *exclude = 0); + void sendGameEventContainer(GameEventContainer *cont, Server_Player *exclude = 0, bool excludeOmniscient = false); + void sendGameEventContainerOmniscient(GameEventContainer *cont, Server_Player *exclude = 0); void sendGameEventToPlayer(Server_Player *player, GameEvent *event); }; diff --git a/common/server_protocolhandler.cpp b/common/server_protocolhandler.cpp index b4e5dc02..5ae69afe 100644 --- a/common/server_protocolhandler.cpp +++ b/common/server_protocolhandler.cpp @@ -148,8 +148,13 @@ void Server_ProtocolHandler::processCommandContainer(CommandContainer *cont) Server_Game *game = games.value(gQPublic->getGameId()).first; Server_Player *player = games.value(gQPublic->getGameId()).second; GameEventContainer *gQPrivate = cont->getGameEventQueuePrivate(); + GameEventContainer *gQOmniscient = cont->getGameEventQueueOmniscient(); if (gQPrivate) { - game->sendGameEventContainer(gQPublic, player); + if (gQOmniscient) { + game->sendGameEventContainer(gQPublic, player, true); + game->sendGameEventContainerOmniscient(gQOmniscient, player); + } else + game->sendGameEventContainer(gQPublic, player); player->sendProtocolItem(gQPrivate); } else game->sendGameEventContainer(gQPublic); @@ -214,7 +219,7 @@ ResponseCode Server_ProtocolHandler::cmdLogin(Command_Login *cmd, CommandContain gamePlayers[j]->setProtocolHandler(this); games.insert(serverGames[i]->getGameId(), QPair(serverGames[i], gamePlayers[j])); - enqueueProtocolItem(new Event_GameJoined(serverGames[i]->getGameId(), serverGames[i]->getDescription(), gamePlayers[j]->getPlayerId(), gamePlayers[j]->getSpectator(), true)); + enqueueProtocolItem(new Event_GameJoined(serverGames[i]->getGameId(), serverGames[i]->getDescription(), gamePlayers[j]->getPlayerId(), gamePlayers[j]->getSpectator(), serverGames[i]->getSpectatorsCanTalk(), serverGames[i]->getSpectatorsSeeEverything(), true)); enqueueProtocolItem(GameEventContainer::makeNew(new Event_GameStateChanged(serverGames[i]->getGameStarted(), serverGames[i]->getActivePlayer(), serverGames[i]->getActivePhase(), serverGames[i]->getGameState(gamePlayers[j])), serverGames[i]->getGameId())); } } @@ -285,6 +290,7 @@ ResponseCode Server_ProtocolHandler::cmdListGames(Command_ListGames * /*cmd*/, C g->getMaxPlayers(), g->getCreatorName(), g->getSpectatorsAllowed(), + g->getSpectatorsNeedPassword(), g->getSpectatorCount() )); } @@ -296,11 +302,11 @@ ResponseCode Server_ProtocolHandler::cmdListGames(Command_ListGames * /*cmd*/, C ResponseCode Server_ProtocolHandler::cmdCreateGame(Command_CreateGame *cmd, CommandContainer *cont) { - Server_Game *game = server->createGame(cmd->getDescription(), cmd->getPassword(), cmd->getMaxPlayers(), cmd->getSpectatorsAllowed(), this); + Server_Game *game = server->createGame(cmd->getDescription(), cmd->getPassword(), cmd->getMaxPlayers(), cmd->getSpectatorsAllowed(), cmd->getSpectatorsNeedPassword(), cmd->getSpectatorsCanTalk(), cmd->getSpectatorsSeeEverything(), this); Server_Player *creator = game->getCreator(); games.insert(game->getGameId(), QPair(game, creator)); - enqueueProtocolItem(new Event_GameJoined(game->getGameId(), game->getDescription(), creator->getPlayerId(), false, false)); + enqueueProtocolItem(new Event_GameJoined(game->getGameId(), game->getDescription(), creator->getPlayerId(), false, game->getSpectatorsCanTalk(), game->getSpectatorsSeeEverything(), false)); enqueueProtocolItem(GameEventContainer::makeNew(new Event_GameStateChanged(game->getGameStarted(), game->getActivePlayer(), game->getActivePhase(), game->getGameState(creator)), game->getGameId())); return RespOk; } @@ -318,7 +324,7 @@ ResponseCode Server_ProtocolHandler::cmdJoinGame(Command_JoinGame *cmd, CommandC if (result == RespOk) { Server_Player *player = g->addPlayer(this, cmd->getSpectator()); games.insert(cmd->getGameId(), QPair(g, player)); - enqueueProtocolItem(new Event_GameJoined(cmd->getGameId(), g->getDescription(), player->getPlayerId(), cmd->getSpectator(), false)); + enqueueProtocolItem(new Event_GameJoined(cmd->getGameId(), g->getDescription(), player->getPlayerId(), cmd->getSpectator(), g->getSpectatorsCanTalk(), g->getSpectatorsSeeEverything(), false)); enqueueProtocolItem(GameEventContainer::makeNew(new Event_GameStateChanged(g->getGameStarted(), g->getActivePlayer(), g->getActivePhase(), g->getGameState(player)), cmd->getGameId())); } return result; @@ -332,6 +338,9 @@ ResponseCode Server_ProtocolHandler::cmdLeaveGame(Command_LeaveGame * /*cmd*/, C ResponseCode Server_ProtocolHandler::cmdDeckSelect(Command_DeckSelect *cmd, CommandContainer *cont, Server_Game *game, Server_Player *player) { + if (player->getSpectator()) + return RespFunctionNotAllowed; + DeckList *deck; if (cmd->getDeckId() == -1) { if (!cmd->getDeck()) @@ -354,6 +363,9 @@ ResponseCode Server_ProtocolHandler::cmdDeckSelect(Command_DeckSelect *cmd, Comm ResponseCode Server_ProtocolHandler::cmdSetSideboardPlan(Command_SetSideboardPlan *cmd, CommandContainer *cont, Server_Game *game, Server_Player *player) { + if (player->getSpectator()) + return RespFunctionNotAllowed; + DeckList *deck = player->getDeck(); if (!deck) return RespContextError; @@ -364,6 +376,9 @@ ResponseCode Server_ProtocolHandler::cmdSetSideboardPlan(Command_SetSideboardPla ResponseCode Server_ProtocolHandler::cmdConcede(Command_Concede * /*cmd*/, CommandContainer *cont, Server_Game *game, Server_Player *player) { + if (player->getSpectator()) + return RespFunctionNotAllowed; + player->setConceded(true); game->sendGameEvent(new Event_PlayerPropertiesChanged(player->getProperties()), new Context_Concede); game->stopGameIfFinished(); @@ -372,6 +387,9 @@ ResponseCode Server_ProtocolHandler::cmdConcede(Command_Concede * /*cmd*/, Comma ResponseCode Server_ProtocolHandler::cmdReadyStart(Command_ReadyStart * /*cmd*/, CommandContainer *cont, Server_Game *game, Server_Player *player) { + if (player->getSpectator()) + return RespFunctionNotAllowed; + if (!player->getDeck()) return RespContextError; @@ -383,12 +401,18 @@ ResponseCode Server_ProtocolHandler::cmdReadyStart(Command_ReadyStart * /*cmd*/, ResponseCode Server_ProtocolHandler::cmdSay(Command_Say *cmd, CommandContainer *cont, Server_Game *game, Server_Player *player) { + if (player->getSpectator() && !game->getSpectatorsCanTalk()) + return RespFunctionNotAllowed; + game->sendGameEvent(new Event_Say(player->getPlayerId(), cmd->getMessage())); return RespOk; } ResponseCode Server_ProtocolHandler::cmdShuffle(Command_Shuffle * /*cmd*/, CommandContainer *cont, Server_Game *game, Server_Player *player) { + if (player->getSpectator()) + return RespFunctionNotAllowed; + if (!game->getGameStarted()) return RespGameNotStarted; @@ -399,6 +423,9 @@ ResponseCode Server_ProtocolHandler::cmdShuffle(Command_Shuffle * /*cmd*/, Comma ResponseCode Server_ProtocolHandler::cmdMulligan(Command_Mulligan * /*cmd*/, CommandContainer *cont, Server_Game *game, Server_Player *player) { + if (player->getSpectator()) + return RespFunctionNotAllowed; + if (!game->getGameStarted()) return RespGameNotStarted; @@ -422,12 +449,18 @@ ResponseCode Server_ProtocolHandler::cmdMulligan(Command_Mulligan * /*cmd*/, Com ResponseCode Server_ProtocolHandler::cmdRollDie(Command_RollDie *cmd, CommandContainer *cont, Server_Game *game, Server_Player *player) { + if (player->getSpectator()) + return RespFunctionNotAllowed; + game->sendGameEvent(new Event_RollDie(player->getPlayerId(), cmd->getSides(), rng->getNumber(1, cmd->getSides()))); return RespOk; } ResponseCode Server_ProtocolHandler::drawCards(Server_Game *game, Server_Player *player, CommandContainer *cont, int number) { + if (player->getSpectator()) + return RespFunctionNotAllowed; + if (!game->getGameStarted()) return RespGameNotStarted; @@ -436,15 +469,18 @@ ResponseCode Server_ProtocolHandler::drawCards(Server_Game *game, Server_Player if (deck->cards.size() < number) number = deck->cards.size(); - QList cardList; + QList cardListPrivate; + QList cardListOmniscient; for (int i = 0; i < number; ++i) { Server_Card *card = deck->cards.takeFirst(); hand->cards.append(card); - cardList.append(new ServerInfo_Card(card->getId(), card->getName())); + cardListPrivate.append(new ServerInfo_Card(card->getId(), card->getName())); + cardListOmniscient.append(new ServerInfo_Card(card->getId(), card->getName())); } - cont->enqueueGameEventPrivate(new Event_DrawCards(player->getPlayerId(), cardList.size(), cardList), game->getGameId()); - cont->enqueueGameEventPublic(new Event_DrawCards(player->getPlayerId(), cardList.size()), game->getGameId()); + cont->enqueueGameEventPrivate(new Event_DrawCards(player->getPlayerId(), cardListPrivate.size(), cardListPrivate), game->getGameId()); + cont->enqueueGameEventOmniscient(new Event_DrawCards(player->getPlayerId(), cardListOmniscient.size(), cardListOmniscient), game->getGameId()); + cont->enqueueGameEventPublic(new Event_DrawCards(player->getPlayerId(), cardListPrivate.size()), game->getGameId()); return RespOk; } @@ -457,6 +493,9 @@ ResponseCode Server_ProtocolHandler::cmdDrawCards(Command_DrawCards *cmd, Comman ResponseCode Server_ProtocolHandler::moveCard(Server_Game *game, Server_Player *player, CommandContainer *cont, const QString &_startZone, int _cardId, const QString &_targetZone, int x, int y, bool faceDown, bool tapped) { + if (player->getSpectator()) + return RespFunctionNotAllowed; + if (!game->getGameStarted()) return RespGameNotStarted; @@ -508,6 +547,7 @@ ResponseCode Server_ProtocolHandler::moveCard(Server_Game *game, Server_Player * if (startzone->getType() == HiddenZone) privatePosition = position; cont->enqueueGameEventPrivate(new Event_MoveCard(player->getPlayerId(), privateOldCardId, privateCardName, startzone->getName(), privatePosition, targetzone->getName(), x, y, privateNewCardId, faceDown), game->getGameId()); + cont->enqueueGameEventOmniscient(new Event_MoveCard(player->getPlayerId(), privateOldCardId, privateCardName, startzone->getName(), privatePosition, targetzone->getName(), x, y, privateNewCardId, faceDown), game->getGameId()); // Other players do not get to see the start and/or target position of the card if the respective // part of the zone is being looked at. The information is not needed anyway because in hidden zones, @@ -554,6 +594,9 @@ ResponseCode Server_ProtocolHandler::cmdMoveCard(Command_MoveCard *cmd, CommandC ResponseCode Server_ProtocolHandler::cmdCreateToken(Command_CreateToken *cmd, CommandContainer *cont, Server_Game *game, Server_Player *player) { + if (player->getSpectator()) + return RespFunctionNotAllowed; + if (!game->getGameStarted()) return RespGameNotStarted; @@ -571,6 +614,9 @@ ResponseCode Server_ProtocolHandler::cmdCreateToken(Command_CreateToken *cmd, Co ResponseCode Server_ProtocolHandler::cmdCreateArrow(Command_CreateArrow *cmd, CommandContainer *cont, Server_Game *game, Server_Player *player) { + if (player->getSpectator()) + return RespFunctionNotAllowed; + if (!game->getGameStarted()) return RespGameNotStarted; @@ -610,6 +656,9 @@ ResponseCode Server_ProtocolHandler::cmdCreateArrow(Command_CreateArrow *cmd, Co ResponseCode Server_ProtocolHandler::cmdDeleteArrow(Command_DeleteArrow *cmd, CommandContainer *cont, Server_Game *game, Server_Player *player) { + if (player->getSpectator()) + return RespFunctionNotAllowed; + if (!game->getGameStarted()) return RespGameNotStarted; @@ -622,6 +671,9 @@ ResponseCode Server_ProtocolHandler::cmdDeleteArrow(Command_DeleteArrow *cmd, Co ResponseCode Server_ProtocolHandler::setCardAttrHelper(CommandContainer *cont, Server_Game *game, Server_Player *player, const QString &zoneName, int cardId, const QString &attrName, const QString &attrValue) { + if (player->getSpectator()) + return RespFunctionNotAllowed; + if (!game->getGameStarted()) return RespGameNotStarted; @@ -655,6 +707,9 @@ ResponseCode Server_ProtocolHandler::cmdSetCardAttr(Command_SetCardAttr *cmd, Co ResponseCode Server_ProtocolHandler::cmdIncCounter(Command_IncCounter *cmd, CommandContainer *cont, Server_Game *game, Server_Player *player) { + if (player->getSpectator()) + return RespFunctionNotAllowed; + if (!game->getGameStarted()) return RespGameNotStarted; @@ -670,6 +725,9 @@ ResponseCode Server_ProtocolHandler::cmdIncCounter(Command_IncCounter *cmd, Comm ResponseCode Server_ProtocolHandler::cmdCreateCounter(Command_CreateCounter *cmd, CommandContainer *cont, Server_Game *game, Server_Player *player) { + if (player->getSpectator()) + return RespFunctionNotAllowed; + if (!game->getGameStarted()) return RespGameNotStarted; @@ -682,6 +740,9 @@ ResponseCode Server_ProtocolHandler::cmdCreateCounter(Command_CreateCounter *cmd ResponseCode Server_ProtocolHandler::cmdSetCounter(Command_SetCounter *cmd, CommandContainer *cont, Server_Game *game, Server_Player *player) { + if (player->getSpectator()) + return RespFunctionNotAllowed; + if (!game->getGameStarted()) return RespGameNotStarted; @@ -696,6 +757,9 @@ ResponseCode Server_ProtocolHandler::cmdSetCounter(Command_SetCounter *cmd, Comm ResponseCode Server_ProtocolHandler::cmdDelCounter(Command_DelCounter *cmd, CommandContainer *cont, Server_Game *game, Server_Player *player) { + if (player->getSpectator()) + return RespFunctionNotAllowed; + if (!game->getGameStarted()) return RespGameNotStarted; @@ -705,8 +769,11 @@ ResponseCode Server_ProtocolHandler::cmdDelCounter(Command_DelCounter *cmd, Comm return RespOk; } -ResponseCode Server_ProtocolHandler::cmdNextTurn(Command_NextTurn * /*cmd*/, CommandContainer *cont, Server_Game *game, Server_Player * /*player*/) +ResponseCode Server_ProtocolHandler::cmdNextTurn(Command_NextTurn * /*cmd*/, CommandContainer *cont, Server_Game *game, Server_Player *player) { + if (player->getSpectator()) + return RespFunctionNotAllowed; + if (!game->getGameStarted()) return RespGameNotStarted; @@ -727,6 +794,9 @@ ResponseCode Server_ProtocolHandler::cmdNextTurn(Command_NextTurn * /*cmd*/, Com ResponseCode Server_ProtocolHandler::cmdSetActivePhase(Command_SetActivePhase *cmd, CommandContainer *cont, Server_Game *game, Server_Player *player) { + if (player->getSpectator()) + return RespFunctionNotAllowed; + if (!game->getGameStarted()) return RespGameNotStarted; From 33606f55ce587ed44337e685f2ce7b725c4b1c54 Mon Sep 17 00:00:00 2001 From: Max-Wilhelm Bruker Date: Wed, 26 May 2010 21:38:02 +0200 Subject: [PATCH 3/6] updated version string --- servatrice/src/servatrice.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/servatrice/src/servatrice.cpp b/servatrice/src/servatrice.cpp index 570f5be0..94b72ad4 100644 --- a/servatrice/src/servatrice.cpp +++ b/servatrice/src/servatrice.cpp @@ -135,4 +135,4 @@ AuthenticationResult Servatrice::checkUserPassword(const QString &user, const QS return UnknownUser; } -const QString Servatrice::versionString = "Servatrice 0.20100309"; +const QString Servatrice::versionString = "Servatrice 0.20100526"; From e6e20cb04832a7e86d5e0df3151ae09240a6b7a5 Mon Sep 17 00:00:00 2001 From: Max-Wilhelm Bruker Date: Thu, 27 May 2010 17:22:18 +0200 Subject: [PATCH 4/6] optional setting for horizonal hand display --- cockatrice/cockatrice.pro | 4 +++ cockatrice/src/dlg_settings.cpp | 14 ++++++++ cockatrice/src/dlg_settings.h | 4 +-- cockatrice/src/gamescene.cpp | 23 +++++++++++++ cockatrice/src/gamescene.h | 1 + cockatrice/src/gameview.cpp | 6 ++++ cockatrice/src/handzone.cpp | 52 +++------------------------- cockatrice/src/handzone.h | 12 +++---- cockatrice/src/handzone_horiz.cpp | 52 ++++++++++++++++++++++++++++ cockatrice/src/handzone_horiz.h | 18 ++++++++++ cockatrice/src/handzone_vert.cpp | 52 ++++++++++++++++++++++++++++ cockatrice/src/handzone_vert.h | 18 ++++++++++ cockatrice/src/player.cpp | 57 ++++++++++++++++++++++++------- cockatrice/src/player.h | 7 +++- cockatrice/src/settingscache.cpp | 7 ++++ cockatrice/src/settingscache.h | 3 ++ cockatrice/src/tab_game.cpp | 3 +- cockatrice/src/tablezone.cpp | 15 +++++--- cockatrice/src/tablezone.h | 3 ++ 19 files changed, 275 insertions(+), 76 deletions(-) create mode 100644 cockatrice/src/handzone_horiz.cpp create mode 100644 cockatrice/src/handzone_horiz.h create mode 100644 cockatrice/src/handzone_vert.cpp create mode 100644 cockatrice/src/handzone_vert.h diff --git a/cockatrice/cockatrice.pro b/cockatrice/cockatrice.pro index 6faeeff7..a4e04489 100644 --- a/cockatrice/cockatrice.pro +++ b/cockatrice/cockatrice.pro @@ -20,6 +20,8 @@ HEADERS += src/counter.h \ src/carditem.h \ src/tablezone.h \ src/handzone.h \ + src/handzone_vert.h \ + src/handzone_horiz.h \ src/carddatabase.h \ src/gameview.h \ src/deck_picturecacher.h \ @@ -73,6 +75,8 @@ SOURCES += src/counter.cpp \ src/carditem.cpp \ src/tablezone.cpp \ src/handzone.cpp \ + src/handzone_vert.cpp \ + src/handzone_horiz.cpp \ src/carddatabase.cpp \ src/gameview.cpp \ src/deck_picturecacher.cpp \ diff --git a/cockatrice/src/dlg_settings.cpp b/cockatrice/src/dlg_settings.cpp index 4e99921c..a55cd592 100644 --- a/cockatrice/src/dlg_settings.cpp +++ b/cockatrice/src/dlg_settings.cpp @@ -199,6 +199,16 @@ AppearanceSettingsPage::AppearanceSettingsPage() zoneBgGroupBox = new QGroupBox; zoneBgGroupBox->setLayout(zoneBgGrid); + horizontalHandCheckBox = new QCheckBox; + horizontalHandCheckBox->setChecked(settingsCache->getHorizontalHand()); + connect(horizontalHandCheckBox, SIGNAL(stateChanged(int)), settingsCache, SLOT(setHorizontalHand(int))); + + QGridLayout *handGrid = new QGridLayout; + handGrid->addWidget(horizontalHandCheckBox, 0, 0, 1, 2); + + handGroupBox = new QGroupBox; + handGroupBox->setLayout(handGrid); + economicGridCheckBox = new QCheckBox; economicGridCheckBox->setChecked(settingsCache->getEconomicGrid()); connect(economicGridCheckBox, SIGNAL(stateChanged(int)), settingsCache, SLOT(setEconomicGrid(int))); @@ -225,6 +235,7 @@ AppearanceSettingsPage::AppearanceSettingsPage() QVBoxLayout *mainLayout = new QVBoxLayout; mainLayout->addWidget(zoneBgGroupBox); + mainLayout->addWidget(handGroupBox); mainLayout->addWidget(tableGroupBox); mainLayout->addWidget(zoneViewGroupBox); @@ -239,6 +250,9 @@ void AppearanceSettingsPage::retranslateUi() tableBgLabel->setText(tr("Path to table background:")); playerAreaBgLabel->setText(tr("Path to player info background:")); + handGroupBox->setTitle(tr("Hand layout")); + horizontalHandCheckBox->setText(tr("Display hand horizontally (wastes space)")); + tableGroupBox->setTitle(tr("Table grid layout")); economicGridCheckBox->setText(tr("Economic layout")); diff --git a/cockatrice/src/dlg_settings.h b/cockatrice/src/dlg_settings.h index ae06b9e2..ad1f6be1 100644 --- a/cockatrice/src/dlg_settings.h +++ b/cockatrice/src/dlg_settings.h @@ -60,8 +60,8 @@ signals: private: QLabel *handBgLabel, *tableBgLabel, *playerAreaBgLabel; QLineEdit *handBgEdit, *tableBgEdit, *playerAreaBgEdit; - QCheckBox *economicGridCheckBox, *zoneViewSortByNameCheckBox, *zoneViewSortByTypeCheckBox; - QGroupBox *zoneBgGroupBox, *tableGroupBox, *zoneViewGroupBox; + QCheckBox *horizontalHandCheckBox, *economicGridCheckBox, *zoneViewSortByNameCheckBox, *zoneViewSortByTypeCheckBox; + QGroupBox *zoneBgGroupBox, *handGroupBox, *tableGroupBox, *zoneViewGroupBox; public: AppearanceSettingsPage(); void retranslateUi(); diff --git a/cockatrice/src/gamescene.cpp b/cockatrice/src/gamescene.cpp index 23c1561d..22fcf6d8 100644 --- a/cockatrice/src/gamescene.cpp +++ b/cockatrice/src/gamescene.cpp @@ -103,3 +103,26 @@ void GameScene::closeMostRecentZoneView() if (!views.isEmpty()) views.last()->close(); } + +void GameScene::processViewSizeChange(const QSize &newSize) +{ + qreal newRatio = ((qreal) newSize.width()) / newSize.height(); + qreal minWidth = 0; + for (int i = 0; i < players.size(); ++i) { + qreal w = players[i]->getMinimumWidth(); + if (w > minWidth) + minWidth = w; + } + + qreal minRatio = minWidth / sceneRect().height(); + if (minRatio > newRatio) { + // Aspect ratio is dominated by table width. + setSceneRect(sceneRect().x(), sceneRect().y(), minWidth, sceneRect().height()); + } else { + // Aspect ratio is dominated by window dimensions. + setSceneRect(sceneRect().x(), sceneRect().y(), newRatio * sceneRect().height(), sceneRect().height()); + } + + for (int i = 0; i < players.size(); ++i) + players[i]->processSceneSizeChange(sceneRect().size()); +} diff --git a/cockatrice/src/gamescene.h b/cockatrice/src/gamescene.h index 437d69d8..68697a19 100644 --- a/cockatrice/src/gamescene.h +++ b/cockatrice/src/gamescene.h @@ -19,6 +19,7 @@ public: GameScene(QObject *parent = 0); void retranslateUi(); const QRectF &getPlayersRect() const { return playersRect; } + void processViewSizeChange(const QSize &newSize); public slots: void toggleZoneView(Player *player, const QString &zoneName, int numberCards); void removeZoneView(ZoneViewWidget *item); diff --git a/cockatrice/src/gameview.cpp b/cockatrice/src/gameview.cpp index b7f8de80..fd716827 100644 --- a/cockatrice/src/gameview.cpp +++ b/cockatrice/src/gameview.cpp @@ -1,4 +1,6 @@ #include "gameview.h" +#include "gamescene.h" +#include #include GameView::GameView(QGraphicsScene *scene, QWidget *parent) @@ -21,6 +23,10 @@ GameView::GameView(QGraphicsScene *scene, QWidget *parent) void GameView::resizeEvent(QResizeEvent *event) { QGraphicsView::resizeEvent(event); + GameScene *s = dynamic_cast(scene()); + if (s) { + s->processViewSizeChange(event->size()); + } updateSceneRect(scene()->sceneRect()); } diff --git a/cockatrice/src/handzone.cpp b/cockatrice/src/handzone.cpp index 3e1f269d..ad09449c 100644 --- a/cockatrice/src/handzone.cpp +++ b/cockatrice/src/handzone.cpp @@ -1,17 +1,13 @@ -#include #include "handzone.h" -#include "player.h" -#include "client.h" -#include "protocol_items.h" #include "settingscache.h" +#include "player.h" +#include "protocol_items.h" -HandZone::HandZone(Player *_p, bool _contentsKnown, int _zoneHeight, QGraphicsItem *parent) - : CardZone(_p, "hand", false, false, _contentsKnown, parent), zoneHeight(_zoneHeight) +HandZone::HandZone(Player *_p, bool _contentsKnown, QGraphicsItem *parent) + : CardZone(_p, "hand", false, false, _contentsKnown, parent) { connect(settingsCache, SIGNAL(handBgPathChanged()), this, SLOT(updateBgPixmap())); updateBgPixmap(); - - setCacheMode(DeviceCoordinateCache); } void HandZone::updateBgPixmap() @@ -22,46 +18,6 @@ void HandZone::updateBgPixmap() update(); } -QRectF HandZone::boundingRect() const -{ - return QRectF(0, 0, 100, zoneHeight); -} - -void HandZone::paint(QPainter *painter, const QStyleOptionGraphicsItem */*option*/, QWidget */*widget*/) -{ - if (bgPixmap.isNull()) - painter->fillRect(boundingRect(), Qt::darkGreen); - else - painter->fillRect(boundingRect(), QBrush(bgPixmap)); -} - -void HandZone::reorganizeCards() -{ - if (!cards.isEmpty()) { - const int cardCount = cards.size(); - qreal totalWidth = boundingRect().width(); - qreal totalHeight = boundingRect().height(); - qreal cardWidth = cards.at(0)->boundingRect().width(); - qreal cardHeight = cards.at(0)->boundingRect().height(); - qreal xspace = 5; - qreal x1 = xspace; - qreal x2 = totalWidth - xspace - cardWidth; - - for (int i = 0; i < cardCount; i++) { - CardItem *c = cards.at(i); - qreal x = i % 2 ? x2 : x1; - // If the total height of the cards is smaller than the available height, - // the cards do not need to overlap and are displayed in the center of the area. - if (cardHeight * cardCount > totalHeight) - c->setPos(x, ((qreal) i) * (totalHeight - cardHeight) / (cardCount - 1)); - else - c->setPos(x, ((qreal) i) * cardHeight + (totalHeight - cardCount * cardHeight) / 2); - c->setZValue(i); - } - } - update(); -} - void HandZone::addCardImpl(CardItem *card, int x, int /*y*/) { if (x == -1) diff --git a/cockatrice/src/handzone.h b/cockatrice/src/handzone.h index f784da56..cd8eb578 100644 --- a/cockatrice/src/handzone.h +++ b/cockatrice/src/handzone.h @@ -5,19 +5,17 @@ class HandZone : public CardZone { Q_OBJECT -private: +protected: QPixmap bgPixmap; - int zoneHeight; -private slots: +private slots: void updateBgPixmap(); public: - HandZone(Player *_p, bool _contentsKnown, int _zoneHeight, QGraphicsItem *parent = 0); - QRectF boundingRect() const; - void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); - void reorganizeCards(); + HandZone(Player *_p, bool _contentsKnown, QGraphicsItem *parent = 0); void handleDropEvent(int cardId, CardZone *startZone, const QPoint &dropPoint, bool faceDown); + virtual void setWidth(qreal _width) = 0; protected: void addCardImpl(CardItem *card, int x, int y); }; #endif + diff --git a/cockatrice/src/handzone_horiz.cpp b/cockatrice/src/handzone_horiz.cpp new file mode 100644 index 00000000..4a1da8c2 --- /dev/null +++ b/cockatrice/src/handzone_horiz.cpp @@ -0,0 +1,52 @@ +#include +#include "handzone_horiz.h" +#include "player.h" + +HandZoneHoriz::HandZoneHoriz(Player *_p, bool _contentsKnown, QGraphicsItem *parent) + : HandZone(_p, _contentsKnown, parent), width(CARD_WIDTH * 10) +{ + setCacheMode(DeviceCoordinateCache); +} + +QRectF HandZoneHoriz::boundingRect() const +{ + return QRectF(0, 0, width, CARD_HEIGHT + 10); +} + +void HandZoneHoriz::paint(QPainter *painter, const QStyleOptionGraphicsItem */*option*/, QWidget */*widget*/) +{ + if (bgPixmap.isNull()) + painter->fillRect(boundingRect(), Qt::darkGreen); + else + painter->fillRect(boundingRect(), QBrush(bgPixmap)); +} + +void HandZoneHoriz::reorganizeCards() +{ + if (!cards.isEmpty()) { + const int cardCount = cards.size(); + const int xPadding = 5; + qreal totalWidth = boundingRect().width() - 2 * xPadding; + qreal cardWidth = cards.at(0)->boundingRect().width(); + + for (int i = 0; i < cardCount; i++) { + CardItem *c = cards.at(i); + + // If the total width of the cards is smaller than the available width, + // the cards do not need to overlap and are displayed in the center of the area. + if (cardWidth * cardCount > totalWidth) + c->setPos(xPadding + ((qreal) i) * (totalWidth - cardWidth) / (cardCount - 1), 5); + else + c->setPos(xPadding + ((qreal) i) * cardWidth + (totalWidth - cardCount * cardWidth) / 2, 5); + c->setZValue(i); + } + } + update(); +} + +void HandZoneHoriz::setWidth(qreal _width) +{ + prepareGeometryChange(); + width = _width; + reorganizeCards(); +} diff --git a/cockatrice/src/handzone_horiz.h b/cockatrice/src/handzone_horiz.h new file mode 100644 index 00000000..37b76d41 --- /dev/null +++ b/cockatrice/src/handzone_horiz.h @@ -0,0 +1,18 @@ +#ifndef HANDZONE_HORIZ_H +#define HANDZONE_HORIZ_H + +#include "handzone.h" + +class HandZoneHoriz : public HandZone { + Q_OBJECT +private: + qreal width; +public: + HandZoneHoriz(Player *_p, bool _contentsKnown, QGraphicsItem *parent = 0); + QRectF boundingRect() const; + void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); + void reorganizeCards(); + void setWidth(qreal _width); +}; + +#endif diff --git a/cockatrice/src/handzone_vert.cpp b/cockatrice/src/handzone_vert.cpp new file mode 100644 index 00000000..3e1ffdfd --- /dev/null +++ b/cockatrice/src/handzone_vert.cpp @@ -0,0 +1,52 @@ +#include +#include "handzone_vert.h" +#include "player.h" +#include "client.h" +#include "protocol_items.h" +#include "settingscache.h" + +HandZoneVert::HandZoneVert(Player *_p, bool _contentsKnown, int _zoneHeight, QGraphicsItem *parent) + : HandZone(_p, _contentsKnown, parent), zoneHeight(_zoneHeight) +{ + setCacheMode(DeviceCoordinateCache); +} + +QRectF HandZoneVert::boundingRect() const +{ + return QRectF(0, 0, 100, zoneHeight); +} + +void HandZoneVert::paint(QPainter *painter, const QStyleOptionGraphicsItem */*option*/, QWidget */*widget*/) +{ + if (bgPixmap.isNull()) + painter->fillRect(boundingRect(), Qt::darkGreen); + else + painter->fillRect(boundingRect(), QBrush(bgPixmap)); +} + +void HandZoneVert::reorganizeCards() +{ + if (!cards.isEmpty()) { + const int cardCount = cards.size(); + qreal totalWidth = boundingRect().width(); + qreal totalHeight = boundingRect().height(); + qreal cardWidth = cards.at(0)->boundingRect().width(); + qreal cardHeight = cards.at(0)->boundingRect().height(); + qreal xspace = 5; + qreal x1 = xspace; + qreal x2 = totalWidth - xspace - cardWidth; + + for (int i = 0; i < cardCount; i++) { + CardItem *c = cards.at(i); + qreal x = i % 2 ? x2 : x1; + // If the total height of the cards is smaller than the available height, + // the cards do not need to overlap and are displayed in the center of the area. + if (cardHeight * cardCount > totalHeight) + c->setPos(x, ((qreal) i) * (totalHeight - cardHeight) / (cardCount - 1)); + else + c->setPos(x, ((qreal) i) * cardHeight + (totalHeight - cardCount * cardHeight) / 2); + c->setZValue(i); + } + } + update(); +} diff --git a/cockatrice/src/handzone_vert.h b/cockatrice/src/handzone_vert.h new file mode 100644 index 00000000..71ae261d --- /dev/null +++ b/cockatrice/src/handzone_vert.h @@ -0,0 +1,18 @@ +#ifndef HANDZONE_VERT_H +#define HANDZONE_VERT_H + +#include "handzone.h" + +class HandZoneVert : public HandZone { + Q_OBJECT +private: + int zoneHeight; +public: + HandZoneVert(Player *_p, bool _contentsKnown, int _zoneHeight, QGraphicsItem *parent = 0); + QRectF boundingRect() const; + void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); + void reorganizeCards(); + void setWidth(qreal /*_width*/) { } +}; + +#endif diff --git a/cockatrice/src/player.cpp b/cockatrice/src/player.cpp index 973872be..2b60095d 100644 --- a/cockatrice/src/player.cpp +++ b/cockatrice/src/player.cpp @@ -7,7 +7,8 @@ #include "zoneviewwidget.h" #include "pilezone.h" #include "tablezone.h" -#include "handzone.h" +#include "handzone_vert.h" +#include "handzone_horiz.h" #include "cardlist.h" #include "tab_game.h" #include "protocol_items.h" @@ -17,8 +18,8 @@ #include #include -Player::Player(const QString &_name, int _id, bool _local, Client *_client, TabGame *_parent) - : QObject(_parent), defaultNumberTopCards(3), name(_name), id(_id), active(false), local(_local), client(_client) +Player::Player(const QString &_name, int _id, bool _local, bool _mirrored, Client *_client, TabGame *_parent) + : QObject(_parent), defaultNumberTopCards(3), name(_name), id(_id), active(false), local(_local), mirrored(_mirrored), client(_client) { setCacheMode(DeviceCoordinateCache); @@ -43,12 +44,25 @@ Player::Player(const QString &_name, int _id, bool _local, Client *_client, TabG table = new TableZone(this, this); connect(table, SIGNAL(sizeChanged()), this, SLOT(updateBoundingRect())); - hand = new HandZone(this, _local || (_parent->getSpectator() && _parent->getSpectatorsSeeEverything()), (int) table->boundingRect().height(), this); base = QPointF(deck->boundingRect().width() + counterAreaWidth + 5, 0); - hand->setPos(base); - base += QPointF(hand->boundingRect().width(), 0); - table->setPos(base); + + if (settingsCache->getHorizontalHand()) { + hand = new HandZoneHoriz(this, _local || (_parent->getSpectator() && _parent->getSpectatorsSeeEverything()), this); + + if (mirrored) { + hand->setPos(counterAreaWidth + CARD_WIDTH + 5, base.y()); + table->setPos(base.x(), base.y() + hand->boundingRect().height()); + } else { + table->setPos(base); + hand->setPos(counterAreaWidth + CARD_WIDTH + 5, base.y() + table->boundingRect().height()); + } + } else { + hand = new HandZoneVert(this, _local || (_parent->getSpectator() && _parent->getSpectatorsSeeEverything()), (int) table->boundingRect().height(), this); + hand->setPos(base); + base += QPointF(hand->boundingRect().width(), 0); + table->setPos(base); + } updateBoundingRect(); @@ -281,7 +295,10 @@ void Player::updateBgPixmap() void Player::updateBoundingRect() { prepareGeometryChange(); - bRect = QRectF(0, 0, CARD_WIDTH + 5 + counterAreaWidth + hand->boundingRect().width() + table->boundingRect().width(), table->boundingRect().height()); + if (settingsCache->getHorizontalHand()) + bRect = QRectF(0, 0, CARD_WIDTH + 5 + counterAreaWidth + table->boundingRect().width(), table->boundingRect().height() + hand->boundingRect().height()); + else + bRect = QRectF(0, 0, CARD_WIDTH + 5 + counterAreaWidth + hand->boundingRect().width() + table->boundingRect().width(), table->boundingRect().height()); emit sizeChanged(); } @@ -707,17 +724,16 @@ QRectF Player::boundingRect() const void Player::paint(QPainter *painter, const QStyleOptionGraphicsItem */*option*/, QWidget */*widget*/) { - if (bgPixmap.isNull()) - painter->fillRect(boundingRect(), QColor(200, 200, 200)); - else - painter->fillRect(boundingRect(), QBrush(bgPixmap)); - QString nameStr = getName(); QFont font("Times"); font.setPixelSize(20); // font.setWeight(QFont::Bold); int totalWidth = CARD_WIDTH + counterAreaWidth + 5; + if (bgPixmap.isNull()) + painter->fillRect(QRectF(0, 0, totalWidth, boundingRect().height()), QColor(200, 200, 200)); + else + painter->fillRect(QRectF(0, 0, totalWidth, boundingRect().height()), QBrush(bgPixmap)); if (getActive()) { QFontMetrics fm(font); @@ -995,3 +1011,18 @@ void Player::actMoveToExile(CardItem *card) CardZone *startZone = qgraphicsitem_cast(card->parentItem()); sendGameCommand(new Command_MoveCard(-1, startZone->getName(), card->getId(), "rfg", 0, 0, false)); } + +qreal Player::getMinimumWidth() const +{ + return table->getMinimumWidth() + CARD_WIDTH + 5 + counterAreaWidth; +} + +void Player::processSceneSizeChange(const QSizeF &newSize) +{ + // This will need to be changed if player areas are displayed side by side (e.g. 2x2 for a 4-player game) + qreal fullPlayerWidth = newSize.width(); + + qreal tableWidth = fullPlayerWidth - CARD_WIDTH - 5 - counterAreaWidth; + table->setWidth(tableWidth); + hand->setWidth(tableWidth); +} diff --git a/cockatrice/src/player.h b/cockatrice/src/player.h index e19093b1..4935d04b 100644 --- a/cockatrice/src/player.h +++ b/cockatrice/src/player.h @@ -112,6 +112,7 @@ private: int id; bool active; bool local; + bool mirrored; QMap zones; TableZone *table; @@ -164,13 +165,14 @@ public: void clearArrows(); Client *client; - Player(const QString &_name, int _id, bool _local, Client *_client, TabGame *_parent); + Player(const QString &_name, int _id, bool _local, bool _mirrored, Client *_client, TabGame *_parent); ~Player(); void retranslateUi(); QMenu *getPlayerMenu() const { return playerMenu; } int getId() const { return id; } QString getName() const { return name; } bool getLocal() const { return local; } + bool getMirrored() const { return mirrored; } const QMap &getZones() const { return zones; } const QMap &getArrows() const { return arrows; } TableZone *getTable() const { return table; } @@ -178,6 +180,9 @@ public: bool getActive() const { return active; } void setActive(bool _active); + qreal getMinimumWidth() const; + void processSceneSizeChange(const QSizeF &newSize); + void processPlayerInfo(ServerInfo_Player *info); void processGameEvent(GameEvent *event, GameEventContext *context); void sendGameCommand(GameCommand *command); diff --git a/cockatrice/src/settingscache.cpp b/cockatrice/src/settingscache.cpp index 5f2bcaad..f9aeddd0 100644 --- a/cockatrice/src/settingscache.cpp +++ b/cockatrice/src/settingscache.cpp @@ -17,6 +17,7 @@ SettingsCache::SettingsCache() picDownload = settings->value("personal/picturedownload", false).toBool(); doubleClickToPlay = settings->value("interface/doubleclicktoplay", true).toBool(); + horizontalHand = settings->value("hand/horizontal", false).toBool(); economicGrid = settings->value("table/economic", false).toBool(); zoneViewSortByName = settings->value("zoneview/sortbyname", false).toBool(); @@ -84,6 +85,12 @@ void SettingsCache::setDoubleClickToPlay(int _doubleClickToPlay) settings->setValue("interface/doubleclicktoplay", doubleClickToPlay); } +void SettingsCache::setHorizontalHand(int _horizontalHand) +{ + horizontalHand = _horizontalHand; + settings->setValue("hand/horizontal", horizontalHand); +} + void SettingsCache::setEconomicGrid(int _economicGrid) { economicGrid = _economicGrid; diff --git a/cockatrice/src/settingscache.h b/cockatrice/src/settingscache.h index d1616368..dc88cbaa 100644 --- a/cockatrice/src/settingscache.h +++ b/cockatrice/src/settingscache.h @@ -24,6 +24,7 @@ private: QString handBgPath, tableBgPath, playerBgPath; bool picDownload; bool doubleClickToPlay; + bool horizontalHand; bool economicGrid; bool zoneViewSortByName, zoneViewSortByType; public: @@ -37,6 +38,7 @@ public: QString getPlayerBgPath() const { return playerBgPath; } bool getPicDownload() const { return picDownload; } bool getDoubleClickToPlay() const { return doubleClickToPlay; } + bool getHorizontalHand() const { return horizontalHand; } bool getEconomicGrid() const { return economicGrid; } bool getZoneViewSortByName() const { return zoneViewSortByName; } bool getZoneViewSortByType() const { return zoneViewSortByType; } @@ -50,6 +52,7 @@ public slots: void setPlayerBgPath(const QString &_playerBgPath); void setPicDownload(int _picDownload); void setDoubleClickToPlay(int _doubleClickToPlay); + void setHorizontalHand(int _horizontalHand); void setEconomicGrid(int _economicGrid); void setZoneViewSortByName(int _zoneViewSortByName); void setZoneViewSortByType(int _zoneViewSortByType); diff --git a/cockatrice/src/tab_game.cpp b/cockatrice/src/tab_game.cpp index 9ebbe998..7ee11070 100644 --- a/cockatrice/src/tab_game.cpp +++ b/cockatrice/src/tab_game.cpp @@ -208,7 +208,8 @@ void TabGame::actRemoveLocalArrows() Player *TabGame::addPlayer(int playerId, const QString &playerName) { - Player *newPlayer = new Player(playerName, playerId, playerId == localPlayerId, client, this); + // XXX Find a different criterion for the 'mirrored' flag. When spectating, both players are not local, but only one should be mirrored. + Player *newPlayer = new Player(playerName, playerId, playerId == localPlayerId, playerId != localPlayerId, client, this); scene->addPlayer(newPlayer); connect(newPlayer, SIGNAL(newCardAdded(AbstractCardItem *)), this, SLOT(newCardAdded(AbstractCardItem *))); diff --git a/cockatrice/src/tablezone.cpp b/cockatrice/src/tablezone.cpp index 80ebafd2..cef7b027 100644 --- a/cockatrice/src/tablezone.cpp +++ b/cockatrice/src/tablezone.cpp @@ -17,6 +17,7 @@ TableZone::TableZone(Player *_p, QGraphicsItem *parent) else height = 4 * CARD_HEIGHT + 3 * paddingY; width = minWidth + 2 * marginX; + currentMinimumWidth = minWidth; setCacheMode(DeviceCoordinateCache); setAcceptsHoverEvents(true); @@ -43,7 +44,7 @@ void TableZone::paint(QPainter *painter, const QStyleOptionGraphicsItem */*optio painter->fillRect(boundingRect(), QBrush(bgPixmap)); painter->setPen(QColor(255, 255, 255, 40)); qreal separatorY = 3 * (CARD_HEIGHT + paddingY) - paddingY / 2; - if (!player->getLocal()) + if (player->getMirrored()) separatorY = height - separatorY; painter->drawLine(QPointF(0, separatorY), QPointF(width, separatorY)); } @@ -120,10 +121,10 @@ void TableZone::resizeToContents() xMax += 2 * CARD_WIDTH; if (xMax < minWidth) xMax = minWidth; - int newWidth = xMax + 2 * marginX; - if (newWidth != width) { + currentMinimumWidth = xMax + 2 * marginX; + if (currentMinimumWidth > width) { prepareGeometryChange(); - width = newWidth; + width = currentMinimumWidth; emit sizeChanged(); } } @@ -206,3 +207,9 @@ QPointF TableZone::closestGridPoint(const QPointF &point) { return mapFromGrid(mapToGrid(point + QPoint(CARD_WIDTH / 2, CARD_HEIGHT / 2))); } + +void TableZone::setWidth(qreal _width) +{ + prepareGeometryChange(); + width = _width; +} diff --git a/cockatrice/src/tablezone.h b/cockatrice/src/tablezone.h index b2410b18..3fd39285 100644 --- a/cockatrice/src/tablezone.h +++ b/cockatrice/src/tablezone.h @@ -9,6 +9,7 @@ signals: void sizeChanged(); private: int width, height; + int currentMinimumWidth; QPixmap bgPixmap; private slots: void updateBgPixmap(); @@ -32,6 +33,8 @@ public: QPointF closestGridPoint(const QPointF &point); CardItem *takeCard(int position, int cardId, const QString &cardName, bool canResize = true); void resizeToContents(); + int getMinimumWidth() const { return currentMinimumWidth; } + void setWidth(qreal _width); protected: void addCardImpl(CardItem *card, int x, int y); }; From ca12aeb5a797f2b7e0537e533fd22f6764b792ef Mon Sep 17 00:00:00 2001 From: Max-Wilhelm Bruker Date: Fri, 28 May 2010 16:41:59 +0200 Subject: [PATCH 5/6] load deck from clipboard; closing feature request 0000019 --- cockatrice/cockatrice.pro | 2 + cockatrice/src/dlg_creategame.cpp | 2 +- .../src/dlg_load_deck_from_clipboard.cpp | 64 ++++ cockatrice/src/dlg_load_deck_from_clipboard.h | 25 ++ cockatrice/src/window_deckeditor.cpp | 17 + cockatrice/src/window_deckeditor.h | 3 +- cockatrice/translations/cockatrice_de.ts | 328 ++++++++++-------- cockatrice/translations/cockatrice_en.ts | 322 +++++++++-------- common/decklist.cpp | 13 +- common/decklist.h | 2 + 10 files changed, 498 insertions(+), 280 deletions(-) create mode 100644 cockatrice/src/dlg_load_deck_from_clipboard.cpp create mode 100644 cockatrice/src/dlg_load_deck_from_clipboard.h diff --git a/cockatrice/cockatrice.pro b/cockatrice/cockatrice.pro index a4e04489..44102ead 100644 --- a/cockatrice/cockatrice.pro +++ b/cockatrice/cockatrice.pro @@ -26,6 +26,7 @@ HEADERS += src/counter.h \ src/gameview.h \ src/deck_picturecacher.h \ src/decklistmodel.h \ + src/dlg_load_deck_from_clipboard.h \ src/dlg_load_remote_deck.h \ src/cardinfowidget.h \ src/messagelogwidget.h \ @@ -81,6 +82,7 @@ SOURCES += src/counter.cpp \ src/gameview.cpp \ src/deck_picturecacher.cpp \ src/decklistmodel.cpp \ + src/dlg_load_deck_from_clipboard.cpp \ src/dlg_load_remote_deck.cpp \ src/cardinfowidget.cpp \ src/messagelogwidget.cpp \ diff --git a/cockatrice/src/dlg_creategame.cpp b/cockatrice/src/dlg_creategame.cpp index fe59fefa..41406cc5 100644 --- a/cockatrice/src/dlg_creategame.cpp +++ b/cockatrice/src/dlg_creategame.cpp @@ -24,7 +24,7 @@ DlgCreateGame::DlgCreateGame(Client *_client, QWidget *parent) spectatorsAllowedCheckBox->setChecked(true); connect(spectatorsAllowedCheckBox, SIGNAL(stateChanged(int)), this, SLOT(spectatorsAllowedChanged(int))); spectatorsNeedPasswordCheckBox = new QCheckBox(tr("Spectators &need a password to join")); - spectatorsCanTalkCheckBox = new QCheckBox(tr("Spectators can &talk")); + spectatorsCanTalkCheckBox = new QCheckBox(tr("Spectators can &chat")); spectatorsSeeEverythingCheckBox = new QCheckBox(tr("Spectators see &everything")); QVBoxLayout *spectatorsLayout = new QVBoxLayout; spectatorsLayout->addWidget(spectatorsAllowedCheckBox); diff --git a/cockatrice/src/dlg_load_deck_from_clipboard.cpp b/cockatrice/src/dlg_load_deck_from_clipboard.cpp new file mode 100644 index 00000000..36741590 --- /dev/null +++ b/cockatrice/src/dlg_load_deck_from_clipboard.cpp @@ -0,0 +1,64 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "dlg_load_deck_from_clipboard.h" +#include "decklist.h" + +DlgLoadDeckFromClipboard::DlgLoadDeckFromClipboard(QWidget *parent) + : QDialog(parent), deckList(0) +{ + contentsEdit = new QPlainTextEdit; + + refreshButton = new QPushButton(tr("&Refresh")); + refreshButton->setShortcut(QKeySequence("F5")); + okButton = new QPushButton(tr("&OK")); + okButton->setDefault(true); + cancelButton = new QPushButton(tr("&Cancel")); + + QHBoxLayout *buttonLayout = new QHBoxLayout; + buttonLayout->addWidget(refreshButton); + buttonLayout->addStretch(); + buttonLayout->addWidget(okButton); + buttonLayout->addWidget(cancelButton); + + QVBoxLayout *mainLayout = new QVBoxLayout; + mainLayout->addWidget(contentsEdit); + mainLayout->addLayout(buttonLayout); + + setLayout(mainLayout); + + setWindowTitle(tr("Load deck from clipboard")); + resize(500, 500); + + connect(refreshButton, SIGNAL(clicked()), this, SLOT(actRefresh())); + connect(okButton, SIGNAL(clicked()), this, SLOT(actOK())); + connect(cancelButton, SIGNAL(clicked()), this, SLOT(reject())); + + actRefresh(); +} + +void DlgLoadDeckFromClipboard::actRefresh() +{ + contentsEdit->setPlainText(QApplication::clipboard()->text()); +} + +void DlgLoadDeckFromClipboard::actOK() +{ + QString buffer = contentsEdit->toPlainText(); + QTextStream stream(&buffer); + + DeckList *l = new DeckList; + if (l->loadFromStream_Plain(stream)) { + deckList = l; + accept(); + } else { + QMessageBox::critical(this, tr("Error"), tr("Invalid deck list.")); + delete l; + } +} diff --git a/cockatrice/src/dlg_load_deck_from_clipboard.h b/cockatrice/src/dlg_load_deck_from_clipboard.h new file mode 100644 index 00000000..f3db6ce6 --- /dev/null +++ b/cockatrice/src/dlg_load_deck_from_clipboard.h @@ -0,0 +1,25 @@ +#ifndef DLG_LOAD_DECK_FROM_CLIPBOARD_H +#define DLG_LOAD_DECK_FROM_CLIPBOARD_H + +#include + +class DeckList; +class QPlainTextEdit; +class QPushButton; + +class DlgLoadDeckFromClipboard : public QDialog { + Q_OBJECT +private slots: + void actOK(); + void actRefresh(); +private: + DeckList *deckList; +public: + DlgLoadDeckFromClipboard(QWidget *parent = 0); + DeckList *getDeckList() const { return deckList; } +private: + QPlainTextEdit *contentsEdit; + QPushButton *refreshButton, *okButton, *cancelButton; +}; + +#endif diff --git a/cockatrice/src/window_deckeditor.cpp b/cockatrice/src/window_deckeditor.cpp index 2d3492de..b059732c 100644 --- a/cockatrice/src/window_deckeditor.cpp +++ b/cockatrice/src/window_deckeditor.cpp @@ -7,6 +7,7 @@ #include "cardinfowidget.h" #include "deck_picturecacher.h" #include "dlg_cardsearch.h" +#include "dlg_load_deck_from_clipboard.h" #include "main.h" void SearchLineEdit::keyPressEvent(QKeyEvent *event) @@ -122,6 +123,8 @@ WndDeckEditor::WndDeckEditor(QWidget *parent) aLoadDeck = new QAction(tr("&Load deck..."), this); aLoadDeck->setShortcuts(QKeySequence::Open); connect(aLoadDeck, SIGNAL(triggered()), this, SLOT(actLoadDeck())); + aLoadDeckFromClipboard = new QAction(tr("Load deck from cl&ipboard..."), this); + connect(aLoadDeckFromClipboard, SIGNAL(triggered()), this, SLOT(actLoadDeckFromClipboard())); aSaveDeck = new QAction(tr("&Save deck"), this); aSaveDeck->setShortcuts(QKeySequence::Save); connect(aSaveDeck, SIGNAL(triggered()), this, SLOT(actSaveDeck())); @@ -141,6 +144,7 @@ WndDeckEditor::WndDeckEditor(QWidget *parent) deckMenu = menuBar()->addMenu(tr("&Deck")); deckMenu->addAction(aNewDeck); deckMenu->addAction(aLoadDeck); + deckMenu->addAction(aLoadDeckFromClipboard); deckMenu->addAction(aSaveDeck); deckMenu->addAction(aSaveDeckAs); deckMenu->addSeparator(); @@ -275,6 +279,19 @@ void WndDeckEditor::actLoadDeck() delete l; } +void WndDeckEditor::actLoadDeckFromClipboard() +{ + if (!confirmClose()) + return; + + DlgLoadDeckFromClipboard dlg; + if (!dlg.exec()) + return; + + setDeck(dlg.getDeckList()); + setWindowModified(true); +} + bool WndDeckEditor::actSaveDeck() { if (lastFileName.isEmpty()) diff --git a/cockatrice/src/window_deckeditor.h b/cockatrice/src/window_deckeditor.h index dc8b6fe4..4c095469 100644 --- a/cockatrice/src/window_deckeditor.h +++ b/cockatrice/src/window_deckeditor.h @@ -36,6 +36,7 @@ private slots: void actNewDeck(); void actLoadDeck(); + void actLoadDeckFromClipboard(); bool actSaveDeck(); bool actSaveDeckAs(); void actPrintDeck(); @@ -70,7 +71,7 @@ private: DlgCardSearch *dlgCardSearch; QMenu *deckMenu, *dbMenu; - QAction *aNewDeck, *aLoadDeck, *aSaveDeck, *aSaveDeckAs, *aPrintDeck, *aClose; + QAction *aNewDeck, *aLoadDeck, *aLoadDeckFromClipboard, *aSaveDeck, *aSaveDeckAs, *aPrintDeck, *aClose; QAction *aEditSets, *aSearch, *aClearSearch; QAction *aAddCard, *aAddCardToSideboard, *aRemoveCard, *aIncrement, *aDecrement; public: diff --git a/cockatrice/translations/cockatrice_de.ts b/cockatrice/translations/cockatrice_de.ts index 328e0a44..99c0f084 100644 --- a/cockatrice/translations/cockatrice_de.ts +++ b/cockatrice/translations/cockatrice_de.ts @@ -27,47 +27,57 @@ AppearanceSettingsPage - + Zone background pictures Hintergrundbilder für Kartenzonen - + Path to hand background: Hintergrundbild für die Hand: - + Path to table background: Hintergrundbild für das Spielfeld: - + Path to player info background: Hintergrundbild für den Spielerbereich: - + + Hand layout + Kartenhand + + + + Display hand horizontally (wastes space) + Hand horizonal anzeigen (verschwendet Platz) + + + Table grid layout Spielfeldraster - + Economic layout Platzsparende Anordnung - + Zone view layout Aussehen des Zonenbetrachters - + Sort by name nach Namen sortieren - + Sort by type nach Kartentypen sortieren @@ -76,9 +86,9 @@ standardmäßig alphabetisch sortieren - - - + + + Choose path Pfad auswählen @@ -486,9 +496,13 @@ Zuschauer brauchen &auch ein Passwort - Spectators can &talk - Zuschauer können sp&rechen + Zuschauer können sp&rechen + + + + Spectators can &chat + Zuschauer können s&chreiben @@ -561,6 +575,39 @@ Mitteilung hinzufügen + + DlgLoadDeckFromClipboard + + + &Refresh + &Aktualisieren + + + + &OK + &OK + + + + &Cancel + A&bbrechen + + + + Load deck from clipboard + Deck aus der Zwischenablage laden + + + + Error + Fehler + + + + Invalid deck list. + Ungültige Deckliste. + + DlgLoadRemoteDeck @@ -582,54 +629,54 @@ DlgSettings - - - + + + Error Fehler - + Your card database is invalid. Please check if the path is set correctly. Ihre Kartendatenbank ist ungültig. Bitte überprüfen Sie, ob der Pfad korrekt gesetzt ist. - + The path to your deck directory is invalid. Der Pfad zum Deckverzeichnis ist ungültig. - + The path to your card pictures directory is invalid. Der Pfad zum Kartenbilderverzeichnis ist ungültig. - + Settings Einstellungen - + General Allgemeines - + Appearance Erscheinungsbild - + User interface Bedienung - + Messages Nachrichten - + &Close S&chließen @@ -965,7 +1012,7 @@ GameView - + Esc Esc @@ -1808,12 +1855,12 @@ MessagesSettingsPage - + &Add &Hinzufügen - + &Remove &Entfernen @@ -1826,12 +1873,12 @@ Entfernen - + Add message Nachricht hinzufügen - + Message: Nachricht: @@ -1897,41 +1944,41 @@ Player - - - + + + Move to &top of library Oben auf die Biblio&thek legen - - - + + + Move to &bottom of library Unter die &Bibliothek legen - + &View library &Zeige Bibliothek - + F3 F3 - + View &top cards of library... Zeige die oberen Kar&ten der Bibliothek... - + &View graveyard &Zeige Friedhof - + F4 F4 @@ -1940,32 +1987,32 @@ Zeige ent&fernte Karten - + &View sideboard Zeige &Sideboard - + Player "%1" Spieler "%1" - + Take &mulligan &Mulligan nehmen - + &Hand &Hand - + &Library Bib&liothek - + &Graveyard &Friedhof @@ -1974,70 +2021,70 @@ Entfe&rnte Karten - + &Sideboard &Sideboard - + View top cards of library Zeige die obersten Karten der Bibliothek - + Number of cards: Anzahl der Karten: - + &Draw card Karte &ziehen - + &View exile &Zeige Exil - + &Exile &Exil - - + + Move to &hand auf die &Hand nehmen - - + + Move to g&raveyard auf den &Friedhof legen - - + + Move to &exile ins &Exil schicken - + Ctrl+W Ctrl+W - + Ctrl+D Ctrl+D - + D&raw cards... Ka&rten ziehen... - + Ctrl+E Ctrl+E @@ -2046,32 +2093,32 @@ &Mulligan nehmen... - + Ctrl+M Ctrl+M - + &Shuffle Mi&schen - + Ctrl+S Ctrl+S - + &Counters &Zähler - + &Untap all permanents &Enttappe alle bleibenden Karten - + Ctrl+U Ctrl+U @@ -2100,143 +2147,143 @@ Ctrl+L - + R&oll die... &Würfeln... - + Ctrl+I Ctrl+I - + &Create token... &Token erstellen... - + Ctrl+T Ctrl+T - + S&ay &Sagen - + C&ard &Karte - + &Tap &Tappen - + &Untap E&nttappen - + Toggle &normal untapping &Normales Enttappen umschalten - + &Flip &Umdrehen - + &Add counter Zählm&arke hinzufügen - + &Remove counter Zählma&rke entfernen - + &Set counters... &Setze Zählmarken... - + &top of library &auf die Bibliothek - + &bottom of library &unter die Bibliothek - + &graveyard in den &Friedhof - + Ctrl+Del Ctrl+Del - + &exile ins &Exil - + &Move to &Verschieben - + F5 F5 - + F6 F6 - + F7 F7 - + F8 F8 - + F9 F9 - + F10 F10 - + Draw cards Karten ziehen - - + + Number: Anzahl: - + Set counters Setze Zählmarken @@ -2249,22 +2296,22 @@ Neue Lebenspunkte insgesamt: - + Roll die Würfeln - + Number of sides: Anzahl der Seiten: - + Create token Token erstellen - + Name: Name: @@ -2573,7 +2620,7 @@ Bitte geben Sie einen Namen ein: Sind Sie sicher, dass Sie das Spiel verlassen möchten? - + Load deck Deck laden @@ -2609,12 +2656,12 @@ Bitte geben Sie einen Namen ein: UserInterfaceSettingsPage - + General interface settings Allgemeine Bedienung - + &Double-click cards to play them (instead of single-click) Karten durch &Doppelklick ausspielen (statt Einzelklick) @@ -2622,37 +2669,37 @@ Bitte geben Sie einen Namen ein: WndDeckEditor - + &Search for: &Suchen nach: - + Deck &name: Deck &Name: - + &Comments: &Kommentare: - + Deck editor [*] Deck-Editor [*] - + &New deck &Neues Deck - + &Load deck... Deck &laden... - + &Save deck Deck &speichern @@ -2661,32 +2708,32 @@ Bitte geben Sie einen Namen ein: Deck &speichern unter... - + Save deck &as... Deck s&peichern unter... - + &Print deck... Deck &drucken... - + &Close S&chließen - + Ctrl+Q Ctrl+Q - + &Edit sets... &Editionen bearbeiten... - + &Deck &Deck @@ -2695,27 +2742,27 @@ Bitte geben Sie einen Namen ein: &Editionen - + Add card to &maindeck Karte zu&m Hauptdeck hinzufügen - + Return Return - + Enter Enter - + Ctrl+Return Ctrl+Return - + Ctrl+Enter Ctrl+Enter @@ -2724,7 +2771,7 @@ Bitte geben Sie einen Namen ein: Ctrl+M - + Add card to &sideboard Karte zum &Sideboard hinzufügen @@ -2733,69 +2780,74 @@ Bitte geben Sie einen Namen ein: Ctrl+N - + &Search... &Suchen... - + &Clear search Suche a&ufheben - + + Load deck from cl&ipboard... + Deck aus &Zwischenablage laden... + + + &Card database &Kartendatenbank - + &Remove row Zeile entfe&rnen - + Del Entf - + &Increment number Anzahl er&höhen - + + + - + &Decrement number Anzahl v&erringern - + - - - + Are you sure? Bist du sicher? - + The decklist has been modified. Do you want to save the changes? Die Deckliste wurde verändert. Willst du die Änderungen speichern? - + Load deck Deck laden - + Save deck Deck speichern diff --git a/cockatrice/translations/cockatrice_en.ts b/cockatrice/translations/cockatrice_en.ts index 2d9eba8b..00932289 100644 --- a/cockatrice/translations/cockatrice_en.ts +++ b/cockatrice/translations/cockatrice_en.ts @@ -4,54 +4,64 @@ AppearanceSettingsPage - + Zone background pictures - + Path to hand background: - + Path to table background: - + Path to player info background: - + + Hand layout + + + + + Display hand horizontally (wastes space) + + + + Table grid layout - + Economic layout - + Zone view layout - + Sort by name - + Sort by type - - - + + + Choose path @@ -407,7 +417,7 @@ - Spectators can &talk + Spectators can &chat @@ -446,6 +456,39 @@ + + DlgLoadDeckFromClipboard + + + &Refresh + + + + + &OK + + + + + &Cancel + + + + + Load deck from clipboard + + + + + Error + + + + + Invalid deck list. + + + DlgLoadRemoteDeck @@ -467,54 +510,54 @@ DlgSettings - - - + + + Error - + Your card database is invalid. Please check if the path is set correctly. - + The path to your deck directory is invalid. - + The path to your card pictures directory is invalid. - + Settings - + General - + Appearance - + User interface - + Messages - + &Close @@ -588,7 +631,7 @@ GameView - + Esc @@ -1135,22 +1178,22 @@ MessagesSettingsPage - + &Add - + &Remove - + Add message - + Message: @@ -1216,330 +1259,330 @@ Player - - - + + + Move to &top of library - - - + + + Move to &bottom of library - + &View library - + F3 - + View &top cards of library... - + &View graveyard - + F4 - + &View sideboard - + Player "%1" - + &Hand - + &Library - + &Graveyard - + &Sideboard - + View top cards of library - + Number of cards: - + &Draw card - + &View exile - + &Exile - - + + Move to &hand - - + + Move to g&raveyard - - + + Move to &exile - + Ctrl+W - + Ctrl+D - + D&raw cards... - + Ctrl+E - + Take &mulligan - + Ctrl+M - + &Shuffle - + Ctrl+S - + &Counters - + &Untap all permanents - + Ctrl+U - + R&oll die... - + Ctrl+I - + &Create token... - + Ctrl+T - + S&ay - + C&ard - + &Tap - + &Untap - + Toggle &normal untapping - + &Flip - + &Add counter - + &Remove counter - + &Set counters... - + &top of library - + &bottom of library - + &graveyard - + Ctrl+Del - + &exile - + &Move to - + F5 - + F6 - + F7 - + F8 - + F9 - + F10 - + Draw cards - - + + Number: - + Roll die - + Number of sides: - + Create token - + Name: - + Set counters @@ -1827,7 +1870,7 @@ Please enter a name: - + Load deck @@ -1848,12 +1891,12 @@ Please enter a name: UserInterfaceSettingsPage - + General interface settings - + &Double-click cards to play them (instead of single-click) @@ -1861,162 +1904,167 @@ Please enter a name: WndDeckEditor - + &Search for: - + Deck &name: - + &Comments: - + Deck editor [*] - + &New deck - + &Load deck... - - &Save deck + + Load deck from cl&ipboard... - Save deck &as... + &Save deck - &Print deck... + Save deck &as... + &Print deck... + + + + &Close - + Ctrl+Q - + &Edit sets... - + &Deck - + Load deck - + Save deck - + Add card to &maindeck - + Return - + Enter - + Ctrl+Return - + Ctrl+Enter - + Add card to &sideboard - + &Search... - + &Clear search - + &Card database - + &Remove row - + Del - + &Increment number - + + - + &Decrement number - + - - + Are you sure? - + The decklist has been modified. Do you want to save the changes? diff --git a/common/decklist.cpp b/common/decklist.cpp index 376a3298..58c161b4 100644 --- a/common/decklist.cpp +++ b/common/decklist.cpp @@ -359,11 +359,11 @@ bool DeckList::saveToFile_Native(QIODevice *device) return true; } -bool DeckList::loadFromFile_Plain(QIODevice *device) +bool DeckList::loadFromStream_Plain(QTextStream &in) { InnerDecklistNode *main = 0, *side = 0; - QTextStream in(device); + int okRows = 0; while (!in.atEnd()) { QString line = in.readLine().simplified(); if (line.startsWith("//")) @@ -393,9 +393,16 @@ bool DeckList::loadFromFile_Plain(QIODevice *device) int number = line.left(i).toInt(&ok); if (!ok) continue; + ++okRows; new DecklistCardNode(line.mid(i + 1), number, zone); } - return true; + return (okRows > 0); +} + +bool DeckList::loadFromFile_Plain(QIODevice *device) +{ + QTextStream in(device); + return loadFromStream_Plain(in); } bool DeckList::saveToFile_Plain(QIODevice *device) diff --git a/common/decklist.h b/common/decklist.h index e55bba30..39ec1efa 100644 --- a/common/decklist.h +++ b/common/decklist.h @@ -9,6 +9,7 @@ class CardDatabase; class QIODevice; +class QTextStream; class QXmlStreamReader; class QXmlStreamWriter; @@ -137,6 +138,7 @@ public: bool loadFromFile_Native(QIODevice *device); bool saveToFile_Native(QIODevice *device); + bool loadFromStream_Plain(QTextStream &stream); bool loadFromFile_Plain(QIODevice *device); bool saveToFile_Plain(QIODevice *device); bool loadFromFile(const QString &fileName, FileFormat fmt); From ac15d1b5e8d6d7f4fbea3c3358089c72cc3a823b Mon Sep 17 00:00:00 2001 From: Max-Wilhelm Bruker Date: Fri, 28 May 2010 16:47:08 +0200 Subject: [PATCH 6/6] spectator leave bugfix --- cockatrice/src/tab_game.cpp | 15 +++++++++++---- cockatrice/src/tab_game.h | 2 ++ 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/cockatrice/src/tab_game.cpp b/cockatrice/src/tab_game.cpp index 7ee11070..c4535f03 100644 --- a/cockatrice/src/tab_game.cpp +++ b/cockatrice/src/tab_game.cpp @@ -232,6 +232,7 @@ void TabGame::processGameEventContainer(GameEventContainer *cont) if (spectators.contains(event->getPlayerId())) { switch (event->getItemId()) { case ItemId_Event_Say: eventSpectatorSay(qobject_cast(event), context); break; + case ItemId_Event_Leave: eventSpectatorLeave(qobject_cast(event), context); break; default: { qDebug() << "unhandled spectator game event"; break; @@ -305,6 +306,16 @@ void TabGame::eventSpectatorSay(Event_Say *event, GameEventContext * /*context*/ messageLog->logSpectatorSay(spectators.value(event->getPlayerId()), event->getMessage()); } +void TabGame::eventSpectatorLeave(Event_Leave *event, GameEventContext * /*context*/) +{ + int playerId = event->getPlayerId(); + messageLog->logLeaveSpectator(spectators.value(playerId)); + playerListWidget->removePlayer(playerId); + spectators.remove(playerId); + + emit userEvent(); +} + void TabGame::eventGameStateChanged(Event_GameStateChanged *event, GameEventContext * /*context*/) { const QList &plList = event->getPlayerList(); @@ -382,10 +393,6 @@ void TabGame::eventLeave(Event_Leave *event, GameEventContext * /*context*/) playerListWidget->removePlayer(playerId); players.remove(playerId); delete player; - } else if (spectators.contains(playerId)) { - messageLog->logLeaveSpectator(spectators.value(playerId)); - playerListWidget->removePlayer(playerId); - spectators.remove(playerId); } emit userEvent(); } diff --git a/cockatrice/src/tab_game.h b/cockatrice/src/tab_game.h index 3f93b8e9..c9c6991f 100644 --- a/cockatrice/src/tab_game.h +++ b/cockatrice/src/tab_game.h @@ -76,6 +76,8 @@ private: void stopGame(); void eventSpectatorSay(Event_Say *event, GameEventContext *context); + void eventSpectatorLeave(Event_Leave *event, GameEventContext *context); + void eventGameStateChanged(Event_GameStateChanged *event, GameEventContext *context); void eventPlayerPropertiesChanged(Event_PlayerPropertiesChanged *event, GameEventContext *context); void eventJoin(Event_Join *event, GameEventContext *context);