From e75d8496797732cb2463956f3986f022529bdb6b Mon Sep 17 00:00:00 2001 From: maj00r Date: Tue, 3 Nov 2026 21:45:57 +0100 Subject: [PATCH] fix(app): a scenery file named in another case than given is found, a scenario that can't be opened goes back to the launcher The command line gives the name of the scenery lowercased, and the sceneries made on Windows name their files and includes in any case: on a case-sensitive filesystem they weren't found. FileCased() finds the file whose name differs only in case; the parser and the scenario loader use it. A scenario that can't be opened logs the reason and goes back to the launcher instead of ending with an exception. --- application/scenarioloadermode.cpp | 16 +++++++++++++++- utilities/parser.cpp | 9 +++++++++ utilities/utilities.cpp | 14 ++++++++++++++ utilities/utilities.h | 3 +++ 4 files changed, 41 insertions(+), 1 deletion(-) diff --git a/application/scenarioloadermode.cpp b/application/scenarioloadermode.cpp index dbdce606..7afe0a44 100644 --- a/application/scenarioloadermode.cpp +++ b/application/scenarioloadermode.cpp @@ -41,11 +41,25 @@ bool scenarioloader_mode::update() { WriteLog("using simulation seed: " + std::to_string(Global.random_seed), logtype::generic); WriteLog("using simulation starting timestamp: " + std::to_string(Global.starting_timestamp), logtype::generic); + // the command line gives the name lowercased, the file may be named in another case, as a scenery made on Windows; + // the scenery is saved back to its own file then + if (auto const cased{FileCased(Global.asCurrentSceneryPath + Global.SceneryFile)}; cased.size() > Global.asCurrentSceneryPath.size()) + Global.SceneryFile = cased.substr(Global.asCurrentSceneryPath.size()); Application.set_title( Global.AppName + " (" + Global.SceneryFile + ")" ); WriteLog( "\nLoading scenario \"" + Global.SceneryFile + "\"..." ); timestart = std::chrono::system_clock::now(); - state = simulation::State.deserialize_begin(Global.SceneryFile); + try { + state = simulation::State.deserialize_begin(Global.SceneryFile); + } + catch (std::exception const &e) { + ErrorLog("Bad init: scenario \"" + Global.SceneryFile + "\" couldn't be opened (" + e.what() + ")"); + state.reset(); + Global.SceneryFile.clear(); + Application.pop_mode(); + Application.push_mode(eu07_application::mode::launcher); + return true; + } } try { diff --git a/utilities/parser.cpp b/utilities/parser.cpp index b64aee39..ee5a9ce5 100644 --- a/utilities/parser.cpp +++ b/utilities/parser.cpp @@ -63,6 +63,15 @@ cParser::cParser(std::string const &Stream, buffertype const Type, std::string P // the file is read in one go, tokens are then extracted straight from the memory std::ifstream file(Path, std::ios_base::binary); if (file.fail()) + { + // named in another case than it's on the disk + if (auto const cased{FileCased(Path)}; false == cased.empty()) + { + file.clear(); + file.open(cased, std::ios_base::binary); + } + } + if (file.fail()) { mFailBit = true; } diff --git a/utilities/utilities.cpp b/utilities/utilities.cpp index 02608262..0c18e002 100644 --- a/utilities/utilities.cpp +++ b/utilities/utilities.cpp @@ -471,6 +471,20 @@ bool FileExists(std::string const &Filename) return std::filesystem::exists(Filename); } +std::string FileCased(std::string const &Filename) +{ + std::error_code error; + if (std::filesystem::exists(Filename, error)) + return Filename; + std::filesystem::path const path{Filename}; + auto const directory{path.has_parent_path() ? path.parent_path() : std::filesystem::path{"."}}; + auto const wanted{ToLower(path.filename().string())}; + for (std::filesystem::directory_iterator entry{directory, error}, end; entry != end; entry.increment(error)) + if (ToLower(entry->path().filename().string()) == wanted) + return path.has_parent_path() ? (directory / entry->path().filename()).string() : entry->path().filename().string(); + return {}; +} + std::pair FileExists(std::vector const &Names, std::vector const &Extensions) { diff --git a/utilities/utilities.h b/utilities/utilities.h index 5392ba6c..d98b7bc9 100644 --- a/utilities/utilities.h +++ b/utilities/utilities.h @@ -217,6 +217,9 @@ template bool extract_value(Type_ &Variable, std::string const template <> bool extract_value(bool &Variable, std::string const &Key, std::string const &Input, std::string const &Default); bool FileExists(std::string const &Filename); +// the file as it's named on the disk when only the case of its name differs, as in the sceneries made on Windows; empty when +// there's none +std::string FileCased(std::string const &Filename); std::pair FileExists(std::vector const &Names, std::vector const &Extensions);