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

Handle corrupted H3 data - show message box instead of silent crash

This commit is contained in:
Ivan Savenko 2024-05-13 15:41:47 +00:00
parent 0aa7362adf
commit 95d761bbb8
4 changed files with 48 additions and 10 deletions

View File

@ -31,6 +31,7 @@
#include "../lib/CConfigHandler.h"
#include "../lib/CGeneralTextHandler.h"
#include "../lib/CThreadHelper.h"
#include "../lib/ExceptionsCommon.h"
#include "../lib/VCMIDirs.h"
#include "../lib/VCMI_Lib.h"
#include "../lib/filesystem/Filesystem.h"
@ -56,6 +57,7 @@ namespace po = boost::program_options;
namespace po_style = boost::program_options::command_line_style;
static std::atomic<bool> headlessQuit = false;
static std::optional<std::string> criticalInitializationError;
#ifndef VCMI_IOS
void processCommand(const std::string &message);
@ -69,9 +71,16 @@ static CBasicLogConfigurator *logConfig;
void init()
{
CStopWatch tmh;
loadDLLClasses();
CGI->setFromLib();
try
{
loadDLLClasses();
CGI->setFromLib();
}
catch (const DataLoadingException & e)
{
criticalInitializationError = e.what();
return;
}
logGlobal->info("Initializing VCMI_Lib: %d ms", tmh.getDiff());
@ -322,6 +331,11 @@ int main(int argc, char * argv[])
#endif // ANDROID
#endif // THREADED
if (criticalInitializationError.has_value())
{
handleFatalError(criticalInitializationError.value(), false);
}
if(!settings["session"]["headless"].Bool())
{
pomtime.getDiff();
@ -412,7 +426,7 @@ static void mainLoop()
}
}
[[noreturn]] static void quitApplicationImmediately()
[[noreturn]] static void quitApplicationImmediately(int error_code)
{
// Perform quick exit without executing static destructors and let OS cleanup anything that we did not
// We generally don't care about them and this leads to numerous issues, e.g.
@ -420,9 +434,9 @@ static void mainLoop()
// Android - std::quick_exit is available only starting from API level 21
// Mingw, macOS and iOS - std::quick_exit is unavailable (at least in current version of CI)
#if (defined(__ANDROID_API__) && __ANDROID_API__ < 21) || (defined(__MINGW32__)) || defined(VCMI_APPLE)
::exit(0);
::exit(error_code);
#else
std::quick_exit(0);
std::quick_exit(error_code);
#endif
}
@ -476,7 +490,7 @@ static void mainLoop()
}
std::cout << "Ending...\n";
quitApplicationImmediately();
quitApplicationImmediately(0);
}
void handleQuit(bool ask)
@ -500,7 +514,7 @@ void handleQuit(bool ask)
// proper solution would be to abort init thread (or wait for it to finish)
if (!CCS->curh)
{
quitApplicationImmediately();
quitApplicationImmediately(0);
}
if (LOCPLINT)
@ -521,5 +535,5 @@ void handleFatalError(const std::string & message, bool terminate)
if (terminate)
throw std::runtime_error(message);
else
exit(1);
quitApplicationImmediately(1);
}

View File

@ -12,6 +12,7 @@
#include "ArtifactUtils.h"
#include "CGeneralTextHandler.h"
#include "ExceptionsCommon.h"
#include "GameSettings.h"
#include "mapObjects/MapObjects.h"
#include "constants/StringConstants.h"
@ -354,7 +355,13 @@ std::vector<JsonNode> CArtHandler::loadLegacyData()
artData["slot"].Vector().emplace_back(artSlot);
}
}
artData["class"].String() = classes.at(parser.readString()[0]);
std::string artClass = parser.readString();
if (classes.count(artClass[0]))
artData["class"].String() = classes.at(artClass[0]);
else
throw DataLoadingException("File ARTRAITS.TXT is invalid or corrupted! Please reinstall Heroes III data files");
artData["text"]["description"].String() = parser.readString();
parser.endLine();

View File

@ -660,6 +660,7 @@ set(lib_MAIN_HEADERS
CStack.h
CStopWatch.h
CTownHandler.h
ExceptionsCommon.h
ExtraOptionsInfo.h
FunctionList.h
GameCallbackHolder.h

16
lib/ExceptionsCommon.h Normal file
View File

@ -0,0 +1,16 @@
/*
* ExceptionsCommon.h, part of VCMI engine
*
* Authors: listed in file AUTHORS in main folder
*
* License: GNU General Public License v2.0 or later
* Full text of license available in license.txt file, in main folder
*
*/
#pragma once
class DLL_LINKAGE DataLoadingException: public std::runtime_error
{
public:
using std::runtime_error::runtime_error;
};