diff --git a/cockatrice/src/messagelogwidget.cpp b/cockatrice/src/messagelogwidget.cpp
index caf9bc4d9..b77324e27 100644
--- a/cockatrice/src/messagelogwidget.cpp
+++ b/cockatrice/src/messagelogwidget.cpp
@@ -202,6 +202,14 @@ void MessageLogWidget::logMoveCard(Player *player, QString cardName, CardZone *s
append(finalStr.arg(sanitizeHtml(player->getName())).arg(cardStr).arg(fromStr).arg(newX));
}
+void MessageLogWidget::logFlipCard(Player *player, QString cardName, bool faceDown)
+{
+ if (faceDown)
+ append(tr("%1 flips %2 face-down.").arg(sanitizeHtml(player->getName())).arg(cardName));
+ else
+ append(tr("%1 flips %2 face-up.").arg(sanitizeHtml(player->getName())).arg(cardName));
+}
+
void MessageLogWidget::logDestroyCard(Player *player, QString cardName)
{
append(tr("%1 destroys %2.").arg(sanitizeHtml(player->getName())).arg(QString("%1").arg(sanitizeHtml(cardName))));
@@ -350,6 +358,7 @@ void MessageLogWidget::connectToPlayer(Player *player)
connect(player, SIGNAL(logSetPT(Player *, QString, QString)), this, SLOT(logSetPT(Player *, QString, QString)));
connect(player, SIGNAL(logSetAnnotation(Player *, QString, QString)), this, SLOT(logSetAnnotation(Player *, QString, QString)));
connect(player, SIGNAL(logMoveCard(Player *, QString, CardZone *, int, CardZone *, int)), this, SLOT(logMoveCard(Player *, QString, CardZone *, int, CardZone *, int)));
+ connect(player, SIGNAL(logFlipCard(Player *, QString, bool)), this, SLOT(logFlipCard(Player *, QString, bool)));
connect(player, SIGNAL(logDestroyCard(Player *, QString)), this, SLOT(logDestroyCard(Player *, QString)));
connect(player, SIGNAL(logAttachCard(Player *, QString, Player *, QString)), this, SLOT(logAttachCard(Player *, QString, Player *, QString)));
connect(player, SIGNAL(logUnattachCard(Player *, QString)), this, SLOT(logUnattachCard(Player *, QString)));
diff --git a/cockatrice/src/messagelogwidget.h b/cockatrice/src/messagelogwidget.h
index c8787b577..b535a5dc3 100644
--- a/cockatrice/src/messagelogwidget.h
+++ b/cockatrice/src/messagelogwidget.h
@@ -39,6 +39,7 @@ public slots:
void logRollDie(Player *player, int sides, int roll);
void logDrawCards(Player *player, int number);
void logMoveCard(Player *player, QString cardName, CardZone *startZone, int oldX, CardZone *targetZone, int newX);
+ void logFlipCard(Player *player, QString cardName, bool faceDown);
void logDestroyCard(Player *player, QString cardName);
void logAttachCard(Player *player, QString cardName, Player *targetPlayer, QString targetCardName);
void logUnattachCard(Player *player, QString cardName);
diff --git a/cockatrice/src/player.cpp b/cockatrice/src/player.cpp
index 6177b5867..545dbd63c 100644
--- a/cockatrice/src/player.cpp
+++ b/cockatrice/src/player.cpp
@@ -737,6 +737,18 @@ void Player::eventMoveCard(Event_MoveCard *event)
}
}
+void Player::eventFlipCard(Event_FlipCard *event)
+{
+ CardZone *zone = zones.value(event->getZone(), 0);
+ if (!zone)
+ return;
+ CardItem *card = zone->getCard(event->getCardId(), event->getCardName());
+ if (!card)
+ return;
+ emit logFlipCard(this, card->getName(), event->getFaceDown());
+ card->setFaceDown(event->getFaceDown());
+}
+
void Player::eventDestroyCard(Event_DestroyCard *event)
{
CardZone *zone = zones.value(event->getZone(), 0);
@@ -829,6 +841,7 @@ void Player::processGameEvent(GameEvent *event, GameEventContext *context)
case ItemId_Event_DumpZone: eventDumpZone(qobject_cast(event)); break;
case ItemId_Event_StopDumpZone: eventStopDumpZone(qobject_cast(event)); break;
case ItemId_Event_MoveCard: eventMoveCard(qobject_cast(event)); break;
+ case ItemId_Event_FlipCard: eventFlipCard(qobject_cast(event)); break;
case ItemId_Event_DestroyCard: eventDestroyCard(qobject_cast(event)); break;
case ItemId_Event_AttachCard: eventAttachCard(qobject_cast(event)); break;
case ItemId_Event_DrawCards: eventDrawCards(qobject_cast(event)); break;
@@ -1109,7 +1122,7 @@ void Player::cardMenuAction()
break;
case 3: {
QString zone = card->getZone()->getName();
- commandList.append(new Command_MoveCard(-1, zone, card->getId(), zone, card->getGridPoint().x(), card->getGridPoint().y(), !card->getFaceDown()));
+ commandList.append(new Command_FlipCard(-1, zone, card->getId(), !card->getFaceDown()));
break;
}
case 4:
diff --git a/cockatrice/src/player.h b/cockatrice/src/player.h
index 227cff534..fc263c591 100644
--- a/cockatrice/src/player.h
+++ b/cockatrice/src/player.h
@@ -38,6 +38,7 @@ class Event_DelCounter;
class Event_DumpZone;
class Event_StopDumpZone;
class Event_MoveCard;
+class Event_FlipCard;
class Event_DestroyCard;
class Event_AttachCard;
class Event_DrawCards;
@@ -54,6 +55,7 @@ signals:
void logCreateToken(Player *player, QString cardName, QString pt);
void logDrawCards(Player *player, int number);
void logMoveCard(Player *player, QString cardName, CardZone *startZone, int oldX, CardZone *targetZone, int newX);
+ void logFlipCard(Player *player, QString cardName, bool faceDown);
void logDestroyCard(Player *player, QString cardName);
void logAttachCard(Player *player, QString cardName, Player *targetPlayer, QString targetCardName);
void logUnattachCard(Player *player, QString cardName);
@@ -153,6 +155,7 @@ private:
void eventDumpZone(Event_DumpZone *event);
void eventStopDumpZone(Event_StopDumpZone *event);
void eventMoveCard(Event_MoveCard *event);
+ void eventFlipCard(Event_FlipCard *event);
void eventDestroyCard(Event_DestroyCard *event);
void eventAttachCard(Event_AttachCard *event);
void eventDrawCards(Event_DrawCards *event);
diff --git a/common/protocol_item_ids.h b/common/protocol_item_ids.h
index efaaa4f77..e7a95a095 100644
--- a/common/protocol_item_ids.h
+++ b/common/protocol_item_ids.h
@@ -20,48 +20,50 @@ ItemId_Command_Mulligan = 1018,
ItemId_Command_RollDie = 1019,
ItemId_Command_DrawCards = 1020,
ItemId_Command_MoveCard = 1021,
-ItemId_Command_AttachCard = 1022,
-ItemId_Command_CreateToken = 1023,
-ItemId_Command_CreateArrow = 1024,
-ItemId_Command_DeleteArrow = 1025,
-ItemId_Command_SetCardAttr = 1026,
-ItemId_Command_SetCardCounter = 1027,
-ItemId_Command_IncCardCounter = 1028,
-ItemId_Command_ReadyStart = 1029,
-ItemId_Command_Concede = 1030,
-ItemId_Command_IncCounter = 1031,
-ItemId_Command_CreateCounter = 1032,
-ItemId_Command_SetCounter = 1033,
-ItemId_Command_DelCounter = 1034,
-ItemId_Command_NextTurn = 1035,
-ItemId_Command_SetActivePhase = 1036,
-ItemId_Command_DumpZone = 1037,
-ItemId_Command_StopDumpZone = 1038,
-ItemId_Event_Say = 1039,
-ItemId_Event_Leave = 1040,
-ItemId_Event_GameClosed = 1041,
-ItemId_Event_Shuffle = 1042,
-ItemId_Event_RollDie = 1043,
-ItemId_Event_MoveCard = 1044,
-ItemId_Event_DestroyCard = 1045,
-ItemId_Event_AttachCard = 1046,
-ItemId_Event_CreateToken = 1047,
-ItemId_Event_DeleteArrow = 1048,
-ItemId_Event_SetCardAttr = 1049,
-ItemId_Event_SetCardCounter = 1050,
-ItemId_Event_SetCounter = 1051,
-ItemId_Event_DelCounter = 1052,
-ItemId_Event_SetActivePlayer = 1053,
-ItemId_Event_SetActivePhase = 1054,
-ItemId_Event_DumpZone = 1055,
-ItemId_Event_StopDumpZone = 1056,
-ItemId_Event_ServerMessage = 1057,
-ItemId_Event_GameJoined = 1058,
-ItemId_Event_ChatJoinChannel = 1059,
-ItemId_Event_ChatLeaveChannel = 1060,
-ItemId_Event_ChatSay = 1061,
-ItemId_Context_ReadyStart = 1062,
-ItemId_Context_Concede = 1063,
-ItemId_Context_DeckSelect = 1064,
-ItemId_Other = 1065
+ItemId_Command_FlipCard = 1022,
+ItemId_Command_AttachCard = 1023,
+ItemId_Command_CreateToken = 1024,
+ItemId_Command_CreateArrow = 1025,
+ItemId_Command_DeleteArrow = 1026,
+ItemId_Command_SetCardAttr = 1027,
+ItemId_Command_SetCardCounter = 1028,
+ItemId_Command_IncCardCounter = 1029,
+ItemId_Command_ReadyStart = 1030,
+ItemId_Command_Concede = 1031,
+ItemId_Command_IncCounter = 1032,
+ItemId_Command_CreateCounter = 1033,
+ItemId_Command_SetCounter = 1034,
+ItemId_Command_DelCounter = 1035,
+ItemId_Command_NextTurn = 1036,
+ItemId_Command_SetActivePhase = 1037,
+ItemId_Command_DumpZone = 1038,
+ItemId_Command_StopDumpZone = 1039,
+ItemId_Event_Say = 1040,
+ItemId_Event_Leave = 1041,
+ItemId_Event_GameClosed = 1042,
+ItemId_Event_Shuffle = 1043,
+ItemId_Event_RollDie = 1044,
+ItemId_Event_MoveCard = 1045,
+ItemId_Event_FlipCard = 1046,
+ItemId_Event_DestroyCard = 1047,
+ItemId_Event_AttachCard = 1048,
+ItemId_Event_CreateToken = 1049,
+ItemId_Event_DeleteArrow = 1050,
+ItemId_Event_SetCardAttr = 1051,
+ItemId_Event_SetCardCounter = 1052,
+ItemId_Event_SetCounter = 1053,
+ItemId_Event_DelCounter = 1054,
+ItemId_Event_SetActivePlayer = 1055,
+ItemId_Event_SetActivePhase = 1056,
+ItemId_Event_DumpZone = 1057,
+ItemId_Event_StopDumpZone = 1058,
+ItemId_Event_ServerMessage = 1059,
+ItemId_Event_GameJoined = 1060,
+ItemId_Event_ChatJoinChannel = 1061,
+ItemId_Event_ChatLeaveChannel = 1062,
+ItemId_Event_ChatSay = 1063,
+ItemId_Context_ReadyStart = 1064,
+ItemId_Context_Concede = 1065,
+ItemId_Context_DeckSelect = 1066,
+ItemId_Other = 1067
};
diff --git a/common/protocol_items.cpp b/common/protocol_items.cpp
index a2a7b8d0c..c4e4e14c1 100644
--- a/common/protocol_items.cpp
+++ b/common/protocol_items.cpp
@@ -114,6 +114,13 @@ Command_MoveCard::Command_MoveCard(int _gameId, const QString &_startZone, int _
insertItem(new SerializableItem_Bool("face_down", _faceDown));
insertItem(new SerializableItem_Bool("tapped", _tapped));
}
+Command_FlipCard::Command_FlipCard(int _gameId, const QString &_zone, int _cardId, bool _faceDown)
+ : GameCommand("flip_card", _gameId)
+{
+ insertItem(new SerializableItem_String("zone", _zone));
+ insertItem(new SerializableItem_Int("card_id", _cardId));
+ insertItem(new SerializableItem_Bool("face_down", _faceDown));
+}
Command_AttachCard::Command_AttachCard(int _gameId, const QString &_startZone, int _cardId, int _targetPlayerId, const QString &_targetZone, int _targetCardId)
: GameCommand("attach_card", _gameId)
{
@@ -267,6 +274,14 @@ Event_MoveCard::Event_MoveCard(int _playerId, int _cardId, const QString &_cardN
insertItem(new SerializableItem_Int("new_card_id", _newCardId));
insertItem(new SerializableItem_Bool("face_down", _faceDown));
}
+Event_FlipCard::Event_FlipCard(int _playerId, const QString &_zone, int _cardId, const QString &_cardName, bool _faceDown)
+ : GameEvent("flip_card", _playerId)
+{
+ insertItem(new SerializableItem_String("zone", _zone));
+ insertItem(new SerializableItem_Int("card_id", _cardId));
+ insertItem(new SerializableItem_String("card_name", _cardName));
+ insertItem(new SerializableItem_Bool("face_down", _faceDown));
+}
Event_DestroyCard::Event_DestroyCard(int _playerId, const QString &_zone, int _cardId)
: GameEvent("destroy_card", _playerId)
{
@@ -418,6 +433,7 @@ void ProtocolItem::initializeHashAuto()
itemNameHash.insert("cmdroll_die", Command_RollDie::newItem);
itemNameHash.insert("cmddraw_cards", Command_DrawCards::newItem);
itemNameHash.insert("cmdmove_card", Command_MoveCard::newItem);
+ itemNameHash.insert("cmdflip_card", Command_FlipCard::newItem);
itemNameHash.insert("cmdattach_card", Command_AttachCard::newItem);
itemNameHash.insert("cmdcreate_token", Command_CreateToken::newItem);
itemNameHash.insert("cmdcreate_arrow", Command_CreateArrow::newItem);
@@ -441,6 +457,7 @@ void ProtocolItem::initializeHashAuto()
itemNameHash.insert("game_eventshuffle", Event_Shuffle::newItem);
itemNameHash.insert("game_eventroll_die", Event_RollDie::newItem);
itemNameHash.insert("game_eventmove_card", Event_MoveCard::newItem);
+ itemNameHash.insert("game_eventflip_card", Event_FlipCard::newItem);
itemNameHash.insert("game_eventdestroy_card", Event_DestroyCard::newItem);
itemNameHash.insert("game_eventattach_card", Event_AttachCard::newItem);
itemNameHash.insert("game_eventcreate_token", Event_CreateToken::newItem);
diff --git a/common/protocol_items.dat b/common/protocol_items.dat
index f1b18eab0..e07eb6ac2 100644
--- a/common/protocol_items.dat
+++ b/common/protocol_items.dat
@@ -19,6 +19,7 @@
2:roll_die:i,sides
2:draw_cards:i,number
2:move_card:s,start_zone:i,card_id:s,target_zone:i,x:i,y:b,face_down:b,tapped
+2:flip_card:s,zone:i,card_id:b,face_down
2:attach_card:s,start_zone:i,card_id:i,target_player_id:s,target_zone:i,target_card_id
2:create_token:s,zone:s,card_name:s,color:s,pt:s,annotation:b,destroy:i,x:i,y
2:create_arrow:i,start_player_id:s,start_zone:i,start_card_id:i,target_player_id:s,target_zone:i,target_card_id:c,color
@@ -42,6 +43,7 @@
3:shuffle
3:roll_die:i,sides:i,value
3:move_card:i,card_id:s,card_name:s,start_zone:i,position:s,target_zone:i,x:i,y:i,new_card_id:b,face_down
+3:flip_card:s,zone:i,card_id:s,card_name:b,face_down
3:destroy_card:s,zone:i,card_id
3:attach_card:s,start_zone:i,card_id:i,target_player_id:s,target_zone:i,target_card_id
3:create_token:s,zone:i,card_id:s,card_name:s,color:s,pt:s,annotation:b,destroy_on_zone_change:i,x:i,y
diff --git a/common/protocol_items.h b/common/protocol_items.h
index aa0483a28..2d60ec314 100644
--- a/common/protocol_items.h
+++ b/common/protocol_items.h
@@ -179,6 +179,16 @@ public:
static SerializableItem *newItem() { return new Command_MoveCard; }
int getItemId() const { return ItemId_Command_MoveCard; }
};
+class Command_FlipCard : public GameCommand {
+ Q_OBJECT
+public:
+ Command_FlipCard(int _gameId = -1, const QString &_zone = QString(), int _cardId = -1, bool _faceDown = false);
+ QString getZone() const { return static_cast(itemMap.value("zone"))->getData(); };
+ int getCardId() const { return static_cast(itemMap.value("card_id"))->getData(); };
+ bool getFaceDown() const { return static_cast(itemMap.value("face_down"))->getData(); };
+ static SerializableItem *newItem() { return new Command_FlipCard; }
+ int getItemId() const { return ItemId_Command_FlipCard; }
+};
class Command_AttachCard : public GameCommand {
Q_OBJECT
public:
@@ -401,6 +411,17 @@ public:
static SerializableItem *newItem() { return new Event_MoveCard; }
int getItemId() const { return ItemId_Event_MoveCard; }
};
+class Event_FlipCard : public GameEvent {
+ Q_OBJECT
+public:
+ Event_FlipCard(int _playerId = -1, const QString &_zone = QString(), int _cardId = -1, const QString &_cardName = QString(), bool _faceDown = false);
+ QString getZone() const { return static_cast(itemMap.value("zone"))->getData(); };
+ int getCardId() const { return static_cast(itemMap.value("card_id"))->getData(); };
+ QString getCardName() const { return static_cast(itemMap.value("card_name"))->getData(); };
+ bool getFaceDown() const { return static_cast(itemMap.value("face_down"))->getData(); };
+ static SerializableItem *newItem() { return new Event_FlipCard; }
+ int getItemId() const { return ItemId_Event_FlipCard; }
+};
class Event_DestroyCard : public GameEvent {
Q_OBJECT
public:
diff --git a/common/server_protocolhandler.cpp b/common/server_protocolhandler.cpp
index d34a3addb..8974cf410 100644
--- a/common/server_protocolhandler.cpp
+++ b/common/server_protocolhandler.cpp
@@ -92,6 +92,7 @@ ResponseCode Server_ProtocolHandler::processCommandHelper(Command *command, Comm
case ItemId_Command_RollDie: return cmdRollDie(qobject_cast(command), cont, game, player);
case ItemId_Command_DrawCards: return cmdDrawCards(qobject_cast(command), cont, game, player);
case ItemId_Command_MoveCard: return cmdMoveCard(qobject_cast(command), cont, game, player);
+ case ItemId_Command_FlipCard: return cmdFlipCard(qobject_cast(command), cont, game, player);
case ItemId_Command_AttachCard: return cmdAttachCard(qobject_cast(command), cont, game, player);
case ItemId_Command_CreateToken: return cmdCreateToken(qobject_cast(command), cont, game, player);
case ItemId_Command_CreateArrow: return cmdCreateArrow(qobject_cast(command), cont, game, player);
@@ -630,6 +631,35 @@ ResponseCode Server_ProtocolHandler::cmdMoveCard(Command_MoveCard *cmd, CommandC
return moveCard(game, player, cont, cmd->getStartZone(), cmd->getCardId(), cmd->getTargetZone(), cmd->getX(), cmd->getY(), cmd->getFaceDown(), cmd->getTapped());
}
+ResponseCode Server_ProtocolHandler::cmdFlipCard(Command_FlipCard *cmd, CommandContainer *cont, Server_Game *game, Server_Player *player)
+{
+ if (player->getSpectator())
+ return RespFunctionNotAllowed;
+
+ if (!game->getGameStarted())
+ return RespGameNotStarted;
+
+ Server_CardZone *zone = player->getZones().value(cmd->getZone());
+ if (!zone)
+ return RespNameNotFound;
+ if (!zone->hasCoords())
+ return RespContextError;
+
+ Server_Card *card = zone->getCard(cmd->getCardId(), false);
+ if (!card)
+ return RespNameNotFound;
+
+ const bool faceDown = cmd->getFaceDown();
+ if (faceDown == card->getFaceDown())
+ return RespContextError;
+
+ card->setFaceDown(faceDown);
+ cont->enqueueGameEventPrivate(new Event_FlipCard(player->getPlayerId(), zone->getName(), card->getId(), card->getName(), faceDown), game->getGameId());
+ cont->enqueueGameEventPublic(new Event_FlipCard(player->getPlayerId(), zone->getName(), card->getId(), card->getName(), faceDown), game->getGameId());
+
+ return RespOk;
+}
+
void Server_ProtocolHandler::unattachCard(Server_Game *game, Server_Player *player, CommandContainer *cont, Server_Card *card)
{
Server_CardZone *zone = card->getZone();
@@ -824,6 +854,8 @@ ResponseCode Server_ProtocolHandler::setCardAttrHelper(CommandContainer *cont, S
Server_CardZone *zone = player->getZones().value(zoneName);
if (!zone)
return RespNameNotFound;
+ if (!zone->hasCoords())
+ return RespContextError;
if (cardId == -1) {
QListIterator CardIterator(zone->cards);
@@ -858,6 +890,8 @@ ResponseCode Server_ProtocolHandler::cmdSetCardCounter(Command_SetCardCounter *c
Server_CardZone *zone = player->getZones().value(cmd->getZone());
if (!zone)
return RespNameNotFound;
+ if (!zone->hasCoords())
+ return RespContextError;
Server_Card *card = zone->getCard(cmd->getCardId(), false);
if (!card)
@@ -881,6 +915,8 @@ ResponseCode Server_ProtocolHandler::cmdIncCardCounter(Command_IncCardCounter *c
Server_CardZone *zone = player->getZones().value(cmd->getZone());
if (!zone)
return RespNameNotFound;
+ if (!zone->hasCoords())
+ return RespContextError;
Server_Card *card = zone->getCard(cmd->getCardId(), false);
if (!card)
diff --git a/common/server_protocolhandler.h b/common/server_protocolhandler.h
index 725920b0c..637f35038 100644
--- a/common/server_protocolhandler.h
+++ b/common/server_protocolhandler.h
@@ -62,6 +62,7 @@ private:
ResponseCode cmdDrawCards(Command_DrawCards *cmd, CommandContainer *cont, Server_Game *game, Server_Player *player);
ResponseCode moveCard(Server_Game *game, Server_Player *player, CommandContainer *cont, const QString &_startZone, int _cardId, const QString &_targetZone, int _x, int _y, bool _faceDown, bool _tapped);
ResponseCode cmdMoveCard(Command_MoveCard *cmd, CommandContainer *cont, Server_Game *game, Server_Player *player);
+ ResponseCode cmdFlipCard(Command_FlipCard *cmd, CommandContainer *cont, Server_Game *game, Server_Player *player);
void unattachCard(Server_Game *game, Server_Player *player, CommandContainer *cont, Server_Card *card);
ResponseCode cmdAttachCard(Command_AttachCard *cmd, CommandContainer *cont, Server_Game *game, Server_Player *player);
ResponseCode cmdCreateToken(Command_CreateToken *cmd, CommandContainer *cont, Server_Game *game, Server_Player *player);