diff --git a/cockatrice/src/client.cpp b/cockatrice/src/client.cpp index f5b9d28d..2e07d54a 100644 --- a/cockatrice/src/client.cpp +++ b/cockatrice/src/client.cpp @@ -131,15 +131,28 @@ void Client::readLine() resp = RespErr; emit responseReceived(msgid, resp); } else if (prefix == "list_games") { - emit gameListEvent(new ServerGame(values[0].toInt(), values[5], values[1], values[2].toInt(), values[3].toInt(), values[4].toInt())); - } else if ((prefix == "list_players") || (prefix == "list_counters") || (prefix == "list_zones") || (prefix == "dump_zone") || (prefix == "welcome")) { + if (values.size() != 8) + return; + emit gameListEvent(new ServerGame(values[0].toInt(), values[5], values[1], values[2].toInt(), values[3].toInt(), values[4].toInt(), values[6].toInt(), values[7].toInt())); + } else if (prefix == "welcome") { + if (values.size() != 2) { + emit protocolVersionMismatch(); + disconnectFromServer(); + } else if (values[0].toInt() != protocolVersion) { + emit protocolVersionMismatch(); + disconnectFromServer(); + } else { + emit welcomeMsgReceived(values[1]); + setStatus(StatusLoggingIn); + login(playerName, password); + } + } else if ((prefix == "list_players") || (prefix == "list_counters") || (prefix == "list_zones") || (prefix == "dump_zone")) { int cmdid = values.takeFirst().toInt(); if (values[0] == ".") { QListIterator i(msgbuf); QList playerlist; QList zonelist; QList zonedump; - QStringList welcomemsg; while (i.hasNext()) { QStringList val = i.next(); @@ -152,8 +165,6 @@ void Client::readLine() zonelist << new ServerZone(val[0], val[1] == "1", val[2] == "1", val[3].toInt()); else if (prefix == "dump_zone") zonedump << new ServerZoneCard(val[0].toInt(), val[1], val[2].toInt(), val[3].toInt(), val[4].toInt(), val[5] == "1", val[6]); - else if (prefix == "welcome") - welcomemsg << val[0]; } if (prefix == "list_players") emit playerListReceived(playerlist); @@ -163,11 +174,6 @@ void Client::readLine() emit zoneListReceived(cmdid, zonelist); else if (prefix == "dump_zone") emit zoneDumpReceived(cmdid, zonedump); - else if (prefix == "welcome") { - emit welcomeMsgReceived(welcomemsg); - setStatus(StatusLoggingIn); - login(playerName, password); - } msgbuf.clear(); } else msgbuf << values; @@ -263,16 +269,16 @@ PendingCommand *Client::listPlayers() return cmd("list_players"); } -PendingCommand *Client::createGame(const QString &description, const QString &password, unsigned int maxPlayers) +PendingCommand *Client::createGame(const QString &description, const QString &password, unsigned int maxPlayers, bool spectatorsAllowed) { - PendingCommand *pc = cmd(QString("create_game|%1|%2|%3").arg(description).arg(password).arg(maxPlayers)); + PendingCommand *pc = cmd(QString("create_game|%1|%2|%3|%4").arg(description).arg(password).arg(maxPlayers).arg(spectatorsAllowed ? 1 : 0)); connect(pc, SIGNAL(finished(ServerResponse)), this, SLOT(enterGameResponse(ServerResponse))); return pc; } -PendingCommand *Client::joinGame(int gameId, const QString &password) +PendingCommand *Client::joinGame(int gameId, const QString &password, bool spectator) { - PendingCommand *pc = cmd(QString("join_game|%1|%2").arg(gameId).arg(password)); + PendingCommand *pc = cmd(QString("join_game|%1|%2|%3").arg(gameId).arg(password).arg(spectator ? 1 : 0)); connect(pc, SIGNAL(finished(ServerResponse)), this, SLOT(enterGameResponse(ServerResponse))); return pc; } diff --git a/cockatrice/src/client.h b/cockatrice/src/client.h index ab4b0121..876669f8 100644 --- a/cockatrice/src/client.h +++ b/cockatrice/src/client.h @@ -52,7 +52,7 @@ class Client : public QObject { Q_OBJECT signals: void statusChanged(ProtocolStatus _status); - void welcomeMsgReceived(QStringList welcomeMsg); + void welcomeMsgReceived(QString welcomeMsg); void gameListEvent(ServerGame *game); void playerListReceived(QList players); void zoneListReceived(int commandId, QList zones); @@ -64,6 +64,7 @@ signals: void serverTimeout(); void logSocketError(const QString &errorString); void serverError(ServerResponse resp); + void protocolVersionMismatch(); private slots: void slotConnected(); void readLine(); @@ -75,6 +76,7 @@ private slots: void enterGameResponse(ServerResponse response); void leaveGameResponse(ServerResponse response); private: + static const int protocolVersion = 1; QTimer *timer; QList PendingCommands; QTcpSocket *socket; @@ -100,8 +102,8 @@ public slots: PendingCommand *chatSay(const QString &name, const QString &s); PendingCommand *listGames(); PendingCommand *listPlayers(); - PendingCommand *createGame(const QString &description, const QString &password, unsigned int maxPlayers); - PendingCommand *joinGame(int gameId, const QString &password); + PendingCommand *createGame(const QString &description, const QString &password, unsigned int maxPlayers, bool spectatorsAllowed); + PendingCommand *joinGame(int gameId, const QString &password, bool spectator); PendingCommand *leaveGame(); PendingCommand *login(const QString &name, const QString &pass); PendingCommand *say(const QString &s); diff --git a/cockatrice/src/dlg_creategame.cpp b/cockatrice/src/dlg_creategame.cpp index 70c14f62..9524df3a 100644 --- a/cockatrice/src/dlg_creategame.cpp +++ b/cockatrice/src/dlg_creategame.cpp @@ -15,6 +15,9 @@ DlgCreateGame::DlgCreateGame(Client *_client, QWidget *parent) maxPlayersLabel = new QLabel(tr("P&layers:")); maxPlayersEdit = new QLineEdit("2"); maxPlayersLabel->setBuddy(maxPlayersEdit); + + spectatorsAllowedCheckBox = new QCheckBox(tr("&Spectators allowed")); + spectatorsAllowedCheckBox->setChecked(true); QGridLayout *grid = new QGridLayout; grid->addWidget(descriptionLabel, 0, 0); @@ -23,6 +26,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); okButton = new QPushButton(tr("&OK")); okButton->setDefault(true); @@ -54,7 +58,7 @@ void DlgCreateGame::actOK() QMessageBox::critical(this, tr("Error"), tr("Invalid number of players.")); return; } - PendingCommand *createCommand = client->createGame(descriptionEdit->text(), passwordEdit->text(), maxPlayers); + PendingCommand *createCommand = client->createGame(descriptionEdit->text(), passwordEdit->text(), maxPlayers, spectatorsAllowedCheckBox->isChecked()); connect(createCommand, SIGNAL(finished(ServerResponse)), this, SLOT(checkResponse(ServerResponse))); okButton->setEnabled(false); cancelButton->setEnabled(false); diff --git a/cockatrice/src/dlg_creategame.h b/cockatrice/src/dlg_creategame.h index e2cc7a12..9a2a9ebf 100644 --- a/cockatrice/src/dlg_creategame.h +++ b/cockatrice/src/dlg_creategame.h @@ -7,6 +7,7 @@ class QLabel; class QLineEdit; class QPushButton; +class QCheckBox; class DlgCreateGame : public QDialog { Q_OBJECT @@ -20,6 +21,7 @@ private: QLabel *descriptionLabel, *passwordLabel, *maxPlayersLabel; QLineEdit *descriptionEdit, *passwordEdit, *maxPlayersEdit; + QCheckBox *spectatorsAllowedCheckBox; QPushButton *okButton, *cancelButton; }; diff --git a/cockatrice/src/gameselector.cpp b/cockatrice/src/gameselector.cpp index 58a8cdd5..82a8e48c 100644 --- a/cockatrice/src/gameselector.cpp +++ b/cockatrice/src/gameselector.cpp @@ -11,10 +11,12 @@ GameSelector::GameSelector(Client *_client, QWidget *parent) createButton = new QPushButton; joinButton = new QPushButton; + spectateButton = new QPushButton; QHBoxLayout *buttonLayout = new QHBoxLayout; buttonLayout->addStretch(); buttonLayout->addWidget(createButton); buttonLayout->addWidget(joinButton); + buttonLayout->addWidget(spectateButton); QVBoxLayout *mainLayout = new QVBoxLayout; mainLayout->addWidget(gameListView); @@ -28,6 +30,7 @@ GameSelector::GameSelector(Client *_client, QWidget *parent) connect(createButton, SIGNAL(clicked()), this, SLOT(actCreate())); connect(joinButton, SIGNAL(clicked()), this, SLOT(actJoin())); + connect(spectateButton, SIGNAL(clicked()), this, SLOT(actJoin())); } void GameSelector::actCreate() @@ -46,6 +49,7 @@ void GameSelector::checkResponse(ServerResponse response) { createButton->setEnabled(true); joinButton->setEnabled(true); + spectateButton->setEnabled(true); if (response == RespOk) disableGameList(); @@ -57,6 +61,8 @@ void GameSelector::checkResponse(ServerResponse response) void GameSelector::actJoin() { + bool spectator = sender() == spectateButton; + QModelIndex ind = gameListView->currentIndex(); if (!ind.isValid()) return; @@ -69,10 +75,11 @@ void GameSelector::actJoin() return; } - PendingCommand *joinCommand = client->joinGame(game->getGameId(), password); + PendingCommand *joinCommand = client->joinGame(game->getGameId(), password, spectator); connect(joinCommand, SIGNAL(finished(ServerResponse)), this, SLOT(checkResponse(ServerResponse))); createButton->setEnabled(false); joinButton->setEnabled(false); + spectateButton->setEnabled(false); } void GameSelector::enableGameList() @@ -99,4 +106,5 @@ void GameSelector::retranslateUi() { createButton->setText(tr("C&reate")); joinButton->setText(tr("&Join")); + spectateButton->setText(tr("J&oin as spectator")); } \ No newline at end of file diff --git a/cockatrice/src/gameselector.h b/cockatrice/src/gameselector.h index fe3ac8cf..6f5d1cb8 100644 --- a/cockatrice/src/gameselector.h +++ b/cockatrice/src/gameselector.h @@ -26,7 +26,7 @@ private: QTreeView *gameListView; GamesModel *gameListModel; - QPushButton *createButton, *joinButton; + QPushButton *createButton, *joinButton, *spectateButton; }; #endif diff --git a/cockatrice/src/messagelogwidget.cpp b/cockatrice/src/messagelogwidget.cpp index b7eaa6d5..34d6f03e 100644 --- a/cockatrice/src/messagelogwidget.cpp +++ b/cockatrice/src/messagelogwidget.cpp @@ -17,13 +17,9 @@ void MessageLogWidget::logConnecting(QString hostname) append(tr("Connecting to %1...").arg(sanitizeHtml(hostname))); } -void MessageLogWidget::logConnected(const QStringList WelcomeMsg) +void MessageLogWidget::logConnected(QString welcomeMsg) { - append(tr("Connected.")); - - QStringListIterator i(WelcomeMsg); - while (i.hasNext()) - append(i.next()); + append(tr("Connected: %1").arg(welcomeMsg)); } void MessageLogWidget::logDisconnected() @@ -44,6 +40,11 @@ void MessageLogWidget::logServerError(ServerResponse response) } } +void MessageLogWidget::logProtocolVersionMismatch() +{ + append(tr("Protocol version mismatch.")); +} + void MessageLogWidget::logPlayerListReceived(QStringList players) { append("---"); diff --git a/cockatrice/src/messagelogwidget.h b/cockatrice/src/messagelogwidget.h index 598b72e7..78dca0e4 100644 --- a/cockatrice/src/messagelogwidget.h +++ b/cockatrice/src/messagelogwidget.h @@ -17,10 +17,11 @@ private: QString trZoneName(CardZone *zone, Player *player, bool hisOwn, GrammaticalCase gc) const; public slots: void logConnecting(QString hostname); - void logConnected(const QStringList WelcomeMsg); + void logConnected(QString welcomeMsg); void logDisconnected(); void logSocketError(const QString &errorString); void logServerError(ServerResponse response); + void logProtocolVersionMismatch(); private slots: void logPlayerListReceived(QStringList players); void logJoin(Player *player); diff --git a/cockatrice/src/servergame.h b/cockatrice/src/servergame.h index 530595da..a5295266 100644 --- a/cockatrice/src/servergame.h +++ b/cockatrice/src/servergame.h @@ -9,15 +9,19 @@ private: bool hasPassword; unsigned char playerCount; unsigned char maxPlayers; + bool spectatorsAllowed; + unsigned int spectatorsCount; public: - ServerGame(int _gameId, const QString &_creator, const QString &_description, bool _hasPassword, unsigned char _playerCount, unsigned char _maxPlayers) - : gameId(_gameId), creator(_creator), description(_description), hasPassword(_hasPassword), playerCount(_playerCount), maxPlayers(_maxPlayers) { } + ServerGame(int _gameId, const QString &_creator, const QString &_description, bool _hasPassword, unsigned char _playerCount, unsigned char _maxPlayers, bool _spectatorsAllowed, unsigned int _spectatorsCount) + : gameId(_gameId), creator(_creator), description(_description), hasPassword(_hasPassword), playerCount(_playerCount), maxPlayers(_maxPlayers), spectatorsAllowed(_spectatorsAllowed), spectatorsCount(_spectatorsCount) { } int getGameId() const { return gameId; } QString getCreator() const { return creator; } QString getDescription() const { return description; } bool getHasPassword() const { return hasPassword; } unsigned char getPlayerCount() const { return playerCount; } unsigned char getMaxPlayers() const { return maxPlayers; } + bool getSpectatorsAllowed() const { return spectatorsAllowed; } + unsigned int getSpectatorsCount() const { return spectatorsCount; } }; #endif diff --git a/cockatrice/src/window_main.cpp b/cockatrice/src/window_main.cpp index b240be70..b1ce55f4 100644 --- a/cockatrice/src/window_main.cpp +++ b/cockatrice/src/window_main.cpp @@ -326,10 +326,11 @@ MainWindow::MainWindow(QTranslator *_translator, QWidget *parent) connect(client, SIGNAL(playerIdReceived(int, QString)), this, SLOT(playerIdReceived(int, QString))); connect(this, SIGNAL(logConnecting(QString)), messageLog, SLOT(logConnecting(QString))); - connect(client, SIGNAL(welcomeMsgReceived(const QStringList)), messageLog, SLOT(logConnected(const QStringList))); + connect(client, SIGNAL(welcomeMsgReceived(QString)), messageLog, SLOT(logConnected(QString))); connect(this, SIGNAL(logDisconnected()), messageLog, SLOT(logDisconnected())); connect(client, SIGNAL(logSocketError(const QString &)), messageLog, SLOT(logSocketError(const QString &))); connect(client, SIGNAL(serverError(ServerResponse)), messageLog, SLOT(logServerError(ServerResponse))); + connect(client, SIGNAL(protocolVersionMismatch()), messageLog, SLOT(logProtocolVersionMismatch())); connect(phasesToolbar, SIGNAL(signalSetPhase(int)), client, SLOT(setActivePhase(int))); connect(phasesToolbar, SIGNAL(signalNextTurn()), client, SLOT(nextTurn())); connect(phasesToolbar, SIGNAL(signalDrawCard()), client, SLOT(drawCard())); diff --git a/servatrice/src/server.cpp b/servatrice/src/server.cpp index 3459848d..35624915 100644 --- a/servatrice/src/server.cpp +++ b/servatrice/src/server.cpp @@ -100,7 +100,6 @@ void Server::incomingConnection(int socketId) ServerSocket *socket = new ServerSocket(this); socket->setSocketDescriptor(socketId); connect(socket, SIGNAL(createGame(const QString, const QString, int, bool, ServerSocket *)), this, SLOT(addGame(const QString, const QString, int, bool, ServerSocket *))); - connect(socket, SIGNAL(joinGame(int, bool, ServerSocket *)), this, SLOT(addClientToGame(int, bool, ServerSocket *))); socket->initConnection(); players << socket; } diff --git a/servatrice/src/serversocket.cpp b/servatrice/src/serversocket.cpp index ae7d1b0d..99ef1bc8 100644 --- a/servatrice/src/serversocket.cpp +++ b/servatrice/src/serversocket.cpp @@ -822,8 +822,7 @@ void ServerSocket::msg(const QString &s) void ServerSocket::initConnection() { - msg(QString("welcome||%1").arg(VERSION_STRING)); - msg("welcome||."); + msg(QString("welcome|%1|%2").arg(PROTOCOL_VERSION).arg(VERSION_STRING)); } void ServerSocket::catchSocketError(QAbstractSocket::SocketError socketError) diff --git a/servatrice/src/version.h b/servatrice/src/version.h index 41d02f0f..21185dbe 100644 --- a/servatrice/src/version.h +++ b/servatrice/src/version.h @@ -18,4 +18,5 @@ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ -const char *VERSION_STRING = "Servatrice 0.20090828"; +int PROTOCOL_VERSION = 1; +const char *VERSION_STRING = "Servatrice 0.20090915";