diff --git a/cockatrice/CMakeLists.txt b/cockatrice/CMakeLists.txt index ca16d3d15..cfe0430e8 100644 --- a/cockatrice/CMakeLists.txt +++ b/cockatrice/CMakeLists.txt @@ -26,6 +26,7 @@ set(cockatrice_SOURCES src/client/ui/widgets/cards/card_info_text_widget.cpp src/client/ui/widgets/cards/card_info_display_widget.cpp src/client/ui/widgets/cards/card_size_widget.cpp + src/game/cards/card_info.cpp src/game/cards/card_item.cpp src/game/cards/card_list.cpp src/game/zones/card_zone.cpp diff --git a/cockatrice/resources/config/qtlogging.ini b/cockatrice/resources/config/qtlogging.ini index b141cbd00..378b962b7 100644 --- a/cockatrice/resources/config/qtlogging.ini +++ b/cockatrice/resources/config/qtlogging.ini @@ -44,6 +44,7 @@ # cockatrice_xml.* = false # cockatrice_xml.xml_3_parser = false # cockatrice_xml.xml_4_parser = false +# card_info = false # card_list = false # stack_zone = false diff --git a/cockatrice/src/game/cards/card_database.cpp b/cockatrice/src/game/cards/card_database.cpp index c7e2f06f2..b22bc2891 100644 --- a/cockatrice/src/game/cards/card_database.cpp +++ b/cockatrice/src/game/cards/card_database.cpp @@ -1,10 +1,8 @@ #include "card_database.h" -#include "../../client/network/spoiler_background_updater.h" #include "../../client/ui/picture_loader/picture_loader.h" #include "../../settings/cache_settings.h" #include "../../utility/card_set_comparator.h" -#include "../game_specific_terms.h" #include "./card_database_parser/cockatrice_xml_3.h" #include "./card_database_parser/cockatrice_xml_4.h" @@ -20,351 +18,6 @@ const char *CardDatabase::TOKENS_SETNAME = "TK"; -CardSet::CardSet(const QString &_shortName, - const QString &_longName, - const QString &_setType, - const QDate &_releaseDate, - const CardSet::Priority _priority) - : shortName(_shortName), longName(_longName), releaseDate(_releaseDate), setType(_setType), priority(_priority) -{ - loadSetOptions(); -} - -CardSetPtr CardSet::newInstance(const QString &_shortName, - const QString &_longName, - const QString &_setType, - const QDate &_releaseDate, - const Priority _priority) -{ - CardSetPtr ptr(new CardSet(_shortName, _longName, _setType, _releaseDate, _priority)); - // ptr->setSmartPointer(ptr); - return ptr; -} - -QString CardSet::getCorrectedShortName() const -{ - // For Windows machines. - QSet invalidFileNames; - invalidFileNames << "CON" - << "PRN" - << "AUX" - << "NUL" - << "COM1" - << "COM2" - << "COM3" - << "COM4" - << "COM5" - << "COM6" - << "COM7" - << "COM8" - << "COM9" - << "LPT1" - << "LPT2" - << "LPT3" - << "LPT4" - << "LPT5" - << "LPT6" - << "LPT7" - << "LPT8" - << "LPT9"; - - return invalidFileNames.contains(shortName) ? shortName + "_" : shortName; -} - -void CardSet::loadSetOptions() -{ - sortKey = SettingsCache::instance().cardDatabase().getSortKey(shortName); - enabled = SettingsCache::instance().cardDatabase().isEnabled(shortName); - isknown = SettingsCache::instance().cardDatabase().isKnown(shortName); -} - -void CardSet::setSortKey(unsigned int _sortKey) -{ - sortKey = _sortKey; - SettingsCache::instance().cardDatabase().setSortKey(shortName, _sortKey); -} - -void CardSet::setEnabled(bool _enabled) -{ - enabled = _enabled; - SettingsCache::instance().cardDatabase().setEnabled(shortName, _enabled); -} - -void CardSet::setIsKnown(bool _isknown) -{ - isknown = _isknown; - SettingsCache::instance().cardDatabase().setIsKnown(shortName, _isknown); -} - -class SetList::KeyCompareFunctor -{ -public: - inline bool operator()(const CardSetPtr &a, const CardSetPtr &b) const - { - if (a.isNull() || b.isNull()) { - qCDebug(CardDatabaseLog) << "SetList::KeyCompareFunctor a or b is null"; - return false; - } - - return a->getSortKey() < b->getSortKey(); - } -}; - -void SetList::sortByKey() -{ - std::sort(begin(), end(), KeyCompareFunctor()); -} - -int SetList::getEnabledSetsNum() -{ - int num = 0; - for (int i = 0; i < size(); ++i) { - CardSetPtr set = at(i); - if (set && set->getEnabled()) { - ++num; - } - } - return num; -} - -int SetList::getUnknownSetsNum() -{ - int num = 0; - for (int i = 0; i < size(); ++i) { - CardSetPtr set = at(i); - if (set && !set->getIsKnown() && !set->getIsKnownIgnored()) { - ++num; - } - } - return num; -} - -QStringList SetList::getUnknownSetsNames() -{ - QStringList sets = QStringList(); - for (int i = 0; i < size(); ++i) { - CardSetPtr set = at(i); - if (set && !set->getIsKnown() && !set->getIsKnownIgnored()) { - sets << set->getShortName(); - } - } - return sets; -} - -void SetList::enableAllUnknown() -{ - for (int i = 0; i < size(); ++i) { - CardSetPtr set = at(i); - if (set && !set->getIsKnown() && !set->getIsKnownIgnored()) { - set->setIsKnown(true); - set->setEnabled(true); - } else if (set && set->getIsKnownIgnored() && !set->getEnabled()) { - set->setEnabled(true); - } - } -} - -void SetList::enableAll() -{ - for (int i = 0; i < size(); ++i) { - CardSetPtr set = at(i); - - if (set == nullptr) { - qCDebug(CardDatabaseLog) << "enabledAll has null"; - continue; - } - - if (!set->getIsKnownIgnored()) { - set->setIsKnown(true); - } - - set->setEnabled(true); - } -} - -void SetList::markAllAsKnown() -{ - for (int i = 0; i < size(); ++i) { - CardSetPtr set = at(i); - if (set && !set->getIsKnown() && !set->getIsKnownIgnored()) { - set->setIsKnown(true); - set->setEnabled(false); - } else if (set && set->getIsKnownIgnored() && !set->getEnabled()) { - set->setEnabled(true); - } - } -} - -void SetList::guessSortKeys() -{ - defaultSort(); - for (int i = 0; i < size(); ++i) { - CardSetPtr set = at(i); - if (set.isNull()) { - qCDebug(CardDatabaseLog) << "guessSortKeys set is null"; - continue; - } - set->setSortKey(i); - } -} - -void SetList::defaultSort() -{ - std::sort(begin(), end(), [](const CardSetPtr &a, const CardSetPtr &b) { - // Sort by priority, then by release date, then by short name - if (a->getPriority() != b->getPriority()) { - return a->getPriority() < b->getPriority(); // lowest first - } else if (a->getReleaseDate() != b->getReleaseDate()) { - return a->getReleaseDate() > b->getReleaseDate(); // most recent first - } else { - return a->getShortName() < b->getShortName(); // alphabetically - } - }); -} - -CardInfoPerSet::CardInfoPerSet(const CardSetPtr &_set) : set(_set) -{ -} - -CardInfo::CardInfo(const QString &_name, - const QString &_text, - bool _isToken, - QVariantHash _properties, - const QList &_relatedCards, - const QList &_reverseRelatedCards, - CardInfoPerSetMap _sets, - bool _cipt, - bool _landscapeOrientation, - int _tableRow, - bool _upsideDownArt) - : name(_name), text(_text), isToken(_isToken), properties(std::move(_properties)), relatedCards(_relatedCards), - reverseRelatedCards(_reverseRelatedCards), sets(std::move(_sets)), cipt(_cipt), - landscapeOrientation(_landscapeOrientation), tableRow(_tableRow), upsideDownArt(_upsideDownArt) -{ - pixmapCacheKey = QLatin1String("card_") + name; - simpleName = CardInfo::simplifyName(name); - - refreshCachedSetNames(); -} - -CardInfo::~CardInfo() -{ - PictureLoader::clearPixmapCache(smartThis); -} - -CardInfoPtr CardInfo::newInstance(const QString &_name) -{ - return newInstance(_name, QString(), false, QVariantHash(), QList(), QList(), - CardInfoPerSetMap(), false, false, 0, false); -} - -CardInfoPtr CardInfo::newInstance(const QString &_name, - const QString &_text, - bool _isToken, - QVariantHash _properties, - const QList &_relatedCards, - const QList &_reverseRelatedCards, - CardInfoPerSetMap _sets, - bool _cipt, - bool _landscapeOrientation, - int _tableRow, - bool _upsideDownArt) -{ - CardInfoPtr ptr(new CardInfo(_name, _text, _isToken, std::move(_properties), _relatedCards, _reverseRelatedCards, - _sets, _cipt, _landscapeOrientation, _tableRow, _upsideDownArt)); - ptr->setSmartPointer(ptr); - - for (const auto &cardInfoPerSetList : _sets) { - for (const CardInfoPerSet &set : cardInfoPerSetList) { - set.getPtr()->append(ptr); - break; - } - } - - return ptr; -} - -QString CardInfo::getCorrectedName() const -{ - // remove all the characters reserved in windows file paths, - // other oses only disallow a subset of these so it covers all - static const QRegularExpression rmrx(R"(( // |[*<>:"\\?\x00-\x08\x10-\x1f]))"); - static const QRegularExpression spacerx(R"([/\x09-\x0f])"); - static const QString space(' '); - QString result = name; - // Fire // Ice, Circle of Protection: Red, "Ach! Hans, Run!", Who/What/When/Where/Why, Question Elemental? - return result.remove(rmrx).replace(spacerx, space); -} - -void CardInfo::addToSet(const CardSetPtr &_set, const CardInfoPerSet _info) -{ - _set->append(smartThis); - sets[_set->getShortName()].append(_info); - - refreshCachedSetNames(); -} - -void CardInfo::combineLegalities(const QVariantHash &props) -{ - QHashIterator it(props); - while (it.hasNext()) { - it.next(); - if (it.key().startsWith("format-")) { - smartThis->setProperty(it.key(), it.value().toString()); - } - } -} - -void CardInfo::refreshCachedSetNames() -{ - QStringList setList; - // update the cached list of set names - for (const auto &cardInfoPerSetList : sets) { - for (const auto &set : cardInfoPerSetList) { - if (set.getPtr()->getEnabled()) { - setList << set.getPtr()->getShortName(); - } - break; - } - } - setsNames = setList.join(", "); -} - -QString CardInfo::simplifyName(const QString &name) -{ - static const QRegularExpression spaceOrSplit("(\\s+|\\/\\/.*)"); - static const QRegularExpression nonAlnum("[^a-z0-9]"); - - QString simpleName = name.toLower(); - - // remove spaces and right halves of split cards - simpleName.remove(spaceOrSplit); - - // So Aetherling would work, but not Ætherling since 'Æ' would get replaced - // with nothing. - simpleName.replace("æ", "ae"); - - // Replace Jötun Grunt with Jotun Grunt. - simpleName = simpleName.normalized(QString::NormalizationForm_KD); - - // remove all non alphanumeric characters from the name - simpleName.remove(nonAlnum); - return simpleName; -} - -const QChar CardInfo::getColorChar() const -{ - QString colors = getColors(); - switch (colors.size()) { - case 0: - return QChar(); - case 1: - return colors.at(0); - default: - return QChar('m'); - } -} - CardDatabase::CardDatabase(QObject *parent) : QObject(parent), loadStatus(NotLoaded) { qRegisterMetaType("CardInfoPtr"); @@ -883,65 +536,4 @@ bool CardDatabase::saveCustomTokensToFile() availableParsers.first()->saveToFile(tmpSets, tmpCards, fileName); return true; -} - -CardRelation::CardRelation(const QString &_name, - AttachType _attachType, - bool _isCreateAllExclusion, - bool _isVariableCount, - int _defaultCount, - bool _isPersistent) - : name(_name), attachType(_attachType), isCreateAllExclusion(_isCreateAllExclusion), - isVariableCount(_isVariableCount), defaultCount(_defaultCount), isPersistent(_isPersistent) -{ -} - -void CardInfo::resetReverseRelatedCards2Me() -{ - for (CardRelation *cardRelation : this->getReverseRelatedCards2Me()) { - cardRelation->deleteLater(); - } - reverseRelatedCardsToMe = QList(); -} - -// Back-compatibility methods. Remove ASAP -const QString CardInfo::getCardType() const -{ - return getProperty(Mtg::CardType); -} -void CardInfo::setCardType(const QString &value) -{ - setProperty(Mtg::CardType, value); -} -const QString CardInfo::getCmc() const -{ - return getProperty(Mtg::ConvertedManaCost); -} -const QString CardInfo::getColors() const -{ - return getProperty(Mtg::Colors); -} -void CardInfo::setColors(const QString &value) -{ - setProperty(Mtg::Colors, value); -} -const QString CardInfo::getLoyalty() const -{ - return getProperty(Mtg::Loyalty); -} -const QString CardInfo::getMainCardType() const -{ - return getProperty(Mtg::MainCardType); -} -const QString CardInfo::getManaCost() const -{ - return getProperty(Mtg::ManaCost); -} -const QString CardInfo::getPowTough() const -{ - return getProperty(Mtg::PowTough); -} -void CardInfo::setPowTough(const QString &value) -{ - setProperty(Mtg::PowTough, value); -} +} \ No newline at end of file diff --git a/cockatrice/src/game/cards/card_database.h b/cockatrice/src/game/cards/card_database.h index 12b4a06fe..236278b30 100644 --- a/cockatrice/src/game/cards/card_database.h +++ b/cockatrice/src/game/cards/card_database.h @@ -1,16 +1,14 @@ #ifndef CARDDATABASE_H #define CARDDATABASE_H +#include "card_info.h" + #include #include #include #include #include -#include -#include -#include #include -#include #include #include @@ -18,406 +16,8 @@ inline Q_LOGGING_CATEGORY(CardDatabaseLog, "card_database"); inline Q_LOGGING_CATEGORY(CardDatabaseLoadingLog, "card_database.loading"); inline Q_LOGGING_CATEGORY(CardDatabaseLoadingSuccessOrFailureLog, "card_database.loading.success_or_failure"); -class CardDatabase; -class CardInfo; -class CardInfoPerSet; -class CardSet; -class CardRelation; class ICardDatabaseParser; -typedef QMap QStringMap; -typedef QSharedPointer CardInfoPtr; -typedef QSharedPointer CardSetPtr; -typedef QMap> CardInfoPerSetMap; - -Q_DECLARE_METATYPE(CardInfoPtr) - -class CardSet : public QList -{ -public: - enum Priority - { - PriorityFallback = 0, - PriorityPrimary = 10, - PrioritySecondary = 20, - PriorityReprint = 30, - PriorityOther = 40, - PriorityLowest = 100, - }; - -private: - QString shortName, longName; - unsigned int sortKey; - QDate releaseDate; - QString setType; - Priority priority; - bool enabled, isknown; - -public: - explicit CardSet(const QString &_shortName = QString(), - const QString &_longName = QString(), - const QString &_setType = QString(), - const QDate &_releaseDate = QDate(), - const Priority _priority = PriorityFallback); - static CardSetPtr newInstance(const QString &_shortName = QString(), - const QString &_longName = QString(), - const QString &_setType = QString(), - const QDate &_releaseDate = QDate(), - const Priority _priority = PriorityFallback); - QString getCorrectedShortName() const; - QString getShortName() const - { - return shortName; - } - QString getLongName() const - { - return longName; - } - QString getSetType() const - { - return setType; - } - QDate getReleaseDate() const - { - return releaseDate; - } - Priority getPriority() const - { - return priority; - } - void setLongName(const QString &_longName) - { - longName = _longName; - } - void setSetType(const QString &_setType) - { - setType = _setType; - } - void setReleaseDate(const QDate &_releaseDate) - { - releaseDate = _releaseDate; - } - void setPriority(const Priority _priority) - { - priority = _priority; - } - - void loadSetOptions(); - int getSortKey() const - { - return sortKey; - } - void setSortKey(unsigned int _sortKey); - bool getEnabled() const - { - return enabled; - } - void setEnabled(bool _enabled); - bool getIsKnown() const - { - return isknown; - } - void setIsKnown(bool _isknown); - - // Determine incomplete sets. - bool getIsKnownIgnored() const - { - return longName.length() + setType.length() + releaseDate.toString().length() == 0; - } -}; - -class SetList : public QList -{ -private: - class KeyCompareFunctor; - -public: - void sortByKey(); - void guessSortKeys(); - void enableAllUnknown(); - void enableAll(); - void markAllAsKnown(); - int getEnabledSetsNum(); - int getUnknownSetsNum(); - QStringList getUnknownSetsNames(); - void defaultSort(); -}; - -class CardInfoPerSet -{ -public: - explicit CardInfoPerSet(const CardSetPtr &_set = QSharedPointer(nullptr)); - ~CardInfoPerSet() = default; - - bool operator==(const CardInfoPerSet &other) const - { - return this->set == other.set && this->properties == other.properties; - } - -private: - CardSetPtr set; - // per-set card properties; - QVariantHash properties; - -public: - const CardSetPtr getPtr() const - { - return set; - } - const QStringList getProperties() const - { - return properties.keys(); - } - const QString getProperty(const QString &propertyName) const - { - return properties.value(propertyName).toString(); - } - void setProperty(const QString &_name, const QString &_value) - { - properties.insert(_name, _value); - } -}; - -class CardInfo : public QObject -{ - Q_OBJECT -private: - CardInfoPtr smartThis; - // The card name - QString name; - // The name without punctuation or capitalization, for better card name recognition. - QString simpleName; - // The key used to identify this card in the cache - QString pixmapCacheKey; - // card text - QString text; - // whether this is not a "real" card but a token - bool isToken; - // basic card properties; common for all the sets - QVariantHash properties; - // the cards i'm related to - QList relatedCards; - // the card i'm reverse-related to - QList reverseRelatedCards; - // the cards thare are reverse-related to me - QList reverseRelatedCardsToMe; - // card sets - CardInfoPerSetMap sets; - // cached set names - QString setsNames; - // positioning properties; used by UI - bool cipt; - bool landscapeOrientation; - int tableRow; - bool upsideDownArt; - -public: - explicit CardInfo(const QString &_name, - const QString &_text, - bool _isToken, - QVariantHash _properties, - const QList &_relatedCards, - const QList &_reverseRelatedCards, - CardInfoPerSetMap _sets, - bool _cipt, - bool _landscapeOrientation, - int _tableRow, - bool _upsideDownArt); - CardInfo(const CardInfo &other) - : QObject(other.parent()), name(other.name), simpleName(other.simpleName), pixmapCacheKey(other.pixmapCacheKey), - text(other.text), isToken(other.isToken), properties(other.properties), relatedCards(other.relatedCards), - reverseRelatedCards(other.reverseRelatedCards), reverseRelatedCardsToMe(other.reverseRelatedCardsToMe), - sets(other.sets), setsNames(other.setsNames), cipt(other.cipt), - landscapeOrientation(other.landscapeOrientation), tableRow(other.tableRow), upsideDownArt(other.upsideDownArt) - { - } - ~CardInfo() override; - - static CardInfoPtr newInstance(const QString &_name); - - static CardInfoPtr newInstance(const QString &_name, - const QString &_text, - bool _isToken, - QVariantHash _properties, - const QList &_relatedCards, - const QList &_reverseRelatedCards, - CardInfoPerSetMap _sets, - bool _cipt, - bool _landscapeOrientation, - int _tableRow, - bool _upsideDownArt); - - CardInfoPtr clone() const - { - // Use the copy constructor to create a new instance - CardInfoPtr newCardInfo = CardInfoPtr(new CardInfo(*this)); - newCardInfo->setSmartPointer(newCardInfo); // Set the smart pointer for the new instance - return newCardInfo; - } - - void setSmartPointer(CardInfoPtr _ptr) - { - smartThis = std::move(_ptr); - } - - // basic properties - inline const QString &getName() const - { - return name; - } - const QString &getSimpleName() const - { - return simpleName; - } - void setPixmapCacheKey(QString _pixmapCacheKey) - { - pixmapCacheKey = _pixmapCacheKey; - } - const QString &getPixmapCacheKey() const - { - return pixmapCacheKey; - } - - const QString &getText() const - { - return text; - } - void setText(const QString &_text) - { - text = _text; - emit cardInfoChanged(smartThis); - } - - bool getIsToken() const - { - return isToken; - } - const QStringList getProperties() const - { - return properties.keys(); - } - const QString getProperty(const QString &propertyName) const - { - return properties.value(propertyName).toString(); - } - void setProperty(const QString &_name, const QString &_value) - { - properties.insert(_name, _value); - emit cardInfoChanged(smartThis); - } - bool hasProperty(const QString &propertyName) const - { - return properties.contains(propertyName); - } - const CardInfoPerSetMap &getSets() const - { - return sets; - } - const QString &getSetsNames() const - { - return setsNames; - } - const QString getSetProperty(const QString &setName, const QString &propertyName) const - { - if (!sets.contains(setName)) - return ""; - - for (const auto &set : sets[setName]) { - if (QLatin1String("card_") + this->getName() + QString("_") + QString(set.getProperty("uuid")) == - this->getPixmapCacheKey()) { - return set.getProperty(propertyName); - } - } - - return sets[setName][0].getProperty(propertyName); - } - - // related cards - const QList &getRelatedCards() const - { - return relatedCards; - } - const QList &getReverseRelatedCards() const - { - return reverseRelatedCards; - } - const QList &getReverseRelatedCards2Me() const - { - return reverseRelatedCardsToMe; - } - const QList getAllRelatedCards() const - { - QList result; - result.append(getRelatedCards()); - result.append(getReverseRelatedCards2Me()); - return result; - } - void resetReverseRelatedCards2Me(); - void addReverseRelatedCards2Me(CardRelation *cardRelation) - { - reverseRelatedCardsToMe.append(cardRelation); - } - - // positioning - bool getCipt() const - { - return cipt; - } - bool getLandscapeOrientation() const - { - return landscapeOrientation; - } - int getTableRow() const - { - return tableRow; - } - void setTableRow(int _tableRow) - { - tableRow = _tableRow; - } - bool getUpsideDownArt() const - { - return upsideDownArt; - } - const QChar getColorChar() const; - - // Back-compatibility methods. Remove ASAP - const QString getCardType() const; - void setCardType(const QString &value); - const QString getCmc() const; - const QString getColors() const; - void setColors(const QString &value); - const QString getLoyalty() const; - const QString getMainCardType() const; - const QString getManaCost() const; - const QString getPowTough() const; - void setPowTough(const QString &value); - - // methods using per-set properties - QString getCustomPicURL(const QString &set) const - { - return getSetProperty(set, "picurl"); - } - QString getCorrectedName() const; - void addToSet(const CardSetPtr &_set, CardInfoPerSet _info = CardInfoPerSet()); - void combineLegalities(const QVariantHash &props); - void emitPixmapUpdated() - { - emit pixmapUpdated(); - } - void refreshCachedSetNames(); - - /** - * Simplify a name to have no punctuation and lowercase all letters, for - * less strict name-matching. - */ - static QString simplifyName(const QString &name); - -signals: - void pixmapUpdated(); - void cardInfoChanged(CardInfoPtr card); -}; - enum LoadStatus { Ok, @@ -523,79 +123,4 @@ signals: void cardRemoved(CardInfoPtr card); }; -class CardRelation : public QObject -{ - Q_OBJECT -public: - enum AttachType - { - DoesNotAttach = 0, - AttachTo = 1, - TransformInto = 2, - }; - -private: - QString name; - AttachType attachType; - bool isCreateAllExclusion; - bool isVariableCount; - int defaultCount; - bool isPersistent; - -public: - explicit CardRelation(const QString &_name = QString(), - AttachType _attachType = DoesNotAttach, - bool _isCreateAllExclusion = false, - bool _isVariableCount = false, - int _defaultCount = 1, - bool _isPersistent = false); - - inline const QString &getName() const - { - return name; - } - AttachType getAttachType() const - { - return attachType; - } - bool getDoesAttach() const - { - return attachType != DoesNotAttach; - } - bool getDoesTransform() const - { - return attachType == TransformInto; - } - QString getAttachTypeAsString() const - { - switch (attachType) { - case AttachTo: - return "attach"; - case TransformInto: - return "transform"; - default: - return ""; - } - } - bool getCanCreateAnother() const - { - return !getDoesAttach(); - } - bool getIsCreateAllExclusion() const - { - return isCreateAllExclusion; - } - bool getIsVariable() const - { - return isVariableCount; - } - int getDefaultCount() const - { - return defaultCount; - } - bool getIsPersistent() const - { - return isPersistent; - } -}; #endif diff --git a/cockatrice/src/game/cards/card_info.cpp b/cockatrice/src/game/cards/card_info.cpp index a5d93f185..c4e00638b 100644 --- a/cockatrice/src/game/cards/card_info.cpp +++ b/cockatrice/src/game/cards/card_info.cpp @@ -1,25 +1,16 @@ #include "card_info.h" -#include "../../client/network/spoiler_background_updater.h" #include "../../client/ui/picture_loader/picture_loader.h" #include "../../settings/cache_settings.h" -#include "../../utility/card_set_comparator.h" #include "../game_specific_terms.h" -#include "./card_database_parser/cockatrice_xml_3.h" -#include "./card_database_parser/cockatrice_xml_4.h" -#include #include #include -#include -#include #include #include #include #include -const char *CardDatabase::TOKENS_SETNAME = "TK"; - CardSet::CardSet(const QString &_shortName, const QString &_longName, const QString &_setType, @@ -102,7 +93,7 @@ public: inline bool operator()(const CardSetPtr &a, const CardSetPtr &b) const { if (a.isNull() || b.isNull()) { - qCDebug(CardDatabaseLog) << "SetList::KeyCompareFunctor a or b is null"; + qCDebug(CardInfoLog) << "SetList::KeyCompareFunctor a or b is null"; return false; } @@ -170,7 +161,7 @@ void SetList::enableAll() CardSetPtr set = at(i); if (set == nullptr) { - qCDebug(CardDatabaseLog) << "enabledAll has null"; + qCDebug(CardInfoLog) << "enabledAll has null"; continue; } @@ -201,7 +192,7 @@ void SetList::guessSortKeys() for (int i = 0; i < size(); ++i) { CardSetPtr set = at(i); if (set.isNull()) { - qCDebug(CardDatabaseLog) << "guessSortKeys set is null"; + qCDebug(CardInfoLog) << "guessSortKeys set is null"; continue; } set->setSortKey(i); @@ -365,526 +356,6 @@ const QChar CardInfo::getColorChar() const } } -CardDatabase::CardDatabase(QObject *parent) : QObject(parent), loadStatus(NotLoaded) -{ - qRegisterMetaType("CardInfoPtr"); - qRegisterMetaType("CardSetPtr"); - - // add new parsers here - availableParsers << new CockatriceXml4Parser; - availableParsers << new CockatriceXml3Parser; - - for (auto &parser : availableParsers) { - connect(parser, &ICardDatabaseParser::addCard, this, &CardDatabase::addCard, Qt::DirectConnection); - connect(parser, &ICardDatabaseParser::addSet, this, &CardDatabase::addSet, Qt::DirectConnection); - } - - connect(&SettingsCache::instance(), &SettingsCache::cardDatabasePathChanged, this, - &CardDatabase::loadCardDatabases); -} - -CardDatabase::~CardDatabase() -{ - clear(); - qDeleteAll(availableParsers); -} - -void CardDatabase::clear() -{ - clearDatabaseMutex->lock(); - - QHashIterator i(cards); - while (i.hasNext()) { - i.next(); - if (i.value()) { - removeCard(i.value()); - } - } - - cards.clear(); - simpleNameCards.clear(); - - sets.clear(); - ICardDatabaseParser::clearSetlist(); - - loadStatus = NotLoaded; - - clearDatabaseMutex->unlock(); -} - -void CardDatabase::addCard(CardInfoPtr card) -{ - if (card == nullptr) { - qCDebug(CardDatabaseLog) << "CardDatabase::addCard(nullptr)"; - return; - } - - // if card already exists just add the new set property - if (cards.contains(card->getName())) { - CardInfoPtr sameCard = cards[card->getName()]; - for (const auto &cardInfoPerSetList : card->getSets()) { - for (const CardInfoPerSet &set : cardInfoPerSetList) { - sameCard->addToSet(set.getPtr(), set); - } - } - return; - } - - addCardMutex->lock(); - cards.insert(card->getName(), card); - simpleNameCards.insert(card->getSimpleName(), card); - addCardMutex->unlock(); - emit cardAdded(card); -} - -void CardDatabase::removeCard(CardInfoPtr card) -{ - if (card.isNull()) { - qCDebug(CardDatabaseLog) << "CardDatabase::removeCard(nullptr)"; - return; - } - - for (auto *cardRelation : card->getRelatedCards()) - cardRelation->deleteLater(); - - for (auto *cardRelation : card->getReverseRelatedCards()) - cardRelation->deleteLater(); - - for (auto *cardRelation : card->getReverseRelatedCards2Me()) - cardRelation->deleteLater(); - - removeCardMutex->lock(); - cards.remove(card->getName()); - simpleNameCards.remove(card->getSimpleName()); - removeCardMutex->unlock(); - emit cardRemoved(card); -} - -CardInfoPtr CardDatabase::getCard(const QString &cardName) const -{ - return getCardFromMap(cards, cardName); -} - -QList CardDatabase::getCards(const QStringList &cardNames) const -{ - QList cardInfos; - for (const QString &cardName : cardNames) { - CardInfoPtr ptr = getCardFromMap(cards, cardName); - if (ptr) - cardInfos.append(ptr); - } - - return cardInfos; -} - -QList CardDatabase::getCardsByNameAndProviderId(const QMap &cardNames) const -{ - QList cardInfos; - for (const QString &cardName : cardNames) { - CardInfoPtr ptr = getCardByNameAndProviderId(cardName, cardNames[cardName]); - if (ptr) - cardInfos.append(ptr); - } - - return cardInfos; -} - -CardInfoPtr CardDatabase::getCardByNameAndProviderId(const QString &cardName, const QString &providerId) const -{ - auto info = getCard(cardName); - if (providerId.isNull() || providerId.isEmpty() || info.isNull()) { - return info; - } - - for (const auto &cardInfoPerSetList : info->getSets()) { - for (const auto &set : cardInfoPerSetList) { - if (set.getProperty("uuid") == providerId) { - CardInfoPtr cardFromSpecificSet = info->clone(); - cardFromSpecificSet->setPixmapCacheKey(QLatin1String("card_") + QString(info->getName()) + - QString("_") + QString(set.getProperty("uuid"))); - return cardFromSpecificSet; - } - } - } - return {}; -} - -CardInfoPtr CardDatabase::getCardBySimpleName(const QString &cardName) const -{ - return getCardFromMap(simpleNameCards, CardInfo::simplifyName(cardName)); -} - -CardInfoPtr CardDatabase::guessCard(const QString &cardName, const QString &providerId) const -{ - CardInfoPtr temp = providerId.isEmpty() ? getCard(cardName) : getCardByNameAndProviderId(cardName, providerId); - - if (temp == nullptr) { // get card by simple name instead - temp = getCardBySimpleName(cardName); - if (temp == nullptr) { // still could not find the card, so simplify the cardName too - const auto &simpleCardName = CardInfo::simplifyName(cardName); - temp = getCardBySimpleName(simpleCardName); - } - } - return temp; // returns nullptr if not found -} - -CardSetPtr CardDatabase::getSet(const QString &setName) -{ - if (sets.contains(setName)) { - return sets.value(setName); - } else { - CardSetPtr newSet = CardSet::newInstance(setName); - sets.insert(setName, newSet); - return newSet; - } -} - -void CardDatabase::addSet(CardSetPtr set) -{ - sets.insert(set->getShortName(), set); -} - -SetList CardDatabase::getSetList() const -{ - SetList result; - QHashIterator i(sets); - while (i.hasNext()) { - i.next(); - result << i.value(); - } - return result; -} - -CardInfoPtr CardDatabase::getCardFromMap(const CardNameMap &cardMap, const QString &cardName) const -{ - if (cardMap.contains(cardName)) - return cardMap.value(cardName); - - return {}; -} - -LoadStatus CardDatabase::loadFromFile(const QString &fileName) -{ - QFile file(fileName); - file.open(QIODevice::ReadOnly); - if (!file.isOpen()) { - return FileError; - } - - for (auto parser : availableParsers) { - file.reset(); - if (parser->getCanParseFile(fileName, file)) { - file.reset(); - parser->parseFile(file); - return Ok; - } - } - - return Invalid; -} - -LoadStatus CardDatabase::loadCardDatabase(const QString &path) -{ - auto startTime = QTime::currentTime(); - LoadStatus tempLoadStatus = NotLoaded; - if (!path.isEmpty()) { - loadFromFileMutex->lock(); - tempLoadStatus = loadFromFile(path); - loadFromFileMutex->unlock(); - } - - int msecs = startTime.msecsTo(QTime::currentTime()); - qCDebug(CardDatabaseLoadingLog) << "Path =" << path << "Status =" << tempLoadStatus << "Cards =" << cards.size() - << "Sets =" << sets.size() << QString("%1ms").arg(msecs); - - return tempLoadStatus; -} - -LoadStatus CardDatabase::loadCardDatabases() -{ - reloadDatabaseMutex->lock(); - - qCDebug(CardDatabaseLoadingLog) << "Started"; - - clear(); // remove old db - - loadStatus = loadCardDatabase(SettingsCache::instance().getCardDatabasePath()); // load main card database - loadCardDatabase(SettingsCache::instance().getTokenDatabasePath()); // load tokens database - loadCardDatabase(SettingsCache::instance().getSpoilerCardDatabasePath()); // load spoilers database - - // find all custom card databases, recursively & following symlinks - // then load them alphabetically - QDirIterator customDatabaseIterator(SettingsCache::instance().getCustomCardDatabasePath(), QStringList() << "*.xml", - QDir::Files, QDirIterator::Subdirectories | QDirIterator::FollowSymlinks); - QStringList databasePaths; - while (customDatabaseIterator.hasNext()) { - customDatabaseIterator.next(); - databasePaths.push_back(customDatabaseIterator.filePath()); - } - databasePaths.sort(); - - for (auto i = 0; i < databasePaths.size(); ++i) { - const auto &databasePath = databasePaths.at(i); - qCDebug(CardDatabaseLoadingLog) << "Loading Custom Set" << i << "(" << databasePath << ")"; - loadCardDatabase(databasePath); - } - - // AFTER all the cards have been loaded - - // Refresh the pixmap cache keys for all cards by setting them to the UUID of the preferred printing - refreshPreferredPrintings(); - // resolve the reverse-related tags - refreshCachedReverseRelatedCards(); - - if (loadStatus == Ok) { - checkUnknownSets(); // update deck editors, etc - qCDebug(CardDatabaseLoadingSuccessOrFailureLog) << "Success"; - emit cardDatabaseLoadingFinished(); - } else { - qCDebug(CardDatabaseLoadingSuccessOrFailureLog) << "Failed"; - emit cardDatabaseLoadingFailed(); // bring up the settings dialog - } - - reloadDatabaseMutex->unlock(); - return loadStatus; -} - -void CardDatabase::refreshPreferredPrintings() -{ - for (const CardInfoPtr &card : cards) { - card->setPixmapCacheKey(QLatin1String("card_") + QString(card->getName()) + QString("_") + - QString(getPreferredPrintingProviderIdForCard(card->getName()))); - } -} - -CardInfoPerSet CardDatabase::getPreferredSetForCard(const QString &cardName) const -{ - CardInfoPtr cardInfo = getCard(cardName); - if (!cardInfo) { - return CardInfoPerSet(nullptr); - } - - CardInfoPerSetMap setMap = cardInfo->getSets(); - if (setMap.empty()) { - return CardInfoPerSet(nullptr); - } - - CardSetPtr preferredSet = nullptr; - CardInfoPerSet preferredCard; - SetPriorityComparator comparator; - - for (const auto &cardInfoPerSetList : setMap) { - for (auto &cardInfoForSet : cardInfoPerSetList) { - CardSetPtr currentSet = cardInfoForSet.getPtr(); - if (!preferredSet || comparator(currentSet, preferredSet)) { - preferredSet = currentSet; - preferredCard = cardInfoForSet; - } - } - } - - if (preferredSet) { - return preferredCard; - } - - return CardInfoPerSet(nullptr); -} - -CardInfoPerSet CardDatabase::getSpecificSetForCard(const QString &cardName, const QString &providerId) const -{ - CardInfoPtr cardInfo = getCard(cardName); - if (!cardInfo) { - return CardInfoPerSet(nullptr); - } - - CardInfoPerSetMap setMap = cardInfo->getSets(); - if (setMap.empty()) { - return CardInfoPerSet(nullptr); - } - - for (const auto &cardInfoPerSetList : setMap) { - for (auto &cardInfoForSet : cardInfoPerSetList) { - if (cardInfoForSet.getProperty("uuid") == providerId) { - return cardInfoForSet; - } - } - } - - if (providerId.isNull()) { - return getPreferredSetForCard(cardName); - } - - return CardInfoPerSet(nullptr); -} - -CardInfoPerSet CardDatabase::getSpecificSetForCard(const QString &cardName, - const QString &setShortName, - const QString &collectorNumber) const -{ - CardInfoPtr cardInfo = getCard(cardName); - if (!cardInfo) { - return CardInfoPerSet(nullptr); - } - - CardInfoPerSetMap setMap = cardInfo->getSets(); - if (setMap.empty()) { - return CardInfoPerSet(nullptr); - } - - for (const auto &cardInfoPerSetList : setMap) { - for (auto &cardInfoForSet : cardInfoPerSetList) { - if (cardInfoForSet.getPtr()->getShortName() == setShortName && - cardInfoForSet.getProperty("num") == collectorNumber) { - return cardInfoForSet; - } - } - } - - return CardInfoPerSet(nullptr); -} - -QString CardDatabase::getPreferredPrintingProviderIdForCard(const QString &cardName) -{ - CardInfoPerSet preferredSetCardInfo = getPreferredSetForCard(cardName); - QString preferredPrintingProviderId = preferredSetCardInfo.getProperty(QString("uuid")); - if (preferredPrintingProviderId.isEmpty()) { - CardInfoPtr defaultCardInfo = getCard(cardName); - if (defaultCardInfo.isNull()) { - return cardName; - } - return defaultCardInfo->getName(); - } - return preferredPrintingProviderId; -} - -bool CardDatabase::isProviderIdForPreferredPrinting(const QString &cardName, const QString &providerId) -{ - if (providerId.startsWith("card_")) { - return providerId == - QLatin1String("card_") + cardName + QString("_") + getPreferredPrintingProviderIdForCard(cardName); - } - return providerId == getPreferredPrintingProviderIdForCard(cardName); -} - -CardInfoPerSet CardDatabase::getSetInfoForCard(const CardInfoPtr &_card) -{ - const CardInfoPerSetMap &setMap = _card->getSets(); - if (setMap.empty()) { - return CardInfoPerSet(nullptr); - } - - for (const auto &cardInfoPerSetList : setMap) { - for (const auto &cardInfoForSet : cardInfoPerSetList) { - if (QLatin1String("card_") + _card->getName() + QString("_") + cardInfoForSet.getProperty("uuid") == - _card->getPixmapCacheKey()) { - return cardInfoForSet; - } - } - } - - return CardInfoPerSet(nullptr); -} - -void CardDatabase::refreshCachedReverseRelatedCards() -{ - for (const CardInfoPtr &card : cards) - card->resetReverseRelatedCards2Me(); - - for (const CardInfoPtr &card : cards) { - if (card->getReverseRelatedCards().isEmpty()) { - continue; - } - - for (CardRelation *cardRelation : card->getReverseRelatedCards()) { - const QString &targetCard = cardRelation->getName(); - if (!cards.contains(targetCard)) { - continue; - } - - auto *newCardRelation = new CardRelation( - card->getName(), cardRelation->getAttachType(), cardRelation->getIsCreateAllExclusion(), - cardRelation->getIsVariable(), cardRelation->getDefaultCount(), cardRelation->getIsPersistent()); - cards.value(targetCard)->addReverseRelatedCards2Me(newCardRelation); - } - } -} - -QStringList CardDatabase::getAllMainCardTypes() const -{ - QSet types; - QHashIterator cardIterator(cards); - while (cardIterator.hasNext()) { - types.insert(cardIterator.next().value()->getMainCardType()); - } - return types.values(); -} - -void CardDatabase::checkUnknownSets() -{ - auto _sets = getSetList(); - - if (_sets.getEnabledSetsNum()) { - // if some sets are first found on this run, ask the user - int numUnknownSets = _sets.getUnknownSetsNum(); - QStringList unknownSetNames = _sets.getUnknownSetsNames(); - if (numUnknownSets > 0) { - emit cardDatabaseNewSetsFound(numUnknownSets, unknownSetNames); - } else { - _sets.markAllAsKnown(); - } - } else { - // No set enabled. Probably this is the first time running trice - _sets.guessSortKeys(); - _sets.sortByKey(); - _sets.enableAll(); - notifyEnabledSetsChanged(); - - emit cardDatabaseAllNewSetsEnabled(); - } -} - -void CardDatabase::enableAllUnknownSets() -{ - auto _sets = getSetList(); - _sets.enableAllUnknown(); -} - -void CardDatabase::markAllSetsAsKnown() -{ - auto _sets = getSetList(); - _sets.markAllAsKnown(); -} - -void CardDatabase::notifyEnabledSetsChanged() -{ - // refresh the list of cached set names - for (const CardInfoPtr &card : cards) - card->refreshCachedSetNames(); - - // inform the carddatabasemodels that they need to re-check their list of cards - emit cardDatabaseEnabledSetsChanged(); -} - -bool CardDatabase::saveCustomTokensToFile() -{ - QString fileName = - SettingsCache::instance().getCustomCardDatabasePath() + "/" + CardDatabase::TOKENS_SETNAME + ".xml"; - - SetNameMap tmpSets; - CardSetPtr customTokensSet = getSet(CardDatabase::TOKENS_SETNAME); - tmpSets.insert(CardDatabase::TOKENS_SETNAME, customTokensSet); - - CardNameMap tmpCards; - for (const CardInfoPtr &card : cards) { - if (card->getSets().contains(CardDatabase::TOKENS_SETNAME)) { - tmpCards.insert(card->getName(), card); - } - } - - availableParsers.first()->saveToFile(tmpSets, tmpCards, fileName); - return true; -} - CardRelation::CardRelation(const QString &_name, AttachType _attachType, bool _isCreateAllExclusion, diff --git a/cockatrice/src/game/cards/card_info.h b/cockatrice/src/game/cards/card_info.h index 12b4a06fe..9d06bc5f6 100644 --- a/cockatrice/src/game/cards/card_info.h +++ b/cockatrice/src/game/cards/card_info.h @@ -1,7 +1,6 @@ -#ifndef CARDDATABASE_H -#define CARDDATABASE_H +#ifndef CARD_INFO_H +#define CARD_INFO_H -#include #include #include #include @@ -11,14 +10,10 @@ #include #include #include -#include #include -inline Q_LOGGING_CATEGORY(CardDatabaseLog, "card_database"); -inline Q_LOGGING_CATEGORY(CardDatabaseLoadingLog, "card_database.loading"); -inline Q_LOGGING_CATEGORY(CardDatabaseLoadingSuccessOrFailureLog, "card_database.loading.success_or_failure"); +inline Q_LOGGING_CATEGORY(CardInfoLog, "card_info"); -class CardDatabase; class CardInfo; class CardInfoPerSet; class CardSet; @@ -418,111 +413,6 @@ signals: void cardInfoChanged(CardInfoPtr card); }; -enum LoadStatus -{ - Ok, - VersionTooOld, - Invalid, - NotLoaded, - FileError, - NoCards -}; - -typedef QHash CardNameMap; -typedef QHash SetNameMap; - -class CardDatabase : public QObject -{ - Q_OBJECT -protected: - /* - * The cards, indexed by name. - */ - CardNameMap cards; - - /** - * The cards, indexed by their simple name. - */ - CardNameMap simpleNameCards; - - /* - * The sets, indexed by short name. - */ - SetNameMap sets; - - LoadStatus loadStatus; - - QVector availableParsers; - -private: - CardInfoPtr getCardFromMap(const CardNameMap &cardMap, const QString &cardName) const; - void checkUnknownSets(); - void refreshCachedReverseRelatedCards(); - - QBasicMutex *reloadDatabaseMutex = new QBasicMutex(), *clearDatabaseMutex = new QBasicMutex(), - *loadFromFileMutex = new QBasicMutex(), *addCardMutex = new QBasicMutex(), - *removeCardMutex = new QBasicMutex(); - -public: - static const char *TOKENS_SETNAME; - - explicit CardDatabase(QObject *parent = nullptr); - ~CardDatabase() override; - void clear(); - void removeCard(CardInfoPtr card); - [[nodiscard]] CardInfoPtr getCard(const QString &cardName) const; - [[nodiscard]] QList getCards(const QStringList &cardNames) const; - QList getCardsByNameAndProviderId(const QMap &cardNames) const; - [[nodiscard]] CardInfoPtr getCardByNameAndProviderId(const QString &cardName, const QString &providerId) const; - [[nodiscard]] CardInfoPerSet getPreferredSetForCard(const QString &cardName) const; - [[nodiscard]] CardInfoPerSet getSpecificSetForCard(const QString &cardName, const QString &providerId) const; - CardInfoPerSet - getSpecificSetForCard(const QString &cardName, const QString &setShortName, const QString &collectorNumber) const; - QString getPreferredPrintingProviderIdForCard(const QString &cardName); - [[nodiscard]] CardInfoPtr guessCard(const QString &cardName, const QString &providerId = QString()) const; - - /* - * Get a card by its simple name. The name will be simplified in this - * function, so you don't need to simplify it beforehand. - */ - [[nodiscard]] CardInfoPtr getCardBySimpleName(const QString &cardName) const; - - CardSetPtr getSet(const QString &setName); - bool isProviderIdForPreferredPrinting(const QString &cardName, const QString &providerId); - static CardInfoPerSet getSetInfoForCard(const CardInfoPtr &_card); - const CardNameMap &getCardList() const - { - return cards; - } - SetList getSetList() const; - LoadStatus loadFromFile(const QString &fileName); - bool saveCustomTokensToFile(); - QStringList getAllMainCardTypes() const; - LoadStatus getLoadStatus() const - { - return loadStatus; - } - void enableAllUnknownSets(); - void markAllSetsAsKnown(); - void notifyEnabledSetsChanged(); - -public slots: - LoadStatus loadCardDatabases(); - void refreshPreferredPrintings(); - void addCard(CardInfoPtr card); - void addSet(CardSetPtr set); -protected slots: - LoadStatus loadCardDatabase(const QString &path); -signals: - void cardDatabaseLoadingFinished(); - void cardDatabaseLoadingFailed(); - void cardDatabaseNewSetsFound(int numUnknownSets, QStringList unknownSetsNames); - void cardDatabaseAllNewSetsEnabled(); - void cardDatabaseEnabledSetsChanged(); - void cardAdded(CardInfoPtr card); - void cardRemoved(CardInfoPtr card); -}; - class CardRelation : public QObject { Q_OBJECT diff --git a/dbconverter/CMakeLists.txt b/dbconverter/CMakeLists.txt index 78fe36350..ca661376e 100644 --- a/dbconverter/CMakeLists.txt +++ b/dbconverter/CMakeLists.txt @@ -9,6 +9,7 @@ set(dbconverter_SOURCES ../cockatrice/src/game/cards/card_database_parser/card_database_parser.cpp ../cockatrice/src/game/cards/card_database_parser/cockatrice_xml_3.cpp ../cockatrice/src/game/cards/card_database_parser/cockatrice_xml_4.cpp + ../cockatrice/src/game/cards/card_info.cpp ../cockatrice/src/settings/settings_manager.cpp ${VERSION_STRING_CPP} ) diff --git a/oracle/CMakeLists.txt b/oracle/CMakeLists.txt index addfecd78..6f8a7043a 100644 --- a/oracle/CMakeLists.txt +++ b/oracle/CMakeLists.txt @@ -18,6 +18,7 @@ set(oracle_SOURCES src/qt-json/json.cpp ../cockatrice/src/game/cards/card_database.cpp ../cockatrice/src/game/cards/card_database_manager.cpp + ../cockatrice/src/game/cards/card_info.cpp ../cockatrice/src/client/ui/picture_loader/picture_loader.cpp ../cockatrice/src/client/ui/picture_loader/picture_loader_worker.cpp ../cockatrice/src/client/ui/picture_loader/picture_to_load.cpp diff --git a/tests/carddatabase/CMakeLists.txt b/tests/carddatabase/CMakeLists.txt index 3ca812c22..403d14d1d 100644 --- a/tests/carddatabase/CMakeLists.txt +++ b/tests/carddatabase/CMakeLists.txt @@ -22,6 +22,7 @@ add_executable( ../../cockatrice/src/game/cards/card_database_parser/card_database_parser.cpp ../../cockatrice/src/game/cards/card_database_parser/cockatrice_xml_3.cpp ../../cockatrice/src/game/cards/card_database_parser/cockatrice_xml_4.cpp + ../../cockatrice/src/game/cards/card_info.cpp ../../cockatrice/src/settings/settings_manager.cpp carddatabase_test.cpp mocks.cpp @@ -35,6 +36,7 @@ add_executable( ../../cockatrice/src/game/cards/card_database_parser/card_database_parser.cpp ../../cockatrice/src/game/cards/card_database_parser/cockatrice_xml_3.cpp ../../cockatrice/src/game/cards/card_database_parser/cockatrice_xml_4.cpp + ../../cockatrice/src/game/cards/card_info.cpp ../../cockatrice/src/game/filters/filter_card.cpp ../../cockatrice/src/game/filters/filter_string.cpp ../../cockatrice/src/game/filters/filter_tree.cpp