1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-12-28 23:06:24 +02:00

Redesign mod incompatibility message

This commit is contained in:
nordsoft 2023-09-23 00:32:48 +02:00
parent 60eef59bc9
commit dce1ac1538
16 changed files with 101 additions and 57 deletions

View File

@ -30,9 +30,9 @@
"vcmi.capitalColors.6" : "褐色",
"vcmi.capitalColors.7" : "粉色",
"vcmi.server.errors.existingProcess" : "一个VCMI进程已经在运行,启动新进程前请结束它。",
"vcmi.server.errors.modsIncompatibility" : "需要加载的MOD列表:",
"vcmi.server.confirmReconnect" : "您想要重连上一个会话么?",
"vcmi.server.errors.existingProcess" : "一个VCMI进程已经在运行,启动新进程前请结束它。",
"vcmi.server.errors.modsToEnable" : "{需要加载的MOD列表}",
"vcmi.server.confirmReconnect" : "您想要重连上一个会话么?",
"vcmi.settingsMainWindow.generalTab.hover" : "常规",
"vcmi.settingsMainWindow.generalTab.help" : "切换到“常规”选项卡 - 设置游戏客户端呈现",

View File

@ -48,9 +48,9 @@
"vcmi.lobby.filename" : "Název souboru",
"vcmi.lobby.creationDate" : "Datum vytvoření",
"vcmi.server.errors.existingProcess" : "Již běží jiný server VCMI. Prosím, ukončete ho před startem nové hry.",
"vcmi.server.errors.modsIncompatibility" : "Následující modifikace jsou nutné pro načtení hry:",
"vcmi.server.confirmReconnect" : "Chcete se připojit k poslední relaci?",
"vcmi.server.errors.existingProcess" : "Již běží jiný server VCMI. Prosím, ukončete ho před startem nové hry.",
"vcmi.server.errors.modsToEnable" : "{Následující modifikace jsou nutné pro načtení hry}",
"vcmi.server.confirmReconnect" : "Chcete se připojit k poslední relaci?",
"vcmi.settingsMainWindow.generalTab.hover" : "Obecné",
"vcmi.settingsMainWindow.generalTab.help" : "Přepne na kartu obecných nastavení, která obsahuje nastavení související s obecným chováním klienta hry",

View File

@ -53,9 +53,10 @@
"vcmi.lobby.filename" : "Filename",
"vcmi.lobby.creationDate" : "Creation date",
"vcmi.server.errors.existingProcess" : "Another VCMI server process is running. Please terminate it before starting a new game.",
"vcmi.server.errors.modsIncompatibility" : "The following mods are required to load the game:",
"vcmi.server.confirmReconnect" : "Do you want to reconnect to the last session?",
"vcmi.server.errors.existingProcess" : "Another VCMI server process is running. Please terminate it before starting a new game.",
"vcmi.server.errors.modsToEnable" : "{Following mods are required}",
"vcmi.server.errors.modsToDisable" : "{Following mods must be disabled}",
"vcmi.server.confirmReconnect" : "Do you want to reconnect to the last session?",
"vcmi.settingsMainWindow.generalTab.hover" : "General",
"vcmi.settingsMainWindow.generalTab.help" : "Switches to General Options tab, which contains settings related to general game client behavior.",

View File

@ -38,9 +38,9 @@
"vcmi.mainMenu.joinTCP" : "Rejoindre TCP/IP jeu",
"vcmi.mainMenu.playerName" : "Joueur",
"vcmi.server.errors.existingProcess" : "Un autre processus de serveur VCMI est en cours d'exécution. Veuillez l'arrêter' avant de démarrer un nouveau jeu.",
"vcmi.server.errors.modsIncompatibility" : "Les mods suivants sont nécessaires pour charger le jeu :",
"vcmi.server.confirmReconnect" : "Voulez-vous vous reconnecter à la dernière session ?",
"vcmi.server.errors.existingProcess" : "Un autre processus de serveur VCMI est en cours d'exécution. Veuillez l'arrêter' avant de démarrer un nouveau jeu.",
"vcmi.server.errors.modsToEnable" : "{Les mods suivants sont nécessaires pour charger le jeu}",
"vcmi.server.confirmReconnect" : "Voulez-vous vous reconnecter à la dernière session ?",
"vcmi.settingsMainWindow.generalTab.hover" : "Général",
"vcmi.settingsMainWindow.generalTab.help" : "Passe à l'onglet Options générales, qui contient des paramètres liés au comportement général du client de jeu",

View File

@ -52,9 +52,9 @@
"vcmi.lobby.filename" : "Dateiname",
"vcmi.lobby.creationDate" : "Erstellungsdatum",
"vcmi.server.errors.existingProcess" : "Es läuft ein weiterer vcmiserver-Prozess, bitte beendet diesen zuerst",
"vcmi.server.errors.modsIncompatibility" : "Erforderliche Mods um das Spiel zu laden:",
"vcmi.server.confirmReconnect" : "Mit der letzten Sitzung verbinden?",
"vcmi.server.errors.existingProcess" : "Es läuft ein weiterer vcmiserver-Prozess, bitte beendet diesen zuerst",
"vcmi.server.errors.modsToEnable" : "{Erforderliche Mods um das Spiel zu laden}",
"vcmi.server.confirmReconnect" : "Mit der letzten Sitzung verbinden?",
"vcmi.settingsMainWindow.generalTab.hover" : "Allgemein",
"vcmi.settingsMainWindow.generalTab.help" : "Wechselt zur Registerkarte Allgemeine Optionen, die Einstellungen zum allgemeinen Verhalten des Spielclients enthält.",

View File

@ -47,9 +47,9 @@
"vcmi.lobby.filename" : "Nazwa pliku",
"vcmi.lobby.creationDate" : "Data utworzenia",
"vcmi.server.errors.existingProcess" : "Inny proces 'vcmiserver' został już uruchomiony, zakończ go nim przejdziesz dalej",
"vcmi.server.errors.modsIncompatibility" : "Następujące mody są wymagane do wczytania gry:",
"vcmi.server.confirmReconnect" : "Połączyć ponownie z ostatnią sesją?",
"vcmi.server.errors.existingProcess" : "Inny proces 'vcmiserver' został już uruchomiony, zakończ go nim przejdziesz dalej",
"vcmi.server.errors.modsToEnable" : "{Następujące mody są wymagane do wczytania gry}",
"vcmi.server.confirmReconnect" : "Połączyć ponownie z ostatnią sesją?",
"vcmi.settingsMainWindow.generalTab.hover" : "Ogólne",
"vcmi.settingsMainWindow.generalTab.help" : "Przełącza do zakładki opcji ogólnych, która zawiera ustawienia związane z ogólnym działaniem gry",

View File

@ -21,9 +21,9 @@
"vcmi.adventureMap.moveCostDetails" : "Очки движения - Стоимость: %TURNS ходов + %POINTS очков, Останется: %REMAINING очков",
"vcmi.adventureMap.moveCostDetailsNoTurns" : "Очки движения - Стоимость: %POINTS очков, Останется: %REMAINING очков",
"vcmi.server.errors.existingProcess" : "Запущен другой процесс vcmiserver, сначала завершите его.",
"vcmi.server.errors.modsIncompatibility" : "Требуемые моды для загрузки игры:",
"vcmi.server.confirmReconnect" : "Подключиться к предыдущей сессии?",
"vcmi.server.errors.existingProcess" : "Запущен другой процесс vcmiserver, сначала завершите его.",
"vcmi.server.errors.modsToEnable" : "{Требуемые моды для загрузки игры}",
"vcmi.server.confirmReconnect" : "Подключиться к предыдущей сессии?",
"vcmi.settingsMainWindow.generalTab.hover" : "Общее",
"vcmi.settingsMainWindow.generalTab.help" : "Переключиться на вкладку \"Общее\", содержащее общие настройки клиента игры",

View File

@ -30,9 +30,9 @@
"vcmi.capitalColors.6" : "Turquesa",
"vcmi.capitalColors.7" : "Rosa",
"vcmi.server.errors.existingProcess" : "Otro proceso de vcmiserver está en ejecución, por favor termínalo primero",
"vcmi.server.errors.modsIncompatibility" : "Mods necesarios para cargar el juego:",
"vcmi.server.confirmReconnect" : "¿Conectar a la última sesión?",
"vcmi.server.errors.existingProcess" : "Otro proceso de vcmiserver está en ejecución, por favor termínalo primero",
"vcmi.server.errors.modsToEnable" : "{Mods necesarios para cargar el juego}",
"vcmi.server.confirmReconnect" : "¿Conectar a la última sesión?",
"vcmi.settingsMainWindow.generalTab.hover" : "General",
"vcmi.settingsMainWindow.generalTab.help" : "Cambiar a la pestaña de opciones generales, que contiene ajustes relacionados con el comportamiento general del juego",

View File

@ -48,9 +48,9 @@
"vcmi.lobby.filename" : "Назва файлу",
"vcmi.lobby.creationDate" : "Дата створення",
"vcmi.server.errors.existingProcess" : "Працює інший процес vcmiserver, будь ласка, спочатку завершіть його",
"vcmi.server.errors.modsIncompatibility" : "Потрібні модифікації для завантаження гри:",
"vcmi.server.confirmReconnect" : "Підключитися до минулої сесії?",
"vcmi.server.errors.existingProcess" : "Працює інший процес vcmiserver, будь ласка, спочатку завершіть його",
"vcmi.server.errors.modsToEnable" : "{Потрібні модифікації для завантаження гри}",
"vcmi.server.confirmReconnect" : "Підключитися до минулої сесії?",
"vcmi.settingsMainWindow.generalTab.hover" : "Загальні",
"vcmi.settingsMainWindow.generalTab.help" : "Перемикає на вкладку загальних параметрів, яка містить налаштування, пов'язані із загальною поведінкою ігрового клієнта",

View File

@ -552,10 +552,17 @@ bool CServerHandler::validateGameStart(bool allowOnlyAI) const
catch(ModIncompatibility & e)
{
logGlobal->warn("Incompatibility exception during start scenario: %s", e.what());
auto errorMsg = CGI->generaltexth->translate("vcmi.server.errors.modsIncompatibility") + '\n';
errorMsg += e.what();
std::string errorMsg;
if(!e.whatMissing().empty())
{
errorMsg += VLC->generaltexth->translate("vcmi.server.errors.modsToEnable") + '\n';
errorMsg += e.whatMissing();
}
if(!e.whatExcessive().empty())
{
errorMsg += VLC->generaltexth->translate("vcmi.server.errors.modsToDisable") + '\n';
errorMsg += e.whatExcessive();
}
showServerError(errorMsg);
return false;
}

View File

@ -29,7 +29,6 @@
#include "../../lib/CGeneralTextHandler.h"
#include "../../lib/campaign/CampaignHandler.h"
#include "../../lib/mapping/CMapInfo.h"
#include "../../lib/modding/ModIncompatibility.h"
#include "../../lib/rmg/CMapGenOptions.h"
CLobbyScreen::CLobbyScreen(ESelectionScreen screenType)

View File

@ -74,12 +74,12 @@ void LobbyInfo::verifyStateBeforeStart(bool ignoreNoHuman) const
throw std::domain_error(VLC->generaltexth->translate("core.genrltxt.529"));
auto missingMods = CMapService::verifyMapHeaderMods(*mi->mapHeader);
ModIncompatibility::ModList modList;
ModIncompatibility::ModListWithVersion modList;
for(const auto & m : missingMods)
modList.push_back({m.second.name, m.second.version.toString()});
if(!modList.empty())
throw ModIncompatibility(std::move(modList));
throw ModIncompatibility(modList);
//there must be at least one human player before game can be started
std::map<PlayerColor, PlayerSettings>::const_iterator i;

View File

@ -481,6 +481,10 @@ void CModHandler::trySetActiveMods(const std::vector<std::pair<TModID, CModInfo:
return nullptr;
};
std::vector<TModID> newActiveMods, missingMods, excessiveMods;
ModIncompatibility::ModListWithVersion missingModsResult;
ModIncompatibility::ModList excessiveModsResult;
for(const auto & m : activeMods)
{
if(searchVerificationInfo(m))
@ -488,11 +492,11 @@ void CModHandler::trySetActiveMods(const std::vector<std::pair<TModID, CModInfo:
//TODO: support actual disabling of these mods
if(getModInfo(m).checkModGameplayAffecting())
{
excessiveMods.push_back(m);
allMods[m].setEnabled(false);
}
}
std::vector<TModID> newActiveMods, missingMods;
ModIncompatibility::ModList missingModsResult;
for(const auto & infoPair : modList)
{
@ -539,9 +543,17 @@ void CModHandler::trySetActiveMods(const std::vector<std::pair<TModID, CModInfo:
missingModsResult.push_back({vInfo->name, vInfo->version.toString()});
}
}
for(auto & m : excessiveMods)
{
auto & vInfo = getModInfo(m).getVerificationInfo();
assert(vInfo.parent != m);
if(!vInfo.parent.empty() && vstd::contains(excessiveMods, vInfo.parent))
continue;
excessiveModsResult.push_back(vInfo.name);
}
if(!missingModsResult.empty())
throw ModIncompatibility(std::move(missingModsResult));
if(!missingModsResult.empty() || !excessiveModsResult.empty())
throw ModIncompatibility(missingModsResult, excessiveModsResult);
//TODO: support actual enabling of these mods
for(auto & m : newActiveMods)

View File

@ -14,29 +14,44 @@ VCMI_LIB_NAMESPACE_BEGIN
class DLL_LINKAGE ModIncompatibility: public std::exception
{
public:
using StringPair = std::pair<const std::string, const std::string>;
using ModList = std::list<StringPair>;
using ModListWithVersion = std::vector<std::pair<const std::string, const std::string>>;
using ModList = std::vector<const std::string>;
ModIncompatibility(ModList && _missingMods):
missingMods(std::move(_missingMods))
ModIncompatibility(const ModListWithVersion & _missingMods)
{
std::ostringstream _ss;
for(const auto & m : missingMods)
for(const auto & m : _missingMods)
_ss << m.first << ' ' << m.second << std::endl;
message = _ss.str();
messageMissingMods = _ss.str();
}
ModIncompatibility(const ModListWithVersion & _missingMods, ModList & _excessiveMods)
: ModIncompatibility(_missingMods)
{
std::ostringstream _ss;
for(const auto & m : _excessiveMods)
_ss << m << std::endl;
messageExcessiveMods = _ss.str();
}
const char * what() const noexcept override
{
return message.c_str();
static const std::string w("Mod incompatibility exception");
return w.c_str();
}
const std::string & whatMissing() const noexcept
{
return messageMissingMods;
}
const std::string & whatExcessive() const noexcept
{
return messageExcessiveMods;
}
private:
//list of mods required to load the game
// first: mod name
// second: mod version
const ModList missingMods;
std::string message;
std::string messageMissingMods, messageExcessiveMods;
};
VCMI_LIB_NAMESPACE_END

View File

@ -336,19 +336,20 @@ bool MainWindow::openMap(const QString & filenameSelect)
if(auto header = mapService.loadMapHeader(resId))
{
auto missingMods = CMapService::verifyMapHeaderMods(*header);
ModIncompatibility::ModList modList;
ModIncompatibility::ModListWithVersion modList;
for(const auto & m : missingMods)
modList.push_back({m.second.name, m.second.version.toString()});
if(!modList.empty())
throw ModIncompatibility(std::move(modList));
throw ModIncompatibility(modList);
controller.setMap(mapService.loadMap(resId));
}
}
catch(const ModIncompatibility & e)
{
QMessageBox::warning(this, "Mods requiered", e.what());
assert(e.whatExcessive().empty());
QMessageBox::warning(this, "Mods are requiered", QString::fromStdString(e.whatMissing()));
return false;
}
catch(const std::exception & e)

View File

@ -1765,8 +1765,17 @@ bool CGameHandler::load(const std::string & filename)
catch(const ModIncompatibility & e)
{
logGlobal->error("Failed to load game: %s", e.what());
auto errorMsg = VLC->generaltexth->translate("vcmi.server.errors.modsIncompatibility") + '\n';
errorMsg += e.what();
std::string errorMsg;
if(!e.whatMissing().empty())
{
errorMsg += VLC->generaltexth->translate("vcmi.server.errors.modsToEnable") + '\n';
errorMsg += e.whatMissing();
}
if(!e.whatExcessive().empty())
{
errorMsg += VLC->generaltexth->translate("vcmi.server.errors.modsToDisable") + '\n';
errorMsg += e.whatExcessive();
}
lobby->announceMessage(errorMsg);
return false;
}