2
0
Эх сурвалжийг харах

Merge pull request #675 from ShubusCorporation/do/fix/mod_system_and_interface_bugs

Fixed: Mods dependency issues leading to hanging & 'Restart Scenario' button functionality
Alexander Shishkin 4 жил өмнө
parent
commit
db1f9a15b0

+ 7 - 0
client/CServerHandler.cpp

@@ -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);
 }
 

+ 22 - 31
lib/CModHandler.cpp

@@ -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(!looksValid(this->allMods.at(mod)))
+				brokenMods.push_back(mod);
+		}
+		if(!brokenMods.empty())
 		{
-			if (isResolved(allMods.at(*it)))
+			vstd::erase_if(modsToResolve, [&](TModID mid) 
 			{
-				toResolve.insert(*it);
-				output.push_back(*it);
-				it = input.erase(it);
-				continue;
-			}
-			it++;
+				return brokenMods.end() != std::find(brokenMods.begin(), brokenMods.end(), mid);
+			});
+			brokenMods.clear();
+			continue;
 		}
-		resolvedMods.insert(toResolve.begin(), toResolve.end());
+		break;
 	}
-
-	return output;
+	boost::range::sort(modsToResolve);
+	return modsToResolve;
 }
 
 std::vector<std::string> CModHandler::getModList(std::string path)

+ 2 - 0
server/CVCMIServer.cpp

@@ -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));