mirror of
https://github.com/Cockatrice/Cockatrice.git
synced 2026-06-11 00:24:47 -07:00
added deck hashing
This commit is contained in:
parent
963e8f0d90
commit
0bb4ef8bb8
31 changed files with 4867 additions and 4831 deletions
|
|
@ -3,6 +3,7 @@
|
|||
#include <QXmlStreamReader>
|
||||
#include <QXmlStreamWriter>
|
||||
#include <QVariant>
|
||||
#include <QCryptographicHash>
|
||||
#include "decklist.h"
|
||||
|
||||
MoveCardToZone::MoveCardToZone(const QString &_cardName, const QString &_startZone, const QString &_targetZone)
|
||||
|
|
@ -263,6 +264,7 @@ DeckList::DeckList(DeckList *other)
|
|||
newMoveList.append(new MoveCardToZone(oldMoveList[i]));
|
||||
sideboardPlans.insert(spIterator.key(), new SideboardPlan(spIterator.key(), newMoveList));
|
||||
}
|
||||
updateDeckHash();
|
||||
}
|
||||
|
||||
DeckList::~DeckList()
|
||||
|
|
@ -453,8 +455,10 @@ bool DeckList::loadFromFile(const QString &fileName, FileFormat fmt)
|
|||
case PlainTextFormat: result = loadFromFile_Plain(&file); break;
|
||||
case CockatriceFormat: result = loadFromFile_Native(&file); break;
|
||||
}
|
||||
if (result)
|
||||
if (result) {
|
||||
updateDeckHash();
|
||||
emit deckLoaded();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
@ -486,6 +490,7 @@ void DeckList::cleanList()
|
|||
root->clearTree();
|
||||
setName();
|
||||
setComments();
|
||||
updateDeckHash();
|
||||
}
|
||||
|
||||
void DeckList::getCardListHelper(InnerDecklistNode *item, QSet<QString> &result) const
|
||||
|
|
@ -512,28 +517,55 @@ DecklistCardNode *DeckList::addCard(const QString &cardName, const QString &zone
|
|||
if (!zoneNode)
|
||||
zoneNode = new InnerDecklistNode(zoneName, root);
|
||||
|
||||
return new DecklistCardNode(cardName, 1, zoneNode);
|
||||
DecklistCardNode *node = new DecklistCardNode(cardName, 1, zoneNode);
|
||||
updateDeckHash();
|
||||
return node;
|
||||
}
|
||||
|
||||
bool DeckList::deleteNode(AbstractDecklistNode *node, InnerDecklistNode *rootNode)
|
||||
{
|
||||
if (node == root)
|
||||
return true;
|
||||
if (!rootNode)
|
||||
bool updateHash = false;
|
||||
if (!rootNode) {
|
||||
rootNode = root;
|
||||
updateHash = true;
|
||||
}
|
||||
|
||||
int index = rootNode->indexOf(node);
|
||||
if (index != -1) {
|
||||
delete rootNode->takeAt(index);
|
||||
if (!rootNode->size())
|
||||
deleteNode(rootNode, rootNode->getParent());
|
||||
if (updateHash)
|
||||
updateDeckHash();
|
||||
return true;
|
||||
}
|
||||
for (int i = 0; i < rootNode->size(); i++) {
|
||||
InnerDecklistNode *inner = dynamic_cast<InnerDecklistNode *>(rootNode->at(i));
|
||||
if (inner)
|
||||
if (deleteNode(node, inner))
|
||||
if (deleteNode(node, inner)) {
|
||||
if (updateHash)
|
||||
updateDeckHash();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void DeckList::updateDeckHash()
|
||||
{
|
||||
QStringList cardList;
|
||||
for (int i = 0; i < root->size(); i++) {
|
||||
InnerDecklistNode *node = dynamic_cast<InnerDecklistNode *>(root->at(i));
|
||||
for (int j = 0; j < node->size(); j++) {
|
||||
DecklistCardNode *card = dynamic_cast<DecklistCardNode *>(node->at(j));
|
||||
for (int k = 0; k < card->getNumber(); ++k)
|
||||
cardList.append((node->getName() == "side" ? "SB:" : "") + card->getName().toLower());
|
||||
}
|
||||
}
|
||||
cardList.sort();
|
||||
deckHash = QCryptographicHash::hash(cardList.join(";").toUtf8(), QCryptographicHash::Sha1).toBase64().left(10);
|
||||
|
||||
emit deckHashChanged();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -118,6 +118,7 @@ public:
|
|||
private:
|
||||
QString name, comments;
|
||||
QString lastFileName;
|
||||
QString deckHash;
|
||||
FileFormat lastFileFormat;
|
||||
QMap<QString, SideboardPlan *> sideboardPlans;
|
||||
InnerDecklistNode *root;
|
||||
|
|
@ -127,6 +128,7 @@ private:
|
|||
void getCardListHelper(InnerDecklistNode *node, QSet<QString> &result) const;
|
||||
signals:
|
||||
void deckLoaded();
|
||||
void deckHashChanged();
|
||||
public slots:
|
||||
void setName(const QString &_name = QString()) { name = _name; }
|
||||
void setComments(const QString &_comments = QString()) { comments = _comments; }
|
||||
|
|
@ -160,6 +162,9 @@ public:
|
|||
void cleanList();
|
||||
bool isEmpty() const { return root->isEmpty() && name.isEmpty() && comments.isEmpty() && sideboardPlans.isEmpty(); }
|
||||
QStringList getCardList() const;
|
||||
|
||||
QString getDeckHash() const { return deckHash; }
|
||||
void updateDeckHash();
|
||||
|
||||
InnerDecklistNode *getRoot() const { return root; }
|
||||
DecklistCardNode *addCard(const QString &cardName, const QString &zoneName);
|
||||
|
|
|
|||
|
|
@ -207,7 +207,7 @@ ServerInfo_Arrow::ServerInfo_Arrow(int _id, int _startPlayerId, const QString &_
|
|||
insertItem(new SerializableItem_Color("color", _color));
|
||||
}
|
||||
|
||||
ServerInfo_PlayerProperties::ServerInfo_PlayerProperties(int _playerId, ServerInfo_User *_userInfo, bool _spectator, bool _conceded, bool _readyStart, int _deckId)
|
||||
ServerInfo_PlayerProperties::ServerInfo_PlayerProperties(int _playerId, ServerInfo_User *_userInfo, bool _spectator, bool _conceded, bool _readyStart, const QString &_deckHash)
|
||||
: SerializableItem_Map("player_properties")
|
||||
{
|
||||
insertItem(new SerializableItem_Int("player_id", _playerId));
|
||||
|
|
@ -217,7 +217,7 @@ ServerInfo_PlayerProperties::ServerInfo_PlayerProperties(int _playerId, ServerIn
|
|||
insertItem(new SerializableItem_Bool("spectator", _spectator));
|
||||
insertItem(new SerializableItem_Bool("conceded", _conceded));
|
||||
insertItem(new SerializableItem_Bool("ready_start", _readyStart));
|
||||
insertItem(new SerializableItem_Int("deck_id", _deckId));
|
||||
insertItem(new SerializableItem_String("deck_hash", _deckHash));
|
||||
}
|
||||
|
||||
ServerInfo_Player::ServerInfo_Player(ServerInfo_PlayerProperties *_properties, DeckList *_deck, const QList<ServerInfo_Zone *> &_zoneList, const QList<ServerInfo_Counter *> &_counterList, const QList<ServerInfo_Arrow *> &_arrowList)
|
||||
|
|
|
|||
|
|
@ -189,14 +189,14 @@ public:
|
|||
|
||||
class ServerInfo_PlayerProperties : public SerializableItem_Map {
|
||||
public:
|
||||
ServerInfo_PlayerProperties(int _playerId = -1, ServerInfo_User *_userInfo = 0, bool _spectator = false, bool _conceded = false, bool _readyStart = false, int _deckId = -1);
|
||||
ServerInfo_PlayerProperties(int _playerId = -1, ServerInfo_User *_userInfo = 0, bool _spectator = false, bool _conceded = false, bool _readyStart = false, const QString &_deckHash = QString());
|
||||
static SerializableItem *newItem() { return new ServerInfo_PlayerProperties; }
|
||||
int getPlayerId() const { return static_cast<SerializableItem_Int *>(itemMap.value("player_id"))->getData(); }
|
||||
ServerInfo_User *getUserInfo() const { return static_cast<ServerInfo_User *>(itemMap.value("user")); }
|
||||
bool getSpectator() const { return static_cast<SerializableItem_Bool *>(itemMap.value("spectator"))->getData(); }
|
||||
bool getConceded() const { return static_cast<SerializableItem_Bool *>(itemMap.value("conceded"))->getData(); }
|
||||
bool getReadyStart() const { return static_cast<SerializableItem_Bool *>(itemMap.value("ready_start"))->getData(); }
|
||||
int getDeckId() const { return static_cast<SerializableItem_Int *>(itemMap.value("deck_id"))->getData(); }
|
||||
QString getDeckHash() const { return static_cast<SerializableItem_String *>(itemMap.value("deck_hash"))->getData(); }
|
||||
};
|
||||
|
||||
class ServerInfo_Player : public SerializableItem_Map {
|
||||
|
|
|
|||
|
|
@ -461,10 +461,10 @@ Context_Concede::Context_Concede()
|
|||
: GameEventContext("concede")
|
||||
{
|
||||
}
|
||||
Context_DeckSelect::Context_DeckSelect(int _deckId)
|
||||
Context_DeckSelect::Context_DeckSelect(const QString &_deckHash)
|
||||
: GameEventContext("deck_select")
|
||||
{
|
||||
insertItem(new SerializableItem_Int("deck_id", _deckId));
|
||||
insertItem(new SerializableItem_String("deck_hash", _deckHash));
|
||||
}
|
||||
Context_UndoDraw::Context_UndoDraw()
|
||||
: GameEventContext("undo_draw")
|
||||
|
|
|
|||
|
|
@ -75,7 +75,7 @@
|
|||
5:room_say:s,player_name:s,message
|
||||
6:ready_start
|
||||
6:concede
|
||||
6:deck_select:i,deck_id
|
||||
6:deck_select:s,deck_hash
|
||||
6:undo_draw
|
||||
6:move_card
|
||||
6:mulligan:i,number
|
||||
|
|
|
|||
|
|
@ -697,8 +697,8 @@ public:
|
|||
class Context_DeckSelect : public GameEventContext {
|
||||
Q_OBJECT
|
||||
public:
|
||||
Context_DeckSelect(int _deckId = -1);
|
||||
int getDeckId() const { return static_cast<SerializableItem_Int *>(itemMap.value("deck_id"))->getData(); };
|
||||
Context_DeckSelect(const QString &_deckHash = QString());
|
||||
QString getDeckHash() const { return static_cast<SerializableItem_String *>(itemMap.value("deck_hash"))->getData(); };
|
||||
static SerializableItem *newItem() { return new Context_DeckSelect; }
|
||||
int getItemId() const { return ItemId_Context_DeckSelect; }
|
||||
};
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@
|
|||
#include <QDebug>
|
||||
|
||||
Server_Player::Server_Player(Server_Game *_game, int _playerId, ServerInfo_User *_userInfo, bool _spectator, Server_ProtocolHandler *_handler)
|
||||
: game(_game), handler(_handler), userInfo(new ServerInfo_User(_userInfo)), deck(0), playerId(_playerId), spectator(_spectator), nextCardId(0), readyStart(false), conceded(false), deckId(-2)
|
||||
: game(_game), handler(_handler), userInfo(new ServerInfo_User(_userInfo)), deck(0), playerId(_playerId), spectator(_spectator), nextCardId(0), readyStart(false), conceded(false)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -187,16 +187,15 @@ ServerInfo_PlayerProperties *Server_Player::getProperties()
|
|||
{
|
||||
QMutexLocker locker(&game->gameMutex);
|
||||
|
||||
return new ServerInfo_PlayerProperties(playerId, new ServerInfo_User(userInfo), spectator, conceded, readyStart, deckId);
|
||||
return new ServerInfo_PlayerProperties(playerId, new ServerInfo_User(userInfo), spectator, conceded, readyStart, deck ? deck->getDeckHash() : QString());
|
||||
}
|
||||
|
||||
void Server_Player::setDeck(DeckList *_deck, int _deckId)
|
||||
void Server_Player::setDeck(DeckList *_deck)
|
||||
{
|
||||
QMutexLocker locker(&game->gameMutex);
|
||||
|
||||
delete deck;
|
||||
deck = _deck;
|
||||
deckId = _deckId;
|
||||
}
|
||||
|
||||
void Server_Player::addZone(Server_CardZone *zone)
|
||||
|
|
|
|||
|
|
@ -39,7 +39,6 @@ private:
|
|||
int nextCardId;
|
||||
bool readyStart;
|
||||
bool conceded;
|
||||
int deckId;
|
||||
public:
|
||||
Server_Player(Server_Game *_game, int _playerId, ServerInfo_User *_userInfo, bool _spectator, Server_ProtocolHandler *_handler);
|
||||
~Server_Player();
|
||||
|
|
@ -57,9 +56,8 @@ public:
|
|||
bool getSpectator() const { return spectator; }
|
||||
bool getConceded() const { return conceded; }
|
||||
void setConceded(bool _conceded) { conceded = _conceded; }
|
||||
int getDeckId() const { return deckId; }
|
||||
ServerInfo_User *getUserInfo() const { return userInfo; }
|
||||
void setDeck(DeckList *_deck, int _deckId);
|
||||
void setDeck(DeckList *_deck);
|
||||
DeckList *getDeck() const { return deck; }
|
||||
Server_Game *getGame() const { return game; }
|
||||
const QMap<QString, Server_CardZone *> &getZones() const { return zones; }
|
||||
|
|
|
|||
|
|
@ -595,9 +595,9 @@ ResponseCode Server_ProtocolHandler::cmdDeckSelect(Command_DeckSelect *cmd, Comm
|
|||
return r;
|
||||
}
|
||||
}
|
||||
player->setDeck(deck, cmd->getDeckId());
|
||||
player->setDeck(deck);
|
||||
|
||||
game->sendGameEvent(new Event_PlayerPropertiesChanged(player->getPlayerId(), player->getProperties()), new Context_DeckSelect(cmd->getDeckId()));
|
||||
game->sendGameEvent(new Event_PlayerPropertiesChanged(player->getPlayerId(), player->getProperties()), new Context_DeckSelect(deck->getDeckHash()));
|
||||
|
||||
cont->setResponse(new Response_DeckDownload(cont->getCmdId(), RespOk, new DeckList(deck)));
|
||||
return RespNothing;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue