diff --git a/config/schemas/settings.json b/config/schemas/settings.json
index da312e19d..276903873 100644
--- a/config/schemas/settings.json
+++ b/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,
diff --git a/launcher/settingsView/csettingsview_moc.cpp b/launcher/settingsView/csettingsview_moc.cpp
index 8cb8c32a0..541a909de 100644
--- a/launcher/settingsView/csettingsview_moc.cpp
+++ b/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";
+}
diff --git a/launcher/settingsView/csettingsview_moc.h b/launcher/settingsView/csettingsview_moc.h
index 1e76f6f2e..512762d0c 100644
--- a/launcher/settingsView/csettingsview_moc.h
+++ b/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;
diff --git a/launcher/settingsView/csettingsview_moc.ui b/launcher/settingsView/csettingsview_moc.ui
index 578fd55b4..c0082edd8 100644
--- a/launcher/settingsView/csettingsview_moc.ui
+++ b/launcher/settingsView/csettingsview_moc.ui
@@ -47,88 +47,19 @@
0
- 0
+ -800
729
- 1449
+ 1506
- -
-
-
- false
-
-
- BattleAI
-
-
-
-
- BattleAI
-
-
- -
-
- StupidAI
-
-
-
-
- -
-
-
-
- 0
- 0
-
-
+
-
+
-
- true
-
- -
-
-
- Use Relative Pointer Mode
-
-
-
- -
-
-
- 25
-
-
- Qt::Horizontal
-
-
- QSlider::TicksAbove
-
-
- 5
-
-
-
- -
-
-
- Additional repository
-
-
-
- -
-
-
- Music Volume
-
-
-
- -
-
-
-
@@ -157,374 +88,6 @@
- -
-
-
- Long Touch Duration
-
-
-
- -
-
-
- false
-
-
- BattleAI
-
-
-
-
- BattleAI
-
-
- -
-
- StupidAI
-
-
-
-
- -
-
-
-
- true
-
-
-
- Video
-
-
- 5
-
-
-
- -
-
-
-
- true
-
-
-
- General
-
-
- 5
-
-
-
- -
-
-
- Heroes III Translation
-
-
-
- -
-
-
- Show Tutorial again
-
-
-
- -
-
-
- Online Lobby port
-
-
-
- -
-
-
- Relative Pointer Speed
-
-
-
- -
-
-
- Touch Tap Tolerance
-
-
-
- -
-
-
- Select display mode for game
-
-Windowed - game will run inside a window that covers part of your screen
-
-Borderless Windowed Mode - game will run in a window that covers entirely of your screen, using same resolution as your screen.
-
-Fullscreen Exclusive Mode - game will cover entirety of your screen and will use selected resolution.
-
-
- 0
-
-
-
-
- Windowed
-
-
- -
-
- Borderless fullscreen
-
-
- -
-
- Exclusive fullscreen
-
-
-
-
- -
-
-
- 500
-
-
- 2000
-
-
- 250
-
-
- 250
-
-
- Qt::Horizontal
-
-
- QSlider::TicksAbove
-
-
- 250
-
-
-
- -
-
-
- Neutral AI in battles
-
-
-
- -
-
-
-
- true
-
-
-
- Input - Mouse
-
-
- 5
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
- Automatic
-
-
- true
-
-
- true
-
-
- buttonGroup
-
-
-
- -
-
-
- Adventure Map Enemies
-
-
-
- -
-
-
- VCAI
-
-
-
-
- VCAI
-
-
- -
-
- Nullkiller
-
-
-
-
- -
-
-
- 0
-
-
- 50
-
-
- 1
-
-
- 10
-
-
- 0
-
-
- Qt::Horizontal
-
-
- QSlider::TicksAbove
-
-
- 10
-
-
-
- -
-
-
- Autosave
-
-
-
- -
-
-
- Renderer
-
-
-
- -
-
-
- Autosave limit (0 = off)
-
-
-
- -
-
-
- Default repository
-
-
-
- -
-
-
- 100
-
-
- Qt::Horizontal
-
-
- QSlider::TicksAbove
-
-
- 10
-
-
-
- -
-
-
- Sticks Sensitivity
-
-
-
- -
-
-
-
- true
-
-
-
- Audio
-
-
- 5
-
-
-
- -
-
-
- -
-
-
- Downscaling Filter
-
-
-
- -
-
-
- 1024
-
-
- 65535
-
-
- 3030
-
-
-
- -
-
-
- 0
-
-
- 50
-
-
- 1
-
-
- 10
-
-
- 0
-
-
- Qt::Horizontal
-
-
- QSlider::TicksAbove
-
-
- 10
-
-
-
- -
-
-
- Ignore SSL errors
-
-
-
-
@@ -532,120 +95,6 @@ Fullscreen Exclusive Mode - game will cover entirety of your screen and will use
- -
-
-
- Refresh now
-
-
-
- -
-
-
- true
-
-
-
- 0
- 0
-
-
-
-
-
-
- true
-
-
- false
-
-
-
- -
-
-
- VSync
-
-
-
- -
-
-
- Resolution
-
-
-
- -
-
-
- VCMI Language
-
-
-
- -
-
-
- Interface Scaling
-
-
-
- -
-
-
- -
-
-
-
-
-
-
- -
-
-
- Online Lobby address
-
-
-
- -
-
-
- VCAI
-
-
-
-
- VCAI
-
-
- -
-
- Nullkiller
-
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
-
-
-
- true
-
-
-
- -
-
-
-
-
-
-
-
@@ -674,38 +123,37 @@ Fullscreen Exclusive Mode - game will cover entirety of your screen and will use
- -
-
+
-
+
+
+ false
+
+
+ BattleAI
+
+
-
+
+ BattleAI
+
+
+ -
+
+ StupidAI
+
+
+
+
+ -
+
- Autosave prefix
+ Additional repository
- -
-
+
-
+
- Reserved screen area
-
-
-
- -
-
-
- Sound Volume
-
-
-
- -
-
-
- Font Scaling (experimental)
-
-
-
- -
-
-
- Framerate Limit
+ Ignore SSL errors
@@ -728,8 +176,130 @@ Fullscreen Exclusive Mode - game will cover entirety of your screen and will use
- -
-
+
-
+
+
+ VCMI Language
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ Automatic
+
+
+ true
+
+
+ true
+
+
+ buttonGroupFonts
+
+
+
+ -
+
+
+
+ true
+
+
+
+ Video
+
+
+ 5
+
+
+
+ -
+
+
+ Show intro
+
+
+
+ -
+
+
+ Heroes III Translation
+
+
+
+ -
+
+
+ 0
+
+
+ 50
+
+
+ 1
+
+
+ 10
+
+
+ 0
+
+
+ Qt::Horizontal
+
+
+ QSlider::TicksAbove
+
+
+ 10
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ Scalable
+
+
+ true
+
+
+ true
+
+
+ buttonGroupFonts
+
+
+
+ -
+
+
+ Touch Tap Tolerance
+
+
+
+ -
+
+
+
+
+
+
+ -
+
100
@@ -744,56 +314,13 @@ Fullscreen Exclusive Mode - game will cover entirety of your screen and will use
- -
-
-
-
-
- Automatic
-
-
- -
-
- None
-
-
- -
-
- xBRZ x2
-
-
- -
-
- xBRZ x3
-
-
- -
-
- xBRZ x4
-
-
-
+ -
+
- -
-
+
-
+
- Autocombat AI in battles
-
-
-
- -
-
-
- Use scalable fonts
-
-
-
- -
-
-
-
-
-
- true
+ Renderer
@@ -812,87 +339,24 @@ Fullscreen Exclusive Mode - game will cover entirety of your screen and will use
- -
-
+
-
+
- Fullscreen
+ Neutral AI in battles
- -
-
-
- 500
-
-
- 2500
-
-
- 25
-
-
- 250
-
-
- 500
-
-
- Qt::Horizontal
-
-
- QSlider::TicksAbove
-
-
- 250
-
-
-
- -
-
+
-
+
- Enemy AI in battles
+ VSync
- -
-
+
-
+
- Sticks Acceleration
-
-
-
- -
-
-
- 100
-
-
- 300
-
-
- Qt::Horizontal
-
-
- QSlider::TicksAbove
-
-
- 25
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
-
-
-
- true
+ Framerate Limit
@@ -903,8 +367,61 @@ Fullscreen Exclusive Mode - game will cover entirety of your screen and will use
- -
-
+
-
+
+
+
+ true
+
+
+
+ Input - Touchscreen
+
+
+ 5
+
+
+
+ -
+
+
+ 0
+
+
+ 50
+
+
+ 1
+
+
+ 10
+
+
+ 0
+
+
+ Qt::Horizontal
+
+
+ QSlider::TicksAbove
+
+
+ 10
+
+
+
+ -
+
+
+ Relative Pointer Speed
+
+
+
+ -
+
+
+ -
+
true
@@ -925,29 +442,6 @@ Fullscreen Exclusive Mode - game will cover entirety of your screen and will use
- -
-
-
-
- 0
- 0
-
-
-
-
-
-
- true
-
-
-
- -
-
-
-
-
-
-
-
@@ -964,33 +458,20 @@ Fullscreen Exclusive Mode - game will cover entirety of your screen and will use
- -
-
+
-
+
- Adventure Map Allies
+ Long Touch Duration
- -
-
-
- Haptic Feedback
-
-
+
-
+
- -
-
-
- %
-
-
- 50
-
-
- 400
-
-
- 10
+
-
+
+
+ Check on startup
@@ -1013,72 +494,6 @@ Fullscreen Exclusive Mode - game will cover entirety of your screen and will use
- -
-
-
- Mouse Click Tolerance
-
-
-
- -
-
-
- BattleAI
-
-
-
-
- BattleAI
-
-
- -
-
- StupidAI
-
-
-
-
- -
-
-
- true
-
-
-
- 0
- 0
-
-
-
-
-
-
- true
-
-
- false
-
-
-
- -
-
-
- Reset
-
-
-
- -
-
-
- -
-
-
- Network port
-
-
-
- -
-
-
-
@@ -1094,15 +509,8 @@ Fullscreen Exclusive Mode - game will cover entirety of your screen and will use
- -
-
-
- Display index
-
-
-
- -
-
+
-
+
0
@@ -1117,128 +525,6 @@ Fullscreen Exclusive Mode - game will cover entirety of your screen and will use
- -
-
-
-
- true
-
-
-
- Network
-
-
- 5
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
- Original
-
-
- true
-
-
- true
-
-
- buttonGroup
-
-
-
- -
-
-
-
-
-
-
- -
-
-
- Show intro
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
-
-
-
- true
-
-
-
- -
-
-
- 1024
-
-
- 65535
-
-
- 3030
-
-
-
- -
-
-
-
- true
-
-
-
- Input - Touchscreen
-
-
- 5
-
-
-
- -
-
-
- 20
-
-
- 1000
-
-
- 10
-
-
-
- -
-
-
- Controller Click Tolerance
-
-
-
- -
-
-
- Check on startup
-
-
-
-
@@ -1270,15 +556,53 @@ Fullscreen Exclusive Mode - game will cover entirety of your screen and will use
- -
-
+
-
+
- Software Cursor
+ Downscaling Filter
- -
-
+
-
+
+
+ Select display mode for game
+
+Windowed - game will run inside a window that covers part of your screen
+
+Borderless Windowed Mode - game will run in a window that covers entirely of your screen, using same resolution as your screen.
+
+Fullscreen Exclusive Mode - game will cover entirety of your screen and will use selected resolution.
+
+
+ 0
+
+
-
+
+ Windowed
+
+
+ -
+
+ Borderless fullscreen
+
+
+ -
+
+ Exclusive fullscreen
+
+
+
+
+ -
+
+
+ Use scalable fonts
+
+
+
+ -
+
0
@@ -1286,7 +610,7 @@ Fullscreen Exclusive Mode - game will cover entirety of your screen and will use
- Scalable
+ Original
true
@@ -1295,13 +619,786 @@ Fullscreen Exclusive Mode - game will cover entirety of your screen and will use
true
- buttonGroup
+ buttonGroupFonts
+ -
+
+
+ -
+
+
-
+
+ Automatic
+
+
+ -
+
+ None
+
+
+ -
+
+ xBRZ x2
+
+
+ -
+
+ xBRZ x3
+
+
+ -
+
+ xBRZ x4
+
+
+
+
+ -
+
+
+ Online Lobby port
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+
+
+ true
+
+
+
+ -
+
+
+ VCAI
+
+
-
+
+ VCAI
+
+
+ -
+
+ Nullkiller
+
+
+
+
+ -
+
+
+
+ true
+
+
+
+ Network
+
+
+ 5
+
+
+
+ -
+
+
+ Refresh now
+
+
+
+ -
+
+
+ 500
+
+
+ 2500
+
+
+ 25
+
+
+ 250
+
+
+ 500
+
+
+ Qt::Horizontal
+
+
+ QSlider::TicksAbove
+
+
+ 250
+
+
+
+ -
+
+
+ Display index
+
+
+
+ -
+
+
+ 500
+
+
+ 2000
+
+
+ 250
+
+
+ 250
+
+
+ Qt::Horizontal
+
+
+ QSlider::TicksAbove
+
+
+ 250
+
+
+
+ -
+
+
+ false
+
+
+ BattleAI
+
+
-
+
+ BattleAI
+
+
+ -
+
+ StupidAI
+
+
+
+
+ -
+
+
+ Adventure Map Enemies
+
+
+
+ -
+
+
+
+
+
+ true
+
+
+
+ -
+
+
+ Reset
+
+
+
+ -
+
+
+ Show Tutorial again
+
+
+
+ -
+
+
+ Fullscreen
+
+
+
+ -
+
+
+ Use Relative Pointer Mode
+
+
+
+ -
+
+
+
+
+
+
+ -
+
+
+ Sticks Acceleration
+
+
+
+ -
+
+
+ Autosave limit (0 = off)
+
+
+
+ -
+
+
+ Mouse Click Tolerance
+
+
+
+ -
+
+
+
+ true
+
+
+
+ General
+
+
+ 5
+
+
+
+ -
+
+
+ Online Lobby address
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+
+
+ true
+
+
+
+ -
+
+
+ Interface Scaling
+
+
+
+ -
+
+
+ Default repository
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+
+
+ true
+
+
+
+ -
+
+
+ Haptic Feedback
+
+
+
+ -
+
+
+ -
+
+
+ Autosave prefix
+
+
+
+ -
+
+
+
+ true
+
+
+
+ Input - Mouse
+
+
+ 5
+
+
+
+ -
+
+
+ 25
+
+
+ Qt::Horizontal
+
+
+ QSlider::TicksAbove
+
+
+ 5
+
+
+
+ -
+
+
+ 20
+
+
+ 1000
+
+
+ 10
+
+
+
+ -
+
+
+ 1024
+
+
+ 65535
+
+
+ 3030
+
+
+
+ -
+
+
+ 100
+
+
+ 300
+
+
+ Qt::Horizontal
+
+
+ QSlider::TicksAbove
+
+
+ 25
+
+
+
+ -
+
+
+ Enemy AI in battles
+
+
+
+ -
+
+
+ Reserved screen area
+
+
+
+ -
+
+
+ %
+
+
+ 50
+
+
+ 400
+
+
+ 10
+
+
+
+ -
+
+
+ Music Volume
+
+
+
+ -
+
+
+ BattleAI
+
+
-
+
+ BattleAI
+
+
+ -
+
+ StupidAI
+
+
+
+
+ -
+
+
+ Autosave
+
+
+
+ -
+
+
+ 100
+
+
+ Qt::Horizontal
+
+
+ QSlider::TicksAbove
+
+
+ 10
+
+
+
+ -
+
+
+ Network port
+
+
+
+ -
+
+
+ true
+
+
+
+ 0
+ 0
+
+
+
+
+
+
+ true
+
+
+ false
+
+
+
+ -
+
+
+ Resolution
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+
+
+ true
+
+
+
+ -
+
+
+ Sound Volume
+
+
+
+ -
+
+
+ Controller Click Tolerance
+
+
+
+ -
+
+
+ Adventure Map Allies
+
+
+
+ -
+
+
+
+ true
+
+
+
+ Miscellaneous
+
+
+ 5
+
+
+
+ -
+
+
+ 1024
+
+
+ 65535
+
+
+ 3030
+
+
+
+ -
+
+
+ VCAI
+
+
-
+
+ VCAI
+
+
+ -
+
+ Nullkiller
+
+
+
+
+ -
+
+
+
+ true
+
+
+
+ Audio
+
+
+ 5
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+
+
+ true
+
+
+
+ -
+
+
+ Software Cursor
+
+
+
+ -
+
+
+ Autocombat AI in battles
+
+
+
-
+ -
+
+
+
+
+
+
+ -
+
+
+ true
+
+
+
+ 0
+ 0
+
+
+
+
+
+
+ true
+
+
+ false
+
+
+
+ -
+
+
+ Font Scaling (experimental)
+
+
+
+ -
+
+
+ Sticks Sensitivity
+
+
+
+ -
+
+
+ Mods Validation
+
+
+
+ -
+
+
+ true
+
+
+
+ 0
+ 0
+
+
+
+ Off
+
+
+ true
+
+
+ false
+
+
+ buttonGroupValidation
+
+
+
+ -
+
+
+ true
+
+
+
+ 0
+ 0
+
+
+
+ Basic
+
+
+ true
+
+
+ false
+
+
+ buttonGroupValidation
+
+
+
+ -
+
+
+ true
+
+
+
+ 0
+ 0
+
+
+
+ Full
+
+
+ true
+
+
+ false
+
+
+ buttonGroupValidation
+
+
+
@@ -1311,6 +1408,7 @@ Fullscreen Exclusive Mode - game will cover entirety of your screen and will use
-
+
+
diff --git a/lib/mapObjectConstructors/CRewardableConstructor.cpp b/lib/mapObjectConstructors/CRewardableConstructor.cpp
index 80d842a47..bbdff2bf2 100644
--- a/lib/mapObjectConstructors/CRewardableConstructor.cpp
+++ b/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());
}
diff --git a/lib/modding/CModHandler.cpp b/lib/modding/CModHandler.cpp
index 15c9d22e4..ccd71e2a6 100644
--- a/lib/modding/CModHandler.cpp
+++ b/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;
-
- if (getModDependencies(leftModName).count(rightModName) || getModDependencies(rightModName).count(leftModName))
- continue;
-
- const auto & filter = [](const ResourcePath &path){return path.getType() != EResType::DIRECTORY;};
-
- std::unordered_set leftResources = modFilesystems[leftModName]->getFilteredFiles(filter);
- std::unordered_set rightResources = modFilesystems[rightModName]->getFilteredFiles(filter);
-
- for (auto const & leftFile : leftResources)
+ for(std::string & rightModName : activeMods)
{
- if (rightResources.count(leftFile))
- logMod->warn("Potential confict detected between '%s' and '%s': both mods add file '%s'", leftModName, rightModName, leftFile.getOriginalName());
+ if (leftModName == rightModName)
+ continue;
+
+ if (getModDependencies(leftModName).count(rightModName) || getModDependencies(rightModName).count(leftModName))
+ continue;
+
+ const auto & filter = [](const ResourcePath &path){return path.getType() != EResType::DIRECTORY;};
+
+ std::unordered_set leftResources = modFilesystems[leftModName]->getFilteredFiles(filter);
+ std::unordered_set 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());
+ }
}
}
}
@@ -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)
diff --git a/lib/modding/ContentTypeHandler.cpp b/lib/modding/ContentTypeHandler.cpp
index 60289ca6e..f2887a711 100644
--- a/lib/modding/ContentTypeHandler.cpp
+++ b/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);
- }
-
- for(auto & otherMod : modData)
- {
- if (otherMod.first == data.first)
- continue;
-
- if (otherMod.second.modData.isNull())
- continue;
-
- for(auto & otherObject : otherMod.second.modData.Struct())
+ if (data.second.modData.isNull())
{
- if (data.second.modData.Struct().count(otherObject.first))
+ 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;
+
+ if (otherMod.second.modData.isNull())
+ continue;
+
+ 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 conflictingMods;
- std::set resolvedConflicts;
-
- for (auto const & conflictModData : conflictModData.Struct())
- conflictingMods.insert(conflictModData.first);
-
- for (auto const & modID : conflictingMods)
- resolvedConflicts.merge(VLC->modh->getModDependencies(modID));
-
- 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
-
- bool allEqual = true;
-
- for (auto const & modID : conflictingMods)
+ for (const auto& [conflictPath, conflictModData] : conflictList.Struct())
{
- if (conflictModData[modID] != conflictModData[*conflictingMods.begin()])
+ std::set conflictingMods;
+ std::set resolvedConflicts;
+
+ for (auto const & conflictModData : conflictModData.Struct())
+ conflictingMods.insert(conflictModData.first);
+
+ for (auto const & modID : conflictingMods)
+ resolvedConflicts.merge(VLC->modh->getModDependencies(modID));
+
+ 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
+
+ bool allEqual = true;
+
+ 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
+
+ logMod->warn("Potential confict in '%s'", conflictPath);
+
+ for (auto const & modID : conflictingMods)
+ logMod->warn("Mod '%s' - value set to %s", modID, conflictModData[modID].toCompactString());
}
-
- 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);
-
- 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>]
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
diff --git a/lib/modding/ContentTypeHandler.h b/lib/modding/ContentTypeHandler.h
index 6c3f553c5..5c21bf182 100644
--- a/lib/modding/ContentTypeHandler.h
+++ b/lib/modding/ContentTypeHandler.h
@@ -58,6 +58,7 @@ class DLL_LINKAGE CContentHandler
std::map handlers;
+ bool validateMod(const CModInfo & mod) const;
public:
void init();