From 62a9003d3e5bdc4ba2d0113df4667b5703babd89 Mon Sep 17 00:00:00 2001 From: Max-Wilhelm Bruker Date: Fri, 18 Jun 2010 19:57:06 +0200 Subject: [PATCH] server has to assign free table space for a new card so that there is no race condition --- cockatrice/src/carditem.cpp | 2 +- cockatrice/src/player.cpp | 2 +- cockatrice/src/tablezone.cpp | 73 ++++++++++--------------------- cockatrice/src/tablezone.h | 10 ++--- common/server_cardzone.cpp | 20 +++++++++ common/server_cardzone.h | 1 + common/server_protocolhandler.cpp | 23 +++++++--- 7 files changed, 69 insertions(+), 62 deletions(-) diff --git a/cockatrice/src/carditem.cpp b/cockatrice/src/carditem.cpp index 41e6a385..99a4cd6d 100644 --- a/cockatrice/src/carditem.cpp +++ b/cockatrice/src/carditem.cpp @@ -209,7 +209,7 @@ void CardItem::playCard(QGraphicsSceneMouseEvent *event) bool tapped = info->getCipt(); TableZone *table = zone->getPlayer()->getTable(); - QPoint gridPoint = table->getFreeGridPoint(info->getTableRow()); + QPoint gridPoint = QPoint(-1, 3 - info->getTableRow()); table->handleDropEventByGrid(id, zone, gridPoint, faceDown, tapped); } } diff --git a/cockatrice/src/player.cpp b/cockatrice/src/player.cpp index f914b8ba..86c6f8ec 100644 --- a/cockatrice/src/player.cpp +++ b/cockatrice/src/player.cpp @@ -493,7 +493,7 @@ void Player::actCreateToken() { QString cardname = QInputDialog::getText(0, tr("Create token"), tr("Name:")); if (!cardname.isEmpty()) - sendGameCommand(new Command_CreateToken(-1, "table", cardname, QString(), 0, 0)); + sendGameCommand(new Command_CreateToken(-1, "table", cardname, QString(), -1, 0)); } void Player::actSayMessage() diff --git a/cockatrice/src/tablezone.cpp b/cockatrice/src/tablezone.cpp index 41b1b6c7..cba76b07 100644 --- a/cockatrice/src/tablezone.cpp +++ b/cockatrice/src/tablezone.cpp @@ -13,10 +13,10 @@ TableZone::TableZone(Player *_p, QGraphicsItem *parent) updateBgPixmap(); if (settingsCache->getEconomicGrid()) - height = (int) (14.0 / 3 * CARD_HEIGHT + 3 * paddingY); + height = 2 * boxLineWidth + (int) (14.0 / 3 * CARD_HEIGHT + 3 * paddingY); else - height = 4 * CARD_HEIGHT + 3 * paddingY; - width = minWidth + 2 * marginX; + height = 2 * boxLineWidth + 4 * CARD_HEIGHT + 3 * paddingY; + width = minWidth + 2 * marginX + 2 * boxLineWidth; currentMinimumWidth = minWidth; setCacheMode(DeviceCoordinateCache); @@ -55,17 +55,17 @@ void TableZone::paint(QPainter *painter, const QStyleOptionGraphicsItem */*optio grad1.setCoordinateMode(QGradient::ObjectBoundingMode); grad1.setColorAt(0, color1); grad1.setColorAt(1, color2); - painter->fillRect(QRectF(0, 0, width, 10), QBrush(grad1)); + painter->fillRect(QRectF(0, 0, width, boxLineWidth), QBrush(grad1)); grad1.setFinalStop(1, 0); - painter->fillRect(QRectF(0, 0, 10, height), QBrush(grad1)); + painter->fillRect(QRectF(0, 0, boxLineWidth, height), QBrush(grad1)); grad1.setStart(0, 1); grad1.setFinalStop(0, 0); - painter->fillRect(QRectF(0, height - 10, width, 10), QBrush(grad1)); + painter->fillRect(QRectF(0, height - boxLineWidth, width, boxLineWidth), QBrush(grad1)); grad1.setStart(1, 0); - painter->fillRect(QRectF(width - 10, 0, 10, height), QBrush(grad1)); + painter->fillRect(QRectF(width - boxLineWidth, 0, boxLineWidth, height), QBrush(grad1)); } } @@ -141,7 +141,7 @@ void TableZone::resizeToContents() xMax += 2 * CARD_WIDTH; if (xMax < minWidth) xMax = minWidth; - currentMinimumWidth = xMax + 2 * marginX; + currentMinimumWidth = xMax + 2 * marginX + 2 * boxLineWidth; if (currentMinimumWidth > width) { prepareGeometryChange(); width = currentMinimumWidth; @@ -159,28 +159,22 @@ CardItem *TableZone::getCardFromGrid(const QPoint &gridPoint) const QPointF TableZone::mapFromGrid(const QPoint &gridPoint) const { - if (gridPoint.y() == 3) { - if (settingsCache->getEconomicGrid()) - return QPointF( - 20 + (CARD_WIDTH * gridPoint.x() + CARD_WIDTH * (gridPoint.x() / 3)) / 2, - (CARD_HEIGHT + paddingY) * gridPoint.y() + (gridPoint.x() % 3 * CARD_HEIGHT) / 3 - ); - else - return QPointF( - 20 + 3 * CARD_WIDTH * gridPoint.x() / 2, - (CARD_HEIGHT + paddingY) * gridPoint.y() - ); - } else + if ((gridPoint.y() == 3) && (settingsCache->getEconomicGrid())) return QPointF( - 20 + CARD_WIDTH * gridPoint.x() / 2, - (CARD_HEIGHT + paddingY) * gridPoint.y() + marginX + (CARD_WIDTH * gridPoint.x() + CARD_WIDTH * (gridPoint.x() / 3)) / 2, + boxLineWidth + (CARD_HEIGHT + paddingY) * gridPoint.y() + (gridPoint.x() % 3 * CARD_HEIGHT) / 3 + ); + else + return QPointF( + marginX + 3 * CARD_WIDTH * gridPoint.x() / 2, + boxLineWidth + (CARD_HEIGHT + paddingY) * gridPoint.y() ); } QPoint TableZone::mapToGrid(const QPointF &mapPoint) const { qreal x = mapPoint.x() - marginX; - qreal y = mapPoint.y() + paddingY / 2; + qreal y = mapPoint.y() + paddingY / 2 - boxLineWidth; if (x < 0) x = 0; else if (x > width - CARD_WIDTH - marginX) @@ -191,36 +185,17 @@ QPoint TableZone::mapToGrid(const QPointF &mapPoint) const y = height - CARD_HEIGHT; QPoint result = QPoint( - (int) (x * 2 / CARD_WIDTH), + (int) (x / (1.5 * CARD_WIDTH)), (int) (y / (CARD_HEIGHT + paddingY)) ); - if (result.y() == 3) { - if (settingsCache->getEconomicGrid()) - return QPoint( - (int) (x * 2 / CARD_WIDTH - floor(x / (2 * CARD_WIDTH))), - 3 - ); - else - return QPoint( - (int) (x / (1.5 * CARD_WIDTH)), - 3 - ); - } else - return result; -} - -QPoint TableZone::getFreeGridPoint(int row) const -{ - int x = 0; - int y = 3 - row; - if (y == 3) - while (getCardFromGrid(QPoint(x, y))) - ++x; + if ((result.y() == 3) && (settingsCache->getEconomicGrid())) + return QPoint( + (int) (x * 2 / CARD_WIDTH - floor(x / (2 * CARD_WIDTH))), + 3 + ); else - while (((x >= 2) && getCardFromGrid(QPoint(x - 2, y))) || ((x >= 1) && getCardFromGrid(QPoint(x - 1, y))) || getCardFromGrid(QPoint(x, y)) || getCardFromGrid(QPoint(x + 1, y)) || getCardFromGrid(QPoint(x + 2, y))) - ++x; - return QPoint(x, y); + return result; } QPointF TableZone::closestGridPoint(const QPointF &point) diff --git a/cockatrice/src/tablezone.h b/cockatrice/src/tablezone.h index b528cafb..215d5f80 100644 --- a/cockatrice/src/tablezone.h +++ b/cockatrice/src/tablezone.h @@ -8,6 +8,11 @@ class TableZone : public CardZone { signals: void sizeChanged(); private: + static const int boxLineWidth = 10; + static const int paddingY = 20; + static const int marginX = 20; + static const int minWidth = 20 * CARD_WIDTH / 2; + int width, height; int currentMinimumWidth; QPixmap bgPixmap; @@ -17,10 +22,6 @@ private slots: public slots: void reorganizeCards(); public: - static const int paddingY = 20; - static const int marginX = 20; - static const int minWidth = 20 * CARD_WIDTH / 2; - TableZone(Player *_p, QGraphicsItem *parent = 0); QRectF boundingRect() const; void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); @@ -30,7 +31,6 @@ public: CardItem *getCardFromGrid(const QPoint &gridPoint) const; QPointF mapFromGrid(const QPoint &gridPoint) const; QPoint mapToGrid(const QPointF &mapPoint) const; - QPoint getFreeGridPoint(int row) const; QPointF closestGridPoint(const QPointF &point); CardItem *takeCard(int position, int cardId, const QString &cardName, bool canResize = true); void resizeToContents(); diff --git a/common/server_cardzone.cpp b/common/server_cardzone.cpp index 2913256e..07a56c15 100644 --- a/common/server_cardzone.cpp +++ b/common/server_cardzone.cpp @@ -73,6 +73,26 @@ Server_Card *Server_CardZone::getCard(int id, bool remove, int *position) } } +int Server_CardZone::getFreeGridColumn(int y) const +{ + int x = 0; + + // Stupid algorithm. For large numbers of cards, it would be more + // efficient to sort the cards by their x value and only need to iterate once. + bool occupied; + do { + occupied = false; + for (int i = 0; i < cards.size(); ++i) + if ((cards[i]->getY() == y) && (cards[i]->getX() == x)) { + occupied = true; + ++x; + break; + } + } while (occupied); + + return x; +} + void Server_CardZone::insertCard(Server_Card *card, int x, int y) { if (hasCoords()) { diff --git a/common/server_cardzone.h b/common/server_cardzone.h index cda335d7..fa35a728 100644 --- a/common/server_cardzone.h +++ b/common/server_cardzone.h @@ -47,6 +47,7 @@ public: QString getName() const { return name; } Server_Player *getPlayer() const { return player; } + int getFreeGridColumn(int y) const; QList cards; void insertCard(Server_Card *card, int x, int y); void shuffle(); diff --git a/common/server_protocolhandler.cpp b/common/server_protocolhandler.cpp index 742cdda3..2fb08dcc 100644 --- a/common/server_protocolhandler.cpp +++ b/common/server_protocolhandler.cpp @@ -515,10 +515,12 @@ ResponseCode Server_ProtocolHandler::moveCard(Server_Game *game, Server_Player * Server_Card *card = startzone->getCard(_cardId, true, &position); if (!card) return RespNameNotFound; - if (x == -1) - x = targetzone->cards.size(); - if (!targetzone->hasCoords()) + if (!targetzone->hasCoords()) { y = 0; + if (x == -1) + x = targetzone->cards.size(); + } else if (x == -1) + x = targetzone->getFreeGridColumn(y); targetzone->insertCard(card, x, y); @@ -612,9 +614,18 @@ ResponseCode Server_ProtocolHandler::cmdCreateToken(Command_CreateToken *cmd, Co if (!zone) return RespNameNotFound; - Server_Card *card = new Server_Card(cmd->getCardName(), player->newCardId(), cmd->getX(), cmd->getY()); - zone->insertCard(card, cmd->getX(), cmd->getY()); - game->sendGameEvent(new Event_CreateToken(player->getPlayerId(), zone->getName(), card->getId(), card->getName(), cmd->getPt(), cmd->getX(), cmd->getY())); + int x = cmd->getX(); + int y = cmd->getY(); + if (zone->hasCoords() && (x == -1)) + x = zone->getFreeGridColumn(y); + if (x < 0) + x = 0; + if (y < 0) + y = 0; + + Server_Card *card = new Server_Card(cmd->getCardName(), player->newCardId(), x, y); + zone->insertCard(card, x, y); + game->sendGameEvent(new Event_CreateToken(player->getPlayerId(), zone->getName(), card->getId(), card->getName(), cmd->getPt(), x, y)); return RespOk; }