mirror of
https://github.com/vcmi/vcmi.git
synced 2025-01-14 02:33:51 +02:00
Merge pull request #3193 from IvanSavenko/warn_mod_dependencies
Show message about mods that failed to load on opening main menu
This commit is contained in:
commit
de02507fff
@ -73,6 +73,8 @@
|
|||||||
"vcmi.server.errors.modsToEnable" : "{Following mods are required}",
|
"vcmi.server.errors.modsToEnable" : "{Following mods are required}",
|
||||||
"vcmi.server.errors.modsToDisable" : "{Following mods must be disabled}",
|
"vcmi.server.errors.modsToDisable" : "{Following mods must be disabled}",
|
||||||
"vcmi.server.confirmReconnect" : "Do you want to reconnect to the last session?",
|
"vcmi.server.confirmReconnect" : "Do you want to reconnect to the last session?",
|
||||||
|
"vcmi.server.errors.modNoDependency" : "Failed to load mod {'%s'}!\n It depends on mod {'%s'} which is not active!\n",
|
||||||
|
"vcmi.server.errors.modConflict" : "Failed to load mod {'%s'}!\n Conflicts with active mod {'%s'}!\n",
|
||||||
|
|
||||||
"vcmi.settingsMainWindow.generalTab.hover" : "General",
|
"vcmi.settingsMainWindow.generalTab.hover" : "General",
|
||||||
"vcmi.settingsMainWindow.generalTab.help" : "Switches to General Options tab, which contains settings related to general game client behavior.",
|
"vcmi.settingsMainWindow.generalTab.help" : "Switches to General Options tab, which contains settings related to general game client behavior.",
|
||||||
|
@ -73,6 +73,8 @@
|
|||||||
"vcmi.server.errors.modsToEnable" : "{Потрібні модифікації для завантаження гри}",
|
"vcmi.server.errors.modsToEnable" : "{Потрібні модифікації для завантаження гри}",
|
||||||
"vcmi.server.errors.modsToDisable" : "{Модифікації що мають бути вимкнені}",
|
"vcmi.server.errors.modsToDisable" : "{Модифікації що мають бути вимкнені}",
|
||||||
"vcmi.server.confirmReconnect" : "Підключитися до минулої сесії?",
|
"vcmi.server.confirmReconnect" : "Підключитися до минулої сесії?",
|
||||||
|
"vcmi.server.errors.modNoDependency" : "Не вдалося увімкнути мод {'%s'}!\n Модифікація потребує мод {'%s'} який зараз не активний!\n",
|
||||||
|
"vcmi.server.errors.modConflict" : "Не вдалося увімкнути мод {'%s'}!\n Конфліктує з активним модом {'%s'}!\n",
|
||||||
|
|
||||||
"vcmi.settingsMainWindow.generalTab.hover" : "Загальні",
|
"vcmi.settingsMainWindow.generalTab.hover" : "Загальні",
|
||||||
"vcmi.settingsMainWindow.generalTab.help" : "Перемикає на вкладку загальних параметрів, яка містить налаштування, пов'язані із загальною поведінкою ігрового клієнта",
|
"vcmi.settingsMainWindow.generalTab.help" : "Перемикає на вкладку загальних параметрів, яка містить налаштування, пов'язані із загальною поведінкою ігрового клієнта",
|
||||||
|
@ -49,6 +49,7 @@
|
|||||||
#include "../../lib/filesystem/Filesystem.h"
|
#include "../../lib/filesystem/Filesystem.h"
|
||||||
#include "../../lib/filesystem/CCompressedStream.h"
|
#include "../../lib/filesystem/CCompressedStream.h"
|
||||||
#include "../../lib/mapping/CMapInfo.h"
|
#include "../../lib/mapping/CMapInfo.h"
|
||||||
|
#include "../../lib/modding/CModHandler.h"
|
||||||
#include "../../lib/VCMIDirs.h"
|
#include "../../lib/VCMIDirs.h"
|
||||||
#include "../../lib/CStopWatch.h"
|
#include "../../lib/CStopWatch.h"
|
||||||
#include "../../lib/CThreadHelper.h"
|
#include "../../lib/CThreadHelper.h"
|
||||||
@ -339,6 +340,17 @@ void CMainMenu::update()
|
|||||||
menu->switchToTab(menu->getActiveTab());
|
menu->switchToTab(menu->getActiveTab());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool warnedAboutModDependencies = false;
|
||||||
|
|
||||||
|
if (!warnedAboutModDependencies)
|
||||||
|
{
|
||||||
|
warnedAboutModDependencies = true;
|
||||||
|
auto errorMessages = CGI->modh->getModLoadErrors();
|
||||||
|
|
||||||
|
if (!errorMessages.empty())
|
||||||
|
CInfoWindow::showInfoDialog(errorMessages, std::vector<std::shared_ptr<CComponent>>(), PlayerColor(1));
|
||||||
|
}
|
||||||
|
|
||||||
// Handles mouse and key input
|
// Handles mouse and key input
|
||||||
GH.handleEvents();
|
GH.handleEvents();
|
||||||
GH.windows().simpleRedraw();
|
GH.windows().simpleRedraw();
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
#include "../CStopWatch.h"
|
#include "../CStopWatch.h"
|
||||||
#include "../GameSettings.h"
|
#include "../GameSettings.h"
|
||||||
#include "../Languages.h"
|
#include "../Languages.h"
|
||||||
|
#include "../MetaString.h"
|
||||||
#include "../ScriptHandler.h"
|
#include "../ScriptHandler.h"
|
||||||
#include "../constants/StringConstants.h"
|
#include "../constants/StringConstants.h"
|
||||||
#include "../filesystem/Filesystem.h"
|
#include "../filesystem/Filesystem.h"
|
||||||
@ -133,6 +134,24 @@ std::vector <TModID> CModHandler::validateAndSortDependencies(std::vector <TModI
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
modLoadErrors = std::make_unique<MetaString>();
|
||||||
|
|
||||||
|
auto addErrorMessage = [this](const std::string & textID, const std::string & brokenModID, const std::string & missingModID)
|
||||||
|
{
|
||||||
|
modLoadErrors->appendTextID(textID);
|
||||||
|
|
||||||
|
if (allMods.count(brokenModID))
|
||||||
|
modLoadErrors->replaceRawString(allMods.at(brokenModID).getVerificationInfo().name);
|
||||||
|
else
|
||||||
|
modLoadErrors->replaceRawString(brokenModID);
|
||||||
|
|
||||||
|
if (allMods.count(missingModID))
|
||||||
|
modLoadErrors->replaceRawString(allMods.at(missingModID).getVerificationInfo().name);
|
||||||
|
else
|
||||||
|
modLoadErrors->replaceRawString(missingModID);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
// Left mods have unresolved dependencies, output all to log.
|
// Left mods have unresolved dependencies, output all to log.
|
||||||
for(const auto & brokenModID : modsToResolve)
|
for(const auto & brokenModID : modsToResolve)
|
||||||
{
|
{
|
||||||
@ -140,17 +159,17 @@ std::vector <TModID> CModHandler::validateAndSortDependencies(std::vector <TModI
|
|||||||
for(const TModID & dependency : brokenMod.dependencies)
|
for(const TModID & dependency : brokenMod.dependencies)
|
||||||
{
|
{
|
||||||
if(!vstd::contains(resolvedModIDs, dependency) && brokenMod.config["modType"].String() != "Compatibility")
|
if(!vstd::contains(resolvedModIDs, dependency) && brokenMod.config["modType"].String() != "Compatibility")
|
||||||
logMod->error("Mod '%s' has been disabled: dependency '%s' is missing.", brokenMod.getVerificationInfo().name, dependency);
|
addErrorMessage("vcmi.server.errors.modNoDependency", brokenModID, dependency);
|
||||||
}
|
}
|
||||||
for(const TModID & conflict : brokenMod.conflicts)
|
for(const TModID & conflict : brokenMod.conflicts)
|
||||||
{
|
{
|
||||||
if(vstd::contains(resolvedModIDs, conflict))
|
if(vstd::contains(resolvedModIDs, conflict))
|
||||||
logMod->error("Mod '%s' has been disabled: conflicts with enabled mod '%s'.", brokenMod.getVerificationInfo().name, conflict);
|
addErrorMessage("vcmi.server.errors.modConflict", brokenModID, conflict);
|
||||||
}
|
}
|
||||||
for(const TModID & reverseConflict : resolvedModIDs)
|
for(const TModID & reverseConflict : resolvedModIDs)
|
||||||
{
|
{
|
||||||
if (vstd::contains(allMods.at(reverseConflict).conflicts, brokenModID))
|
if (vstd::contains(allMods.at(reverseConflict).conflicts, brokenModID))
|
||||||
logMod->error("Mod '%s' has been disabled: conflicts with enabled mod '%s'.", brokenMod.getVerificationInfo().name, reverseConflict);
|
addErrorMessage("vcmi.server.errors.modConflict", brokenModID, reverseConflict);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return sortedValidMods;
|
return sortedValidMods;
|
||||||
@ -235,7 +254,7 @@ void CModHandler::loadMods(bool onlyEssential)
|
|||||||
coreMod = std::make_unique<CModInfo>(ModScope::scopeBuiltin(), modConfig[ModScope::scopeBuiltin()], JsonNode(JsonPath::builtin("config/gameConfig.json")));
|
coreMod = std::make_unique<CModInfo>(ModScope::scopeBuiltin(), modConfig[ModScope::scopeBuiltin()], JsonNode(JsonPath::builtin("config/gameConfig.json")));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string> CModHandler::getAllMods()
|
std::vector<std::string> CModHandler::getAllMods() const
|
||||||
{
|
{
|
||||||
std::vector<std::string> modlist;
|
std::vector<std::string> modlist;
|
||||||
modlist.reserve(allMods.size());
|
modlist.reserve(allMods.size());
|
||||||
@ -244,11 +263,16 @@ std::vector<std::string> CModHandler::getAllMods()
|
|||||||
return modlist;
|
return modlist;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string> CModHandler::getActiveMods()
|
std::vector<std::string> CModHandler::getActiveMods() const
|
||||||
{
|
{
|
||||||
return activeMods;
|
return activeMods;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string CModHandler::getModLoadErrors() const
|
||||||
|
{
|
||||||
|
return modLoadErrors->toString();
|
||||||
|
}
|
||||||
|
|
||||||
const CModInfo & CModHandler::getModInfo(const TModID & modId) const
|
const CModInfo & CModHandler::getModInfo(const TModID & modId) const
|
||||||
{
|
{
|
||||||
return allMods.at(modId);
|
return allMods.at(modId);
|
||||||
@ -320,7 +344,7 @@ void CModHandler::loadModFilesystems()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TModID CModHandler::findResourceOrigin(const ResourcePath & name)
|
TModID CModHandler::findResourceOrigin(const ResourcePath & name) const
|
||||||
{
|
{
|
||||||
for(const auto & modID : boost::adaptors::reverse(activeMods))
|
for(const auto & modID : boost::adaptors::reverse(activeMods))
|
||||||
{
|
{
|
||||||
|
@ -21,6 +21,7 @@ class CIdentifierStorage;
|
|||||||
class CContentHandler;
|
class CContentHandler;
|
||||||
struct ModVerificationInfo;
|
struct ModVerificationInfo;
|
||||||
class ResourcePath;
|
class ResourcePath;
|
||||||
|
class MetaString;
|
||||||
|
|
||||||
using TModID = std::string;
|
using TModID = std::string;
|
||||||
|
|
||||||
@ -29,6 +30,7 @@ class DLL_LINKAGE CModHandler final : boost::noncopyable
|
|||||||
std::map <TModID, CModInfo> allMods;
|
std::map <TModID, CModInfo> allMods;
|
||||||
std::vector <TModID> activeMods;//active mods, in order in which they were loaded
|
std::vector <TModID> activeMods;//active mods, in order in which they were loaded
|
||||||
std::unique_ptr<CModInfo> coreMod;
|
std::unique_ptr<CModInfo> coreMod;
|
||||||
|
mutable std::unique_ptr<MetaString> modLoadErrors;
|
||||||
|
|
||||||
bool hasCircularDependency(const TModID & mod, std::set<TModID> currentList = std::set<TModID>()) const;
|
bool hasCircularDependency(const TModID & mod, std::set<TModID> currentList = std::set<TModID>()) const;
|
||||||
|
|
||||||
@ -60,15 +62,18 @@ public:
|
|||||||
void loadModFilesystems();
|
void loadModFilesystems();
|
||||||
|
|
||||||
/// returns ID of mod that provides selected file resource
|
/// returns ID of mod that provides selected file resource
|
||||||
TModID findResourceOrigin(const ResourcePath & name);
|
TModID findResourceOrigin(const ResourcePath & name) const;
|
||||||
|
|
||||||
std::string getModLanguage(const TModID & modId) const;
|
std::string getModLanguage(const TModID & modId) const;
|
||||||
|
|
||||||
std::set<TModID> getModDependencies(const TModID & modId, bool & isModFound) const;
|
std::set<TModID> getModDependencies(const TModID & modId, bool & isModFound) const;
|
||||||
|
|
||||||
/// returns list of all (active) mods
|
/// returns list of all (active) mods
|
||||||
std::vector<std::string> getAllMods();
|
std::vector<std::string> getAllMods() const;
|
||||||
std::vector<std::string> getActiveMods();
|
std::vector<std::string> getActiveMods() const;
|
||||||
|
|
||||||
|
/// Returns human-readable string that describes erros encounter during mod loading, such as missing dependencies
|
||||||
|
std::string getModLoadErrors() const;
|
||||||
|
|
||||||
const CModInfo & getModInfo(const TModID & modId) const;
|
const CModInfo & getModInfo(const TModID & modId) const;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user