From ea7ab9d5ed756a3aa3ae5ac36f01dbe109b7dc89 Mon Sep 17 00:00:00 2001 From: nordsoft Date: Fri, 1 Sep 2023 04:12:41 +0400 Subject: [PATCH 1/4] Migrate launcher to vcmi versions --- launcher/modManager/cmodlist.cpp | 88 +++++++----------------- launcher/modManager/cmodlist.h | 3 - launcher/modManager/cmodlistview_moc.cpp | 3 +- lib/modding/CModVersion.cpp | 11 +++ lib/modding/CModVersion.h | 2 + 5 files changed, 38 insertions(+), 69 deletions(-) diff --git a/launcher/modManager/cmodlist.cpp b/launcher/modManager/cmodlist.cpp index f04c485e2..8733adc42 100644 --- a/launcher/modManager/cmodlist.cpp +++ b/launcher/modManager/cmodlist.cpp @@ -14,54 +14,7 @@ #include "../../lib/JsonNode.h" #include "../../lib/filesystem/CFileInputStream.h" #include "../../lib/GameConstants.h" - -namespace -{ -bool isCompatible(const QString & verMin, const QString & verMax) -{ - QVersionNumber vcmiVersion(VCMI_VERSION_MAJOR, - VCMI_VERSION_MINOR, - VCMI_VERSION_PATCH); - - auto versionMin = QVersionNumber::fromString(verMin); - auto versionMax = QVersionNumber::fromString(verMax); - - auto buildVersion = [](QVersionNumber & ver) - { - const int maxSections = 3; // versions consist from up to 3 sections, major.minor.patch - - if(ver.segmentCount() < maxSections) - { - auto segments = ver.segments(); - for(int i = segments.size(); i < maxSections; ++i) - segments.append(0); - ver = QVersionNumber(segments); - } - }; - - if(!versionMin.isNull()) - { - buildVersion(versionMin); - if(vcmiVersion < versionMin) - return false; - } - - if(!versionMax.isNull()) - { - buildVersion(versionMax); - if(vcmiVersion > versionMax) - return false; - } - return true; -} -} - -bool CModEntry::compareVersions(QString lesser, QString greater) -{ - auto versionLesser = QVersionNumber::fromString(lesser); - auto versionGreater = QVersionNumber::fromString(greater); - return versionLesser < versionGreater; -} +#include "../../lib/modding/CModVersion.h" QString CModEntry::sizeToString(double size) { @@ -110,18 +63,24 @@ bool CModEntry::isUpdateable() const if(!isInstalled()) return false; - QString installedVer = localData["installedVersion"].toString(); - QString availableVer = repository["latestVersion"].toString(); + auto installedVer = localData["installedVersion"].toString().toStdString(); + auto availableVer = repository["latestVersion"].toString().toStdString(); - if(compareVersions(installedVer, availableVer)) - return true; - return false; + return (CModVersion::fromString(installedVer) < CModVersion::fromString(availableVer)); +} + +bool isCompatible(const QVariantMap & compatibility) +{ + auto compatibleMin = CModVersion::fromString(compatibility["min"].toString().toStdString()); + auto compatibleMax = CModVersion::fromString(compatibility["max"].toString().toStdString()); + + return (compatibleMin.isNull() || CModVersion::GameVersion().compatible(compatibleMin, true, true)) + && (compatibleMax.isNull() || compatibleMax.compatible(CModVersion::GameVersion(), true, true)); } bool CModEntry::isCompatible() const { - auto compatibility = localData["compatibility"].toMap(); - return ::isCompatible(compatibility["min"].toString(), compatibility["max"].toString()); + return ::isCompatible(localData["compatibility"].toMap()); } bool CModEntry::isEssential() const @@ -186,10 +145,10 @@ QVariant CModEntry::getValueImpl(QString value, bool localized) const if(repository.contains(value) && localData.contains(value)) { // value is present in both repo and locally installed. Select one from latest version - QString installedVer = localData["installedVersion"].toString(); - QString availableVer = repository["latestVersion"].toString(); + auto installedVer = localData["installedVersion"].toString().toStdString(); + auto availableVer = repository["latestVersion"].toString().toStdString(); - useRepositoryData = compareVersions(installedVer, availableVer); + useRepositoryData = CModVersion::fromString(installedVer) < CModVersion::fromString(availableVer); } auto & storage = useRepositoryData ? repository : localData; @@ -310,10 +269,8 @@ CModEntry CModList::getMod(QString modname) const if(settings.value("active").toBool()) { - auto compatibility = local.value("compatibility").toMap(); - if(compatibility["min"].isValid() || compatibility["max"].isValid()) - if(!isCompatible(compatibility["min"].toString(), compatibility["max"].toString())) - settings["active"] = false; + if(!::isCompatible(local.value("compatibility").toMap())) + settings["active"] = false; } for(auto entry : repositories) @@ -322,10 +279,11 @@ CModEntry CModList::getMod(QString modname) const if(repoVal.isValid()) { auto repoValMap = repoVal.toMap(); - auto compatibility = repoValMap["compatibility"].toMap(); - if(isCompatible(compatibility["min"].toString(), compatibility["max"].toString())) + if(::isCompatible(repoValMap["compatibility"].toMap())) { - if(repo.empty() || CModEntry::compareVersions(repo["version"].toString(), repoValMap["version"].toString())) + if(repo.empty() + || CModVersion::fromString(repo["version"].toString().toStdString()) + < CModVersion::fromString(repoValMap["version"].toString().toStdString())) { //take valid download link and screenshots before assignment auto download = repo.value("download"); diff --git a/launcher/modManager/cmodlist.h b/launcher/modManager/cmodlist.h index b8a9276ae..4143ed4b8 100644 --- a/launcher/modManager/cmodlist.h +++ b/launcher/modManager/cmodlist.h @@ -74,9 +74,6 @@ public: QVariant getValue(QString value) const; QVariant getBaseValue(QString value) const; - // returns true if less < greater comparing versions section by section - static bool compareVersions(QString lesser, QString greater); - static QString sizeToString(double size); }; diff --git a/launcher/modManager/cmodlistview_moc.cpp b/launcher/modManager/cmodlistview_moc.cpp index 7ecf53ab3..2d3d218d6 100644 --- a/launcher/modManager/cmodlistview_moc.cpp +++ b/launcher/modManager/cmodlistview_moc.cpp @@ -25,6 +25,7 @@ #include "../../lib/CConfigHandler.h" #include "../../lib/Languages.h" +#include "../../lib/modding/CModVersion.h" void CModListView::setupModModel() { @@ -191,7 +192,7 @@ QString CModListView::genChangelogText(CModEntry & mod) std::sort(versions.begin(), versions.end(), [](QString lesser, QString greater) { - return CModEntry::compareVersions(lesser, greater); + return CModVersion::fromString(lesser.toStdString()) < CModVersion::fromString(greater.toStdString()); }); std::reverse(versions.begin(), versions.end()); diff --git a/lib/modding/CModVersion.cpp b/lib/modding/CModVersion.cpp index 0624dc1e7..4f80274bd 100644 --- a/lib/modding/CModVersion.cpp +++ b/lib/modding/CModVersion.cpp @@ -60,4 +60,15 @@ bool CModVersion::isNull() const return major == 0 && minor == 0 && patch == 0; } +bool operator < (const CModVersion & lesser, const CModVersion & greater) +{ + if(lesser.major == greater.major) + { + if(lesser.minor == greater.minor) + return lesser.patch < greater.patch; + return lesser.minor < greater.minor; + } + return lesser.major < greater.major; +} + VCMI_LIB_NAMESPACE_END diff --git a/lib/modding/CModVersion.h b/lib/modding/CModVersion.h index 6e43fb2b6..73c2e724b 100644 --- a/lib/modding/CModVersion.h +++ b/lib/modding/CModVersion.h @@ -42,4 +42,6 @@ struct DLL_LINKAGE CModVersion } }; +DLL_LINKAGE bool operator < (const CModVersion & lesser, const CModVersion & greater); + VCMI_LIB_NAMESPACE_END From e9ba1d73d1aeddea7ae6b076dd9da0dfe94e8e62 Mon Sep 17 00:00:00 2001 From: nordsoft Date: Fri, 1 Sep 2023 04:36:53 +0400 Subject: [PATCH 2/4] Support partial versions --- lib/modding/CModVersion.cpp | 29 ++++++++++++++++++++++++----- lib/modding/CModVersion.h | 8 +++++--- 2 files changed, 29 insertions(+), 8 deletions(-) diff --git a/lib/modding/CModVersion.cpp b/lib/modding/CModVersion.cpp index 4f80274bd..084010602 100644 --- a/lib/modding/CModVersion.cpp +++ b/lib/modding/CModVersion.cpp @@ -20,9 +20,9 @@ CModVersion CModVersion::GameVersion() CModVersion CModVersion::fromString(std::string from) { - int major = 0; - int minor = 0; - int patch = 0; + int major = Any; + int minor = Any; + int patch = Any; try { auto pointPos = from.find('.'); @@ -45,11 +45,29 @@ CModVersion CModVersion::fromString(std::string from) std::string CModVersion::toString() const { - return std::to_string(major) + '.' + std::to_string(minor) + '.' + std::to_string(patch); + std::string res; + if(major != Any) + { + res += std::to_string(major); + if(minor != Any) + { + res += '.' + std::to_string(minor); + if(patch != Any) + res += '.' + std::to_string(patch); + } + } + return res; } bool CModVersion::compatible(const CModVersion & other, bool checkMinor, bool checkPatch) const { + if(minor == Any || other.minor == Any) + checkMinor = false; + if(patch == Any || other.patch == Any) + checkPatch = false; + + assert(checkMinor || !checkPatch); + return (major == other.major && (!checkMinor || minor >= other.minor) && (!checkPatch || minor > other.minor || (minor == other.minor && patch >= other.patch))); @@ -57,11 +75,12 @@ bool CModVersion::compatible(const CModVersion & other, bool checkMinor, bool ch bool CModVersion::isNull() const { - return major == 0 && minor == 0 && patch == 0; + return major == Any; } bool operator < (const CModVersion & lesser, const CModVersion & greater) { + //specific is "greater" than non-specific, that's why do not check for Any value if(lesser.major == greater.major) { if(lesser.minor == greater.minor) diff --git a/lib/modding/CModVersion.h b/lib/modding/CModVersion.h index 73c2e724b..15221dab3 100644 --- a/lib/modding/CModVersion.h +++ b/lib/modding/CModVersion.h @@ -20,9 +20,11 @@ VCMI_LIB_NAMESPACE_BEGIN struct DLL_LINKAGE CModVersion { - int major = 0; - int minor = 0; - int patch = 0; + static const int Any = -1; + + int major = Any; + int minor = Any; + int patch = Any; CModVersion() = default; CModVersion(int mj, int mi, int p): major(mj), minor(mi), patch(p) {} From 15037b782f862c0eac692b9c64f836d1bbb4b593 Mon Sep 17 00:00:00 2001 From: nordsoft Date: Fri, 1 Sep 2023 04:39:32 +0400 Subject: [PATCH 3/4] Fix assert --- lib/modding/CModVersion.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/modding/CModVersion.cpp b/lib/modding/CModVersion.cpp index 084010602..b44d51c6d 100644 --- a/lib/modding/CModVersion.cpp +++ b/lib/modding/CModVersion.cpp @@ -66,7 +66,7 @@ bool CModVersion::compatible(const CModVersion & other, bool checkMinor, bool ch if(patch == Any || other.patch == Any) checkPatch = false; - assert(checkMinor || !checkPatch); + assert(!checkPatch || (checkPatch && checkMinor)); return (major == other.major && (!checkMinor || minor >= other.minor) && From 8040cafb3d9687c3945cd5a8c26d5cedb4b3941e Mon Sep 17 00:00:00 2001 From: nordsoft Date: Fri, 1 Sep 2023 15:17:46 +0400 Subject: [PATCH 4/4] Code review tweaks --- lib/modding/CModVersion.cpp | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/lib/modding/CModVersion.cpp b/lib/modding/CModVersion.cpp index b44d51c6d..3ed3640a8 100644 --- a/lib/modding/CModVersion.cpp +++ b/lib/modding/CModVersion.cpp @@ -61,16 +61,14 @@ std::string CModVersion::toString() const bool CModVersion::compatible(const CModVersion & other, bool checkMinor, bool checkPatch) const { - if(minor == Any || other.minor == Any) - checkMinor = false; - if(patch == Any || other.patch == Any) - checkPatch = false; + bool doCheckMinor = checkMinor && minor != Any && other.minor != Any; + bool doCheckPatch = checkPatch && patch != Any && other.patch != Any; - assert(!checkPatch || (checkPatch && checkMinor)); + assert(!doCheckPatch || (doCheckPatch && doCheckMinor)); return (major == other.major && - (!checkMinor || minor >= other.minor) && - (!checkPatch || minor > other.minor || (minor == other.minor && patch >= other.patch))); + (!doCheckMinor || minor >= other.minor) && + (!doCheckPatch || minor > other.minor || (minor == other.minor && patch >= other.patch))); } bool CModVersion::isNull() const