diff --git a/cockatrice/src/abstractclient.h b/cockatrice/src/abstractclient.h index dae91752..94388d6e 100644 --- a/cockatrice/src/abstractclient.h +++ b/cockatrice/src/abstractclient.h @@ -47,6 +47,8 @@ signals: void gameJoinedEventReceived(Event_GameJoined *event); void messageEventReceived(Event_Message *event); void userInfoChanged(ServerInfo_User *userInfo); + void buddyListReceived(const QList &buddyList); + void ignoreListReceived(const QList &ignoreList); protected slots: void processProtocolItem(ProtocolItem *item); protected: diff --git a/cockatrice/src/dlg_creategame.cpp b/cockatrice/src/dlg_creategame.cpp index 20775954..d0ed38e8 100644 --- a/cockatrice/src/dlg_creategame.cpp +++ b/cockatrice/src/dlg_creategame.cpp @@ -18,10 +18,6 @@ DlgCreateGame::DlgCreateGame(AbstractClient *_client, int _roomId, const QMapsetBuddy(descriptionEdit); - passwordLabel = new QLabel(tr("&Password:")); - passwordEdit = new QLineEdit; - passwordLabel->setBuddy(passwordEdit); - maxPlayersLabel = new QLabel(tr("P&layers:")); maxPlayersEdit = new QSpinBox(); maxPlayersEdit->setMinimum(1); @@ -40,6 +36,22 @@ DlgCreateGame::DlgCreateGame(AbstractClient *_client, int _roomId, const QMapsetLayout(gameTypeLayout); + passwordLabel = new QLabel(tr("&Password:")); + passwordEdit = new QLineEdit; + passwordLabel->setBuddy(passwordEdit); + + onlyBuddiesCheckBox = new QCheckBox(tr("Only &buddies can join")); + onlyRegisteredCheckBox = new QCheckBox(tr("Only ®istered users can join")); + + QGridLayout *joinRestrictionsLayout = new QGridLayout; + joinRestrictionsLayout->addWidget(passwordLabel, 0, 0); + joinRestrictionsLayout->addWidget(passwordEdit, 0, 1); + joinRestrictionsLayout->addWidget(onlyBuddiesCheckBox, 1, 0, 1, 2); + joinRestrictionsLayout->addWidget(onlyRegisteredCheckBox, 2, 0, 1, 2); + + QGroupBox *joinRestrictionsGroupBox = new QGroupBox(tr("Joining restrictions")); + joinRestrictionsGroupBox->setLayout(joinRestrictionsLayout); + spectatorsAllowedCheckBox = new QCheckBox(tr("&Spectators allowed")); spectatorsAllowedCheckBox->setChecked(true); connect(spectatorsAllowedCheckBox, SIGNAL(stateChanged(int)), this, SLOT(spectatorsAllowedChanged(int))); @@ -57,11 +69,10 @@ DlgCreateGame::DlgCreateGame(AbstractClient *_client, int _roomId, const QMapaddWidget(descriptionLabel, 0, 0); grid->addWidget(descriptionEdit, 0, 1); - grid->addWidget(passwordLabel, 1, 0); - grid->addWidget(passwordEdit, 1, 1); - grid->addWidget(maxPlayersLabel, 2, 0); - grid->addWidget(maxPlayersEdit, 2, 1); - grid->addWidget(gameTypeGroupBox, 3, 0, 1, 2); + grid->addWidget(maxPlayersLabel, 1, 0); + grid->addWidget(maxPlayersEdit, 1, 1); + grid->addWidget(gameTypeGroupBox, 2, 0, 1, 2); + grid->addWidget(joinRestrictionsGroupBox, 3, 0, 1, 2); grid->addWidget(spectatorsGroupBox, 4, 0, 1, 2); okButton = new QPushButton(tr("&OK")); @@ -102,6 +113,8 @@ void DlgCreateGame::actOK() passwordEdit->text(), maxPlayersEdit->value(), gameTypeList, + onlyBuddiesCheckBox->isChecked(), + onlyRegisteredCheckBox->isChecked(), spectatorsAllowedCheckBox->isChecked(), spectatorsNeedPasswordCheckBox->isChecked(), spectatorsCanTalkCheckBox->isChecked(), diff --git a/cockatrice/src/dlg_creategame.h b/cockatrice/src/dlg_creategame.h index dd68e08e..c0ddc63f 100644 --- a/cockatrice/src/dlg_creategame.h +++ b/cockatrice/src/dlg_creategame.h @@ -29,6 +29,7 @@ private: QLabel *descriptionLabel, *passwordLabel, *maxPlayersLabel; QLineEdit *descriptionEdit, *passwordEdit; QSpinBox *maxPlayersEdit; + QCheckBox *onlyBuddiesCheckBox, *onlyRegisteredCheckBox; QCheckBox *spectatorsAllowedCheckBox, *spectatorsNeedPasswordCheckBox, *spectatorsCanTalkCheckBox, *spectatorsSeeEverythingCheckBox; QPushButton *okButton, *cancelButton; }; diff --git a/cockatrice/src/gamesmodel.cpp b/cockatrice/src/gamesmodel.cpp index 38adbd16..700877f2 100644 --- a/cockatrice/src/gamesmodel.cpp +++ b/cockatrice/src/gamesmodel.cpp @@ -40,8 +40,16 @@ QVariant GamesModel::data(const QModelIndex &index, int role) const return result.join(", "); } case 3: return g->getHasPassword() ? (g->getSpectatorsNeedPassword() ? tr("yes") : tr("yes, free for spectators")) : tr("no"); - case 4: return QString("%1/%2").arg(g->getPlayerCount()).arg(g->getMaxPlayers()); - case 5: return g->getSpectatorsAllowed() ? QVariant(g->getSpectatorCount()) : QVariant(tr("not allowed")); + case 4: { + QStringList result; + if (g->getOnlyBuddies()) + result.append(tr("buddies only")); + if (g->getOnlyRegistered()) + result.append(tr("reg. users only")); + return result.join(", "); + } + case 5: return QString("%1/%2").arg(g->getPlayerCount()).arg(g->getMaxPlayers()); + case 6: return g->getSpectatorsAllowed() ? QVariant(g->getSpectatorCount()) : QVariant(tr("not allowed")); default: return QVariant(); } } @@ -55,8 +63,9 @@ QVariant GamesModel::headerData(int section, Qt::Orientation orientation, int ro case 1: return tr("Creator"); case 2: return tr("Game type"); case 3: return tr("Password"); - case 4: return tr("Players"); - case 5: return tr("Spectators"); + case 4: return tr("Restrictions"); + case 5: return tr("Players"); + case 6: return tr("Spectators"); default: return QVariant(); } } @@ -73,7 +82,7 @@ void GamesModel::updateGameList(ServerInfo_Game *_game) for (int i = 0; i < oldGameTypeList.size(); ++i) gameTypeList.append(new GameTypeId(oldGameTypeList[i]->getData())); - ServerInfo_Game *game = new ServerInfo_Game(_game->getGameId(), _game->getDescription(), _game->getHasPassword(), _game->getPlayerCount(), _game->getMaxPlayers(), gameTypeList, new ServerInfo_User(_game->getCreatorInfo()), _game->getSpectatorsAllowed(), _game->getSpectatorsNeedPassword(), _game->getSpectatorCount()); + ServerInfo_Game *game = new ServerInfo_Game(_game->getGameId(), _game->getDescription(), _game->getHasPassword(), _game->getPlayerCount(), _game->getMaxPlayers(), gameTypeList, new ServerInfo_User(_game->getCreatorInfo()), _game->getOnlyBuddies(), _game->getOnlyRegistered(), _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/gamesmodel.h b/cockatrice/src/gamesmodel.h index 525d75e6..a7f4fe68 100644 --- a/cockatrice/src/gamesmodel.h +++ b/cockatrice/src/gamesmodel.h @@ -16,7 +16,7 @@ public: GamesModel(const QMap &_gameTypes, QObject *parent = 0); ~GamesModel(); int rowCount(const QModelIndex &parent = QModelIndex()) const { return parent.isValid() ? 0 : gameList.size(); } - int columnCount(const QModelIndex &/*parent*/ = QModelIndex()) const { return 5; } + int columnCount(const QModelIndex &/*parent*/ = QModelIndex()) const { return 7; } QVariant data(const QModelIndex &index, int role) const; QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; diff --git a/cockatrice/src/localserver.h b/cockatrice/src/localserver.h index ebdb32e2..db28b639 100644 --- a/cockatrice/src/localserver.h +++ b/cockatrice/src/localserver.h @@ -20,6 +20,8 @@ public: LocalServerInterface *newConnection(); protected: ServerInfo_User *getUserData(const QString &name); + QList getBuddyList(const QString & /*name*/) { return QList(); } + QList getIgnoreList(const QString & /*name*/) { return QList(); } }; #endif \ No newline at end of file diff --git a/cockatrice/src/remoteclient.cpp b/cockatrice/src/remoteclient.cpp index e378fb8b..6baa7f30 100644 --- a/cockatrice/src/remoteclient.cpp +++ b/cockatrice/src/remoteclient.cpp @@ -51,6 +51,8 @@ void RemoteClient::loginResponse(ProtocolResponse *response) } setStatus(StatusLoggedIn); emit userInfoChanged(resp->getUserInfo()); + emit buddyListReceived(resp->getBuddyList()); + emit ignoreListReceived(resp->getIgnoreList()); } else { emit serverError(response->getResponseCode()); setStatus(StatusDisconnecting); diff --git a/cockatrice/src/tab_room.cpp b/cockatrice/src/tab_room.cpp index d8f15168..8892479e 100644 --- a/cockatrice/src/tab_room.cpp +++ b/cockatrice/src/tab_room.cpp @@ -46,7 +46,7 @@ GameSelector::GameSelector(AbstractClient *_client, TabRoom *_room, QWidget *par retranslateUi(); setLayout(mainLayout); - setMinimumWidth(gameListView->columnWidth(0) * gameListModel->columnCount()); + setMinimumWidth((qreal) (gameListView->columnWidth(0) * gameListModel->columnCount()) / 1.5); setMinimumHeight(400); connect(showFullGamesCheckBox, SIGNAL(stateChanged(int)), this, SLOT(showFullGamesChanged(int))); @@ -77,6 +77,8 @@ void GameSelector::checkResponse(ResponseCode response) case RespSpectatorsNotAllowed: QMessageBox::critical(this, tr("Error"), tr("Spectators are not allowed in this game.")); break; case RespGameFull: QMessageBox::critical(this, tr("Error"), tr("The game is already full.")); break; case RespNameNotFound: QMessageBox::critical(this, tr("Error"), tr("The game does not exist any more.")); break; + case RespUserLevelTooLow: QMessageBox::critical(this, tr("Error"), tr("This game is only open to registered users.")); break; + case RespOnlyBuddies: QMessageBox::critical(this, tr("Error"), tr("This game is only open to its creator's buddies.")); break; default: ; } } diff --git a/cockatrice/src/tab_server.cpp b/cockatrice/src/tab_server.cpp index f92bf581..47c49af8 100644 --- a/cockatrice/src/tab_server.cpp +++ b/cockatrice/src/tab_server.cpp @@ -15,7 +15,6 @@ #include "protocol_items.h" #include "userlist.h" #include "userinfobox.h" -//#include "pixmapgenerator.h" #include RoomSelector::RoomSelector(AbstractClient *_client, QWidget *parent) diff --git a/common/protocol.cpp b/common/protocol.cpp index 8607f460..a883dc99 100644 --- a/common/protocol.cpp +++ b/common/protocol.cpp @@ -169,12 +169,14 @@ void CommandContainer::enqueueGameEventPrivate(GameEvent *event, int gameId, int gameEventQueuePrivate->setContext(context); } -Command_CreateGame::Command_CreateGame(int _roomId, const QString &_description, const QString &_password, int _maxPlayers, const QList &_gameTypes, bool _spectatorsAllowed, bool _spectatorsNeedPassword, bool _spectatorsCanTalk, bool _spectatorsSeeEverything) +Command_CreateGame::Command_CreateGame(int _roomId, const QString &_description, const QString &_password, int _maxPlayers, const QList &_gameTypes, bool _onlyBuddies, bool _onlyRegistered, bool _spectatorsAllowed, bool _spectatorsNeedPassword, bool _spectatorsCanTalk, bool _spectatorsSeeEverything) : RoomCommand("create_game", _roomId) { insertItem(new SerializableItem_String("description", _description)); insertItem(new SerializableItem_String("password", _password)); insertItem(new SerializableItem_Int("max_players", _maxPlayers)); + insertItem(new SerializableItem_Bool("only_buddies", _onlyBuddies)); + insertItem(new SerializableItem_Bool("only_registered", _onlyRegistered)); insertItem(new SerializableItem_Bool("spectators_allowed", _spectatorsAllowed)); insertItem(new SerializableItem_Bool("spectators_need_password", _spectatorsNeedPassword)); insertItem(new SerializableItem_Bool("spectators_can_talk", _spectatorsCanTalk)); @@ -260,6 +262,8 @@ void ProtocolResponse::initializeHash() responseHash.insert("context_error", RespContextError); responseHash.insert("wrong_password", RespWrongPassword); responseHash.insert("spectators_not_allowed", RespSpectatorsNotAllowed); + responseHash.insert("only_buddies", RespOnlyBuddies); + responseHash.insert("user_level_too_low", RespUserLevelTooLow); } Response_JoinRoom::Response_JoinRoom(int _cmdId, ResponseCode _responseCode, ServerInfo_Room *_roomInfo) @@ -322,12 +326,15 @@ Response_DumpZone::Response_DumpZone(int _cmdId, ResponseCode _responseCode, Ser insertItem(_zone); } -Response_Login::Response_Login(int _cmdId, ResponseCode _responseCode, ServerInfo_User *_userInfo) +Response_Login::Response_Login(int _cmdId, ResponseCode _responseCode, ServerInfo_User *_userInfo, const QList &_buddyList, const QList &_ignoreList) : ProtocolResponse(_cmdId, _responseCode, "login") { if (!_userInfo) _userInfo = new ServerInfo_User; insertItem(_userInfo); + + insertItem(new ServerInfo_UserList("buddy_list", _buddyList)); + insertItem(new ServerInfo_UserList("ignore_list", _ignoreList)); } GameEvent::GameEvent(const QString &_eventName, int _playerId) diff --git a/common/protocol.h b/common/protocol.h index b4a7fb95..fda322ac 100644 --- a/common/protocol.h +++ b/common/protocol.h @@ -178,10 +178,12 @@ public: class Command_CreateGame : public RoomCommand { Q_OBJECT public: - Command_CreateGame(int _roomId = -1, const QString &_description = QString(), const QString &_password = QString(), int _maxPlayers = -1, const QList &_gameTypes = QList(), bool _spectatorsAllowed = false, bool _spectatorsNeedPassword = false, bool _spectatorsCanTalk = false, bool _spectatorsSeeEverything = false); + Command_CreateGame(int _roomId = -1, const QString &_description = QString(), const QString &_password = QString(), int _maxPlayers = -1, const QList &_gameTypes = QList(), bool _onlyBuddies = false, bool _onlyRegistered = false, 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 getOnlyBuddies() const { return static_cast(itemMap.value("only_buddies"))->getData(); }; + bool getOnlyRegistered() const { return static_cast(itemMap.value("only_registered"))->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(); }; @@ -318,10 +320,12 @@ public: class Response_Login : public ProtocolResponse { Q_OBJECT public: - Response_Login(int _cmdId = -1, ResponseCode _responseCode = RespOk, ServerInfo_User *_userInfo = 0); + Response_Login(int _cmdId = -1, ResponseCode _responseCode = RespOk, ServerInfo_User *_userInfo = 0, const QList &_buddyList = QList(), const QList &_ignoreList = QList()); int getItemId() const { return ItemId_Response_Login; } static SerializableItem *newItem() { return new Response_Login; } ServerInfo_User *getUserInfo() const { return static_cast(itemMap.value("user")); } + QList getBuddyList() const { return static_cast(itemMap.value("buddy_list"))->getUserList(); } + QList getIgnoreList() const { return static_cast(itemMap.value("ignore_list"))->getUserList(); } }; // -------------- diff --git a/common/protocol_datastructures.cpp b/common/protocol_datastructures.cpp index b340bab4..687bf8df 100644 --- a/common/protocol_datastructures.cpp +++ b/common/protocol_datastructures.cpp @@ -31,7 +31,14 @@ ServerInfo_User::ServerInfo_User(const ServerInfo_User *other, bool complete) insertItem(new SerializableItem_ByteArray("avatar_bmp", complete ? other->getAvatarBmp() : QByteArray())); } -ServerInfo_Game::ServerInfo_Game(int _gameId, const QString &_description, bool _hasPassword, int _playerCount, int _maxPlayers, const QList &_gameTypes, ServerInfo_User *_creatorInfo, bool _spectatorsAllowed, bool _spectatorsNeedPassword, int _spectatorCount) +ServerInfo_UserList::ServerInfo_UserList(const QString &_itemType, const QList &_userList) + : SerializableItem_Map(_itemType) +{ + for (int i = 0; i < _userList.size(); ++i) + itemList.append(_userList[i]); +} + +ServerInfo_Game::ServerInfo_Game(int _gameId, const QString &_description, bool _hasPassword, int _playerCount, int _maxPlayers, const QList &_gameTypes, ServerInfo_User *_creatorInfo, bool _onlyBuddies, bool _onlyRegistered, bool _spectatorsAllowed, bool _spectatorsNeedPassword, int _spectatorCount) : SerializableItem_Map("game") { insertItem(new SerializableItem_Int("game_id", _gameId)); @@ -42,6 +49,8 @@ ServerInfo_Game::ServerInfo_Game(int _gameId, const QString &_description, bool if (!_creatorInfo) _creatorInfo = new ServerInfo_User; insertItem(_creatorInfo); + insertItem(new SerializableItem_Bool("only_buddies", _onlyBuddies)); + insertItem(new SerializableItem_Bool("only_registered", _onlyRegistered)); 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 b2c9050f..045a4003 100644 --- a/common/protocol_datastructures.h +++ b/common/protocol_datastructures.h @@ -8,7 +8,7 @@ class DeckList; -enum ResponseCode { RespNothing, RespOk, RespInvalidCommand, RespInvalidData, RespNameNotFound, RespLoginNeeded, RespFunctionNotAllowed, RespGameNotStarted, RespGameFull, RespContextError, RespWrongPassword, RespSpectatorsNotAllowed }; +enum ResponseCode { RespNothing, RespOk, RespInvalidCommand, RespInvalidData, RespNameNotFound, RespLoginNeeded, RespFunctionNotAllowed, RespGameNotStarted, RespGameFull, RespContextError, RespWrongPassword, RespSpectatorsNotAllowed, RespOnlyBuddies, RespUserLevelTooLow }; // PrivateZone: Contents of the zone are always visible to the owner, // but not to anyone else. @@ -55,9 +55,15 @@ public: QByteArray getAvatarBmp() const { return static_cast(itemMap.value("avatar_bmp"))->getData(); } }; +class ServerInfo_UserList : public SerializableItem_Map { +public: + ServerInfo_UserList(const QString &_itemType, const QList &_userList = QList()); + QList getUserList() const { return typecastItemList(); } +}; + 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 QList &_gameTypes = QList(), ServerInfo_User *creatorInfo = 0, bool _spectatorsAllowed = false, bool _spectatorsNeedPassword = false, int _spectatorCount = -1); + ServerInfo_Game(int _gameId = -1, const QString &_description = QString(), bool _hasPassword = false, int _playerCount = -1, int _maxPlayers = -1, const QList &_gameTypes = QList(), ServerInfo_User *creatorInfo = 0, bool _onlyBuddies = false, bool _onlyRegistered = false, 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(); } @@ -66,6 +72,8 @@ public: int getMaxPlayers() const { return static_cast(itemMap.value("max_players"))->getData(); } QList getGameTypes() const { return typecastItemList(); } ServerInfo_User *getCreatorInfo() const { return static_cast(itemMap.value("user")); } + bool getOnlyBuddies() const { return static_cast(itemMap.value("only_buddies"))->getData(); } + bool getOnlyRegistered() const { return static_cast(itemMap.value("only_registered"))->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/serializable_item.h b/common/serializable_item.h index 14e383e9..979ebb98 100644 --- a/common/serializable_item.h +++ b/common/serializable_item.h @@ -7,6 +7,7 @@ #include #include #include +#include #include "color.h" class QXmlStreamReader; @@ -80,7 +81,7 @@ protected: bool readElement(QXmlStreamReader *xml); void writeElement(QXmlStreamWriter *xml); public: - SerializableItem_String(const QString &_itemType, const QString &_data) + SerializableItem_String(const QString &_itemType, const QString &_data = QString()) : SerializableItem(_itemType), data(_data) { } const QString &getData() { return data; } void setData(const QString &_data) { data = _data; } @@ -94,7 +95,7 @@ protected: bool readElement(QXmlStreamReader *xml); void writeElement(QXmlStreamWriter *xml); public: - SerializableItem_Int(const QString &_itemType, int _data) + SerializableItem_Int(const QString &_itemType, int _data = -1) : SerializableItem(_itemType), data(_data) { } int getData() { return data; } void setData(int _data) { data = _data; } @@ -108,7 +109,7 @@ protected: bool readElement(QXmlStreamReader *xml); void writeElement(QXmlStreamWriter *xml); public: - SerializableItem_Bool(const QString &_itemType, bool _data) + SerializableItem_Bool(const QString &_itemType, bool _data = false) : SerializableItem(_itemType), data(_data) { } bool getData() { return data; } void setData(bool _data) { data = _data; } @@ -122,7 +123,7 @@ protected: bool readElement(QXmlStreamReader *xml); void writeElement(QXmlStreamWriter *xml); public: - SerializableItem_Color(const QString &_itemType, const Color &_data) + SerializableItem_Color(const QString &_itemType, const Color &_data = Color()) : SerializableItem(_itemType), data(_data) { } const Color &getData() { return data; } void setData(const Color &_data) { data = _data; } @@ -136,7 +137,7 @@ protected: bool readElement(QXmlStreamReader *xml); void writeElement(QXmlStreamWriter *xml); public: - SerializableItem_DateTime(const QString &_itemType, const QDateTime &_data) + SerializableItem_DateTime(const QString &_itemType, const QDateTime &_data = QDateTime()) : SerializableItem(_itemType), data(_data) { } const QDateTime &getData() { return data; } void setData(const QDateTime &_data) { data = _data; } @@ -150,7 +151,7 @@ protected: bool readElement(QXmlStreamReader *xml); void writeElement(QXmlStreamWriter *xml); public: - SerializableItem_ByteArray(const QString &_itemType, const QByteArray &_data) + SerializableItem_ByteArray(const QString &_itemType, const QByteArray &_data = QByteArray()) : SerializableItem(_itemType), data(_data) { } const QByteArray &getData() { return data; } void setData(const QByteArray &_data) { data = _data; } diff --git a/common/server.h b/common/server.h index d382626a..aa0e5dbc 100644 --- a/common/server.h +++ b/common/server.h @@ -38,6 +38,9 @@ public: virtual bool getGameShouldPing() const = 0; virtual int getMaxGameInactivityTime() const = 0; virtual int getMaxPlayerInactivityTime() const = 0; + + virtual QList getBuddyList(const QString &name) = 0; + virtual QList getIgnoreList(const QString &name) = 0; protected: QMap games; QList clients; diff --git a/common/server_game.cpp b/common/server_game.cpp index e85ddc7f..72c2016a 100644 --- a/common/server_game.cpp +++ b/common/server_game.cpp @@ -28,8 +28,8 @@ #include #include -Server_Game::Server_Game(Server_ProtocolHandler *_creator, int _gameId, const QString &_description, const QString &_password, int _maxPlayers, const QList &_gameTypes, bool _spectatorsAllowed, bool _spectatorsNeedPassword, bool _spectatorsCanTalk, bool _spectatorsSeeEverything, Server_Room *parent) - : QObject(parent), creatorInfo(new ServerInfo_User(_creator->getUserInfo())), gameStarted(false), gameId(_gameId), description(_description), password(_password), maxPlayers(_maxPlayers), gameTypes(_gameTypes), activePlayer(-1), activePhase(-1), spectatorsAllowed(_spectatorsAllowed), spectatorsNeedPassword(_spectatorsNeedPassword), spectatorsCanTalk(_spectatorsCanTalk), spectatorsSeeEverything(_spectatorsSeeEverything), inactivityCounter(0), secondsElapsed(0) +Server_Game::Server_Game(Server_ProtocolHandler *_creator, int _gameId, const QString &_description, const QString &_password, int _maxPlayers, const QList &_gameTypes, bool _onlyBuddies, bool _onlyRegistered, bool _spectatorsAllowed, bool _spectatorsNeedPassword, bool _spectatorsCanTalk, bool _spectatorsSeeEverything, Server_Room *parent) + : QObject(parent), creatorInfo(new ServerInfo_User(_creator->getUserInfo())), gameStarted(false), gameId(_gameId), description(_description), password(_password), maxPlayers(_maxPlayers), gameTypes(_gameTypes), activePlayer(-1), activePhase(-1), onlyBuddies(_onlyBuddies), onlyRegistered(_onlyRegistered), spectatorsAllowed(_spectatorsAllowed), spectatorsNeedPassword(_spectatorsNeedPassword), spectatorsCanTalk(_spectatorsCanTalk), spectatorsSeeEverything(_spectatorsSeeEverything), inactivityCounter(0), secondsElapsed(0) { addPlayer(_creator, false, false); @@ -173,10 +173,12 @@ void Server_Game::stopGameIfFinished() } } -ResponseCode Server_Game::checkJoin(const QString &_password, bool spectator) +ResponseCode Server_Game::checkJoin(ServerInfo_User *user, const QString &_password, bool spectator) { if ((_password != password) && !(spectator && !spectatorsNeedPassword)) return RespWrongPassword; + if (!(user->getUserLevel() & ServerInfo_User::IsRegistered) && onlyRegistered) + return RespUserLevelTooLow; if (spectator) { if (!spectatorsAllowed) return RespSpectatorsNotAllowed; @@ -419,6 +421,8 @@ ServerInfo_Game *Server_Game::getInfo() const getMaxPlayers(), gameTypeList, new ServerInfo_User(getCreatorInfo(), false), + onlyBuddies, + onlyRegistered, getSpectatorsAllowed(), getSpectatorsNeedPassword(), getSpectatorCount() diff --git a/common/server_game.h b/common/server_game.h index e5fbc5a2..a58a213d 100644 --- a/common/server_game.h +++ b/common/server_game.h @@ -42,6 +42,7 @@ private: int maxPlayers; QList gameTypes; int activePlayer, activePhase; + bool onlyBuddies, onlyRegistered; bool spectatorsAllowed; bool spectatorsNeedPassword; bool spectatorsCanTalk; @@ -54,7 +55,7 @@ signals: private slots: void pingClockTimeout(); public: - Server_Game(Server_ProtocolHandler *_creator, int _gameId, const QString &_description, const QString &_password, int _maxPlayers, const QList &_gameTypes, bool _spectatorsAllowed, bool _spectatorsNeedPassword, bool _spectatorsCanTalk, bool _spectatorsSeeEverything, Server_Room *parent); + Server_Game(Server_ProtocolHandler *_creator, int _gameId, const QString &_description, const QString &_password, int _maxPlayers, const QList &_gameTypes, bool _onlyBuddies, bool _onlyRegistered, bool _spectatorsAllowed, bool _spectatorsNeedPassword, bool _spectatorsCanTalk, bool _spectatorsSeeEverything, Server_Room *parent); ~Server_Game(); ServerInfo_Game *getInfo() const; ServerInfo_User *getCreatorInfo() const { return creatorInfo; } @@ -71,7 +72,7 @@ public: bool getSpectatorsNeedPassword() const { return spectatorsNeedPassword; } bool getSpectatorsCanTalk() const { return spectatorsCanTalk; } bool getSpectatorsSeeEverything() const { return spectatorsSeeEverything; } - ResponseCode checkJoin(const QString &_password, bool spectator); + ResponseCode checkJoin(ServerInfo_User *user, const QString &_password, bool spectator); Server_Player *addPlayer(Server_ProtocolHandler *handler, bool spectator, bool broadcastUpdate = true); void removePlayer(Server_Player *player); void startGameIfReady(); diff --git a/common/server_protocolhandler.cpp b/common/server_protocolhandler.cpp index 2b97d9a2..8fb191b8 100644 --- a/common/server_protocolhandler.cpp +++ b/common/server_protocolhandler.cpp @@ -42,6 +42,10 @@ Server_ProtocolHandler::~Server_ProtocolHandler() } delete userInfo; + for (int i = 0; i < buddyList.size(); ++i) + delete buddyList[i]; + for (int i = 0; i < ignoreList.size(); ++i) + delete ignoreList[i]; } void Server_ProtocolHandler::playerRemovedFromGame(Server_Game *game) @@ -233,6 +237,9 @@ ResponseCode Server_ProtocolHandler::cmdLogin(Command_Login *cmd, CommandContain enqueueProtocolItem(new Event_ServerMessage(server->getLoginMessage())); if (authState == PasswordRight) { + buddyList = server->getBuddyList(userInfo->getName()); + ignoreList = server->getIgnoreList(userInfo->getName()); + // 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) { @@ -248,7 +255,14 @@ ResponseCode Server_ProtocolHandler::cmdLogin(Command_Login *cmd, CommandContain } } - cont->setResponse(new Response_Login(cont->getCmdId(), RespOk, new ServerInfo_User(userInfo, true))); + QList _buddyList; + for (int i = 0; i < buddyList.size(); ++i) + _buddyList.append(new ServerInfo_User(buddyList[i])); + QList _ignoreList; + for (int i = 0; i < ignoreList.size(); ++i) + _ignoreList.append(new ServerInfo_User(ignoreList[i])); + + cont->setResponse(new Response_Login(cont->getCmdId(), RespOk, new ServerInfo_User(userInfo, true), _buddyList, _ignoreList)); return RespNothing; } @@ -361,7 +375,7 @@ ResponseCode Server_ProtocolHandler::cmdCreateGame(Command_CreateGame *cmd, Comm for (int i = 0; i < gameTypeList.size(); ++i) gameTypes.append(gameTypeList[i]->getData()); - Server_Game *game = room->createGame(cmd->getDescription(), cmd->getPassword(), cmd->getMaxPlayers(), gameTypes, cmd->getSpectatorsAllowed(), cmd->getSpectatorsNeedPassword(), cmd->getSpectatorsCanTalk(), cmd->getSpectatorsSeeEverything(), this); + Server_Game *game = room->createGame(cmd->getDescription(), cmd->getPassword(), cmd->getMaxPlayers(), gameTypes, cmd->getOnlyBuddies(), cmd->getOnlyRegistered(), cmd->getSpectatorsAllowed(), cmd->getSpectatorsNeedPassword(), cmd->getSpectatorsCanTalk(), cmd->getSpectatorsSeeEverything(), this); Server_Player *creator = game->getPlayers().values().first(); games.insert(game->getGameId(), QPair(game, creator)); @@ -382,7 +396,7 @@ ResponseCode Server_ProtocolHandler::cmdJoinGame(Command_JoinGame *cmd, CommandC if (!g) return RespNameNotFound; - ResponseCode result = g->checkJoin(cmd->getPassword(), cmd->getSpectator()); + ResponseCode result = g->checkJoin(userInfo, cmd->getPassword(), cmd->getSpectator()); if (result == RespOk) { Server_Player *player = g->addPlayer(this, cmd->getSpectator()); games.insert(cmd->getGameId(), QPair(g, player)); diff --git a/common/server_protocolhandler.h b/common/server_protocolhandler.h index 10d8516d..8f9caaf6 100644 --- a/common/server_protocolhandler.h +++ b/common/server_protocolhandler.h @@ -27,7 +27,7 @@ protected: bool acceptsUserListChanges; bool acceptsRoomListChanges; ServerInfo_User *userInfo; - + QList buddyList, ignoreList; private: QList itemQueue; QDateTime lastCommandTime; @@ -95,6 +95,8 @@ public: bool getAcceptsRoomListChanges() const { return acceptsRoomListChanges; } ServerInfo_User *getUserInfo() const { return userInfo; } void setUserInfo(ServerInfo_User *_userInfo) { userInfo = _userInfo; } + const QList &getBuddyList() const { return buddyList; } + const QList &getIgnoreList() const { return ignoreList; } const QDateTime &getLastCommandTime() const { return lastCommandTime; } void processCommandContainer(CommandContainer *cont); diff --git a/common/server_room.cpp b/common/server_room.cpp index 4b51bff9..fe7b83ee 100644 --- a/common/server_room.cpp +++ b/common/server_room.cpp @@ -68,9 +68,9 @@ void Server_Room::broadcastGameListUpdate(Server_Game *game) delete event; } -Server_Game *Server_Room::createGame(const QString &description, const QString &password, int maxPlayers, const QList &gameTypes, bool spectatorsAllowed, bool spectatorsNeedPassword, bool spectatorsCanTalk, bool spectatorsSeeEverything, Server_ProtocolHandler *creator) +Server_Game *Server_Room::createGame(const QString &description, const QString &password, int maxPlayers, const QList &gameTypes, bool onlyBuddies, bool onlyRegistered, bool spectatorsAllowed, bool spectatorsNeedPassword, bool spectatorsCanTalk, bool spectatorsSeeEverything, Server_ProtocolHandler *creator) { - Server_Game *newGame = new Server_Game(creator, static_cast(parent())->getNextGameId(), description, password, maxPlayers, gameTypes, spectatorsAllowed, spectatorsNeedPassword, spectatorsCanTalk, spectatorsSeeEverything, this); + Server_Game *newGame = new Server_Game(creator, static_cast(parent())->getNextGameId(), description, password, maxPlayers, gameTypes, onlyBuddies, onlyRegistered, spectatorsAllowed, spectatorsNeedPassword, spectatorsCanTalk, spectatorsSeeEverything, this); games.insert(newGame->getGameId(), newGame); connect(newGame, SIGNAL(gameClosing()), this, SLOT(removeGame())); diff --git a/common/server_room.h b/common/server_room.h index cc8c52aa..8571f04e 100644 --- a/common/server_room.h +++ b/common/server_room.h @@ -44,7 +44,7 @@ public: void removeClient(Server_ProtocolHandler *client); void say(Server_ProtocolHandler *client, const QString &s); void broadcastGameListUpdate(Server_Game *game); - Server_Game *createGame(const QString &description, const QString &password, int maxPlayers, const QList &_gameTypes, bool spectatorsAllowed, bool spectatorsNeedPassword, bool spectatorsCanTalk, bool spectatorsSeeEverything, Server_ProtocolHandler *creator); + Server_Game *createGame(const QString &description, const QString &password, int maxPlayers, const QList &_gameTypes, bool onlyBuddies, bool onlyRegistered, bool spectatorsAllowed, bool spectatorsNeedPassword, bool spectatorsCanTalk, bool spectatorsSeeEverything, Server_ProtocolHandler *creator); void sendRoomEvent(RoomEvent *event); }; diff --git a/servatrice/servatrice.sql b/servatrice/servatrice.sql index fd5115fa..0f41a127 100644 --- a/servatrice/servatrice.sql +++ b/servatrice/servatrice.sql @@ -110,7 +110,8 @@ CREATE TABLE IF NOT EXISTS `cockatrice_users` ( `registrationDate` datetime NOT NULL, `active` tinyint(1) NOT NULL, `token` char(32) NOT NULL, - PRIMARY KEY (`id`) + PRIMARY KEY (`id`), + UNIQUE KEY `name` (`name`) ) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=915 ; CREATE TABLE `cockatrice_uptime` ( diff --git a/servatrice/src/servatrice.cpp b/servatrice/src/servatrice.cpp index a9ff3b36..9684c634 100644 --- a/servatrice/src/servatrice.cpp +++ b/servatrice/src/servatrice.cpp @@ -168,6 +168,29 @@ AuthenticationResult Servatrice::checkUserPassword(const QString &user, const QS return UnknownUser; } +ServerInfo_User *Servatrice::evalUserQueryResult(const QSqlQuery &query, bool complete) +{ + QString name = query.value(0).toString(); + bool is_admin = query.value(1).toInt(); + QString realName = query.value(2).toString(); + QString country = query.value(3).toString(); + QByteArray avatarBmp; + if (complete) + avatarBmp = query.value(4).toByteArray(); + + int userLevel = ServerInfo_User::IsUser | ServerInfo_User::IsRegistered; + if (is_admin) + userLevel |= ServerInfo_User::IsAdmin; + + return new ServerInfo_User( + name, + userLevel, + realName, + country, + avatarBmp + ); +} + ServerInfo_User *Servatrice::getUserData(const QString &name) { const QString method = settings->value("authentication/method").toString(); @@ -175,34 +198,59 @@ ServerInfo_User *Servatrice::getUserData(const QString &name) checkSql(); QSqlQuery query; - query.prepare("select admin, realname, country, avatar_bmp from " + dbPrefix + "_users where name = :name and active = 1"); + query.prepare("select name, admin, realname, country, avatar_bmp from " + dbPrefix + "_users where name = :name and active = 1"); query.bindValue(":name", name); if (!execSqlQuery(query)) return new ServerInfo_User(name, ServerInfo_User::IsUser); - if (query.next()) { - bool is_admin = query.value(0).toInt(); - QString realName = query.value(1).toString(); - QString country = query.value(2).toString(); - QByteArray avatarBmp = query.value(3).toByteArray(); - - int userLevel = ServerInfo_User::IsUser | ServerInfo_User::IsRegistered; - if (is_admin) - userLevel |= ServerInfo_User::IsAdmin; - - return new ServerInfo_User( - name, - userLevel, - realName, - country, - avatarBmp - ); - } else + if (query.next()) + return evalUserQueryResult(query, true); + else return new ServerInfo_User(name, ServerInfo_User::IsUser); } else return new ServerInfo_User(name, ServerInfo_User::IsUser); } +QList Servatrice::getBuddyList(const QString &name) +{ + QList result; + + const QString method = settings->value("authentication/method").toString(); + if (method == "sql") { + checkSql(); + + QSqlQuery query; + query.prepare("select a.name, a.admin, a.realname, a.country from " + dbPrefix + "_users a left join " + dbPrefix + "_buddylist b on a.id = b.id_user2 left join " + dbPrefix + "_users c on b.id_user1 = c.id where c.name = :name"); + query.bindValue(":name", name); + if (!execSqlQuery(query)) + return result; + + while (query.next()) + result.append(evalUserQueryResult(query, false)); + } + return result; +} + +QList Servatrice::getIgnoreList(const QString &name) +{ + QList result; + + const QString method = settings->value("authentication/method").toString(); + if (method == "sql") { + checkSql(); + + QSqlQuery query; + query.prepare("select a.name, a.admin, a.realname, a.country from " + dbPrefix + "_users a left join " + dbPrefix + "_ignorelist b on a.id = b.id_user2 left join " + dbPrefix + "_users c on b.id_user1 = c.id where c.name = :name"); + query.bindValue(":name", name); + if (!execSqlQuery(query)) + return result; + + while (query.next()) + result.append(evalUserQueryResult(query, false)); + } + return result; +} + void Servatrice::updateLoginMessage() { checkSql(); diff --git a/servatrice/src/servatrice.h b/servatrice/src/servatrice.h index 479af4fd..9bc9ab00 100644 --- a/servatrice/src/servatrice.h +++ b/servatrice/src/servatrice.h @@ -50,6 +50,8 @@ public: protected: AuthenticationResult checkUserPassword(const QString &user, const QString &password); ServerInfo_User *getUserData(const QString &name); + QList getBuddyList(const QString &name); + QList getIgnoreList(const QString &name); private: QTimer *pingClock, *statusUpdateClock; QTcpServer *tcpServer; @@ -59,6 +61,7 @@ private: int uptime; int maxGameInactivityTime; int maxPlayerInactivityTime; + ServerInfo_User *evalUserQueryResult(const QSqlQuery &query, bool complete); }; #endif