]> git.lizzy.rs Git - minetest.git/commitdiff
Add `minetest.get_game_info` and allow reading `game.conf` (#12989)
authorJude Melton-Houghton <jwmhjwmh@gmail.com>
Mon, 28 Nov 2022 12:21:43 +0000 (07:21 -0500)
committerGitHub <noreply@github.com>
Mon, 28 Nov 2022 12:21:43 +0000 (07:21 -0500)
Co-authored-by: sfan5 <sfan5@live.de>
doc/lua_api.txt
games/devtest/mods/unittests/misc.lua
src/gamedef.h
src/script/cpp_api/s_security.cpp
src/script/lua_api/l_server.cpp
src/script/lua_api/l_server.h
src/server.h

index 1c8cc10221ae10473c8bd94cff2c274b15411f39..b58c75d11f18899610eac99f9f332fdc1291a384 100644 (file)
@@ -4879,6 +4879,18 @@ Utilities
   or checking if a mod is enabled.
 * `minetest.get_modnames()`: returns a list of enabled mods, sorted alphabetically.
     * Does not include disabled mods, even if they are installed.
+* `minetest.get_game_info()`: returns a table containing information about the
+  current game. Note that other meta information (e.g. version/release number)
+  can be manually read from `game.conf` in the game's root directory.
+
+      {
+          id = string,
+          title = string,
+          author = string,
+          -- The root directory of the game
+          path = string,
+      }
+
 * `minetest.get_worldpath()`: returns e.g. `"/home/user/.minetest/world"`
     * Useful for storing custom data
 * `minetest.is_singleplayer()`
index 8ac3ed110502cae71dbc10ebcd692eb23eb243b9..7c16b7c8201e20c76432083a4146754544ac3cc1 100644 (file)
@@ -103,3 +103,10 @@ local function test_compress()
 end
 unittests.register("test_compress", test_compress)
 
+local function test_game_info()
+       local info = minetest.get_game_info()
+       local game_conf = Settings(info.path .. "/game.conf")
+       assert(info.id == "devtest")
+       assert(info.title == game_conf:get("title"))
+end
+unittests.register("test_game_info", test_game_info)
index e32d10509ab304f58148ba92b16573821fee3e88..df1fa24582959e4c4fb31e068385124819b38f8c 100644 (file)
@@ -40,6 +40,7 @@ namespace irr { namespace scene {
        class ISceneManager;
 }}
 
+struct SubgameSpec;
 struct ModSpec;
 /*
        An interface for fetching game-global definitions like tool and
@@ -72,6 +73,7 @@ class IGameDef
 
        virtual const std::vector<ModSpec> &getMods() const = 0;
        virtual const ModSpec* getModSpec(const std::string &modname) const = 0;
+       virtual const SubgameSpec* getGameSpec() const { return nullptr; }
        virtual std::string getWorldPath() const { return ""; }
        virtual ModStorageDatabase *getModStorageDatabase() = 0;
 
index 0d989ae04d07ca314ffb3fcc1e93943cff7caf68..09e97100753a6f085e735b283d574179fdf63507 100644 (file)
@@ -579,6 +579,17 @@ bool ScriptApiSecurity::checkPath(lua_State *L, const char *path,
        }
        lua_pop(L, 1);  // Pop mod name
 
+       // Allow read-only access to game directory
+       if (!write_required) {
+               const SubgameSpec *game_spec = gamedef->getGameSpec();
+               if (game_spec && !game_spec->path.empty()) {
+                       str = fs::AbsolutePath(game_spec->path);
+                       if (!str.empty() && fs::PathStartsWith(abs_path, str)) {
+                               return true;
+                       }
+               }
+       }
+
        // Allow read-only access to all mod directories
        if (!write_required) {
                const std::vector<ModSpec> &mods = gamedef->getMods();
index a5daae346ae6304947b07092be6624dcfe2e1c57..fb2018aacce948177a07a68e4a8e9e45303a9ea6 100644 (file)
@@ -424,6 +424,20 @@ int ModApiServer::l_get_modnames(lua_State *L)
        return 1;
 }
 
+// get_game_info()
+int ModApiServer::l_get_game_info(lua_State *L)
+{
+       NO_MAP_LOCK_REQUIRED;
+       const SubgameSpec *game_spec = getGameDef(L)->getGameSpec();
+       assert(game_spec);
+       lua_newtable(L);
+       setstringfield(L, -1, "id", game_spec->id);
+       setstringfield(L, -1, "title", game_spec->title);
+       setstringfield(L, -1, "author", game_spec->author);
+       setstringfield(L, -1, "path", game_spec->path);
+       return 1;
+}
+
 // get_worldpath()
 int ModApiServer::l_get_worldpath(lua_State *L)
 {
@@ -608,6 +622,7 @@ void ModApiServer::Initialize(lua_State *L, int top)
        API_FCT(get_current_modname);
        API_FCT(get_modpath);
        API_FCT(get_modnames);
+       API_FCT(get_game_info);
 
        API_FCT(print);
 
@@ -643,4 +658,5 @@ void ModApiServer::InitializeAsync(lua_State *L, int top)
        API_FCT(get_current_modname);
        API_FCT(get_modpath);
        API_FCT(get_modnames);
+       API_FCT(get_game_info);
 }
index a4f38c34e7d7c06581f0c58e05d7e2753b52d995..15d61669e58488fddc1a69f3ca608bf4935453c0 100644 (file)
@@ -52,6 +52,9 @@ class ModApiServer : public ModApiBase
        // the returned list is sorted alphabetically for you
        static int l_get_modnames(lua_State *L);
 
+       // get_game_info()
+       static int l_get_game_info(lua_State *L);
+
        // print(text)
        static int l_print(lua_State *L);
 
index 06da14a9a4b5e8af647151930da86fd2401d88f0..365fdf625f6d776e67554fd62ffb7451e33a6f44 100644 (file)
@@ -284,6 +284,7 @@ class Server : public con::PeerHandler, public MapEventReceiver,
 
        virtual const std::vector<ModSpec> &getMods() const;
        virtual const ModSpec* getModSpec(const std::string &modname) const;
+       virtual const SubgameSpec* getGameSpec() const { return &m_gamespec; }
        static std::string getBuiltinLuaPath();
        virtual std::string getWorldPath() const { return m_path_world; }