From 9e044ffad01afd64fb038ec6494a79eb68b533ab Mon Sep 17 00:00:00 2001 From: Max-Wilhelm Bruker Date: Tue, 30 Jun 2009 20:50:16 +0200 Subject: [PATCH 1/3] more intuitive tapping behaviour --- cockatrice/src/game.cpp | 8 +++++--- cockatrice/src/game.h | 5 +++-- cockatrice/src/player.cpp | 5 +++-- cockatrice/src/player.h | 3 ++- cockatrice/src/tablezone.cpp | 14 ++++++++++---- 5 files changed, 23 insertions(+), 12 deletions(-) diff --git a/cockatrice/src/game.cpp b/cockatrice/src/game.cpp index 437e02e13..25686862c 100644 --- a/cockatrice/src/game.cpp +++ b/cockatrice/src/game.cpp @@ -144,7 +144,7 @@ void Game::initSayMenu() Player *Game::addPlayer(int playerId, const QString &playerName, QPointF base, bool local) { - Player *newPlayer = new Player(playerName, playerId, base, local, db, client, scene); + Player *newPlayer = new Player(playerName, playerId, base, local, db, client, scene, this); connect(newPlayer, SIGNAL(hoverCard(QString)), this, SIGNAL(hoverCard(QString))); connect(newPlayer, SIGNAL(sigShowCardMenu(QPoint)), this, SLOT(showCardMenu(QPoint))); @@ -346,7 +346,8 @@ void Game::actTap() QListIterator i(scene->selectedItems()); while (i.hasNext()) { CardItem *temp = (CardItem *) i.next(); - client->setCardAttr(qgraphicsitem_cast(temp->parentItem())->getName(), temp->getId(), "tapped", "1"); + if (!temp->getTapped()) + client->setCardAttr(qgraphicsitem_cast(temp->parentItem())->getName(), temp->getId(), "tapped", "1"); } } @@ -355,7 +356,8 @@ void Game::actUntap() QListIterator i(scene->selectedItems()); while (i.hasNext()) { CardItem *temp = (CardItem *) i.next(); - client->setCardAttr(qgraphicsitem_cast(temp->parentItem())->getName(), temp->getId(), "tapped", "0"); + if (temp->getTapped()) + client->setCardAttr(qgraphicsitem_cast(temp->parentItem())->getName(), temp->getId(), "tapped", "0"); } } diff --git a/cockatrice/src/game.h b/cockatrice/src/game.h index 66d675bde..f244d15d0 100644 --- a/cockatrice/src/game.h +++ b/cockatrice/src/game.h @@ -40,8 +40,6 @@ private slots: void actEditMessages(); void showCardMenu(QPoint p); - void actTap(); - void actUntap(); void actDoesntUntap(); void actFlip(); void actAddCounter(); @@ -54,6 +52,9 @@ private slots: void gameEvent(const ServerEventData &msg); void playerListReceived(QList playerList); void readyStart(); +public slots: + void actTap(); + void actUntap(); signals: void submitDecklist(); void hoverCard(QString name); diff --git a/cockatrice/src/player.cpp b/cockatrice/src/player.cpp index 8cd365bd9..d7aa4eda8 100644 --- a/cockatrice/src/player.cpp +++ b/cockatrice/src/player.cpp @@ -4,11 +4,12 @@ #include "playerarea.h" #include "counter.h" #include "zoneviewzone.h" +#include "game.h" #include #include -Player::Player(const QString &_name, int _id, QPointF _base, bool _local, CardDatabase *_db, Client *_client, QGraphicsScene *_scene) - : QObject(), defaultNumberTopCards(3), name(_name), id(_id), base(_base), local(_local), db(_db), client(_client) +Player::Player(const QString &_name, int _id, QPointF _base, bool _local, CardDatabase *_db, Client *_client, QGraphicsScene *_scene, Game *_parent) + : QObject(_parent), defaultNumberTopCards(3), name(_name), id(_id), base(_base), local(_local), db(_db), client(_client) { area = new PlayerArea(this); area->setPos(_base); diff --git a/cockatrice/src/player.h b/cockatrice/src/player.h index 77029fab8..760ccf1b6 100644 --- a/cockatrice/src/player.h +++ b/cockatrice/src/player.h @@ -12,6 +12,7 @@ class QMenu; class QAction; class PlayerArea; class ZoneViewZone; +class Game; class Player : public QObject { Q_OBJECT @@ -57,7 +58,7 @@ public: PlayerArea *area; Client *client; void addZone(CardZone *z); - Player(const QString &_name, int _id, QPointF _base, bool _local, CardDatabase *_db, Client *_client, QGraphicsScene *_scene); + Player(const QString &_name, int _id, QPointF _base, bool _local, CardDatabase *_db, Client *_client, QGraphicsScene *_scene, Game *_parent); ~Player(); QMenu *getPlayerMenu() const { return playerMenu; } int getId() const { return id; } diff --git a/cockatrice/src/tablezone.cpp b/cockatrice/src/tablezone.cpp index 99d549a7e..49f5636af 100644 --- a/cockatrice/src/tablezone.cpp +++ b/cockatrice/src/tablezone.cpp @@ -55,9 +55,15 @@ void TableZone::reorganizeCards() void TableZone::toggleTapped() { - QListIterator i(scene()->selectedItems()); - while (i.hasNext()) { - CardItem *temp = (CardItem *) i.next(); - setCardAttr(temp->getId(), "tapped", temp->getTapped() ? "0" : "1"); + QList selectedItems = scene()->selectedItems(); + bool tapAll = false; + for (int i = 0; i < selectedItems.size(); i++) + if (!qgraphicsitem_cast(selectedItems[i])->getTapped()) { + tapAll = true; + break; + } + for (int i = 0; i < selectedItems.size(); i++) { + CardItem *temp = qgraphicsitem_cast(selectedItems[i]); + setCardAttr(temp->getId(), "tapped", (!temp->getTapped() || tapAll) ? "1" : "0"); } } From 47eadb6f86ae3b7fb0fe78618d07b2014f462be5 Mon Sep 17 00:00:00 2001 From: Max-Wilhelm Bruker Date: Tue, 30 Jun 2009 23:26:10 +0200 Subject: [PATCH 2/3] started protocol documentation --- cockatrice/doc/protocol.txt | 110 +++++++++++++++++++++++++++++++ servatrice/src/returnmessage.cpp | 1 - servatrice/src/returnmessage.h | 2 +- 3 files changed, 111 insertions(+), 2 deletions(-) create mode 100644 cockatrice/doc/protocol.txt diff --git a/cockatrice/doc/protocol.txt b/cockatrice/doc/protocol.txt new file mode 100644 index 000000000..639437c02 --- /dev/null +++ b/cockatrice/doc/protocol.txt @@ -0,0 +1,110 @@ +1. Abstract + +The Cockatrice protocol is a client/server protocol intended for communication between +a card game client and a suitable server. It is designed with the goal in mind to make +playing card games, such as Magic the Gathering, over a network easy while eliminating +the possibility of unfair play. Because of that, the server stores all hidden information +and transmits pieces of it to clients only when necessary. + +2. Protocol structure + +All communication is done over a TCP/IP connection. The protocol is text based. +Strings are encoded in UTF-8 and have UNIX-style line endings (\n). + +There are four distinct types of messages: + - Command (section 3) + - Response (section 4) + - Event (section 5) + - List (section 6) + +3. Commands + +A command can only be sent from client to server and has the following structure: + {ID}|{command}|{parameter1}|{parameter2}... +"ID" is an arbitrary number to be chosen uniquely for each command. +"command" is a command identifier (see section 3). +It depends on the command identifier what has to be passed as parameters. + +3.1 ping + +Flags: + none +Parameters: + none +Valid response codes: + ok + +No effect. + +3.2 login + +Flags: + none +Parameters: + User name (string) + Password (string) +Valid response codes: + ok + password + +If the supplied credentials are correct, "ok" is returned and the connection state +is set to authenticated. (The server is not required to actually check the validity +of the credentials.) +Otherwise, "password" is returned. + +3.3 list_games + +Flags: + login needed +Parameters: + none +Valid response codes: + ok + +If the connection state is unauthenticated, "login_needed" is returned. +Otherwise, "ok" is returned and for each game currently, a list_games event XXX is +sent to the client. The "accepts game list changes" flag of the connection is set. + +3.4 create_game +3.5 join_game +3.6 leave_game +3.7 list_players +3.8 say +3.9 submit_deck +3.10 ready_start +3.11 shuffle +3.12 draw_cards +3.13 reveal_card +3.14 move_card +3.15 create_token +3.16 set_card_attr +3.17 inc_counter +3.18 add_counter +3.19 set_counter +3.20 del_counter +3.21 list_counters +3.22 list_zones +3.23 dump_zone +3.24 roll_dice +3.25 set_active_player +3.26 set_active_phase + +4. Responses + +After processing any command, the server sends a response to the client, indicating +whether the command was understood and valid. +A response can only be sent from server to client and has the following structure: + resp|{ID}|{resp-code} + +{ID} is the identifier belonging to the command in question. +{resp-code} contains information about the processing of the command. It can have the +following values: + ok (Success) + login_needed (Error: Command requires login) + syntax (Error: Invalid command or parameters) + context (Error: Command cannot be applied here) + password (Error: Wrong login data) + +The response code "syntax" is valid as a response to any command and is +hence not explicitly listed in section 3. The response code "login_needed" applies +to all commands with the "login needed" flag. \ No newline at end of file diff --git a/servatrice/src/returnmessage.cpp b/servatrice/src/returnmessage.cpp index 6fb9a84a3..a88e1ce9c 100644 --- a/servatrice/src/returnmessage.cpp +++ b/servatrice/src/returnmessage.cpp @@ -15,7 +15,6 @@ bool ReturnMessage::send(ReturnCode code) case ReturnSyntaxError: returnCodeString = "syntax"; break; case ReturnContextError: returnCodeString = "context"; break; case ReturnPasswordWrong: returnCodeString = "password"; break; - case ReturnNameNotFound: returnCodeString = "name_not_found"; break; } s->msg(QString("resp|%1|%2|%3").arg(msg_id) .arg(success ? "ok" : "err") diff --git a/servatrice/src/returnmessage.h b/servatrice/src/returnmessage.h index 2eaed90ce..37837bca5 100644 --- a/servatrice/src/returnmessage.h +++ b/servatrice/src/returnmessage.h @@ -9,7 +9,7 @@ private: unsigned int msg_id; QString cmd; public: - enum ReturnCode { ReturnNothing, ReturnOk, ReturnLoginNeeded, ReturnSyntaxError, ReturnContextError, ReturnPasswordWrong, ReturnNameNotFound }; + enum ReturnCode { ReturnNothing, ReturnOk, ReturnLoginNeeded, ReturnSyntaxError, ReturnContextError, ReturnPasswordWrong }; ReturnMessage(QObject *parent = 0) : QObject(parent), msg_id(0) { } unsigned int getMsgId() const { return msg_id; } void setMsgId(unsigned int _msg_id) { msg_id = _msg_id; } From c3fb56581d45d4d088fda01bb382ef808c0a6c97 Mon Sep 17 00:00:00 2001 From: Max-Wilhelm Bruker Date: Wed, 1 Jul 2009 01:05:52 +0200 Subject: [PATCH 3/3] small changes --- cockatrice/src/carditem.cpp | 16 ++++++++-------- cockatrice/src/cardlist.cpp | 1 + cockatrice/src/cardlist.h | 3 ++- cockatrice/src/cardzone.cpp | 7 +++---- cockatrice/src/cardzone.h | 1 + cockatrice/src/counter.cpp | 2 +- cockatrice/src/handzone.cpp | 2 +- cockatrice/src/libraryzone.cpp | 2 +- cockatrice/src/pilezone.cpp | 3 ++- cockatrice/src/tablezone.cpp | 2 +- cockatrice/src/zoneviewlayout.cpp | 1 - cockatrice/src/zoneviewzone.cpp | 5 ++--- 12 files changed, 23 insertions(+), 22 deletions(-) diff --git a/cockatrice/src/carditem.cpp b/cockatrice/src/carditem.cpp index c9411d6ee..bdb2c3b5b 100644 --- a/cockatrice/src/carditem.cpp +++ b/cockatrice/src/carditem.cpp @@ -70,7 +70,7 @@ void CardItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, void CardItem::setName(const QString &_name) { name = _name; - update(boundingRect()); + update(); } void CardItem::setTapped(bool _tapped) @@ -80,31 +80,31 @@ void CardItem::setTapped(bool _tapped) setTransform(QTransform().translate((float) CARD_WIDTH / 2, (float) CARD_HEIGHT / 2).rotate(90).translate((float) -CARD_WIDTH / 2, (float) -CARD_HEIGHT / 2)); else setTransform(QTransform()); - update(boundingRect()); + update(); } void CardItem::setAttacking(bool _attacking) { attacking = _attacking; - update(boundingRect()); + update(); } void CardItem::setFaceDown(bool _facedown) { facedown = _facedown; - update(boundingRect()); + update(); } void CardItem::setCounters(int _counters) { counters = _counters; - update(boundingRect()); + update(); } void CardItem::setAnnotation(const QString &_annotation) { annotation = _annotation; - update(boundingRect()); + update(); } void CardItem::setDoesntUntap(bool _doesntUntap) @@ -120,7 +120,7 @@ void CardItem::resetState() annotation = QString(); setTapped(false); setDoesntUntap(false); - update(boundingRect()); + update(); } CardDragItem *CardItem::createDragItem(int _id, const QPointF &_pos, const QPointF &_scenePos, bool faceDown) @@ -215,7 +215,7 @@ QVariant CardItem::itemChange(QGraphicsItem::GraphicsItemChange change, const QV return value; } else if (change == ItemSelectedHasChanged) { qDebug("selection changed"); - update(boundingRect()); + update(); return value; } else return QGraphicsItem::itemChange(change, value); diff --git a/cockatrice/src/cardlist.cpp b/cockatrice/src/cardlist.cpp index 99e9544b5..1b2bb4399 100644 --- a/cockatrice/src/cardlist.cpp +++ b/cockatrice/src/cardlist.cpp @@ -1,4 +1,5 @@ #include "cardlist.h" +#include "carditem.h" CardList::CardList(bool _contentsKnown) : QList(), contentsKnown(_contentsKnown) diff --git a/cockatrice/src/cardlist.h b/cockatrice/src/cardlist.h index 06a30b608..f37076c85 100644 --- a/cockatrice/src/cardlist.h +++ b/cockatrice/src/cardlist.h @@ -1,9 +1,10 @@ #ifndef CARDLIST_H #define CARDLIST_H -#include "carditem.h" #include +class CardItem; + class CardList : public QList { protected: bool contentsKnown; diff --git a/cockatrice/src/cardzone.cpp b/cockatrice/src/cardzone.cpp index b49e76a99..699e3ba8d 100644 --- a/cockatrice/src/cardzone.cpp +++ b/cockatrice/src/cardzone.cpp @@ -6,7 +6,7 @@ #include "zoneviewzone.h" CardZone::CardZone(Player *_p, const QString &_name, bool _hasCardAttr, bool _isShufflable, QGraphicsItem *parent, bool isView) - : AbstractGraphicsItem(parent), player(_p), name(_name), cards(NULL), view(NULL), menu(NULL), hasCardAttr(_hasCardAttr), isShufflable(_isShufflable) + : AbstractGraphicsItem(parent), player(_p), name(_name), cards(NULL), view(NULL), menu(NULL), doubleClickAction(0), hasCardAttr(_hasCardAttr), isShufflable(_isShufflable) { if (!isView) player->addZone(this); @@ -27,7 +27,7 @@ void CardZone::clearContents() cards->clear(); } -void CardZone::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event) +void CardZone::mouseDoubleClickEvent(QGraphicsSceneMouseEvent */*event*/) { if (doubleClickAction) doubleClickAction->trigger(); @@ -71,8 +71,7 @@ CardItem *CardZone::getCard(int cardId, const QString &cardName) CardItem *CardZone::takeCard(int position, int cardId, const QString &cardName) { - if (position >= cards->size()) - return NULL; + Q_ASSERT(position < cards->size()); CardItem *c = cards->takeAt(position); diff --git a/cockatrice/src/cardzone.h b/cockatrice/src/cardzone.h index f81aee8ad..9f06c0140 100644 --- a/cockatrice/src/cardzone.h +++ b/cockatrice/src/cardzone.h @@ -3,6 +3,7 @@ #include #include "cardlist.h" +#include "carditem.h" #include "abstractgraphicsitem.h" class Player; diff --git a/cockatrice/src/counter.cpp b/cockatrice/src/counter.cpp index 6ca53f425..a628f11e8 100644 --- a/cockatrice/src/counter.cpp +++ b/cockatrice/src/counter.cpp @@ -26,7 +26,7 @@ void Counter::paint(QPainter *painter, const QStyleOptionGraphicsItem */*option* void Counter::setValue(int _value) { value = _value; - update(boundingRect()); + update(); } void Counter::mousePressEvent(QGraphicsSceneMouseEvent *event) diff --git a/cockatrice/src/handzone.cpp b/cockatrice/src/handzone.cpp index 89a9529a4..6d83358c9 100644 --- a/cockatrice/src/handzone.cpp +++ b/cockatrice/src/handzone.cpp @@ -59,7 +59,7 @@ void HandZone::addCardImpl(CardItem *card, int x, int /*y*/) card->setParentItem(this); card->resetState(); card->setVisible(true); - card->update(card->boundingRect()); + card->update(); } void HandZone::handleDropEvent(int cardId, CardZone *startZone, const QPoint &/*dropPoint*/, bool /*faceDown*/) diff --git a/cockatrice/src/libraryzone.cpp b/cockatrice/src/libraryzone.cpp index 487b3a97b..86aa9eb86 100644 --- a/cockatrice/src/libraryzone.cpp +++ b/cockatrice/src/libraryzone.cpp @@ -50,7 +50,7 @@ void LibraryZone::handleDropEvent(int cardId, CardZone *startZone, const QPoint void LibraryZone::reorganizeCards() { - update(boundingRect()); + update(); } void LibraryZone::mousePressEvent(QGraphicsSceneMouseEvent *event) diff --git a/cockatrice/src/pilezone.cpp b/cockatrice/src/pilezone.cpp index 649c6472d..9adbd5332 100644 --- a/cockatrice/src/pilezone.cpp +++ b/cockatrice/src/pilezone.cpp @@ -20,6 +20,7 @@ QRectF PileZone::boundingRect() const void PileZone::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { + qDebug("PileZone::paint"); if (!cards->isEmpty()) { painter->save(); cards->at(0)->paint(painter, option, widget); @@ -47,7 +48,7 @@ void PileZone::handleDropEvent(int cardId, CardZone *startZone, const QPoint &/* void PileZone::reorganizeCards() { qDebug(QString("PileZone: reorganize, x=%1, y=%2, w=%3, h=%4").arg(boundingRect().x()).arg(boundingRect().y()).arg(boundingRect().width()).arg(boundingRect().height()).toLatin1()); - update(boundingRect()); + update(); } void PileZone::mousePressEvent(QGraphicsSceneMouseEvent *event) diff --git a/cockatrice/src/tablezone.cpp b/cockatrice/src/tablezone.cpp index 49f5636af..38bbb6b4c 100644 --- a/cockatrice/src/tablezone.cpp +++ b/cockatrice/src/tablezone.cpp @@ -31,7 +31,7 @@ void TableZone::addCardImpl(CardItem *card, int x, int y) qDebug(QString("table: appended %1 at pos %2: zValue = %3, x = %4, y = %5").arg(card->getName()).arg(cards->size() - 1).arg(card->zValue()).arg(x).arg(y).toLatin1()); card->setParentItem(this); card->setVisible(true); - card->update(card->boundingRect()); + card->update(); } void TableZone::handleDropEvent(int cardId, CardZone *startZone, const QPoint &dropPoint, bool faceDown) diff --git a/cockatrice/src/zoneviewlayout.cpp b/cockatrice/src/zoneviewlayout.cpp index 4db8fb295..08db31b98 100644 --- a/cockatrice/src/zoneviewlayout.cpp +++ b/cockatrice/src/zoneviewlayout.cpp @@ -52,7 +52,6 @@ void ZoneViewLayout::removeItem(ZoneViewWidget *item) { qDebug("ZoneViewLayout::removeItem"); views.removeAt(views.indexOf(item)); - scene()->removeItem(item); reorganize(); } diff --git a/cockatrice/src/zoneviewzone.cpp b/cockatrice/src/zoneviewzone.cpp index b685d95c4..bf4228e35 100644 --- a/cockatrice/src/zoneviewzone.cpp +++ b/cockatrice/src/zoneviewzone.cpp @@ -75,7 +75,7 @@ void ZoneViewZone::addCardImpl(CardItem *card, int x, int /*y*/) { cards->insert(x, card); card->setParentItem(this); - card->update(card->boundingRect()); + card->update(); } void ZoneViewZone::handleDropEvent(int cardId, CardZone *startZone, const QPoint &/*dropPoint*/, bool /*faceDown*/) @@ -89,8 +89,7 @@ void ZoneViewZone::removeCard(int position) if (position >= cards->size()) return; - CardItem *card = cards->at(position); - cards->removeAt(position); + CardItem *card = cards->takeAt(position); delete card; reorganizeCards(); }