diff --git a/cockatrice/src/player.cpp b/cockatrice/src/player.cpp index 5f93098a..430d3e29 100644 --- a/cockatrice/src/player.cpp +++ b/cockatrice/src/player.cpp @@ -60,6 +60,9 @@ Player::Player(ServerInfo_User *info, int _id, bool _local, TabGame *_parent) updateBoundingRect(); if (local) { + connect(_parent, SIGNAL(playerAdded(Player *)), this, SLOT(addPlayer(Player *))); + connect(_parent, SIGNAL(playerRemoved(Player *)), this, SLOT(removePlayer(Player *))); + aMoveHandToTopLibrary = new QAction(this); aMoveHandToTopLibrary->setData(QList() << "deck" << 0); aMoveHandToBottomLibrary = new QAction(this); @@ -141,6 +144,9 @@ Player::Player(ServerInfo_User *info, int _id, bool _local, TabGame *_parent) handMenu->addAction(aMoveHandToBottomLibrary); handMenu->addAction(aMoveHandToGrave); handMenu->addAction(aMoveHandToRfg); + handMenu->addSeparator(); + playerLists.append(mRevealHand = handMenu->addMenu(QString())); + playerLists.append(mRevealRandomHandCard = handMenu->addMenu(QString())); hand->setMenu(handMenu); libraryMenu = playerMenu->addMenu(QString()); @@ -152,6 +158,9 @@ Player::Player(ServerInfo_User *info, int _id, bool _local, TabGame *_parent) libraryMenu->addAction(aViewLibrary); libraryMenu->addAction(aViewTopCards); libraryMenu->addSeparator(); + playerLists.append(mRevealLibrary = libraryMenu->addMenu(QString())); + playerLists.append(mRevealTopCard = libraryMenu->addMenu(QString())); + libraryMenu->addSeparator(); libraryMenu->addAction(aMoveTopCardsToGrave); libraryMenu->addAction(aMoveTopCardsToExile); deck->setMenu(libraryMenu, aDrawCard); @@ -221,6 +230,10 @@ Player::Player(ServerInfo_User *info, int _id, bool _local, TabGame *_parent) aCardMenu = 0; } + const QList &players = _parent->getPlayers().values(); + for (int i = 0; i < players.size(); ++i) + addPlayer(players[i]); + rearrangeZones(); retranslateUi(); } @@ -242,6 +255,40 @@ Player::~Player() delete userInfo; } +void Player::addPlayer(Player *player) +{ + if (player == this) + return; + for (int i = 0; i < playerLists.size(); ++i) { + QAction *newAction = playerLists[i]->addAction(player->getName()); + newAction->setData(player->getId()); + connect(newAction, SIGNAL(triggered()), this, SLOT(playerListActionTriggered())); + } +} + +void Player::removePlayer(Player *player) +{ + for (int i = 0; i < playerLists.size(); ++i) { + QList actionList = playerLists[i]->actions(); + for (int j = 0; j < actionList.size(); ++j) + if (actionList[j]->data().toInt() == player->getId()) { + playerLists[i]->removeAction(actionList[j]); + actionList[j]->deleteLater(); + } + } +} + +void Player::playerListActionTriggered() +{ + QAction *action = static_cast(sender()); + QMenu *menu = static_cast(action->parentWidget()); + int otherPlayerId = action->data().toInt(); + + if (menu == mRevealLibrary) { + sendGameCommand(new Command_RevealCards(-1, "deck", -1, otherPlayerId)); + } +} + void Player::rearrangeZones() { QPointF base = QPointF(CARD_WIDTH + counterAreaWidth + 5, 0); @@ -297,7 +344,7 @@ void Player::retranslateUi() if (local) { aMoveHandToTopLibrary->setText(tr("Move to &top of library")); aMoveHandToBottomLibrary->setText(tr("Move to &bottom of library")); - aMoveHandToGrave->setText(tr("Move to g&raveyard")); + aMoveHandToGrave->setText(tr("Move to &graveyard")); aMoveHandToRfg->setText(tr("Move to &exile")); aMoveGraveToTopLibrary->setText(tr("Move to &top of library")); aMoveGraveToBottomLibrary->setText(tr("Move to &bottom of library")); @@ -306,18 +353,22 @@ void Player::retranslateUi() aMoveRfgToTopLibrary->setText(tr("Move to &top of library")); aMoveRfgToBottomLibrary->setText(tr("Move to &bottom of library")); aMoveRfgToHand->setText(tr("Move to &hand")); - aMoveRfgToGrave->setText(tr("Move to g&raveyard")); + aMoveRfgToGrave->setText(tr("Move to &graveyard")); aViewLibrary->setText(tr("&View library")); aViewTopCards->setText(tr("View &top cards of library...")); + mRevealLibrary->setTitle(tr("Reveal &library to")); + mRevealTopCard->setTitle(tr("Reveal t&op card to")); aViewSideboard->setText(tr("&View sideboard")); aDrawCard->setText(tr("&Draw card")); aDrawCards->setText(tr("D&raw cards...")); aMulligan->setText(tr("Take &mulligan")); aShuffle->setText(tr("&Shuffle")); - aMoveTopCardsToGrave->setText(tr("Move top cards to g&raveyard...")); + aMoveTopCardsToGrave->setText(tr("Move top cards to &graveyard...")); aMoveTopCardsToExile->setText(tr("Move top cards to &exile...")); handMenu->setTitle(tr("&Hand")); + mRevealHand->setTitle(tr("&Reveal to")); + mRevealRandomHandCard->setTitle(tr("Reveal r&andom card to")); sbMenu->setTitle(tr("&Sideboard")); libraryMenu->setTitle(tr("&Library")); countersMenu->setTitle(tr("&Counters")); diff --git a/cockatrice/src/player.h b/cockatrice/src/player.h index b9dafe3b..2a5a581b 100644 --- a/cockatrice/src/player.h +++ b/cockatrice/src/player.h @@ -98,11 +98,17 @@ public slots: void actCardCounterTrigger(); private slots: + void addPlayer(Player *player); + void removePlayer(Player *player); + void playerListActionTriggered(); + void updateBgPixmap(); void updateBoundingRect(); void rearrangeZones(); private: - QMenu *playerMenu, *handMenu, *graveMenu, *rfgMenu, *libraryMenu, *sbMenu, *countersMenu, *sayMenu; + QMenu *playerMenu, *handMenu, *graveMenu, *rfgMenu, *libraryMenu, *sbMenu, *countersMenu, *sayMenu, + *mRevealLibrary, *mRevealTopCard, *mRevealHand, *mRevealRandomHandCard; + QList playerLists; QAction *aMoveHandToTopLibrary, *aMoveHandToBottomLibrary, *aMoveHandToGrave, *aMoveHandToRfg, *aMoveGraveToTopLibrary, *aMoveGraveToBottomLibrary, *aMoveGraveToHand, *aMoveGraveToRfg, *aMoveRfgToTopLibrary, *aMoveRfgToBottomLibrary, *aMoveRfgToHand, *aMoveRfgToGrave, diff --git a/cockatrice/src/tab_game.cpp b/cockatrice/src/tab_game.cpp index 8405719f..c99d70da 100644 --- a/cockatrice/src/tab_game.cpp +++ b/cockatrice/src/tab_game.cpp @@ -351,6 +351,7 @@ Player *TabGame::addPlayer(int playerId, ServerInfo_User *info) tabMenu->insertMenu(playersSeparator, newPlayer->getPlayerMenu()); players.insert(playerId, newPlayer); + emit playerAdded(newPlayer); return newPlayer; } @@ -581,7 +582,8 @@ void TabGame::eventLeave(Event_Leave *event, GameEventContext * /*context*/) messageLog->logLeave(player); playerListWidget->removePlayer(playerId); players.remove(playerId); - delete player; + emit playerRemoved(player); + player->deleteLater(); } emit userEvent(); } diff --git a/cockatrice/src/tab_game.h b/cockatrice/src/tab_game.h index 802f847e..db7ebd0b 100644 --- a/cockatrice/src/tab_game.h +++ b/cockatrice/src/tab_game.h @@ -133,6 +133,8 @@ private: void eventPing(Event_Ping *event, GameEventContext *context); signals: void gameClosing(TabGame *tab); + void playerAdded(Player *player); + void playerRemoved(Player *player); private slots: void newCardAdded(AbstractCardItem *card); void showCardInfoPopup(const QPoint &pos, const QString &cardName); diff --git a/common/protocol.cpp b/common/protocol.cpp index c957692f..ccfc081a 100644 --- a/common/protocol.cpp +++ b/common/protocol.cpp @@ -53,6 +53,7 @@ void ProtocolItem::initializeHash() registerSerializableItem("game_eventcreate_arrows", Event_CreateArrows::newItem); registerSerializableItem("game_eventcreate_counters", Event_CreateCounters::newItem); registerSerializableItem("game_eventdraw_cards", Event_DrawCards::newItem); + registerSerializableItem("game_eventreveal_cards", Event_RevealCards::newItem); registerSerializableItem("game_eventping", Event_Ping::newItem); registerSerializableItem("chat_eventchat_list_players", Event_ChatListPlayers::newItem); registerSerializableItem("chat_eventchat_join_channel", Event_ChatJoinChannel::newItem); @@ -108,7 +109,7 @@ void Command::processResponse(ProtocolResponse *response) } CommandContainer::CommandContainer(const QList &_commandList, int _cmdId) - : ProtocolItem("container", "cmd"), ticks(0), resp(0), gameEventQueuePublic(0), gameEventQueueOmniscient(0), gameEventQueuePrivate(0) + : ProtocolItem("container", "cmd"), ticks(0), resp(0), gameEventQueuePublic(0), gameEventQueueOmniscient(0), gameEventQueuePrivate(0), privatePlayerId(-1) { if (_cmdId == -1) _cmdId = lastCmdId++; @@ -148,11 +149,12 @@ void CommandContainer::enqueueGameEventOmniscient(GameEvent *event, int gameId) gameEventQueueOmniscient->addGameEvent(event); } -void CommandContainer::enqueueGameEventPrivate(GameEvent *event, int gameId) +void CommandContainer::enqueueGameEventPrivate(GameEvent *event, int gameId, int playerId) { if (!gameEventQueuePrivate) gameEventQueuePrivate = new GameEventContainer(QList(), gameId); gameEventQueuePrivate->addGameEvent(event); + privatePlayerId = playerId; } Command_DeckUpload::Command_DeckUpload(DeckList *_deck, const QString &_path) @@ -430,3 +432,13 @@ Event_DrawCards::Event_DrawCards(int _playerId, int _numberCards, const QList &_cardList) + : GameEvent("reveal_cards", _playerId) +{ + insertItem(new SerializableItem_String("zone_name", _zoneName)); + insertItem(new SerializableItem_Int("card_id", _cardId)); + insertItem(new SerializableItem_Int("other_player_id", _otherPlayerId)); + for (int i = 0; i < _cardList.size(); ++i) + itemList.append(_cardList[i]); +} diff --git a/common/protocol.h b/common/protocol.h index e60a7162..a32588dc 100644 --- a/common/protocol.h +++ b/common/protocol.h @@ -35,8 +35,9 @@ enum ItemId { ItemId_Event_CreateArrows = ItemId_Other + 207, ItemId_Event_CreateCounters = ItemId_Other + 208, ItemId_Event_DrawCards = ItemId_Other + 209, - ItemId_Event_Join = ItemId_Other + 210, - ItemId_Event_Ping = ItemId_Other + 211, + ItemId_Event_RevealCards = ItemId_Other + 210, + ItemId_Event_Join = ItemId_Other + 211, + ItemId_Event_Ping = ItemId_Other + 212, ItemId_Response_ListUsers = ItemId_Other + 300, ItemId_Response_GetUserInfo = ItemId_Other + 301, ItemId_Response_DeckList = ItemId_Other + 302, @@ -112,6 +113,7 @@ private: GameEventContainer *gameEventQueuePublic; GameEventContainer *gameEventQueueOmniscient; GameEventContainer *gameEventQueuePrivate; + int privatePlayerId; public: CommandContainer(const QList &_commandList = QList(), int _cmdId = -1); static SerializableItem *newItem() { return new CommandContainer; } @@ -130,7 +132,8 @@ public: GameEventContainer *getGameEventQueueOmniscient() const { return gameEventQueueOmniscient; } void enqueueGameEventOmniscient(GameEvent *event, int gameId); GameEventContainer *getGameEventQueuePrivate() const { return gameEventQueuePrivate; } - void enqueueGameEventPrivate(GameEvent *event, int gameId); + void enqueueGameEventPrivate(GameEvent *event, int gameId, int playerId = -1); + int getPrivatePlayerId() const { return privatePlayerId; } }; class ChatCommand : public Command { @@ -420,4 +423,16 @@ public: QList getCardList() const { return typecastItemList(); } }; +class Event_RevealCards : public GameEvent { + Q_OBJECT +public: + Event_RevealCards(int _playerId = -1, const QString &_zoneName = QString(), int cardId = -1, int _otherPlayerId = -1, const QList &_cardList = QList()); + int getItemId() const { return ItemId_Event_RevealCards; } + static SerializableItem *newItem() { return new Event_RevealCards; } + QString getZoneName() const { return static_cast(itemMap.value("zone_name"))->getData(); } + int getCardId() const { return static_cast(itemMap.value("card_id"))->getData(); } + int getOtherPlayerId() const { return static_cast(itemMap.value("other_player_id"))->getData(); } + QList getCardList() const { return typecastItemList(); } +}; + #endif diff --git a/common/protocol_item_ids.h b/common/protocol_item_ids.h index 6921eb81..8404364b 100644 --- a/common/protocol_item_ids.h +++ b/common/protocol_item_ids.h @@ -41,33 +41,34 @@ ItemId_Command_NextTurn = 1039, ItemId_Command_SetActivePhase = 1040, ItemId_Command_DumpZone = 1041, ItemId_Command_StopDumpZone = 1042, -ItemId_Event_Say = 1043, -ItemId_Event_Leave = 1044, -ItemId_Event_GameClosed = 1045, -ItemId_Event_Shuffle = 1046, -ItemId_Event_RollDie = 1047, -ItemId_Event_MoveCard = 1048, -ItemId_Event_FlipCard = 1049, -ItemId_Event_DestroyCard = 1050, -ItemId_Event_AttachCard = 1051, -ItemId_Event_CreateToken = 1052, -ItemId_Event_DeleteArrow = 1053, -ItemId_Event_SetCardAttr = 1054, -ItemId_Event_SetCardCounter = 1055, -ItemId_Event_SetCounter = 1056, -ItemId_Event_DelCounter = 1057, -ItemId_Event_SetActivePlayer = 1058, -ItemId_Event_SetActivePhase = 1059, -ItemId_Event_DumpZone = 1060, -ItemId_Event_StopDumpZone = 1061, -ItemId_Event_ServerMessage = 1062, -ItemId_Event_Message = 1063, -ItemId_Event_GameJoined = 1064, -ItemId_Event_UserLeft = 1065, -ItemId_Event_ChatLeaveChannel = 1066, -ItemId_Event_ChatSay = 1067, -ItemId_Context_ReadyStart = 1068, -ItemId_Context_Concede = 1069, -ItemId_Context_DeckSelect = 1070, -ItemId_Other = 1071 +ItemId_Command_RevealCards = 1043, +ItemId_Event_Say = 1044, +ItemId_Event_Leave = 1045, +ItemId_Event_GameClosed = 1046, +ItemId_Event_Shuffle = 1047, +ItemId_Event_RollDie = 1048, +ItemId_Event_MoveCard = 1049, +ItemId_Event_FlipCard = 1050, +ItemId_Event_DestroyCard = 1051, +ItemId_Event_AttachCard = 1052, +ItemId_Event_CreateToken = 1053, +ItemId_Event_DeleteArrow = 1054, +ItemId_Event_SetCardAttr = 1055, +ItemId_Event_SetCardCounter = 1056, +ItemId_Event_SetCounter = 1057, +ItemId_Event_DelCounter = 1058, +ItemId_Event_SetActivePlayer = 1059, +ItemId_Event_SetActivePhase = 1060, +ItemId_Event_DumpZone = 1061, +ItemId_Event_StopDumpZone = 1062, +ItemId_Event_ServerMessage = 1063, +ItemId_Event_Message = 1064, +ItemId_Event_GameJoined = 1065, +ItemId_Event_UserLeft = 1066, +ItemId_Event_ChatLeaveChannel = 1067, +ItemId_Event_ChatSay = 1068, +ItemId_Context_ReadyStart = 1069, +ItemId_Context_Concede = 1070, +ItemId_Context_DeckSelect = 1071, +ItemId_Other = 1072 }; diff --git a/common/protocol_items.cpp b/common/protocol_items.cpp index 74f51c02..57a32f63 100644 --- a/common/protocol_items.cpp +++ b/common/protocol_items.cpp @@ -253,6 +253,13 @@ Command_StopDumpZone::Command_StopDumpZone(int _gameId, int _playerId, const QSt insertItem(new SerializableItem_Int("player_id", _playerId)); insertItem(new SerializableItem_String("zone_name", _zoneName)); } +Command_RevealCards::Command_RevealCards(int _gameId, const QString &_zoneName, int _cardId, int _playerId) + : GameCommand("reveal_cards", _gameId) +{ + insertItem(new SerializableItem_String("zone_name", _zoneName)); + insertItem(new SerializableItem_Int("card_id", _cardId)); + insertItem(new SerializableItem_Int("player_id", _playerId)); +} Event_Say::Event_Say(int _playerId, const QString &_message) : GameEvent("say", _playerId) { @@ -476,6 +483,7 @@ void ProtocolItem::initializeHashAuto() itemNameHash.insert("cmdset_active_phase", Command_SetActivePhase::newItem); itemNameHash.insert("cmddump_zone", Command_DumpZone::newItem); itemNameHash.insert("cmdstop_dump_zone", Command_StopDumpZone::newItem); + itemNameHash.insert("cmdreveal_cards", Command_RevealCards::newItem); itemNameHash.insert("game_eventsay", Event_Say::newItem); itemNameHash.insert("game_eventleave", Event_Leave::newItem); itemNameHash.insert("game_eventgame_closed", Event_GameClosed::newItem); diff --git a/common/protocol_items.dat b/common/protocol_items.dat index ec077b41..bc9a28e5 100644 --- a/common/protocol_items.dat +++ b/common/protocol_items.dat @@ -40,6 +40,7 @@ 2:set_active_phase:i,phase 2:dump_zone:i,player_id:s,zone_name:i,number_cards 2:stop_dump_zone:i,player_id:s,zone_name +2:reveal_cards:s,zone_name:i,card_id:i,player_id 3:say:s,message 3:leave 3:game_closed diff --git a/common/protocol_items.h b/common/protocol_items.h index 00c16260..69664127 100644 --- a/common/protocol_items.h +++ b/common/protocol_items.h @@ -381,6 +381,16 @@ public: static SerializableItem *newItem() { return new Command_StopDumpZone; } int getItemId() const { return ItemId_Command_StopDumpZone; } }; +class Command_RevealCards : public GameCommand { + Q_OBJECT +public: + Command_RevealCards(int _gameId = -1, const QString &_zoneName = QString(), int _cardId = -1, int _playerId = -1); + QString getZoneName() const { return static_cast(itemMap.value("zone_name"))->getData(); }; + int getCardId() const { return static_cast(itemMap.value("card_id"))->getData(); }; + int getPlayerId() const { return static_cast(itemMap.value("player_id"))->getData(); }; + static SerializableItem *newItem() { return new Command_RevealCards; } + int getItemId() const { return ItemId_Command_RevealCards; } +}; class Event_Say : public GameEvent { Q_OBJECT public: diff --git a/common/server_protocolhandler.cpp b/common/server_protocolhandler.cpp index 56645dfc..4a2fe7b3 100644 --- a/common/server_protocolhandler.cpp +++ b/common/server_protocolhandler.cpp @@ -110,6 +110,7 @@ ResponseCode Server_ProtocolHandler::processCommandHelper(Command *command, Comm case ItemId_Command_SetActivePhase: return cmdSetActivePhase(qobject_cast(command), cont, game, player); case ItemId_Command_DumpZone: return cmdDumpZone(qobject_cast(command), cont, game, player); case ItemId_Command_StopDumpZone: return cmdStopDumpZone(qobject_cast(command), cont, game, player); + case ItemId_Command_RevealCards: return cmdRevealCards(qobject_cast(command), cont, game, player); } } else { qDebug() << "received generic Command"; @@ -156,12 +157,18 @@ void Server_ProtocolHandler::processCommandContainer(CommandContainer *cont) GameEventContainer *gQPrivate = cont->getGameEventQueuePrivate(); GameEventContainer *gQOmniscient = cont->getGameEventQueueOmniscient(); if (gQPrivate) { + int privatePlayerId = cont->getPrivatePlayerId(); + Server_Player *privatePlayer; + if (privatePlayerId == -1) + privatePlayer = player; + else + privatePlayer = game->getPlayer(privatePlayerId); if (gQOmniscient) { - game->sendGameEventContainer(gQPublic, player, true); - game->sendGameEventContainerOmniscient(gQOmniscient, player); + game->sendGameEventContainer(gQPublic, privatePlayer, true); + game->sendGameEventContainerOmniscient(gQOmniscient, privatePlayer); } else - game->sendGameEventContainer(gQPublic, player); - player->sendProtocolItem(gQPrivate); + game->sendGameEventContainer(gQPublic, privatePlayer); + privatePlayer->sendProtocolItem(gQPrivate); } else game->sendGameEventContainer(gQPublic); } @@ -1145,3 +1152,59 @@ ResponseCode Server_ProtocolHandler::cmdStopDumpZone(Command_StopDumpZone *cmd, } return RespOk; } + +ResponseCode Server_ProtocolHandler::cmdRevealCards(Command_RevealCards *cmd, CommandContainer *cont, Server_Game *game, Server_Player *player) +{ + if (player->getSpectator()) + return RespFunctionNotAllowed; + + if (!game->getGameStarted()) + return RespGameNotStarted; + + Server_Player *otherPlayer = game->getPlayer(cmd->getPlayerId()); + if (!otherPlayer) + return RespNameNotFound; + Server_CardZone *zone = player->getZones().value(cmd->getZoneName()); + if (!zone) + return RespNameNotFound; + + QList cardsToReveal; + if (cmd->getCardId() == -1) + cardsToReveal = zone->cards; + else { + Server_Card *card = zone->getCard(cmd->getCardId(), false); + if (!card) + return RespNameNotFound; + cardsToReveal.append(card); + } + + QList respCardListPrivate, respCardListOmniscient; + for (int i = 0; i < cardsToReveal.size(); ++i) { + Server_Card *card = cardsToReveal[i]; + + QList cardCounterList; + QMapIterator cardCounterIterator(card->getCounters()); + while (cardCounterIterator.hasNext()) { + cardCounterIterator.next(); + cardCounterList.append(new ServerInfo_CardCounter(cardCounterIterator.key(), cardCounterIterator.value())); + } + + int attachPlayerId = -1; + QString attachZone; + int attachCardId = -1; + if (card->getParentCard()) { + attachPlayerId = card->getParentCard()->getZone()->getPlayer()->getPlayerId(); + attachZone = card->getParentCard()->getZone()->getName(); + attachCardId = card->getParentCard()->getId(); + } + + respCardListPrivate.append(new ServerInfo_Card(card->getId(), card->getName(), card->getX(), card->getY(), card->getTapped(), card->getAttacking(), card->getColor(), card->getPT(), card->getAnnotation(), card->getDestroyOnZoneChange(), cardCounterList, attachPlayerId, attachZone, attachCardId)); + respCardListOmniscient.append(new ServerInfo_Card(card->getId(), card->getName(), card->getX(), card->getY(), card->getTapped(), card->getAttacking(), card->getColor(), card->getPT(), card->getAnnotation(), card->getDestroyOnZoneChange(), cardCounterList, attachPlayerId, attachZone, attachCardId)); + } + + cont->enqueueGameEventPublic(new Event_RevealCards(player->getPlayerId(), zone->getName(), cmd->getCardId(), otherPlayer->getPlayerId()), game->getGameId()); + cont->enqueueGameEventPrivate(new Event_RevealCards(player->getPlayerId(), zone->getName(), cmd->getCardId(), otherPlayer->getPlayerId(), respCardListPrivate), game->getGameId(), otherPlayer->getPlayerId()); + cont->enqueueGameEventOmniscient(new Event_RevealCards(player->getPlayerId(), zone->getName(), cmd->getCardId(), otherPlayer->getPlayerId(), respCardListOmniscient), game->getGameId()); + + return RespOk; +} \ No newline at end of file diff --git a/common/server_protocolhandler.h b/common/server_protocolhandler.h index 0f6ccc8c..d7719259 100644 --- a/common/server_protocolhandler.h +++ b/common/server_protocolhandler.h @@ -85,6 +85,7 @@ private: ResponseCode cmdSetActivePhase(Command_SetActivePhase *cmd, CommandContainer *cont, Server_Game *game, Server_Player *player); ResponseCode cmdDumpZone(Command_DumpZone *cmd, CommandContainer *cont, Server_Game *game, Server_Player *player); ResponseCode cmdStopDumpZone(Command_StopDumpZone *cmd, CommandContainer *cont, Server_Game *game, Server_Player *player); + ResponseCode cmdRevealCards(Command_RevealCards *cmd, CommandContainer *cont, Server_Game *game, Server_Player *player); ResponseCode processCommandHelper(Command *command, CommandContainer *cont); private slots: