diff --git a/src/engine.cpp b/src/engine.cpp index 17c5d976..7fdbedc5 100644 --- a/src/engine.cpp +++ b/src/engine.cpp @@ -259,7 +259,7 @@ void Engine::loadContent() { names = manager.assembly(names); contentPacks = manager.getAll(names); - std::vector> resRoots; + std::vector resRoots; for (auto& pack : contentPacks) { resRoots.push_back({pack.id, pack.folder}); diff --git a/src/files/engine_paths.cpp b/src/files/engine_paths.cpp index f14828b3..509c4055 100644 --- a/src/files/engine_paths.cpp +++ b/src/files/engine_paths.cpp @@ -164,14 +164,14 @@ fs::path EnginePaths::resolve(std::string path) { throw files_access_error("unknown entry point '"+prefix+"'"); } -ResPaths::ResPaths(fs::path mainRoot, std::vector> roots) +ResPaths::ResPaths(fs::path mainRoot, std::vector roots) : mainRoot(mainRoot), roots(roots) { } fs::path ResPaths::find(const std::string& filename) const { for (int i = roots.size()-1; i >= 0; i--) { auto& root = roots[i]; - fs::path file = root.second / fs::u8path(filename); + fs::path file = root.path / fs::u8path(filename); if (fs::exists(file)) { return file; } @@ -182,8 +182,8 @@ fs::path ResPaths::find(const std::string& filename) const { std::string ResPaths::findRaw(const std::string& filename) const { for (int i = roots.size()-1; i >= 0; i--) { auto& root = roots[i]; - if (fs::exists(root.second / fs::path(filename))) { - return root.first+":"+filename; + if (fs::exists(root.path / fs::path(filename))) { + return root.name + ":" + filename; } } auto resDir = mainRoot; @@ -193,11 +193,35 @@ std::string ResPaths::findRaw(const std::string& filename) const { throw std::runtime_error("could not to find file "+util::quote(filename)); } +std::vector ResPaths::listdirRaw(const std::string& folderName) const { + std::vector entries; + for (int i = roots.size()-1; i >= 0; i--) { + auto& root = roots[i]; + fs::path folder = root.path / fs::u8path(folderName); + if (!fs::is_directory(folder)) + continue; + for (const auto& entry : fs::directory_iterator(folder)) { + auto name = entry.path().filename().u8string(); + entries.push_back(root.name+":"+folderName+"/"+name); + } + } + { + fs::path folder = mainRoot / fs::u8path(folderName); + if (!fs::is_directory(folder)) + return entries; + for (const auto& entry : fs::directory_iterator(folder)) { + auto name = entry.path().filename().u8string(); + entries.push_back("core:"+folderName+"/"+name); + } + } + return entries; +} + std::vector ResPaths::listdir(const std::string& folderName) const { std::vector entries; for (int i = roots.size()-1; i >= 0; i--) { auto& root = roots[i]; - fs::path folder = root.second / fs::u8path(folderName); + fs::path folder = root.path / fs::u8path(folderName); if (!fs::is_directory(folder)) continue; for (const auto& entry : fs::directory_iterator(folder)) { diff --git a/src/files/engine_paths.hpp b/src/files/engine_paths.hpp index 41c57e6e..ac1ed5a8 100644 --- a/src/files/engine_paths.hpp +++ b/src/files/engine_paths.hpp @@ -42,18 +42,24 @@ public: fs::path resolve(std::string path); }; +struct PathsRoot { + std::string name; + fs::path path; +}; + class ResPaths { fs::path mainRoot; - std::vector> roots; + std::vector roots; public: ResPaths( fs::path mainRoot, - std::vector> roots + std::vector roots ); fs::path find(const std::string& filename) const; std::string findRaw(const std::string& filename) const; std::vector listdir(const std::string& folder) const; + std::vector listdirRaw(const std::string& folder) const; const fs::path& getMainRoot() const; }; diff --git a/src/logic/scripting/lua/libfile.cpp b/src/logic/scripting/lua/libfile.cpp index 9c6ebe97..7db2d5ab 100644 --- a/src/logic/scripting/lua/libfile.cpp +++ b/src/logic/scripting/lua/libfile.cpp @@ -140,6 +140,37 @@ static int l_file_write_bytes(lua_State* L) { } } +static int l_file_list_all_res(lua_State* L, const std::string& path) { + auto files = scripting::engine->getResPaths()->listdirRaw(path); + lua_createtable(L, files.size(), 0); + for (size_t i = 0; i < files.size(); i++) { + lua_pushstring(L, files[i].c_str()); + lua_rawseti(L, -2, i+1); + } + return 1; +} + +static int l_file_list(lua_State* L) { + std::string dirname = lua_tostring(L, 1); + if (dirname.find(':') == std::string::npos) { + return l_file_list_all_res(L, dirname); + } + fs::path path = resolve_path(L, dirname); + if (!fs::is_directory(path)) { + throw std::runtime_error(util::quote(path.u8string())+" is not a directory"); + } + lua_createtable(L, 0, 0); + size_t index = 1; + for (auto& entry : fs::directory_iterator(path)) { + auto name = entry.path().filename().u8string(); + auto file = dirname + "/" + name; + lua_pushstring(L, file.c_str()); + lua_rawseti(L, -2, index); + index++; + } + return 1; +} + const luaL_Reg filelib [] = { {"resolve", lua_wrap_errors}, {"find", lua_wrap_errors}, @@ -153,5 +184,6 @@ const luaL_Reg filelib [] = { {"mkdirs", lua_wrap_errors}, {"read_bytes", lua_wrap_errors}, {"write_bytes", lua_wrap_errors}, + {"list", lua_wrap_errors}, {NULL, NULL} };