1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-06-15 00:05:02 +02:00

add support for soft dependencies

This commit is contained in:
kdmcser
2024-10-25 23:21:32 +08:00
parent 1826b5bbdf
commit 3b72594743
10 changed files with 81 additions and 4 deletions

View File

@ -87,8 +87,9 @@ std::vector <TModID> CModHandler::validateAndSortDependencies(std::vector <TModI
std::vector <TModID> sortedValidMods; // Vector keeps order of elements (LIFO)
sortedValidMods.reserve(modsToResolve.size()); // push_back calls won't cause memory reallocation
std::set <TModID> resolvedModIDs; // Use a set for validation for performance reason, but set does not keep order of elements
std::set <TModID> notResolvedModIDs(modsToResolve.begin(), modsToResolve.end()); // Use a set for validation for performance reason
// Mod is resolved if it has not dependencies or all its dependencies are already resolved
// Mod is resolved if it has no dependencies or all its dependencies are already resolved
auto isResolved = [&](const CModInfo & mod) -> bool
{
if(mod.dependencies.size() > resolvedModIDs.size())
@ -100,6 +101,12 @@ std::vector <TModID> CModHandler::validateAndSortDependencies(std::vector <TModI
return false;
}
for(const TModID & softDependency : mod.softDependencies)
{
if(vstd::contains(notResolvedModIDs, softDependency))
return false;
}
for(const TModID & conflict : mod.conflicts)
{
if(vstd::contains(resolvedModIDs, conflict))
@ -130,9 +137,11 @@ std::vector <TModID> CModHandler::validateAndSortDependencies(std::vector <TModI
if(!resolvedOnCurrentTreeLevel.empty())
{
resolvedModIDs.insert(resolvedOnCurrentTreeLevel.begin(), resolvedOnCurrentTreeLevel.end());
continue;
for(auto it = resolvedOnCurrentTreeLevel.begin(); it != resolvedOnCurrentTreeLevel.end(); it++)
notResolvedModIDs.erase(*it);
continue;
}
// If there're no valid mods on the current mods tree level, no more mod can be resolved, should be end.
// If there are no valid mods on the current mods tree level, no more mod can be resolved, should be ended.
break;
}
@ -158,21 +167,42 @@ std::vector <TModID> CModHandler::validateAndSortDependencies(std::vector <TModI
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;
}
@ -352,6 +382,9 @@ void CModHandler::loadModFilesystems()
if (getModDependencies(leftModName).count(rightModName) || getModDependencies(rightModName).count(leftModName))
continue;
if (getModSoftDependencies(leftModName).count(rightModName) || getModSoftDependencies(rightModName).count(leftModName))
continue;
const auto & filter = [](const ResourcePath &path){return path.getType() != EResType::DIRECTORY;};
std::unordered_set<ResourcePath> leftResources = modFilesystems[leftModName]->getFilteredFiles(filter);
@ -417,6 +450,28 @@ std::set<TModID> CModHandler::getModDependencies(const TModID & modId, bool & is
return {};
}
std::set<TModID> CModHandler::getModSoftDependencies(const TModID & modId) const
{
auto it = allMods.find(modId);
if(it != allMods.end())
return it->second.softDependencies;
logMod->error("Mod not found: '%s'", modId);
return {};
}
std::set<TModID> CModHandler::getModEnabledSoftDependencies(const TModID & modId) const
{
std::set<TModID> softDependencies = getModSoftDependencies(modId);
for (auto it = softDependencies.begin(); it != softDependencies.end();)
{
if (allMods.find(*it) == allMods.end())
it = softDependencies.erase(it);
else
it++;
}
return softDependencies;
}
void CModHandler::initializeConfig()
{
VLC->settingsHandler->loadBase(JsonUtils::assembleFromFiles(coreMod->config["settings"]));