/* * ModDescription.cpp, part of VCMI engine * * Authors: listed in file AUTHORS in main folder * * License: GNU General Public License v2.0 or later * Full text of license available in license.txt file, in main folder * */ #include "StdInc.h" #include "ModDescription.h" #include "CModVersion.h" #include "ModVerificationInfo.h" #include "../json/JsonNode.h" #include "../texts/CGeneralTextHandler.h" VCMI_LIB_NAMESPACE_BEGIN ModDescription::ModDescription(const TModID & fullID, const JsonNode & localConfig, const JsonNode & repositoryConfig) : identifier(fullID) , localConfig(std::make_unique(localConfig)) , repositoryConfig(std::make_unique(repositoryConfig)) , dependencies(loadModList(getValue("depends"))) , softDependencies(loadModList(getValue("softDepends"))) , conflicts(loadModList(getValue("conflicts"))) { if(getID() != "core") dependencies.emplace("core"); if (!getParentID().empty()) dependencies.emplace(getParentID()); } ModDescription::~ModDescription() = default; TModSet ModDescription::loadModList(const JsonNode & configNode) const { TModSet result; for(const auto & entry : configNode.Vector()) result.insert(boost::algorithm::to_lower_copy(entry.String())); return result; } const TModID & ModDescription::getID() const { return identifier; } TModID ModDescription::getParentID() const { size_t dotPos = identifier.find_last_of('.'); if(dotPos == std::string::npos) return {}; return identifier.substr(0, dotPos); } TModID ModDescription::getTopParentID() const { size_t dotPos = identifier.find('.'); if(dotPos == std::string::npos) return {}; return identifier.substr(0, dotPos); } const TModSet & ModDescription::getDependencies() const { return dependencies; } const TModSet & ModDescription::getSoftDependencies() const { return softDependencies; } const TModSet & ModDescription::getConflicts() const { return conflicts; } const std::string & ModDescription::getBaseLanguage() const { static const std::string defaultLanguage = "english"; return getValue("language").isString() ? getValue("language").String() : defaultLanguage; } const std::string & ModDescription::getName() const { return getLocalizedValue("name").String(); } const JsonNode & ModDescription::getFilesystemConfig() const { return getLocalValue("filesystem"); } const JsonNode & ModDescription::getLocalConfig() const { return *localConfig; } const JsonNode & ModDescription::getLocalizedValue(const std::string & keyName) const { const std::string language = CGeneralTextHandler::getPreferredLanguage(); const JsonNode & languageNode = getValue(language); const JsonNode & baseValue = getValue(keyName); const JsonNode & localizedValue = languageNode[keyName]; if (localizedValue.isNull()) return baseValue; else return localizedValue; } const JsonNode & ModDescription::getValue(const std::string & keyName) const { if (!isInstalled() || isUpdateAvailable()) return getRepositoryValue(keyName); else return getLocalValue(keyName); } const JsonNode & ModDescription::getLocalValue(const std::string & keyName) const { return getLocalConfig()[keyName]; } const JsonNode & ModDescription::getRepositoryValue(const std::string & keyName) const { return (*repositoryConfig)[keyName]; } CModVersion ModDescription::getVersion() const { return CModVersion::fromString(getValue("version").String()); } ModVerificationInfo ModDescription::getVerificationInfo() const { ModVerificationInfo result; result.name = getName(); result.version = getVersion(); result.impactsGameplay = affectsGameplay(); result.parent = getParentID(); return result; } bool ModDescription::isCompatible() const { const JsonNode & compatibility = getValue("compatibility"); if (compatibility.isNull()) return true; auto vcmiCompatibleMin = CModVersion::fromString(compatibility["min"].String()); auto vcmiCompatibleMax = CModVersion::fromString(compatibility["max"].String()); bool compatible = true; compatible &= (vcmiCompatibleMin.isNull() || CModVersion::GameVersion().compatible(vcmiCompatibleMin, true, true)); compatible &= (vcmiCompatibleMax.isNull() || vcmiCompatibleMax.compatible(CModVersion::GameVersion(), true, true)); return compatible; } bool ModDescription::isCompatibility() const { return getValue("modType").String() == "Compatibility"; } bool ModDescription::isTranslation() const { return getValue("modType").String() == "Translation"; } bool ModDescription::keepDisabled() const { return getValue("keepDisabled").Bool(); } bool ModDescription::isInstalled() const { return !localConfig->isNull(); } bool ModDescription::affectsGameplay() const { static const std::array keysToTest = { "artifacts", "battlefields", "creatures", "factions", "heroClasses", "heroes", "objects", "obstacles", "rivers", "roads", "settings", "skills", "spells", "terrains", }; for(const auto & key : keysToTest) if (!getLocalValue(key).isNull()) return true; return false; } bool ModDescription::isUpdateAvailable() const { if (getRepositoryValue("version").isNull()) return false; if (getLocalValue("version").isNull()) return false; auto localVersion = CModVersion::fromString(getLocalValue("version").String()); auto repositoryVersion = CModVersion::fromString(getRepositoryValue("version").String()); return localVersion < repositoryVersion; } VCMI_LIB_NAMESPACE_END