preliminary AlwaysRevealTopCard support related to issue #31, server code cleanup (finally removed getGameState)

This commit is contained in:
Max-Wilhelm Bruker 2012-03-31 21:47:30 +02:00
parent 75bac4a5b9
commit 7417236c3a
28 changed files with 329 additions and 184 deletions

View file

@ -25,6 +25,7 @@ protected:
bool hasCardAttr;
bool isShufflable;
bool isView;
bool alwaysRevealTopCard;
void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event);
void mousePressEvent(QGraphicsSceneMouseEvent *event);
virtual void addCardImpl(CardItem *card, int x, int y) = 0;
@ -61,6 +62,8 @@ public:
virtual void reorganizeCards() = 0;
virtual QPointF closestGridPoint(const QPointF &point);
bool getIsView() const { return isView; }
bool getAlwaysRevealTopCard() const { return alwaysRevealTopCard; }
void setAlwaysRevealTopCard(bool _alwaysRevealTopCard) { alwaysRevealTopCard = _alwaysRevealTopCard; }
};
#endif

View file

@ -760,6 +760,17 @@ void MessageLogWidget::logRevealCards(Player *player, CardZone *zone, int cardId
}
}
void MessageLogWidget::logAlwaysRevealTopCard(Player *player, CardZone *zone, bool reveal)
{
QString str;
if (reveal)
str = tr("%1 is now keeping the top card %2 revealed.");
else
str = tr("%1 is not revealing the top card %2 any longer.");
appendHtml(str.arg(sanitizeHtml(player->getName())).arg(zone->getTranslatedName(true, CaseGenitive)));
}
void MessageLogWidget::logSetActivePlayer(Player *player)
{
soundEngine->notification();
@ -844,6 +855,7 @@ void MessageLogWidget::connectToPlayer(Player *player)
connect(player, SIGNAL(logDrawCards(Player *, int)), this, SLOT(logDrawCards(Player *, int)));
connect(player, SIGNAL(logUndoDraw(Player *, QString)), this, SLOT(logUndoDraw(Player *, QString)));
connect(player, SIGNAL(logRevealCards(Player *, CardZone *, int, QString, Player *, bool)), this, SLOT(logRevealCards(Player *, CardZone *, int, QString, Player *, bool)));
connect(player, SIGNAL(logAlwaysRevealTopCard(Player *, CardZone *, bool)), this, SLOT(logAlwaysRevealTopCard(Player *, CardZone *, bool)));
}
MessageLogWidget::MessageLogWidget(const QString &_ownName, bool _female, QWidget *parent)

View file

@ -78,6 +78,7 @@ public slots:
void logDumpZone(Player *player, CardZone *zone, int numberCards);
void logStopDumpZone(Player *player, CardZone *zone);
void logRevealCards(Player *player, CardZone *zone, int cardId, QString cardName, Player *otherPlayer, bool faceDown);
void logAlwaysRevealTopCard(Player *player, CardZone *zone, bool reveal);
void logSetActivePlayer(Player *player);
void logSetActivePhase(int phase);
void containerProcessingStarted(const GameEventContext &context);

View file

@ -23,6 +23,7 @@
#include <QMenu>
#include <QDebug>
#include "pb/command_change_zone_properties.pb.h"
#include "pb/command_reveal_cards.pb.h"
#include "pb/command_shuffle.pb.h"
#include "pb/command_attach_card.pb.h"
@ -60,6 +61,7 @@
#include "pb/event_attach_card.pb.h"
#include "pb/event_draw_cards.pb.h"
#include "pb/event_reveal_cards.pb.h"
#include "pb/event_change_zone_properties.pb.h"
PlayerArea::PlayerArea(QGraphicsItem *parentItem)
: QObject(), QGraphicsItem(parentItem)
@ -186,6 +188,9 @@ Player::Player(const ServerInfo_User &info, int _id, bool _local, TabGame *_pare
connect(aViewLibrary, SIGNAL(triggered()), this, SLOT(actViewLibrary()));
aViewTopCards = new QAction(this);
connect(aViewTopCards, SIGNAL(triggered()), this, SLOT(actViewTopCards()));
aAlwaysRevealTopCard = new QAction(this);
aAlwaysRevealTopCard->setCheckable(true);
connect(aAlwaysRevealTopCard, SIGNAL(triggered()), this, SLOT(actAlwaysRevealTopCard()));
}
aViewGraveyard = new QAction(this);
@ -242,6 +247,7 @@ Player::Player(const ServerInfo_User &info, int _id, bool _local, TabGame *_pare
libraryMenu->addSeparator();
playerLists.append(mRevealLibrary = libraryMenu->addMenu(QString()));
playerLists.append(mRevealTopCard = libraryMenu->addMenu(QString()));
libraryMenu->addAction(aAlwaysRevealTopCard);
libraryMenu->addSeparator();
libraryMenu->addAction(aMoveTopCardsToGrave);
libraryMenu->addAction(aMoveTopCardsToExile);
@ -571,6 +577,7 @@ void Player::retranslateUi()
aViewTopCards->setText(tr("View &top cards of library..."));
mRevealLibrary->setTitle(tr("Reveal &library to"));
mRevealTopCard->setTitle(tr("Reveal t&op card to"));
aAlwaysRevealTopCard->setText(tr("&Always reveal top card"));
aViewSideboard->setText(tr("&View sideboard"));
aDrawCard->setText(tr("&Draw card"));
aDrawCards->setText(tr("D&raw cards..."));
@ -731,6 +738,15 @@ void Player::actViewTopCards()
}
}
void Player::actAlwaysRevealTopCard()
{
Command_ChangeZoneProperties cmd;
cmd.set_zone_name("deck");
cmd.set_always_reveal_top_card(aAlwaysRevealTopCard->isChecked());
sendGameCommand(cmd);
}
void Player::actViewGraveyard()
{
static_cast<GameScene *>(scene())->toggleZoneView(this, "grave", -1);
@ -1291,6 +1307,18 @@ void Player::eventRevealCards(const Event_RevealCards &event)
}
}
void Player::eventChangeZoneProperties(const Event_ChangeZoneProperties &event)
{
CardZone *zone = zones.value(QString::fromStdString(event.zone_name()));
if (!zone)
return;
if (event.has_always_reveal_top_card()) {
zone->setAlwaysRevealTopCard(event.always_reveal_top_card());
emit logAlwaysRevealTopCard(this, zone, event.always_reveal_top_card());
}
}
void Player::processGameEvent(GameEvent::GameEventType type, const GameEvent &event, const GameEventContext &context)
{
switch (type) {
@ -1313,6 +1341,7 @@ void Player::processGameEvent(GameEvent::GameEventType type, const GameEvent &ev
case GameEvent::ATTACH_CARD: eventAttachCard(event.GetExtension(Event_AttachCard::ext)); break;
case GameEvent::DRAW_CARDS: eventDrawCards(event.GetExtension(Event_DrawCards::ext)); break;
case GameEvent::REVEAL_CARDS: eventRevealCards(event.GetExtension(Event_RevealCards::ext)); break;
case GameEvent::CHANGE_ZONE_PROPERTIES: eventChangeZoneProperties(event.GetExtension(Event_ChangeZoneProperties::ext)); break;
default: {
qDebug() << "unhandled game event";
}
@ -1363,6 +1392,9 @@ void Player::processPlayerInfo(const ServerInfo_Player &info)
zone->addCard(card, false, cardInfo.x(), cardInfo.y());
}
}
if (zoneInfo.has_always_reveal_top_card())
zone->setAlwaysRevealTopCard(zoneInfo.always_reveal_top_card());
zone->reorganizeCards();
}
@ -1370,10 +1402,6 @@ void Player::processPlayerInfo(const ServerInfo_Player &info)
for (int i = 0; i < counterListSize; ++i)
addCounter(info.counter_list(i));
const int arrowListSize = info.arrow_list_size();
for (int i = 0; i < arrowListSize; ++i)
addArrow(info.arrow_list(i));
setConceded(info.properties().conceded());
}
@ -1399,6 +1427,10 @@ void Player::processCardAttachment(const ServerInfo_Player &info)
}
}
}
const int arrowListSize = info.arrow_list_size();
for (int i = 0; i < arrowListSize; ++i)
addArrow(info.arrow_list(i));
}
void Player::playCard(CardItem *c, bool faceDown, bool tapped)

View file

@ -52,6 +52,7 @@ class Event_DestroyCard;
class Event_AttachCard;
class Event_DrawCards;
class Event_RevealCards;
class Event_ChangeZoneProperties;
class PendingCommand;
class PlayerArea : public QObject, public QGraphicsItem {
@ -98,6 +99,7 @@ signals:
void logDumpZone(Player *player, CardZone *zone, int numberCards);
void logStopDumpZone(Player *player, CardZone *zone);
void logRevealCards(Player *player, CardZone *zone, int cardId, QString cardName, Player *otherPlayer, bool faceDown);
void logAlwaysRevealTopCard(Player *player, CardZone *zone, bool reveal);
void sizeChanged();
void gameConceded();
@ -117,6 +119,7 @@ public slots:
void actViewLibrary();
void actViewTopCards();
void actAlwaysRevealTopCard();
void actViewGraveyard();
void actViewRfg();
void actViewSideboard();
@ -156,7 +159,7 @@ private:
QAction *aMoveHandToTopLibrary, *aMoveHandToBottomLibrary, *aMoveHandToGrave, *aMoveHandToRfg,
*aMoveGraveToTopLibrary, *aMoveGraveToBottomLibrary, *aMoveGraveToHand, *aMoveGraveToRfg,
*aMoveRfgToTopLibrary, *aMoveRfgToBottomLibrary, *aMoveRfgToHand, *aMoveRfgToGrave,
*aViewLibrary, *aViewTopCards, *aMoveTopCardsToGrave, *aMoveTopCardsToExile, *aMoveTopCardToBottom,
*aViewLibrary, *aViewTopCards, *aAlwaysRevealTopCard, *aMoveTopCardsToGrave, *aMoveTopCardsToExile, *aMoveTopCardToBottom,
*aViewGraveyard, *aViewRfg, *aViewSideboard,
*aDrawCard, *aDrawCards, *aUndoDraw, *aMulligan, *aShuffle,
*aUntapAll, *aRollDie, *aCreateToken, *aCreateAnotherToken,
@ -221,6 +224,7 @@ private:
void eventAttachCard(const Event_AttachCard &event);
void eventDrawCards(const Event_DrawCards &event);
void eventRevealCards(const Event_RevealCards &event);
void eventChangeZoneProperties(const Event_ChangeZoneProperties &event);
public:
static const int counterAreaWidth = 55;
enum CardMenuActionType { cmTap, cmUntap, cmDoesntUntap, cmFlip, cmPeek, cmClone, cmMoveToTopLibrary, cmMoveToBottomLibrary, cmMoveToGraveyard, cmMoveToExile };

View file

@ -2,7 +2,6 @@
#include "userlist.h"
#include "userinfobox.h"
#include "abstractclient.h"
#include <QDebug>
#include <QHBoxLayout>
#include <QVBoxLayout>
@ -107,7 +106,6 @@ void TabUserLists::processUserLeftEvent(const Event_UserLeft &event)
void TabUserLists::buddyListReceived(const QList<ServerInfo_User> &_buddyList)
{
qDebug() << "BUDDY LIST" << _buddyList.size();
for (int i = 0; i < _buddyList.size(); ++i)
buddyList->processUserInfo(_buddyList[i], false);
buddyList->sortItems();

View file

@ -9,8 +9,10 @@ SET(common_SOURCES
rng_sfmt.cpp
server.cpp
server_abstractuserinterface.cpp
server_arrow.cpp
server_card.cpp
server_cardzone.cpp
server_counter.cpp
server_game.cpp
server_player.cpp
server_protocolhandler.cpp

View file

@ -5,6 +5,7 @@ SET(PROTO_FILES
card_attributes.proto
color.proto
command_attach_card.proto
command_change_zone_properties.proto
command_concede.proto
command_create_arrow.proto
command_create_counter.proto
@ -56,6 +57,7 @@ SET(PROTO_FILES
context_undo_draw.proto
event_add_to_list.proto
event_attach_card.proto
event_change_zone_properties.proto
event_connection_closed.proto
event_create_arrow.proto
event_create_counter.proto

View file

@ -0,0 +1,10 @@
import "game_commands.proto";
message Command_ChangeZoneProperties {
extend GameCommand {
optional Command_ChangeZoneProperties ext = 1031;
}
optional string zone_name = 1;
optional bool always_reveal_top_card = 10;
}

View file

@ -0,0 +1,10 @@
import "game_event.proto";
message Event_ChangeZoneProperties {
extend GameEvent {
optional Event_ChangeZoneProperties ext = 2020;
}
optional string zone_name = 1;
optional bool always_reveal_top_card = 10;
}

View file

@ -31,6 +31,7 @@ message GameCommand {
SET_SIDEBOARD_PLAN = 1028;
DECK_SELECT = 1029;
SET_SIDEBOARD_LOCK = 1030;
CHANGE_ZONE_PROPERTIES = 1031;
}
extensions 100 to max;
}

View file

@ -28,6 +28,7 @@ message GameEvent {
SET_ACTIVE_PHASE = 2017;
DUMP_ZONE = 2018;
STOP_DUMP_ZONE = 2019;
CHANGE_ZONE_PROPERTIES = 2020;
}
optional sint32 player_id = 1 [default = -1];
extensions 100 to max;

View file

@ -20,4 +20,5 @@ message ServerInfo_Zone {
optional bool with_coords = 3;
optional sint32 card_count = 4;
repeated ServerInfo_Card card_list = 5;
optional bool always_reveal_top_card = 10;
}

View file

@ -19,6 +19,7 @@
***************************************************************************/
#include "server.h"
#include "server_game.h"
#include "server_player.h"
#include "server_counter.h"
#include "server_room.h"
#include "server_protocolhandler.h"
@ -358,7 +359,7 @@ void Server::externalGameCommandContainerReceived(const CommandContainer &cont,
}
QMutexLocker gameLocker(&game->gameMutex);
Server_Player *player = game->getPlayer(playerId);
Server_Player *player = game->getPlayers().value(playerId);
if (!player) {
qDebug() << "externalGameCommandContainerReceived: player id=" << playerId << "not found";
throw Response::RespNotInRoom;

View file

@ -8,6 +8,7 @@
#include "server.h"
#include "server_room.h"
#include "server_game.h"
#include "server_player.h"
#include "pb/event_game_joined.pb.h"
#include "pb/event_game_state_changed.pb.h"
#include <google/protobuf/descriptor.h>

30
common/server_arrow.cpp Normal file
View file

@ -0,0 +1,30 @@
#include "server_arrow.h"
#include "server_player.h"
#include "server_card.h"
#include "server_cardzone.h"
#include "pb/serverinfo_arrow.pb.h"
Server_Arrow::Server_Arrow(int _id, Server_Card *_startCard, Server_ArrowTarget *_targetItem, const color &_arrowColor)
: id(_id),
startCard(_startCard),
targetItem(_targetItem),
arrowColor(_arrowColor)
{
}
void Server_Arrow::getInfo(ServerInfo_Arrow *info)
{
info->set_id(id);
info->set_start_player_id(startCard->getZone()->getPlayer()->getPlayerId());
info->set_start_zone(startCard->getZone()->getName().toStdString());
info->set_start_card_id(startCard->getId());
info->mutable_arrow_color()->CopyFrom(arrowColor);
Server_Card *targetCard = qobject_cast<Server_Card *>(targetItem);
if (targetCard) {
info->set_target_player_id(targetCard->getZone()->getPlayer()->getPlayerId());
info->set_target_zone(targetCard->getZone()->getName().toStdString());
info->set_target_card_id(targetCard->getId());
} else
info->set_target_player_id(static_cast<Server_Player *>(targetItem)->getPlayerId());
}

View file

@ -5,6 +5,7 @@
class Server_Card;
class Server_ArrowTarget;
class ServerInfo_Arrow;
class Server_Arrow {
private:
@ -13,12 +14,13 @@ private:
Server_ArrowTarget *targetItem;
color arrowColor;
public:
Server_Arrow(int _id, Server_Card *_startCard, Server_ArrowTarget *_targetItem, const color &_arrowColor)
: id(_id), startCard(_startCard), targetItem(_targetItem), arrowColor(_arrowColor) { }
Server_Arrow(int _id, Server_Card *_startCard, Server_ArrowTarget *_targetItem, const color &_arrowColor);
int getId() const { return id; }
Server_Card *getStartCard() const { return startCard; }
Server_ArrowTarget *getTargetItem() const { return targetItem; }
const color &getColor() const { return arrowColor; }
void getInfo(ServerInfo_Arrow *info);
};
#endif

View file

@ -18,6 +18,9 @@
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#include "server_card.h"
#include "server_cardzone.h"
#include "server_player.h"
#include "pb/serverinfo_card.pb.h"
Server_Card::Server_Card(QString _name, int _id, int _coord_x, int _coord_y, Server_CardZone *_zone)
: zone(_zone), id(_id), coord_x(_coord_x), coord_y(_coord_y), name(_name), tapped(false), attacking(false), facedown(false), color(QString()), power(-1), toughness(-1), annotation(QString()), destroyOnZoneChange(false), doesntUntap(false), parentCard(0)
@ -115,3 +118,43 @@ void Server_Card::setParentCard(Server_Card *_parentCard)
if (parentCard)
parentCard->addAttachedCard(this);
}
void Server_Card::getInfo(ServerInfo_Card *info)
{
QString displayedName = facedown ? QString() : name;
info->set_id(id);
info->set_name(displayedName.toStdString());
info->set_x(coord_x);
info->set_y(coord_y);
if (facedown)
info->set_face_down(true);
info->set_tapped(tapped);
if (attacking)
info->set_attacking(true);
if (!color.isEmpty())
info->set_color(color.toStdString());
const QString ptStr = getPT();
if (!ptStr.isEmpty())
info->set_pt(ptStr.toStdString());
if (!annotation.isEmpty())
info->set_annotation(annotation.toStdString());
if (destroyOnZoneChange)
info->set_destroy_on_zone_change(true);
if (doesntUntap)
info->set_doesnt_untap(true);
QMapIterator<int, int> cardCounterIterator(counters);
while (cardCounterIterator.hasNext()) {
cardCounterIterator.next();
ServerInfo_CardCounter *counterInfo = info->add_counter_list();
counterInfo->set_id(cardCounterIterator.key());
counterInfo->set_value(cardCounterIterator.value());
}
if (parentCard) {
info->set_attach_player_id(parentCard->getZone()->getPlayer()->getPlayerId());
info->set_attach_zone(parentCard->getZone()->getName().toStdString());
info->set_attach_card_id(parentCard->getId());
}
}

View file

@ -26,6 +26,7 @@
#include <QMap>
class Server_CardZone;
class ServerInfo_Card;
class Server_Card : public Server_ArrowTarget {
Q_OBJECT
@ -88,6 +89,8 @@ public:
void resetState();
QString setAttribute(CardAttribute attribute, const QString &avalue, bool allCards);
void getInfo(ServerInfo_Card *info);
};
#endif

View file

@ -23,11 +23,15 @@
#include "rng_abstract.h"
#include <QSet>
#include <QDebug>
#include "server_game.h"
#include "pb/command_move_card.pb.h"
Server_CardZone::Server_CardZone(Server_Player *_player, const QString &_name, bool _has_coords, ServerInfo_Zone::ZoneType _type)
: player(_player), name(_name), has_coords(_has_coords), type(_type), cardsBeingLookedAt(0)
: player(_player),
name(_name),
has_coords(_has_coords),
type(_type),
cardsBeingLookedAt(0),
alwaysRevealTopCard(false)
{
}
@ -215,3 +219,20 @@ void Server_CardZone::addWritePermission(int playerId)
{
playersWithWritePermission.insert(playerId);
}
void Server_CardZone::getInfo(ServerInfo_Zone *info, Server_Player *playerWhosAsking, bool omniscient)
{
info->set_name(name.toStdString());
info->set_type(type);
info->set_with_coords(has_coords);
info->set_card_count(cards.size());
info->set_always_reveal_top_card(alwaysRevealTopCard);
if (
(((playerWhosAsking == player) || omniscient) && (type != ServerInfo_Zone::HiddenZone))
|| ((playerWhosAsking != player) && (type == ServerInfo_Zone::PublicZone))
) {
QListIterator<Server_Card *> cardIterator(cards);
while (cardIterator.hasNext())
cardIterator.next()->getInfo(info->add_card_list());
}
}

View file

@ -39,6 +39,7 @@ private:
ServerInfo_Zone::ZoneType type;
int cardsBeingLookedAt;
QSet<int> playersWithWritePermission;
bool alwaysRevealTopCard;
public:
Server_CardZone(Server_Player *_player, const QString &_name, bool _has_coords, ServerInfo_Zone::ZoneType _type);
~Server_CardZone();
@ -52,6 +53,7 @@ public:
ServerInfo_Zone::ZoneType getType() const { return type; }
QString getName() const { return name; }
Server_Player *getPlayer() const { return player; }
void getInfo(ServerInfo_Zone *info, Server_Player *playerWhosAsking, bool omniscient);
int getFreeGridColumn(int x, int y, const QString &cardName) const;
bool isColumnEmpty(int x, int y) const;
@ -64,6 +66,8 @@ public:
void clear();
void addWritePermission(int playerId);
const QSet<int> &getPlayersWithWritePermission() const { return playersWithWritePermission; }
bool getAlwaysRevealTopCard() const { return alwaysRevealTopCard; }
void setAlwaysRevealTopCard(bool _alwaysRevealTopCard) { alwaysRevealTopCard = _alwaysRevealTopCard; }
};
#endif

20
common/server_counter.cpp Normal file
View file

@ -0,0 +1,20 @@
#include "server_counter.h"
#include "pb/serverinfo_counter.pb.h"
Server_Counter::Server_Counter(int _id, const QString &_name, const color &_counterColor, int _radius, int _count)
: id(_id),
name(_name),
counterColor(_counterColor),
radius(_radius),
count(_count)
{
}
void Server_Counter::getInfo(ServerInfo_Counter *info)
{
info->set_id(id);
info->set_name(name.toStdString());
info->mutable_counter_color()->CopyFrom(counterColor);
info->set_radius(radius);
info->set_count(count);
}

View file

@ -23,6 +23,8 @@
#include <QString>
#include "pb/color.pb.h"
class ServerInfo_Counter;
class Server_Counter {
protected:
int id;
@ -31,7 +33,7 @@ protected:
int radius;
int count;
public:
Server_Counter(int _id, const QString &_name, const color &_counterColor, int _radius, int _count = 0) : id(_id), name(_name), counterColor(_counterColor), radius(_radius), count(_count) { }
Server_Counter(int _id, const QString &_name, const color &_counterColor, int _radius, int _count = 0);
~Server_Counter() { }
int getId() const { return id; }
QString getName() const { return name; }
@ -39,6 +41,8 @@ public:
int getRadius() const { return radius; }
int getCount() const { return count; }
void setCount(int _count) { count = _count; }
void getInfo(ServerInfo_Counter *info);
};
#endif

View file

@ -20,11 +20,11 @@
#include "server.h"
#include "server_room.h"
#include "server_game.h"
#include "server_player.h"
#include "server_protocolhandler.h"
#include "server_arrow.h"
#include "server_card.h"
#include "server_cardzone.h"
#include "server_counter.h"
#include "decklist.h"
#include "pb/context_connection_state_changed.pb.h"
#include "pb/context_ping_changed.pb.h"
@ -186,23 +186,26 @@ int Server_Game::getSpectatorCount() const
return result;
}
void Server_Game::createGameStateChangedEvent(Event_GameStateChanged *event, Server_Player *playerWhosAsking, bool omniscient, bool withUserInfo)
{
event->set_seconds_elapsed(secondsElapsed);
if (gameStarted) {
event->set_game_started(true);
event->set_active_player_id(0);
event->set_active_phase(0);
} else
event->set_game_started(false);
QMapIterator<int, Server_Player *> playerIterator(players);
while (playerIterator.hasNext())
playerIterator.next().value()->getInfo(event->add_player_list(), playerWhosAsking, omniscient, withUserInfo);
}
void Server_Game::sendGameStateToPlayers()
{
// Prepare game state information that everyone can see
Event_GameStateChanged gameStateChangedEvent;
gameStateChangedEvent.set_seconds_elapsed(secondsElapsed);
if (gameStarted) {
gameStateChangedEvent.set_game_started(true);
gameStateChangedEvent.set_active_player_id(0);
gameStateChangedEvent.set_active_phase(0);
} else
gameStateChangedEvent.set_game_started(false);
// game state information for replay and omniscient spectators
Event_GameStateChanged omniscientEvent(gameStateChangedEvent);
QListIterator<ServerInfo_Player> omniscientGameStateIterator(getGameState(0, true));
while (omniscientGameStateIterator.hasNext())
omniscientEvent.add_player_list()->CopyFrom(omniscientGameStateIterator.next());
Event_GameStateChanged omniscientEvent;
createGameStateChangedEvent(&omniscientEvent, 0, true, false);
GameEventContainer *replayCont = prepareGameEvent(omniscientEvent, -1);
replayCont->set_seconds_elapsed(secondsElapsed - startTimeOfThisGame);
@ -210,14 +213,13 @@ void Server_Game::sendGameStateToPlayers()
currentReplay->add_event_list()->CopyFrom(*replayCont);
delete replayCont;
// If spectators are not omniscient, we need an additional getGameState call, otherwise we can use the data we used for the replay.
// All spectators are equal, so we don't need to make a getGameState call for each one.
Event_GameStateChanged spectatorEvent(spectatorsSeeEverything ? omniscientEvent : gameStateChangedEvent);
if (!spectatorsSeeEverything) {
QListIterator<ServerInfo_Player> spectatorGameStateIterator(getGameState(0, false));
while (spectatorGameStateIterator.hasNext())
spectatorEvent.add_player_list()->CopyFrom(spectatorGameStateIterator.next());
}
// If spectators are not omniscient, we need an additional createGameStateChangedEvent call, otherwise we can use the data we used for the replay.
// All spectators are equal, so we don't need to make a createGameStateChangedEvent call for each one.
Event_GameStateChanged spectatorEvent;
if (spectatorsSeeEverything)
spectatorEvent = omniscientEvent;
else
createGameStateChangedEvent(&spectatorEvent, 0, false, false);
// send game state info to clients according to their role in the game
QMapIterator<int, Server_Player *> playerIterator(players);
@ -227,10 +229,8 @@ void Server_Game::sendGameStateToPlayers()
if (player->getSpectator())
gec = prepareGameEvent(spectatorEvent, -1);
else {
Event_GameStateChanged event(gameStateChangedEvent);
QListIterator<ServerInfo_Player> gameStateIterator(getGameState(player));
while (gameStateIterator.hasNext())
event.add_player_list()->CopyFrom(gameStateIterator.next());
Event_GameStateChanged event;
createGameStateChangedEvent(&event, player, false, false);
gec = prepareGameEvent(event, -1);
}
@ -274,9 +274,7 @@ void Server_Game::doStartGameIfReady()
getInfo(*currentReplay->mutable_game_info());
Event_GameStateChanged omniscientEvent;
QListIterator<ServerInfo_Player> omniscientGameStateIterator(getGameState(0, true, true));
while (omniscientGameStateIterator.hasNext())
omniscientEvent.add_player_list()->CopyFrom(omniscientGameStateIterator.next());
createGameStateChangedEvent(&omniscientEvent, 0, true, true);
GameEventContainer *replayCont = prepareGameEvent(omniscientEvent, -1);
replayCont->set_seconds_elapsed(0);
@ -577,113 +575,6 @@ void Server_Game::nextTurn()
setActivePlayer(keys[listPos]);
}
QList<ServerInfo_Player> Server_Game::getGameState(Server_Player *playerWhosAsking, bool omniscient, bool withUserInfo) const
{
QMutexLocker locker(&gameMutex);
QList<ServerInfo_Player> result;
QMapIterator<int, Server_Player *> playerIterator(players);
while (playerIterator.hasNext()) {
Server_Player *player = playerIterator.next().value();
ServerInfo_Player playerInfo;
playerInfo.mutable_properties()->CopyFrom(player->getProperties(withUserInfo));
if (player == playerWhosAsking)
if (player->getDeck())
playerInfo.set_deck_list(player->getDeck()->writeToString_Native().toStdString());
QList<ServerInfo_Arrow *> arrowList;
QMapIterator<int, Server_Arrow *> arrowIterator(player->getArrows());
while (arrowIterator.hasNext()) {
Server_Arrow *arrow = arrowIterator.next().value();
Server_Card *targetCard = qobject_cast<Server_Card *>(arrow->getTargetItem());
ServerInfo_Arrow *arrowInfo = playerInfo.add_arrow_list();
arrowInfo->set_id(arrow->getId());
arrowInfo->set_start_player_id(arrow->getStartCard()->getZone()->getPlayer()->getPlayerId());
arrowInfo->set_start_zone(arrow->getStartCard()->getZone()->getName().toStdString());
arrowInfo->set_start_card_id(arrow->getStartCard()->getId());
arrowInfo->mutable_arrow_color()->CopyFrom(arrow->getColor());
if (targetCard) {
arrowInfo->set_target_player_id(targetCard->getZone()->getPlayer()->getPlayerId());
arrowInfo->set_target_zone(targetCard->getZone()->getName().toStdString());
arrowInfo->set_target_card_id(targetCard->getId());
} else
arrowInfo->set_target_player_id(qobject_cast<Server_Player *>(arrow->getTargetItem())->getPlayerId());
}
QMapIterator<int, Server_Counter *> counterIterator(player->getCounters());
while (counterIterator.hasNext()) {
Server_Counter *counter = counterIterator.next().value();
ServerInfo_Counter *counterInfo = playerInfo.add_counter_list();
counterInfo->set_id(counter->getId());
counterInfo->set_name(counter->getName().toStdString());
counterInfo->mutable_counter_color()->CopyFrom(counter->getColor());
counterInfo->set_radius(counter->getRadius());
counterInfo->set_count(counter->getCount());
}
QList<ServerInfo_Zone *> zoneList;
QMapIterator<QString, Server_CardZone *> zoneIterator(player->getZones());
while (zoneIterator.hasNext()) {
Server_CardZone *zone = zoneIterator.next().value();
ServerInfo_Zone *zoneInfo = playerInfo.add_zone_list();
zoneInfo->set_name(zone->getName().toStdString());
zoneInfo->set_type(zone->getType());
zoneInfo->set_with_coords(zone->hasCoords());
zoneInfo->set_card_count(zone->cards.size());
if (
(((playerWhosAsking == player) || omniscient) && (zone->getType() != ServerInfo_Zone::HiddenZone))
|| ((playerWhosAsking != player) && (zone->getType() == ServerInfo_Zone::PublicZone))
) {
QListIterator<Server_Card *> cardIterator(zone->cards);
while (cardIterator.hasNext()) {
Server_Card *card = cardIterator.next();
ServerInfo_Card *cardInfo = zoneInfo->add_card_list();
QString displayedName = card->getFaceDown() ? QString() : card->getName();
cardInfo->set_id(card->getId());
cardInfo->set_name(displayedName.toStdString());
cardInfo->set_x(card->getX());
cardInfo->set_y(card->getY());
if (card->getFaceDown())
cardInfo->set_face_down(true);
cardInfo->set_tapped(card->getTapped());
if (card->getAttacking())
cardInfo->set_attacking(true);
if (!card->getColor().isEmpty())
cardInfo->set_color(card->getColor().toStdString());
if (!card->getPT().isEmpty())
cardInfo->set_pt(card->getPT().toStdString());
if (!card->getAnnotation().isEmpty())
cardInfo->set_annotation(card->getAnnotation().toStdString());
if (card->getDestroyOnZoneChange())
cardInfo->set_destroy_on_zone_change(true);
if (card->getDoesntUntap())
cardInfo->set_doesnt_untap(true);
QList<ServerInfo_CardCounter *> cardCounterList;
QMapIterator<int, int> cardCounterIterator(card->getCounters());
while (cardCounterIterator.hasNext()) {
cardCounterIterator.next();
ServerInfo_CardCounter *counterInfo = cardInfo->add_counter_list();
counterInfo->set_id(cardCounterIterator.key());
counterInfo->set_value(cardCounterIterator.value());
}
if (card->getParentCard()) {
cardInfo->set_attach_player_id(card->getParentCard()->getZone()->getPlayer()->getPlayerId());
cardInfo->set_attach_zone(card->getParentCard()->getZone()->getName().toStdString());
cardInfo->set_attach_card_id(card->getParentCard()->getId());
}
}
}
}
result.append(playerInfo);
}
return result;
}
void Server_Game::createGameJoinedEvent(Server_Player *player, ResponseContainer &rc, bool resuming)
{
Event_GameJoined event1;
@ -703,13 +594,15 @@ void Server_Game::createGameJoinedEvent(Server_Player *player, ResponseContainer
rc.enqueuePostResponseItem(ServerMessage::SESSION_EVENT, Server_AbstractUserInterface::prepareSessionEvent(event1));
Event_GameStateChanged event2;
QListIterator<ServerInfo_Player> gameStateIterator(getGameState(player, player->getSpectator() && spectatorsSeeEverything, true));
while (gameStateIterator.hasNext())
event2.add_player_list()->CopyFrom(gameStateIterator.next());
event2.set_seconds_elapsed(secondsElapsed);
event2.set_game_started(gameStarted);
event2.set_active_player_id(activePlayer);
event2.set_active_phase(activePhase);
QMapIterator<int, Server_Player *> playerIterator(players);
while (playerIterator.hasNext())
playerIterator.next().value()->getInfo(event2.add_player_list(), player, player->getSpectator() && spectatorsSeeEverything, true);
rc.enqueuePostResponseItem(ServerMessage::GAME_EVENT_CONTAINER, prepareGameEvent(event2, -1));
}

View file

@ -21,22 +21,26 @@
#define SERVERGAME_H
#include <QStringList>
#include <QPointer>
#include <QObject>
#include <QMutex>
#include <QSet>
#include <QDateTime>
#include "server_player.h"
#include <QMap>
#include "server_response_containers.h"
#include "pb/response.pb.h"
#include "pb/serverinfo_player.pb.h"
//#include "pb/serverinfo_player.pb.h"
#include "pb/serverinfo_game.pb.h"
class QTimer;
class GameEventContainer;
class GameReplay;
class Server_Room;
class Server_Player;
class ServerInfo_User;
class ServerInfo_Player;
class ServerInfo_Game;
class Server_AbstractUserInterface;
class Event_GameStateChanged;
class Server_Game : public QObject {
Q_OBJECT
@ -66,6 +70,9 @@ private:
QTimer *pingClock;
QList<GameReplay *> replayList;
GameReplay *currentReplay;
void createGameStateChangedEvent(Event_GameStateChanged *event, Server_Player *playerWhosAsking, bool omniscient, bool withUserInfo);
void sendGameStateToPlayers();
signals:
void sigStartGameIfReady();
void gameInfoChanged(ServerInfo_Game gameInfo);
@ -84,7 +91,6 @@ public:
int getPlayerCount() const;
int getSpectatorCount() const;
const QMap<int, Server_Player *> &getPlayers() const { return players; }
Server_Player *getPlayer(int playerId) const { return players.value(playerId, 0); }
int getGameId() const { return gameId; }
QString getDescription() const { return description; }
QString getPassword() const { return password; }
@ -110,8 +116,6 @@ public:
int getSecondsElapsed() const { return secondsElapsed; }
void createGameJoinedEvent(Server_Player *player, ResponseContainer &rc, bool resuming);
void sendGameStateToPlayers();
QList<ServerInfo_Player> getGameState(Server_Player *playerWhosAsking, bool omniscient = false, bool withUserInfo = false) const;
GameEventContainer *prepareGameEvent(const ::google::protobuf::Message &gameEvent, int playerId, GameEventContext *context = 0);
GameEventContext prepareGameEventContext(const ::google::protobuf::Message &gameEventContext);

View file

@ -16,6 +16,7 @@
#include "pb/response_deck_download.pb.h"
#include "pb/response_dump_zone.pb.h"
#include "pb/command_attach_card.pb.h"
#include "pb/command_change_zone_properties.pb.h"
#include "pb/command_concede.pb.h"
#include "pb/command_create_arrow.pb.h"
#include "pb/command_create_counter.pb.h"
@ -47,7 +48,9 @@
#include "pb/command_stop_dump_zone.pb.h"
#include "pb/command_undo_draw.pb.h"
#include "pb/serverinfo_user.pb.h"
#include "pb/serverinfo_player.pb.h"
#include "pb/event_attach_card.pb.h"
#include "pb/event_change_zone_properties.pb.h"
#include "pb/event_create_arrow.pb.h"
#include "pb/event_create_counter.pb.h"
#include "pb/event_create_token.pb.h"
@ -330,21 +333,6 @@ Response::ResponseCode Server_Player::drawCards(GameEventStorage &ges, int numbe
return Response::RespOk;
}
Response::ResponseCode Server_Player::undoDraw(GameEventStorage &ges)
{
QMutexLocker locker(&game->gameMutex);
if (lastDrawList.isEmpty())
return Response::RespContextError;
Response::ResponseCode retVal;
CardToMove *cardToMove = new CardToMove;
cardToMove->set_card_id(lastDrawList.takeLast());
retVal = moveCard(ges, zones.value("hand"), QList<const CardToMove *>() << cardToMove, zones.value("deck"), 0, 0, false, true);
delete cardToMove;
return retVal;
}
class Server_Player::MoveCardCompareFunctor {
private:
int x;
@ -863,7 +851,16 @@ Response::ResponseCode Server_Player::cmdUndoDraw(const Command_UndoDraw & /*cmd
if (conceded)
return Response::RespContextError;
return undoDraw(ges);
if (lastDrawList.isEmpty())
return Response::RespContextError;
Response::ResponseCode retVal;
CardToMove *cardToMove = new CardToMove;
cardToMove->set_card_id(lastDrawList.takeLast());
retVal = moveCard(ges, zones.value("hand"), QList<const CardToMove *>() << cardToMove, zones.value("deck"), 0, 0, false, true);
delete cardToMove;
return retVal;
}
Response::ResponseCode Server_Player::cmdMoveCard(const Command_MoveCard &cmd, ResponseContainer & /*rc*/, GameEventStorage &ges)
@ -963,7 +960,7 @@ Response::ResponseCode Server_Player::cmdAttachCard(const Command_AttachCard &cm
Server_Card *targetCard = 0;
if (cmd.has_target_player_id()) {
targetPlayer = game->getPlayer(cmd.target_player_id());
targetPlayer = game->getPlayers().value(cmd.target_player_id());
if (!targetPlayer)
return Response::RespNameNotFound;
} else if (!card->getParentCard())
@ -1094,8 +1091,8 @@ Response::ResponseCode Server_Player::cmdCreateArrow(const Command_CreateArrow &
if (conceded)
return Response::RespContextError;
Server_Player *startPlayer = game->getPlayer(cmd.start_player_id());
Server_Player *targetPlayer = game->getPlayer(cmd.target_player_id());
Server_Player *startPlayer = game->getPlayers().value(cmd.start_player_id());
Server_Player *targetPlayer = game->getPlayers().value(cmd.target_player_id());
if (!startPlayer || !targetPlayer)
return Response::RespNameNotFound;
QString startZoneName = QString::fromStdString(cmd.start_zone());
@ -1383,7 +1380,7 @@ Response::ResponseCode Server_Player::cmdDumpZone(const Command_DumpZone &cmd, R
if (!game->getGameStarted())
return Response::RespGameNotStarted;
Server_Player *otherPlayer = game->getPlayer(cmd.player_id());
Server_Player *otherPlayer = game->getPlayers().value(cmd.player_id());
if (!otherPlayer)
return Response::RespNameNotFound;
Server_CardZone *zone = otherPlayer->getZones().value(QString::fromStdString(cmd.zone_name()));
@ -1456,7 +1453,7 @@ Response::ResponseCode Server_Player::cmdStopDumpZone(const Command_StopDumpZone
if (conceded)
return Response::RespContextError;
Server_Player *otherPlayer = game->getPlayer(cmd.player_id());
Server_Player *otherPlayer = game->getPlayers().value(cmd.player_id());
if (!otherPlayer)
return Response::RespNameNotFound;
Server_CardZone *zone = otherPlayer->getZones().value(QString::fromStdString(cmd.zone_name()));
@ -1486,7 +1483,7 @@ Response::ResponseCode Server_Player::cmdRevealCards(const Command_RevealCards &
Server_Player *otherPlayer = 0;
if (cmd.has_player_id()) {
otherPlayer = game->getPlayer(cmd.player_id());
otherPlayer = game->getPlayers().value(cmd.player_id());
if (!otherPlayer)
return Response::RespNameNotFound;
}
@ -1569,6 +1566,26 @@ Response::ResponseCode Server_Player::cmdRevealCards(const Command_RevealCards &
return Response::RespOk;
}
Response::ResponseCode Server_Player::cmdChangeZoneProperties(const Command_ChangeZoneProperties &cmd, ResponseContainer &rc, GameEventStorage &ges)
{
Server_CardZone *zone = zones.value(QString::fromStdString(cmd.zone_name()));
if (!zone)
return Response::RespNameNotFound;
Event_ChangeZoneProperties event;
event.set_zone_name(cmd.zone_name());
if (cmd.has_always_reveal_top_card()) {
if (zone->getAlwaysRevealTopCard() == cmd.always_reveal_top_card())
return Response::RespContextError;
zone->setAlwaysRevealTopCard(cmd.always_reveal_top_card());
event.set_always_reveal_top_card(cmd.always_reveal_top_card());
ges.enqueueGameEvent(event, playerId);
} else
return Response::RespContextError;
}
Response::ResponseCode Server_Player::processGameCommand(const GameCommand &command, ResponseContainer &rc, GameEventStorage &ges)
{
switch ((GameCommand::GameCommandType) getPbExtension(command)) {
@ -1603,6 +1620,7 @@ Response::ResponseCode Server_Player::processGameCommand(const GameCommand &comm
case GameCommand::SET_SIDEBOARD_PLAN: return cmdSetSideboardPlan(command.GetExtension(Command_SetSideboardPlan::ext), rc, ges); break;
case GameCommand::DECK_SELECT: return cmdDeckSelect(command.GetExtension(Command_DeckSelect::ext), rc, ges); break;
case GameCommand::SET_SIDEBOARD_LOCK: return cmdSetSideboardLock(command.GetExtension(Command_SetSideboardLock::ext), rc, ges); break;
case GameCommand::CHANGE_ZONE_PROPERTIES: return cmdChangeZoneProperties(command.GetExtension(Command_ChangeZoneProperties::ext), rc, ges); break;
default: return Response::RespInvalidCommand;
}
}
@ -1639,3 +1657,23 @@ void Server_Player::disconnectClient()
else
setUserInterface(0);
}
void Server_Player::getInfo(ServerInfo_Player *info, Server_Player *playerWhosAsking, bool omniscient, bool withUserInfo)
{
info->mutable_properties()->CopyFrom(getProperties(withUserInfo));
if (playerWhosAsking == this)
if (deck)
info->set_deck_list(deck->writeToString_Native().toStdString());
QMapIterator<int, Server_Arrow *> arrowIterator(arrows);
while (arrowIterator.hasNext())
arrowIterator.next().value()->getInfo(info->add_arrow_list());
QMapIterator<int, Server_Counter *> counterIterator(counters);
while (counterIterator.hasNext())
counterIterator.next().value()->getInfo(info->add_counter_list());
QMapIterator<QString, Server_CardZone *> zoneIterator(zones);
while (zoneIterator.hasNext())
zoneIterator.next().value()->getInfo(info->add_zone_list(), playerWhosAsking, omniscient);
}

View file

@ -18,6 +18,7 @@ class Server_Arrow;
class Server_Card;
class Server_AbstractUserInterface;
class ServerInfo_User;
class ServerInfo_Player;
class ServerInfo_PlayerProperties;
class CommandContainer;
class CardToMove;
@ -57,6 +58,7 @@ class Command_MoveCard;
class Command_SetSideboardPlan;
class Command_DeckSelect;
class Command_SetSideboardLock;
class Command_ChangeZoneProperties;
class Server_Player : public Server_ArrowTarget {
Q_OBJECT
@ -118,7 +120,6 @@ public:
void setupZones();
Response::ResponseCode drawCards(GameEventStorage &ges, int number);
Response::ResponseCode undoDraw(GameEventStorage &ges);
Response::ResponseCode moveCard(GameEventStorage &ges, Server_CardZone *startzone, const QList<const CardToMove *> &_cards, Server_CardZone *targetzone, int x, int y, bool fixFreeSpaces = true, bool undoingDraw = false);
void unattachCard(GameEventStorage &ges, Server_Card *card);
Response::ResponseCode setCardAttrHelper(GameEventStorage &ges, const QString &zone, int cardId, CardAttribute attribute, const QString &attrValue);
@ -154,9 +155,12 @@ public:
Response::ResponseCode cmdDumpZone(const Command_DumpZone &cmd, ResponseContainer &rc, GameEventStorage &ges);
Response::ResponseCode cmdStopDumpZone(const Command_StopDumpZone &cmd, ResponseContainer &rc, GameEventStorage &ges);
Response::ResponseCode cmdRevealCards(const Command_RevealCards &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);
void sendGameEvent(const GameEventContainer &event);
void getInfo(ServerInfo_Player *info, Server_Player *playerWhosAsking, bool omniscient, bool withUserInfo);
};
#endif

View file

@ -70,7 +70,7 @@ void Server_ProtocolHandler::prepareDestroy()
continue;
}
g->gameMutex.lock();
Server_Player *p = g->getPlayer(gameIterator.value().second);
Server_Player *p = g->getPlayers().value(gameIterator.value().second);
if (!p) {
g->gameMutex.unlock();
r->gamesMutex.unlock();
@ -220,7 +220,7 @@ Response::ResponseCode Server_ProtocolHandler::processGameCommandContainer(const
}
QMutexLocker gameLocker(&game->gameMutex);
Server_Player *player = game->getPlayer(roomIdAndPlayerId.second);
Server_Player *player = game->getPlayers().value(roomIdAndPlayerId.second);
if (!player)
return Response::RespNotInRoom;