1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-12-24 22:14:36 +02:00

Loading of translation mods is now skipped on language mismatch

This commit is contained in:
Ivan Savenko 2023-03-14 15:59:33 +02:00
parent a062e5e425
commit 369e925af8
11 changed files with 73 additions and 66 deletions

View File

@ -258,7 +258,7 @@ int main(int argc, char * argv[])
// Init filesystem and settings // Init filesystem and settings
preinitDLL(::console); preinitDLL(::console);
settings.init();
Settings session = settings.write["session"]; Settings session = settings.write["session"];
auto setSettingBool = [](std::string key, std::string arg) { auto setSettingBool = [](std::string key, std::string arg) {
Settings s = settings.write(vstd::split(key, "/")); Settings s = settings.write(vstd::split(key, "/"));

View File

@ -139,6 +139,11 @@ bool CModEntry::isValid() const
return !localData.isEmpty() || !repository.isEmpty(); return !localData.isEmpty() || !repository.isEmpty();
} }
bool CModEntry::isTranslation() const
{
return getBaseValue("modType").toString().toLower() == "translation";
}
int CModEntry::getModStatus() const int CModEntry::getModStatus() const
{ {
int status = 0; int status = 0;

View File

@ -62,6 +62,8 @@ public:
bool isCompatible() const; bool isCompatible() const;
// returns if has any data // returns if has any data
bool isValid() const; bool isValid() const;
// installed and enabled
bool isTranslation() const;
// see ModStatus enum // see ModStatus enum
int getModStatus() const; int getModStatus() const;

View File

@ -847,7 +847,7 @@ QString CModListView::getTranslationModName(const QString & language)
{ {
auto mod = modModel->getMod(modName); auto mod = modModel->getMod(modName);
if (mod.getBaseValue("modType").toString().toLower() != "translation") if (!mod.isTranslation())
continue; continue;
if (mod.getBaseValue("language").toString() != language) if (mod.getBaseValue("language").toString() != language)

View File

@ -387,8 +387,6 @@ CGeneralTextHandler::CGeneralTextHandler():
znpc00 (*this, "vcmi.znpc00" ), // technically - wog znpc00 (*this, "vcmi.znpc00" ), // technically - wog
qeModCommands (*this, "vcmi.quickExchange" ) qeModCommands (*this, "vcmi.quickExchange" )
{ {
detectInstallParameters();
readToVector("core.vcdesc", "DATA/VCDESC.TXT" ); readToVector("core.vcdesc", "DATA/VCDESC.TXT" );
readToVector("core.lcdesc", "DATA/LCDESC.TXT" ); readToVector("core.lcdesc", "DATA/LCDESC.TXT" );
readToVector("core.tcommand", "DATA/TCOMMAND.TXT" ); readToVector("core.tcommand", "DATA/TCOMMAND.TXT" );
@ -605,16 +603,19 @@ std::string CGeneralTextHandler::getModLanguage(const std::string & modContext)
std::string CGeneralTextHandler::getPreferredLanguage() std::string CGeneralTextHandler::getPreferredLanguage()
{ {
assert(!settings["general"]["language"].String().empty());
return settings["general"]["language"].String(); return settings["general"]["language"].String();
} }
std::string CGeneralTextHandler::getInstalledLanguage() std::string CGeneralTextHandler::getInstalledLanguage()
{ {
assert(!settings["session"]["language"].String().empty());
return settings["session"]["language"].String(); return settings["session"]["language"].String();
} }
std::string CGeneralTextHandler::getInstalledEncoding() std::string CGeneralTextHandler::getInstalledEncoding()
{ {
assert(!settings["session"]["encoding"].String().empty());
return settings["session"]["encoding"].String(); return settings["session"]["encoding"].String();
} }

View File

@ -616,7 +616,8 @@ bool CModInfo::Version::isNull() const
CModInfo::CModInfo(): CModInfo::CModInfo():
checksum(0), checksum(0),
enabled(false), explicitlyEnabled(false),
implicitlyEnabled(true),
validation(PENDING) validation(PENDING)
{ {
@ -629,7 +630,8 @@ CModInfo::CModInfo(std::string identifier,const JsonNode & local, const JsonNode
dependencies(config["depends"].convertTo<std::set<std::string> >()), dependencies(config["depends"].convertTo<std::set<std::string> >()),
conflicts(config["conflicts"].convertTo<std::set<std::string> >()), conflicts(config["conflicts"].convertTo<std::set<std::string> >()),
checksum(0), checksum(0),
enabled(false), explicitlyEnabled(false),
implicitlyEnabled(true),
validation(PENDING), validation(PENDING),
config(addMeta(config, identifier)) config(addMeta(config, identifier))
{ {
@ -654,7 +656,7 @@ JsonNode CModInfo::saveLocalData() const
stream << std::noshowbase << std::hex << std::setw(8) << std::setfill('0') << checksum; stream << std::noshowbase << std::hex << std::setw(8) << std::setfill('0') << checksum;
JsonNode conf; JsonNode conf;
conf["active"].Bool() = enabled; conf["active"].Bool() = explicitlyEnabled;
conf["validated"].Bool() = validation != FAILED; conf["validated"].Bool() = validation != FAILED;
conf["checksum"].String() = stream.str(); conf["checksum"].String() = stream.str();
return conf; return conf;
@ -683,33 +685,52 @@ void CModInfo::updateChecksum(ui32 newChecksum)
void CModInfo::loadLocalData(const JsonNode & data) void CModInfo::loadLocalData(const JsonNode & data)
{ {
bool validated = false; bool validated = false;
enabled = true; implicitlyEnabled = true;
explicitlyEnabled = true;
checksum = 0; checksum = 0;
if (data.getType() == JsonNode::JsonType::DATA_BOOL) if (data.getType() == JsonNode::JsonType::DATA_BOOL)
{ {
enabled = data.Bool(); explicitlyEnabled = data.Bool();
} }
if (data.getType() == JsonNode::JsonType::DATA_STRUCT) if (data.getType() == JsonNode::JsonType::DATA_STRUCT)
{ {
enabled = data["active"].Bool(); explicitlyEnabled = data["active"].Bool();
validated = data["validated"].Bool(); validated = data["validated"].Bool();
checksum = strtol(data["checksum"].String().c_str(), nullptr, 16); checksum = strtol(data["checksum"].String().c_str(), nullptr, 16);
} }
//check compatibility //check compatibility
bool wasEnabled = enabled; implicitlyEnabled &= (vcmiCompatibleMin.isNull() || Version::GameVersion().compatible(vcmiCompatibleMin));
enabled = enabled && (vcmiCompatibleMin.isNull() || Version::GameVersion().compatible(vcmiCompatibleMin)); implicitlyEnabled &= (vcmiCompatibleMax.isNull() || vcmiCompatibleMax.compatible(Version::GameVersion()));
enabled = enabled && (vcmiCompatibleMax.isNull() || vcmiCompatibleMax.compatible(Version::GameVersion()));
if(wasEnabled && !enabled) if(!implicitlyEnabled)
logGlobal->warn("Mod %s is incompatible with current version of VCMI and cannot be enabled", name); logGlobal->warn("Mod %s is incompatible with current version of VCMI and cannot be enabled", name);
if (enabled) if (boost::iequals(config["modType"].String(), "translation")) // compatibility code - mods use "Translation" type at the moment
{
if (baseLanguage != VLC->generaltexth->getPreferredLanguage())
{
logGlobal->warn("Translation mod %s was not loaded: language mismatch!", name);
implicitlyEnabled = false;
}
}
if (isEnabled())
validation = validated ? PASSED : PENDING; validation = validated ? PASSED : PENDING;
else else
validation = validated ? PASSED : FAILED; validation = validated ? PASSED : FAILED;
} }
bool CModInfo::isEnabled() const
{
return implicitlyEnabled && explicitlyEnabled;
}
void CModInfo::setEnabled(bool on)
{
explicitlyEnabled = on;
}
CModHandler::CModHandler() : content(std::make_shared<CContentHandler>()) CModHandler::CModHandler() : content(std::make_shared<CContentHandler>())
{ {
modules.COMMANDERS = false; modules.COMMANDERS = false;
@ -820,36 +841,6 @@ bool CModHandler::hasCircularDependency(TModID modID, std::set <TModID> currentL
return false; return false;
} }
bool CModHandler::checkDependencies(const std::vector <TModID> & input) const
{
for(const TModID & id : input)
{
const CModInfo & mod = allMods.at(id);
for(const TModID & dep : mod.dependencies)
{
if(!vstd::contains(input, dep))
{
logMod->error("Error: Mod %s requires missing %s!", mod.name, dep);
return false;
}
}
for(const TModID & conflicting : mod.conflicts)
{
if(vstd::contains(input, conflicting))
{
logMod->error("Error: Mod %s conflicts with %s!", mod.name, allMods.at(conflicting).name);
return false;
}
}
if(hasCircularDependency(id))
return false;
}
return true;
}
// Returned vector affects the resource loaders call order (see CFilesystemList::load). // Returned vector affects the resource loaders call order (see CFilesystemList::load).
// The loaders call order matters when dependent mod overrides resources in its dependencies. // The loaders call order matters when dependent mod overrides resources in its dependencies.
std::vector <TModID> CModHandler::validateAndSortDependencies(std::vector <TModID> modsToResolve) const std::vector <TModID> CModHandler::validateAndSortDependencies(std::vector <TModID> modsToResolve) const
@ -995,10 +986,10 @@ void CModHandler::loadOneMod(std::string modName, std::string parent, const Json
mod.dependencies.insert(parent); mod.dependencies.insert(parent);
allMods[modFullName] = mod; allMods[modFullName] = mod;
if (mod.enabled && enableMods) if (mod.isEnabled() && enableMods)
activeMods.push_back(modFullName); activeMods.push_back(modFullName);
loadMods(CModInfo::getModDir(modFullName) + '/', modFullName, modSettings[modName]["mods"], enableMods && mod.enabled); loadMods(CModInfo::getModDir(modFullName) + '/', modFullName, modSettings[modName]["mods"], enableMods && mod.isEnabled());
} }
} }
@ -1087,6 +1078,8 @@ static ui32 calculateModChecksum(const std::string modName, ISimpleResourceLoade
void CModHandler::loadModFilesystems() void CModHandler::loadModFilesystems()
{ {
CGeneralTextHandler::detectInstallParameters();
activeMods = validateAndSortDependencies(activeMods); activeMods = validateAndSortDependencies(activeMods);
coreMod.updateChecksum(calculateModChecksum(CModHandler::scopeBuiltin(), CResourceHandler::get(CModHandler::scopeBuiltin()))); coreMod.updateChecksum(calculateModChecksum(CModHandler::scopeBuiltin(), CResourceHandler::get(CModHandler::scopeBuiltin())));
@ -1109,6 +1102,9 @@ TModID CModHandler::findResourceOrigin(const ResourceID & name)
if(CResourceHandler::get("core")->existsResource(name)) if(CResourceHandler::get("core")->existsResource(name))
return "core"; return "core";
if(CResourceHandler::get("mapEditor")->existsResource(name))
return "core"; // Workaround for loading maps via map editor
assert(0); assert(0);
return ""; return "";
} }

View File

@ -236,9 +236,6 @@ public:
/// CRC-32 checksum of the mod /// CRC-32 checksum of the mod
ui32 checksum; ui32 checksum;
/// true if mod is enabled
bool enabled;
EValidationStatus validation; EValidationStatus validation;
JsonNode config; JsonNode config;
@ -249,10 +246,19 @@ public:
JsonNode saveLocalData() const; JsonNode saveLocalData() const;
void updateChecksum(ui32 newChecksum); void updateChecksum(ui32 newChecksum);
bool isEnabled() const;
void setEnabled(bool on);
static std::string getModDir(std::string name); static std::string getModDir(std::string name);
static std::string getModFile(std::string name); static std::string getModFile(std::string name);
private: private:
/// true if mod is enabled by user, e.g. in Launcher UI
bool explicitlyEnabled;
/// true if mod can be loaded - compatible and has no missing deps
bool implicitlyEnabled;
void loadLocalData(const JsonNode & data); void loadLocalData(const JsonNode & data);
}; };
@ -266,12 +272,6 @@ class DLL_LINKAGE CModHandler
bool hasCircularDependency(TModID mod, std::set <TModID> currentList = std::set <TModID>()) const; bool hasCircularDependency(TModID mod, std::set <TModID> currentList = std::set <TModID>()) const;
//returns false if mod list is incorrect and prints error to console. Possible errors are:
// - missing dependency mod
// - conflicting mod in load order
// - circular dependencies
bool checkDependencies(const std::vector <TModID> & input) const;
/** /**
* 1. Set apart mods with resolved dependencies from mods which have unresolved dependencies * 1. Set apart mods with resolved dependencies from mods which have unresolved dependencies
* 2. Sort resolved mods using topological algorithm * 2. Sort resolved mods using topological algorithm
@ -449,7 +449,7 @@ public:
h & mver; h & mver;
if(allMods.count(m) && (allMods[m].version.isNull() || mver.isNull() || allMods[m].version.compatible(mver))) if(allMods.count(m) && (allMods[m].version.isNull() || mver.isNull() || allMods[m].version.compatible(mver)))
allMods[m].enabled = true; allMods[m].setEnabled(true);
else else
missingMods.emplace_back(m, mver.toString()); missingMods.emplace_back(m, mver.toString());
} }

View File

@ -18,6 +18,7 @@
#include "CHeroHandler.h" #include "CHeroHandler.h"
#include "mapObjects/CObjectHandler.h" #include "mapObjects/CObjectHandler.h"
#include "CTownHandler.h" #include "CTownHandler.h"
#include "CConfigHandler.h"
#include "RoadHandler.h" #include "RoadHandler.h"
#include "RiverHandler.h" #include "RiverHandler.h"
#include "TerrainHandler.h" #include "TerrainHandler.h"
@ -48,7 +49,9 @@ DLL_LINKAGE void preinitDLL(CConsoleHandler * Console, bool onlyEssential, bool
VLC = new LibClasses(); VLC = new LibClasses();
try try
{ {
VLC->loadFilesystem(onlyEssential, extractArchives); VLC->loadFilesystem(extractArchives);
settings.init();
VLC->loadModFilesystem(onlyEssential);
} }
catch(...) catch(...)
{ {
@ -160,9 +163,8 @@ void LibClasses::updateEntity(Metatype metatype, int32_t index, const JsonNode &
} }
} }
void LibClasses::loadFilesystem(bool onlyEssential, bool extractArchives) void LibClasses::loadFilesystem(bool extractArchives)
{ {
CStopWatch totalTime;
CStopWatch loadTime; CStopWatch loadTime;
CResourceHandler::initialize(); CResourceHandler::initialize();
@ -170,15 +172,17 @@ void LibClasses::loadFilesystem(bool onlyEssential, bool extractArchives)
CResourceHandler::load("config/filesystem.json", extractArchives); CResourceHandler::load("config/filesystem.json", extractArchives);
logGlobal->info("\tData loading: %d ms", loadTime.getDiff()); logGlobal->info("\tData loading: %d ms", loadTime.getDiff());
}
void LibClasses::loadModFilesystem(bool onlyEssential)
{
CStopWatch loadTime;
modh = new CModHandler(); modh = new CModHandler();
modh->loadMods(onlyEssential);
logGlobal->info("\tMod handler: %d ms", loadTime.getDiff()); logGlobal->info("\tMod handler: %d ms", loadTime.getDiff());
modh->loadMods(onlyEssential);
modh->loadModFilesystems(); modh->loadModFilesystems();
logGlobal->info("\tMod filesystems: %d ms", loadTime.getDiff()); logGlobal->info("\tMod filesystems: %d ms", loadTime.getDiff());
logGlobal->info("Basic initialization: %d ms", totalTime.getDiff());
} }
static void logHandlerLoaded(const std::string & name, CStopWatch & timer) static void logHandlerLoaded(const std::string & name, CStopWatch & timer)

View File

@ -107,7 +107,8 @@ public:
void clear(); //deletes all handlers and its data void clear(); //deletes all handlers and its data
// basic initialization. should be called before init(). Can also extract original H3 archives // basic initialization. should be called before init(). Can also extract original H3 archives
void loadFilesystem(bool onlyEssential, bool extractArchives = false); void loadFilesystem(bool extractArchives);
void loadModFilesystem(bool onlyEssential);
#if SCRIPTING_ENABLED #if SCRIPTING_ENABLED
void scriptsLoaded(); void scriptsLoaded();

View File

@ -170,7 +170,6 @@ MainWindow::MainWindow(QWidget* parent) :
//init //init
preinitDLL(::console, false, extractionOptions.extractArchives); preinitDLL(::console, false, extractionOptions.extractArchives);
settings.init();
// Initialize logging based on settings // Initialize logging based on settings
logConfig->configure(); logConfig->configure();

View File

@ -1117,7 +1117,6 @@ int main(int argc, const char * argv[])
boost::program_options::variables_map opts; boost::program_options::variables_map opts;
handleCommandOptions(argc, argv, opts); handleCommandOptions(argc, argv, opts);
preinitDLL(console); preinitDLL(console);
settings.init();
logConfig.configure(); logConfig.configure();
loadDLLClasses(); loadDLLClasses();