mirror of
https://github.com/vcmi/vcmi.git
synced 2025-02-03 13:01:33 +02:00
Restored all disabled mod functinality that was used by client
This commit is contained in:
parent
67fdd14dca
commit
87a665fb7f
@ -362,17 +362,6 @@ void CMainMenu::update()
|
||||
menu->switchToTab(menu->getActiveTab());
|
||||
}
|
||||
|
||||
static bool warnedAboutModDependencies = false;
|
||||
|
||||
if (!warnedAboutModDependencies)
|
||||
{
|
||||
warnedAboutModDependencies = true;
|
||||
auto errorMessages = CGI->modh->getModLoadErrors();
|
||||
|
||||
if (!errorMessages.empty())
|
||||
CInfoWindow::showInfoDialog(errorMessages, std::vector<std::shared_ptr<CComponent>>(), PlayerColor(1));
|
||||
}
|
||||
|
||||
// Handles mouse and key input
|
||||
GH.handleEvents();
|
||||
GH.windows().simpleRedraw();
|
||||
|
@ -809,7 +809,7 @@ void CModListView::installFiles(QStringList files)
|
||||
if(!modJsonUrl.isNull())
|
||||
downloadFile(QString::fromStdString(modName + ".json"), QString::fromStdString(modJsonUrl.String()), tr("mods repository index"));
|
||||
|
||||
repository[modNameLower] = repoData;
|
||||
repository[modNameLower] = modJson;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -38,19 +38,14 @@ CModHandler::~CModHandler() = default;
|
||||
|
||||
std::vector<std::string> CModHandler::getAllMods() const
|
||||
{
|
||||
return modManager->getActiveMods();// TODO: currently identical to active
|
||||
return modManager->getAllMods();
|
||||
}
|
||||
|
||||
std::vector<std::string> CModHandler::getActiveMods() const
|
||||
const std::vector<std::string> & CModHandler::getActiveMods() const
|
||||
{
|
||||
return modManager->getActiveMods();
|
||||
}
|
||||
|
||||
std::string CModHandler::getModLoadErrors() const
|
||||
{
|
||||
return ""; // TODO: modLoadErrors->toString();
|
||||
}
|
||||
|
||||
const ModDescription & CModHandler::getModInfo(const TModID & modId) const
|
||||
{
|
||||
return modManager->getModDescription(modId);
|
||||
@ -86,35 +81,6 @@ static ISimpleResourceLoader * genModFilesystem(const std::string & modName, con
|
||||
return CResourceHandler::createFileSystem(getModDirectory(modName), defaultFS);
|
||||
}
|
||||
|
||||
//static ui32 calculateModChecksum(const std::string & modName, ISimpleResourceLoader * filesystem)
|
||||
//{
|
||||
// boost::crc_32_type modChecksum;
|
||||
// // first - add current VCMI version into checksum to force re-validation on VCMI updates
|
||||
// modChecksum.process_bytes(reinterpret_cast<const void*>(GameConstants::VCMI_VERSION.data()), GameConstants::VCMI_VERSION.size());
|
||||
//
|
||||
// // second - add mod.json into checksum because filesystem does not contains this file
|
||||
// // FIXME: remove workaround for core mod
|
||||
// if (modName != ModScope::scopeBuiltin())
|
||||
// {
|
||||
// auto modConfFile = CModInfo::getModFile(modName);
|
||||
// ui32 configChecksum = CResourceHandler::get("initial")->load(modConfFile)->calculateCRC32();
|
||||
// modChecksum.process_bytes(reinterpret_cast<const void *>(&configChecksum), sizeof(configChecksum));
|
||||
// }
|
||||
// // third - add all detected text files from this mod into checksum
|
||||
// auto files = filesystem->getFilteredFiles([](const ResourcePath & resID)
|
||||
// {
|
||||
// return (resID.getType() == EResType::TEXT || resID.getType() == EResType::JSON) &&
|
||||
// ( boost::starts_with(resID.getName(), "DATA") || boost::starts_with(resID.getName(), "CONFIG"));
|
||||
// });
|
||||
//
|
||||
// for (const ResourcePath & file : files)
|
||||
// {
|
||||
// ui32 fileChecksum = filesystem->load(file)->calculateCRC32();
|
||||
// modChecksum.process_bytes(reinterpret_cast<const void *>(&fileChecksum), sizeof(fileChecksum));
|
||||
// }
|
||||
// return modChecksum.checksum();
|
||||
//}
|
||||
|
||||
void CModHandler::loadModFilesystems()
|
||||
{
|
||||
CGeneralTextHandler::detectInstallParameters();
|
||||
@ -250,7 +216,7 @@ std::set<TModID> CModHandler::getModEnabledSoftDependencies(const TModID & modId
|
||||
{
|
||||
std::set<TModID> softDependencies = getModSoftDependencies(modId);
|
||||
|
||||
vstd::erase_if(softDependencies, [&](const TModID & dependency){ return !modManager->isModActive(dependency);});
|
||||
vstd::erase_if(softDependencies, [this](const TModID & dependency){ return !modManager->isModActive(dependency);});
|
||||
|
||||
return softDependencies;
|
||||
}
|
||||
@ -285,18 +251,41 @@ void CModHandler::load()
|
||||
|
||||
content->init();
|
||||
|
||||
// for(const TModID & modName : getActiveMods())
|
||||
// {
|
||||
// logMod->trace("Generating checksum for %s", modName);
|
||||
// allMods[modName].updateChecksum(calculateModChecksum(modName, CResourceHandler::get(modName)));
|
||||
// }
|
||||
const auto & activeMods = getActiveMods();
|
||||
|
||||
for(const TModID & modName : getActiveMods())
|
||||
content->preloadData(getModInfo(modName));
|
||||
validationPassed.insert(activeMods.begin(), activeMods.end());
|
||||
|
||||
for(const TModID & modName : activeMods)
|
||||
{
|
||||
modChecksums[modName] = this->modManager->computeChecksum(modName);
|
||||
}
|
||||
|
||||
for(const TModID & modName : activeMods)
|
||||
{
|
||||
const auto & modInfo = getModInfo(modName);
|
||||
bool isValid = content->preloadData(modInfo, isModValidationNeeded(modInfo));
|
||||
if (isValid)
|
||||
logGlobal->info("\t\tParsing mod: OK (%s)", modInfo.getName());
|
||||
else
|
||||
logGlobal->warn("\t\tParsing mod: Issues found! (%s)", modInfo.getName());
|
||||
|
||||
if (!isValid)
|
||||
validationPassed.erase(modName);
|
||||
}
|
||||
logMod->info("\tParsing mod data");
|
||||
|
||||
for(const TModID & modName : getActiveMods())
|
||||
content->load(getModInfo(modName));
|
||||
for(const TModID & modName : activeMods)
|
||||
{
|
||||
const auto & modInfo = getModInfo(modName);
|
||||
bool isValid = content->load(getModInfo(modName), isModValidationNeeded(getModInfo(modName)));
|
||||
if (isValid)
|
||||
logGlobal->info("\t\tLoading mod: OK (%s)", modInfo.getName());
|
||||
else
|
||||
logGlobal->warn("\t\tLoading mod: Issues found! (%s)", modInfo.getName());
|
||||
|
||||
if (!isValid)
|
||||
validationPassed.erase(modName);
|
||||
}
|
||||
|
||||
#if SCRIPTING_ENABLED
|
||||
VLC->scriptHandler->performRegistration(VLC);//todo: this should be done before any other handlers load
|
||||
@ -304,7 +293,7 @@ void CModHandler::load()
|
||||
|
||||
content->loadCustom();
|
||||
|
||||
for(const TModID & modName : getActiveMods())
|
||||
for(const TModID & modName : activeMods)
|
||||
loadTranslation(modName);
|
||||
|
||||
logMod->info("\tLoading mod data");
|
||||
@ -319,21 +308,30 @@ void CModHandler::load()
|
||||
|
||||
void CModHandler::afterLoad(bool onlyEssential)
|
||||
{
|
||||
//JsonNode modSettings;
|
||||
//for (auto & modEntry : getActiveMods())
|
||||
//{
|
||||
// std::string pointer = "/" + boost::algorithm::replace_all_copy(modEntry.first, ".", "/mods/");
|
||||
JsonNode modSettings;
|
||||
for (auto & modEntry : getActiveMods())
|
||||
{
|
||||
if (validationPassed.count(modEntry))
|
||||
modManager->setValidatedChecksum(modEntry, modChecksums.at(modEntry));
|
||||
else
|
||||
modManager->setValidatedChecksum(modEntry, std::nullopt);
|
||||
}
|
||||
|
||||
// modSettings["activeMods"].resolvePointer(pointer) = modEntry.second.saveLocalData();
|
||||
//}
|
||||
//modSettings[ModScope::scopeBuiltin()] = coreMod->saveLocalData();
|
||||
//modSettings[ModScope::scopeBuiltin()]["name"].String() = "Original game files";
|
||||
modManager->saveConfigurationState();
|
||||
}
|
||||
|
||||
//if(!onlyEssential)
|
||||
//{
|
||||
// std::fstream file(CResourceHandler::get()->getResourceName(ResourcePath("config/modSettings.json"))->c_str(), std::ofstream::out | std::ofstream::trunc);
|
||||
// file << modSettings.toString();
|
||||
//}
|
||||
bool CModHandler::isModValidationNeeded(const ModDescription & mod) const
|
||||
{
|
||||
if (settings["mods"]["validation"].String() == "full")
|
||||
return true;
|
||||
|
||||
if (modManager->getValidatedChecksum(mod.getID()) == modChecksums.at(mod.getID()))
|
||||
return false;
|
||||
|
||||
if (settings["mods"]["validation"].String() == "off")
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
VCMI_LIB_NAMESPACE_END
|
||||
|
@ -23,12 +23,16 @@ using TModID = std::string;
|
||||
class DLL_LINKAGE CModHandler final : boost::noncopyable
|
||||
{
|
||||
std::unique_ptr<ModManager> modManager;
|
||||
std::map<std::string, uint32_t> modChecksums;
|
||||
std::set<std::string> validationPassed;
|
||||
|
||||
void loadTranslation(const TModID & modName);
|
||||
void checkModFilesystemsConflicts(const std::map<TModID, ISimpleResourceLoader *> & modFilesystems);
|
||||
|
||||
bool isModValidationNeeded(const ModDescription & mod) const;
|
||||
|
||||
public:
|
||||
std::shared_ptr<CContentHandler> content; //FIXME: make private
|
||||
std::shared_ptr<CContentHandler> content;
|
||||
|
||||
/// receives list of available mods and trying to load mod.json from all of them
|
||||
void initializeConfig();
|
||||
@ -52,11 +56,8 @@ public:
|
||||
|
||||
/// returns list of all (active) mods
|
||||
std::vector<std::string> getAllMods() const;
|
||||
std::vector<std::string> getActiveMods() const;
|
||||
const std::vector<std::string> & getActiveMods() const;
|
||||
|
||||
/// Returns human-readable string that describes errors encounter during mod loading, such as missing dependencies
|
||||
std::string getModLoadErrors() const;
|
||||
|
||||
const ModDescription & getModInfo(const TModID & modId) const;
|
||||
|
||||
/// load content from all available mods
|
||||
|
@ -55,7 +55,7 @@ ContentTypeHandler::ContentTypeHandler(IHandlerBase * handler, const std::string
|
||||
|
||||
bool ContentTypeHandler::preloadModData(const std::string & modName, const JsonNode & fileList, bool validate)
|
||||
{
|
||||
bool result = false;
|
||||
bool result = true;
|
||||
JsonNode data = JsonUtils::assembleFromFiles(fileList, result);
|
||||
data.setModScope(modName);
|
||||
|
||||
@ -259,22 +259,28 @@ void CContentHandler::init()
|
||||
handlers.insert(std::make_pair("biomes", ContentTypeHandler(VLC->biomeHandler.get(), "biome")));
|
||||
}
|
||||
|
||||
bool CContentHandler::preloadModData(const std::string & modName, JsonNode modConfig, bool validate)
|
||||
bool CContentHandler::preloadData(const ModDescription & mod, bool validate)
|
||||
{
|
||||
bool result = true;
|
||||
if (validate && mod.getID() != ModScope::scopeBuiltin()) // TODO: remove workaround
|
||||
{
|
||||
if (!JsonUtils::validate(mod.getLocalConfig(), "vcmi:mod", mod.getID()))
|
||||
result = false;
|
||||
}
|
||||
|
||||
for(auto & handler : handlers)
|
||||
{
|
||||
result &= handler.second.preloadModData(modName, modConfig[handler.first], validate);
|
||||
result &= handler.second.preloadModData(mod.getID(), mod.getLocalValue(handler.first), validate);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
bool CContentHandler::loadMod(const std::string & modName, bool validate)
|
||||
bool CContentHandler::load(const ModDescription & mod, bool validate)
|
||||
{
|
||||
bool result = true;
|
||||
for(auto & handler : handlers)
|
||||
{
|
||||
result &= handler.second.loadMod(modName, validate);
|
||||
result &= handler.second.loadMod(mod.getID(), validate);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@ -295,62 +301,9 @@ void CContentHandler::afterLoadFinalization()
|
||||
}
|
||||
}
|
||||
|
||||
void CContentHandler::preloadData(const ModDescription & mod)
|
||||
{
|
||||
preloadModData(mod.getID(), mod.getLocalConfig(), false);
|
||||
|
||||
// bool validate = validateMod(mod);
|
||||
//
|
||||
// // print message in format [<8-symbols checksum>] <modname>
|
||||
// auto & info = mod.getVerificationInfo();
|
||||
// logMod->info("\t\t[%08x]%s", info.checksum, info.name);
|
||||
//
|
||||
// if (validate && mod.identifier != ModScope::scopeBuiltin())
|
||||
// {
|
||||
// if (!JsonUtils::validate(mod.config, "vcmi:mod", mod.identifier))
|
||||
// mod.validation = CModInfo::FAILED;
|
||||
// }
|
||||
// if (!preloadModData(mod.identifier, mod.config, validate))
|
||||
// mod.validation = CModInfo::FAILED;
|
||||
}
|
||||
|
||||
void CContentHandler::load(const ModDescription & mod)
|
||||
{
|
||||
loadMod(mod.getID(), false);
|
||||
|
||||
// bool validate = validateMod(mod);
|
||||
//
|
||||
// if (!loadMod(mod.identifier, validate))
|
||||
// mod.validation = CModInfo::FAILED;
|
||||
//
|
||||
// if (validate)
|
||||
// {
|
||||
// if (mod.validation != CModInfo::FAILED)
|
||||
// logMod->info("\t\t[DONE] %s", mod.getVerificationInfo().name);
|
||||
// else
|
||||
// logMod->error("\t\t[FAIL] %s", mod.getVerificationInfo().name);
|
||||
// }
|
||||
// else
|
||||
// logMod->info("\t\t[SKIP] %s", mod.getVerificationInfo().name);
|
||||
}
|
||||
|
||||
const ContentTypeHandler & CContentHandler::operator[](const std::string & name) const
|
||||
{
|
||||
return handlers.at(name);
|
||||
}
|
||||
|
||||
bool CContentHandler::validateMod(const ModDescription & mod) const
|
||||
{
|
||||
if (settings["mods"]["validation"].String() == "full")
|
||||
return true;
|
||||
|
||||
// if (mod.validation == CModInfo::PASSED)
|
||||
// return false;
|
||||
|
||||
if (settings["mods"]["validation"].String() == "off")
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
VCMI_LIB_NAMESPACE_END
|
||||
|
@ -50,23 +50,16 @@ public:
|
||||
/// class used to load all game data into handlers. Used only during loading
|
||||
class DLL_LINKAGE CContentHandler
|
||||
{
|
||||
/// preloads all data from fileList as data from modName.
|
||||
bool preloadModData(const std::string & modName, JsonNode modConfig, bool validate);
|
||||
|
||||
/// actually loads data in mod
|
||||
bool loadMod(const std::string & modName, bool validate);
|
||||
|
||||
std::map<std::string, ContentTypeHandler> handlers;
|
||||
|
||||
bool validateMod(const ModDescription & mod) const;
|
||||
public:
|
||||
void init();
|
||||
|
||||
/// preloads all data from fileList as data from modName.
|
||||
void preloadData(const ModDescription & mod);
|
||||
bool preloadData(const ModDescription & mod, bool validateMod);
|
||||
|
||||
/// actually loads data in mod
|
||||
void load(const ModDescription & mod);
|
||||
bool load(const ModDescription & mod, bool validateMod);
|
||||
|
||||
void loadCustom();
|
||||
|
||||
|
@ -26,7 +26,7 @@ ModDescription::ModDescription(const TModID & fullID, const JsonNode & localConf
|
||||
, conflicts(loadModList(getValue("conflicts")))
|
||||
{
|
||||
if(getID() != "core")
|
||||
dependencies.insert("core");
|
||||
dependencies.emplace("core");
|
||||
}
|
||||
|
||||
ModDescription::~ModDescription() = default;
|
||||
|
@ -21,10 +21,11 @@ using TModSet = std::set<TModID>;
|
||||
|
||||
class DLL_LINKAGE ModDescription : boost::noncopyable
|
||||
{
|
||||
TModID identifier;
|
||||
|
||||
std::unique_ptr<JsonNode> localConfig;
|
||||
std::unique_ptr<JsonNode> repositoryConfig;
|
||||
|
||||
TModID identifier;
|
||||
TModSet dependencies;
|
||||
TModSet softDependencies;
|
||||
TModSet conflicts;
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include "ModDescription.h"
|
||||
#include "ModScope.h"
|
||||
|
||||
#include "../constants/StringConstants.h"
|
||||
#include "../filesystem/Filesystem.h"
|
||||
#include "../json/JsonNode.h"
|
||||
#include "../texts/CGeneralTextHandler.h"
|
||||
@ -49,17 +50,45 @@ ModsState::ModsState()
|
||||
|
||||
for(const auto & submod : scanModsDirectory(getModSettingsDirectory(target)))
|
||||
testLocations.push_back(target + '.' + submod);
|
||||
|
||||
// TODO: check that this is vcmi mod and not era mod?
|
||||
// TODO: check that mod name is not reserved (ModScope::isScopeReserved(modFullName)))
|
||||
}
|
||||
}
|
||||
|
||||
TModList ModsState::getAllMods() const
|
||||
TModList ModsState::getInstalledMods() const
|
||||
{
|
||||
return modList;
|
||||
}
|
||||
|
||||
uint32_t ModsState::computeChecksum(const TModID & modName) const
|
||||
{
|
||||
boost::crc_32_type modChecksum;
|
||||
// first - add current VCMI version into checksum to force re-validation on VCMI updates
|
||||
modChecksum.process_bytes(reinterpret_cast<const void*>(GameConstants::VCMI_VERSION.data()), GameConstants::VCMI_VERSION.size());
|
||||
|
||||
// second - add mod.json into checksum because filesystem does not contains this file
|
||||
// FIXME: remove workaround for core mod
|
||||
if (modName != ModScope::scopeBuiltin())
|
||||
{
|
||||
auto modConfFile = getModDescriptionFile(modName);
|
||||
ui32 configChecksum = CResourceHandler::get("initial")->load(modConfFile)->calculateCRC32();
|
||||
modChecksum.process_bytes(reinterpret_cast<const void *>(&configChecksum), sizeof(configChecksum));
|
||||
}
|
||||
|
||||
// third - add all detected text files from this mod into checksum
|
||||
const auto & filesystem = CResourceHandler::get(modName);
|
||||
|
||||
auto files = filesystem->getFilteredFiles([](const ResourcePath & resID)
|
||||
{
|
||||
return resID.getType() == EResType::JSON && boost::starts_with(resID.getName(), "CONFIG");
|
||||
});
|
||||
|
||||
for (const ResourcePath & file : files)
|
||||
{
|
||||
ui32 fileChecksum = filesystem->load(file)->calculateCRC32();
|
||||
modChecksum.process_bytes(reinterpret_cast<const void *>(&fileChecksum), sizeof(fileChecksum));
|
||||
}
|
||||
return modChecksum.checksum();
|
||||
}
|
||||
|
||||
std::vector<TModID> ModsState::scanModsDirectory(const std::string & modDir) const
|
||||
{
|
||||
size_t depth = boost::range::count(modDir, '/');
|
||||
@ -90,6 +119,9 @@ std::vector<TModID> ModsState::scanModsDirectory(const std::string & modDir) con
|
||||
if(name.find('.') != std::string::npos)
|
||||
continue;
|
||||
|
||||
if (ModScope::isScopeReserved(boost::to_lower_copy(name)))
|
||||
continue;
|
||||
|
||||
if(!CResourceHandler::get("initial")->existsResource(JsonPath::builtin(entry.getName() + "/MOD")))
|
||||
continue;
|
||||
|
||||
@ -123,20 +155,14 @@ ModsPresetState::ModsPresetState()
|
||||
else
|
||||
importInitialPreset(); // 1.5 format import
|
||||
|
||||
saveConfiguration(modConfig);
|
||||
saveConfigurationState();
|
||||
}
|
||||
}
|
||||
|
||||
void ModsPresetState::saveConfiguration(const JsonNode & modSettings)
|
||||
{
|
||||
std::fstream file(CResourceHandler::get()->getResourceName(ResourcePath("config/modSettings.json"))->c_str(), std::ofstream::out | std::ofstream::trunc);
|
||||
file << modSettings.toString();
|
||||
}
|
||||
|
||||
void ModsPresetState::createInitialPreset()
|
||||
{
|
||||
// TODO: scan mods directory for all its content? Probably unnecessary since this looks like new install, but who knows?
|
||||
modConfig["presets"]["default"]["mods"].Vector().push_back(JsonNode("vcmi"));
|
||||
modConfig["presets"]["default"]["mods"].Vector().emplace_back("vcmi");
|
||||
}
|
||||
|
||||
void ModsPresetState::importInitialPreset()
|
||||
@ -146,7 +172,7 @@ void ModsPresetState::importInitialPreset()
|
||||
for(const auto & mod : modConfig["activeMods"].Struct())
|
||||
{
|
||||
if(mod.second["active"].Bool())
|
||||
preset["mods"].Vector().push_back(JsonNode(mod.first));
|
||||
preset["mods"].Vector().emplace_back(mod.first);
|
||||
|
||||
for(const auto & submod : mod.second["mods"].Struct())
|
||||
preset["settings"][mod.first][submod.first] = submod.second["active"];
|
||||
@ -176,6 +202,15 @@ std::map<TModID, bool> ModsPresetState::getModSettings(const TModID & modID) con
|
||||
return modSettings;
|
||||
}
|
||||
|
||||
std::optional<uint32_t> ModsPresetState::getValidatedChecksum(const TModID & modName) const
|
||||
{
|
||||
const JsonNode & node = modConfig["validatedMods"][modName];
|
||||
if (node.isNull())
|
||||
return std::nullopt;
|
||||
else
|
||||
return node.Integer();
|
||||
}
|
||||
|
||||
void ModsPresetState::setSettingActiveInPreset(const TModID & modName, const TModID & settingName, bool isActive)
|
||||
{
|
||||
const std::string & currentPresetName = modConfig["activePreset"].String();
|
||||
@ -212,6 +247,20 @@ std::vector<TModID> ModsPresetState::getActiveMods() const
|
||||
return allActiveMods;
|
||||
}
|
||||
|
||||
void ModsPresetState::setValidatedChecksum(const TModID & modName, std::optional<uint32_t> value)
|
||||
{
|
||||
if (value.has_value())
|
||||
modConfig["validatedMods"][modName].Integer() = *value;
|
||||
else
|
||||
modConfig["validatedMods"].Struct().erase(modName);
|
||||
}
|
||||
|
||||
void ModsPresetState::saveConfigurationState() const
|
||||
{
|
||||
std::fstream file(CResourceHandler::get()->getResourceName(ResourcePath("config/modSettings.json"))->c_str(), std::ofstream::out | std::ofstream::trunc);
|
||||
file << modConfig.toCompactString();
|
||||
}
|
||||
|
||||
ModsStorage::ModsStorage(const std::vector<TModID> & modsToLoad, const JsonNode & repositoryList)
|
||||
{
|
||||
JsonNode coreModConfig(JsonPath::builtin("config/gameConfig.json"));
|
||||
@ -221,10 +270,7 @@ ModsStorage::ModsStorage(const std::vector<TModID> & modsToLoad, const JsonNode
|
||||
for(auto modID : modsToLoad)
|
||||
{
|
||||
if(ModScope::isScopeReserved(modID))
|
||||
{
|
||||
logMod->error("Can not load mod %s - this name is reserved for internal use!", modID);
|
||||
continue;
|
||||
}
|
||||
|
||||
JsonNode modConfig(getModDescriptionFile(modID));
|
||||
modConfig.setModScope(modID);
|
||||
@ -273,10 +319,10 @@ ModManager::ModManager(const JsonNode & repositoryList)
|
||||
: modsState(std::make_unique<ModsState>())
|
||||
, modsPreset(std::make_unique<ModsPresetState>())
|
||||
{
|
||||
//TODO: load only active mods & all their submods in game mode?
|
||||
modsStorage = std::make_unique<ModsStorage>(modsState->getInstalledMods(), repositoryList);
|
||||
|
||||
eraseMissingModsFromPreset();
|
||||
//TODO: load only active mods & all their submods in game mode
|
||||
modsStorage = std::make_unique<ModsStorage>(modsState->getAllMods(), repositoryList);
|
||||
addNewModsToPreset();
|
||||
|
||||
std::vector<TModID> desiredModList = modsPreset->getActiveMods();
|
||||
@ -301,6 +347,26 @@ const TModList & ModManager::getActiveMods() const
|
||||
return activeMods;
|
||||
}
|
||||
|
||||
uint32_t ModManager::computeChecksum(const TModID & modName) const
|
||||
{
|
||||
return modsState->computeChecksum(modName);
|
||||
}
|
||||
|
||||
std::optional<uint32_t> ModManager::getValidatedChecksum(const TModID & modName) const
|
||||
{
|
||||
return modsPreset->getValidatedChecksum(modName);
|
||||
}
|
||||
|
||||
void ModManager::setValidatedChecksum(const TModID & modName, std::optional<uint32_t> value)
|
||||
{
|
||||
modsPreset->setValidatedChecksum(modName, value);
|
||||
}
|
||||
|
||||
void ModManager::saveConfigurationState() const
|
||||
{
|
||||
modsPreset->saveConfigurationState();
|
||||
}
|
||||
|
||||
TModList ModManager::getAllMods() const
|
||||
{
|
||||
return modsStorage->getAllMods();
|
||||
@ -308,7 +374,7 @@ TModList ModManager::getAllMods() const
|
||||
|
||||
void ModManager::eraseMissingModsFromPreset()
|
||||
{
|
||||
const TModList & installedMods = modsState->getAllMods();
|
||||
const TModList & installedMods = modsState->getInstalledMods();
|
||||
const TModList & rootMods = modsPreset->getActiveRootMods();
|
||||
|
||||
for(const auto & rootMod : rootMods)
|
||||
@ -335,7 +401,7 @@ void ModManager::eraseMissingModsFromPreset()
|
||||
|
||||
void ModManager::addNewModsToPreset()
|
||||
{
|
||||
const TModList & installedMods = modsState->getAllMods();
|
||||
const TModList & installedMods = modsState->getInstalledMods();
|
||||
|
||||
for(const auto & modID : installedMods)
|
||||
{
|
||||
@ -421,66 +487,4 @@ void ModManager::generateLoadOrder(std::vector<TModID> modsToResolve)
|
||||
brokenMods = modsToResolve;
|
||||
}
|
||||
|
||||
// modLoadErrors = std::make_unique<MetaString>();
|
||||
//
|
||||
// auto addErrorMessage = [this](const std::string & textID, const std::string & brokenModID, const std::string & missingModID)
|
||||
// {
|
||||
// modLoadErrors->appendTextID(textID);
|
||||
//
|
||||
// if (allMods.count(brokenModID))
|
||||
// modLoadErrors->replaceRawString(allMods.at(brokenModID).getVerificationInfo().name);
|
||||
// else
|
||||
// modLoadErrors->replaceRawString(brokenModID);
|
||||
//
|
||||
// if (allMods.count(missingModID))
|
||||
// modLoadErrors->replaceRawString(allMods.at(missingModID).getVerificationInfo().name);
|
||||
// else
|
||||
// modLoadErrors->replaceRawString(missingModID);
|
||||
//
|
||||
// };
|
||||
//
|
||||
// // Left mods have unresolved dependencies, output all to log.
|
||||
// for(const auto & brokenModID : modsToResolve)
|
||||
// {
|
||||
// const CModInfo & brokenMod = allMods.at(brokenModID);
|
||||
// bool showErrorMessage = false;
|
||||
// for(const TModID & dependency : brokenMod.dependencies)
|
||||
// {
|
||||
// if(!vstd::contains(resolvedModIDs, dependency) && brokenMod.config["modType"].String() != "Compatibility")
|
||||
// {
|
||||
// addErrorMessage("vcmi.server.errors.modNoDependency", brokenModID, dependency);
|
||||
// showErrorMessage = true;
|
||||
// }
|
||||
// }
|
||||
// for(const TModID & conflict : brokenMod.conflicts)
|
||||
// {
|
||||
// if(vstd::contains(resolvedModIDs, conflict))
|
||||
// {
|
||||
// addErrorMessage("vcmi.server.errors.modConflict", brokenModID, conflict);
|
||||
// showErrorMessage = true;
|
||||
// }
|
||||
// }
|
||||
// for(const TModID & reverseConflict : resolvedModIDs)
|
||||
// {
|
||||
// if (vstd::contains(allMods.at(reverseConflict).conflicts, brokenModID))
|
||||
// {
|
||||
// addErrorMessage("vcmi.server.errors.modConflict", brokenModID, reverseConflict);
|
||||
// showErrorMessage = true;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// // some mods may in a (soft) dependency loop.
|
||||
// if(!showErrorMessage && brokenMod.config["modType"].String() != "Compatibility")
|
||||
// {
|
||||
// modLoadErrors->appendTextID("vcmi.server.errors.modDependencyLoop");
|
||||
// if (allMods.count(brokenModID))
|
||||
// modLoadErrors->replaceRawString(allMods.at(brokenModID).getVerificationInfo().name);
|
||||
// else
|
||||
// modLoadErrors->replaceRawString(brokenModID);
|
||||
// }
|
||||
//
|
||||
// }
|
||||
// return sortedValidMods;
|
||||
//}
|
||||
|
||||
VCMI_LIB_NAMESPACE_END
|
||||
|
@ -31,7 +31,9 @@ class ModsState : boost::noncopyable
|
||||
public:
|
||||
ModsState();
|
||||
|
||||
TModList getAllMods() const;
|
||||
TModList getInstalledMods() const;
|
||||
|
||||
uint32_t computeChecksum(const TModID & modName) const;
|
||||
};
|
||||
|
||||
/// Provides interface to access or change current mod preset
|
||||
@ -39,8 +41,6 @@ class ModsPresetState : boost::noncopyable
|
||||
{
|
||||
JsonNode modConfig;
|
||||
|
||||
void saveConfiguration(const JsonNode & config);
|
||||
|
||||
void createInitialPreset();
|
||||
void importInitialPreset();
|
||||
|
||||
@ -61,6 +61,10 @@ public:
|
||||
|
||||
/// Returns list of all known settings (submods) for a specified mod
|
||||
std::map<TModID, bool> getModSettings(const TModID & modID) const;
|
||||
std::optional<uint32_t> getValidatedChecksum(const TModID & modName) const;
|
||||
void setValidatedChecksum(const TModID & modName, std::optional<uint32_t> value);
|
||||
|
||||
void saveConfigurationState() const;
|
||||
};
|
||||
|
||||
/// Provides access to mod properties
|
||||
@ -101,7 +105,12 @@ public:
|
||||
const ModDescription & getModDescription(const TModID & modID) const;
|
||||
const TModList & getActiveMods() const;
|
||||
TModList getAllMods() const;
|
||||
|
||||
bool isModActive(const TModID & modID) const;
|
||||
uint32_t computeChecksum(const TModID & modName) const;
|
||||
std::optional<uint32_t> getValidatedChecksum(const TModID & modName) const;
|
||||
void setValidatedChecksum(const TModID & modName, std::optional<uint32_t> value);
|
||||
void saveConfigurationState() const;
|
||||
};
|
||||
|
||||
VCMI_LIB_NAMESPACE_END
|
||||
|
@ -116,7 +116,7 @@ JsonNode toJson(QVariant object)
|
||||
void jsonToFile(QString filename, const JsonNode & object)
|
||||
{
|
||||
std::fstream file(qstringToPath(filename).c_str(), std::ios::out | std::ios_base::binary);
|
||||
file << object.toString();
|
||||
file << object.toCompactString();
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user