mirror of
				https://github.com/vcmi/vcmi.git
				synced 2025-10-31 00:07:39 +02:00 
			
		
		
		
	Merge pull request #675 from ShubusCorporation/do/fix/mod_system_and_interface_bugs
Fixed: Mods dependency issues leading to hanging & 'Restart Scenario' button functionality
This commit is contained in:
		| @@ -451,6 +451,13 @@ void CServerHandler::sendStartGame(bool allowOnlyAI) const | ||||
| { | ||||
| 	verifyStateBeforeStart(allowOnlyAI ? true : settings["session"]["onlyai"].Bool()); | ||||
| 	LobbyStartGame lsg; | ||||
| 	if(client) | ||||
| 	{ | ||||
| 		lsg.initializedStartInfo = std::make_shared<StartInfo>(* const_cast<StartInfo *>(client->getStartInfo(true))); | ||||
| 		lsg.initializedStartInfo->mode = StartInfo::NEW_GAME; | ||||
| 		lsg.initializedStartInfo->seedToBeUsed = lsg.initializedStartInfo->seedPostInit = 0; | ||||
| 		* si = * lsg.initializedStartInfo; | ||||
| 	} | ||||
| 	sendLobbyPack(lsg); | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -716,50 +716,41 @@ bool CModHandler::checkDependencies(const std::vector <TModID> & input) const | ||||
| 	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 | ||||
| 	// 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 | ||||
| 	std::vector<TModID> brokenMods; | ||||
|  | ||||
| 	// first - sort input to have input strictly based on name (and not on hashmap or anything else) | ||||
| 	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 looksValid = [&](const CModInfo & mod) -> bool | ||||
| 	{ | ||||
| 		auto res = true; | ||||
| 		for(const TModID & dependency : mod.dependencies) | ||||
| 		{ | ||||
| 			if (!vstd::contains(resolvedMods, dependency)) | ||||
| 				return false; | ||||
| 			if(!(res = vstd::contains(modsToResolve, dependency))) | ||||
| 				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 it = input.begin(); it != input.end();) | ||||
| 		for(auto mod : modsToResolve) | ||||
| 		{ | ||||
| 			if (isResolved(allMods.at(*it))) | ||||
| 			{ | ||||
| 				toResolve.insert(*it); | ||||
| 				output.push_back(*it); | ||||
| 				it = input.erase(it); | ||||
| 				continue; | ||||
| 			} | ||||
| 			it++; | ||||
| 			if(!looksValid(this->allMods.at(mod))) | ||||
| 				brokenMods.push_back(mod); | ||||
| 		} | ||||
| 		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; | ||||
| 	} | ||||
|  | ||||
| 	return output; | ||||
| 	boost::range::sort(modsToResolve); | ||||
| 	return modsToResolve; | ||||
| } | ||||
|  | ||||
| std::vector<std::string> CModHandler::getModList(std::string path) | ||||
|   | ||||
| @@ -228,6 +228,8 @@ void CVCMIServer::prepareToStartGame() | ||||
| 	if(state == EServerState::GAMEPLAY) | ||||
| 	{ | ||||
| 		restartGameplay = true; | ||||
| 		* si = * gh->gs->initialOpts; | ||||
| 		si->seedToBeUsed = si->seedPostInit = 0; | ||||
| 		state = EServerState::LOBBY; | ||||
| 		// FIXME: dirry hack to make sure old CGameHandler::run is finished | ||||
| 		boost::this_thread::sleep(boost::posix_time::milliseconds(1000)); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user