Browse Source

Added an option to configure validation level in launcher

Ivan Savenko 1 year ago
parent
commit
66fdad145c

+ 18 - 1
config/schemas/settings.json

@@ -3,7 +3,7 @@
 {
 	"type" : "object",
 	"$schema" : "http://json-schema.org/draft-04/schema",
-	"required" : [ "general", "video", "adventure", "battle", "input", "server", "logging", "launcher", "lobby", "gameTweaks" ],
+	"required" : [ "general", "video", "adventure", "battle", "input", "server", "logging", "launcher", "lobby", "gameTweaks", "mods" ],
 	"definitions" : {
 		"logLevelEnum" : {
 			"type" : "string",
@@ -149,6 +149,23 @@
 				}
 			}
 		},
+		
+		"mods" : {
+			"type" : "object",
+			"additionalProperties" : false,
+			"default" : {},
+			"required" : [ 
+				"validation"
+			],
+			"properties" : {
+				"validation" : {
+					"type" : "string",
+					"enum" : [ "off", "basic", "full" ],
+					"default" : "basic"
+				}
+			}
+		},
+		
 		"video" : {
 			"type" : "object",
 			"additionalProperties" : false,

+ 25 - 0
launcher/settingsView/csettingsview_moc.cpp

@@ -182,6 +182,13 @@ void CSettingsView::loadSettings()
 	else
 		ui->buttonFontScalable->setChecked(true);
 
+	if (settings["mods"]["validation"].String() == "off")
+		ui->buttonValidationOff->setChecked(true);
+	else if (settings["mods"]["validation"].String() == "basic")
+		ui->buttonValidationBasic->setChecked(true);
+	else
+		ui->buttonValidationFull->setChecked(true);
+
 	loadToggleButtonSettings();
 }
 
@@ -791,3 +798,21 @@ void CSettingsView::on_buttonFontOriginal_clicked(bool checked)
 	Settings node = settings.write["video"]["fontsType"];
 	node->String() = "original";
 }
+
+void CSettingsView::on_buttonValidationOff_clicked(bool checked)
+{
+	Settings node = settings.write["mods"]["validation"];
+	node->String() = "off";
+}
+
+void CSettingsView::on_buttonValidationBasic_clicked(bool checked)
+{
+	Settings node = settings.write["mods"]["validation"];
+	node->String() = "basic";
+}
+
+void CSettingsView::on_buttonValidationFull_clicked(bool checked)
+{
+	Settings node = settings.write["mods"]["validation"];
+	node->String() = "full";
+}

+ 7 - 6
launcher/settingsView/csettingsview_moc.h

@@ -83,19 +83,20 @@ private slots:
 	void on_sliderToleranceDistanceController_valueChanged(int value);
 	void on_lineEditGameLobbyHost_textChanged(const QString &arg1);
 	void on_spinBoxNetworkPortLobby_valueChanged(int arg1);
-
 	void on_sliderControllerSticksAcceleration_valueChanged(int value);
-
 	void on_sliderControllerSticksSensitivity_valueChanged(int value);
-
-	//void on_buttonTtfFont_toggled(bool value);
-
 	void on_sliderScalingFont_valueChanged(int value);
-
 	void on_buttonFontAuto_clicked(bool checked);
 	void on_buttonFontScalable_clicked(bool checked);
 	void on_buttonFontOriginal_clicked(bool checked);
 
+
+	void on_buttonValidationOff_clicked(bool checked);
+
+	void on_buttonValidationBasic_clicked(bool checked);
+
+	void on_buttonValidationFull_clicked(bool checked);
+
 private:
 	Ui::CSettingsView * ui;
 

File diff suppressed because it is too large
+ 377 - 382
launcher/settingsView/csettingsview_moc.ui


+ 3 - 1
lib/mapObjectConstructors/CRewardableConstructor.cpp

@@ -14,6 +14,7 @@
 #include "../mapObjects/CRewardableObject.h"
 #include "../texts/CGeneralTextHandler.h"
 #include "../IGameCallback.h"
+#include "../CConfigHandler.h"
 
 VCMI_LIB_NAMESPACE_BEGIN
 
@@ -25,7 +26,8 @@ void CRewardableConstructor::initTypeData(const JsonNode & config)
 	if (!config["name"].isNull())
 		VLC->generaltexth->registerString( config.getModScope(), getNameTextID(), config["name"].String());
 
-	JsonUtils::validate(config, "vcmi:rewardable", getJsonKey());
+	if (settings["mods"]["validation"].String() != "off")
+		JsonUtils::validate(config, "vcmi:rewardable", getJsonKey());
 	
 }
 

+ 19 - 15
lib/modding/CModHandler.cpp

@@ -17,6 +17,7 @@
 #include "ModIncompatibility.h"
 
 #include "../CCreatureHandler.h"
+#include "../CConfigHandler.h"
 #include "../CStopWatch.h"
 #include "../GameSettings.h"
 #include "../ScriptHandler.h"
@@ -339,25 +340,28 @@ void CModHandler::loadModFilesystems()
 	for(std::string & modName : activeMods)
 		CResourceHandler::addFilesystem("data", modName, modFilesystems[modName]);
 
-	for(std::string & leftModName : activeMods)
+	if (settings["mods"]["validation"].String() == "full")
 	{
-		for(std::string & rightModName : activeMods)
+		for(std::string & leftModName : activeMods)
 		{
-			if (leftModName == rightModName)
-				continue;
+			for(std::string & rightModName : activeMods)
+			{
+				if (leftModName == rightModName)
+					continue;
 
-			if (getModDependencies(leftModName).count(rightModName) || getModDependencies(rightModName).count(leftModName))
-				continue;
+				if (getModDependencies(leftModName).count(rightModName) || getModDependencies(rightModName).count(leftModName))
+					continue;
 
-			const auto & filter = [](const ResourcePath &path){return path.getType() != EResType::DIRECTORY;};
+				const auto & filter = [](const ResourcePath &path){return path.getType() != EResType::DIRECTORY;};
 
-			std::unordered_set<ResourcePath> leftResources = modFilesystems[leftModName]->getFilteredFiles(filter);
-			std::unordered_set<ResourcePath> rightResources = modFilesystems[rightModName]->getFilteredFiles(filter);
+				std::unordered_set<ResourcePath> leftResources = modFilesystems[leftModName]->getFilteredFiles(filter);
+				std::unordered_set<ResourcePath> rightResources = modFilesystems[rightModName]->getFilteredFiles(filter);
 
-			for (auto const & leftFile : leftResources)
-			{
-				if (rightResources.count(leftFile))
-					logMod->warn("Potential confict detected between '%s' and '%s': both mods add file '%s'", leftModName, rightModName, leftFile.getOriginalName());
+				for (auto const & leftFile : leftResources)
+				{
+					if (rightResources.count(leftFile))
+						logMod->warn("Potential confict detected between '%s' and '%s': both mods add file '%s'", leftModName, rightModName, leftFile.getOriginalName());
+				}
 			}
 		}
 	}
@@ -508,8 +512,8 @@ void CModHandler::load()
 
 	content->loadCustom();
 
-//	for(const TModID & modName : activeMods)
-//		loadTranslation(modName);
+	for(const TModID & modName : activeMods)
+		loadTranslation(modName);
 
 #if 0
 	for(const TModID & modName : activeMods)

+ 61 - 43
lib/modding/ContentTypeHandler.cpp

@@ -17,6 +17,7 @@
 #include "../BattleFieldHandler.h"
 #include "../CArtHandler.h"
 #include "../CCreatureHandler.h"
+#include "../CConfigHandler.h"
 #include "../entities/faction/CTownHandler.h"
 #include "../texts/CGeneralTextHandler.h"
 #include "../CHeroHandler.h"
@@ -79,7 +80,7 @@ bool ContentTypeHandler::preloadModData(const std::string & modName, const std::
 			logMod->trace("Patching object %s (%s) from %s", objectName, remoteName, modName);
 			JsonNode & remoteConf = modData[remoteName].patches[objectName];
 
-			if (!remoteConf.isNull())
+			if (!remoteConf.isNull() && settings["mods"]["validation"].String() != "off")
 				JsonUtils::detectConflicts(conflictList, remoteConf, entry.second, objectName);
 
 			JsonUtils::merge(remoteConf, entry.second);
@@ -162,67 +163,70 @@ void ContentTypeHandler::loadCustom()
 
 void ContentTypeHandler::afterLoadFinalization()
 {
-	for (auto const & data : modData)
+	if (settings["mods"]["validation"].String() != "off")
 	{
-		if (data.second.modData.isNull())
+		for (auto const & data : modData)
 		{
-			for (auto node : data.second.patches.Struct())
-				logMod->warn("Mod '%s' have added patch for object '%s' from mod '%s', but this mod was not loaded or has no new objects.", node.second.getModScope(), node.first, data.first);
-		}
+			if (data.second.modData.isNull())
+			{
+				for (auto node : data.second.patches.Struct())
+					logMod->warn("Mod '%s' have added patch for object '%s' from mod '%s', but this mod was not loaded or has no new objects.", node.second.getModScope(), node.first, data.first);
+			}
 
-		for(auto & otherMod : modData)
-		{
-			if (otherMod.first == data.first)
-				continue;
+			for(auto & otherMod : modData)
+			{
+				if (otherMod.first == data.first)
+					continue;
 
-			if (otherMod.second.modData.isNull())
-				continue;
+				if (otherMod.second.modData.isNull())
+					continue;
 
-			for(auto & otherObject : otherMod.second.modData.Struct())
-			{
-				if (data.second.modData.Struct().count(otherObject.first))
+				for(auto & otherObject : otherMod.second.modData.Struct())
 				{
-					logMod->warn("Mod '%s' have added object with name '%s' that is also available in mod '%s'", data.first, otherObject.first, otherMod.first);
-					logMod->warn("Two objects with same name were loaded. Please use form '%s:%s' if mod '%s' needs to modify this object instead", otherMod.first, otherObject.first, data.first);
+					if (data.second.modData.Struct().count(otherObject.first))
+					{
+						logMod->warn("Mod '%s' have added object with name '%s' that is also available in mod '%s'", data.first, otherObject.first, otherMod.first);
+						logMod->warn("Two objects with same name were loaded. Please use form '%s:%s' if mod '%s' needs to modify this object instead", otherMod.first, otherObject.first, data.first);
+					}
 				}
 			}
 		}
-	}
 
-	for (const auto& [conflictPath, conflictModData] : conflictList.Struct())
-	{
-		std::set<std::string> conflictingMods;
-		std::set<std::string> resolvedConflicts;
+		for (const auto& [conflictPath, conflictModData] : conflictList.Struct())
+		{
+			std::set<std::string> conflictingMods;
+			std::set<std::string> resolvedConflicts;
 
-		for (auto const & conflictModData : conflictModData.Struct())
-			conflictingMods.insert(conflictModData.first);
+			for (auto const & conflictModData : conflictModData.Struct())
+				conflictingMods.insert(conflictModData.first);
 
-		for (auto const & modID : conflictingMods)
-			resolvedConflicts.merge(VLC->modh->getModDependencies(modID));
+			for (auto const & modID : conflictingMods)
+				resolvedConflicts.merge(VLC->modh->getModDependencies(modID));
 
-		vstd::erase_if(conflictingMods, [&resolvedConflicts](const std::string & entry){ return resolvedConflicts.count(entry);});
+			vstd::erase_if(conflictingMods, [&resolvedConflicts](const std::string & entry){ return resolvedConflicts.count(entry);});
 
-		if (conflictingMods.size() < 2)
-			continue; // all conflicts were resolved - either via compatibility patch (mod that depends on 2 conflicting mods) or simple mod that depends on another one
+			if (conflictingMods.size() < 2)
+				continue; // all conflicts were resolved - either via compatibility patch (mod that depends on 2 conflicting mods) or simple mod that depends on another one
 
-		bool allEqual = true;
+			bool allEqual = true;
 
-		for (auto const & modID : conflictingMods)
-		{
-			if (conflictModData[modID] != conflictModData[*conflictingMods.begin()])
+			for (auto const & modID : conflictingMods)
 			{
-				allEqual = false;
-				break;
+				if (conflictModData[modID] != conflictModData[*conflictingMods.begin()])
+				{
+					allEqual = false;
+					break;
+				}
 			}
-		}
 
-		if (allEqual)
-			continue; // conflict still present, but all mods use the same value for conflicting entry - permit it
+			if (allEqual)
+				continue; // conflict still present, but all mods use the same value for conflicting entry - permit it
 
-		logMod->warn("Potential confict in '%s'", conflictPath);
+			logMod->warn("Potential confict in '%s'", conflictPath);
 
-		for (auto const & modID : conflictingMods)
-			logMod->warn("Mod '%s' - value set to %s", modID, conflictModData[modID].toCompactString());
+			for (auto const & modID : conflictingMods)
+				logMod->warn("Mod '%s' - value set to %s", modID, conflictModData[modID].toCompactString());
+		}
 	}
 
 	handler->afterLoadFinalization();
@@ -288,7 +292,7 @@ void CContentHandler::afterLoadFinalization()
 
 void CContentHandler::preloadData(CModInfo & mod)
 {
-	bool validate = (mod.validation != CModInfo::PASSED);
+	bool validate = validateMod(mod);
 
 	// print message in format [<8-symbols checksum>] <modname>
 	auto & info = mod.getVerificationInfo();
@@ -305,7 +309,7 @@ void CContentHandler::preloadData(CModInfo & mod)
 
 void CContentHandler::load(CModInfo & mod)
 {
-	bool validate = (mod.validation != CModInfo::PASSED);
+	bool validate = validateMod(mod);
 
 	if (!loadMod(mod.identifier, validate))
 		mod.validation = CModInfo::FAILED;
@@ -326,4 +330,18 @@ const ContentTypeHandler & CContentHandler::operator[](const std::string & name)
 	return handlers.at(name);
 }
 
+bool CContentHandler::validateMod(const CModInfo & mod) const
+{
+	if (settings["mods"]["validation"].String() == "full")
+		return true;
+
+	if (mod.validation == CModInfo::PASSED)
+		return false;
+
+	if (settings["mods"]["validation"].String() == "off")
+		return false;
+
+	return true;
+}
+
 VCMI_LIB_NAMESPACE_END

+ 1 - 0
lib/modding/ContentTypeHandler.h

@@ -58,6 +58,7 @@ class DLL_LINKAGE CContentHandler
 
 	std::map<std::string, ContentTypeHandler> handlers;
 
+	bool validateMod(const CModInfo & mod) const;
 public:
 	void init();
 

Some files were not shown because too many files changed in this diff