refactor EngineController
This commit is contained in:
parent
4d1a2b3764
commit
45ccf893ae
@ -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()) {
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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<MenuScreen>(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<MenuScreen>(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<MenuScreen>(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<MenuScreen>(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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -32,5 +32,5 @@ namespace menus {
|
||||
const std::wstring& text = L""
|
||||
);
|
||||
|
||||
bool call(Engine& engine, runnable func);
|
||||
void call(Engine& engine, runnable func);
|
||||
}
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
#include "EngineController.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <filesystem>
|
||||
#include <memory>
|
||||
|
||||
#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<Task> create_converter(
|
||||
);
|
||||
}
|
||||
|
||||
static void show_convert_request(
|
||||
Engine& engine,
|
||||
const Content* content,
|
||||
const std::shared_ptr<ContentReport>& report,
|
||||
const std::shared_ptr<WorldFiles>& 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<ContentReport>& 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> 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>& 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<ContentReport>& report) {
|
||||
void EngineController::onMissingContent(
|
||||
const std::shared_ptr<ContentReport>& report
|
||||
) {
|
||||
if (engine.isHeadless()) {
|
||||
throw std::runtime_error(
|
||||
"missing content: " +
|
||||
@ -196,50 +189,63 @@ void EngineController::onMissingContent(const std::shared_ptr<ContentReport>& 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<WorldFiles>(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<WorldFiles>(
|
||||
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<std::string>& packsToAdd,
|
||||
const std::vector<std::string>& 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<std::string>& names,
|
||||
const std::vector<std::string>& packsToAdd,
|
||||
const std::vector<std::string>& 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<std::string>& 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,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user