Load files from subfolders in texturepacks
authornumber Zero <silverunicorn2011@yandex.ru>
Wed, 13 Sep 2017 20:03:18 +0000 (23:03 +0300)
committerparamat <mat.gregory@virginmedia.com>
Fri, 17 Nov 2017 19:23:08 +0000 (19:23 +0000)
Updated and rebased version of a PR by red-001

src/client.cpp
src/client/tile.cpp
src/client/tile.h
src/filesys.cpp
src/filesys.h
src/script/lua_api/l_mainmenu.cpp
src/server.cpp

index bca9f41d04b827da051fa3cf12485168eb817b3f..1a6a87487bec2e52e400d0ed0d6d96ac049d3d30 100644 (file)
@@ -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;
index d0b9d81bfc895d9e2c5b5a46f4dde3b31e749442..91a3c0a3853352a70af93ec93a4b0a10489fecab 100644 (file)
@@ -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<std::string> &getTextureDirs()
+{
+       static thread_local std::vector<std::string> dirs =
+               fs::GetRecursiveDirs(g_settings->get("texture_path"));
+       return dirs;
+}
index e69dbe0c7bb3d6d7352dd74f28f907a53662ee13..817b1aa58595e5ad8b719e97d4b8644a832858ce 100644 (file)
@@ -337,3 +337,5 @@ struct TileSpec
        //! The first is base texture, the second is overlay.
        TileLayer layers[MAX_TILE_LAYERS];
 };
+
+const std::vector<std::string> &getTextureDirs();
index d965384a298669a6289d547d84c40297a2dc9a51..694169d2071a7ad24acffaed6f069ef615ed15be 100644 (file)
@@ -380,15 +380,36 @@ std::string TempPath()
 
 #endif
 
-void GetRecursiveSubPaths(const std::string &path, std::vector<std::string> &dst)
+void GetRecursiveDirs(std::vector<std::string> &dirs, const std::string &dir)
+{
+       static const std::set<char> chars_to_ignore = { '_', '.' };
+       if (dir.empty() || !IsDir(dir))
+               return;
+       dirs.push_back(dir);
+       fs::GetRecursiveSubPaths(dir, dirs, false, chars_to_ignore);
+}
+
+std::vector<std::string> GetRecursiveDirs(const std::string &dir)
+{
+       std::vector<std::string> result;
+       GetRecursiveDirs(result, dir);
+       return result;
+}
+
+void GetRecursiveSubPaths(const std::string &path,
+                 std::vector<std::string> &dst,
+                 bool list_files,
+                 const std::set<char> &ignore)
 {
        std::vector<DirListNode> 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);
        }
 }
 
index 5f246e3875deefb436ae590bfd1cde934c394018..09f129aa332815e91b988e3d9c2c0f7e3a02b581 100644 (file)
@@ -19,6 +19,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 
 #pragma once
 
+#include <set>
 #include <string>
 #include <vector>
 #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<std::string> &dirs, const std::string &dir);
+std::vector<std::string> GetRecursiveDirs(const std::string &dir);
+
 /* Multiplatform */
 
-// The path itself not included
-void GetRecursiveSubPaths(const std::string &path, std::vector<std::string> &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<std::string> &dst,
+                 bool list_files,
+                 const std::set<char> &ignore = {});
 
 // Tries to delete all, returns false if any failed
 bool DeletePaths(const std::vector<std::string> &paths);
index cdb27fb60ead44608058bbb9fa955dde859f9341..95696bc20f7bb444f9aacb00fae0a5da3c54f97c 100644 (file)
@@ -532,7 +532,7 @@ int ModApiMainMenu::l_delete_world(lua_State *L)
 
                std::vector<std::string> paths;
                paths.push_back(spec.path);
-               fs::GetRecursiveSubPaths(spec.path, paths);
+               fs::GetRecursiveSubPaths(spec.path, paths, true);
 
                // Delete files
                if (!fs::DeletePaths(paths)) {
index 98c3eca9a6387c058b59b3dcf7dcdcfca294bec4..653441b54213b0233938bd544e79f3b7b4e6b9a8 100644 (file)
@@ -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<fs::DirListNode> dirlist = fs::GetDirListing(mediapath);