diff --git a/src/client.cpp b/src/client.cpp index bca9f41d0..1a6a87487 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -29,6 +29,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "threading/mutex_auto_lock.h" #include "client/clientevent.h" #include "client/renderingengine.h" +#include "client/tile.h" #include "util/auth.h" #include "util/directiontables.h" #include "util/pointedthing.h" @@ -1643,9 +1644,8 @@ void Client::afterContentReceived() text = wgettext("Initializing nodes..."); RenderingEngine::draw_load_screen(text, guienv, m_tsrc, 0, 72); m_nodedef->updateAliases(m_itemdef); - std::string texture_path = g_settings->get("texture_path"); - if (!texture_path.empty() && fs::IsDir(texture_path)) - m_nodedef->applyTextureOverrides(texture_path + DIR_DELIM + "override.txt"); + for (const auto &path : getTextureDirs()) + m_nodedef->applyTextureOverrides(path + DIR_DELIM + "override.txt"); m_nodedef->setNodeRegistrationStatus(true); m_nodedef->runNodeResolveCallbacks(); delete[] text; diff --git a/src/client/tile.cpp b/src/client/tile.cpp index d0b9d81bf..91a3c0a38 100644 --- a/src/client/tile.cpp +++ b/src/client/tile.cpp @@ -129,11 +129,12 @@ std::string getTexturePath(const std::string &filename) /* Check from texture_path */ - const std::string &texture_path = g_settings->get("texture_path"); - if (!texture_path.empty()) { - std::string testpath = texture_path + DIR_DELIM + filename; + for (const auto &path : getTextureDirs()) { + std::string testpath = path + DIR_DELIM + filename; // Check all filename extensions. Returns "" if not found. fullpath = getImagePath(testpath); + if (!fullpath.empty()) + break; } /* @@ -2388,3 +2389,10 @@ video::ITexture *TextureSource::getShaderFlagsTexture(bool normalmap_present) return getTexture(tname); } + +const std::vector &getTextureDirs() +{ + static thread_local std::vector dirs = + fs::GetRecursiveDirs(g_settings->get("texture_path")); + return dirs; +} diff --git a/src/client/tile.h b/src/client/tile.h index e69dbe0c7..817b1aa58 100644 --- a/src/client/tile.h +++ b/src/client/tile.h @@ -337,3 +337,5 @@ struct TileSpec //! The first is base texture, the second is overlay. TileLayer layers[MAX_TILE_LAYERS]; }; + +const std::vector &getTextureDirs(); diff --git a/src/filesys.cpp b/src/filesys.cpp index d965384a2..694169d20 100644 --- a/src/filesys.cpp +++ b/src/filesys.cpp @@ -380,15 +380,36 @@ std::string TempPath() #endif -void GetRecursiveSubPaths(const std::string &path, std::vector &dst) +void GetRecursiveDirs(std::vector &dirs, const std::string &dir) +{ + static const std::set chars_to_ignore = { '_', '.' }; + if (dir.empty() || !IsDir(dir)) + return; + dirs.push_back(dir); + fs::GetRecursiveSubPaths(dir, dirs, false, chars_to_ignore); +} + +std::vector GetRecursiveDirs(const std::string &dir) +{ + std::vector result; + GetRecursiveDirs(result, dir); + return result; +} + +void GetRecursiveSubPaths(const std::string &path, + std::vector &dst, + bool list_files, + const std::set &ignore) { std::vector content = GetDirListing(path); for (const auto &n : content) { std::string fullpath = path + DIR_DELIM + n.name; - dst.push_back(fullpath); - if (n.dir) { - GetRecursiveSubPaths(fullpath, dst); - } + if (ignore.count(n.name[0])) + continue; + if (list_files || n.dir) + dst.push_back(fullpath); + if (n.dir) + GetRecursiveSubPaths(fullpath, dst, list_files, ignore); } } diff --git a/src/filesys.h b/src/filesys.h index 5f246e387..09f129aa3 100644 --- a/src/filesys.h +++ b/src/filesys.h @@ -19,6 +19,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #pragma once +#include #include #include #include "exceptions.h" @@ -66,10 +67,23 @@ bool DeleteSingleFileOrEmptyDirectory(const std::string &path); // Returns path to temp directory, can return "" on error std::string TempPath(); +/* Returns a list of subdirectories, including the path itself, but excluding + hidden directories (whose names start with . or _) +*/ +void GetRecursiveDirs(std::vector &dirs, const std::string &dir); +std::vector GetRecursiveDirs(const std::string &dir); + /* Multiplatform */ -// The path itself not included -void GetRecursiveSubPaths(const std::string &path, std::vector &dst); +/* The path itself not included, returns a list of all subpaths. + dst - vector that contains all the subpaths. + list files - include files in the list of subpaths. + ignore - paths that start with these charcters will not be listed. +*/ +void GetRecursiveSubPaths(const std::string &path, + std::vector &dst, + bool list_files, + const std::set &ignore = {}); // Tries to delete all, returns false if any failed bool DeletePaths(const std::vector &paths); diff --git a/src/script/lua_api/l_mainmenu.cpp b/src/script/lua_api/l_mainmenu.cpp index cdb27fb60..95696bc20 100644 --- a/src/script/lua_api/l_mainmenu.cpp +++ b/src/script/lua_api/l_mainmenu.cpp @@ -532,7 +532,7 @@ int ModApiMainMenu::l_delete_world(lua_State *L) std::vector paths; paths.push_back(spec.path); - fs::GetRecursiveSubPaths(spec.path, paths); + fs::GetRecursiveSubPaths(spec.path, paths, true); // Delete files if (!fs::DeletePaths(paths)) { diff --git a/src/server.cpp b/src/server.cpp index 98c3eca9a..653441b54 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -253,9 +253,8 @@ Server::Server( m_nodedef->updateAliases(m_itemdef); // Apply texture overrides from texturepack/override.txt - std::string texture_path = g_settings->get("texture_path"); - if (!texture_path.empty() && fs::IsDir(texture_path)) - m_nodedef->applyTextureOverrides(texture_path + DIR_DELIM + "override.txt"); + for (const auto &path : fs::GetRecursiveDirs(g_settings->get("texture_path"))) + m_nodedef->applyTextureOverrides(path + DIR_DELIM + "override.txt"); m_nodedef->setNodeRegistrationStatus(true); @@ -2253,8 +2252,8 @@ void Server::fillMediaCache() paths.push_back(mod.path + DIR_DELIM + "models"); paths.push_back(mod.path + DIR_DELIM + "locale"); } - paths.push_back(porting::path_user + DIR_DELIM + "textures" + DIR_DELIM + "server"); - + fs::GetRecursiveDirs(paths, porting::path_user + DIR_DELIM + + "textures" + DIR_DELIM + "server"); // Collect media file information from paths into cache for (const std::string &mediapath : paths) { std::vector dirlist = fs::GetDirListing(mediapath);