1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-10-31 00:07:39 +02:00

Fix: Hanging on start up if mod dependency is not resolved'

This commit is contained in:
Dmitry Orlov
2021-01-20 11:23:58 +03:00
parent 2f5c8d7587
commit 98fdf909e8

View File

@@ -716,50 +716,41 @@ bool CModHandler::checkDependencies(const std::vector <TModID> & input) const
return true; return true;
} }
std::vector <TModID> CModHandler::resolveDependencies(std::vector <TModID> input) const std::vector <TModID> CModHandler::resolveDependencies(std::vector <TModID> modsToResolve) const
{ {
// Topological sort algorithm std::vector<TModID> brokenMods;
// May not be the fastest one but VCMI does not needs any speed here
// Unless user have dozens of mods with complex dependencies this code should be fine
// first - sort input to have input strictly based on name (and not on hashmap or anything else) auto looksValid = [&](const CModInfo & mod) -> bool
boost::range::sort(input);
std::vector <TModID> output;
output.reserve(input.size());
std::set <TModID> resolvedMods;
// Check if all mod dependencies are resolved (moved to resolvedMods)
auto isResolved = [&](const CModInfo & mod) -> bool
{ {
auto res = true;
for(const TModID & dependency : mod.dependencies) for(const TModID & dependency : mod.dependencies)
{ {
if (!vstd::contains(resolvedMods, dependency)) if(!(res = vstd::contains(modsToResolve, dependency)))
return false; logMod->error("Mod '%s' will not work: it depends on mod '%s', which is not installed.", mod.name, dependency);
} }
return true; return res;
}; };
while (!input.empty()) while(true)
{ {
std::set <TModID> toResolve; // list of mods resolved on this iteration for(auto mod : modsToResolve)
for (auto it = input.begin(); it != input.end();)
{ {
if (isResolved(allMods.at(*it))) if(!looksValid(this->allMods.at(mod)))
{ brokenMods.push_back(mod);
toResolve.insert(*it);
output.push_back(*it);
it = input.erase(it);
continue;
}
it++;
} }
resolvedMods.insert(toResolve.begin(), toResolve.end()); if(!brokenMods.empty())
{
vstd::erase_if(modsToResolve, [&](TModID mid)
{
return brokenMods.end() != std::find(brokenMods.begin(), brokenMods.end(), mid);
});
brokenMods.clear();
continue;
}
break;
} }
boost::range::sort(modsToResolve);
return output; return modsToResolve;
} }
std::vector<std::string> CModHandler::getModList(std::string path) std::vector<std::string> CModHandler::getModList(std::string path)