From c7ef61f750294faf73fe1c93c3f4e51a6fba5349 Mon Sep 17 00:00:00 2001 From: Max-Wilhelm Bruker Date: Sun, 13 Nov 2011 13:13:41 +0100 Subject: [PATCH] moderators can override game restrictions and kick players when spectating; game host privileges shift when host leaves --- cockatrice/src/gameselector.cpp | 10 ++-- cockatrice/src/gameselector.h | 4 +- cockatrice/src/main.h | 2 +- cockatrice/src/playerlistwidget.cpp | 15 ++++-- cockatrice/src/playerlistwidget.h | 3 +- cockatrice/src/tab.h | 1 + cockatrice/src/tab_admin.cpp | 4 +- cockatrice/src/tab_admin.h | 2 + cockatrice/src/tab_game.cpp | 26 +++++++--- cockatrice/src/tab_game.h | 7 ++- cockatrice/src/tab_room.cpp | 2 +- cockatrice/src/tab_supervisor.cpp | 5 +- cockatrice/src/tab_supervisor.h | 1 + cockatrice/src/userlist.cpp | 2 +- common/protocol_item_ids.h | 73 +++++++++++++++-------------- common/protocol_items.cpp | 11 ++++- common/protocol_items.dat | 7 +-- common/protocol_items.h | 13 ++++- common/server_game.cpp | 49 +++++++++++++------ common/server_game.h | 4 +- common/server_protocolhandler.cpp | 12 ++--- servatrice/src/servatrice.cpp | 2 +- 22 files changed, 165 insertions(+), 90 deletions(-) diff --git a/cockatrice/src/gameselector.cpp b/cockatrice/src/gameselector.cpp index 6d3ee6a3..63ede6ec 100644 --- a/cockatrice/src/gameselector.cpp +++ b/cockatrice/src/gameselector.cpp @@ -6,14 +6,15 @@ #include #include #include +#include "tab_supervisor.h" #include "dlg_creategame.h" #include "abstractclient.h" #include "protocol_items.h" #include "gameselector.h" #include "gamesmodel.h" -GameSelector::GameSelector(AbstractClient *_client, TabRoom *_room, const QMap &_rooms, const QMap &_gameTypes, QWidget *parent) - : QGroupBox(parent), client(_client), room(_room) +GameSelector::GameSelector(AbstractClient *_client, TabSupervisor *_tabSupervisor, TabRoom *_room, const QMap &_rooms, const QMap &_gameTypes, QWidget *parent) + : QGroupBox(parent), client(_client), tabSupervisor(_tabSupervisor), room(_room) { gameListView = new QTreeView; gameListModel = new GamesModel(_rooms, _gameTypes, this); @@ -115,15 +116,16 @@ void GameSelector::actJoin() if (!ind.isValid()) return; ServerInfo_Game *game = gameListModel->getGame(ind.data(Qt::UserRole).toInt()); + bool overrideRestrictions = !tabSupervisor->getAdminLocked(); QString password; - if (game->getHasPassword() && !(spectator && !game->getSpectatorsNeedPassword())) { + if (game->getHasPassword() && !(spectator && !game->getSpectatorsNeedPassword()) && !overrideRestrictions) { bool ok; password = QInputDialog::getText(this, tr("Join game"), tr("Password:"), QLineEdit::Password, QString(), &ok); if (!ok) return; } - Command_JoinGame *commandJoinGame = new Command_JoinGame(game->getRoomId(), game->getGameId(), password, spectator); + Command_JoinGame *commandJoinGame = new Command_JoinGame(game->getRoomId(), game->getGameId(), password, spectator, overrideRestrictions); connect(commandJoinGame, SIGNAL(finished(ResponseCode)), this, SLOT(checkResponse(ResponseCode))); client->sendCommand(commandJoinGame); diff --git a/cockatrice/src/gameselector.h b/cockatrice/src/gameselector.h index cf603b33..16fc2d7d 100644 --- a/cockatrice/src/gameselector.h +++ b/cockatrice/src/gameselector.h @@ -12,6 +12,7 @@ class GamesProxyModel; class QPushButton; class QCheckBox; class AbstractClient; +class TabSupervisor; class TabRoom; class GameSelector : public QGroupBox { @@ -26,6 +27,7 @@ signals: void gameJoined(int gameId); private: AbstractClient *client; + TabSupervisor *tabSupervisor; TabRoom *room; QTreeView *gameListView; @@ -34,7 +36,7 @@ private: QPushButton *createButton, *joinButton, *spectateButton; QCheckBox *showFullGamesCheckBox, *showRunningGamesCheckBox; public: - GameSelector(AbstractClient *_client, TabRoom *_room, const QMap &_rooms, const QMap &_gameTypes, QWidget *parent = 0); + GameSelector(AbstractClient *_client, TabSupervisor *_tabSupervisor, TabRoom *_room, const QMap &_rooms, const QMap &_gameTypes, QWidget *parent = 0); void retranslateUi(); void processGameInfo(ServerInfo_Game *info); }; diff --git a/cockatrice/src/main.h b/cockatrice/src/main.h index c9d6ad04..34ee91df 100644 --- a/cockatrice/src/main.h +++ b/cockatrice/src/main.h @@ -9,7 +9,7 @@ extern CardDatabase *db; extern QTranslator *translator; const QString translationPrefix = "cockatrice"; -const QString versionString = "0.20111101"; +const QString versionString = "0.20111113"; void installNewTranslator(); diff --git a/cockatrice/src/playerlistwidget.cpp b/cockatrice/src/playerlistwidget.cpp index fee463d0..44f2d8c3 100644 --- a/cockatrice/src/playerlistwidget.cpp +++ b/cockatrice/src/playerlistwidget.cpp @@ -9,7 +9,6 @@ #include "protocol_items.h" #include "userlist.h" #include "userinfobox.h" -#include #include #include #include @@ -46,8 +45,8 @@ bool PlayerListTWI::operator<(const QTreeWidgetItem &other) const return data(4, Qt::UserRole + 1).toInt() < other.data(4, Qt::UserRole + 1).toInt(); } -PlayerListWidget::PlayerListWidget(TabSupervisor *_tabSupervisor, AbstractClient *_client, TabGame *_game, bool _gameCreator, QWidget *parent) - : QTreeWidget(parent), tabSupervisor(_tabSupervisor), client(_client), game(_game), gameCreator(_gameCreator), gameStarted(false) +PlayerListWidget::PlayerListWidget(TabSupervisor *_tabSupervisor, AbstractClient *_client, TabGame *_game, QWidget *parent) + : QTreeWidget(parent), tabSupervisor(_tabSupervisor), client(_client), game(_game), gameStarted(false) { readyIcon = QIcon(":/resources/icon_ready_start.svg"); notReadyIcon = QIcon(":/resources/icon_not_ready_start.svg"); @@ -179,10 +178,18 @@ void PlayerListWidget::showContextMenu(const QPoint &pos, const QModelIndex &ind else menu->addAction(aAddToIgnoreList); } - if (gameCreator) { + if (game->isHost() || !game->getTabSupervisor()->getAdminLocked()) { menu->addSeparator(); menu->addAction(aKick); } + if (userName == game->getTabSupervisor()->getUserInfo()->getName()) { + aChat->setEnabled(false); + aAddToBuddyList->setEnabled(false); + aRemoveFromBuddyList->setEnabled(false); + aAddToIgnoreList->setEnabled(false); + aRemoveFromIgnoreList->setEnabled(false); + aKick->setEnabled(false); + } QAction *actionClicked = menu->exec(pos); if (actionClicked == aDetails) { diff --git a/cockatrice/src/playerlistwidget.h b/cockatrice/src/playerlistwidget.h index dad5f82c..d2d956d8 100644 --- a/cockatrice/src/playerlistwidget.h +++ b/cockatrice/src/playerlistwidget.h @@ -31,13 +31,12 @@ private: TabSupervisor *tabSupervisor; AbstractClient *client; TabGame *game; - bool gameCreator; QIcon readyIcon, notReadyIcon, concededIcon, playerIcon, spectatorIcon; bool gameStarted; signals: void openMessageDialog(const QString &userName, bool focus); public: - PlayerListWidget(TabSupervisor *_tabSupervisor, AbstractClient *_client, TabGame *_game, bool _gameCreator, QWidget *parent = 0); + PlayerListWidget(TabSupervisor *_tabSupervisor, AbstractClient *_client, TabGame *_game, QWidget *parent = 0); void retranslateUi(); void addPlayer(ServerInfo_PlayerProperties *player); void removePlayer(int playerId); diff --git a/cockatrice/src/tab.h b/cockatrice/src/tab.h index 3fefde1a..f7dc472f 100644 --- a/cockatrice/src/tab.h +++ b/cockatrice/src/tab.h @@ -23,6 +23,7 @@ private: public: Tab(TabSupervisor *_tabSupervisor, QWidget *parent = 0); QMenu *getTabMenu() const { return tabMenu; } + TabSupervisor *getTabSupervisor() const { return tabSupervisor; } bool getContentsChanged() const { return contentsChanged; } void setContentsChanged(bool _contentsChanged) { contentsChanged = _contentsChanged; } virtual QString getTabText() const = 0; diff --git a/cockatrice/src/tab_admin.cpp b/cockatrice/src/tab_admin.cpp index 08232138..59614fcf 100644 --- a/cockatrice/src/tab_admin.cpp +++ b/cockatrice/src/tab_admin.cpp @@ -118,6 +118,7 @@ void TabAdmin::actUnlock() lockButton->setEnabled(true); unlockButton->setEnabled(false); locked = false; + emit adminLockChanged(false); } } @@ -128,4 +129,5 @@ void TabAdmin::actLock() lockButton->setEnabled(false); unlockButton->setEnabled(true); locked = true; -} \ No newline at end of file + emit adminLockChanged(true); +} diff --git a/cockatrice/src/tab_admin.h b/cockatrice/src/tab_admin.h index a4982bba..f0cdd126 100644 --- a/cockatrice/src/tab_admin.h +++ b/cockatrice/src/tab_admin.h @@ -31,6 +31,8 @@ private: QPushButton *updateServerMessageButton, *shutdownServerButton; QGroupBox *adminGroupBox; QPushButton *unlockButton, *lockButton; +signals: + void adminLockChanged(bool lock); private slots: void actUpdateServerMessage(); void actShutdownServer(); diff --git a/cockatrice/src/tab_game.cpp b/cockatrice/src/tab_game.cpp index 513bf985..4040e8f3 100644 --- a/cockatrice/src/tab_game.cpp +++ b/cockatrice/src/tab_game.cpp @@ -6,6 +6,7 @@ #include #include #include "tab_game.h" +#include "tab_supervisor.h" #include "cardinfowidget.h" #include "playerlistwidget.h" #include "messagelogwidget.h" @@ -158,8 +159,8 @@ void DeckViewContainer::setDeck(DeckList *deck) readyStartButton->setEnabled(true); } -TabGame::TabGame(TabSupervisor *_tabSupervisor, QList &_clients, int _gameId, const QString &_gameDescription, int _localPlayerId, ServerInfo_User *_userInfo, bool _spectator, bool _spectatorsCanTalk, bool _spectatorsSeeEverything, bool _resuming) - : Tab(_tabSupervisor), clients(_clients), gameId(_gameId), gameDescription(_gameDescription), localPlayerId(_localPlayerId), spectator(_spectator), spectatorsCanTalk(_spectatorsCanTalk), spectatorsSeeEverything(_spectatorsSeeEverything), gameStateKnown(false), started(false), resuming(_resuming), currentPhase(-1) +TabGame::TabGame(TabSupervisor *_tabSupervisor, QList &_clients, int _gameId, const QString &_gameDescription, int _hostId, int _localPlayerId, bool _spectator, bool _spectatorsCanTalk, bool _spectatorsSeeEverything, bool _resuming) + : Tab(_tabSupervisor), clients(_clients), gameId(_gameId), gameDescription(_gameDescription), hostId(_hostId), localPlayerId(_localPlayerId), spectator(_spectator), spectatorsCanTalk(_spectatorsCanTalk), spectatorsSeeEverything(_spectatorsSeeEverything), gameStateKnown(false), started(false), resuming(_resuming), currentPhase(-1) { phasesToolbar = new PhasesToolbar; phasesToolbar->hide(); @@ -170,13 +171,13 @@ TabGame::TabGame(TabSupervisor *_tabSupervisor, QList &_client gameView->hide(); cardInfo = new CardInfoWidget(CardInfoWidget::ModeGameTab); - playerListWidget = new PlayerListWidget(tabSupervisor, clients.first(), this, true); + playerListWidget = new PlayerListWidget(tabSupervisor, clients.first(), this); playerListWidget->setFocusPolicy(Qt::NoFocus); connect(playerListWidget, SIGNAL(openMessageDialog(QString, bool)), this, SIGNAL(openMessageDialog(QString, bool))); timeElapsedLabel = new QLabel; timeElapsedLabel->setAlignment(Qt::AlignCenter); - messageLog = new MessageLogWidget(_userInfo->getName(), _userInfo->getGender() == ServerInfo_User::Female); + messageLog = new MessageLogWidget(tabSupervisor->getUserInfo()->getName(), tabSupervisor->getUserInfo()->getGender() == ServerInfo_User::Female); connect(messageLog, SIGNAL(cardNameHovered(QString)), cardInfo, SLOT(setCard(QString))); connect(messageLog, SIGNAL(showCardInfoPopup(QPoint, QString)), this, SLOT(showCardInfoPopup(QPoint, QString))); connect(messageLog, SIGNAL(deleteCardInfoPopup(QString)), this, SLOT(deleteCardInfoPopup(QString))); @@ -208,11 +209,11 @@ TabGame::TabGame(TabSupervisor *_tabSupervisor, QList &_client mainLayout->addLayout(deckViewContainerLayout, 10); mainLayout->addWidget(splitter); - if (spectator && !spectatorsCanTalk) { + if (spectator && !spectatorsCanTalk && tabSupervisor->getAdminLocked()) { sayLabel->hide(); sayEdit->hide(); } - + connect(tabSupervisor, SIGNAL(adminLockChanged(bool)), this, SLOT(adminLockChanged(bool))); connect(sayEdit, SIGNAL(returnPressed()), this, SLOT(actSay())); // Menu actions @@ -314,6 +315,13 @@ void TabGame::closeRequest() actLeaveGame(); } +void TabGame::adminLockChanged(bool lock) +{ + bool v = !(spectator && !spectatorsCanTalk && lock); + sayLabel->setVisible(v); + sayEdit->setVisible(v); +} + void TabGame::actConcede() { if (QMessageBox::question(this, tr("Concede"), tr("Are you sure you want to concede this game?"), QMessageBox::Yes | QMessageBox::No, QMessageBox::No) != QMessageBox::Yes) @@ -433,6 +441,7 @@ void TabGame::processGameEventContainer(GameEventContainer *cont, AbstractClient case ItemId_Event_Join: eventJoin(static_cast(event), context); break; case ItemId_Event_Leave: eventLeave(static_cast(event), context); break; case ItemId_Event_Kicked: eventKicked(static_cast(event), context); break; + case ItemId_Event_GameHostChanged: eventGameHostChanged(static_cast(event), context); break; case ItemId_Event_GameClosed: eventGameClosed(static_cast(event), context); break; case ItemId_Event_SetActivePlayer: eventSetActivePlayer(static_cast(event), context); break; case ItemId_Event_SetActivePhase: eventSetActivePhase(static_cast(event), context); break; @@ -672,6 +681,11 @@ void TabGame::eventKicked(Event_Kicked * /*event*/, GameEventContext * /*context deleteLater(); } +void TabGame::eventGameHostChanged(Event_GameHostChanged *event, GameEventContext * /*context*/) +{ + hostId = event->getPlayerId(); +} + void TabGame::eventGameClosed(Event_GameClosed * /*event*/, GameEventContext * /*context*/) { started = false; diff --git a/cockatrice/src/tab_game.h b/cockatrice/src/tab_game.h index 7013f70c..220a49d0 100644 --- a/cockatrice/src/tab_game.h +++ b/cockatrice/src/tab_game.h @@ -30,6 +30,7 @@ class Event_GameStateChanged; class Event_PlayerPropertiesChanged; class Event_Join; class Event_Leave; +class Event_GameHostChanged; class Event_GameClosed; class Event_GameStart; class Event_SetActivePlayer; @@ -88,6 +89,7 @@ private: QList clients; int gameId; QString gameDescription; + int hostId; int localPlayerId; bool spectator; bool spectatorsCanTalk, spectatorsSeeEverything; @@ -132,6 +134,7 @@ private: void eventJoin(Event_Join *event, GameEventContext *context); void eventLeave(Event_Leave *event, GameEventContext *context); void eventKicked(Event_Kicked *event, GameEventContext *context); + void eventGameHostChanged(Event_GameHostChanged *event, GameEventContext *context); void eventGameClosed(Event_GameClosed *event, GameEventContext *context); Player *setActivePlayer(int id); void eventSetActivePlayer(Event_SetActivePlayer *event, GameEventContext *context); @@ -146,6 +149,7 @@ signals: void containerProcessingDone(); void openMessageDialog(const QString &userName, bool focus); private slots: + void adminLockChanged(bool lock); void newCardAdded(AbstractCardItem *card); void actConcede(); @@ -156,12 +160,13 @@ private slots: void actNextPhase(); void actNextTurn(); public: - TabGame(TabSupervisor *_tabSupervisor, QList &_clients, int _gameId, const QString &_gameDescription, int _localPlayerId, ServerInfo_User *_userInfo, bool _spectator, bool _spectatorsCanTalk, bool _spectatorsSeeEverything, bool _resuming); + TabGame(TabSupervisor *_tabSupervisor, QList &_clients, int _gameId, const QString &_gameDescription, int _hostId, int _localPlayerId, bool _spectator, bool _spectatorsCanTalk, bool _spectatorsSeeEverything, bool _resuming); ~TabGame(); void retranslateUi(); void closeRequest(); const QMap &getPlayers() const { return players; } CardItem *getCard(int playerId, const QString &zoneName, int cardId) const; + bool isHost() const { return hostId == localPlayerId; } int getGameId() const { return gameId; } QString getTabText() const { return tr("Game %1: %2").arg(gameId).arg(gameDescription); } bool getSpectator() const { return spectator; } diff --git a/cockatrice/src/tab_room.cpp b/cockatrice/src/tab_room.cpp index 3d13a192..ed418824 100644 --- a/cockatrice/src/tab_room.cpp +++ b/cockatrice/src/tab_room.cpp @@ -26,7 +26,7 @@ TabRoom::TabRoom(TabSupervisor *_tabSupervisor, AbstractClient *_client, const Q QMap tempMap; tempMap.insert(info->getRoomId(), gameTypes); - gameSelector = new GameSelector(client, this, QMap(), tempMap); + gameSelector = new GameSelector(client, tabSupervisor, this, QMap(), tempMap); userList = new UserList(tabSupervisor, client, UserList::RoomList); connect(userList, SIGNAL(openMessageDialog(const QString &, bool)), this, SIGNAL(openMessageDialog(const QString &, bool))); diff --git a/cockatrice/src/tab_supervisor.cpp b/cockatrice/src/tab_supervisor.cpp index f9e6737c..62bf331e 100644 --- a/cockatrice/src/tab_supervisor.cpp +++ b/cockatrice/src/tab_supervisor.cpp @@ -136,6 +136,7 @@ void TabSupervisor::start(AbstractClient *_client, ServerInfo_User *_userInfo) if (userInfo->getUserLevel() & ServerInfo_User::IsModerator) { tabAdmin = new TabAdmin(this, client, (userInfo->getUserLevel() & ServerInfo_User::IsAdmin)); + connect(tabAdmin, SIGNAL(adminLockChanged(bool)), this, SIGNAL(adminLockChanged(bool))); myAddTab(tabAdmin); } else tabAdmin = 0; @@ -227,7 +228,7 @@ void TabSupervisor::addCloseButtonToTab(Tab *tab, int tabIndex) void TabSupervisor::gameJoined(Event_GameJoined *event) { - TabGame *tab = new TabGame(this, QList() << client, event->getGameId(), event->getGameDescription(), event->getPlayerId(), userInfo, event->getSpectator(), event->getSpectatorsCanTalk(), event->getSpectatorsSeeEverything(), event->getResuming()); + TabGame *tab = new TabGame(this, QList() << client, event->getGameId(), event->getGameDescription(), event->getHostId(), event->getPlayerId(), event->getSpectator(), event->getSpectatorsCanTalk(), event->getSpectatorsSeeEverything(), event->getResuming()); connect(tab, SIGNAL(gameClosing(TabGame *)), this, SLOT(gameLeft(TabGame *))); connect(tab, SIGNAL(openMessageDialog(const QString &, bool)), this, SLOT(addMessageTab(const QString &, bool))); int tabIndex = myAddTab(tab); @@ -238,7 +239,7 @@ void TabSupervisor::gameJoined(Event_GameJoined *event) void TabSupervisor::localGameJoined(Event_GameJoined *event) { - TabGame *tab = new TabGame(this, localClients, event->getGameId(), event->getGameDescription(), event->getPlayerId(), userInfo, event->getSpectator(), event->getSpectatorsCanTalk(), event->getSpectatorsSeeEverything(), event->getResuming()); + TabGame *tab = new TabGame(this, localClients, event->getGameId(), event->getGameDescription(), event->getHostId(), event->getPlayerId(), event->getSpectator(), event->getSpectatorsCanTalk(), event->getSpectatorsSeeEverything(), event->getResuming()); connect(tab, SIGNAL(gameClosing(TabGame *)), this, SLOT(gameLeft(TabGame *))); int tabIndex = myAddTab(tab); addCloseButtonToTab(tab, tabIndex); diff --git a/cockatrice/src/tab_supervisor.h b/cockatrice/src/tab_supervisor.h index a88e7384..de05c58b 100644 --- a/cockatrice/src/tab_supervisor.h +++ b/cockatrice/src/tab_supervisor.h @@ -65,6 +65,7 @@ public: signals: void setMenu(QMenu *menu); void localGameEnded(); + void adminLockChanged(bool lock); private slots: void closeButtonPressed(); void updateCurrent(int index); diff --git a/cockatrice/src/userlist.cpp b/cockatrice/src/userlist.cpp index 6a2a28c3..38275ee3 100644 --- a/cockatrice/src/userlist.cpp +++ b/cockatrice/src/userlist.cpp @@ -309,7 +309,7 @@ void UserList::gamesOfUserReceived(ProtocolResponse *resp) gameTypeMap.insert(roomList[i]->getRoomId(), tempMap); } - GameSelector *selector = new GameSelector(client, 0, roomMap, gameTypeMap); + GameSelector *selector = new GameSelector(client, tabSupervisor, 0, roomMap, gameTypeMap); const QList gameList = response->getGameList(); for (int i = 0; i < gameList.size(); ++i) selector->processGameInfo(gameList[i]); diff --git a/common/protocol_item_ids.h b/common/protocol_item_ids.h index 6d6cb37b..0187628f 100644 --- a/common/protocol_item_ids.h +++ b/common/protocol_item_ids.h @@ -48,40 +48,41 @@ ItemId_Event_ConnectionStateChanged = 1046, ItemId_Event_Say = 1047, ItemId_Event_Leave = 1048, ItemId_Event_GameClosed = 1049, -ItemId_Event_Kicked = 1050, -ItemId_Event_Shuffle = 1051, -ItemId_Event_RollDie = 1052, -ItemId_Event_MoveCard = 1053, -ItemId_Event_FlipCard = 1054, -ItemId_Event_DestroyCard = 1055, -ItemId_Event_AttachCard = 1056, -ItemId_Event_CreateToken = 1057, -ItemId_Event_DeleteArrow = 1058, -ItemId_Event_SetCardAttr = 1059, -ItemId_Event_SetCardCounter = 1060, -ItemId_Event_SetCounter = 1061, -ItemId_Event_DelCounter = 1062, -ItemId_Event_SetActivePlayer = 1063, -ItemId_Event_SetActivePhase = 1064, -ItemId_Event_DumpZone = 1065, -ItemId_Event_StopDumpZone = 1066, -ItemId_Event_RemoveFromList = 1067, -ItemId_Event_ServerMessage = 1068, -ItemId_Event_ServerShutdown = 1069, -ItemId_Event_ConnectionClosed = 1070, -ItemId_Event_Message = 1071, -ItemId_Event_GameJoined = 1072, -ItemId_Event_UserLeft = 1073, -ItemId_Event_LeaveRoom = 1074, -ItemId_Event_RoomSay = 1075, -ItemId_Context_ReadyStart = 1076, -ItemId_Context_Concede = 1077, -ItemId_Context_DeckSelect = 1078, -ItemId_Context_UndoDraw = 1079, -ItemId_Context_MoveCard = 1080, -ItemId_Context_Mulligan = 1081, -ItemId_Command_UpdateServerMessage = 1082, -ItemId_Command_ShutdownServer = 1083, -ItemId_Command_BanFromServer = 1084, -ItemId_Other = 1085 +ItemId_Event_GameHostChanged = 1050, +ItemId_Event_Kicked = 1051, +ItemId_Event_Shuffle = 1052, +ItemId_Event_RollDie = 1053, +ItemId_Event_MoveCard = 1054, +ItemId_Event_FlipCard = 1055, +ItemId_Event_DestroyCard = 1056, +ItemId_Event_AttachCard = 1057, +ItemId_Event_CreateToken = 1058, +ItemId_Event_DeleteArrow = 1059, +ItemId_Event_SetCardAttr = 1060, +ItemId_Event_SetCardCounter = 1061, +ItemId_Event_SetCounter = 1062, +ItemId_Event_DelCounter = 1063, +ItemId_Event_SetActivePlayer = 1064, +ItemId_Event_SetActivePhase = 1065, +ItemId_Event_DumpZone = 1066, +ItemId_Event_StopDumpZone = 1067, +ItemId_Event_RemoveFromList = 1068, +ItemId_Event_ServerMessage = 1069, +ItemId_Event_ServerShutdown = 1070, +ItemId_Event_ConnectionClosed = 1071, +ItemId_Event_Message = 1072, +ItemId_Event_GameJoined = 1073, +ItemId_Event_UserLeft = 1074, +ItemId_Event_LeaveRoom = 1075, +ItemId_Event_RoomSay = 1076, +ItemId_Context_ReadyStart = 1077, +ItemId_Context_Concede = 1078, +ItemId_Context_DeckSelect = 1079, +ItemId_Context_UndoDraw = 1080, +ItemId_Context_MoveCard = 1081, +ItemId_Context_Mulligan = 1082, +ItemId_Command_UpdateServerMessage = 1083, +ItemId_Command_ShutdownServer = 1084, +ItemId_Command_BanFromServer = 1085, +ItemId_Other = 1086 }; diff --git a/common/protocol_items.cpp b/common/protocol_items.cpp index 20edd389..d46e8887 100644 --- a/common/protocol_items.cpp +++ b/common/protocol_items.cpp @@ -86,12 +86,13 @@ Command_RoomSay::Command_RoomSay(int _roomId, const QString &_message) { insertItem(new SerializableItem_String("message", _message)); } -Command_JoinGame::Command_JoinGame(int _roomId, int _gameId, const QString &_password, bool _spectator) +Command_JoinGame::Command_JoinGame(int _roomId, int _gameId, const QString &_password, bool _spectator, bool _overrideRestrictions) : RoomCommand("join_game", _roomId) { insertItem(new SerializableItem_Int("game_id", _gameId)); insertItem(new SerializableItem_String("password", _password)); insertItem(new SerializableItem_Bool("spectator", _spectator)); + insertItem(new SerializableItem_Bool("override_restrictions", _overrideRestrictions)); } Command_KickFromGame::Command_KickFromGame(int _gameId, int _playerId) : GameCommand("kick_from_game", _gameId) @@ -278,6 +279,10 @@ Event_GameClosed::Event_GameClosed(int _playerId) : GameEvent("game_closed", _playerId) { } +Event_GameHostChanged::Event_GameHostChanged(int _playerId) + : GameEvent("game_host_changed", _playerId) +{ +} Event_Kicked::Event_Kicked(int _playerId) : GameEvent("kicked", _playerId) { @@ -426,11 +431,12 @@ Event_Message::Event_Message(const QString &_senderName, const QString &_receive insertItem(new SerializableItem_String("receiver_name", _receiverName)); insertItem(new SerializableItem_String("text", _text)); } -Event_GameJoined::Event_GameJoined(int _gameId, const QString &_gameDescription, int _playerId, bool _spectator, bool _spectatorsCanTalk, bool _spectatorsSeeEverything, bool _resuming) +Event_GameJoined::Event_GameJoined(int _gameId, const QString &_gameDescription, int _hostId, 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("host_id", _hostId)); insertItem(new SerializableItem_Int("player_id", _playerId)); insertItem(new SerializableItem_Bool("spectator", _spectator)); insertItem(new SerializableItem_Bool("spectators_can_talk", _spectatorsCanTalk)); @@ -548,6 +554,7 @@ void ProtocolItem::initializeHashAuto() itemNameHash.insert("game_eventsay", Event_Say::newItem); itemNameHash.insert("game_eventleave", Event_Leave::newItem); itemNameHash.insert("game_eventgame_closed", Event_GameClosed::newItem); + itemNameHash.insert("game_eventgame_host_changed", Event_GameHostChanged::newItem); itemNameHash.insert("game_eventkicked", Event_Kicked::newItem); itemNameHash.insert("game_eventshuffle", Event_Shuffle::newItem); itemNameHash.insert("game_eventroll_die", Event_RollDie::newItem); diff --git a/common/protocol_items.dat b/common/protocol_items.dat index 6c41af26..a638db35 100644 --- a/common/protocol_items.dat +++ b/common/protocol_items.dat @@ -15,7 +15,7 @@ 0:join_room:i,room_id 1:leave_room 1:room_say:s,message -1:join_game:i,game_id:s,password:b,spectator +1:join_game:i,game_id:s,password:b,spectator:b,override_restrictions 2:kick_from_game:i,player_id 2:leave_game 2:say:s,message @@ -47,6 +47,7 @@ 3:say:s,message 3:leave 3:game_closed +3:game_host_changed 3:kicked 3:shuffle 3:roll_die:i,sides:i,value @@ -69,7 +70,7 @@ 4:server_shutdown:s,reason:i,minutes 4:connection_closed:s,reason 4:message:s,sender_name:s,receiver_name:s,text -4:game_joined:i,game_id:s,game_description:i,player_id:b,spectator:b,spectators_can_talk:b,spectators_see_everything:b,resuming +4:game_joined:i,game_id:s,game_description:i,host_id:i,player_id:b,spectator:b,spectators_can_talk:b,spectators_see_everything:b,resuming 4:user_left:s,user_name 5:leave_room:s,player_name 5:room_say:s,player_name:s,message @@ -81,4 +82,4 @@ 6:mulligan:i,number 7:update_server_message 7:shutdown_server:s,reason:i,minutes -8:ban_from_server:s,user_name:s,address:i,minutes:s,reason \ No newline at end of file +8:ban_from_server:s,user_name:s,address:i,minutes:s,reason diff --git a/common/protocol_items.h b/common/protocol_items.h index 773e44bd..ac26ef71 100644 --- a/common/protocol_items.h +++ b/common/protocol_items.h @@ -142,10 +142,11 @@ public: class Command_JoinGame : public RoomCommand { Q_OBJECT public: - Command_JoinGame(int _roomId = -1, int _gameId = -1, const QString &_password = QString(), bool _spectator = false); + Command_JoinGame(int _roomId = -1, int _gameId = -1, const QString &_password = QString(), bool _spectator = false, bool _overrideRestrictions = false); int getGameId() const { return static_cast(itemMap.value("game_id"))->getData(); }; QString getPassword() const { return static_cast(itemMap.value("password"))->getData(); }; bool getSpectator() const { return static_cast(itemMap.value("spectator"))->getData(); }; + bool getOverrideRestrictions() const { return static_cast(itemMap.value("override_restrictions"))->getData(); }; static SerializableItem *newItem() { return new Command_JoinGame; } int getItemId() const { return ItemId_Command_JoinGame; } }; @@ -427,6 +428,13 @@ public: static SerializableItem *newItem() { return new Event_GameClosed; } int getItemId() const { return ItemId_Event_GameClosed; } }; +class Event_GameHostChanged : public GameEvent { + Q_OBJECT +public: + Event_GameHostChanged(int _playerId = -1); + static SerializableItem *newItem() { return new Event_GameHostChanged; } + int getItemId() const { return ItemId_Event_GameHostChanged; } +}; class Event_Kicked : public GameEvent { Q_OBJECT public: @@ -644,9 +652,10 @@ 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 _spectatorsCanTalk = false, bool _spectatorsSeeEverything = false, bool _resuming = false); + Event_GameJoined(int _gameId = -1, const QString &_gameDescription = QString(), int _hostId = -1, 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 getHostId() const { return static_cast(itemMap.value("host_id"))->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(); }; diff --git a/common/server_game.cpp b/common/server_game.cpp index ba8eb81c..91c0a9c6 100644 --- a/common/server_game.cpp +++ b/common/server_game.cpp @@ -29,7 +29,7 @@ #include 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 *_room) - : QObject(), room(_room), 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), gameMutex(QMutex::Recursive) + : QObject(), room(_room), hostId(0), 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), gameMutex(QMutex::Recursive) { connect(this, SIGNAL(sigStartGameIfReady()), this, SLOT(doStartGameIfReady()), Qt::QueuedConnection); @@ -201,21 +201,24 @@ void Server_Game::stopGameIfFinished() } } -ResponseCode Server_Game::checkJoin(ServerInfo_User *user, const QString &_password, bool spectator) +ResponseCode Server_Game::checkJoin(ServerInfo_User *user, const QString &_password, bool spectator, bool overrideRestrictions) { - if ((_password != password) && !(spectator && !spectatorsNeedPassword)) - return RespWrongPassword; - if (!(user->getUserLevel() & ServerInfo_User::IsRegistered) && onlyRegistered) - return RespUserLevelTooLow; - if (onlyBuddies) - if (!room->getServer()->getBuddyList(creatorInfo->getName()).contains(user->getName())) - return RespOnlyBuddies; - if (room->getServer()->getIgnoreList(creatorInfo->getName()).contains(user->getName())) - return RespInIgnoreList; - if (spectator) { - if (!spectatorsAllowed) - return RespSpectatorsNotAllowed; - } else if (gameStarted || (getPlayerCount() >= getMaxPlayers())) + if (!(overrideRestrictions && (user->getUserLevel() & ServerInfo_User::IsModerator))) { + if ((_password != password) && !(spectator && !spectatorsNeedPassword)) + return RespWrongPassword; + if (!(user->getUserLevel() & ServerInfo_User::IsRegistered) && onlyRegistered) + return RespUserLevelTooLow; + if (onlyBuddies) + if (!room->getServer()->getBuddyList(creatorInfo->getName()).contains(user->getName())) + return RespOnlyBuddies; + if (room->getServer()->getIgnoreList(creatorInfo->getName()).contains(user->getName())) + return RespInIgnoreList; + if (spectator) { + if (!spectatorsAllowed) + return RespSpectatorsNotAllowed; + } + } + if (!spectator && (gameStarted || (getPlayerCount() >= getMaxPlayers()))) return RespGameFull; return RespOk; @@ -260,12 +263,28 @@ void Server_Game::removePlayer(Server_Player *player) sendGameEvent(new Event_Leave(player->getPlayerId())); bool playerActive = activePlayer == player->getPlayerId(); + bool playerHost = hostId == player->getPlayerId(); bool spectator = player->getSpectator(); player->prepareDestroy(); if (!getPlayerCount()) deleteLater(); else if (!spectator) { + if (playerHost) { + int newHostId = -1; + QMapIterator playerIterator(players); + while (playerIterator.hasNext()) { + Server_Player *p = playerIterator.next().value(); + if (!p->getSpectator()) { + newHostId = p->getPlayerId(); + break; + } + } + if (newHostId != -1) { + hostId = newHostId; + sendGameEvent(new Event_GameHostChanged(hostId)); + } + } stopGameIfFinished(); if (gameStarted && playerActive) nextTurn(); diff --git a/common/server_game.h b/common/server_game.h index f3d761f3..0b1ecc8e 100644 --- a/common/server_game.h +++ b/common/server_game.h @@ -35,6 +35,7 @@ class Server_Game : public QObject { Q_OBJECT private: Server_Room *room; + int hostId; ServerInfo_User *creatorInfo; QMap players; bool gameStarted; @@ -62,6 +63,7 @@ public: 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; + int getHostId() const { return hostId; } ServerInfo_User *getCreatorInfo() const { return creatorInfo; } bool getGameStarted() const { return gameStarted; } int getPlayerCount() const; @@ -76,7 +78,7 @@ public: bool getSpectatorsNeedPassword() const { return spectatorsNeedPassword; } bool getSpectatorsCanTalk() const { return spectatorsCanTalk; } bool getSpectatorsSeeEverything() const { return spectatorsSeeEverything; } - ResponseCode checkJoin(ServerInfo_User *user, const QString &_password, bool spectator); + ResponseCode checkJoin(ServerInfo_User *user, const QString &_password, bool spectator, bool overrideRestrictions); bool containsUser(const QString &userName) const; Server_Player *addPlayer(Server_ProtocolHandler *handler, bool spectator, bool broadcastUpdate = true); void removePlayer(Server_Player *player); diff --git a/common/server_protocolhandler.cpp b/common/server_protocolhandler.cpp index 759df264..7bd1e99f 100644 --- a/common/server_protocolhandler.cpp +++ b/common/server_protocolhandler.cpp @@ -327,7 +327,7 @@ ResponseCode Server_ProtocolHandler::cmdLogin(Command_Login *cmd, CommandContain game->postConnectionStatusUpdate(gamePlayers[j], true); games.insert(game->getGameId(), QPair(game, gamePlayers[j])); - enqueueProtocolItem(new Event_GameJoined(game->getGameId(), game->getDescription(), gamePlayers[j]->getPlayerId(), gamePlayers[j]->getSpectator(), game->getSpectatorsCanTalk(), game->getSpectatorsSeeEverything(), true)); + enqueueProtocolItem(new Event_GameJoined(game->getGameId(), game->getDescription(), game->getHostId(), gamePlayers[j]->getPlayerId(), gamePlayers[j]->getSpectator(), game->getSpectatorsCanTalk(), game->getSpectatorsSeeEverything(), true)); enqueueProtocolItem(GameEventContainer::makeNew(new Event_GameStateChanged(game->getGameStarted(), game->getActivePlayer(), game->getActivePhase(), game->getGameState(gamePlayers[j])), game->getGameId())); break; @@ -527,7 +527,7 @@ ResponseCode Server_ProtocolHandler::cmdCreateGame(Command_CreateGame *cmd, Comm QMutexLocker gameListLocker(&gameListMutex); games.insert(game->getGameId(), QPair(game, creator)); - sendProtocolItem(new Event_GameJoined(game->getGameId(), game->getDescription(), creator->getPlayerId(), false, game->getSpectatorsCanTalk(), game->getSpectatorsSeeEverything(), false)); + sendProtocolItem(new Event_GameJoined(game->getGameId(), game->getDescription(), creator->getPlayerId(), creator->getPlayerId(), false, game->getSpectatorsCanTalk(), game->getSpectatorsSeeEverything(), false)); sendProtocolItem(GameEventContainer::makeNew(new Event_GameStateChanged(game->getGameStarted(), game->getActivePlayer(), game->getActivePhase(), game->getGameState(creator)), game->getGameId())); game->gameMutex.unlock(); @@ -551,11 +551,11 @@ ResponseCode Server_ProtocolHandler::cmdJoinGame(Command_JoinGame *cmd, CommandC QMutexLocker locker(&g->gameMutex); - ResponseCode result = g->checkJoin(userInfo, cmd->getPassword(), cmd->getSpectator()); + ResponseCode result = g->checkJoin(userInfo, cmd->getPassword(), cmd->getSpectator(), cmd->getOverrideRestrictions()); 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(), g->getSpectatorsCanTalk(), g->getSpectatorsSeeEverything(), false)); + enqueueProtocolItem(new Event_GameJoined(cmd->getGameId(), g->getDescription(), g->getHostId(), 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; @@ -569,7 +569,7 @@ ResponseCode Server_ProtocolHandler::cmdLeaveGame(Command_LeaveGame * /*cmd*/, C ResponseCode Server_ProtocolHandler::cmdKickFromGame(Command_KickFromGame *cmd, CommandContainer * /*cont*/, Server_Game *game, Server_Player *player) { - if (game->getCreatorInfo()->getName() != player->getUserInfo()->getName()) + if ((game->getHostId() != player->getPlayerId()) && !(userInfo->getUserLevel() & ServerInfo_User::IsModerator)) return RespFunctionNotAllowed; if (!game->kickPlayer(cmd->getPlayerId())) @@ -657,7 +657,7 @@ ResponseCode Server_ProtocolHandler::cmdReadyStart(Command_ReadyStart *cmd, Comm ResponseCode Server_ProtocolHandler::cmdSay(Command_Say *cmd, CommandContainer * /*cont*/, Server_Game *game, Server_Player *player) { - if (player->getSpectator() && !game->getSpectatorsCanTalk()) + if (player->getSpectator() && !game->getSpectatorsCanTalk() && !(userInfo->getUserLevel() & ServerInfo_User::IsModerator)) return RespFunctionNotAllowed; game->sendGameEvent(new Event_Say(player->getPlayerId(), cmd->getMessage())); diff --git a/servatrice/src/servatrice.cpp b/servatrice/src/servatrice.cpp index e29dd0bc..d5798ce8 100644 --- a/servatrice/src/servatrice.cpp +++ b/servatrice/src/servatrice.cpp @@ -419,4 +419,4 @@ void Servatrice::shutdownTimeout() deleteLater(); } -const QString Servatrice::versionString = "Servatrice 0.20111101"; +const QString Servatrice::versionString = "Servatrice 0.20111113";