diff --git a/doc/lua_api.txt b/doc/lua_api.txt index f593b0db8..ebd70ea6e 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -1069,6 +1069,8 @@ minetest.pos_to_string({x=X,y=Y,z=Z}) -> "(X,Y,Z)" minetest.string_to_pos(string) -> position ^ Same but in reverse ^ escapes characters [ ] \ , ; that can not be used in formspecs +minetest.is_yes(string) +^ returns whether string can be interpreted as yes minetest namespace reference ----------------------------- @@ -1737,6 +1739,18 @@ methods: ^ from (minx,miny,minz) to (maxx,maxy,maxz) in the order of [z [y [x]]] - iterp(minp, maxp): same as above, except takes a vector +Settings: An interface to read config files in the format of minetest.conf +- Can be created via Settings(filename) +methods: +- get(key) -> value +- get_bool(key) -> boolean +- set(key, value) +- remove(key) -> success +- get_names() -> {key1,...} +- write() -> success + ^ write changes to file +- to_table() -> {[key1]=value1,...} + Mapgen objects --------------- A mapgen object is a construct used in map generation. Mapgen objects can be used by an on_generate diff --git a/doc/menu_lua_api.txt b/doc/menu_lua_api.txt index d4bc093b0..5763f875c 100644 --- a/doc/menu_lua_api.txt +++ b/doc/menu_lua_api.txt @@ -182,3 +182,9 @@ string:split(separator) ^ eg. string:split("a,b", ",") == {"a","b"} string:trim() ^ eg. string.trim("\n \t\tfoo bar\t ") == "foo bar" +minetest.is_yes(string) +^ returns whether string can be interpreted as yes + +Class reference +---------------- +Settings: see lua_api.txt diff --git a/src/script/lua_api/CMakeLists.txt b/src/script/lua_api/CMakeLists.txt index d75c04335..08960d2ad 100644 --- a/src/script/lua_api/CMakeLists.txt +++ b/src/script/lua_api/CMakeLists.txt @@ -15,6 +15,7 @@ set(common_SCRIPT_LUA_API_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/l_server.cpp ${CMAKE_CURRENT_SOURCE_DIR}/l_util.cpp ${CMAKE_CURRENT_SOURCE_DIR}/l_vmanip.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/l_settings.cpp PARENT_SCOPE) # Used by client only diff --git a/src/script/lua_api/l_settings.cpp b/src/script/lua_api/l_settings.cpp new file mode 100644 index 000000000..13a88ee95 --- /dev/null +++ b/src/script/lua_api/l_settings.cpp @@ -0,0 +1,216 @@ +/* +Minetest +Copyright (C) 2013 PilzAdam + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 2.1 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include "lua_api/l_settings.h" +#include "lua_api/l_internal.h" +#include "settings.h" +#include "log.h" + +// garbage collector +int LuaSettings::gc_object(lua_State* L) +{ + LuaSettings* o = *(LuaSettings **)(lua_touserdata(L, 1)); + delete o; + return 0; +} + +// get(self, key) -> value +int LuaSettings::l_get(lua_State* L) +{ + NO_MAP_LOCK_REQUIRED; + LuaSettings* o = checkobject(L, 1); + + std::string key = std::string(luaL_checkstring(L, 2)); + if (o->m_settings->exists(key)) { + std::string value = o->m_settings->get(key); + lua_pushstring(L, value.c_str()); + } else { + lua_pushnil(L); + } + + return 1; +} + +// get_bool(self, key) -> boolean +int LuaSettings::l_get_bool(lua_State* L) +{ + NO_MAP_LOCK_REQUIRED; + LuaSettings* o = checkobject(L, 1); + + std::string key = std::string(luaL_checkstring(L, 2)); + if (o->m_settings->exists(key)) { + bool value = o->m_settings->getBool(key); + lua_pushboolean(L, value); + } else { + lua_pushnil(L); + } + + return 1; +} + +// set(self, key, value) +int LuaSettings::l_set(lua_State* L) +{ + NO_MAP_LOCK_REQUIRED; + LuaSettings* o = checkobject(L, 1); + + std::string key = std::string(luaL_checkstring(L, 2)); + const char* value = luaL_checkstring(L, 3); + + o->m_settings->set(key, value); + + return 1; +} + +// remove(self, key) -> success +int LuaSettings::l_remove(lua_State* L) +{ + NO_MAP_LOCK_REQUIRED; + LuaSettings* o = checkobject(L, 1); + + std::string key = std::string(luaL_checkstring(L, 2)); + + bool success = o->m_settings->remove(key); + lua_pushboolean(L, success); + + return 1; +} + +// get_names(self) -> {key1, ...} +int LuaSettings::l_get_names(lua_State* L) +{ + NO_MAP_LOCK_REQUIRED; + LuaSettings* o = checkobject(L, 1); + + std::vector keys = o->m_settings->getNames(); + + lua_newtable(L); + for (unsigned int i=0; i < keys.size(); i++) + { + lua_pushstring(L, keys[i].c_str()); + lua_rawseti(L, -2, i + 1); + } + + return 1; +} + +// write(self) -> success +int LuaSettings::l_write(lua_State* L) +{ + NO_MAP_LOCK_REQUIRED; + LuaSettings* o = checkobject(L, 1); + + bool success = o->m_settings->updateConfigFile(o->m_filename.c_str()); + lua_pushboolean(L, success); + + return 1; +} + +// to_table(self) -> {[key1]=value1,...} +int LuaSettings::l_to_table(lua_State* L) +{ + NO_MAP_LOCK_REQUIRED; + LuaSettings* o = checkobject(L, 1); + + std::vector keys = o->m_settings->getNames(); + + lua_newtable(L); + for (unsigned int i=0; i < keys.size(); i++) + { + lua_pushstring(L, o->m_settings->get(keys[i]).c_str()); + lua_setfield(L, -2, keys[i].c_str()); + } + + return 1; +} + +LuaSettings::LuaSettings(const char* filename) +{ + m_filename = std::string(filename); + + m_settings = new Settings(); + m_settings->readConfigFile(m_filename.c_str()); +} + +LuaSettings::~LuaSettings() +{ + delete m_settings; +} + +void LuaSettings::Register(lua_State* L) +{ + lua_newtable(L); + int methodtable = lua_gettop(L); + luaL_newmetatable(L, className); + int metatable = lua_gettop(L); + + lua_pushliteral(L, "__metatable"); + lua_pushvalue(L, methodtable); + lua_settable(L, metatable); // hide metatable from Lua getmetatable() + + lua_pushliteral(L, "__index"); + lua_pushvalue(L, methodtable); + lua_settable(L, metatable); + + lua_pushliteral(L, "__gc"); + lua_pushcfunction(L, gc_object); + lua_settable(L, metatable); + + lua_pop(L, 1); // drop metatable + + luaL_openlib(L, 0, methods, 0); // fill methodtable + lua_pop(L, 1); // drop methodtable + + // Can be created from Lua (Settings(filename)) + lua_register(L, className, create_object); +} + +// LuaSettings(filename) +// Creates an LuaSettings and leaves it on top of stack +int LuaSettings::create_object(lua_State* L) +{ + NO_MAP_LOCK_REQUIRED; + const char* filename = luaL_checkstring(L, 1); + LuaSettings* o = new LuaSettings(filename); + *(void **)(lua_newuserdata(L, sizeof(void *))) = o; + luaL_getmetatable(L, className); + lua_setmetatable(L, -2); + return 1; +} + +LuaSettings* LuaSettings::checkobject(lua_State* L, int narg) +{ + NO_MAP_LOCK_REQUIRED; + luaL_checktype(L, narg, LUA_TUSERDATA); + void *ud = luaL_checkudata(L, narg, className); + if(!ud) luaL_typerror(L, narg, className); + return *(LuaSettings**)ud; // unbox pointer +} + +const char LuaSettings::className[] = "Settings"; +const luaL_reg LuaSettings::methods[] = { + luamethod(LuaSettings, get), + luamethod(LuaSettings, get_bool), + luamethod(LuaSettings, set), + luamethod(LuaSettings, remove), + luamethod(LuaSettings, get_names), + luamethod(LuaSettings, write), + luamethod(LuaSettings, to_table), + {0,0} +}; diff --git a/src/script/lua_api/l_settings.h b/src/script/lua_api/l_settings.h new file mode 100644 index 000000000..cb0c09a73 --- /dev/null +++ b/src/script/lua_api/l_settings.h @@ -0,0 +1,73 @@ +/* +Minetest +Copyright (C) 2013 PilzAdam + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 2.1 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#ifndef L_SETTINGS_H_ +#define L_SETTINGS_H_ + +#include "lua_api/l_base.h" + +class Settings; + +class LuaSettings : public ModApiBase { +private: + static const char className[]; + static const luaL_reg methods[]; + + // garbage collector + static int gc_object(lua_State* L); + + // get(self, key) -> value + static int l_get(lua_State* L); + + // get_bool(self, key) -> boolean + static int l_get_bool(lua_State* L); + + // set(self, key, value) + static int l_set(lua_State* L); + + // remove(self, key) -> success + static int l_remove(lua_State* L); + + // get_names(self) -> {key1, ...} + static int l_get_names(lua_State* L); + + // write(self) -> success + static int l_write(lua_State* L); + + // to_table(self) -> {[key1]=value1,...} + static int l_to_table(lua_State* L); + + Settings* m_settings; + std::string m_filename; + +public: + LuaSettings(const char* filename); + ~LuaSettings(); + + // LuaSettings(filename) + // Creates an LuaSettings and leaves it on top of stack + static int create_object(lua_State* L); + + static LuaSettings* checkobject(lua_State* L, int narg); + + static void Register(lua_State* L); + +}; + +#endif diff --git a/src/script/lua_api/l_util.cpp b/src/script/lua_api/l_util.cpp index 30fa56c42..34788accd 100644 --- a/src/script/lua_api/l_util.cpp +++ b/src/script/lua_api/l_util.cpp @@ -220,6 +220,16 @@ int ModApiUtil::l_get_password_hash(lua_State *L) return 1; } +// is_yes(string) +int ModApiUtil::l_is_yes(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + std::string str = luaL_checkstring(L, 1); + bool yes = is_yes(str); + lua_pushboolean(L, yes); + return 1; +} + void ModApiUtil::Initialize(lua_State *L, int top) { API_FCT(debug); @@ -237,5 +247,7 @@ void ModApiUtil::Initialize(lua_State *L, int top) API_FCT(get_hit_params); API_FCT(get_password_hash); + + API_FCT(is_yes); } diff --git a/src/script/lua_api/l_util.h b/src/script/lua_api/l_util.h index 71c55b342..ae2163ec8 100644 --- a/src/script/lua_api/l_util.h +++ b/src/script/lua_api/l_util.h @@ -71,6 +71,9 @@ private: // get_password_hash(name, raw_password) static int l_get_password_hash(lua_State *L); + // is_yes(string) + static int l_is_yes(lua_State *L); + public: static void Initialize(lua_State *L, int top); diff --git a/src/script/scripting_game.cpp b/src/script/scripting_game.cpp index dfbf471d2..043ee4bae 100644 --- a/src/script/scripting_game.cpp +++ b/src/script/scripting_game.cpp @@ -35,6 +35,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "lua_api/l_server.h" #include "lua_api/l_util.h" #include "lua_api/l_vmanip.h" +#include "lua_api/l_settings.h" extern "C" { #include "lualib.h" @@ -96,4 +97,5 @@ void GameScripting::InitializeModApi(lua_State *L, int top) NodeMetaRef::Register(L); NodeTimerRef::Register(L); ObjectRef::Register(L); + LuaSettings::Register(L); } diff --git a/src/script/scripting_mainmenu.cpp b/src/script/scripting_mainmenu.cpp index 47461e7ca..31581a1bf 100644 --- a/src/script/scripting_mainmenu.cpp +++ b/src/script/scripting_mainmenu.cpp @@ -24,6 +24,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "lua_api/l_base.h" #include "lua_api/l_mainmenu.h" #include "lua_api/l_util.h" +#include "lua_api/l_settings.h" extern "C" { #include "lualib.h" @@ -62,4 +63,7 @@ void MainMenuScripting::InitializeModApi(lua_State *L, int top) // Initialize mod api modules ModApiMainMenu::Initialize(L, top); ModApiUtil::Initialize(L, top); + + // Register reference classes (userdata) + LuaSettings::Register(L); }