#include "StdInc.h" #include "cmodlist.h" #include "../../lib/JsonNode.h" #include "../../lib/filesystem/CFileInputStream.h" bool CModEntry::compareVersions(QString lesser, QString greater) { static const int maxSections = 3; // versions consist from up to 3 sections, major.minor.patch QStringList lesserList = lesser.split("."); QStringList greaterList = greater.split("."); assert(lesserList.size() <= maxSections); assert(greaterList.size() <= maxSections); for (int i=0; i< maxSections; i++) { if (greaterList.size() <= i) // 1.1.1 > 1.1 return false; if (lesserList.size() <= i) // 1.1 < 1.1.1 return true; if (lesserList[i].toInt() != greaterList[i].toInt()) return lesserList[i].toInt() < greaterList[i].toInt(); // 1.1 < 1.2 } return false; } QString CModEntry::sizeToString(double size) { static const QString sizes[] = { /*"%1 B", */"%1 KiB", "%1 MiB", "%1 GiB", "%1 TiB" }; size_t index = 0; while (size > 1024 && index < 4) { size /= 1024; index++; } return sizes[index].arg(QString::number(size, 'f', 1)); } CModEntry::CModEntry(QVariantMap repository, QVariantMap localData, QVariantMap modSettings, QString modname): repository(repository), localData(localData), modSettings(modSettings), modname(modname) { } bool CModEntry::isEnabled() const { if (!isInstalled()) return false; return modSettings["active"].toBool(); } bool CModEntry::isDisabled() const { if (!isInstalled()) return false; return !isEnabled(); } bool CModEntry::isAvailable() const { if (isInstalled()) return false; return !repository.isEmpty(); } bool CModEntry::isUpdateable() const { if (!isInstalled()) return false; QString installedVer = localData["installedVersion"].toString(); QString availableVer = repository["latestVersion"].toString(); if (compareVersions(installedVer, availableVer)) return true; return false; } bool CModEntry::isInstalled() const { return !localData.isEmpty(); } int CModEntry::getModStatus() const { return (isEnabled() ? ModStatus::ENABLED : 0) | (isInstalled() ? ModStatus::INSTALLED : 0) | (isUpdateable()? ModStatus::UPDATEABLE : 0); } QString CModEntry::getName() const { return modname; } QVariant CModEntry::getValue(QString value) 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(); if (compareVersions(installedVer, availableVer)) return repository[value]; else return localData[value]; } if (repository.contains(value)) return repository[value]; if (localData.contains(value)) return localData[value]; return QVariant(); } QVariantMap CModList::copyField(QVariantMap data, QString from, QString to) { QVariantMap renamed; for (auto it = data.begin(); it != data.end(); it++) { QVariantMap modConf = it.value().toMap(); modConf.insert(to, modConf.value(from)); renamed.insert(it.key(), modConf); } return renamed; } void CModList::resetRepositories() { repositories.clear(); } void CModList::addRepository(QVariantMap data) { repositories.push_back(copyField(data, "version", "latestVersion")); } void CModList::setLocalModList(QVariantMap data) { localModList = copyField(data, "version", "installedVersion"); } void CModList::setModSettings(QVariant data) { modSettings = data.toMap(); } void CModList::modChanged(QString modID) { } static QVariant getValue(QVariantMap input, QString path) { if (path.size() > 1) { QString entryName = path.section('/', 0, 1); QString remainder = "/" + path.section('/', 2, -1); entryName.remove(0, 1); return getValue(input.value(entryName).toMap(), remainder); } else { return input; } } CModEntry CModList::getMod(QString modname) const { QVariantMap repo; QVariantMap local = localModList[modname].toMap(); QVariantMap settings; QString path = modname; path = "/" + path.replace(".", "/mods/"); QVariant conf = getValue(modSettings, path); if (conf.isNull()) { settings["active"] = true; // default } else { if (conf.canConvert()) settings = conf.toMap(); else settings.insert("active", conf); } for (auto entry : repositories) { QVariant repoVal = getValue(entry, path); if (repoVal.isValid()) { if (repo.empty()) repo = repoVal.toMap(); else { if (CModEntry::compareVersions(repo["version"].toString(), repoVal.toMap()["version"].toString())) repo = repoVal.toMap(); } } } return CModEntry(repo, local, settings, modname); } bool CModList::hasMod(QString modname) const { if (localModList.contains(modname)) return true; for (auto entry : repositories) if (entry.contains(modname)) return true; return false; } QStringList CModList::getRequirements(QString modname) { QStringList ret; if (hasMod(modname)) { auto mod = getMod(modname); for (auto entry : mod.getValue("depends").toStringList()) ret += getRequirements(entry); } ret += modname; return ret; } QVector CModList::getModList() const { QSet knownMods; QVector modList; for (auto repo : repositories) { for (auto it = repo.begin(); it != repo.end(); it++) { knownMods.insert(it.key()); } } for (auto it = localModList.begin(); it != localModList.end(); it++) { knownMods.insert(it.key()); } for (auto entry : knownMods) { modList.push_back(entry); } return modList; }