From d10ea2ad7efc2364a8a2007b4c6d3e85511e2f84 Mon Sep 17 00:00:00 2001 From: Maxime Devos Date: Tue, 3 Aug 2021 01:00:23 +0200 Subject: [PATCH] Add environment variable MINETEST_MOD_PATH This adds an environment variable MINETEST_MOD_PATH. When it exists, Minetest will look there for mods in addition to ~/.minetest/mods/. Mods can still be installed to ~/.minetest/mods/ with the built-in installer. With thanks to Liliana Marie Prikler. --- builtin/mainmenu/pkgmgr.lua | 7 +++---- doc/menu_lua_api.txt | 8 +++++++- src/content/subgames.cpp | 11 +++++++++++ src/script/lua_api/l_mainmenu.cpp | 23 +++++++++++++++++++++++ src/script/lua_api/l_mainmenu.h | 2 ++ 5 files changed, 46 insertions(+), 5 deletions(-) diff --git a/builtin/mainmenu/pkgmgr.lua b/builtin/mainmenu/pkgmgr.lua index 787936e31..d8fba0ebe 100644 --- a/builtin/mainmenu/pkgmgr.lua +++ b/builtin/mainmenu/pkgmgr.lua @@ -682,10 +682,9 @@ function pkgmgr.preparemodlist(data) local game_mods = {} --read global mods - local modpath = core.get_modpath() - - if modpath ~= nil and - modpath ~= "" then + local modpaths = core.get_modpaths() + --XXX what was ‘modpath ~= ""’ and ‘modpath ~= nil’ for? + for _,modpath in ipairs(modpaths) do get_mods(modpath,global_mods) end diff --git a/doc/menu_lua_api.txt b/doc/menu_lua_api.txt index b3975bc1d..132444b14 100644 --- a/doc/menu_lua_api.txt +++ b/doc/menu_lua_api.txt @@ -218,7 +218,13 @@ Package - content which is downloadable from the content db, may or may not be i * returns path to global user data, the directory that contains user-provided mods, worlds, games, and texture packs. * core.get_modpath() (possible in async calls) - * returns path to global modpath + * returns path to global modpath, where mods can be installed +* core.get_modpaths() (possible in async calls) + * returns list of paths to global modpaths, where mods have been installed + + The difference with "core.get_modpath" is that no mods should be installed in these + directories by Minetest -- they might be read-only. + * core.get_clientmodpath() (possible in async calls) * returns path to global client-side modpath * core.get_gamepath() (possible in async calls) diff --git a/src/content/subgames.cpp b/src/content/subgames.cpp index e9dc609b0..d73f95a1f 100644 --- a/src/content/subgames.cpp +++ b/src/content/subgames.cpp @@ -61,6 +61,12 @@ std::string getSubgamePathEnv() return subgame_path ? std::string(subgame_path) : ""; } +std::string getModPathEnv() +{ + char *mod_path = getenv("MINETEST_MOD_PATH"); + return mod_path ? std::string(mod_path) : ""; +} + SubgameSpec findSubgame(const std::string &id) { if (id.empty()) @@ -110,6 +116,11 @@ SubgameSpec findSubgame(const std::string &id) std::set mods_paths; if (!user_game) mods_paths.insert(share + DIR_DELIM + "mods"); + + Strfnd mod_search_paths(getModPathEnv()); + while (!mod_search_paths.at_end()) + mods_paths.insert(mod_search_paths.next(PATH_DELIM)); + if (user != share || user_game) mods_paths.insert(user + DIR_DELIM + "mods"); diff --git a/src/script/lua_api/l_mainmenu.cpp b/src/script/lua_api/l_mainmenu.cpp index 3e9709bde..903ac3a22 100644 --- a/src/script/lua_api/l_mainmenu.cpp +++ b/src/script/lua_api/l_mainmenu.cpp @@ -21,6 +21,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "lua_api/l_internal.h" #include "common/c_content.h" #include "cpp_api/s_async.h" +#include "util/strfnd.h" #include "gui/guiEngine.h" #include "gui/guiMainMenu.h" #include "gui/guiKeyChangeMenu.h" @@ -502,6 +503,26 @@ int ModApiMainMenu::l_get_modpath(lua_State *L) return 1; } +/******************************************************************************/ +int ModApiMainMenu::l_get_modpaths(lua_State *L) +{ + const char *c_modpath = getenv("MINETEST_MOD_PATH"); + if (c_modpath == NULL) + c_modpath = ""; + int index = 1; + lua_newtable(L); + Strfnd mod_search_paths{std::string(c_modpath)}; + while (!mod_search_paths.at_end()) { + std::string component = mod_search_paths.next(PATH_DELIM); + lua_pushstring(L, component.c_str()); + lua_rawseti(L, -2, index); + index++; + } + ModApiMainMenu::l_get_modpath(L); + lua_rawseti(L, -2, index); + return 1; +} + /******************************************************************************/ int ModApiMainMenu::l_get_clientmodpath(lua_State *L) { @@ -949,6 +970,7 @@ void ModApiMainMenu::Initialize(lua_State *L, int top) API_FCT(get_mapgen_names); API_FCT(get_user_path); API_FCT(get_modpath); + API_FCT(get_modpaths); API_FCT(get_clientmodpath); API_FCT(get_gamepath); API_FCT(get_texturepath); @@ -983,6 +1005,7 @@ void ModApiMainMenu::InitializeAsync(lua_State *L, int top) API_FCT(get_mapgen_names); API_FCT(get_user_path); API_FCT(get_modpath); + API_FCT(get_modpaths); API_FCT(get_clientmodpath); API_FCT(get_gamepath); API_FCT(get_texturepath); diff --git a/src/script/lua_api/l_mainmenu.h b/src/script/lua_api/l_mainmenu.h index 33ac9e721..a6a54a2cb 100644 --- a/src/script/lua_api/l_mainmenu.h +++ b/src/script/lua_api/l_mainmenu.h @@ -112,6 +112,8 @@ class ModApiMainMenu: public ModApiBase static int l_get_modpath(lua_State *L); + static int l_get_modpaths(lua_State *L); + static int l_get_clientmodpath(lua_State *L); static int l_get_gamepath(lua_State *L); -- 2.32.0