From f54165025e2cf5fa4fe5a4b8a34e6a3a9d4ae163 Mon Sep 17 00:00:00 2001 From: ctrlaltca Date: Wed, 28 Aug 2019 02:04:27 +0200 Subject: [PATCH] Add a new command to reverse turn order (#3802) --- cockatrice/src/messagelogwidget.cpp | 7 +++++++ cockatrice/src/messagelogwidget.h | 1 + cockatrice/src/tab_game.cpp | 29 +++++++++++++++++++++++++++ cockatrice/src/tab_game.h | 5 ++++- common/pb/CMakeLists.txt | 4 +++- common/pb/command_reverse_turn.proto | 8 ++++++++ common/pb/event_reverse_turn.proto | 9 +++++++++ common/pb/game_commands.proto | 1 + common/pb/game_event.proto | 1 + common/server_game.cpp | 17 ++++++++++++---- common/server_game.h | 5 +++++ common/server_player.cpp | 30 +++++++++++++++++++++++++++- common/server_player.h | 3 +++ 13 files changed, 113 insertions(+), 7 deletions(-) create mode 100644 common/pb/command_reverse_turn.proto create mode 100644 common/pb/event_reverse_turn.proto diff --git a/cockatrice/src/messagelogwidget.cpp b/cockatrice/src/messagelogwidget.cpp index 3a677ab3..9d64a972 100644 --- a/cockatrice/src/messagelogwidget.cpp +++ b/cockatrice/src/messagelogwidget.cpp @@ -530,6 +530,13 @@ void MessageLogWidget::logRevealCards(Player *player, } } +void MessageLogWidget::logReverseTurn(Player *player, bool reversed) +{ + appendHtmlServerMessage(tr("%1 reversed turn order, now it's %2.") + .arg(sanitizeHtml(player->getName())) + .arg(reversed ? tr("reversed") : tr("normal"))); +} + void MessageLogWidget::logRollDie(Player *player, int sides, int roll) { if (sides == 2) { diff --git a/cockatrice/src/messagelogwidget.h b/cockatrice/src/messagelogwidget.h index 80df4f5e..71faaa01 100644 --- a/cockatrice/src/messagelogwidget.h +++ b/cockatrice/src/messagelogwidget.h @@ -77,6 +77,7 @@ public slots: Player *otherPlayer, bool faceDown, int amount); + void logReverseTurn(Player *player, bool reversed); void logRollDie(Player *player, int sides, int roll); void logSay(Player *player, QString message); void logSetActivePhase(int phase); diff --git a/cockatrice/src/tab_game.cpp b/cockatrice/src/tab_game.cpp index 196219aa..8c9fd18f 100644 --- a/cockatrice/src/tab_game.cpp +++ b/cockatrice/src/tab_game.cpp @@ -47,6 +47,7 @@ #include "pb/command_leave_game.pb.h" #include "pb/command_next_turn.pb.h" #include "pb/command_ready_start.pb.h" +#include "pb/command_reverse_turn.pb.h" #include "pb/command_set_active_phase.pb.h" #include "pb/command_set_sideboard_lock.pb.h" #include "pb/command_set_sideboard_plan.pb.h" @@ -62,6 +63,7 @@ #include "pb/event_kicked.pb.h" #include "pb/event_leave.pb.h" #include "pb/event_player_properties_changed.pb.h" +#include "pb/event_reverse_turn.pb.h" #include "pb/event_set_active_phase.pb.h" #include "pb/event_set_active_player.pb.h" #include "pb/game_event_container.pb.h" @@ -215,6 +217,9 @@ void TabGame::refreshShortcuts() if (aNextTurn) { aNextTurn->setShortcuts(settingsCache->shortcuts().getShortcut("Player/aNextTurn")); } + if (aReverseTurn) { + aReverseTurn->setShortcuts(settingsCache->shortcuts().getShortcut("Player/aReverseTurn")); + } if (aRemoveLocalArrows) { aRemoveLocalArrows->setShortcuts(settingsCache->shortcuts().getShortcut("Player/aRemoveLocalArrows")); } @@ -496,6 +501,9 @@ void TabGame::retranslateUi() if (aNextTurn) { aNextTurn->setText(tr("Next &turn")); } + if (aReverseTurn) { + aReverseTurn->setText(tr("Reverse turn order")); + } if (aRemoveLocalArrows) { aRemoveLocalArrows->setText(tr("&Remove all local arrows")); } @@ -716,6 +724,11 @@ void TabGame::actNextTurn() sendGameCommand(Command_NextTurn()); } +void TabGame::actReverseTurn() +{ + sendGameCommand(Command_ReverseTurn()); +} + void TabGame::actRemoveLocalArrows() { QMapIterator playerIterator(players); @@ -847,6 +860,9 @@ void TabGame::processGameEventContainer(const GameEventContainer &cont, Abstract case GameEvent::SET_ACTIVE_PHASE: eventSetActivePhase(event.GetExtension(Event_SetActivePhase::ext), playerId, context); break; + case GameEvent::REVERSE_TURN: + eventReverseTurn(event.GetExtension(Event_ReverseTurn::ext), playerId, context); + break; default: { Player *player = players.value(playerId, 0); @@ -1209,6 +1225,15 @@ void TabGame::eventKicked(const Event_Kicked & /*event*/, int /*eventPlayerId*/, emitUserEvent(); } +void TabGame::eventReverseTurn(const Event_ReverseTurn &event, int eventPlayerId, const GameEventContext & /*context*/) +{ + Player *player = players.value(eventPlayerId, 0); + if (!player) + return; + + messageLog->logReverseTurn(player, event.reversed()); +} + void TabGame::eventGameHostChanged(const Event_GameHostChanged & /*event*/, int eventPlayerId, const GameEventContext & /*context*/) @@ -1367,6 +1392,8 @@ void TabGame::createMenuItems() connect(aNextPhaseAction, SIGNAL(triggered()), this, SLOT(actNextPhaseAction())); aNextTurn = new QAction(this); connect(aNextTurn, SIGNAL(triggered()), this, SLOT(actNextTurn())); + aReverseTurn = new QAction(this); + connect(aReverseTurn, SIGNAL(triggered()), this, SLOT(actReverseTurn())); aRemoveLocalArrows = new QAction(this); connect(aRemoveLocalArrows, SIGNAL(triggered()), this, SLOT(actRemoveLocalArrows())); aRotateViewCW = new QAction(this); @@ -1399,6 +1426,7 @@ void TabGame::createMenuItems() playersSeparator = gameMenu->addSeparator(); gameMenu->addMenu(phasesMenu); gameMenu->addAction(aNextTurn); + gameMenu->addAction(aReverseTurn); gameMenu->addSeparator(); gameMenu->addAction(aRemoveLocalArrows); gameMenu->addAction(aRotateViewCW); @@ -1415,6 +1443,7 @@ void TabGame::createReplayMenuItems() aNextPhase = nullptr; aNextPhaseAction = nullptr; aNextTurn = nullptr; + aReverseTurn = nullptr; aRemoveLocalArrows = nullptr; aRotateViewCW = nullptr; aRotateViewCCW = nullptr; diff --git a/cockatrice/src/tab_game.h b/cockatrice/src/tab_game.h index 4543c145..10cee2c5 100644 --- a/cockatrice/src/tab_game.h +++ b/cockatrice/src/tab_game.h @@ -45,6 +45,7 @@ class Event_SetActivePhase; class Event_Ping; class Event_GameSay; class Event_Kicked; +class Event_ReverseTurn; class Player; class CardZone; class AbstractCardItem; @@ -165,7 +166,7 @@ private: QMenu *gameMenu, *phasesMenu, *viewMenu, *cardInfoDockMenu, *messageLayoutDockMenu, *playerListDockMenu, *replayDockMenu; QAction *aGameInfo, *aConcede, *aLeaveGame, *aCloseReplay, *aNextPhase, *aNextPhaseAction, *aNextTurn, - *aRemoveLocalArrows, *aRotateViewCW, *aRotateViewCCW, *aResetLayout, *aResetReplayLayout; + *aReverseTurn, *aRemoveLocalArrows, *aRotateViewCW, *aRotateViewCCW, *aResetLayout, *aResetReplayLayout; QAction *aCardInfoDockVisible, *aCardInfoDockFloating, *aMessageLayoutDockVisible, *aMessageLayoutDockFloating, *aPlayerListDockVisible, *aPlayerListDockFloating, *aReplayDockVisible, *aReplayDockFloating; QList phaseActions; @@ -193,6 +194,7 @@ private: void setActivePhase(int phase); void eventSetActivePhase(const Event_SetActivePhase &event, int eventPlayerId, const GameEventContext &context); void eventPing(const Event_Ping &event, int eventPlayerId, const GameEventContext &context); + void eventReverseTurn(const Event_ReverseTurn &event, int eventPlayerId, const GameEventContext & /*context*/); void emitUserEvent(); void createMenuItems(); void createReplayMenuItems(); @@ -236,6 +238,7 @@ private slots: void actNextPhase(); void actNextPhaseAction(); void actNextTurn(); + void actReverseTurn(); void addMentionTag(QString value); void linkCardToChat(QString cardName); diff --git a/common/pb/CMakeLists.txt b/common/pb/CMakeLists.txt index 7be8edba..4f3bdedf 100644 --- a/common/pb/CMakeLists.txt +++ b/common/pb/CMakeLists.txt @@ -38,6 +38,7 @@ SET(PROTO_FILES command_replay_download.proto command_replay_modify_match.proto command_reveal_cards.proto + command_reverse_turn.proto command_roll_die.proto command_set_active_phase.proto command_set_card_attr.proto @@ -88,6 +89,7 @@ SET(PROTO_FILES event_remove_from_list.proto event_replay_added.proto event_reveal_cards.proto + event_reverse_turn.proto event_roll_die.proto event_room_say.proto event_server_complete_list.proto @@ -172,7 +174,7 @@ target_link_libraries(cockatrice_protocol ${cockatrice_protocol_LIBS}) # ubuntu uses an outdated package for protobuf, 3.1.0 is required if(${Protobuf_VERSION} VERSION_LESS "3.1.0") # remove unused parameter and misleading indentation warnings when compiling to avoid errors - set(CMAKE_CXX_FLAGS_DEBUG + set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -Wno-unused-parameter -Wno-misleading-indentation") message(WARNING "Outdated protobuf version found (${Protobuf_VERSION} < 3.1.0), " "disabled warnings to avoid compilation errors.") diff --git a/common/pb/command_reverse_turn.proto b/common/pb/command_reverse_turn.proto new file mode 100644 index 00000000..193379a0 --- /dev/null +++ b/common/pb/command_reverse_turn.proto @@ -0,0 +1,8 @@ +syntax = "proto2"; +import "game_commands.proto"; +message Command_ReverseTurn { + extend GameCommand { + optional Command_ReverseTurn ext = 1034; + } +} + diff --git a/common/pb/event_reverse_turn.proto b/common/pb/event_reverse_turn.proto new file mode 100644 index 00000000..0357d5c0 --- /dev/null +++ b/common/pb/event_reverse_turn.proto @@ -0,0 +1,9 @@ +syntax = "proto2"; +import "game_event.proto"; + +message Event_ReverseTurn { + extend GameEvent { + optional Event_ReverseTurn ext = 2021; + } + optional bool reversed = 1; +} diff --git a/common/pb/game_commands.proto b/common/pb/game_commands.proto index 1544f00c..76f7b200 100644 --- a/common/pb/game_commands.proto +++ b/common/pb/game_commands.proto @@ -35,6 +35,7 @@ message GameCommand { CHANGE_ZONE_PROPERTIES = 1031; UNCONCEDE = 1032; JUDGE = 1033; + REVERSE_TURN = 1034; } extensions 100 to max; } diff --git a/common/pb/game_event.proto b/common/pb/game_event.proto index 09fbe93b..0d7c2d9c 100644 --- a/common/pb/game_event.proto +++ b/common/pb/game_event.proto @@ -30,6 +30,7 @@ message GameEvent { DUMP_ZONE = 2018; STOP_DUMP_ZONE = 2019; CHANGE_ZONE_PROPERTIES = 2020; + REVERSE_TURN = 2021; } optional sint32 player_id = 1 [default = -1]; extensions 100 to max; diff --git a/common/server_game.cpp b/common/server_game.cpp index 2fff28a4..c87c1a64 100644 --- a/common/server_game.cpp +++ b/common/server_game.cpp @@ -66,7 +66,8 @@ Server_Game::Server_Game(const ServerInfo_User &_creatorInfo, onlyRegistered(_onlyRegistered), spectatorsAllowed(_spectatorsAllowed), spectatorsNeedPassword(_spectatorsNeedPassword), spectatorsCanTalk(_spectatorsCanTalk), spectatorsSeeEverything(_spectatorsSeeEverything), inactivityCounter(0), startTimeOfThisGame(0), - secondsElapsed(0), firstGameStarted(false), startTime(QDateTime::currentDateTime()), gameMutex(QMutex::Recursive) + secondsElapsed(0), firstGameStarted(false), turnOrderReversed(false), startTime(QDateTime::currentDateTime()), + gameMutex(QMutex::Recursive) { currentReplay = new GameReplay; currentReplay->set_replay_id(room->getServer()->getDatabaseInterface()->getNextReplayId()); @@ -657,9 +658,17 @@ void Server_Game::nextTurn() if (activePlayer != -1) listPos = keys.indexOf(activePlayer); do { - ++listPos; - if (listPos == keys.size()) - listPos = 0; + if (turnOrderReversed) { + --listPos; + if (listPos < 0) { + listPos = keys.size() - 1; + } + } else { + ++listPos; + if (listPos == keys.size()) { + listPos = 0; + } + } } while (players.value(keys[listPos])->getSpectator() || players.value(keys[listPos])->getConceded()); setActivePlayer(keys[listPos]); diff --git a/common/server_game.h b/common/server_game.h index 39470b52..dc282433 100644 --- a/common/server_game.h +++ b/common/server_game.h @@ -68,6 +68,7 @@ private: int inactivityCounter; int startTimeOfThisGame, secondsElapsed; bool firstGameStarted; + bool turnOrderReversed; QDateTime startTime; QTimer *pingClock; QList replayList; @@ -185,6 +186,10 @@ public: { return secondsElapsed; } + bool reverseTurnOrder() + { + return turnOrderReversed = !turnOrderReversed; + } void createGameJoinedEvent(Server_Player *player, ResponseContainer &rc, bool resuming); diff --git a/common/server_player.cpp b/common/server_player.cpp index 3d3a17f3..4f635ef0 100644 --- a/common/server_player.cpp +++ b/common/server_player.cpp @@ -35,6 +35,7 @@ #include "pb/command_next_turn.pb.h" #include "pb/command_ready_start.pb.h" #include "pb/command_reveal_cards.pb.h" +#include "pb/command_reverse_turn.pb.h" #include "pb/command_roll_die.pb.h" #include "pb/command_set_active_phase.pb.h" #include "pb/command_set_card_attr.pb.h" @@ -60,6 +61,7 @@ #include "pb/event_move_card.pb.h" #include "pb/event_player_properties_changed.pb.h" #include "pb/event_reveal_cards.pb.h" +#include "pb/event_reverse_turn.pb.h" #include "pb/event_roll_die.pb.h" #include "pb/event_set_card_attr.pb.h" #include "pb/event_set_card_counter.pb.h" @@ -1990,6 +1992,30 @@ Response::ResponseCode Server_Player::cmdChangeZoneProperties(const Command_Chan } } +Response::ResponseCode +Server_Player::cmdReverseTurn(const Command_ReverseTurn & /*cmd*/, ResponseContainer & /*rc*/, GameEventStorage &ges) +{ + if (spectator) { + return Response::RespFunctionNotAllowed; + } + + if (!game->getGameStarted()) { + return Response::RespGameNotStarted; + } + + if (conceded) { + return Response::RespContextError; + } + + bool reversedTurn = game->reverseTurnOrder(); + + Event_ReverseTurn event; + event.set_reversed(reversedTurn); + ges.enqueueGameEvent(event, playerId); + + return Response::RespOk; +} + Response::ResponseCode Server_Player::processGameCommand(const GameCommand &command, ResponseContainer &rc, GameEventStorage &ges) { @@ -2096,7 +2122,9 @@ Server_Player::processGameCommand(const GameCommand &command, ResponseContainer case GameCommand::JUDGE: return cmdJudge(command.GetExtension(Command_Judge::ext), rc, ges); break; - + case GameCommand::REVERSE_TURN: + return cmdReverseTurn(command.GetExtension(Command_ReverseTurn::ext), rc, ges); + break; default: return Response::RespInvalidCommand; } diff --git a/common/server_player.h b/common/server_player.h index aba9fbe5..b31cf64e 100644 --- a/common/server_player.h +++ b/common/server_player.h @@ -57,6 +57,7 @@ class Command_SetActivePhase; class Command_DumpZone; class Command_StopDumpZone; class Command_RevealCards; +class Command_ReverseTurn; class Command_MoveCard; class Command_SetSideboardPlan; class Command_DeckSelect; @@ -228,6 +229,8 @@ public: cmdStopDumpZone(const Command_StopDumpZone &cmd, ResponseContainer &rc, GameEventStorage &ges); Response::ResponseCode cmdRevealCards(const Command_RevealCards &cmd, ResponseContainer &rc, GameEventStorage &ges); Response::ResponseCode + cmdReverseTurn(const Command_ReverseTurn & /*cmd*/, ResponseContainer & /*rc*/, GameEventStorage &ges); + Response::ResponseCode cmdChangeZoneProperties(const Command_ChangeZoneProperties &cmd, ResponseContainer &rc, GameEventStorage &ges); Response::ResponseCode processGameCommand(const GameCommand &command, ResponseContainer &rc, GameEventStorage &ges);