diff --git a/src/frontend/ContentGfxCache.cpp b/src/frontend/ContentGfxCache.cpp index 844fd4e6..574c22a5 100644 --- a/src/frontend/ContentGfxCache.cpp +++ b/src/frontend/ContentGfxCache.cpp @@ -69,10 +69,6 @@ void ContentGfxCache::refresh() { ContentGfxCache::~ContentGfxCache() = default; -const Content* ContentGfxCache::getContent() const { - return &content; -} - const model::Model& ContentGfxCache::getModel(blockid_t id) const { const auto& found = models.find(id); if (found == models.end()) { diff --git a/src/frontend/ContentGfxCache.hpp b/src/frontend/ContentGfxCache.hpp index c1b17db3..b5816c82 100644 --- a/src/frontend/ContentGfxCache.hpp +++ b/src/frontend/ContentGfxCache.hpp @@ -38,8 +38,6 @@ public: const model::Model& getModel(blockid_t id) const; - const Content* getContent() const; - void refresh(const Block& block, const Atlas& atlas); void refresh(); diff --git a/src/frontend/LevelFrontend.cpp b/src/frontend/LevelFrontend.cpp index b796625c..5dfdf822 100644 --- a/src/frontend/LevelFrontend.cpp +++ b/src/frontend/LevelFrontend.cpp @@ -101,14 +101,6 @@ Level& LevelFrontend::getLevel() { return level; } -const Level& LevelFrontend::getLevel() const { - return level; -} - -const Assets& LevelFrontend::getAssets() const { - return assets; -} - ContentGfxCache& LevelFrontend::getContentGfxCache() { return *contentCache; } diff --git a/src/frontend/LevelFrontend.hpp b/src/frontend/LevelFrontend.hpp index da1f198a..cc4f996b 100644 --- a/src/frontend/LevelFrontend.hpp +++ b/src/frontend/LevelFrontend.hpp @@ -25,8 +25,6 @@ public: ~LevelFrontend(); Level& getLevel(); - const Level& getLevel() const; - const Assets& getAssets() const; const ContentGfxCache& getContentGfxCache() const; ContentGfxCache& getContentGfxCache(); LevelController* getController() const; diff --git a/src/frontend/menu.cpp b/src/frontend/menu.cpp index 9877cf60..62cf6959 100644 --- a/src/frontend/menu.cpp +++ b/src/frontend/menu.cpp @@ -32,13 +32,12 @@ void menus::create_version_label(gui::GUI& gui) { )); } -bool menus::call(Engine& engine, runnable func) { +void menus::call(Engine& engine, runnable func) { if (engine.isHeadless()) { throw std::runtime_error("menus::call(...) in headless mode"); } try { func(); - return true; } catch (const contentpack_error& error) { engine.setScreen(std::make_shared(engine)); // could not to find or read pack @@ -47,7 +46,7 @@ bool menus::call(Engine& engine, runnable func) { langs::get(L"error.pack-not-found") + L": " + util::str2wstr_utf8(error.getPackId()) ); - return false; + throw std::runtime_error(error); } catch (const assetload::error& error) { engine.setScreen(std::make_shared(engine)); guiutil::alert( @@ -55,11 +54,11 @@ bool menus::call(Engine& engine, runnable func) { langs::get(L"Assets Load Error", L"menu") + L":\n" + util::str2wstr_utf8(error.what()) ); - return false; + throw std::runtime_error(error); } catch (const parsing_error& error) { engine.setScreen(std::make_shared(engine)); guiutil::alert(engine, util::str2wstr_utf8(error.errorLog())); - return false; + throw std::runtime_error(error); } catch (const std::runtime_error& error) { engine.setScreen(std::make_shared(engine)); guiutil::alert( @@ -67,7 +66,7 @@ bool menus::call(Engine& engine, runnable func) { langs::get(L"Content Error", L"menu") + L":\n" + util::str2wstr_utf8(error.what()) ); - return false; + throw std::runtime_error(error); } } diff --git a/src/frontend/menu.hpp b/src/frontend/menu.hpp index b7fb4495..ea44c900 100644 --- a/src/frontend/menu.hpp +++ b/src/frontend/menu.hpp @@ -32,5 +32,5 @@ namespace menus { const std::wstring& text = L"" ); - bool call(Engine& engine, runnable func); + void call(Engine& engine, runnable func); } diff --git a/src/logic/EngineController.cpp b/src/logic/EngineController.cpp index 48bad7cf..4d9f8953 100644 --- a/src/logic/EngineController.cpp +++ b/src/logic/EngineController.cpp @@ -1,7 +1,6 @@ #include "EngineController.hpp" #include -#include #include #include "engine/Engine.hpp" @@ -26,12 +25,9 @@ #include "world/World.hpp" #include "LevelController.hpp" -namespace fs = std::filesystem; - static debug::Logger logger("engine-control"); -EngineController::EngineController(Engine& engine) : engine(engine) { -} +EngineController::EngineController(Engine& engine) : engine(engine) {} void EngineController::deleteWorld(const std::string& name) { io::path folder = engine.getPaths().getWorldFolderByName(name); @@ -83,65 +79,66 @@ std::shared_ptr create_converter( ); } -static void show_convert_request( - Engine& engine, - const Content* content, - const std::shared_ptr& report, - const std::shared_ptr& worldFiles, - const runnable& postRunnable -) { - auto on_confirm = [&engine, worldFiles, content, report, postRunnable]() { - auto converter = - create_converter(engine, worldFiles, content, report, postRunnable); - menus::show_process_panel( - engine, converter, L"Converting world..." - ); - }; +struct ConfirmRequest { + bool memo; + std::wstring message; + std::wstring text; +}; - std::wstring message = L"world.convert-block-layouts"; +static ConfirmRequest create_convert_request( + const std::shared_ptr& report +) { + ConfirmRequest request {false, L"", L""}; + + request.message = L"world.convert-block-layouts"; if (report->hasContentReorder()) { - message = L"world.convert-request"; + request.message = L"world.convert-request"; } if (report->isUpgradeRequired()) { - message = L"world.upgrade-request"; + request.message = L"world.upgrade-request"; } else if (report->hasDataLoss()) { - message = L"world.convert-with-loss"; - std::wstring text; + request.message = L"world.convert-with-loss"; + request.memo = true; for (const auto& line : report->getDataLoss()) { - text += util::str2wstr_utf8(line) + L"\n"; + request.text += util::str2wstr_utf8(line) + L"\n"; } - guiutil::confirm_with_memo( - engine, - langs::get(message), - text, - on_confirm, - L"", - langs::get(L"Cancel") - ); - return; } - guiutil::confirm( - engine, - langs::get(message), - on_confirm, - nullptr, - L"", - langs::get(L"Cancel") - ); + return request; } -static bool load_world_content(Engine& engine, const io::path& folder) { +static void call(Engine& engine, runnable func) { + if (engine.isHeadless()) { + func(); + } else { + menus::call(engine, std::move(func)); + } +} + +static void start(Engine& engine, std::shared_ptr task, const std::wstring& message) { + if (engine.isHeadless()) { + task->waitForEnd(); + } else { + menus::show_process_panel(engine, task, message); + } +} + +static void check_world(const EnginePaths& paths, const io::path& folder) { + auto worldFile = folder / "world.json"; + if (!io::exists(worldFile)) { + throw std::runtime_error(worldFile.string() + " does not exists"); + } +} + +static const Content* load_world_content(Engine& engine, const io::path& folder) { auto& paths = engine.getPaths(); auto& contentControl = engine.getContentControl(); paths.setCurrentWorldFolder(folder); - if (engine.isHeadless()) { + + check_world(paths, folder); + call(engine, [&contentControl]() { contentControl.loadContent(ContentPack::worldPacksList("world:")); - return true; - } else { - return menus::call(engine, [&contentControl]() { - contentControl.loadContent(ContentPack::worldPacksList("world:")); - }); - } + }); + return contentControl.get(); } static void load_world( @@ -149,21 +146,15 @@ static void load_world( const std::shared_ptr& worldFiles, int64_t localPlayer ) { - try { + call(engine, [&engine, worldFiles, localPlayer] () { auto& contentControl = engine.getContentControl(); auto content = contentControl.get(); - auto& packs = contentControl.getContentPacks(); + const auto& packs = contentControl.getContentPacks(); auto& settings = engine.getSettings(); auto level = World::load(worldFiles, settings, *content, packs); engine.onWorldOpen(std::move(level), localPlayer); - } catch (const world_load_error& error) { - guiutil::alert( - engine, - langs::get(L"Error") + L": " + util::str2wstr_utf8(error.what()) - ); - return; - } + }); } static dv::value create_missing_content_report( @@ -180,7 +171,9 @@ static dv::value create_missing_content_report( return root; } -void EngineController::onMissingContent(const std::shared_ptr& report) { +void EngineController::onMissingContent( + const std::shared_ptr& report +) { if (engine.isHeadless()) { throw std::runtime_error( "missing content: " + @@ -196,50 +189,63 @@ void EngineController::onMissingContent(const std::shared_ptr& re } } +static void confirm( + Engine& engine, ConfirmRequest request, bool confirmed, runnable callback +) { + if (confirmed || engine.isHeadless()) { + callback(); + return; + } + if (request.memo) { + guiutil::confirm_with_memo( + engine, + langs::get(request.message), + request.text, + callback, + L"", + langs::get(L"Cancel") + ); + } else { + guiutil::confirm( + engine, + langs::get(request.message), + callback, + nullptr, + L"", + langs::get(L"Cancel") + ); + } +} + void EngineController::openWorld(const std::string& name, bool confirmConvert) { const auto& paths = engine.getPaths(); + auto& debugSettings = engine.getSettings().debug; auto folder = paths.getWorldsFolder() / name; - auto worldFile = folder / "world.json"; - if (!io::exists(worldFile)) { - throw std::runtime_error(worldFile.string() + " does not exists"); - } - if (!load_world_content(engine, folder)) { + auto content = load_world_content(engine, folder); + auto worldFiles = std::make_shared(folder, debugSettings); + auto report = World::checkIndices(worldFiles, content); + + if (report == nullptr) { + load_world(engine, std::move(worldFiles), localPlayer); + return; + } + if (report->hasMissingContent()) { + onMissingContent(report); return; } - const auto& contentControl = engine.getContentControl(); - const Content* content = contentControl.get(); - auto worldFiles = std::make_shared( - folder, engine.getSettings().debug); - if (auto report = World::checkIndices(worldFiles, content)) { - if (report->hasMissingContent()) { - onMissingContent(report); - } else { - if (confirmConvert) { - auto task = create_converter( - engine, - worldFiles, - content, - report, - [=]() { openWorld(name, false); } - ); - if (engine.isHeadless()) { - task->waitForEnd(); - } else { - menus::show_process_panel( - engine, task, L"Converting world..." - ); - } - } else { - show_convert_request(engine, content, report, std::move(worldFiles), [=]() { - openWorld(name, false); - }); - } - } - return; - } - load_world(engine, std::move(worldFiles), localPlayer); + auto request = create_convert_request(report); + confirm(engine, std::move(request), confirmConvert, [=]() { + auto task = create_converter( + engine, + worldFiles, + content, + report, + [=]() { openWorld(name, false); } + ); + start(engine, std::move(task), L"Converting world..."); + }); } inline uint64_t str2seed(const std::string& seedstr) { @@ -266,15 +272,11 @@ void EngineController::createWorld( EnginePaths& paths = engine.getPaths(); auto folder = paths.getWorldsFolder() / name; - if (engine.isHeadless()) { + call(engine, [this, &paths, folder]() { engine.getContentControl().loadContent(); paths.setCurrentWorldFolder(folder); - } else if (!menus::call(engine, [this, &paths, folder]() { - engine.getContentControl().loadContent(); - paths.setCurrentWorldFolder(folder); - })) { - return; - } + }); + auto& contentControl = engine.getContentControl(); auto level = World::create( name, @@ -301,6 +303,48 @@ void EngineController::reopenWorld(World* world) { openWorld(name, true); } +static void reconfig_packs_outside( + ContentControl& contentControl, + const std::vector& packsToAdd, + const std::vector& packsToRemove +) { + auto& manager = contentControl.scan(); + + auto names = PacksManager::getNames( + contentControl.getContentPacks() + ); + for (const auto& id : packsToAdd) { + names.push_back(id); + } + for (const auto& id : packsToRemove) { + manager.exclude(id); + names.erase(std::find(names.begin(), names.end(), id)); + } + names = manager.assemble(names); + contentControl.getContentPacks() = manager.getAll(names); +} + +static void reconfig_packs_inside( + PacksManager& manager, + std::vector& names, + const std::vector& packsToAdd, + const std::vector& packsToRemove +) { + for (const auto& id : packsToAdd) { + names.push_back(id); + } + for (const auto& id : packsToRemove) { + manager.exclude(id); + const auto& found = std::find(names.begin(), names.end(), id); + if (found != names.end()) { + names.erase(found); + } else { + logger.warning() + << "attempt to remove non-installed pack: " << id; + } + } +} + void EngineController::reconfigPacks( LevelController* controller, const std::vector& packsToAdd, @@ -308,8 +352,32 @@ void EngineController::reconfigPacks( ) { auto& contentControl = engine.getContentControl(); auto content = contentControl.get(); - bool hasIndices = false; + runnable removeFunc = [this, controller, packsToAdd, packsToRemove, &contentControl]() { + if (controller == nullptr) { + try { + reconfig_packs_outside(contentControl, packsToAdd, packsToRemove); + } catch (const contentpack_error& err) { + throw std::runtime_error( + std::string(err.what()) + " [" + err.getPackId() + "]" + ); + } + } else { + auto world = controller->getLevel()->getWorld(); + controller->saveWorld(); + + auto names = PacksManager::getNames(world->getPacks()); + auto& manager = contentControl.scan(); + reconfig_packs_inside(manager, names, packsToAdd, packsToRemove); + + auto& wfile = *world->wfile; + wfile.removeIndices(packsToRemove); + wfile.writePacks(manager.getAll(names)); + reopenWorld(world); + } + }; + + bool hasIndices = false; std::stringstream ss; if (content) { for (const auto& id : packsToRemove) { @@ -323,53 +391,6 @@ void EngineController::reconfigPacks( } } } - - runnable removeFunc = [this, controller, packsToAdd, packsToRemove, &contentControl]() { - auto& manager = contentControl.scan(); - if (controller == nullptr) { - try { - auto names = PacksManager::getNames( - engine.getContentControl().getContentPacks() - ); - for (const auto& id : packsToAdd) { - names.push_back(id); - } - for (const auto& id : packsToRemove) { - manager.exclude(id); - names.erase(std::find(names.begin(), names.end(), id)); - } - names = manager.assemble(names); - engine.getContentControl().getContentPacks() = manager.getAll(names); - } catch (const contentpack_error& err) { - throw std::runtime_error( - std::string(err.what()) + " [" + err.getPackId() + "]" - ); - } - } else { - auto world = controller->getLevel()->getWorld(); - auto& wfile = *world->wfile; - controller->saveWorld(); - - auto names = PacksManager::getNames(world->getPacks()); - for (const auto& id : packsToAdd) { - names.push_back(id); - } - for (const auto& id : packsToRemove) { - manager.exclude(id); - const auto& found = std::find(names.begin(), names.end(), id); - if (found != names.end()) { - names.erase(found); - } else { - logger.warning() - << "attempt to remove non-installed pack: " << id; - } - } - wfile.removeIndices(packsToRemove); - wfile.writePacks(manager.getAll(names)); - reopenWorld(world); - } - }; - if (hasIndices && !engine.isHeadless()) { guiutil::confirm( engine,