From a653b063e6a0c98eec125fa5a0822bc9d3e3ab17 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Tue, 4 Feb 2025 12:35:19 +0300 Subject: [PATCH] completely remove EnginePaths::resolve --- src/frontend/screens/LevelScreen.cpp | 2 +- src/io/devices/StdfsDevice.cpp | 20 +++++- src/io/devices/StdfsDevice.hpp | 2 +- src/io/engine_paths.cpp | 70 +++++-------------- src/io/engine_paths.hpp | 2 - src/io/io.cpp | 4 ++ src/io/io.hpp | 1 + src/logic/scripting/lua/libs/libcore.cpp | 3 +- src/logic/scripting/lua/libs/libfile.cpp | 55 +++++---------- .../scripting/lua/libs/libgeneration.cpp | 6 +- src/logic/scripting/lua/libs/libgui.cpp | 6 +- .../lua/usertypes/lua_type_heightmap.cpp | 2 +- 12 files changed, 67 insertions(+), 106 deletions(-) diff --git a/src/frontend/screens/LevelScreen.cpp b/src/frontend/screens/LevelScreen.cpp index d16907474..08e1b41e5 100644 --- a/src/frontend/screens/LevelScreen.cpp +++ b/src/frontend/screens/LevelScreen.cpp @@ -147,7 +147,7 @@ void LevelScreen::saveWorldPreview() { worldRenderer->draw(ctx, camera, false, true, 0.0f, postProcessing.get()); auto image = postProcessing->toImage(); image->flipY(); - imageio::write(paths.resolve("world:preview.png").string(), image.get()); + imageio::write("world:preview.png", image.get()); } catch (const std::exception& err) { logger.error() << err.what(); } diff --git a/src/io/devices/StdfsDevice.cpp b/src/io/devices/StdfsDevice.cpp index 98ef15682..3951dc32b 100644 --- a/src/io/devices/StdfsDevice.cpp +++ b/src/io/devices/StdfsDevice.cpp @@ -10,6 +10,18 @@ namespace fs = std::filesystem; static debug::Logger logger("io-stdfs"); +StdfsDevice::StdfsDevice(fs::path root, bool createDirectory) + : root(std::move(root)) { + if (createDirectory && !fs::is_directory(this->root)) { + std::error_code ec; + fs::create_directories(this->root, ec); + if (ec) { + logger.error() << "error creating root directory " << this->root + << ": " << ec.message(); + } + } +} + fs::path StdfsDevice::resolve(std::string_view path) { return root / fs::u8path(path); } @@ -54,7 +66,13 @@ bool StdfsDevice::isfile(std::string_view path) { void StdfsDevice::mkdirs(std::string_view path) { auto resolved = resolve(path); - fs::create_directories(resolved); + + std::error_code ec; + fs::create_directories(resolved, ec); + if (ec) { + logger.error() << "error creating directory " << resolved << ": " + << ec.message(); + } } bool StdfsDevice::remove(std::string_view path) { diff --git a/src/io/devices/StdfsDevice.hpp b/src/io/devices/StdfsDevice.hpp index bf284ccb6..f518af932 100644 --- a/src/io/devices/StdfsDevice.hpp +++ b/src/io/devices/StdfsDevice.hpp @@ -3,7 +3,7 @@ namespace io { class StdfsDevice : public Device { public: - StdfsDevice(std::filesystem::path root) : root(std::move(root)) {} + StdfsDevice(std::filesystem::path root, bool createDirectory = true); std::filesystem::path resolve(std::string_view path) override; void write(std::string_view path, const void* data, size_t size) override; diff --git a/src/io/engine_paths.cpp b/src/io/engine_paths.cpp index f9a2701d9..ca20b265b 100644 --- a/src/io/engine_paths.cpp +++ b/src/io/engine_paths.cpp @@ -20,8 +20,8 @@ static debug::Logger logger("engine-paths"); static inline auto SCREENSHOTS_FOLDER = std::filesystem::u8path("screenshots"); static inline auto CONTENT_FOLDER = std::filesystem::u8path("content"); static inline auto WORLDS_FOLDER = std::filesystem::u8path("worlds"); -static inline auto CONFIG_FOLDER = std::filesystem::u8path("config"); -static inline auto EXPORT_FOLDER = std::filesystem::u8path("export"); +static inline auto CONFIG_FOLDER = io::path("config"); +static inline auto EXPORT_FOLDER = io::path("export"); static inline auto CONTROLS_FILE = std::filesystem::u8path("controls.toml"); static inline auto SETTINGS_FILE = std::filesystem::u8path("settings.toml"); @@ -52,7 +52,7 @@ static io::path toCanonic(io::path path) { } void EnginePaths::prepare() { - io::set_device("res", std::make_shared(resourcesFolder)); + io::set_device("res", std::make_shared(resourcesFolder, false)); io::set_device("user", std::make_shared(userFilesFolder)); if (!io::is_directory("res:")) { @@ -60,10 +60,6 @@ void EnginePaths::prepare() { resourcesFolder.string() + " is not a directory" ); } - if (!io::is_directory("user:")) { - io::create_directories("user:"); - } - logger.info() << "resources folder: " << fs::canonical(resourcesFolder).u8string(); logger.info() << "user files folder: " << fs::canonical(userFilesFolder).u8string(); @@ -71,14 +67,10 @@ void EnginePaths::prepare() { if (!io::is_directory(contentFolder)) { io::create_directories(contentFolder); } - auto exportFolder = io::path("user:") / EXPORT_FOLDER; - if (!io::is_directory(exportFolder)) { - io::create_directories(exportFolder); - } - auto configFolder = io::path("user:") / CONFIG_FOLDER; - if (!io::is_directory(configFolder)) { - io::create_directories(configFolder); - } + + io::create_subdevice("core", "res", ""); + io::create_subdevice("export", "user", EXPORT_FOLDER); + io::create_subdevice("config", "user", CONFIG_FOLDER); } const std::filesystem::path& EnginePaths::getUserFilesFolder() const { @@ -187,7 +179,16 @@ void EnginePaths::setCurrentWorldFolder(io::path folder) { } void EnginePaths::setContentPacks(std::vector* contentPacks) { + // Remove previous content entry-points + for (const auto& pack : *this->contentPacks) { + io::remove_device(pack.id); + } this->contentPacks = contentPacks; + // Create content devices + for (const auto& pack : *contentPacks) { + auto parent = pack.folder.entryPoint(); + io::create_subdevice(pack.id, parent, pack.folder); + } } std::tuple EnginePaths::parsePath(std::string_view path) { @@ -200,45 +201,6 @@ std::tuple EnginePaths::parsePath(std::string_view pat return {prefix, filename}; } -// TODO: remove -io::path EnginePaths::resolve( - const std::string& path, bool throwErr -) const { - auto [prefix, filename] = EnginePaths::parsePath(path); - if (prefix.empty()) { - throw files_access_error("no entry point specified"); - } - filename = toCanonic(filename).string(); - - if (prefix == "core") { - return io::path("res:") / filename; - } - - if (prefix == "res" || prefix == "user" || prefix == "script") { - return prefix + ":" + filename; - } - if (prefix == "config") { - return getConfigFolder() / filename; - } - if (prefix == "world") { - return currentWorldFolder / filename; - } - if (prefix == "export") { - return io::path("user:") / EXPORT_FOLDER / filename; - } - if (contentPacks) { - for (auto& pack : *contentPacks) { - if (pack.id == prefix) { - return pack.folder / filename; - } - } - } - if (throwErr) { - throw files_access_error("unknown entry point '" + prefix + "'"); - } - return filename; -} - ResPaths::ResPaths(io::path mainRoot, std::vector roots) : mainRoot(std::move(mainRoot)), roots(std::move(roots)) { } diff --git a/src/io/engine_paths.hpp b/src/io/engine_paths.hpp index 920b01aac..fda770870 100644 --- a/src/io/engine_paths.hpp +++ b/src/io/engine_paths.hpp @@ -43,8 +43,6 @@ class EnginePaths { std::vector scanForWorlds() const; - io::path resolve(const std::string& path, bool throwErr = true) const; - static std::tuple parsePath(std::string_view view); static inline auto CONFIG_DEFAULTS = diff --git a/src/io/io.cpp b/src/io/io.cpp index b8d8d7d97..2cfa75d9e 100644 --- a/src/io/io.cpp +++ b/src/io/io.cpp @@ -23,6 +23,10 @@ void io::set_device(const std::string& name, std::shared_ptr device) devices[name] = device; } +void io::remove_device(const std::string& name) { + devices.erase(name); +} + std::shared_ptr io::get_device(const std::string& name) { const auto& found = devices.find(name); if (found == devices.end()) { diff --git a/src/io/io.hpp b/src/io/io.hpp index 435753f94..fdccc6acc 100644 --- a/src/io/io.hpp +++ b/src/io/io.hpp @@ -16,6 +16,7 @@ namespace io { class Device; void set_device(const std::string& name, std::shared_ptr device); + void remove_device(const std::string& name); std::shared_ptr get_device(const std::string& name); Device& require_device(const std::string& name); diff --git a/src/logic/scripting/lua/libs/libcore.cpp b/src/logic/scripting/lua/libs/libcore.cpp index 4c1e5dc6c..7b8c152cb 100644 --- a/src/logic/scripting/lua/libs/libcore.cpp +++ b/src/logic/scripting/lua/libs/libcore.cpp @@ -259,8 +259,7 @@ static int l_load_texture(lua::State* L) { } static int l_open_folder(lua::State* L) { - auto path = engine->getPaths().resolve(lua::require_string(L, 1)); - platform::open_folder(io::resolve(path)); + platform::open_folder(io::resolve(lua::require_string(L, 1))); return 0; } diff --git a/src/logic/scripting/lua/libs/libfile.cpp b/src/logic/scripting/lua/libs/libfile.cpp index c1843e2fd..175d3171b 100644 --- a/src/logic/scripting/lua/libs/libfile.cpp +++ b/src/logic/scripting/lua/libs/libfile.cpp @@ -13,17 +13,6 @@ namespace fs = std::filesystem; using namespace scripting; -static io::path resolve_path(const std::string& path) { - return engine->getPaths().resolve(path); -} - -static io::path resolve_path_soft(const std::string& path) { - if (path.find(':') == std::string::npos) { - return ""; - } - return engine->getPaths().resolve(path, false); -} - static int l_find(lua::State* L) { auto path = lua::require_string(L, 1); try { @@ -34,12 +23,12 @@ static int l_find(lua::State* L) { } static int l_resolve(lua::State* L) { - io::path path = resolve_path(lua::require_string(L, 1)); + io::path path = lua::require_string(L, 1); return lua::pushstring(L, path.string()); } static int l_read(lua::State* L) { - io::path path = resolve_path(lua::require_string(L, 1)); + io::path path = lua::require_string(L, 1); if (io::is_regular_file(path)) { return lua::pushstring(L, io::read_string(path)); } @@ -53,9 +42,8 @@ static std::set writeable_entry_points { }; static io::path get_writeable_path(lua::State* L) { - std::string rawpath = lua::require_string(L, 1); - io::path path = resolve_path(rawpath); - auto entryPoint = rawpath.substr(0, rawpath.find(':')); + io::path path = lua::require_string(L, 1); + auto entryPoint = path.entryPoint(); if (writeable_entry_points.find(entryPoint) == writeable_entry_points.end()) { throw std::runtime_error("access denied"); } @@ -70,9 +58,8 @@ static int l_write(lua::State* L) { } static int l_remove(lua::State* L) { - std::string rawpath = lua::require_string(L, 1); - io::path path = resolve_path(rawpath); - auto entryPoint = rawpath.substr(0, rawpath.find(':')); + io::path path = lua::require_string(L, 1); + auto entryPoint = path.entryPoint(); if (writeable_entry_points.find(entryPoint) == writeable_entry_points.end()) { throw std::runtime_error("access denied"); } @@ -80,9 +67,8 @@ static int l_remove(lua::State* L) { } static int l_remove_tree(lua::State* L) { - std::string rawpath = lua::require_string(L, 1); - io::path path = resolve_path(rawpath); - auto entryPoint = rawpath.substr(0, rawpath.find(':')); + io::path path = lua::require_string(L, 1); + auto entryPoint = path.entryPoint(); if (writeable_entry_points.find(entryPoint) == writeable_entry_points.end()) { throw std::runtime_error("access denied"); } @@ -90,23 +76,19 @@ static int l_remove_tree(lua::State* L) { } static int l_exists(lua::State* L) { - io::path path = resolve_path_soft(lua::require_string(L, 1)); - return lua::pushboolean(L, io::exists(path)); + return lua::pushboolean(L, io::exists(lua::require_string(L, 1))); } static int l_isfile(lua::State* L) { - const char* string =lua::require_string(L, 1); - io::path path = resolve_path_soft(string); - return lua::pushboolean(L, io::is_regular_file(path)); + return lua::pushboolean(L, io::is_regular_file(lua::require_string(L, 1))); } static int l_isdir(lua::State* L) { - io::path path = resolve_path_soft(lua::require_string(L, 1)); - return lua::pushboolean(L, io::is_directory(path)); + return lua::pushboolean(L, io::is_directory(lua::require_string(L, 1))); } static int l_length(lua::State* L) { - io::path path = resolve_path(lua::require_string(L, 1)); + io::path path = lua::require_string(L, 1); if (io::exists(path)) { return lua::pushinteger(L, io::file_size(path)); } else { @@ -115,17 +97,17 @@ static int l_length(lua::State* L) { } static int l_mkdir(lua::State* L) { - io::path path = resolve_path(lua::require_string(L, 1)); + io::path path = lua::require_string(L, 1); return lua::pushboolean(L, io::create_directories(path)); // FIXME } static int l_mkdirs(lua::State* L) { - io::path path = resolve_path(lua::require_string(L, 1)); + io::path path = lua::require_string(L, 1); return lua::pushboolean(L, io::create_directories(path)); } static int l_read_bytes(lua::State* L) { - io::path path = resolve_path(lua::require_string(L, 1)); + io::path path = lua::require_string(L, 1); if (io::is_regular_file(path)) { size_t length = static_cast(io::file_size(path)); @@ -177,7 +159,7 @@ static int l_list(lua::State* L) { if (dirname.find(':') == std::string::npos) { return l_list_all_res(L, dirname); } - io::path path = resolve_path(dirname); + io::path path = dirname; if (!io::is_directory(path)) { throw std::runtime_error( util::quote(path.string()) + " is not a directory" @@ -238,9 +220,8 @@ static int l_read_combined_object(lua::State* L) { } static int l_is_writeable(lua::State* L) { - std::string rawpath = lua::require_string(L, 1); - io::path path = resolve_path(rawpath); - auto entryPoint = rawpath.substr(0, rawpath.find(':')); + io::path path = lua::require_string(L, 1); + auto entryPoint = path.entryPoint(); if (writeable_entry_points.find(entryPoint) == writeable_entry_points.end()) { return lua::pushboolean(L, false); } diff --git a/src/logic/scripting/lua/libs/libgeneration.cpp b/src/logic/scripting/lua/libs/libgeneration.cpp index 196dae74e..855700a9c 100644 --- a/src/logic/scripting/lua/libs/libgeneration.cpp +++ b/src/logic/scripting/lua/libs/libgeneration.cpp @@ -14,7 +14,7 @@ using namespace scripting; static int l_save_fragment(lua::State* L) { const auto& paths = engine->getPaths(); auto fragment = lua::touserdata(L, 1); - auto file = paths.resolve(lua::require_string(L, 2), true); + auto file = lua::require_string(L, 2); auto map = fragment->getFragment()->serialize(); auto bytes = json::to_binary(map, true); io::write_bytes(file, bytes.data(), bytes.size()); @@ -35,9 +35,7 @@ static int l_create_fragment(lua::State* L) { } static int l_load_fragment(lua::State* L) { - const auto& paths = engine->getPaths(); - auto filename = lua::require_string(L, 1); - auto path = paths.resolve(filename); + io::path path = lua::require_string(L, 1); if (!io::exists(path)) { throw std::runtime_error("file "+path.string()+" does not exist"); } diff --git a/src/logic/scripting/lua/libs/libgui.cpp b/src/logic/scripting/lua/libs/libgui.cpp index 995cb625d..d3b9c93a9 100644 --- a/src/logic/scripting/lua/libs/libgui.cpp +++ b/src/logic/scripting/lua/libs/libgui.cpp @@ -808,15 +808,15 @@ static int l_gui_alert(lua::State* L) { } static int l_gui_load_document(lua::State* L) { - auto filename = lua::require_string(L, 1); + io::path filename = lua::require_string(L, 1); auto alias = lua::require_string(L, 2); auto args = lua::tovalue(L, 3); auto documentPtr = UiDocument::read( scripting::get_root_environment(), alias, - engine->getPaths().resolve(filename), - filename + filename, + filename.string() ); auto document = documentPtr.get(); engine->getAssets()->store(std::move(documentPtr), alias); diff --git a/src/logic/scripting/lua/usertypes/lua_type_heightmap.cpp b/src/logic/scripting/lua/usertypes/lua_type_heightmap.cpp index 983f9ba38..9e7cabc8e 100644 --- a/src/logic/scripting/lua/usertypes/lua_type_heightmap.cpp +++ b/src/logic/scripting/lua/usertypes/lua_type_heightmap.cpp @@ -52,7 +52,7 @@ const float* LuaHeightmap::getValues() const { static int l_dump(lua::State* L) { const auto& paths = scripting::engine->getPaths(); if (auto heightmap = touserdata(L, 1)) { - auto file = paths.resolve(require_string(L, 2)); + io::path file = require_string(L, 2); uint w = heightmap->getWidth(); uint h = heightmap->getHeight(); ImageData image(ImageFormat::rgb888, w, h);