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:
		| @@ -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) | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user