diff options
author | Kahrl <kahrl@gmx.net> | 2013-08-11 04:09:45 +0200 |
---|---|---|
committer | Kahrl <kahrl@gmx.net> | 2013-08-14 21:03:33 +0200 |
commit | 4e1f50035e860a00636ca5d804c267119df99601 (patch) | |
tree | c6cab522305ef2a5b9cfdb3685340d57590f1ff1 /src/script | |
parent | 6228d634fb31d1ce925d1fdc2dac022629a007ef (diff) | |
download | minetest-4e1f50035e860a00636ca5d804c267119df99601.tar.gz minetest-4e1f50035e860a00636ca5d804c267119df99601.tar.bz2 minetest-4e1f50035e860a00636ca5d804c267119df99601.zip |
Omnicleanup: header cleanup, add ModApiUtil shared between game and mainmenu
Diffstat (limited to 'src/script')
63 files changed, 3872 insertions, 2255 deletions
diff --git a/src/script/CMakeLists.txt b/src/script/CMakeLists.txt index e1a03b95a..491c05a1e 100644 --- a/src/script/CMakeLists.txt +++ b/src/script/CMakeLists.txt @@ -2,8 +2,18 @@ add_subdirectory(common) add_subdirectory(cpp_api) add_subdirectory(lua_api) -set(SCRIPT_SRCS - ${SCRIPT_COMMON_SRCS} - ${SCRIPT_CPP_API_SRCS} - ${SCRIPT_LUA_API_SRCS} +# Used by server and client +set(common_SCRIPT_SRCS + ${CMAKE_CURRENT_SOURCE_DIR}/scripting_game.cpp + ${common_SCRIPT_COMMON_SRCS} + ${common_SCRIPT_CPP_API_SRCS} + ${common_SCRIPT_LUA_API_SRCS} + PARENT_SCOPE) + +# Used by client only +set(minetest_SCRIPT_SRCS + ${CMAKE_CURRENT_SOURCE_DIR}/scripting_mainmenu.cpp + ${minetest_SCRIPT_COMMON_SRCS} + ${minetest_SCRIPT_CPP_API_SRCS} + ${minetest_SCRIPT_LUA_API_SRCS} PARENT_SCOPE) diff --git a/src/script/common/CMakeLists.txt b/src/script/common/CMakeLists.txt index c8f7ef783..27e2fb4d5 100644 --- a/src/script/common/CMakeLists.txt +++ b/src/script/common/CMakeLists.txt @@ -1,6 +1,11 @@ -set(SCRIPT_COMMON_SRCS +# Used by server and client +set(common_SCRIPT_COMMON_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/c_content.cpp ${CMAKE_CURRENT_SOURCE_DIR}/c_converter.cpp ${CMAKE_CURRENT_SOURCE_DIR}/c_types.cpp ${CMAKE_CURRENT_SOURCE_DIR}/c_internal.cpp PARENT_SCOPE) + +# Used by client only +set(minetest_SCRIPT_COMMON_SRCS + PARENT_SCOPE) diff --git a/src/script/common/c_content.cpp b/src/script/common/c_content.cpp index cb2b0e737..2e26adb76 100644 --- a/src/script/common/c_content.cpp +++ b/src/script/common/c_content.cpp @@ -29,7 +29,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "server.h" #include "log.h" #include "tool.h" -#include "server.h" +#include "serverobject.h" #include "mapgen.h" struct EnumString es_TileAnimationType[] = @@ -694,8 +694,7 @@ void push_tool_capabilities(lua_State *L, } /******************************************************************************/ -void push_inventory_list(Inventory *inv, const char *name, - lua_State *L) +void push_inventory_list(lua_State *L, Inventory *inv, const char *name) { InventoryList *invlist = inv->getList(name); if(invlist == NULL){ @@ -709,8 +708,8 @@ void push_inventory_list(Inventory *inv, const char *name, } /******************************************************************************/ -void read_inventory_list(Inventory *inv, const char *name, - lua_State *L, int tableindex, Server* srv,int forcesize) +void read_inventory_list(lua_State *L, int tableindex, + Inventory *inv, const char *name, Server* srv, int forcesize) { if(tableindex < 0) tableindex = lua_gettop(L) + 1 + tableindex; diff --git a/src/script/common/c_content.h b/src/script/common/c_content.h index fc00ce089..6d1dfe1d5 100644 --- a/src/script/common/c_content.h +++ b/src/script/common/c_content.h @@ -87,14 +87,13 @@ void read_object_properties (lua_State *L, int index, ObjectProperties *prop); -//TODO fix parameter oreder! -void push_inventory_list (Inventory *inv, - const char *name, - lua_State *L); -void read_inventory_list (Inventory *inv, - const char *name, - lua_State *L, +void push_inventory_list (lua_State *L, + Inventory *inv, + const char *name); +void read_inventory_list (lua_State *L, int tableindex, + Inventory *inv, + const char *name, Server* srv, int forcesize=-1); diff --git a/src/script/common/c_internal.cpp b/src/script/common/c_internal.cpp index 42e9fb3e1..5c16b88d9 100644 --- a/src/script/common/c_internal.cpp +++ b/src/script/common/c_internal.cpp @@ -18,17 +18,7 @@ with this program; if not, write to the Free Software Foundation, Inc., */ #include "common/c_internal.h" -#include "server.h" -#include "cpp_api/scriptapi.h" - -ScriptApi* get_scriptapi(lua_State *L) -{ - // Get server from registry - lua_getfield(L, LUA_REGISTRYINDEX, "scriptapi"); - ScriptApi* sapi_ptr = (ScriptApi*) lua_touserdata(L, -1); - lua_pop(L, 1); - return sapi_ptr; -} +#include "debug.h" std::string script_get_backtrace(lua_State *L) { @@ -51,15 +41,108 @@ std::string script_get_backtrace(lua_State *L) return s; } -void script_error(lua_State* L,const char *fmt, ...) +void script_error(lua_State *L, const char *fmt, ...) { va_list argp; va_start(argp, fmt); char buf[10000]; vsnprintf(buf, 10000, fmt, argp); va_end(argp); - //errorstream<<"SCRIPT ERROR: "<<buf; throw LuaError(L, buf); } +// Push the list of callbacks (a lua table). +// Then push nargs arguments. +// Then call this function, which +// - runs the callbacks +// - removes the table and arguments from the lua stack +// - pushes the return value, computed depending on mode +void script_run_callbacks(lua_State *L, int nargs, RunCallbacksMode mode) +{ + // Insert the return value into the lua stack, below the table + assert(lua_gettop(L) >= nargs + 1); + lua_pushnil(L); + lua_insert(L, -(nargs + 1) - 1); + // Stack now looks like this: + // ... <return value = nil> <table> <arg#1> <arg#2> ... <arg#n> + + int rv = lua_gettop(L) - nargs - 1; + int table = rv + 1; + int arg = table + 1; + + luaL_checktype(L, table, LUA_TTABLE); + + // Foreach + lua_pushnil(L); + bool first_loop = true; + while(lua_next(L, table) != 0){ + // key at index -2 and value at index -1 + luaL_checktype(L, -1, LUA_TFUNCTION); + // Call function + for(int i = 0; i < nargs; i++) + lua_pushvalue(L, arg+i); + if(lua_pcall(L, nargs, 1, 0)) + script_error(L, "error: %s", lua_tostring(L, -1)); + + // Move return value to designated space in stack + // Or pop it + if(first_loop){ + // Result of first callback is always moved + lua_replace(L, rv); + first_loop = false; + } else { + // Otherwise, what happens depends on the mode + if(mode == RUN_CALLBACKS_MODE_FIRST) + lua_pop(L, 1); + else if(mode == RUN_CALLBACKS_MODE_LAST) + lua_replace(L, rv); + else if(mode == RUN_CALLBACKS_MODE_AND || + mode == RUN_CALLBACKS_MODE_AND_SC){ + if((bool)lua_toboolean(L, rv) == true && + (bool)lua_toboolean(L, -1) == false) + lua_replace(L, rv); + else + lua_pop(L, 1); + } + else if(mode == RUN_CALLBACKS_MODE_OR || + mode == RUN_CALLBACKS_MODE_OR_SC){ + if((bool)lua_toboolean(L, rv) == false && + (bool)lua_toboolean(L, -1) == true) + lua_replace(L, rv); + else + lua_pop(L, 1); + } + else + assert(0); + } + + // Handle short circuit modes + if(mode == RUN_CALLBACKS_MODE_AND_SC && + (bool)lua_toboolean(L, rv) == false) + break; + else if(mode == RUN_CALLBACKS_MODE_OR_SC && + (bool)lua_toboolean(L, rv) == true) + break; + + // value removed, keep key for next iteration + } + + // Remove stuff from stack, leaving only the return value + lua_settop(L, rv); + + // Fix return value in case no callbacks were called + if(first_loop){ + if(mode == RUN_CALLBACKS_MODE_AND || + mode == RUN_CALLBACKS_MODE_AND_SC){ + lua_pop(L, 1); + lua_pushboolean(L, true); + } + else if(mode == RUN_CALLBACKS_MODE_OR || + mode == RUN_CALLBACKS_MODE_OR_SC){ + lua_pop(L, 1); + lua_pushboolean(L, false); + } + } +} + diff --git a/src/script/common/c_internal.h b/src/script/common/c_internal.h index dafde5843..9a50b8e96 100644 --- a/src/script/common/c_internal.h +++ b/src/script/common/c_internal.h @@ -27,34 +27,46 @@ with this program; if not, write to the Free Software Foundation, Inc., #ifndef C_INTERNAL_H_ #define C_INTERNAL_H_ -class Server; -class ScriptApi; -#include <iostream> - -#include "lua_api/l_base.h" - extern "C" { -#include "lua.h" +#include <lua.h> +#include <lauxlib.h> } -#define luamethod(class, name) {#name, class::l_##name} -#define STACK_TO_SERVER(L) get_scriptapi(L)->getServer() -#define API_FCT(name) registerFunction(L,#name,l_##name,top) - -#define REGISTER_LUA_REF(cln) \ -class ModApi_##cln : public ModApiBase { \ - public: \ - ModApi_##cln() : ModApiBase() {}; \ - bool Initialize(lua_State* L, int top) { \ - cln::Register(L); \ - return true; \ - }; \ -}; \ -ModApi_##cln macro_generated_prototype__##cln; +#include "common/c_types.h" +// What script_run_callbacks does with the return values of callbacks. +// Regardless of the mode, if only one callback is defined, +// its return value is the total return value. +// Modes only affect the case where 0 or >= 2 callbacks are defined. +enum RunCallbacksMode +{ + // Returns the return value of the first callback + // Returns nil if list of callbacks is empty + RUN_CALLBACKS_MODE_FIRST, + // Returns the return value of the last callback + // Returns nil if list of callbacks is empty + RUN_CALLBACKS_MODE_LAST, + // If any callback returns a false value, the first such is returned + // Otherwise, the first callback's return value (trueish) is returned + // Returns true if list of callbacks is empty + RUN_CALLBACKS_MODE_AND, + // Like above, but stops calling callbacks (short circuit) + // after seeing the first false value + RUN_CALLBACKS_MODE_AND_SC, + // If any callback returns a true value, the first such is returned + // Otherwise, the first callback's return value (falseish) is returned + // Returns false if list of callbacks is empty + RUN_CALLBACKS_MODE_OR, + // Like above, but stops calling callbacks (short circuit) + // after seeing the first true value + RUN_CALLBACKS_MODE_OR_SC, + // Note: "a true value" and "a false value" refer to values that + // are converted by lua_toboolean to true or false, respectively. +}; -ScriptApi* get_scriptapi (lua_State *L); std::string script_get_backtrace (lua_State *L); void script_error (lua_State *L, const char *fmt, ...); +void script_run_callbacks (lua_State *L, int nargs, + RunCallbacksMode mode); #endif /* C_INTERNAL_H_ */ diff --git a/src/script/common/c_types.h b/src/script/common/c_types.h index 7df869432..bc9f1cb96 100644 --- a/src/script/common/c_types.h +++ b/src/script/common/c_types.h @@ -50,26 +50,6 @@ public: } }; -class ModNameStorer -{ -private: - lua_State *L; -public: - ModNameStorer(lua_State *L_, const std::string modname): - L(L_) - { - // Store current modname in registry - lua_pushstring(L, modname.c_str()); - lua_setfield(L, LUA_REGISTRYINDEX, "minetest_current_modname"); - } - ~ModNameStorer() - { - // Clear current modname in registry - lua_pushnil(L); - lua_setfield(L, LUA_REGISTRYINDEX, "minetest_current_modname"); - } -}; - class LuaError : public std::exception { public: diff --git a/src/script/cpp_api/CMakeLists.txt b/src/script/cpp_api/CMakeLists.txt index 6f5b51a49..b753eda17 100644 --- a/src/script/cpp_api/CMakeLists.txt +++ b/src/script/cpp_api/CMakeLists.txt @@ -1,4 +1,5 @@ -set(SCRIPT_CPP_API_SRCS +# Used by server and client +set(common_SCRIPT_CPP_API_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/s_base.cpp ${CMAKE_CURRENT_SOURCE_DIR}/s_entity.cpp ${CMAKE_CURRENT_SOURCE_DIR}/s_env.cpp @@ -7,5 +8,10 @@ set(SCRIPT_CPP_API_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/s_node.cpp ${CMAKE_CURRENT_SOURCE_DIR}/s_nodemeta.cpp ${CMAKE_CURRENT_SOURCE_DIR}/s_player.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/scriptapi.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/s_server.cpp + PARENT_SCOPE) + +# Used by client only +set(minetest_SCRIPT_CPP_API_SRCS + ${CMAKE_CURRENT_SOURCE_DIR}/s_mainmenu.cpp PARENT_SCOPE) diff --git a/src/script/cpp_api/s_base.cpp b/src/script/cpp_api/s_base.cpp index e2e586357..e26d54ba7 100644 --- a/src/script/cpp_api/s_base.cpp +++ b/src/script/cpp_api/s_base.cpp @@ -17,30 +17,141 @@ with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ +#include "cpp_api/s_base.h" +#include "cpp_api/s_internal.h" +#include "lua_api/l_object.h" +#include "serverobject.h" +#include "debug.h" +#include "log.h" +#include "mods.h" +#include "util/string.h" + + +extern "C" { +#include "lualib.h" +} + #include <stdio.h> #include <cstdarg> -extern "C" { -#include "lua.h" -#include "lauxlib.h" + +class ModNameStorer +{ +private: + lua_State *L; +public: + ModNameStorer(lua_State *L_, const std::string modname): + L(L_) + { + // Store current modname in registry + lua_pushstring(L, modname.c_str()); + lua_setfield(L, LUA_REGISTRYINDEX, "minetest_current_modname"); + } + ~ModNameStorer() + { + // Clear current modname in registry + lua_pushnil(L); + lua_setfield(L, LUA_REGISTRYINDEX, "minetest_current_modname"); + } +}; + +static int loadScript_ErrorHandler(lua_State *L) { + lua_getfield(L, LUA_GLOBALSINDEX, "debug"); + if (!lua_istable(L, -1)) { + lua_pop(L, 1); + return 1; + } + lua_getfield(L, -1, "traceback"); + if (!lua_isfunction(L, -1)) { + lua_pop(L, 2); + return 1; + } + lua_pushvalue(L, 1); + lua_pushinteger(L, 2); + lua_call(L, 2, 1); + return 1; } -#include "cpp_api/s_base.h" -#include "lua_api/l_object.h" -#include "serverobject.h" -ScriptApiBase::ScriptApiBase() : - m_luastackmutex(), -#ifdef LOCK_DEBUG - m_locked(false), -#endif - m_luastack(0), - m_server(0), - m_environment(0) +/* + ScriptApiBase +*/ + +ScriptApiBase::ScriptApiBase() { + m_luastackmutex.Init(); + + #ifdef SCRIPTAPI_LOCK_DEBUG + m_locked = false; + #endif + m_luastack = luaL_newstate(); + assert(m_luastack); + + // Make the ScriptApiBase* accessible to ModApiBase + lua_pushlightuserdata(m_luastack, this); + lua_setfield(m_luastack, LUA_REGISTRYINDEX, "scriptapi"); + + m_server = 0; + m_environment = 0; + m_guiengine = 0; } +ScriptApiBase::~ScriptApiBase() +{ + lua_close(m_luastack); +} + +bool ScriptApiBase::loadMod(const std::string &scriptpath, + const std::string &modname) +{ + ModNameStorer modnamestorer(getStack(), modname); + + if(!string_allowed(modname, MODNAME_ALLOWED_CHARS)){ + errorstream<<"Error loading mod \""<<modname + <<"\": modname does not follow naming conventions: " + <<"Only chararacters [a-z0-9_] are allowed."<<std::endl; + return false; + } + + bool success = false; + + try{ + success = loadScript(scriptpath); + } + catch(LuaError &e){ + errorstream<<"Error loading mod \""<<modname + <<"\": "<<e.what()<<std::endl; + } + + return success; +} + +bool ScriptApiBase::loadScript(const std::string &scriptpath) +{ + verbosestream<<"Loading and running script from "<<scriptpath<<std::endl; + + lua_State *L = getStack(); + + lua_pushcfunction(L, loadScript_ErrorHandler); + int errorhandler = lua_gettop(L); + + int ret = luaL_loadfile(L, scriptpath.c_str()) || lua_pcall(L, 0, 0, errorhandler); + if(ret){ + errorstream<<"========== ERROR FROM LUA ==========="<<std::endl; + errorstream<<"Failed to load and run script from "<<std::endl; + errorstream<<scriptpath<<":"<<std::endl; + errorstream<<std::endl; + errorstream<<lua_tostring(L, -1)<<std::endl; + errorstream<<std::endl; + errorstream<<"=======END OF ERROR FROM LUA ========"<<std::endl; + lua_pop(L, 1); // Pop error message from stack + lua_pop(L, 1); // Pop the error handler from stack + return false; + } + lua_pop(L, 1); // Pop the error handler from stack + return true; +} void ScriptApiBase::realityCheck() { @@ -52,7 +163,7 @@ void ScriptApiBase::realityCheck() } } -void ScriptApiBase::scriptError(const char *fmt, ...) +void ScriptApiBase::scriptError(const char *fmt, ...) { va_list argp; va_start(argp, fmt); @@ -65,130 +176,34 @@ void ScriptApiBase::scriptError(const char *fmt, ...) void ScriptApiBase::stackDump(std::ostream &o) { - int i; - int top = lua_gettop(m_luastack); - for (i = 1; i <= top; i++) { /* repeat for each level */ - int t = lua_type(m_luastack, i); - switch (t) { - - case LUA_TSTRING: /* strings */ - o<<"\""<<lua_tostring(m_luastack, i)<<"\""; - break; - - case LUA_TBOOLEAN: /* booleans */ - o<<(lua_toboolean(m_luastack, i) ? "true" : "false"); - break; - - case LUA_TNUMBER: /* numbers */ { - char buf[10]; - snprintf(buf, 10, "%g", lua_tonumber(m_luastack, i)); - o<<buf; - break; } - - default: /* other values */ - o<<lua_typename(m_luastack, t); - break; - - } - o<<" "; - } - o<<std::endl; -} - -// Push the list of callbacks (a lua table). -// Then push nargs arguments. -// Then call this function, which -// - runs the callbacks -// - removes the table and arguments from the lua stack -// - pushes the return value, computed depending on mode -void ScriptApiBase::runCallbacks(int nargs,RunCallbacksMode mode) -{ - lua_State *L = getStack(); - - // Insert the return value into the lua stack, below the table - assert(lua_gettop(L) >= nargs + 1); - lua_pushnil(L); - lua_insert(L, -(nargs + 1) - 1); - // Stack now looks like this: - // ... <return value = nil> <table> <arg#1> <arg#2> ... <arg#n> + int i; + int top = lua_gettop(m_luastack); + for (i = 1; i <= top; i++) { /* repeat for each level */ + int t = lua_type(m_luastack, i); + switch (t) { - int rv = lua_gettop(L) - nargs - 1; - int table = rv + 1; - int arg = table + 1; + case LUA_TSTRING: /* strings */ + o<<"\""<<lua_tostring(m_luastack, i)<<"\""; + break; - luaL_checktype(L, table, LUA_TTABLE); + case LUA_TBOOLEAN: /* booleans */ + o<<(lua_toboolean(m_luastack, i) ? "true" : "false"); + break; - // Foreach - lua_pushnil(L); - bool first_loop = true; - while(lua_next(L, table) != 0){ - // key at index -2 and value at index -1 - luaL_checktype(L, -1, LUA_TFUNCTION); - // Call function - for(int i = 0; i < nargs; i++) - lua_pushvalue(L, arg+i); - if(lua_pcall(L, nargs, 1, 0)) - scriptError("error: %s", lua_tostring(L, -1)); - - // Move return value to designated space in stack - // Or pop it - if(first_loop){ - // Result of first callback is always moved - lua_replace(L, rv); - first_loop = false; - } else { - // Otherwise, what happens depends on the mode - if(mode == RUN_CALLBACKS_MODE_FIRST) - lua_pop(L, 1); - else if(mode == RUN_CALLBACKS_MODE_LAST) - lua_replace(L, rv); - else if(mode == RUN_CALLBACKS_MODE_AND || - mode == RUN_CALLBACKS_MODE_AND_SC){ - if((bool)lua_toboolean(L, rv) == true && - (bool)lua_toboolean(L, -1) == false) - lua_replace(L, rv); - else - lua_pop(L, 1); - } - else if(mode == RUN_CALLBACKS_MODE_OR || - mode == RUN_CALLBACKS_MODE_OR_SC){ - if((bool)lua_toboolean(L, rv) == false && - (bool)lua_toboolean(L, -1) == true) - lua_replace(L, rv); - else - lua_pop(L, 1); - } - else - assert(0); - } + case LUA_TNUMBER: /* numbers */ { + char buf[10]; + snprintf(buf, 10, "%g", lua_tonumber(m_luastack, i)); + o<<buf; + break; } - // Handle short circuit modes - if(mode == RUN_CALLBACKS_MODE_AND_SC && - (bool)lua_toboolean(L, rv) == false) - break; - else if(mode == RUN_CALLBACKS_MODE_OR_SC && - (bool)lua_toboolean(L, rv) == true) - break; + default: /* other values */ + o<<lua_typename(m_luastack, t); + break; - // value removed, keep key for next iteration - } - - // Remove stuff from stack, leaving only the return value - lua_settop(L, rv); - - // Fix return value in case no callbacks were called - if(first_loop){ - if(mode == RUN_CALLBACKS_MODE_AND || - mode == RUN_CALLBACKS_MODE_AND_SC){ - lua_pop(L, 1); - lua_pushboolean(L, true); - } - else if(mode == RUN_CALLBACKS_MODE_OR || - mode == RUN_CALLBACKS_MODE_OR_SC){ - lua_pop(L, 1); - lua_pushboolean(L, false); } + o<<" "; } + o<<std::endl; } void ScriptApiBase::addObjectReference(ServerActiveObject *cobj) diff --git a/src/script/cpp_api/s_base.h b/src/script/cpp_api/s_base.h index 8799d3c00..3cb59634b 100644 --- a/src/script/cpp_api/s_base.h +++ b/src/script/cpp_api/s_base.h @@ -21,67 +21,37 @@ with this program; if not, write to the Free Software Foundation, Inc., #define S_BASE_H_ #include <iostream> +#include <string> + +extern "C" { +#include <lua.h> +} #include "irrlichttypes.h" #include "jmutex.h" #include "jmutexautolock.h" #include "common/c_types.h" -#include "debug.h" -#define LOCK_DEBUG +#define SCRIPTAPI_LOCK_DEBUG class Server; class Environment; +class GUIEngine; class ServerActiveObject; -class LuaABM; -class InvRef; -class ModApiBase; -class ModApiEnvMod; -class ObjectRef; -class NodeMetaRef; - - -/* definitions */ -// What scriptapi_run_callbacks does with the return values of callbacks. -// Regardless of the mode, if only one callback is defined, -// its return value is the total return value. -// Modes only affect the case where 0 or >= 2 callbacks are defined. -enum RunCallbacksMode -{ - // Returns the return value of the first callback - // Returns nil if list of callbacks is empty - RUN_CALLBACKS_MODE_FIRST, - // Returns the return value of the last callback - // Returns nil if list of callbacks is empty - RUN_CALLBACKS_MODE_LAST, - // If any callback returns a false value, the first such is returned - // Otherwise, the first callback's return value (trueish) is returned - // Returns true if list of callbacks is empty - RUN_CALLBACKS_MODE_AND, - // Like above, but stops calling callbacks (short circuit) - // after seeing the first false value - RUN_CALLBACKS_MODE_AND_SC, - // If any callback returns a true value, the first such is returned - // Otherwise, the first callback's return value (falseish) is returned - // Returns false if list of callbacks is empty - RUN_CALLBACKS_MODE_OR, - // Like above, but stops calling callbacks (short circuit) - // after seeing the first true value - RUN_CALLBACKS_MODE_OR_SC, - // Note: "a true value" and "a false value" refer to values that - // are converted by lua_toboolean to true or false, respectively. -}; - class ScriptApiBase { public: + ScriptApiBase(); + virtual ~ScriptApiBase(); + + bool loadMod(const std::string &scriptpath, const std::string &modname); + bool loadScript(const std::string &scriptpath); + /* object */ void addObjectReference(ServerActiveObject *cobj); void removeObjectReference(ServerActiveObject *cobj); - ScriptApiBase(); - protected: friend class LuaABM; friend class InvRef; @@ -91,78 +61,35 @@ protected: friend class ModApiEnvMod; friend class LuaVoxelManip; - - inline lua_State* getStack() + lua_State* getStack() { return m_luastack; } - bool setStack(lua_State* stack) { - if (m_luastack == 0) { - m_luastack = stack; - return true; - } - return false; - } - void realityCheck(); void scriptError(const char *fmt, ...); void stackDump(std::ostream &o); - void runCallbacks(int nargs,RunCallbacksMode mode); - inline Server* getServer() { return m_server; } + Server* getServer() { return m_server; } void setServer(Server* server) { m_server = server; } Environment* getEnv() { return m_environment; } void setEnv(Environment* env) { m_environment = env; } + GUIEngine* getGuiEngine() { return m_guiengine; } + void setGuiEngine(GUIEngine* guiengine) { m_guiengine = guiengine; } + void objectrefGetOrCreate(ServerActiveObject *cobj); void objectrefGet(u16 id); - JMutex m_luastackmutex; -#ifdef LOCK_DEBUG + JMutex m_luastackmutex; +#ifdef SCRIPTAPI_LOCK_DEBUG bool m_locked; #endif private: lua_State* m_luastack; - Server* m_server; - Environment* m_environment; - - -}; - -#ifdef LOCK_DEBUG -class LockChecker { -public: - LockChecker(bool* variable) { - assert(*variable == false); - - m_variable = variable; - *m_variable = true; - } - ~LockChecker() { - *m_variable = false; - } -private: -bool* m_variable; + Server* m_server; + Environment* m_environment; + GUIEngine* m_guiengine; }; -#define LOCK_CHECK LockChecker(&(this->m_locked)) -#else -#define LOCK_CHECK while(0) -#endif - -#define LUA_STACK_AUTOLOCK JMutexAutoLock(this->m_luastackmutex) - -#define SCRIPTAPI_PRECHECKHEADER \ - LUA_STACK_AUTOLOCK; \ - LOCK_CHECK; \ - realityCheck(); \ - lua_State *L = getStack(); \ - assert(lua_checkstack(L, 20)); \ - StackUnroller stack_unroller(L); - -#define PLAYER_TO_SA(p) p->getEnv()->getScriptIface() -#define ENV_TO_SA(env) env->getScriptIface() -#define SERVER_TO_SA(srv) srv->getScriptIface() - #endif /* S_BASE_H_ */ diff --git a/src/script/cpp_api/s_entity.cpp b/src/script/cpp_api/s_entity.cpp index c494e8232..cefa27cb1 100644 --- a/src/script/cpp_api/s_entity.cpp +++ b/src/script/cpp_api/s_entity.cpp @@ -18,15 +18,12 @@ with this program; if not, write to the Free Software Foundation, Inc., */ #include "cpp_api/s_entity.h" +#include "cpp_api/s_internal.h" #include "log.h" #include "object_properties.h" #include "common/c_converter.h" #include "common/c_content.h" -extern "C" { -#include "lauxlib.h" -} - bool ScriptApiEntity::luaentity_Add(u16 id, const char *name) { SCRIPTAPI_PRECHECKHEADER diff --git a/src/script/cpp_api/s_env.cpp b/src/script/cpp_api/s_env.cpp index 632b28f45..ef3a1dddf 100644 --- a/src/script/cpp_api/s_env.cpp +++ b/src/script/cpp_api/s_env.cpp @@ -18,16 +18,13 @@ with this program; if not, write to the Free Software Foundation, Inc., */ #include "cpp_api/s_env.h" +#include "cpp_api/s_internal.h" #include "common/c_converter.h" #include "log.h" #include "environment.h" #include "mapgen.h" #include "lua_api/l_env.h" -extern "C" { -#include "lauxlib.h" -} - void ScriptApiEnv::environment_OnGenerated(v3s16 minp, v3s16 maxp, u32 blockseed) { @@ -40,7 +37,7 @@ void ScriptApiEnv::environment_OnGenerated(v3s16 minp, v3s16 maxp, push_v3s16(L, minp); push_v3s16(L, maxp); lua_pushnumber(L, blockseed); - runCallbacks(3, RUN_CALLBACKS_MODE_FIRST); + script_run_callbacks(L, 3, RUN_CALLBACKS_MODE_FIRST); } void ScriptApiEnv::environment_Step(float dtime) @@ -53,7 +50,7 @@ void ScriptApiEnv::environment_Step(float dtime) lua_getfield(L, -1, "registered_globalsteps"); // Call callbacks lua_pushnumber(L, dtime); - runCallbacks(1, RUN_CALLBACKS_MODE_FIRST); + script_run_callbacks(L, 1, RUN_CALLBACKS_MODE_FIRST); } void ScriptApiEnv::environment_OnMapgenInit(MapgenParams *mgparams) @@ -80,7 +77,7 @@ void ScriptApiEnv::environment_OnMapgenInit(MapgenParams *mgparams) lua_pushstring(L, flagstr.c_str()); lua_setfield(L, -2, "flags"); - runCallbacks(1, RUN_CALLBACKS_MODE_FIRST); + script_run_callbacks(L, 1, RUN_CALLBACKS_MODE_FIRST); } void ScriptApiEnv::initializeEnvironment(ServerEnvironment *env) diff --git a/src/script/cpp_api/s_internal.h b/src/script/cpp_api/s_internal.h new file mode 100644 index 000000000..10ee1a7de --- /dev/null +++ b/src/script/cpp_api/s_internal.h @@ -0,0 +1,63 @@ +/* +Minetest +Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com> + +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. +*/ + +/******************************************************************************/ +/******************************************************************************/ +/* WARNING!!!! do NOT add this header in any include file or any code file */ +/* not being a modapi file!!!!!!!! */ +/******************************************************************************/ +/******************************************************************************/ + +#ifndef S_INTERNAL_H_ +#define S_INTERNAL_H_ + +#include "common/c_internal.h" +#include "cpp_api/s_base.h" + +#ifdef SCRIPTAPI_LOCK_DEBUG +#include "debug.h" // assert() +class LockChecker { +public: + LockChecker(bool* variable) { + assert(*variable == false); + + m_variable = variable; + *m_variable = true; + } + ~LockChecker() { + *m_variable = false; + } +private: +bool* m_variable; +}; + +#define SCRIPTAPI_LOCK_CHECK LockChecker(&(this->m_locked)) +#else +#define SCRIPTAPI_LOCK_CHECK while(0) +#endif + +#define SCRIPTAPI_PRECHECKHEADER \ + JMutexAutoLock(this->m_luastackmutex); \ + SCRIPTAPI_LOCK_CHECK; \ + realityCheck(); \ + lua_State *L = getStack(); \ + assert(lua_checkstack(L, 20)); \ + StackUnroller stack_unroller(L); + +#endif /* S_INTERNAL_H_ */ diff --git a/src/script/cpp_api/s_inventory.cpp b/src/script/cpp_api/s_inventory.cpp index 2402d198c..09f26d80c 100644 --- a/src/script/cpp_api/s_inventory.cpp +++ b/src/script/cpp_api/s_inventory.cpp @@ -18,6 +18,7 @@ with this program; if not, write to the Free Software Foundation, Inc., */ #include "cpp_api/s_inventory.h" +#include "cpp_api/s_internal.h" #include "inventorymanager.h" #include "lua_api/l_inventory.h" #include "lua_api/l_item.h" diff --git a/src/script/cpp_api/s_item.cpp b/src/script/cpp_api/s_item.cpp index 6937ebbeb..b4536ac63 100644 --- a/src/script/cpp_api/s_item.cpp +++ b/src/script/cpp_api/s_item.cpp @@ -18,10 +18,13 @@ with this program; if not, write to the Free Software Foundation, Inc., */ #include "cpp_api/s_item.h" +#include "cpp_api/s_internal.h" #include "common/c_converter.h" #include "common/c_content.h" #include "lua_api/l_item.h" #include "server.h" +#include "log.h" +#include "util/pointedthing.h" bool ScriptApiItem::item_OnDrop(ItemStack &item, ServerActiveObject *dropper, v3f pos) diff --git a/src/script/cpp_api/s_mainmenu.cpp b/src/script/cpp_api/s_mainmenu.cpp new file mode 100644 index 000000000..af92c59a9 --- /dev/null +++ b/src/script/cpp_api/s_mainmenu.cpp @@ -0,0 +1,80 @@ +/* +Minetest +Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com> + +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 "cpp_api/s_mainmenu.h" +#include "cpp_api/s_internal.h" +#include "common/c_converter.h" + +void ScriptApiMainMenu::setMainMenuErrorMessage(std::string errormessage) +{ + SCRIPTAPI_PRECHECKHEADER + + lua_getglobal(L, "gamedata"); + int gamedata_idx = lua_gettop(L); + lua_pushstring(L, "errormessage"); + lua_pushstring(L, errormessage.c_str()); + lua_settable(L, gamedata_idx); + lua_pop(L, 1); +} + +void ScriptApiMainMenu::handleMainMenuEvent(std::string text) +{ + SCRIPTAPI_PRECHECKHEADER + + // Get handler function + lua_getglobal(L, "engine"); + lua_getfield(L, -1, "event_handler"); + if(lua_isnil(L, -1)) + return; + luaL_checktype(L, -1, LUA_TFUNCTION); + + // Call it + lua_pushstring(L, text.c_str()); + if(lua_pcall(L, 1, 0, 0)) + scriptError("error running function engine.event_handler: %s\n", + lua_tostring(L, -1)); +} + +void ScriptApiMainMenu::handleMainMenuButtons(std::map<std::string, std::string> fields) +{ + SCRIPTAPI_PRECHECKHEADER + + // Get handler function + lua_getglobal(L, "engine"); + lua_getfield(L, -1, "button_handler"); + if(lua_isnil(L, -1)) + return; + luaL_checktype(L, -1, LUA_TFUNCTION); + + // Convert fields to lua table + lua_newtable(L); + for(std::map<std::string, std::string>::const_iterator + i = fields.begin(); i != fields.end(); i++){ + const std::string &name = i->first; + const std::string &value = i->second; + lua_pushstring(L, name.c_str()); + lua_pushlstring(L, value.c_str(), value.size()); + lua_settable(L, -3); + } + + // Call it + if(lua_pcall(L, 1, 0, 0)) + scriptError("error running function engine.button_handler: %s\n", + lua_tostring(L, -1)); +} diff --git a/src/script/cpp_api/s_mainmenu.h b/src/script/cpp_api/s_mainmenu.h new file mode 100644 index 000000000..53dcd37e9 --- /dev/null +++ b/src/script/cpp_api/s_mainmenu.h @@ -0,0 +1,49 @@ +/* +Minetest +Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com> + +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 S_MAINMENU_H_ +#define S_MAINMENU_H_ + +#include "cpp_api/s_base.h" +#include <map> + +class ScriptApiMainMenu + : virtual public ScriptApiBase +{ +public: + /** + * set gamedata.errormessage to inform lua of an error + * @param errormessage the error message + */ + void setMainMenuErrorMessage(std::string errormessage); + + /** + * process events received from formspec + * @param text events in textual form + */ + void handleMainMenuEvent(std::string text); + + /** + * process field data recieved from formspec + * @param fields data in field format + */ + void handleMainMenuButtons(std::map<std::string, std::string> fields); +}; + +#endif /* S_MAINMENU_H_ */ diff --git a/src/script/cpp_api/s_node.cpp b/src/script/cpp_api/s_node.cpp index d0b0583c0..92fd00a74 100644 --- a/src/script/cpp_api/s_node.cpp +++ b/src/script/cpp_api/s_node.cpp @@ -18,10 +18,12 @@ with this program; if not, write to the Free Software Foundation, Inc., */ #include "cpp_api/s_node.h" +#include "cpp_api/s_internal.h" #include "common/c_converter.h" #include "common/c_content.h" #include "nodedef.h" #include "server.h" +#include "environment.h" struct EnumString ScriptApiNode::es_DrawType[] = diff --git a/src/script/cpp_api/s_nodemeta.cpp b/src/script/cpp_api/s_nodemeta.cpp index 56cea8e5f..e87464c61 100644 --- a/src/script/cpp_api/s_nodemeta.cpp +++ b/src/script/cpp_api/s_nodemeta.cpp @@ -18,16 +18,14 @@ with this program; if not, write to the Free Software Foundation, Inc., */ #include "cpp_api/s_nodemeta.h" +#include "cpp_api/s_internal.h" #include "common/c_converter.h" #include "nodedef.h" #include "mapnode.h" #include "server.h" +#include "environment.h" #include "lua_api/l_item.h" -extern "C" { -#include "lauxlib.h" -} - // Return number of accepted items to be moved int ScriptApiNodemeta::nodemeta_inventory_AllowMove(v3s16 p, const std::string &from_list, int from_index, diff --git a/src/script/cpp_api/s_player.cpp b/src/script/cpp_api/s_player.cpp index 0dbd52527..215a34d53 100644 --- a/src/script/cpp_api/s_player.cpp +++ b/src/script/cpp_api/s_player.cpp @@ -18,6 +18,7 @@ with this program; if not, write to the Free Software Foundation, Inc., */ #include "cpp_api/s_player.h" +#include "cpp_api/s_internal.h" void ScriptApiPlayer::on_newplayer(ServerActiveObject *player) { @@ -28,7 +29,7 @@ void ScriptApiPlayer::on_newplayer(ServerActiveObject *player) lua_getfield(L, -1, "registered_on_newplayers"); // Call callbacks objectrefGetOrCreate(player); - runCallbacks(1, RUN_CALLBACKS_MODE_FIRST); + script_run_callbacks(L, 1, RUN_CALLBACKS_MODE_FIRST); } void ScriptApiPlayer::on_dieplayer(ServerActiveObject *player) @@ -40,7 +41,7 @@ void ScriptApiPlayer::on_dieplayer(ServerActiveObject *player) lua_getfield(L, -1, "registered_on_dieplayers"); // Call callbacks objectrefGetOrCreate(player); - runCallbacks(1, RUN_CALLBACKS_MODE_FIRST); + script_run_callbacks(L, 1, RUN_CALLBACKS_MODE_FIRST); } bool ScriptApiPlayer::on_respawnplayer(ServerActiveObject *player) @@ -52,7 +53,7 @@ bool ScriptApiPlayer::on_respawnplayer(ServerActiveObject *player) lua_getfield(L, -1, "registered_on_respawnplayers"); // Call callbacks objectrefGetOrCreate(player); - runCallbacks(1, RUN_CALLBACKS_MODE_OR); + script_run_callbacks(L, 1, RUN_CALLBACKS_MODE_OR); bool positioning_handled_by_some = lua_toboolean(L, -1); return positioning_handled_by_some; } @@ -66,7 +67,7 @@ void ScriptApiPlayer::on_joinplayer(ServerActiveObject *player) lua_getfield(L, -1, "registered_on_joinplayers"); // Call callbacks objectrefGetOrCreate(player); - runCallbacks(1, RUN_CALLBACKS_MODE_FIRST); + script_run_callbacks(L, 1, RUN_CALLBACKS_MODE_FIRST); } void ScriptApiPlayer::on_leaveplayer(ServerActiveObject *player) @@ -78,7 +79,7 @@ void ScriptApiPlayer::on_leaveplayer(ServerActiveObject *player) lua_getfield(L, -1, "registered_on_leaveplayers"); // Call callbacks objectrefGetOrCreate(player); - runCallbacks(1, RUN_CALLBACKS_MODE_FIRST); + script_run_callbacks(L, 1, RUN_CALLBACKS_MODE_FIRST); } void ScriptApiPlayer::on_cheat(ServerActiveObject *player, @@ -94,7 +95,7 @@ void ScriptApiPlayer::on_cheat(ServerActiveObject *player, lua_newtable(L); lua_pushlstring(L, cheat_type.c_str(), cheat_type.size()); lua_setfield(L, -2, "type"); - runCallbacks(2, RUN_CALLBACKS_MODE_FIRST); + script_run_callbacks(L, 2, RUN_CALLBACKS_MODE_FIRST); } void ScriptApiPlayer::on_playerReceiveFields(ServerActiveObject *player, @@ -121,7 +122,7 @@ void ScriptApiPlayer::on_playerReceiveFields(ServerActiveObject *player, lua_pushlstring(L, value.c_str(), value.size()); lua_settable(L, -3); } - runCallbacks(3, RUN_CALLBACKS_MODE_OR_SC); + script_run_callbacks(L, 3, RUN_CALLBACKS_MODE_OR_SC); } ScriptApiPlayer::~ScriptApiPlayer() { } diff --git a/src/script/cpp_api/s_player.h b/src/script/cpp_api/s_player.h index c0409a481..88221f486 100644 --- a/src/script/cpp_api/s_player.h +++ b/src/script/cpp_api/s_player.h @@ -20,6 +20,8 @@ with this program; if not, write to the Free Software Foundation, Inc., #ifndef S_PLAYER_H_ #define S_PLAYER_H_ +#include <map> + #include "cpp_api/s_base.h" diff --git a/src/script/cpp_api/s_server.cpp b/src/script/cpp_api/s_server.cpp new file mode 100644 index 000000000..d41805b7b --- /dev/null +++ b/src/script/cpp_api/s_server.cpp @@ -0,0 +1,151 @@ +/* +Minetest +Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com> + +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 "cpp_api/s_server.h" +#include "cpp_api/s_internal.h" +#include "common/c_converter.h" + +bool ScriptApiServer::getAuth(const std::string &playername, + std::string *dst_password, + std::set<std::string> *dst_privs) +{ + SCRIPTAPI_PRECHECKHEADER + + getAuthHandler(); + lua_getfield(L, -1, "get_auth"); + if(lua_type(L, -1) != LUA_TFUNCTION) + throw LuaError(L, "Authentication handler missing get_auth"); + lua_pushstring(L, playername.c_str()); + if(lua_pcall(L, 1, 1, 0)) + scriptError("error: %s", lua_tostring(L, -1)); + + // nil = login not allowed + if(lua_isnil(L, -1)) + return false; + luaL_checktype(L, -1, LUA_TTABLE); + + std::string password; + bool found = getstringfield(L, -1, "password", password); + if(!found) + throw LuaError(L, "Authentication handler didn't return password"); + if(dst_password) + *dst_password = password; + + lua_getfield(L, -1, "privileges"); + if(!lua_istable(L, -1)) + throw LuaError(L, + "Authentication handler didn't return privilege table"); + if(dst_privs) + readPrivileges(-1, *dst_privs); + lua_pop(L, 1); + + return true; +} + +void ScriptApiServer::getAuthHandler() +{ + lua_State *L = getStack(); + + lua_getglobal(L, "minetest"); + lua_getfield(L, -1, "registered_auth_handler"); + if(lua_isnil(L, -1)){ + lua_pop(L, 1); + lua_getfield(L, -1, "builtin_auth_handler"); + } + if(lua_type(L, -1) != LUA_TTABLE) + throw LuaError(L, "Authentication handler table not valid"); +} + +void ScriptApiServer::readPrivileges(int index, std::set<std::string> &result) +{ + lua_State *L = getStack(); + + result.clear(); + lua_pushnil(L); + if(index < 0) + index -= 1; + while(lua_next(L, index) != 0){ + // key at index -2 and value at index -1 + std::string key = luaL_checkstring(L, -2); + bool value = lua_toboolean(L, -1); + if(value) + result.insert(key); + // removes value, keeps key for next iteration + lua_pop(L, 1); + } +} + +void ScriptApiServer::createAuth(const std::string &playername, + const std::string &password) +{ + SCRIPTAPI_PRECHECKHEADER + + getAuthHandler(); + lua_getfield(L, -1, "create_auth"); + if(lua_type(L, -1) != LUA_TFUNCTION) + throw LuaError(L, "Authentication handler missing create_auth"); + lua_pushstring(L, playername.c_str()); + lua_pushstring(L, password.c_str()); + if(lua_pcall(L, 2, 0, 0)) + scriptError("error: %s", lua_tostring(L, -1)); +} + +bool ScriptApiServer::setPassword(const std::string &playername, + const std::string &password) +{ + SCRIPTAPI_PRECHECKHEADER + + getAuthHandler(); + lua_getfield(L, -1, "set_password"); + if(lua_type(L, -1) != LUA_TFUNCTION) + throw LuaError(L, "Authentication handler missing set_password"); + lua_pushstring(L, playername.c_str()); + lua_pushstring(L, password.c_str()); + if(lua_pcall(L, 2, 1, 0)) + scriptError("error: %s", lua_tostring(L, -1)); + return lua_toboolean(L, -1); +} + +bool ScriptApiServer::on_chat_message(const std::string &name, + const std::string &message) +{ + SCRIPTAPI_PRECHECKHEADER + + // Get minetest.registered_on_chat_messages + lua_getglobal(L, "minetest"); + lua_getfield(L, -1, "registered_on_chat_messages"); + // Call callbacks + lua_pushstring(L, name.c_str()); + lua_pushstring(L, message.c_str()); + script_run_callbacks(L, 2, RUN_CALLBACKS_MODE_OR_SC); + bool ate = lua_toboolean(L, -1); + return ate; +} + +void ScriptApiServer::on_shutdown() +{ + SCRIPTAPI_PRECHECKHEADER + + // Get registered shutdown hooks + lua_getglobal(L, "minetest"); + lua_getfield(L, -1, "registered_on_shutdown"); + // Call callbacks + script_run_callbacks(L, 0, RUN_CALLBACKS_MODE_FIRST); +} + diff --git a/src/script/cpp_api/s_server.h b/src/script/cpp_api/s_server.h new file mode 100644 index 000000000..a63e36320 --- /dev/null +++ b/src/script/cpp_api/s_server.h @@ -0,0 +1,52 @@ +/* +Minetest +Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com> + +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 S_SERVER_H_ +#define S_SERVER_H_ + +#include "cpp_api/s_base.h" +#include <set> + +class ScriptApiServer + : virtual public ScriptApiBase +{ +public: + // Calls on_chat_message handlers + // Returns true if script handled message + bool on_chat_message(const std::string &name, const std::string &message); + + // Calls on_shutdown handlers + void on_shutdown(); + + /* auth */ + bool getAuth(const std::string &playername, + std::string *dst_password, + std::set<std::string> *dst_privs); + void createAuth(const std::string &playername, + const std::string &password); + bool setPassword(const std::string &playername, + const std::string &password); +private: + void getAuthHandler(); + void readPrivileges(int index, std::set<std::string> &result); +}; + + + +#endif /* S_SERVER_H_ */ diff --git a/src/script/cpp_api/scriptapi.cpp b/src/script/cpp_api/scriptapi.cpp deleted file mode 100644 index b6d376b1f..000000000 --- a/src/script/cpp_api/scriptapi.cpp +++ /dev/null @@ -1,291 +0,0 @@ -/* -Minetest -Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com> - -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. -*/ - -extern "C" { -#include "lua.h" -#include "lauxlib.h" -#include "lualib.h" -} - - -#include "scriptapi.h" -#include "common/c_converter.h" -#include "lua_api/l_base.h" -#include "log.h" -#include "mods.h" - -int script_ErrorHandler(lua_State *L) { - lua_getfield(L, LUA_GLOBALSINDEX, "debug"); - if (!lua_istable(L, -1)) { - lua_pop(L, 1); - return 1; - } - lua_getfield(L, -1, "traceback"); - if (!lua_isfunction(L, -1)) { - lua_pop(L, 2); - return 1; - } - lua_pushvalue(L, 1); - lua_pushinteger(L, 2); - lua_call(L, 2, 1); - return 1; -} - - -bool ScriptApi::getAuth(const std::string &playername, - std::string *dst_password, std::set<std::string> *dst_privs) -{ - SCRIPTAPI_PRECHECKHEADER - - getAuthHandler(); - lua_getfield(L, -1, "get_auth"); - if(lua_type(L, -1) != LUA_TFUNCTION) - throw LuaError(L, "Authentication handler missing get_auth"); - lua_pushstring(L, playername.c_str()); - if(lua_pcall(L, 1, 1, 0)) - scriptError("error: %s", lua_tostring(L, -1)); - - // nil = login not allowed - if(lua_isnil(L, -1)) - return false; - luaL_checktype(L, -1, LUA_TTABLE); - - std::string password; - bool found = getstringfield(L, -1, "password", password); - if(!found) - throw LuaError(L, "Authentication handler didn't return password"); - if(dst_password) - *dst_password = password; - - lua_getfield(L, -1, "privileges"); - if(!lua_istable(L, -1)) - throw LuaError(L, - "Authentication handler didn't return privilege table"); - if(dst_privs) - readPrivileges(-1, *dst_privs); - lua_pop(L, 1); - - return true; -} - -void ScriptApi::getAuthHandler() -{ - lua_State *L = getStack(); - - lua_getglobal(L, "minetest"); - lua_getfield(L, -1, "registered_auth_handler"); - if(lua_isnil(L, -1)){ - lua_pop(L, 1); - lua_getfield(L, -1, "builtin_auth_handler"); - } - if(lua_type(L, -1) != LUA_TTABLE) - throw LuaError(L, "Authentication handler table not valid"); -} - -void ScriptApi::readPrivileges(int index,std::set<std::string> &result) -{ - lua_State *L = getStack(); - - result.clear(); - lua_pushnil(L); - if(index < 0) - index -= 1; - while(lua_next(L, index) != 0){ - // key at index -2 and value at index -1 - std::string key = luaL_checkstring(L, -2); - bool value = lua_toboolean(L, -1); - if(value) - result.insert(key); - // removes value, keeps key for next iteration - lua_pop(L, 1); - } -} - -void ScriptApi::createAuth(const std::string &playername, - const std::string &password) -{ - SCRIPTAPI_PRECHECKHEADER - - getAuthHandler(); - lua_getfield(L, -1, "create_auth"); - if(lua_type(L, -1) != LUA_TFUNCTION) - throw LuaError(L, "Authentication handler missing create_auth"); - lua_pushstring(L, playername.c_str()); - lua_pushstring(L, password.c_str()); - if(lua_pcall(L, 2, 0, 0)) - scriptError("error: %s", lua_tostring(L, -1)); -} - -bool ScriptApi::setPassword(const std::string &playername, - const std::string &password) -{ - SCRIPTAPI_PRECHECKHEADER - - getAuthHandler(); - lua_getfield(L, -1, "set_password"); - if(lua_type(L, -1) != LUA_TFUNCTION) - throw LuaError(L, "Authentication handler missing set_password"); - lua_pushstring(L, playername.c_str()); - lua_pushstring(L, password.c_str()); - if(lua_pcall(L, 2, 1, 0)) - scriptError("error: %s", lua_tostring(L, -1)); - return lua_toboolean(L, -1); -} - -bool ScriptApi::on_chat_message(const std::string &name, - const std::string &message) -{ - SCRIPTAPI_PRECHECKHEADER - - // Get minetest.registered_on_chat_messages - lua_getglobal(L, "minetest"); - lua_getfield(L, -1, "registered_on_chat_messages"); - // Call callbacks - lua_pushstring(L, name.c_str()); - lua_pushstring(L, message.c_str()); - runCallbacks(2, RUN_CALLBACKS_MODE_OR_SC); - bool ate = lua_toboolean(L, -1); - return ate; -} - -void ScriptApi::on_shutdown() -{ - SCRIPTAPI_PRECHECKHEADER - - // Get registered shutdown hooks - lua_getglobal(L, "minetest"); - lua_getfield(L, -1, "registered_on_shutdown"); - // Call callbacks - runCallbacks(0, RUN_CALLBACKS_MODE_FIRST); -} - -bool ScriptApi::loadMod(const std::string &scriptpath,const std::string &modname) -{ - ModNameStorer modnamestorer(getStack(), modname); - - if(!string_allowed(modname, MODNAME_ALLOWED_CHARS)){ - errorstream<<"Error loading mod \""<<modname - <<"\": modname does not follow naming conventions: " - <<"Only chararacters [a-z0-9_] are allowed."<<std::endl; - return false; - } - - bool success = false; - - try{ - success = scriptLoad(scriptpath.c_str()); - } - catch(LuaError &e){ - errorstream<<"Error loading mod \""<<modname - <<"\": "<<e.what()<<std::endl; - } - - return success; -} - -ScriptApi::ScriptApi() { - assert("Invalid call to default constructor of scriptapi!" == 0); -} - -ScriptApi::ScriptApi(Server* server) -{ - - setServer(server); - setStack(luaL_newstate()); - assert(getStack()); - - //TODO add security - - luaL_openlibs(getStack()); - - SCRIPTAPI_PRECHECKHEADER - - lua_pushlightuserdata(L, this); - lua_setfield(L, LUA_REGISTRYINDEX, "scriptapi"); - - lua_newtable(L); - lua_setglobal(L, "minetest"); - - - for (std::vector<ModApiBase*>::iterator i = m_mod_api_modules->begin(); - i != m_mod_api_modules->end(); i++) { - //initializers are called within minetest global table! - lua_getglobal(L, "minetest"); - int top = lua_gettop(L); - bool ModInitializedSuccessfull = (*i)->Initialize(L,top); - assert(ModInitializedSuccessfull); - } - - infostream << "SCRIPTAPI: initialized " << m_mod_api_modules->size() - << " modules" << std::endl; - - // Get the main minetest table - lua_getglobal(L, "minetest"); - - // Add tables to minetest - lua_newtable(L); - lua_setfield(L, -2, "object_refs"); - - lua_newtable(L); - lua_setfield(L, -2, "luaentities"); -} - -ScriptApi::~ScriptApi() { - lua_close(getStack()); -} - -bool ScriptApi::scriptLoad(const char *path) -{ - lua_State* L = getStack(); - setStack(0); - - verbosestream<<"Loading and running script from "<<path<<std::endl; - - lua_pushcfunction(L, script_ErrorHandler); - int errorhandler = lua_gettop(L); - - int ret = luaL_loadfile(L, path) || lua_pcall(L, 0, 0, errorhandler); - if(ret){ - errorstream<<"========== ERROR FROM LUA ==========="<<std::endl; - errorstream<<"Failed to load and run script from "<<std::endl; - errorstream<<path<<":"<<std::endl; - errorstream<<std::endl; - errorstream<<lua_tostring(L, -1)<<std::endl; - errorstream<<std::endl; - errorstream<<"=======END OF ERROR FROM LUA ========"<<std::endl; - lua_pop(L, 1); // Pop error message from stack - lua_pop(L, 1); // Pop the error handler from stack - return false; - } - lua_pop(L, 1); // Pop the error handler from stack - return true; -} - -bool ScriptApi::registerModApiModule(ModApiBase* ptr) { - if (ScriptApi::m_mod_api_modules == 0) - ScriptApi::m_mod_api_modules = new std::vector<ModApiBase*>(); - - assert(ScriptApi::m_mod_api_modules != 0); - - ScriptApi::m_mod_api_modules->push_back(ptr); - - return true; -} - -std::vector<ModApiBase*>* ScriptApi::m_mod_api_modules = 0; diff --git a/src/script/lua_api/CMakeLists.txt b/src/script/lua_api/CMakeLists.txt index f67cf6886..d75c04335 100644 --- a/src/script/lua_api/CMakeLists.txt +++ b/src/script/lua_api/CMakeLists.txt @@ -1,14 +1,23 @@ -set(SCRIPT_LUA_API_SRCS +# Used by server and client +set(common_SCRIPT_LUA_API_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/l_base.cpp ${CMAKE_CURRENT_SOURCE_DIR}/l_craft.cpp ${CMAKE_CURRENT_SOURCE_DIR}/l_env.cpp ${CMAKE_CURRENT_SOURCE_DIR}/l_inventory.cpp ${CMAKE_CURRENT_SOURCE_DIR}/l_item.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/luaapi.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/l_mapgen.cpp ${CMAKE_CURRENT_SOURCE_DIR}/l_nodemeta.cpp ${CMAKE_CURRENT_SOURCE_DIR}/l_nodetimer.cpp ${CMAKE_CURRENT_SOURCE_DIR}/l_noise.cpp ${CMAKE_CURRENT_SOURCE_DIR}/l_object.cpp ${CMAKE_CURRENT_SOURCE_DIR}/l_particles.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/l_rollback.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/l_server.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/l_util.cpp ${CMAKE_CURRENT_SOURCE_DIR}/l_vmanip.cpp PARENT_SCOPE) + +# Used by client only +set(minetest_SCRIPT_LUA_API_SRCS + ${CMAKE_CURRENT_SOURCE_DIR}/l_mainmenu.cpp + PARENT_SCOPE) diff --git a/src/script/lua_api/l_base.cpp b/src/script/lua_api/l_base.cpp index b1766e6df..b8d673ee4 100644 --- a/src/script/lua_api/l_base.cpp +++ b/src/script/lua_api/l_base.cpp @@ -17,32 +17,35 @@ with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#include "cpp_api/scriptapi.h" #include "lua_api/l_base.h" -#include "common/c_internal.h" -#include "log.h" - -extern "C" { -#include "lua.h" +#include "lua_api/l_internal.h" +#include "cpp_api/s_base.h" + +ScriptApiBase* ModApiBase::getScriptApiBase(lua_State *L) { + // Get server from registry + lua_getfield(L, LUA_REGISTRYINDEX, "scriptapi"); + ScriptApiBase *sapi_ptr = (ScriptApiBase*) lua_touserdata(L, -1); + lua_pop(L, 1); + return sapi_ptr; } -ModApiBase::ModApiBase() { - ScriptApi::registerModApiModule(this); +Server* ModApiBase::getServer(lua_State *L) { + return getScriptApiBase(L)->getServer(); } -Server* ModApiBase::getServer(lua_State* L) { - return get_scriptapi(L)->getServer(); +Environment* ModApiBase::getEnv(lua_State *L) { + return getScriptApiBase(L)->getEnv(); } -Environment* ModApiBase::getEnv(lua_State* L) { - return get_scriptapi(L)->getEnv(); +GUIEngine* ModApiBase::getGuiEngine(lua_State *L) { + return getScriptApiBase(L)->getGuiEngine(); } -bool ModApiBase::registerFunction( lua_State* L, - const char* name, - lua_CFunction fct, - int top - ) { +bool ModApiBase::registerFunction(lua_State *L, + const char *name, + lua_CFunction fct, + int top + ) { //TODO check presence first! lua_pushstring(L,name); @@ -51,13 +54,3 @@ bool ModApiBase::registerFunction( lua_State* L, return true; } - -struct EnumString es_BiomeTerrainType[] = -{ - {BIOME_TERRAIN_NORMAL, "normal"}, - {BIOME_TERRAIN_LIQUID, "liquid"}, - {BIOME_TERRAIN_NETHER, "nether"}, - {BIOME_TERRAIN_AETHER, "aether"}, - {BIOME_TERRAIN_FLAT, "flat"}, - {0, NULL}, -}; diff --git a/src/script/lua_api/l_base.h b/src/script/lua_api/l_base.h index f2e0d59a9..71ebd215c 100644 --- a/src/script/lua_api/l_base.h +++ b/src/script/lua_api/l_base.h @@ -20,44 +20,43 @@ with this program; if not, write to the Free Software Foundation, Inc., #ifndef L_BASE_H_ #define L_BASE_H_ -#include "biome.h" #include "common/c_types.h" extern "C" { -#include "lua.h" +#include <lua.h> +#include <lauxlib.h> } -extern struct EnumString es_BiomeTerrainType[]; - -class ScriptApi; +class ScriptApiBase; class Server; class Environment; +class GUIEngine; -typedef class ModApiBase { - -public: - ModApiBase(); - - virtual bool Initialize(lua_State* L, int top) = 0; - virtual ~ModApiBase() {}; +class ModApiBase { protected: - static Server* getServer( lua_State* L); - static Environment* getEnv( lua_State* L); - static bool registerFunction( lua_State* L, - const char* name, - lua_CFunction fct, - int top - ); -} ModApiBase; - -#if (defined(WIN32) || defined(_WIN32_WCE)) -#define NO_MAP_LOCK_REQUIRED -#else -#include "main.h" -#include "profiler.h" -#define NO_MAP_LOCK_REQUIRED ScopeProfiler nolocktime(g_profiler,"Scriptapi: unlockable time",SPT_ADD) -//#define NO_ENVLOCK_REQUIRED assert(getServer(L).m_env_mutex.IsLocked() == false) -#endif + static ScriptApiBase* getScriptApiBase(lua_State *L); + static Server* getServer(lua_State *L); + static Environment* getEnv(lua_State *L); + static GUIEngine* getGuiEngine(lua_State *L); + + // Get an arbitrary subclass of ScriptApiBase + // by using dynamic_cast<> on getScriptApiBase() + template<typename T> + static T* getScriptApi(lua_State *L) { + ScriptApiBase *scriptIface = getScriptApiBase(L); + T *scriptIfaceDowncast = dynamic_cast<T*>(scriptIface); + if (!scriptIfaceDowncast) { + throw LuaError(L, "Requested unavailable ScriptApi - core engine bug!"); + } + return scriptIfaceDowncast; + } + + static bool registerFunction(lua_State *L, + const char* name, + lua_CFunction fct, + int top + ); +}; #endif /* L_BASE_H_ */ diff --git a/src/script/lua_api/l_craft.cpp b/src/script/lua_api/l_craft.cpp index a32fb9dff..b0a47bfc1 100644 --- a/src/script/lua_api/l_craft.cpp +++ b/src/script/lua_api/l_craft.cpp @@ -19,20 +19,12 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "lua_api/l_craft.h" -#include "common/c_internal.h" +#include "lua_api/l_internal.h" +#include "lua_api/l_item.h" #include "common/c_converter.h" #include "common/c_content.h" #include "server.h" -#include "lua_api/l_item.h" - -extern "C" { -#include "lauxlib.h" -} - -ModApiCraft::ModApiCraft() - : ModApiBase() { - -} +#include "craftdef.h" struct EnumString ModApiCraft::es_CraftMethod[] = { @@ -463,15 +455,10 @@ int ModApiCraft::l_get_all_craft_recipes(lua_State *L) return 1; } -bool ModApiCraft::Initialize(lua_State* L, int top) { - bool retval = true; - - retval &= API_FCT(get_all_craft_recipes); - retval &= API_FCT(get_craft_recipe); - retval &= API_FCT(get_craft_result); - retval &= API_FCT(register_craft); - - return retval; +void ModApiCraft::Initialize(lua_State *L, int top) +{ + API_FCT(get_all_craft_recipes); + API_FCT(get_craft_recipe); + API_FCT(get_craft_result); + API_FCT(register_craft); } - -ModApiCraft modapicraft_prototype; diff --git a/src/script/lua_api/l_craft.h b/src/script/lua_api/l_craft.h index d8319199d..548608776 100644 --- a/src/script/lua_api/l_craft.h +++ b/src/script/lua_api/l_craft.h @@ -20,19 +20,14 @@ with this program; if not, write to the Free Software Foundation, Inc., #ifndef L_CRAFT_H_ #define L_CRAFT_H_ +#include <string> #include <vector> -extern "C" { -#include <lua.h> -} - #include "lua_api/l_base.h" -#include "craftdef.h" + +struct CraftReplacements; class ModApiCraft : public ModApiBase { -public: - ModApiCraft(); - bool Initialize(lua_State* L, int top); private: static int l_register_craft(lua_State *L); static int l_get_craft_recipe(lua_State *L); @@ -47,6 +42,9 @@ private: int &width, std::vector<std::string> &recipe); static struct EnumString es_CraftMethod[]; + +public: + static void Initialize(lua_State *L, int top); }; #endif /* L_CRAFT_H_ */ diff --git a/src/script/lua_api/l_env.cpp b/src/script/lua_api/l_env.cpp index 47bc9baf7..dbaf6fb36 100644 --- a/src/script/lua_api/l_env.cpp +++ b/src/script/lua_api/l_env.cpp @@ -17,53 +17,39 @@ with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#include "cpp_api/scriptapi.h" -#include "lua_api/l_base.h" #include "lua_api/l_env.h" +#include "lua_api/l_internal.h" +#include "lua_api/l_nodemeta.h" +#include "lua_api/l_nodetimer.h" +#include "lua_api/l_noise.h" #include "lua_api/l_vmanip.h" +#include "common/c_converter.h" +#include "common/c_content.h" +#include "scripting_game.h" #include "environment.h" #include "server.h" +#include "nodedef.h" #include "daynightratio.h" #include "util/pointedthing.h" #include "content_sao.h" - -#include "common/c_converter.h" -#include "common/c_content.h" -#include "common/c_internal.h" -#include "lua_api/l_nodemeta.h" -#include "lua_api/l_nodetimer.h" -#include "lua_api/l_noise.h" #include "treegen.h" #include "pathfinder.h" -#include "emerge.h" -#include "mapgen_v7.h" #define GET_ENV_PTR ServerEnvironment* env = \ dynamic_cast<ServerEnvironment*>(getEnv(L)); \ if( env == NULL) return 0 -struct EnumString ModApiEnvMod::es_MapgenObject[] = -{ - {MGOBJ_VMANIP, "voxelmanip"}, - {MGOBJ_HEIGHTMAP, "heightmap"}, - {MGOBJ_BIOMEMAP, "biomemap"}, - {MGOBJ_HEATMAP, "heatmap"}, - {MGOBJ_HUMIDMAP, "humiditymap"}, - {0, NULL}, -}; - - /////////////////////////////////////////////////////////////////////////////// void LuaABM::trigger(ServerEnvironment *env, v3s16 p, MapNode n, u32 active_object_count, u32 active_object_count_wider) { - ScriptApi* scriptIface = SERVER_TO_SA(env); + GameScripting *scriptIface = env->getScriptIface(); scriptIface->realityCheck(); - lua_State* L = scriptIface->getStack(); + lua_State *L = scriptIface->getStack(); assert(lua_checkstack(L, 20)); StackUnroller stack_unroller(L); @@ -196,8 +182,13 @@ int ModApiEnvMod::l_place_node(lua_State *L) { GET_ENV_PTR; + ScriptApiItem *scriptIfaceItem = getScriptApi<ScriptApiItem>(L); + Server *server = getServer(L); + INodeDefManager *ndef = server->ndef(); + IItemDefManager *idef = server->idef(); + v3s16 pos = read_v3s16(L, 1); - MapNode n = readnode(L, 2, env->getGameDef()->ndef()); + MapNode n = readnode(L, 2, ndef); // Don't attempt to load non-loaded area as of now MapNode n_old = env->getMap().getNodeNoEx(pos); @@ -206,8 +197,6 @@ int ModApiEnvMod::l_place_node(lua_State *L) return 1; } // Create item to place - INodeDefManager *ndef = getServer(L)->ndef(); - IItemDefManager *idef = getServer(L)->idef(); ItemStack item(ndef->get(n).name, 1, 0, "", idef); // Make pointed position PointedThing pointed; @@ -216,7 +205,7 @@ int ModApiEnvMod::l_place_node(lua_State *L) pointed.node_undersurface = pos + v3s16(0,-1,0); // Place it with a NULL placer (appears in Lua as a non-functional // ObjectRef) - bool success = get_scriptapi(L)->item_OnPlace(item, NULL, pointed); + bool success = scriptIfaceItem->item_OnPlace(item, NULL, pointed); lua_pushboolean(L, success); return 1; } @@ -227,6 +216,8 @@ int ModApiEnvMod::l_dig_node(lua_State *L) { GET_ENV_PTR; + ScriptApiNode *scriptIfaceNode = getScriptApi<ScriptApiNode>(L); + v3s16 pos = read_v3s16(L, 1); // Don't attempt to load non-loaded area as of now @@ -237,7 +228,7 @@ int ModApiEnvMod::l_dig_node(lua_State *L) } // Dig it out with a NULL digger (appears in Lua as a // non-functional ObjectRef) - bool success = get_scriptapi(L)->node_on_dig(pos, n, NULL); + bool success = scriptIfaceNode->node_on_dig(pos, n, NULL); lua_pushboolean(L, success); return 1; } @@ -248,6 +239,8 @@ int ModApiEnvMod::l_punch_node(lua_State *L) { GET_ENV_PTR; + ScriptApiNode *scriptIfaceNode = getScriptApi<ScriptApiNode>(L); + v3s16 pos = read_v3s16(L, 1); // Don't attempt to load non-loaded area as of now @@ -258,7 +251,7 @@ int ModApiEnvMod::l_punch_node(lua_State *L) } // Punch it with a NULL puncher (appears in Lua as a non-functional // ObjectRef) - bool success = get_scriptapi(L)->node_on_punch(pos, n, NULL); + bool success = scriptIfaceNode->node_on_punch(pos, n, NULL); lua_pushboolean(L, success); return 1; } @@ -361,7 +354,7 @@ int ModApiEnvMod::l_add_entity(lua_State *L) if(objectid == 0) return 0; // Return ObjectRef - get_scriptapi(L)->objectrefGetOrCreate(obj); + getScriptApiBase(L)->objectrefGetOrCreate(obj); return 1; } @@ -420,7 +413,7 @@ int ModApiEnvMod::l_get_player_by_name(lua_State *L) return 1; } // Put player on stack - get_scriptapi(L)->objectrefGetOrCreate(sao); + getScriptApiBase(L)->objectrefGetOrCreate(sao); return 1; } @@ -446,7 +439,7 @@ int ModApiEnvMod::l_get_objects_inside_radius(lua_State *L) // Insert object reference into table lua_pushvalue(L, table_insert); lua_pushvalue(L, table); - get_scriptapi(L)->objectrefGetOrCreate(obj); + getScriptApiBase(L)->objectrefGetOrCreate(obj); if(lua_pcall(L, 2, 0, 0)) script_error(L, "error: %s", lua_tostring(L, -1)); } @@ -624,142 +617,6 @@ int ModApiEnvMod::l_get_voxel_manip(lua_State *L) return 1; } -// minetest.get_mapgen_object(objectname) -// returns the requested object used during map generation -int ModApiEnvMod::l_get_mapgen_object(lua_State *L) -{ - const char *mgobjstr = lua_tostring(L, 1); - - int mgobjint; - if (!string_to_enum(es_MapgenObject, mgobjint, mgobjstr ? mgobjstr : "")) - return 0; - - enum MapgenObject mgobj = (MapgenObject)mgobjint; - - EmergeManager *emerge = getServer(L)->getEmergeManager(); - Mapgen *mg = emerge->getCurrentMapgen(); - if (!mg) - return 0; - - size_t maplen = mg->csize.X * mg->csize.Z; - - int nargs = 1; - - switch (mgobj) { - case MGOBJ_VMANIP: { - ManualMapVoxelManipulator *vm = mg->vm; - - // VoxelManip object - LuaVoxelManip *o = new LuaVoxelManip(vm, true); - *(void **)(lua_newuserdata(L, sizeof(void *))) = o; - luaL_getmetatable(L, "VoxelManip"); - lua_setmetatable(L, -2); - - // emerged min pos - push_v3s16(L, vm->m_area.MinEdge); - - // emerged max pos - push_v3s16(L, vm->m_area.MaxEdge); - - nargs = 3; - - break; } - case MGOBJ_HEIGHTMAP: { - if (!mg->heightmap) - return 0; - - lua_newtable(L); - for (size_t i = 0; i != maplen; i++) { - lua_pushinteger(L, mg->heightmap[i]); - lua_rawseti(L, -2, i + 1); - } - break; } - case MGOBJ_BIOMEMAP: { - if (!mg->biomemap) - return 0; - - lua_newtable(L); - for (size_t i = 0; i != maplen; i++) { - lua_pushinteger(L, mg->biomemap[i]); - lua_rawseti(L, -2, i + 1); - } - break; } - case MGOBJ_HEATMAP: { // Mapgen V7 specific objects - case MGOBJ_HUMIDMAP: - if (strcmp(emerge->params->mg_name.c_str(), "v7")) - return 0; - - MapgenV7 *mgv7 = (MapgenV7 *)mg; - - float *arr = (mgobj == MGOBJ_HEATMAP) ? - mgv7->noise_heat->result : mgv7->noise_humidity->result; - if (!arr) - return 0; - - lua_newtable(L); - for (size_t i = 0; i != maplen; i++) { - lua_pushnumber(L, arr[i]); - lua_rawseti(L, -2, i + 1); - } - break; } - } - - return nargs; -} - -// minetest.set_mapgen_params(params) -// set mapgen parameters -int ModApiEnvMod::l_set_mapgen_params(lua_State *L) -{ - if (!lua_istable(L, 1)) - return 0; - - EmergeManager *emerge = getServer(L)->getEmergeManager(); - if (emerge->mapgen.size()) - return 0; - - MapgenParams *oparams = new MapgenParams; - u32 paramsmodified = 0; - u32 flagmask = 0; - - lua_getfield(L, 1, "mgname"); - if (lua_isstring(L, -1)) { - oparams->mg_name = std::string(lua_tostring(L, -1)); - paramsmodified |= MGPARAMS_SET_MGNAME; - } - - lua_getfield(L, 1, "seed"); - if (lua_isnumber(L, -1)) { - oparams->seed = lua_tointeger(L, -1); - paramsmodified |= MGPARAMS_SET_SEED; - } - - lua_getfield(L, 1, "water_level"); - if (lua_isnumber(L, -1)) { - oparams->water_level = lua_tointeger(L, -1); - paramsmodified |= MGPARAMS_SET_WATER_LEVEL; - } - - lua_getfield(L, 1, "flags"); - if (lua_isstring(L, -1)) { - std::string flagstr = std::string(lua_tostring(L, -1)); - oparams->flags = readFlagString(flagstr, flagdesc_mapgen); - paramsmodified |= MGPARAMS_SET_FLAGS; - - lua_getfield(L, 1, "flagmask"); - if (lua_isstring(L, -1)) { - flagstr = std::string(lua_tostring(L, -1)); - flagmask = readFlagString(flagstr, flagdesc_mapgen); - } - } - - emerge->luaoverride_params = oparams; - emerge->luaoverride_params_modified = paramsmodified; - emerge->luaoverride_flagmask = flagmask; - - return 0; -} - // minetest.clear_objects() // clear all objects in the environment int ModApiEnvMod::l_clear_objects(lua_State *L) @@ -913,48 +770,39 @@ int ModApiEnvMod::l_get_humidity(lua_State *L) } -bool ModApiEnvMod::Initialize(lua_State *L,int top) -{ - - bool retval = true; - - retval &= API_FCT(set_node); - retval &= API_FCT(add_node); - retval &= API_FCT(add_item); - retval &= API_FCT(remove_node); - retval &= API_FCT(get_node); - retval &= API_FCT(get_node_or_nil); - retval &= API_FCT(get_node_light); - retval &= API_FCT(place_node); - retval &= API_FCT(dig_node); - retval &= API_FCT(punch_node); - retval &= API_FCT(get_node_max_level); - retval &= API_FCT(get_node_level); - retval &= API_FCT(set_node_level); - retval &= API_FCT(add_node_level); - retval &= API_FCT(add_entity); - retval &= API_FCT(get_meta); - retval &= API_FCT(get_node_timer); - retval &= API_FCT(get_player_by_name); - retval &= API_FCT(get_objects_inside_radius); - retval &= API_FCT(set_timeofday); - retval &= API_FCT(get_timeofday); - retval &= API_FCT(find_node_near); - retval &= API_FCT(find_nodes_in_area); - retval &= API_FCT(get_perlin); - retval &= API_FCT(get_perlin_map); - retval &= API_FCT(get_voxel_manip); - retval &= API_FCT(get_mapgen_object); - retval &= API_FCT(set_mapgen_params); - retval &= API_FCT(clear_objects); - retval &= API_FCT(spawn_tree); - retval &= API_FCT(find_path); - retval &= API_FCT(line_of_sight); - retval &= API_FCT(transforming_liquid_add); - retval &= API_FCT(get_heat); - retval &= API_FCT(get_humidity); - - return retval; -} - -ModApiEnvMod modapienv_prototype; +void ModApiEnvMod::Initialize(lua_State *L, int top) +{ + API_FCT(set_node); + API_FCT(add_node); + API_FCT(add_item); + API_FCT(remove_node); + API_FCT(get_node); + API_FCT(get_node_or_nil); + API_FCT(get_node_light); + API_FCT(place_node); + API_FCT(dig_node); + API_FCT(punch_node); + API_FCT(get_node_max_level); + API_FCT(get_node_level); + API_FCT(set_node_level); + API_FCT(add_node_level); + API_FCT(add_entity); + API_FCT(get_meta); + API_FCT(get_node_timer); + API_FCT(get_player_by_name); + API_FCT(get_objects_inside_radius); + API_FCT(set_timeofday); + API_FCT(get_timeofday); + API_FCT(find_node_near); + API_FCT(find_nodes_in_area); + API_FCT(get_perlin); + API_FCT(get_perlin_map); + API_FCT(get_voxel_manip); + API_FCT(clear_objects); + API_FCT(spawn_tree); + API_FCT(find_path); + API_FCT(line_of_sight); + API_FCT(transforming_liquid_add); + API_FCT(get_heat); + API_FCT(get_humidity); +} diff --git a/src/script/lua_api/l_env.h b/src/script/lua_api/l_env.h index 4122fd037..adb80a8a8 100644 --- a/src/script/lua_api/l_env.h +++ b/src/script/lua_api/l_env.h @@ -20,17 +20,10 @@ with this program; if not, write to the Free Software Foundation, Inc., #ifndef L_ENV_H_ #define L_ENV_H_ -extern "C" { -#include <lua.h> -#include <lauxlib.h> -} - -#include "environment.h" #include "lua_api/l_base.h" +#include "environment.h" -class ModApiEnvMod - :public ModApiBase -{ +class ModApiEnvMod : public ModApiBase { private: // minetest.set_node(pos, node) // pos = {x=num, y=num, z=num} @@ -131,14 +124,6 @@ private: // returns world-specific voxel manipulator static int l_get_voxel_manip(lua_State *L); - // minetest.get_mapgen_object(objectname) - // returns the requested object used during map generation - static int l_get_mapgen_object(lua_State *L); - - // minetest.set_mapgen_params(params) - // set mapgen parameters - static int l_set_mapgen_params(lua_State *L); - // minetest.clear_objects() // clear all objects in the environment static int l_clear_objects(lua_State *L); @@ -159,10 +144,8 @@ private: static int l_get_heat(lua_State *L); static int l_get_humidity(lua_State *L); - static struct EnumString es_MapgenObject[]; - public: - bool Initialize(lua_State *L, int top); + static void Initialize(lua_State *L, int top); }; class LuaABM : public ActiveBlockModifier diff --git a/src/script/lua_api/l_internal.h b/src/script/lua_api/l_internal.h new file mode 100644 index 000000000..14215ee5d --- /dev/null +++ b/src/script/lua_api/l_internal.h @@ -0,0 +1,43 @@ +/* +Minetest +Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com> + +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. +*/ + +/******************************************************************************/ +/******************************************************************************/ +/* WARNING!!!! do NOT add this header in any include file or any code file */ +/* not being a modapi file!!!!!!!! */ +/******************************************************************************/ +/******************************************************************************/ + +#ifndef L_INTERNAL_H_ +#define L_INTERNAL_H_ + +#include "common/c_internal.h" + +#define luamethod(class, name) {#name, class::l_##name} +#define API_FCT(name) registerFunction(L,#name,l_##name,top) + +#if (defined(WIN32) || defined(_WIN32_WCE)) +#define NO_MAP_LOCK_REQUIRED +#else +#include "main.h" +#include "profiler.h" +#define NO_MAP_LOCK_REQUIRED ScopeProfiler nolocktime(g_profiler,"Scriptapi: unlockable time",SPT_ADD) +#endif + +#endif /* L_INTERNAL_H_ */ diff --git a/src/script/lua_api/l_inventory.cpp b/src/script/lua_api/l_inventory.cpp index f57a4e8cd..67b78bcaf 100644 --- a/src/script/lua_api/l_inventory.cpp +++ b/src/script/lua_api/l_inventory.cpp @@ -17,15 +17,13 @@ with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#include "cpp_api/scriptapi.h" -#include "common/c_converter.h" -#include "common/c_content.h" #include "lua_api/l_inventory.h" +#include "lua_api/l_internal.h" #include "lua_api/l_item.h" -#include "common/c_internal.h" +#include "common/c_converter.h" +#include "common/c_content.h" #include "server.h" -#include "log.h" -#include "inventorymanager.h" +#include "player.h" /* InvRef @@ -40,7 +38,7 @@ InvRef* InvRef::checkobject(lua_State *L, int narg) Inventory* InvRef::getinv(lua_State *L, InvRef *ref) { - return STACK_TO_SERVER(L)->getInventory(ref->m_loc); + return getServer(L)->getInventory(ref->m_loc); } InventoryList* InvRef::getlist(lua_State *L, InvRef *ref, @@ -56,7 +54,7 @@ InventoryList* InvRef::getlist(lua_State *L, InvRef *ref, void InvRef::reportInventoryChange(lua_State *L, InvRef *ref) { // Inform other things that the inventory has changed - STACK_TO_SERVER(L)->setInventoryModified(ref->m_loc); + getServer(L)->setInventoryModified(ref->m_loc); } // Exported functions @@ -182,7 +180,7 @@ int InvRef::l_set_stack(lua_State *L) InvRef *ref = checkobject(L, 1); const char *listname = luaL_checkstring(L, 2); int i = luaL_checknumber(L, 3) - 1; - ItemStack newitem = read_item(L, 4,STACK_TO_SERVER(L)); + ItemStack newitem = read_item(L, 4, getServer(L)); InventoryList *list = getlist(L, ref, listname); if(list != NULL && i >= 0 && i < (int) list->getSize()){ list->changeItem(i, newitem); @@ -202,7 +200,7 @@ int InvRef::l_get_list(lua_State *L) const char *listname = luaL_checkstring(L, 2); Inventory *inv = getinv(L, ref); if(inv){ - push_inventory_list(inv, listname, L); + push_inventory_list(L, inv, listname); } else { lua_pushnil(L); } @@ -221,10 +219,10 @@ int InvRef::l_set_list(lua_State *L) } InventoryList *list = inv->getList(listname); if(list) - read_inventory_list(inv, listname, L, 3, - STACK_TO_SERVER(L),list->getSize()); + read_inventory_list(L, 3, inv, listname, + getServer(L), list->getSize()); else - read_inventory_list(inv, listname, L, 3,STACK_TO_SERVER(L)); + read_inventory_list(L, 3, inv, listname, getServer(L)); reportInventoryChange(L, ref); return 0; } @@ -236,7 +234,7 @@ int InvRef::l_add_item(lua_State *L) NO_MAP_LOCK_REQUIRED; InvRef *ref = checkobject(L, 1); const char *listname = luaL_checkstring(L, 2); - ItemStack item = read_item(L, 3,STACK_TO_SERVER(L)); + ItemStack item = read_item(L, 3, getServer(L)); InventoryList *list = getlist(L, ref, listname); if(list){ ItemStack leftover = list->addItem(item); @@ -256,7 +254,7 @@ int InvRef::l_room_for_item(lua_State *L) NO_MAP_LOCK_REQUIRED; InvRef *ref = checkobject(L, 1); const char *listname = luaL_checkstring(L, 2); - ItemStack item = read_item(L, 3,STACK_TO_SERVER(L)); + ItemStack item = read_item(L, 3, getServer(L)); InventoryList *list = getlist(L, ref, listname); if(list){ lua_pushboolean(L, list->roomForItem(item)); @@ -273,7 +271,7 @@ int InvRef::l_contains_item(lua_State *L) NO_MAP_LOCK_REQUIRED; InvRef *ref = checkobject(L, 1); const char *listname = luaL_checkstring(L, 2); - ItemStack item = read_item(L, 3, STACK_TO_SERVER(L)); + ItemStack item = read_item(L, 3, getServer(L)); InventoryList *list = getlist(L, ref, listname); if(list){ lua_pushboolean(L, list->containsItem(item)); @@ -290,7 +288,7 @@ int InvRef::l_remove_item(lua_State *L) NO_MAP_LOCK_REQUIRED; InvRef *ref = checkobject(L, 1); const char *listname = luaL_checkstring(L, 2); - ItemStack item = read_item(L, 3,STACK_TO_SERVER(L)); + ItemStack item = read_item(L, 3, getServer(L)); InventoryList *list = getlist(L, ref, listname); if(list){ ItemStack removed = list->removeItem(item); @@ -473,20 +471,8 @@ int ModApiInventory::l_create_detached_inventory_raw(lua_State *L) return 1; } -bool ModApiInventory::Initialize(lua_State *L, int top) { - bool retval = true; - - retval &= API_FCT(create_detached_inventory_raw); - retval &= API_FCT(get_inventory); - - InvRef::Register(L); - - return retval; -} - -ModApiInventory::ModApiInventory() - : ModApiBase() { - +void ModApiInventory::Initialize(lua_State *L, int top) +{ + API_FCT(create_detached_inventory_raw); + API_FCT(get_inventory); } - -ModApiInventory modapiinventory_prototype; diff --git a/src/script/lua_api/l_inventory.h b/src/script/lua_api/l_inventory.h index 83e8039b8..ed3249e5f 100644 --- a/src/script/lua_api/l_inventory.h +++ b/src/script/lua_api/l_inventory.h @@ -20,23 +20,18 @@ with this program; if not, write to the Free Software Foundation, Inc., #ifndef L_INVENTORY_H_ #define L_INVENTORY_H_ -extern "C" { -#include <lua.h> -#include <lauxlib.h> -} +#include "lua_api/l_base.h" -#include "inventorymanager.h" -#include "player.h" -#include "serverobject.h" #include "inventory.h" +#include "inventorymanager.h" + +class Player; -#include "lua_api/l_base.h" /* InvRef */ -class InvRef -{ +class InvRef : public ModApiBase { private: InventoryLocation m_loc; @@ -116,22 +111,19 @@ public: static void Register(lua_State *L); }; -class ModApiInventory - : public ModApiBase -{ -public: - ModApiInventory(); - - bool Initialize(lua_State *L, int top); - +class ModApiInventory : public ModApiBase { +private: static int l_create_detached_inventory_raw(lua_State *L); + static int l_get_inventory(lua_State *L); -private: + static void inventory_set_list_from_lua(Inventory *inv, const char *name, lua_State *L, int tableindex, int forcesize); static void inventory_get_list_to_lua(Inventory *inv, const char *name, lua_State *L); +public: + static void Initialize(lua_State *L, int top); }; #endif /* L_INVENTORY_H_ */ diff --git a/src/script/lua_api/l_item.cpp b/src/script/lua_api/l_item.cpp index 6182c037b..a43b2858f 100644 --- a/src/script/lua_api/l_item.cpp +++ b/src/script/lua_api/l_item.cpp @@ -18,11 +18,16 @@ with this program; if not, write to the Free Software Foundation, Inc., */ #include "lua_api/l_item.h" +#include "lua_api/l_internal.h" #include "common/c_converter.h" #include "common/c_content.h" -#include "cpp_api/scriptapi.h" +#include "itemdef.h" +#include "nodedef.h" #include "server.h" -#include "common/c_internal.h" +#include "content_sao.h" +#include "inventory.h" +#include "log.h" + // garbage collector int LuaItemStack::gc_object(lua_State *L) @@ -97,7 +102,7 @@ int LuaItemStack::l_replace(lua_State *L) { NO_MAP_LOCK_REQUIRED; LuaItemStack *o = checkobject(L, 1); - o->m_stack = read_item(L,2,STACK_TO_SERVER(L)); + o->m_stack = read_item(L,2,getServer(L)); lua_pushboolean(L, true); return 1; } @@ -143,7 +148,7 @@ int LuaItemStack::l_get_stack_max(lua_State *L) NO_MAP_LOCK_REQUIRED; LuaItemStack *o = checkobject(L, 1); ItemStack &item = o->m_stack; - lua_pushinteger(L, item.getStackMax(STACK_TO_SERVER(L)->idef())); + lua_pushinteger(L, item.getStackMax(getServer(L)->idef())); return 1; } @@ -153,7 +158,7 @@ int LuaItemStack::l_get_free_space(lua_State *L) NO_MAP_LOCK_REQUIRED; LuaItemStack *o = checkobject(L, 1); ItemStack &item = o->m_stack; - lua_pushinteger(L, item.freeSpace(STACK_TO_SERVER(L)->idef())); + lua_pushinteger(L, item.freeSpace(getServer(L)->idef())); return 1; } @@ -164,7 +169,7 @@ int LuaItemStack::l_is_known(lua_State *L) NO_MAP_LOCK_REQUIRED; LuaItemStack *o = checkobject(L, 1); ItemStack &item = o->m_stack; - bool is_known = item.isKnown(STACK_TO_SERVER(L)->idef()); + bool is_known = item.isKnown(getServer(L)->idef()); lua_pushboolean(L, is_known); return 1; } @@ -200,7 +205,7 @@ int LuaItemStack::l_get_tool_capabilities(lua_State *L) LuaItemStack *o = checkobject(L, 1); ItemStack &item = o->m_stack; const ToolCapabilities &prop = - item.getToolCapabilities(STACK_TO_SERVER(L)->idef()); + item.getToolCapabilities(getServer(L)->idef()); push_tool_capabilities(L, prop); return 1; } @@ -215,7 +220,7 @@ int LuaItemStack::l_add_wear(lua_State *L) LuaItemStack *o = checkobject(L, 1); ItemStack &item = o->m_stack; int amount = lua_tointeger(L, 2); - bool result = item.addWear(amount, STACK_TO_SERVER(L)->idef()); + bool result = item.addWear(amount, getServer(L)->idef()); lua_pushboolean(L, result); return 1; } @@ -227,8 +232,8 @@ int LuaItemStack::l_add_item(lua_State *L) NO_MAP_LOCK_REQUIRED; LuaItemStack *o = checkobject(L, 1); ItemStack &item = o->m_stack; - ItemStack newitem = read_item(L,-1, STACK_TO_SERVER(L)); - ItemStack leftover = item.addItem(newitem, STACK_TO_SERVER(L)->idef()); + ItemStack newitem = read_item(L,-1, getServer(L)); + ItemStack leftover = item.addItem(newitem, getServer(L)->idef()); create(L, leftover); return 1; } @@ -241,9 +246,9 @@ int LuaItemStack::l_item_fits(lua_State *L) NO_MAP_LOCK_REQUIRED; LuaItemStack *o = checkobject(L, 1); ItemStack &item = o->m_stack; - ItemStack newitem = read_item(L, 2 ,STACK_TO_SERVER(L)); + ItemStack newitem = read_item(L, 2, getServer(L)); ItemStack restitem; - bool fits = item.itemFits(newitem, &restitem, STACK_TO_SERVER(L)->idef()); + bool fits = item.itemFits(newitem, &restitem, getServer(L)->idef()); lua_pushboolean(L, fits); // first return value create(L, restitem); // second return value return 2; @@ -300,7 +305,7 @@ ItemStack& LuaItemStack::getItem() int LuaItemStack::create_object(lua_State *L) { NO_MAP_LOCK_REQUIRED; - ItemStack item = read_item(L,1,STACK_TO_SERVER(L)); + ItemStack item = read_item(L, 1, getServer(L)); LuaItemStack *o = new LuaItemStack(item); *(void **)(lua_newuserdata(L, sizeof(void *))) = o; luaL_getmetatable(L, className); @@ -378,9 +383,6 @@ const luaL_reg LuaItemStack::methods[] = { {0,0} }; -ModApiItemMod::ModApiItemMod() { -} - /* ItemDefinition */ @@ -392,13 +394,11 @@ int ModApiItemMod::l_register_item_raw(lua_State *L) luaL_checktype(L, 1, LUA_TTABLE); int table = 1; - ScriptApi* scriptIface = get_scriptapi(L); - // Get the writable item and node definition managers from the server IWritableItemDefManager *idef = - scriptIface->getServer()->getWritableItemDefManager(); + getServer(L)->getWritableItemDefManager(); IWritableNodeDefManager *ndef = - scriptIface->getServer()->getWritableNodeDefManager(); + getServer(L)->getWritableNodeDefManager(); // Check if name is defined std::string name; @@ -455,7 +455,7 @@ int ModApiItemMod::l_register_alias_raw(lua_State *L) // Get the writable item definition manager from the server IWritableItemDefManager *idef = - STACK_TO_SERVER(L)->getWritableItemDefManager(); + getServer(L)->getWritableItemDefManager(); idef->registerAlias(name, convert_to); @@ -468,7 +468,7 @@ int ModApiItemMod::l_get_content_id(lua_State *L) NO_MAP_LOCK_REQUIRED; std::string name = luaL_checkstring(L, 1); - INodeDefManager *ndef = STACK_TO_SERVER(L)->getNodeDefManager(); + INodeDefManager *ndef = getServer(L)->getNodeDefManager(); content_t c = ndef->getId(name); lua_pushinteger(L, c); @@ -481,25 +481,17 @@ int ModApiItemMod::l_get_name_from_content_id(lua_State *L) NO_MAP_LOCK_REQUIRED; content_t c = luaL_checkint(L, 1); - INodeDefManager *ndef = STACK_TO_SERVER(L)->getNodeDefManager(); + INodeDefManager *ndef = getServer(L)->getNodeDefManager(); const char *name = ndef->get(c).name.c_str(); lua_pushstring(L, name); return 1; /* number of results */ } -bool ModApiItemMod::Initialize(lua_State *L,int top) { - - bool retval = true; - - retval &= API_FCT(register_item_raw); - retval &= API_FCT(register_alias_raw); - retval &= API_FCT(get_content_id); - retval &= API_FCT(get_name_from_content_id); - - LuaItemStack::Register(L); - - return retval; +void ModApiItemMod::Initialize(lua_State *L, int top) +{ + API_FCT(register_item_raw); + API_FCT(register_alias_raw); + API_FCT(get_content_id); + API_FCT(get_name_from_content_id); } - -ModApiItemMod modapi_item_prototyp; diff --git a/src/script/lua_api/l_item.h b/src/script/lua_api/l_item.h index bad517e08..7c2e1b098 100644 --- a/src/script/lua_api/l_item.h +++ b/src/script/lua_api/l_item.h @@ -20,24 +20,10 @@ with this program; if not, write to the Free Software Foundation, Inc., #ifndef L_ITEM_H_ #define L_ITEM_H_ -extern "C" { -#include <lua.h> -#include <lauxlib.h> -} - -#include <vector> - -#include "itemdef.h" -#include "content_sao.h" -#include "util/pointedthing.h" -#include "inventory.h" - #include "lua_api/l_base.h" +#include "inventory.h" // ItemStack -class ModApiInventory; - -class LuaItemStack -{ +class LuaItemStack : public ModApiBase { private: ItemStack m_stack; @@ -134,18 +120,14 @@ public: }; -class ModApiItemMod - :virtual public ModApiBase -{ -public: - ModApiItemMod(); - - bool Initialize(lua_State *L, int top); - +class ModApiItemMod : public ModApiBase { +private: static int l_register_item_raw(lua_State *L); static int l_register_alias_raw(lua_State *L); static int l_get_content_id(lua_State *L); static int l_get_name_from_content_id(lua_State *L); +public: + static void Initialize(lua_State *L, int top); }; diff --git a/src/script/lua_api/l_mainmenu.cpp b/src/script/lua_api/l_mainmenu.cpp new file mode 100644 index 000000000..b3ae1f3f1 --- /dev/null +++ b/src/script/lua_api/l_mainmenu.cpp @@ -0,0 +1,1016 @@ +/* +Minetest +Copyright (C) 2013 sapier + +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_mainmenu.h" +#include "lua_api/l_internal.h" +#include "common/c_content.h" +#include "guiEngine.h" +#include "guiMainMenu.h" +#include "guiKeyChangeMenu.h" +#include "guiFileSelectMenu.h" +#include "subgame.h" +#include "porting.h" +#include "filesys.h" +#include "convert_json.h" +#include "serverlist.h" +#include "sound.h" +#include "settings.h" +#include "main.h" // for g_settings + +#include <IFileArchive.h> +#include <IFileSystem.h> + +/******************************************************************************/ +std::string ModApiMainMenu::getTextData(lua_State *L, std::string name) +{ + lua_getglobal(L, "gamedata"); + + lua_getfield(L, -1, name.c_str()); + + if(lua_isnil(L, -1)) + return ""; + + return luaL_checkstring(L, -1); +} + +/******************************************************************************/ +int ModApiMainMenu::getIntegerData(lua_State *L, std::string name,bool& valid) +{ + lua_getglobal(L, "gamedata"); + + lua_getfield(L, -1, name.c_str()); + + if(lua_isnil(L, -1)) { + valid = false; + return -1; + } + + valid = true; + return luaL_checkinteger(L, -1); +} + +/******************************************************************************/ +int ModApiMainMenu::getBoolData(lua_State *L, std::string name,bool& valid) +{ + lua_getglobal(L, "gamedata"); + + lua_getfield(L, -1, name.c_str()); + + if(lua_isnil(L, -1)) { + valid = false; + return false; + } + + valid = true; + return lua_toboolean(L, -1); +} + +/******************************************************************************/ +int ModApiMainMenu::l_update_formspec(lua_State *L) +{ + GUIEngine* engine = getGuiEngine(L); + assert(engine != 0); + + if (engine->m_startgame) + return 0; + + //read formspec + std::string formspec(luaL_checkstring(L, 1)); + + if (engine->m_formspecgui != 0) { + engine->m_formspecgui->setForm(formspec); + } + + return 0; +} + +/******************************************************************************/ +int ModApiMainMenu::l_start(lua_State *L) +{ + GUIEngine* engine = getGuiEngine(L); + assert(engine != 0); + + //update c++ gamedata from lua table + + bool valid = false; + + + engine->m_data->selected_world = getIntegerData(L, "selected_world",valid) -1; + engine->m_data->simple_singleplayer_mode = getBoolData(L,"singleplayer",valid); + engine->m_data->name = getTextData(L,"playername"); + engine->m_data->password = getTextData(L,"password"); + engine->m_data->address = getTextData(L,"address"); + engine->m_data->port = getTextData(L,"port"); + engine->m_data->serverdescription = getTextData(L,"serverdescription"); + engine->m_data->servername = getTextData(L,"servername"); + + //close menu next time + engine->m_startgame = true; + return 0; +} + +/******************************************************************************/ +int ModApiMainMenu::l_close(lua_State *L) +{ + GUIEngine* engine = getGuiEngine(L); + assert(engine != 0); + + engine->m_data->kill = true; + + //close menu next time + engine->m_startgame = true; + engine->m_menu->quitMenu(); + return 0; +} + +/******************************************************************************/ +int ModApiMainMenu::l_set_background(lua_State *L) +{ + GUIEngine* engine = getGuiEngine(L); + assert(engine != 0); + + std::string backgroundlevel(luaL_checkstring(L, 1)); + std::string texturename(luaL_checkstring(L, 2)); + + bool retval = false; + + if (backgroundlevel == "background") { + retval |= engine->setTexture(TEX_LAYER_BACKGROUND,texturename); + } + + if (backgroundlevel == "overlay") { + retval |= engine->setTexture(TEX_LAYER_OVERLAY,texturename); + } + + if (backgroundlevel == "header") { + retval |= engine->setTexture(TEX_LAYER_HEADER,texturename); + } + + if (backgroundlevel == "footer") { + retval |= engine->setTexture(TEX_LAYER_FOOTER,texturename); + } + + lua_pushboolean(L,retval); + return 1; +} + +/******************************************************************************/ +int ModApiMainMenu::l_set_clouds(lua_State *L) +{ + GUIEngine* engine = getGuiEngine(L); + assert(engine != 0); + + bool value = lua_toboolean(L,1); + + engine->m_clouds_enabled = value; + + return 0; +} + +/******************************************************************************/ +int ModApiMainMenu::l_get_textlist_index(lua_State *L) +{ + GUIEngine* engine = getGuiEngine(L); + assert(engine != 0); + + std::string listboxname(luaL_checkstring(L, 1)); + + int selection = engine->m_menu->getListboxIndex(listboxname); + + if (selection >= 0) + selection++; + + lua_pushinteger(L, selection); + return 1; +} + +/******************************************************************************/ +int ModApiMainMenu::l_get_worlds(lua_State *L) +{ + GUIEngine* engine = getGuiEngine(L); + assert(engine != 0); + + std::vector<WorldSpec> worlds = getAvailableWorlds(); + + lua_newtable(L); + int top = lua_gettop(L); + unsigned int index = 1; + + for (unsigned int i = 0; i < worlds.size(); i++) + { + lua_pushnumber(L,index); + + lua_newtable(L); + int top_lvl2 = lua_gettop(L); + + lua_pushstring(L,"path"); + lua_pushstring(L,worlds[i].path.c_str()); + lua_settable(L, top_lvl2); + + lua_pushstring(L,"name"); + lua_pushstring(L,worlds[i].name.c_str()); + lua_settable(L, top_lvl2); + + lua_pushstring(L,"gameid"); + lua_pushstring(L,worlds[i].gameid.c_str()); + lua_settable(L, top_lvl2); + + lua_settable(L, top); + index++; + } + return 1; +} + +/******************************************************************************/ +int ModApiMainMenu::l_get_games(lua_State *L) +{ + GUIEngine* engine = getGuiEngine(L); + assert(engine != 0); + + std::vector<SubgameSpec> games = getAvailableGames(); + + lua_newtable(L); + int top = lua_gettop(L); + unsigned int index = 1; + + for (unsigned int i = 0; i < games.size(); i++) + { + lua_pushnumber(L,index); + lua_newtable(L); + int top_lvl2 = lua_gettop(L); + + lua_pushstring(L,"id"); + lua_pushstring(L,games[i].id.c_str()); + lua_settable(L, top_lvl2); + + lua_pushstring(L,"path"); + lua_pushstring(L,games[i].path.c_str()); + lua_settable(L, top_lvl2); + + lua_pushstring(L,"gamemods_path"); + lua_pushstring(L,games[i].gamemods_path.c_str()); + lua_settable(L, top_lvl2); + + lua_pushstring(L,"name"); + lua_pushstring(L,games[i].name.c_str()); + lua_settable(L, top_lvl2); + + lua_pushstring(L,"menuicon_path"); + lua_pushstring(L,games[i].menuicon_path.c_str()); + lua_settable(L, top_lvl2); + + lua_pushstring(L,"addon_mods_paths"); + lua_newtable(L); + int table2 = lua_gettop(L); + int internal_index=1; + for (std::set<std::string>::iterator iter = games[i].addon_mods_paths.begin(); + iter != games[i].addon_mods_paths.end(); iter++) { + lua_pushnumber(L,internal_index); + lua_pushstring(L,(*iter).c_str()); + lua_settable(L, table2); + internal_index++; + } + lua_settable(L, top_lvl2); + lua_settable(L, top); + index++; + } + return 1; +} +/******************************************************************************/ +int ModApiMainMenu::l_get_modstore_details(lua_State *L) +{ + const char *modid = luaL_checkstring(L, 1); + + if (modid != 0) { + Json::Value details; + std::string url = ""; + try{ + url = g_settings->get("modstore_details_url"); + } + catch(SettingNotFoundException &e) { + lua_pushnil(L); + return 1; + } + + size_t idpos = url.find("*"); + url.erase(idpos,1); + url.insert(idpos,modid); + + details = getModstoreUrl(url); + + ModStoreModDetails current_mod = readModStoreModDetails(details); + + if ( current_mod.valid) { + lua_newtable(L); + int top = lua_gettop(L); + + lua_pushstring(L,"id"); + lua_pushnumber(L,current_mod.id); + lua_settable(L, top); + + lua_pushstring(L,"title"); + lua_pushstring(L,current_mod.title.c_str()); + lua_settable(L, top); + + lua_pushstring(L,"basename"); + lua_pushstring(L,current_mod.basename.c_str()); + lua_settable(L, top); + + lua_pushstring(L,"description"); + lua_pushstring(L,current_mod.description.c_str()); + lua_settable(L, top); + + lua_pushstring(L,"author"); + lua_pushstring(L,current_mod.author.username.c_str()); + lua_settable(L, top); + + lua_pushstring(L,"download_url"); + lua_pushstring(L,current_mod.versions[0].file.c_str()); + lua_settable(L, top); + + lua_pushstring(L,"screenshot_url"); + lua_pushstring(L,current_mod.titlepic.file.c_str()); + lua_settable(L, top); + + lua_pushstring(L,"license"); + lua_pushstring(L,current_mod.license.shortinfo.c_str()); + lua_settable(L, top); + + lua_pushstring(L,"rating"); + lua_pushnumber(L,current_mod.rating); + lua_settable(L, top); + + //TODO depends + + //TODO softdepends + return 1; + } + } + return 0; +} + +/******************************************************************************/ +int ModApiMainMenu::l_get_modstore_list(lua_State *L) +{ + GUIEngine* engine = getGuiEngine(L); + assert(engine != 0); + + std::string listtype = "local"; + + if (!lua_isnone(L,1)) { + listtype = luaL_checkstring(L,1); + } + Json::Value mods; + std::string url = ""; + try{ + url = g_settings->get("modstore_listmods_url"); + } + catch(SettingNotFoundException &e) { + lua_pushnil(L); + return 1; + } + + mods = getModstoreUrl(url); + + std::vector<ModStoreMod> moddata = readModStoreList(mods); + + lua_newtable(L); + int top = lua_gettop(L); + unsigned int index = 1; + + for (unsigned int i = 0; i < moddata.size(); i++) + { + if (moddata[i].valid) { + lua_pushnumber(L,index); + lua_newtable(L); + + int top_lvl2 = lua_gettop(L); + + lua_pushstring(L,"id"); + lua_pushnumber(L,moddata[i].id); + lua_settable(L, top_lvl2); + + lua_pushstring(L,"title"); + lua_pushstring(L,moddata[i].title.c_str()); + lua_settable(L, top_lvl2); + + lua_pushstring(L,"basename"); + lua_pushstring(L,moddata[i].basename.c_str()); + lua_settable(L, top_lvl2); + + lua_settable(L, top); + index++; + } + } + return 1; +} + +/******************************************************************************/ +int ModApiMainMenu::l_get_favorites(lua_State *L) +{ + GUIEngine* engine = getGuiEngine(L); + assert(engine != 0); + + std::string listtype = "local"; + + if (!lua_isnone(L,1)) { + listtype = luaL_checkstring(L,1); + } + + std::vector<ServerListSpec> servers; +#if USE_CURL + if(listtype == "online") { + servers = ServerList::getOnline(); + } else { + servers = ServerList::getLocal(); + } +#else + servers = ServerList::getLocal(); +#endif + + lua_newtable(L); + int top = lua_gettop(L); + unsigned int index = 1; + + for (unsigned int i = 0; i < servers.size(); i++) + { + lua_pushnumber(L,index); + + lua_newtable(L); + int top_lvl2 = lua_gettop(L); + + if (servers[i]["clients"].asString().size()) { + + const char* clients_raw = servers[i]["clients"].asString().c_str(); + char* endptr = 0; + int numbervalue = strtol(clients_raw,&endptr,10); + + if ((*clients_raw != 0) && (*endptr == 0)) { + lua_pushstring(L,"clients"); + lua_pushnumber(L,numbervalue); + lua_settable(L, top_lvl2); + } + } + + if (servers[i]["clients_max"].asString().size()) { + + const char* clients_max_raw = servers[i]["clients_max"].asString().c_str(); + char* endptr = 0; + int numbervalue = strtol(clients_max_raw,&endptr,10); + + if ((*clients_max_raw != 0) && (*endptr == 0)) { + lua_pushstring(L,"clients_max"); + lua_pushnumber(L,numbervalue); + lua_settable(L, top_lvl2); + } + } + + if (servers[i]["version"].asString().size()) { + lua_pushstring(L,"version"); + lua_pushstring(L,servers[i]["version"].asString().c_str()); + lua_settable(L, top_lvl2); + } + + if (servers[i]["password"].asString().size()) { + lua_pushstring(L,"password"); + lua_pushboolean(L,true); + lua_settable(L, top_lvl2); + } + + if (servers[i]["creative"].asString().size()) { + lua_pushstring(L,"creative"); + lua_pushboolean(L,true); + lua_settable(L, top_lvl2); + } + + if (servers[i]["damage"].asString().size()) { + lua_pushstring(L,"damage"); + lua_pushboolean(L,true); + lua_settable(L, top_lvl2); + } + + if (servers[i]["pvp"].asString().size()) { + lua_pushstring(L,"pvp"); + lua_pushboolean(L,true); + lua_settable(L, top_lvl2); + } + + if (servers[i]["description"].asString().size()) { + lua_pushstring(L,"description"); + lua_pushstring(L,servers[i]["description"].asString().c_str()); + lua_settable(L, top_lvl2); + } + + if (servers[i]["name"].asString().size()) { + lua_pushstring(L,"name"); + lua_pushstring(L,servers[i]["name"].asString().c_str()); + lua_settable(L, top_lvl2); + } + + if (servers[i]["address"].asString().size()) { + lua_pushstring(L,"address"); + lua_pushstring(L,servers[i]["address"].asString().c_str()); + lua_settable(L, top_lvl2); + } + + if (servers[i]["port"].asString().size()) { + lua_pushstring(L,"port"); + lua_pushstring(L,servers[i]["port"].asString().c_str()); + lua_settable(L, top_lvl2); + } + + lua_settable(L, top); + index++; + } + return 1; +} + +/******************************************************************************/ +int ModApiMainMenu::l_delete_favorite(lua_State *L) +{ + GUIEngine* engine = getGuiEngine(L); + assert(engine != 0); + + std::vector<ServerListSpec> servers; + + std::string listtype = "local"; + + if (!lua_isnone(L,2)) { + listtype = luaL_checkstring(L,2); + } + + if ((listtype != "local") && + (listtype != "online")) + return 0; + +#if USE_CURL + if(listtype == "online") { + servers = ServerList::getOnline(); + } else { + servers = ServerList::getLocal(); + } +#else + servers = ServerList::getLocal(); +#endif + + int fav_idx = luaL_checkinteger(L,1) -1; + + if ((fav_idx >= 0) && + (fav_idx < (int) servers.size())) { + + ServerList::deleteEntry(servers[fav_idx]); + } + + return 0; +} + +/******************************************************************************/ +int ModApiMainMenu::l_show_keys_menu(lua_State *L) +{ + GUIEngine* engine = getGuiEngine(L); + assert(engine != 0); + + GUIKeyChangeMenu *kmenu + = new GUIKeyChangeMenu( engine->m_device->getGUIEnvironment(), + engine->m_parent, + -1, + engine->m_menumanager); + kmenu->drop(); + return 0; +} + +/******************************************************************************/ +int ModApiMainMenu::l_create_world(lua_State *L) +{ + GUIEngine* engine = getGuiEngine(L); + assert(engine != 0); + + const char *name = luaL_checkstring(L, 1); + int gameidx = luaL_checkinteger(L,2) -1; + + std::string path = porting::path_user + DIR_DELIM + "worlds" + DIR_DELIM + + name; + + std::vector<SubgameSpec> games = getAvailableGames(); + + if ((gameidx >= 0) && + (gameidx < (int) games.size())) { + + // Create world if it doesn't exist + if(!initializeWorld(path, games[gameidx].id)){ + lua_pushstring(L, "Failed to initialize world"); + + } + else { + lua_pushnil(L); + } + } + else { + lua_pushstring(L, "Invalid game index"); + } + return 1; +} + +/******************************************************************************/ +int ModApiMainMenu::l_delete_world(lua_State *L) +{ + GUIEngine* engine = getGuiEngine(L); + assert(engine != 0); + + int worldidx = luaL_checkinteger(L,1) -1; + + std::vector<WorldSpec> worlds = getAvailableWorlds(); + + if ((worldidx >= 0) && + (worldidx < (int) worlds.size())) { + + WorldSpec spec = worlds[worldidx]; + + std::vector<std::string> paths; + paths.push_back(spec.path); + fs::GetRecursiveSubPaths(spec.path, paths); + + // Delete files + if (!fs::DeletePaths(paths)) { + lua_pushstring(L, "Failed to delete world"); + } + else { + lua_pushnil(L); + } + } + else { + lua_pushstring(L, "Invalid world index"); + } + return 1; +} + +/******************************************************************************/ +int ModApiMainMenu::l_set_topleft_text(lua_State *L) +{ + GUIEngine* engine = getGuiEngine(L); + assert(engine != 0); + + std::string text = ""; + + if (!lua_isnone(L,1) && !lua_isnil(L,1)) + text = luaL_checkstring(L, 1); + + engine->setTopleftText(text); + return 0; +} + +/******************************************************************************/ +int ModApiMainMenu::l_get_modpath(lua_State *L) +{ + std::string modpath + = fs::RemoveRelativePathComponents(porting::path_user + DIR_DELIM + "mods" + DIR_DELIM); + lua_pushstring(L, modpath.c_str()); + return 1; +} + +/******************************************************************************/ +int ModApiMainMenu::l_get_gamepath(lua_State *L) +{ + std::string gamepath + = fs::RemoveRelativePathComponents(porting::path_user + DIR_DELIM + "games" + DIR_DELIM); + lua_pushstring(L, gamepath.c_str()); + return 1; +} + +/******************************************************************************/ +int ModApiMainMenu::l_get_texturepath(lua_State *L) +{ + std::string gamepath + = fs::RemoveRelativePathComponents(porting::path_user + DIR_DELIM + "textures"); + lua_pushstring(L, gamepath.c_str()); + return 1; +} + +/******************************************************************************/ +int ModApiMainMenu::l_get_dirlist(lua_State *L) +{ + const char *path = luaL_checkstring(L, 1); + bool dironly = lua_toboolean(L, 2); + + std::vector<fs::DirListNode> dirlist = fs::GetDirListing(path); + + unsigned int index = 1; + lua_newtable(L); + int table = lua_gettop(L); + + for (unsigned int i=0;i< dirlist.size(); i++) { + if ((dirlist[i].dir) || (dironly == false)) { + lua_pushnumber(L,index); + lua_pushstring(L,dirlist[i].name.c_str()); + lua_settable(L, table); + index++; + } + } + + return 1; +} + +/******************************************************************************/ +int ModApiMainMenu::l_create_dir(lua_State *L) { + const char *path = luaL_checkstring(L, 1); + + if (ModApiMainMenu::isMinetestPath(path)) { + lua_pushboolean(L,fs::CreateAllDirs(path)); + return 1; + } + lua_pushboolean(L,false); + return 1; +} + +/******************************************************************************/ +int ModApiMainMenu::l_delete_dir(lua_State *L) +{ + const char *path = luaL_checkstring(L, 1); + + std::string absolute_path = fs::RemoveRelativePathComponents(path); + + if (ModApiMainMenu::isMinetestPath(absolute_path)) { + lua_pushboolean(L,fs::RecursiveDelete(absolute_path)); + return 1; + } + lua_pushboolean(L,false); + return 1; +} + +/******************************************************************************/ +int ModApiMainMenu::l_copy_dir(lua_State *L) +{ + const char *source = luaL_checkstring(L, 1); + const char *destination = luaL_checkstring(L, 2); + + bool keep_source = true; + + if ((!lua_isnone(L,3)) && + (!lua_isnil(L,3))) { + keep_source = lua_toboolean(L,3); + } + + std::string absolute_destination = fs::RemoveRelativePathComponents(destination); + std::string absolute_source = fs::RemoveRelativePathComponents(source); + + if ((ModApiMainMenu::isMinetestPath(absolute_source)) && + (ModApiMainMenu::isMinetestPath(absolute_destination))) { + bool retval = fs::CopyDir(absolute_source,absolute_destination); + + if (retval && (!keep_source)) { + + retval &= fs::RecursiveDelete(absolute_source); + } + lua_pushboolean(L,retval); + return 1; + } + lua_pushboolean(L,false); + return 1; +} + +/******************************************************************************/ +int ModApiMainMenu::l_extract_zip(lua_State *L) +{ + GUIEngine* engine = getGuiEngine(L); + assert(engine != 0); + + const char *zipfile = luaL_checkstring(L, 1); + const char *destination = luaL_checkstring(L, 2); + + std::string absolute_destination = fs::RemoveRelativePathComponents(destination); + + if (ModApiMainMenu::isMinetestPath(absolute_destination)) { + fs::CreateAllDirs(absolute_destination); + + io::IFileSystem* fs = engine->m_device->getFileSystem(); + + fs->addFileArchive(zipfile,true,false,io::EFAT_ZIP); + + assert(fs->getFileArchiveCount() > 0); + + /**********************************************************************/ + /* WARNING this is not threadsafe!! */ + /**********************************************************************/ + io::IFileArchive* opened_zip = + fs->getFileArchive(fs->getFileArchiveCount()-1); + + const io::IFileList* files_in_zip = opened_zip->getFileList(); + + unsigned int number_of_files = files_in_zip->getFileCount(); + + for (unsigned int i=0; i < number_of_files; i++) { + std::string fullpath = destination; + fullpath += DIR_DELIM; + fullpath += files_in_zip->getFullFileName(i).c_str(); + + if (files_in_zip->isDirectory(i)) { + if (! fs::CreateAllDirs(fullpath) ) { + fs->removeFileArchive(fs->getFileArchiveCount()-1); + lua_pushboolean(L,false); + return 1; + } + } + else { + io::IReadFile* toread = opened_zip->createAndOpenFile(i); + + FILE *targetfile = fopen(fullpath.c_str(),"wb"); + + if (targetfile == NULL) { + fs->removeFileArchive(fs->getFileArchiveCount()-1); + lua_pushboolean(L,false); + return 1; + } + + char read_buffer[1024]; + unsigned int total_read = 0; + + while (total_read < toread->getSize()) { + + unsigned int bytes_read = + toread->read(read_buffer,sizeof(read_buffer)); + unsigned int bytes_written; + if ((bytes_read < 0 ) || + (bytes_written = fwrite(read_buffer, 1, bytes_read, targetfile) != bytes_read)) + { + fclose(targetfile); + fs->removeFileArchive(fs->getFileArchiveCount()-1); + lua_pushboolean(L,false); + return 1; + } + total_read += bytes_read; + } + + fclose(targetfile); + } + + } + + fs->removeFileArchive(fs->getFileArchiveCount()-1); + lua_pushboolean(L,true); + return 1; + } + + lua_pushboolean(L,false); + return 1; +} + +/******************************************************************************/ +int ModApiMainMenu::l_get_scriptdir(lua_State *L) +{ + GUIEngine* engine = getGuiEngine(L); + assert(engine != 0); + + lua_pushstring(L,engine->getScriptDir().c_str()); + return 1; +} + +/******************************************************************************/ +bool ModApiMainMenu::isMinetestPath(std::string path) +{ + if (fs::PathStartsWith(path,fs::TempPath())) + return true; + + /* games */ + if (fs::PathStartsWith(path,fs::RemoveRelativePathComponents(porting::path_share + DIR_DELIM + "games"))) + return true; + + /* mods */ + if (fs::PathStartsWith(path,fs::RemoveRelativePathComponents(porting::path_user + DIR_DELIM + "mods"))) + return true; + + /* worlds */ + if (fs::PathStartsWith(path,fs::RemoveRelativePathComponents(porting::path_user + DIR_DELIM + "worlds"))) + return true; + + + return false; +} + +/******************************************************************************/ +int ModApiMainMenu::l_show_file_open_dialog(lua_State *L) +{ + GUIEngine* engine = getGuiEngine(L); + assert(engine != 0); + + const char *formname= luaL_checkstring(L, 1); + const char *title = luaL_checkstring(L, 2); + + GUIFileSelectMenu* fileOpenMenu = + new GUIFileSelectMenu(engine->m_device->getGUIEnvironment(), + engine->m_parent, + -1, + engine->m_menumanager, + title, + formname); + fileOpenMenu->setTextDest(engine->m_buttonhandler); + fileOpenMenu->drop(); + return 0; +} + +/******************************************************************************/ +int ModApiMainMenu::l_get_version(lua_State *L) +{ + lua_pushstring(L,VERSION_STRING); + return 1; +} + +/******************************************************************************/ +int ModApiMainMenu::l_sound_play(lua_State *L) +{ + GUIEngine* engine = getGuiEngine(L); + + SimpleSoundSpec spec; + read_soundspec(L, 1, spec); + bool looped = lua_toboolean(L, 2); + + u32 handle = engine->playSound(spec, looped); + + lua_pushinteger(L, handle); + + return 1; +} + +/******************************************************************************/ +int ModApiMainMenu::l_sound_stop(lua_State *L) +{ + GUIEngine* engine = getGuiEngine(L); + + u32 handle = luaL_checkinteger(L, 1); + engine->stopSound(handle); + + return 1; +} + +/******************************************************************************/ +int ModApiMainMenu::l_download_file(lua_State *L) +{ + GUIEngine* engine = getGuiEngine(L); + assert(engine != 0); + + const char *url = luaL_checkstring(L, 1); + const char *target = luaL_checkstring(L, 2); + + //check path + std::string absolute_destination = fs::RemoveRelativePathComponents(target); + + if (ModApiMainMenu::isMinetestPath(absolute_destination)) { + if (engine->downloadFile(url,absolute_destination)) { + lua_pushboolean(L,true); + return 1; + } + } + lua_pushboolean(L,false); + return 1; +} + +/******************************************************************************/ +void ModApiMainMenu::Initialize(lua_State *L, int top) +{ + API_FCT(update_formspec); + API_FCT(set_clouds); + API_FCT(get_textlist_index); + API_FCT(get_worlds); + API_FCT(get_games); + API_FCT(start); + API_FCT(close); + API_FCT(get_favorites); + API_FCT(show_keys_menu); + API_FCT(create_world); + API_FCT(delete_world); + API_FCT(delete_favorite); + API_FCT(set_background); + API_FCT(set_topleft_text); + API_FCT(get_modpath); + API_FCT(get_gamepath); + API_FCT(get_texturepath); + API_FCT(get_dirlist); + API_FCT(create_dir); + API_FCT(delete_dir); + API_FCT(copy_dir); + API_FCT(extract_zip); + API_FCT(get_scriptdir); + API_FCT(show_file_open_dialog); + API_FCT(get_version); + API_FCT(download_file); + API_FCT(get_modstore_details); + API_FCT(get_modstore_list); + API_FCT(sound_play); + API_FCT(sound_stop); +} diff --git a/src/script/lua_api/l_mainmenu.h b/src/script/lua_api/l_mainmenu.h new file mode 100644 index 000000000..21dd82c68 --- /dev/null +++ b/src/script/lua_api/l_mainmenu.h @@ -0,0 +1,137 @@ +/* +Minetest +Copyright (C) 2013 sapier + +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_MAINMENU_H_ +#define L_MAINMENU_H_ + +#include "lua_api/l_base.h" + +/** Implementation of lua api support for mainmenu */ +class ModApiMainMenu : public ModApiBase { + +private: + /** + * read a text variable from gamedata table within lua stack + * @param L stack to read variable from + * @param name name of variable to read + * @return string value of requested variable + */ + static std::string getTextData(lua_State *L, std::string name); + + /** + * read a integer variable from gamedata table within lua stack + * @param L stack to read variable from + * @param name name of variable to read + * @return integer value of requested variable + */ + static int getIntegerData(lua_State *L, std::string name,bool& valid); + + /** + * read a bool variable from gamedata table within lua stack + * @param L stack to read variable from + * @param name name of variable to read + * @return bool value of requested variable + */ + static int getBoolData(lua_State *L, std::string name,bool& valid); + + /** + * check if a path is within some of minetests folders + * @param path path to check + * @return true/false + */ + static bool isMinetestPath(std::string path); + + //api calls + + static int l_start(lua_State *L); + + static int l_close(lua_State *L); + + static int l_create_world(lua_State *L); + + static int l_delete_world(lua_State *L); + + static int l_get_worlds(lua_State *L); + + static int l_get_games(lua_State *L); + + static int l_get_favorites(lua_State *L); + + static int l_delete_favorite(lua_State *L); + + static int l_get_version(lua_State *L); + + static int l_sound_play(lua_State *L); + + static int l_sound_stop(lua_State *L); + + //gui + + static int l_show_keys_menu(lua_State *L); + + static int l_show_file_open_dialog(lua_State *L); + + static int l_set_topleft_text(lua_State *L); + + static int l_set_clouds(lua_State *L); + + static int l_get_textlist_index(lua_State *L); + + static int l_set_background(lua_State *L); + + static int l_update_formspec(lua_State *L); + + //filesystem + + static int l_get_scriptdir(lua_State *L); + + static int l_get_modpath(lua_State *L); + + static int l_get_gamepath(lua_State *L); + + static int l_get_texturepath(lua_State *L); + + static int l_get_dirlist(lua_State *L); + + static int l_create_dir(lua_State *L); + + static int l_delete_dir(lua_State *L); + + static int l_copy_dir(lua_State *L); + + static int l_extract_zip(lua_State *L); + + static int l_get_modstore_details(lua_State *L); + + static int l_get_modstore_list(lua_State *L); + + static int l_download_file(lua_State *L); + + +public: + /** + * initialize this API module + * @param L lua stack to initialize + * @param top index (in lua stack) of global API table + */ + static void Initialize(lua_State *L, int top); + +}; + +#endif /* L_MAINMENU_H_ */ diff --git a/src/script/lua_api/l_mapgen.cpp b/src/script/lua_api/l_mapgen.cpp new file mode 100644 index 000000000..14693b43f --- /dev/null +++ b/src/script/lua_api/l_mapgen.cpp @@ -0,0 +1,574 @@ +/* +Minetest +Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com> + +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_mapgen.h" +#include "lua_api/l_internal.h" +#include "lua_api/l_vmanip.h" +#include "common/c_converter.h" +#include "common/c_content.h" +#include "server.h" +#include "environment.h" +#include "biome.h" +#include "emerge.h" +#include "mapgen_v7.h" + + +struct EnumString ModApiMapgen::es_BiomeTerrainType[] = +{ + {BIOME_TERRAIN_NORMAL, "normal"}, + {BIOME_TERRAIN_LIQUID, "liquid"}, + {BIOME_TERRAIN_NETHER, "nether"}, + {BIOME_TERRAIN_AETHER, "aether"}, + {BIOME_TERRAIN_FLAT, "flat"}, + {0, NULL}, +}; + +struct EnumString ModApiMapgen::es_DecorationType[] = +{ + {DECO_SIMPLE, "simple"}, + {DECO_SCHEMATIC, "schematic"}, + {DECO_LSYSTEM, "lsystem"}, + {0, NULL}, +}; + +struct EnumString ModApiMapgen::es_MapgenObject[] = +{ + {MGOBJ_VMANIP, "voxelmanip"}, + {MGOBJ_HEIGHTMAP, "heightmap"}, + {MGOBJ_BIOMEMAP, "biomemap"}, + {MGOBJ_HEATMAP, "heatmap"}, + {MGOBJ_HUMIDMAP, "humiditymap"}, + {0, NULL}, +}; + +struct EnumString ModApiMapgen::es_OreType[] = +{ + {ORE_SCATTER, "scatter"}, + {ORE_SHEET, "sheet"}, + {ORE_CLAYLIKE, "claylike"}, + {0, NULL}, +}; + +struct EnumString ModApiMapgen::es_Rotation[] = +{ + {ROTATE_0, "0"}, + {ROTATE_90, "90"}, + {ROTATE_180, "180"}, + {ROTATE_270, "270"}, + {ROTATE_RAND, "random"}, + {0, NULL}, +}; + + +// minetest.get_mapgen_object(objectname) +// returns the requested object used during map generation +int ModApiMapgen::l_get_mapgen_object(lua_State *L) +{ + const char *mgobjstr = lua_tostring(L, 1); + + int mgobjint; + if (!string_to_enum(es_MapgenObject, mgobjint, mgobjstr ? mgobjstr : "")) + return 0; + + enum MapgenObject mgobj = (MapgenObject)mgobjint; + + EmergeManager *emerge = getServer(L)->getEmergeManager(); + Mapgen *mg = emerge->getCurrentMapgen(); + if (!mg) + return 0; + + size_t maplen = mg->csize.X * mg->csize.Z; + + int nargs = 1; + + switch (mgobj) { + case MGOBJ_VMANIP: { + ManualMapVoxelManipulator *vm = mg->vm; + + // VoxelManip object + LuaVoxelManip *o = new LuaVoxelManip(vm, true); + *(void **)(lua_newuserdata(L, sizeof(void *))) = o; + luaL_getmetatable(L, "VoxelManip"); + lua_setmetatable(L, -2); + + // emerged min pos + push_v3s16(L, vm->m_area.MinEdge); + + // emerged max pos + push_v3s16(L, vm->m_area.MaxEdge); + + nargs = 3; + + break; } + case MGOBJ_HEIGHTMAP: { + if (!mg->heightmap) + return 0; + + lua_newtable(L); + for (size_t i = 0; i != maplen; i++) { + lua_pushinteger(L, mg->heightmap[i]); + lua_rawseti(L, -2, i + 1); + } + break; } + case MGOBJ_BIOMEMAP: { + if (!mg->biomemap) + return 0; + + lua_newtable(L); + for (size_t i = 0; i != maplen; i++) { + lua_pushinteger(L, mg->biomemap[i]); + lua_rawseti(L, -2, i + 1); + } + break; } + case MGOBJ_HEATMAP: { // Mapgen V7 specific objects + case MGOBJ_HUMIDMAP: + if (strcmp(emerge->params->mg_name.c_str(), "v7")) + return 0; + + MapgenV7 *mgv7 = (MapgenV7 *)mg; + + float *arr = (mgobj == MGOBJ_HEATMAP) ? + mgv7->noise_heat->result : mgv7->noise_humidity->result; + if (!arr) + return 0; + + lua_newtable(L); + for (size_t i = 0; i != maplen; i++) { + lua_pushnumber(L, arr[i]); + lua_rawseti(L, -2, i + 1); + } + break; } + } + + return nargs; +} + +// minetest.set_mapgen_params(params) +// set mapgen parameters +int ModApiMapgen::l_set_mapgen_params(lua_State *L) +{ + if (!lua_istable(L, 1)) + return 0; + + EmergeManager *emerge = getServer(L)->getEmergeManager(); + if (emerge->mapgen.size()) + return 0; + + MapgenParams *oparams = new MapgenParams; + u32 paramsmodified = 0; + u32 flagmask = 0; + + lua_getfield(L, 1, "mgname"); + if (lua_isstring(L, -1)) { + oparams->mg_name = std::string(lua_tostring(L, -1)); + paramsmodified |= MGPARAMS_SET_MGNAME; + } + + lua_getfield(L, 1, "seed"); + if (lua_isnumber(L, -1)) { + oparams->seed = lua_tointeger(L, -1); + paramsmodified |= MGPARAMS_SET_SEED; + } + + lua_getfield(L, 1, "water_level"); + if (lua_isnumber(L, -1)) { + oparams->water_level = lua_tointeger(L, -1); + paramsmodified |= MGPARAMS_SET_WATER_LEVEL; + } + + lua_getfield(L, 1, "flags"); + if (lua_isstring(L, -1)) { + std::string flagstr = std::string(lua_tostring(L, -1)); + oparams->flags = readFlagString(flagstr, flagdesc_mapgen); + paramsmodified |= MGPARAMS_SET_FLAGS; + + lua_getfield(L, 1, "flagmask"); + if (lua_isstring(L, -1)) { + flagstr = std::string(lua_tostring(L, -1)); + flagmask = readFlagString(flagstr, flagdesc_mapgen); + } + } + + emerge->luaoverride_params = oparams; + emerge->luaoverride_params_modified = paramsmodified; + emerge->luaoverride_flagmask = flagmask; + + return 0; +} + +// register_biome({lots of stuff}) +int ModApiMapgen::l_register_biome(lua_State *L) +{ + int index = 1; + luaL_checktype(L, index, LUA_TTABLE); + + BiomeDefManager *bmgr = getServer(L)->getEmergeManager()->biomedef; + if (!bmgr) { + verbosestream << "register_biome: BiomeDefManager not active" << std::endl; + return 0; + } + + enum BiomeTerrainType terrain = (BiomeTerrainType)getenumfield(L, index, + "terrain_type", es_BiomeTerrainType, BIOME_TERRAIN_NORMAL); + Biome *b = bmgr->createBiome(terrain); + + b->name = getstringfield_default(L, index, "name", + "<no name>"); + b->nname_top = getstringfield_default(L, index, "node_top", + "mapgen_dirt_with_grass"); + b->nname_filler = getstringfield_default(L, index, "node_filler", + "mapgen_dirt"); + b->nname_water = getstringfield_default(L, index, "node_water", + "mapgen_water_source"); + b->nname_dust = getstringfield_default(L, index, "node_dust", + "air"); + b->nname_dust_water = getstringfield_default(L, index, "node_dust_water", + "mapgen_water_source"); + + b->depth_top = getintfield_default(L, index, "depth_top", 1); + b->depth_filler = getintfield_default(L, index, "depth_filler", 3); + b->height_min = getintfield_default(L, index, "height_min", 0); + b->height_max = getintfield_default(L, index, "height_max", 0); + b->heat_point = getfloatfield_default(L, index, "heat_point", 0.); + b->humidity_point = getfloatfield_default(L, index, "humidity_point", 0.); + + b->flags = 0; //reserved + b->c_top = CONTENT_IGNORE; + b->c_filler = CONTENT_IGNORE; + b->c_water = CONTENT_IGNORE; + b->c_dust = CONTENT_IGNORE; + b->c_dust_water = CONTENT_IGNORE; + + verbosestream << "register_biome: " << b->name << std::endl; + bmgr->addBiome(b); + + return 0; +} + +// register_decoration({lots of stuff}) +int ModApiMapgen::l_register_decoration(lua_State *L) +{ + int index = 1; + luaL_checktype(L, index, LUA_TTABLE); + + EmergeManager *emerge = getServer(L)->getEmergeManager(); + BiomeDefManager *bdef = emerge->biomedef; + + enum DecorationType decotype = (DecorationType)getenumfield(L, index, + "deco_type", es_DecorationType, -1); + if (decotype == -1) { + errorstream << "register_decoration: unrecognized " + "decoration placement type"; + return 0; + } + + Decoration *deco = createDecoration(decotype); + if (!deco) { + errorstream << "register_decoration: decoration placement type " + << decotype << " not implemented"; + return 0; + } + + deco->c_place_on = CONTENT_IGNORE; + deco->place_on_name = getstringfield_default(L, index, "place_on", "ignore"); + deco->fill_ratio = getfloatfield_default(L, index, "fill_ratio", 0.02); + deco->sidelen = getintfield_default(L, index, "sidelen", 8); + if (deco->sidelen <= 0) { + errorstream << "register_decoration: sidelen must be " + "greater than 0" << std::endl; + delete deco; + return 0; + } + + lua_getfield(L, index, "noise_params"); + deco->np = read_noiseparams(L, -1); + lua_pop(L, 1); + + lua_getfield(L, index, "biomes"); + if (lua_istable(L, -1)) { + lua_pushnil(L); + while (lua_next(L, -2)) { + const char *s = lua_tostring(L, -1); + u8 biomeid = bdef->getBiomeIdByName(s); + if (biomeid) + deco->biomes.insert(biomeid); + + lua_pop(L, 1); + } + lua_pop(L, 1); + } + + switch (decotype) { + case DECO_SIMPLE: { + DecoSimple *dsimple = (DecoSimple *)deco; + dsimple->c_deco = CONTENT_IGNORE; + dsimple->c_spawnby = CONTENT_IGNORE; + dsimple->spawnby_name = getstringfield_default(L, index, "spawn_by", "air"); + dsimple->deco_height = getintfield_default(L, index, "height", 1); + dsimple->deco_height_max = getintfield_default(L, index, "height_max", 0); + dsimple->nspawnby = getintfield_default(L, index, "num_spawn_by", -1); + + lua_getfield(L, index, "decoration"); + if (lua_istable(L, -1)) { + lua_pushnil(L); + while (lua_next(L, -2)) { + const char *s = lua_tostring(L, -1); + std::string str(s); + dsimple->decolist_names.push_back(str); + + lua_pop(L, 1); + } + } else if (lua_isstring(L, -1)) { + dsimple->deco_name = std::string(lua_tostring(L, -1)); + } else { + dsimple->deco_name = std::string("air"); + } + lua_pop(L, 1); + + if (dsimple->deco_height <= 0) { + errorstream << "register_decoration: simple decoration height" + " must be greater than 0" << std::endl; + delete dsimple; + return 0; + } + + break; } + case DECO_SCHEMATIC: { + DecoSchematic *dschem = (DecoSchematic *)deco; + dschem->flags = getflagsfield(L, index, "flags", flagdesc_deco_schematic); + dschem->rotation = (Rotation)getenumfield(L, index, + "rotation", es_Rotation, ROTATE_0); + + lua_getfield(L, index, "replacements"); + if (lua_istable(L, -1)) { + int i = lua_gettop(L); + lua_pushnil(L); + while (lua_next(L, i) != 0) { + // key at index -2 and value at index -1 + lua_rawgeti(L, -1, 1); + std::string replace_from = lua_tostring(L, -1); + lua_pop(L, 1); + lua_rawgeti(L, -1, 2); + std::string replace_to = lua_tostring(L, -1); + lua_pop(L, 1); + dschem->replacements[replace_from] = replace_to; + // removes value, keeps key for next iteration + lua_pop(L, 1); + } + } + lua_pop(L, 1); + + lua_getfield(L, index, "schematic"); + if (!read_schematic(L, -1, dschem, getServer(L))) { + delete dschem; + return 0; + } + lua_pop(L, -1); + + if (!dschem->filename.empty() && !dschem->loadSchematicFile()) { + errorstream << "register_decoration: failed to load schematic file '" + << dschem->filename << "'" << std::endl; + delete dschem; + return 0; + } + break; } + case DECO_LSYSTEM: { + //DecoLSystem *decolsystem = (DecoLSystem *)deco; + + break; } + } + + emerge->decorations.push_back(deco); + + verbosestream << "register_decoration: decoration '" << deco->getName() + << "' registered" << std::endl; + return 0; +} + +// register_ore({lots of stuff}) +int ModApiMapgen::l_register_ore(lua_State *L) +{ + int index = 1; + luaL_checktype(L, index, LUA_TTABLE); + + EmergeManager *emerge = getServer(L)->getEmergeManager(); + + enum OreType oretype = (OreType)getenumfield(L, index, + "ore_type", es_OreType, ORE_SCATTER); + Ore *ore = createOre(oretype); + if (!ore) { + errorstream << "register_ore: ore_type " + << oretype << " not implemented"; + return 0; + } + + ore->ore_name = getstringfield_default(L, index, "ore", ""); + ore->ore_param2 = (u8)getintfield_default(L, index, "ore_param2", 0); + ore->clust_scarcity = getintfield_default(L, index, "clust_scarcity", 1); + ore->clust_num_ores = getintfield_default(L, index, "clust_num_ores", 1); + ore->clust_size = getintfield_default(L, index, "clust_size", 0); + ore->height_min = getintfield_default(L, index, "height_min", 0); + ore->height_max = getintfield_default(L, index, "height_max", 0); + ore->flags = getflagsfield(L, index, "flags", flagdesc_ore); + ore->nthresh = getfloatfield_default(L, index, "noise_threshhold", 0.); + + lua_getfield(L, index, "wherein"); + if (lua_istable(L, -1)) { + int i = lua_gettop(L); + lua_pushnil(L); + while(lua_next(L, i) != 0) { + ore->wherein_names.push_back(lua_tostring(L, -1)); + lua_pop(L, 1); + } + } else if (lua_isstring(L, -1)) { + ore->wherein_names.push_back(lua_tostring(L, -1)); + } else { + ore->wherein_names.push_back(""); + } + lua_pop(L, 1); + + lua_getfield(L, index, "noise_params"); + ore->np = read_noiseparams(L, -1); + lua_pop(L, 1); + + ore->noise = NULL; + + if (ore->clust_scarcity <= 0 || ore->clust_num_ores <= 0) { + errorstream << "register_ore: clust_scarcity and clust_num_ores" + "must be greater than 0" << std::endl; + delete ore; + return 0; + } + + emerge->ores.push_back(ore); + + verbosestream << "register_ore: ore '" << ore->ore_name + << "' registered" << std::endl; + return 0; +} + +// create_schematic(p1, p2, probability_list, filename) +int ModApiMapgen::l_create_schematic(lua_State *L) +{ + DecoSchematic dschem; + + Map *map = &(getEnv(L)->getMap()); + INodeDefManager *ndef = getServer(L)->getNodeDefManager(); + + v3s16 p1 = read_v3s16(L, 1); + v3s16 p2 = read_v3s16(L, 2); + sortBoxVerticies(p1, p2); + + std::vector<std::pair<v3s16, u8> > probability_list; + if (lua_istable(L, 3)) { + lua_pushnil(L); + while (lua_next(L, 3)) { + if (lua_istable(L, -1)) { + lua_getfield(L, -1, "pos"); + v3s16 pos = read_v3s16(L, -1); + lua_pop(L, 1); + + u8 prob = getintfield_default(L, -1, "prob", 0xFF); + probability_list.push_back(std::make_pair(pos, prob)); + } + + lua_pop(L, 1); + } + } + + dschem.filename = std::string(lua_tostring(L, 4)); + + if (!dschem.getSchematicFromMap(map, p1, p2)) { + errorstream << "create_schematic: failed to get schematic " + "from map" << std::endl; + return 0; + } + + dschem.applyProbabilities(&probability_list, p1); + + dschem.saveSchematicFile(ndef); + actionstream << "create_schematic: saved schematic file '" + << dschem.filename << "'." << std::endl; + + return 1; +} + + +// place_schematic(p, schematic, rotation, replacement) +int ModApiMapgen::l_place_schematic(lua_State *L) +{ + DecoSchematic dschem; + + Map *map = &(getEnv(L)->getMap()); + INodeDefManager *ndef = getServer(L)->getNodeDefManager(); + + v3s16 p = read_v3s16(L, 1); + if (!read_schematic(L, 2, &dschem, getServer(L))) + return 0; + + Rotation rot = ROTATE_0; + if (lua_isstring(L, 3)) + string_to_enum(es_Rotation, (int &)rot, std::string(lua_tostring(L, 3))); + + dschem.rotation = rot; + + if (lua_istable(L, 4)) { + int index = 4; + lua_pushnil(L); + while (lua_next(L, index) != 0) { + // key at index -2 and value at index -1 + lua_rawgeti(L, -1, 1); + std::string replace_from = lua_tostring(L, -1); + lua_pop(L, 1); + lua_rawgeti(L, -1, 2); + std::string replace_to = lua_tostring(L, -1); + lua_pop(L, 1); + dschem.replacements[replace_from] = replace_to; + // removes value, keeps key for next iteration + lua_pop(L, 1); + } + } + + if (!dschem.filename.empty()) { + if (!dschem.loadSchematicFile()) { + errorstream << "place_schematic: failed to load schematic file '" + << dschem.filename << "'" << std::endl; + return 0; + } + dschem.resolveNodeNames(ndef); + } + + dschem.placeStructure(map, p); + + return 1; +} + +void ModApiMapgen::Initialize(lua_State *L, int top) +{ + API_FCT(get_mapgen_object); + + API_FCT(set_mapgen_params); + + API_FCT(register_biome); + API_FCT(register_decoration); + API_FCT(register_ore); + + API_FCT(create_schematic); + API_FCT(place_schematic); +} diff --git a/src/script/lua_api/l_mapgen.h b/src/script/lua_api/l_mapgen.h new file mode 100644 index 000000000..d0da5bb13 --- /dev/null +++ b/src/script/lua_api/l_mapgen.h @@ -0,0 +1,62 @@ +/* +Minetest +Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com> + +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_MAPGEN_H_ +#define L_MAPGEN_H_ + +#include "lua_api/l_base.h" + +class ModApiMapgen : public ModApiBase { +private: + // minetest.get_mapgen_object(objectname) + // returns the requested object used during map generation + static int l_get_mapgen_object(lua_State *L); + + // minetest.set_mapgen_params(params) + // set mapgen parameters + static int l_set_mapgen_params(lua_State *L); + + // register_biome({lots of stuff}) + static int l_register_biome(lua_State *L); + + // register_decoration({lots of stuff}) + static int l_register_decoration(lua_State *L); + + // register_ore({lots of stuff}) + static int l_register_ore(lua_State *L); + + // create_schematic(p1, p2, probability_list, filename) + static int l_create_schematic(lua_State *L); + + // place_schematic(p, schematic, rotation, replacement) + static int l_place_schematic(lua_State *L); + + static struct EnumString es_BiomeTerrainType[]; + static struct EnumString es_DecorationType[]; + static struct EnumString es_MapgenObject[]; + static struct EnumString es_OreType[]; + static struct EnumString es_Rotation[]; + +public: + static void Initialize(lua_State *L, int top); +}; + + + +#endif /* L_MAPGEN_H_ */ diff --git a/src/script/lua_api/l_nodemeta.cpp b/src/script/lua_api/l_nodemeta.cpp index 511fb38ce..f9c8794d5 100644 --- a/src/script/lua_api/l_nodemeta.cpp +++ b/src/script/lua_api/l_nodemeta.cpp @@ -17,13 +17,15 @@ with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#include "cpp_api/scriptapi.h" +#include "lua_api/l_nodemeta.h" +#include "lua_api/l_internal.h" +#include "lua_api/l_inventory.h" #include "common/c_converter.h" #include "common/c_content.h" +#include "environment.h" #include "map.h" -#include "lua_api/l_nodemeta.h" -#include "common/c_internal.h" -#include "lua_api/l_inventory.h" +#include "nodemetadata.h" + /* @@ -211,7 +213,7 @@ int NodeMetaRef::l_to_table(lua_State *L) std::vector<const InventoryList*> lists = inv->getLists(); for(std::vector<const InventoryList*>::const_iterator i = lists.begin(); i != lists.end(); i++){ - push_inventory_list(inv, (*i)->getName().c_str(), L); + push_inventory_list(L, inv, (*i)->getName().c_str()); lua_setfield(L, -2, (*i)->getName().c_str()); } } @@ -257,7 +259,7 @@ int NodeMetaRef::l_from_table(lua_State *L) while(lua_next(L, inventorytable) != 0){ // key at index -2 and value at index -1 std::string name = lua_tostring(L, -2); - read_inventory_list(inv, name.c_str(), L, -1,STACK_TO_SERVER(L)); + read_inventory_list(L, -1, inv, name.c_str(), getServer(L)); lua_pop(L, 1); // removes value, keeps key for next iteration } reportMetadataChange(ref); @@ -328,5 +330,3 @@ const luaL_reg NodeMetaRef::methods[] = { luamethod(NodeMetaRef, from_table), {0,0} }; - -REGISTER_LUA_REF(NodeMetaRef); diff --git a/src/script/lua_api/l_nodemeta.h b/src/script/lua_api/l_nodemeta.h index 23404a084..ed06ff0fa 100644 --- a/src/script/lua_api/l_nodemeta.h +++ b/src/script/lua_api/l_nodemeta.h @@ -19,20 +19,17 @@ with this program; if not, write to the Free Software Foundation, Inc., #ifndef L_NODEMETA_H_ #define L_NODEMETA_H_ -extern "C" { -#include <lua.h> -#include <lauxlib.h> -} +#include "lua_api/l_base.h" +#include "irrlichttypes_bloated.h" -#include "environment.h" -#include "nodemetadata.h" +class ServerEnvironment; +class NodeMetadata; /* NodeMetaRef */ -class NodeMetaRef -{ +class NodeMetaRef : public ModApiBase { private: v3s16 m_p; ServerEnvironment *m_env; @@ -90,4 +87,4 @@ public: static void Register(lua_State *L); }; -#endif //L_NODEMETA_H_ +#endif /* L_NODEMETA_H_ */ diff --git a/src/script/lua_api/l_nodetimer.cpp b/src/script/lua_api/l_nodetimer.cpp index 60e4ec061..c81a7ebc9 100644 --- a/src/script/lua_api/l_nodetimer.cpp +++ b/src/script/lua_api/l_nodetimer.cpp @@ -17,9 +17,9 @@ with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#include "cpp_api/scriptapi.h" #include "lua_api/l_nodetimer.h" -#include "common/c_internal.h" +#include "lua_api/l_internal.h" +#include "environment.h" #include "map.h" @@ -165,5 +165,3 @@ const luaL_reg NodeTimerRef::methods[] = { luamethod(NodeTimerRef, get_elapsed), {0,0} }; - -REGISTER_LUA_REF(NodeTimerRef); diff --git a/src/script/lua_api/l_nodetimer.h b/src/script/lua_api/l_nodetimer.h index f652b4900..9f8dd21c8 100644 --- a/src/script/lua_api/l_nodetimer.h +++ b/src/script/lua_api/l_nodetimer.h @@ -20,15 +20,12 @@ with this program; if not, write to the Free Software Foundation, Inc., #ifndef L_NODETIMER_H_ #define L_NODETIMER_H_ -extern "C" { -#include <lua.h> -#include <lauxlib.h> -} +#include "lua_api/l_base.h" +#include "irr_v3d.h" -#include "environment.h" +class ServerEnvironment; -class NodeTimerRef -{ +class NodeTimerRef : public ModApiBase { private: v3s16 m_p; ServerEnvironment *m_env; diff --git a/src/script/lua_api/l_noise.cpp b/src/script/lua_api/l_noise.cpp index 43149e93c..ecbda9fad 100644 --- a/src/script/lua_api/l_noise.cpp +++ b/src/script/lua_api/l_noise.cpp @@ -18,8 +18,9 @@ with this program; if not, write to the Free Software Foundation, Inc., */ #include "lua_api/l_noise.h" -#include "common/c_internal.h" +#include "lua_api/l_internal.h" #include "common/c_converter.h" +#include "common/c_content.h" #include "log.h" // garbage collector @@ -412,7 +413,3 @@ const luaL_reg LuaPseudoRandom::methods[] = { luamethod(LuaPseudoRandom, next), {0,0} }; - -REGISTER_LUA_REF(LuaPseudoRandom); -REGISTER_LUA_REF(LuaPerlinNoiseMap); -REGISTER_LUA_REF(LuaPerlinNoise); diff --git a/src/script/lua_api/l_noise.h b/src/script/lua_api/l_noise.h index 6275ca472..65a927882 100644 --- a/src/script/lua_api/l_noise.h +++ b/src/script/lua_api/l_noise.h @@ -20,16 +20,14 @@ with this program; if not, write to the Free Software Foundation, Inc., #ifndef L_NOISE_H_ #define L_NOISE_H_ -extern "C" { -#include <lua.h> -#include <lauxlib.h> -} - +#include "lua_api/l_base.h" #include "irr_v3d.h" #include "noise.h" -class LuaPerlinNoise -{ +/* + LuaPerlinNoise +*/ +class LuaPerlinNoise : public ModApiBase { private: int seed; int octaves; @@ -62,10 +60,9 @@ public: }; /* - PerlinNoiseMap - */ -class LuaPerlinNoiseMap -{ + LuaPerlinNoiseMap +*/ +class LuaPerlinNoiseMap : public ModApiBase { private: Noise *noise; static const char className[]; @@ -95,10 +92,7 @@ public: /* LuaPseudoRandom */ - - -class LuaPseudoRandom -{ +class LuaPseudoRandom : public ModApiBase { private: PseudoRandom m_pseudo; @@ -130,6 +124,4 @@ public: static void Register(lua_State *L); }; -NoiseParams *read_noiseparams(lua_State *L, int index); - #endif /* L_NOISE_H_ */ diff --git a/src/script/lua_api/l_object.cpp b/src/script/lua_api/l_object.cpp index ee24789c5..c0da79c29 100644 --- a/src/script/lua_api/l_object.cpp +++ b/src/script/lua_api/l_object.cpp @@ -17,13 +17,12 @@ with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#include "cpp_api/scriptapi.h" -#include "common/c_converter.h" -#include "common/c_content.h" #include "lua_api/l_object.h" -#include "common/c_internal.h" +#include "lua_api/l_internal.h" #include "lua_api/l_inventory.h" #include "lua_api/l_item.h" +#include "common/c_converter.h" +#include "common/c_content.h" #include "log.h" #include "tool.h" #include "serverobject.h" @@ -275,7 +274,7 @@ int ObjectRef::l_get_inventory(lua_State *L) if(co == NULL) return 0; // Do it InventoryLocation loc = co->getInventoryLocation(); - if(STACK_TO_SERVER(L)->getInventory(loc) != NULL) + if(getServer(L)->getInventory(loc) != NULL) InvRef::create(L, loc); else lua_pushnil(L); // An object may have no inventory (nil) @@ -330,7 +329,7 @@ int ObjectRef::l_set_wielded_item(lua_State *L) ServerActiveObject *co = getobject(ref); if(co == NULL) return 0; // Do it - ItemStack item = read_item(L, 2,STACK_TO_SERVER(L)); + ItemStack item = read_item(L, 2, getServer(L)); bool success = co->setWieldedItem(item); lua_pushboolean(L, success); return 1; @@ -739,7 +738,7 @@ int ObjectRef::l_set_inventory_formspec(lua_State *L) std::string formspec = luaL_checkstring(L, 2); player->inventory_formspec = formspec; - STACK_TO_SERVER(L)->reportInventoryFormspecModified(player->getName()); + getServer(L)->reportInventoryFormspecModified(player->getName()); lua_pushboolean(L, true); return 1; } @@ -841,7 +840,7 @@ int ObjectRef::l_hud_add(lua_State *L) elem->offset = lua_istable(L, -1) ? read_v2f(L, -1) : v2f(); lua_pop(L, 1); - u32 id = STACK_TO_SERVER(L)->hudAdd(player, elem); + u32 id = getServer(L)->hudAdd(player, elem); if (id == (u32)-1) { delete elem; return 0; @@ -863,7 +862,7 @@ int ObjectRef::l_hud_remove(lua_State *L) if (!lua_isnil(L, 2)) id = lua_tonumber(L, 2); - if (!STACK_TO_SERVER(L)->hudRemove(player, id)) + if (!getServer(L)->hudRemove(player, id)) return 0; lua_pushboolean(L, true); @@ -929,7 +928,7 @@ int ObjectRef::l_hud_change(lua_State *L) value = &e->offset; } - STACK_TO_SERVER(L)->hudChange(player, id, stat, value); + getServer(L)->hudChange(player, id, stat, value); lua_pushboolean(L, true); return 1; @@ -999,7 +998,7 @@ int ObjectRef::l_hud_set_flags(lua_State *L) mask |= esp[i].num; } } - if (!STACK_TO_SERVER(L)->hudSetFlags(player, flags, mask)) + if (!getServer(L)->hudSetFlags(player, flags, mask)) return 0; lua_pushboolean(L, true); @@ -1016,7 +1015,7 @@ int ObjectRef::l_hud_set_hotbar_itemcount(lua_State *L) s32 hotbar_itemcount = lua_tonumber(L, 2); - if (!STACK_TO_SERVER(L)->hudSetHotbarItemcount(player, hotbar_itemcount)) + if (!getServer(L)->hudSetHotbarItemcount(player, hotbar_itemcount)) return 0; lua_pushboolean(L, true); @@ -1139,5 +1138,3 @@ const luaL_reg ObjectRef::methods[] = { luamethod(ObjectRef, hud_set_hotbar_itemcount), {0,0} }; - -REGISTER_LUA_REF(ObjectRef) diff --git a/src/script/lua_api/l_object.h b/src/script/lua_api/l_object.h index a82638442..b6f5cd06f 100644 --- a/src/script/lua_api/l_object.h +++ b/src/script/lua_api/l_object.h @@ -20,10 +20,8 @@ with this program; if not, write to the Free Software Foundation, Inc., #ifndef L_OBJECT_H_ #define L_OBJECT_H_ -extern "C" { -#include <lua.h> -#include <lauxlib.h> -} +#include "lua_api/l_base.h" +#include "irrlichttypes.h" class ServerActiveObject; class LuaEntitySAO; @@ -34,8 +32,7 @@ class Player; ObjectRef */ -class ObjectRef -{ +class ObjectRef : public ModApiBase { private: ServerActiveObject *m_object; diff --git a/src/script/lua_api/l_particles.cpp b/src/script/lua_api/l_particles.cpp index c291cc21e..6b009149e 100644 --- a/src/script/lua_api/l_particles.cpp +++ b/src/script/lua_api/l_particles.cpp @@ -17,22 +17,10 @@ with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#include "cpp_api/scriptapi.h" -#include "common/c_converter.h" -#include "lua_api/l_base.h" #include "lua_api/l_particles.h" +#include "lua_api/l_internal.h" +#include "common/c_converter.h" #include "server.h" -#include "common/c_internal.h" - -bool ModApiParticles::Initialize(lua_State *L, int top) { - bool retval = true; - - retval &= API_FCT(add_particle); - retval &= API_FCT(add_particlespawner); - retval &= API_FCT(delete_particlespawner); - - return retval; -} // add_particle(pos, velocity, acceleration, expirationtime, // size, collisiondetection, texture, player) @@ -146,4 +134,10 @@ int ModApiParticles::l_delete_particlespawner(lua_State *L) return 1; } -ModApiParticles modapiparticles_prototyp; +void ModApiParticles::Initialize(lua_State *L, int top) +{ + API_FCT(add_particle); + API_FCT(add_particlespawner); + API_FCT(delete_particlespawner); +} + diff --git a/src/script/lua_api/l_particles.h b/src/script/lua_api/l_particles.h index 3729f8761..c593f47e4 100644 --- a/src/script/lua_api/l_particles.h +++ b/src/script/lua_api/l_particles.h @@ -20,20 +20,18 @@ with this program; if not, write to the Free Software Foundation, Inc., #ifndef L_PARTICLES_H_ #define L_PARTICLES_H_ -extern "C" { -#include <lua.h> -#include <lauxlib.h> -} +#include "lua_api/l_base.h" class ModApiParticles : public ModApiBase { -public: - bool Initialize(lua_State *L, int top); private: static int l_add_particle(lua_State *L); static int l_add_particlespawner(lua_State *L); static int l_delete_particlespawner(lua_State *L); + +public: + static void Initialize(lua_State *L, int top); }; -#endif // L_PARTICLES_H_ +#endif /* L_PARTICLES_H_ */ diff --git a/src/script/lua_api/l_rollback.cpp b/src/script/lua_api/l_rollback.cpp new file mode 100644 index 000000000..6076399ae --- /dev/null +++ b/src/script/lua_api/l_rollback.cpp @@ -0,0 +1,80 @@ +/* +Minetest +Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com> + +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_rollback.h" +#include "lua_api/l_internal.h" +#include "common/c_converter.h" +#include "server.h" +#include "rollback.h" + + +// rollback_get_last_node_actor(p, range, seconds) -> actor, p, seconds +int ModApiRollback::l_rollback_get_last_node_actor(lua_State *L) +{ + v3s16 p = read_v3s16(L, 1); + int range = luaL_checknumber(L, 2); + int seconds = luaL_checknumber(L, 3); + Server *server = getServer(L); + IRollbackManager *rollback = server->getRollbackManager(); + v3s16 act_p; + int act_seconds = 0; + std::string actor = rollback->getLastNodeActor(p, range, seconds, &act_p, &act_seconds); + lua_pushstring(L, actor.c_str()); + push_v3s16(L, act_p); + lua_pushnumber(L, act_seconds); + return 3; +} + +// rollback_revert_actions_by(actor, seconds) -> bool, log messages +int ModApiRollback::l_rollback_revert_actions_by(lua_State *L) +{ + std::string actor = luaL_checkstring(L, 1); + int seconds = luaL_checknumber(L, 2); + Server *server = getServer(L); + IRollbackManager *rollback = server->getRollbackManager(); + std::list<RollbackAction> actions = rollback->getRevertActions(actor, seconds); + std::list<std::string> log; + bool success = server->rollbackRevertActions(actions, &log); + // Push boolean result + lua_pushboolean(L, success); + // Get the table insert function and push the log table + lua_getglobal(L, "table"); + lua_getfield(L, -1, "insert"); + int table_insert = lua_gettop(L); + lua_newtable(L); + int table = lua_gettop(L); + for(std::list<std::string>::const_iterator i = log.begin(); + i != log.end(); i++) + { + lua_pushvalue(L, table_insert); + lua_pushvalue(L, table); + lua_pushstring(L, i->c_str()); + if(lua_pcall(L, 2, 0, 0)) + script_error(L, "error: %s", lua_tostring(L, -1)); + } + lua_remove(L, -2); // Remove table + lua_remove(L, -2); // Remove insert + return 2; +} + +void ModApiRollback::Initialize(lua_State *L, int top) +{ + API_FCT(rollback_get_last_node_actor); + API_FCT(rollback_revert_actions_by); +} diff --git a/src/script/lua_api/l_rollback.h b/src/script/lua_api/l_rollback.h new file mode 100644 index 000000000..86992a47e --- /dev/null +++ b/src/script/lua_api/l_rollback.h @@ -0,0 +1,37 @@ +/* +Minetest +Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com> + +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_ROLLBACK_H_ +#define L_ROLLBACK_H_ + +#include "lua_api/l_base.h" + +class ModApiRollback : public ModApiBase { +private: + // rollback_get_last_node_actor(p, range, seconds) -> actor, p, seconds + static int l_rollback_get_last_node_actor(lua_State *L); + + // rollback_revert_actions_by(actor, seconds) -> bool, log messages + static int l_rollback_revert_actions_by(lua_State *L); + +public: + static void Initialize(lua_State *L, int top); +}; + +#endif /* L_ROLLBACK_H_ */ diff --git a/src/script/lua_api/l_server.cpp b/src/script/lua_api/l_server.cpp new file mode 100644 index 000000000..8e809c36a --- /dev/null +++ b/src/script/lua_api/l_server.cpp @@ -0,0 +1,347 @@ +/* +Minetest +Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com> + +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_server.h" +#include "lua_api/l_internal.h" +#include "common/c_converter.h" +#include "common/c_content.h" +#include "server.h" +#include "environment.h" +#include "player.h" + +// request_shutdown() +int ModApiServer::l_request_shutdown(lua_State *L) +{ + getServer(L)->requestShutdown(); + return 0; +} + +// get_server_status() +int ModApiServer::l_get_server_status(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + lua_pushstring(L, wide_to_narrow(getServer(L)->getStatusString()).c_str()); + return 1; +} + +// chat_send_all(text) +int ModApiServer::l_chat_send_all(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + const char *text = luaL_checkstring(L, 1); + // Get server from registry + Server *server = getServer(L); + // Send + server->notifyPlayers(narrow_to_wide(text)); + return 0; +} + +// chat_send_player(name, text, prepend) +int ModApiServer::l_chat_send_player(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + const char *name = luaL_checkstring(L, 1); + const char *text = luaL_checkstring(L, 2); + bool prepend = true; + + if (lua_isboolean(L, 3)) + prepend = lua_toboolean(L, 3); + + // Get server from registry + Server *server = getServer(L); + // Send + server->notifyPlayer(name, narrow_to_wide(text), prepend); + return 0; +} + +// get_player_privs(name, text) +int ModApiServer::l_get_player_privs(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + const char *name = luaL_checkstring(L, 1); + // Get server from registry + Server *server = getServer(L); + // Do it + lua_newtable(L); + int table = lua_gettop(L); + std::set<std::string> privs_s = server->getPlayerEffectivePrivs(name); + for(std::set<std::string>::const_iterator + i = privs_s.begin(); i != privs_s.end(); i++){ + lua_pushboolean(L, true); + lua_setfield(L, table, i->c_str()); + } + lua_pushvalue(L, table); + return 1; +} + +// get_player_ip() +int ModApiServer::l_get_player_ip(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + const char * name = luaL_checkstring(L, 1); + Player *player = getEnv(L)->getPlayer(name); + if(player == NULL) + { + lua_pushnil(L); // no such player + return 1; + } + try + { + Address addr = getServer(L)->getPeerAddress(getEnv(L)->getPlayer(name)->peer_id); + std::string ip_str = addr.serializeString(); + lua_pushstring(L, ip_str.c_str()); + return 1; + } + catch(con::PeerNotFoundException) // unlikely + { + dstream << __FUNCTION_NAME << ": peer was not found" << std::endl; + lua_pushnil(L); // error + return 1; + } +} + +// get_ban_list() +int ModApiServer::l_get_ban_list(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + lua_pushstring(L, getServer(L)->getBanDescription("").c_str()); + return 1; +} + +// get_ban_description() +int ModApiServer::l_get_ban_description(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + const char * ip_or_name = luaL_checkstring(L, 1); + lua_pushstring(L, getServer(L)->getBanDescription(std::string(ip_or_name)).c_str()); + return 1; +} + +// ban_player() +int ModApiServer::l_ban_player(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + const char * name = luaL_checkstring(L, 1); + Player *player = getEnv(L)->getPlayer(name); + if(player == NULL) + { + lua_pushboolean(L, false); // no such player + return 1; + } + try + { + Address addr = getServer(L)->getPeerAddress(getEnv(L)->getPlayer(name)->peer_id); + std::string ip_str = addr.serializeString(); + getServer(L)->setIpBanned(ip_str, name); + } + catch(con::PeerNotFoundException) // unlikely + { + dstream << __FUNCTION_NAME << ": peer was not found" << std::endl; + lua_pushboolean(L, false); // error + return 1; + } + lua_pushboolean(L, true); + return 1; +} + +// unban_player_or_ip() +int ModApiServer::l_unban_player_or_ip(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + const char * ip_or_name = luaL_checkstring(L, 1); + getServer(L)->unsetIpBanned(ip_or_name); + lua_pushboolean(L, true); + return 1; +} + +// show_formspec(playername,formname,formspec) +int ModApiServer::l_show_formspec(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + const char *playername = luaL_checkstring(L, 1); + const char *formname = luaL_checkstring(L, 2); + const char *formspec = luaL_checkstring(L, 3); + + if(getServer(L)->showFormspec(playername,formspec,formname)) + { + lua_pushboolean(L, true); + }else{ + lua_pushboolean(L, false); + } + return 1; +} + +// get_current_modname() +int ModApiServer::l_get_current_modname(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + lua_getfield(L, LUA_REGISTRYINDEX, "minetest_current_modname"); + return 1; +} + +// get_modpath(modname) +int ModApiServer::l_get_modpath(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + std::string modname = luaL_checkstring(L, 1); + // Do it + if(modname == "__builtin"){ + std::string path = getServer(L)->getBuiltinLuaPath(); + lua_pushstring(L, path.c_str()); + return 1; + } + const ModSpec *mod = getServer(L)->getModSpec(modname); + if(!mod){ + lua_pushnil(L); + return 1; + } + lua_pushstring(L, mod->path.c_str()); + return 1; +} + +// get_modnames() +// the returned list is sorted alphabetically for you +int ModApiServer::l_get_modnames(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + // Get a list of mods + std::list<std::string> mods_unsorted, mods_sorted; + getServer(L)->getModNames(mods_unsorted); + + // Take unsorted items from mods_unsorted and sort them into + // mods_sorted; not great performance but the number of mods on a + // server will likely be small. + for(std::list<std::string>::iterator i = mods_unsorted.begin(); + i != mods_unsorted.end(); ++i) + { + bool added = false; + for(std::list<std::string>::iterator x = mods_sorted.begin(); + x != mods_sorted.end(); ++x) + { + // I doubt anybody using Minetest will be using + // anything not ASCII based :) + if((*i).compare(*x) <= 0) + { + mods_sorted.insert(x, *i); + added = true; + break; + } + } + if(!added) + mods_sorted.push_back(*i); + } + + // Get the table insertion function from Lua. + lua_getglobal(L, "table"); + lua_getfield(L, -1, "insert"); + int insertion_func = lua_gettop(L); + + // Package them up for Lua + lua_newtable(L); + int new_table = lua_gettop(L); + std::list<std::string>::iterator i = mods_sorted.begin(); + while(i != mods_sorted.end()) + { + lua_pushvalue(L, insertion_func); + lua_pushvalue(L, new_table); + lua_pushstring(L, (*i).c_str()); + if(lua_pcall(L, 2, 0, 0) != 0) + { + script_error(L, "error: %s", lua_tostring(L, -1)); + } + ++i; + } + return 1; +} + +// get_worldpath() +int ModApiServer::l_get_worldpath(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + std::string worldpath = getServer(L)->getWorldPath(); + lua_pushstring(L, worldpath.c_str()); + return 1; +} + +// sound_play(spec, parameters) +int ModApiServer::l_sound_play(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + SimpleSoundSpec spec; + read_soundspec(L, 1, spec); + ServerSoundParams params; + read_server_sound_params(L, 2, params); + s32 handle = getServer(L)->playSound(spec, params); + lua_pushinteger(L, handle); + return 1; +} + +// sound_stop(handle) +int ModApiServer::l_sound_stop(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + int handle = luaL_checkinteger(L, 1); + getServer(L)->stopSound(handle); + return 0; +} + +// is_singleplayer() +int ModApiServer::l_is_singleplayer(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + lua_pushboolean(L, getServer(L)->isSingleplayer()); + return 1; +} + +// notify_authentication_modified(name) +int ModApiServer::l_notify_authentication_modified(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + std::string name = ""; + if(lua_isstring(L, 1)) + name = lua_tostring(L, 1); + getServer(L)->reportPrivsModified(name); + return 0; +} + +void ModApiServer::Initialize(lua_State *L, int top) +{ + API_FCT(request_shutdown); + API_FCT(get_server_status); + API_FCT(get_worldpath); + API_FCT(is_singleplayer); + + API_FCT(get_current_modname); + API_FCT(get_modpath); + API_FCT(get_modnames); + + API_FCT(chat_send_all); + API_FCT(chat_send_player); + API_FCT(show_formspec); + API_FCT(sound_play); + API_FCT(sound_stop); + + API_FCT(get_player_privs); + API_FCT(get_player_ip); + API_FCT(get_ban_list); + API_FCT(get_ban_description); + API_FCT(ban_player); + API_FCT(unban_player_or_ip); + API_FCT(notify_authentication_modified); +} diff --git a/src/script/lua_api/luaapi.h b/src/script/lua_api/l_server.h index af73625ba..21f300400 100644 --- a/src/script/lua_api/luaapi.h +++ b/src/script/lua_api/l_server.h @@ -17,48 +17,34 @@ with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#ifndef LUAAPI_H_ -#define LUAAPI_H_ +#ifndef L_SERVER_H_ +#define L_SERVER_H_ +#include "lua_api/l_base.h" -class ModApiBasic : public ModApiBase { - -public: - ModApiBasic(); - - bool Initialize(lua_State* L,int top); - +class ModApiServer : public ModApiBase { private: - // debug(text) - // Writes a line to dstream - static int l_debug(lua_State *L); - - // log([level,] text) - // Writes a line to the logger. - // The one-argument version logs to infostream. - // The two-argument version accept a log level: error, action, info, or verbose. - static int l_log(lua_State *L); - // request_shutdown() static int l_request_shutdown(lua_State *L); // get_server_status() static int l_get_server_status(lua_State *L); - // register_biome({lots of stuff}) - static int l_register_biome(lua_State *L); + // get_worldpath() + static int l_get_worldpath(lua_State *L); - // setting_set(name, value) - static int l_setting_set(lua_State *L); + // is_singleplayer() + static int l_is_singleplayer(lua_State *L); - // setting_get(name) - static int l_setting_get(lua_State *L); + // get_current_modname() + static int l_get_current_modname(lua_State *L); - // setting_getbool(name) - static int l_setting_getbool(lua_State *L); + // get_modpath(modname) + static int l_get_modpath(lua_State *L); - // setting_save() - static int l_setting_save(lua_State *L); + // get_modnames() + // the returned list is sorted alphabetically for you + static int l_get_modnames(lua_State *L); // chat_send_all(text) static int l_chat_send_all(lua_State *L); @@ -66,6 +52,15 @@ private: // chat_send_player(name, text) static int l_chat_send_player(lua_State *L); + // show_formspec(playername,formname,formspec) + static int l_show_formspec(lua_State *L); + + // sound_play(spec, parameters) + static int l_sound_play(lua_State *L); + + // sound_stop(handle) + static int l_sound_stop(lua_State *L); + // get_player_privs(name, text) static int l_get_player_privs(lua_State *L); @@ -84,67 +79,12 @@ private: // unban_player_or_ip() static int l_unban_player_or_ip(lua_State *L); - // show_formspec(playername,formname,formspec) - static int l_show_formspec(lua_State *L); - - // get_dig_params(groups, tool_capabilities[, time_from_last_punch]) - static int l_get_dig_params(lua_State *L); - - // get_hit_params(groups, tool_capabilities[, time_from_last_punch]) - static int l_get_hit_params(lua_State *L); - - // get_current_modname() - static int l_get_current_modname(lua_State *L); - - // get_modpath(modname) - static int l_get_modpath(lua_State *L); - - // get_modnames() - // the returned list is sorted alphabetically for you - static int l_get_modnames(lua_State *L); - - // get_worldpath() - static int l_get_worldpath(lua_State *L); - - // sound_play(spec, parameters) - static int l_sound_play(lua_State *L); - - // sound_stop(handle) - static int l_sound_stop(lua_State *L); - - // is_singleplayer() - static int l_is_singleplayer(lua_State *L); - - // get_password_hash(name, raw_password) - static int l_get_password_hash(lua_State *L); - // notify_authentication_modified(name) static int l_notify_authentication_modified(lua_State *L); - // rollback_get_last_node_actor(p, range, seconds) -> actor, p, seconds - static int l_rollback_get_last_node_actor(lua_State *L); - - // rollback_revert_actions_by(actor, seconds) -> bool, log messages - static int l_rollback_revert_actions_by(lua_State *L); - - // register_ore(oredesc) - static int l_register_ore(lua_State *L); - - // register_decoration(deco) - static int l_register_decoration(lua_State *L); - - // create_schematic(p1, p2, filename) - static int l_create_schematic(lua_State *L); - - // place_schematic(p, filename, rotation) - static int l_place_schematic(lua_State *L); - - static struct EnumString es_OreType[]; - static struct EnumString es_DecorationType[]; - static struct EnumString es_Rotation[]; +public: + static void Initialize(lua_State *L, int top); }; - - -#endif /* LUAAPI_H_ */ +#endif /* L_SERVER_H_ */ diff --git a/src/script/lua_api/l_util.cpp b/src/script/lua_api/l_util.cpp new file mode 100644 index 000000000..0e4de9eee --- /dev/null +++ b/src/script/lua_api/l_util.cpp @@ -0,0 +1,199 @@ +/* +Minetest +Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com> + +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_util.h" +#include "lua_api/l_internal.h" +#include "common/c_converter.h" +#include "common/c_content.h" +#include "debug.h" +#include "log.h" +#include "tool.h" +#include "settings.h" +#include "main.h" //required for g_settings, g_settings_path + +// debug(...) +// Writes a line to dstream +int ModApiUtil::l_debug(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + // Handle multiple parameters to behave like standard lua print() + int n = lua_gettop(L); + lua_getglobal(L, "tostring"); + for (int i = 1; i <= n; i++) { + /* + Call tostring(i-th argument). + This is what print() does, and it behaves a bit + differently from directly calling lua_tostring. + */ + lua_pushvalue(L, -1); /* function to be called */ + lua_pushvalue(L, i); /* value to print */ + lua_call(L, 1, 1); + const char *s = lua_tostring(L, -1); + if (i>1) + dstream << "\t"; + if (s) + dstream << s; + lua_pop(L, 1); + } + dstream << std::endl; + return 0; +} + +// log([level,] text) +// Writes a line to the logger. +// The one-argument version logs to infostream. +// The two-argument version accept a log level: error, action, info, or verbose. +int ModApiUtil::l_log(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + std::string text; + LogMessageLevel level = LMT_INFO; + if (lua_isnone(L, 2)) { + text = lua_tostring(L, 1); + } + else { + std::string levelname = luaL_checkstring(L, 1); + text = luaL_checkstring(L, 2); + if(levelname == "error") + level = LMT_ERROR; + else if(levelname == "action") + level = LMT_ACTION; + else if(levelname == "verbose") + level = LMT_VERBOSE; + } + log_printline(level, text); + return 0; +} + +// setting_set(name, value) +int ModApiUtil::l_setting_set(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + const char *name = luaL_checkstring(L, 1); + const char *value = luaL_checkstring(L, 2); + g_settings->set(name, value); + return 0; +} + +// setting_get(name) +int ModApiUtil::l_setting_get(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + const char *name = luaL_checkstring(L, 1); + try{ + std::string value = g_settings->get(name); + lua_pushstring(L, value.c_str()); + } catch(SettingNotFoundException &e){ + lua_pushnil(L); + } + return 1; +} + +// setting_setbool(name) +int ModApiUtil::l_setting_setbool(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + const char *name = luaL_checkstring(L, 1); + bool value = lua_toboolean(L, 2); + g_settings->setBool(name, value); + return 0; +} + +// setting_getbool(name) +int ModApiUtil::l_setting_getbool(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + const char *name = luaL_checkstring(L, 1); + try{ + bool value = g_settings->getBool(name); + lua_pushboolean(L, value); + } catch(SettingNotFoundException &e){ + lua_pushnil(L); + } + return 1; +} + +// setting_save() +int ModApiUtil::l_setting_save(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + if(g_settings_path != "") + g_settings->updateConfigFile(g_settings_path.c_str()); + return 0; +} + +// get_dig_params(groups, tool_capabilities[, time_from_last_punch]) +int ModApiUtil::l_get_dig_params(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + std::map<std::string, int> groups; + read_groups(L, 1, groups); + ToolCapabilities tp = read_tool_capabilities(L, 2); + if(lua_isnoneornil(L, 3)) + push_dig_params(L, getDigParams(groups, &tp)); + else + push_dig_params(L, getDigParams(groups, &tp, + luaL_checknumber(L, 3))); + return 1; +} + +// get_hit_params(groups, tool_capabilities[, time_from_last_punch]) +int ModApiUtil::l_get_hit_params(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + std::map<std::string, int> groups; + read_groups(L, 1, groups); + ToolCapabilities tp = read_tool_capabilities(L, 2); + if(lua_isnoneornil(L, 3)) + push_hit_params(L, getHitParams(groups, &tp)); + else + push_hit_params(L, getHitParams(groups, &tp, + luaL_checknumber(L, 3))); + return 1; +} + +// get_password_hash(name, raw_password) +int ModApiUtil::l_get_password_hash(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + std::string name = luaL_checkstring(L, 1); + std::string raw_password = luaL_checkstring(L, 2); + std::string hash = translatePassword(name, + narrow_to_wide(raw_password)); + lua_pushstring(L, hash.c_str()); + return 1; +} + +void ModApiUtil::Initialize(lua_State *L, int top) +{ + API_FCT(debug); + API_FCT(log); + + API_FCT(setting_set); + API_FCT(setting_get); + API_FCT(setting_setbool); + API_FCT(setting_getbool); + API_FCT(setting_save); + + API_FCT(get_dig_params); + API_FCT(get_hit_params); + + API_FCT(get_password_hash); +} + diff --git a/src/script/lua_api/l_util.h b/src/script/lua_api/l_util.h new file mode 100644 index 000000000..b102e315b --- /dev/null +++ b/src/script/lua_api/l_util.h @@ -0,0 +1,76 @@ +/* +Minetest +Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com> + +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_UTIL_H_ +#define L_UTIL_H_ + +#include "lua_api/l_base.h" + +class ModApiUtil : public ModApiBase { +private: + /* + NOTE: + The functions in this module are available through + minetest.<function> in the in-game API as well as + engine.<function> in the mainmenu API + + All functions that don't require either a Server or + GUIEngine instance should be in here. + */ + + // debug(text) + // Writes a line to dstream + static int l_debug(lua_State *L); + + // log([level,] text) + // Writes a line to the logger. + // The one-argument version logs to infostream. + // The two-argument version accept a log level: error, action, info, or verbose. + static int l_log(lua_State *L); + + // setting_set(name, value) + static int l_setting_set(lua_State *L); + + // setting_get(name) + static int l_setting_get(lua_State *L); + + // setting_setbool(name, value) + static int l_setting_setbool(lua_State *L); + + // setting_getbool(name) + static int l_setting_getbool(lua_State *L); + + // setting_save() + static int l_setting_save(lua_State *L); + + // get_dig_params(groups, tool_capabilities[, time_from_last_punch]) + static int l_get_dig_params(lua_State *L); + + // get_hit_params(groups, tool_capabilities[, time_from_last_punch]) + static int l_get_hit_params(lua_State *L); + + // get_password_hash(name, raw_password) + static int l_get_password_hash(lua_State *L); + +public: + static void Initialize(lua_State *L, int top); + +}; + +#endif /* L_UTIL_H_ */ diff --git a/src/script/lua_api/l_vmanip.cpp b/src/script/lua_api/l_vmanip.cpp index 195682579..1e9cc350f 100644 --- a/src/script/lua_api/l_vmanip.cpp +++ b/src/script/lua_api/l_vmanip.cpp @@ -18,16 +18,14 @@ with this program; if not, write to the Free Software Foundation, Inc., */ -#include "lua_api/l_base.h" #include "lua_api/l_vmanip.h" - -/////// - -#include "cpp_api/scriptapi.h" +#include "lua_api/l_internal.h" #include "common/c_converter.h" -#include "server.h" #include "emerge.h" -#include "common/c_internal.h" +#include "environment.h" +#include "map.h" +#include "server.h" +#include "mapgen.h" // garbage collector int LuaVoxelManip::gc_object(lua_State *L) @@ -111,9 +109,13 @@ int LuaVoxelManip::l_write_to_map(lua_State *L) int LuaVoxelManip::l_update_liquids(lua_State *L) { LuaVoxelManip *o = checkobject(L, 1); - - INodeDefManager *ndef = STACK_TO_SERVER(L)->getNodeDefManager(); - Map *map = &(get_scriptapi(L)->getEnv()->getMap()); + + Environment *env = getEnv(L); + if (!env) + return 0; + + Map *map = &(env->getMap()); + INodeDefManager *ndef = getServer(L)->getNodeDefManager(); ManualMapVoxelManipulator *vm = o->vm; Mapgen mg; @@ -134,8 +136,8 @@ int LuaVoxelManip::l_calc_lighting(lua_State *L) if (!o->is_mapgen_vm) return 0; - INodeDefManager *ndef = STACK_TO_SERVER(L)->getNodeDefManager(); - EmergeManager *emerge = STACK_TO_SERVER(L)->getEmergeManager(); + INodeDefManager *ndef = getServer(L)->getNodeDefManager(); + EmergeManager *emerge = getServer(L)->getEmergeManager(); ManualMapVoxelManipulator *vm = o->vm; Mapgen mg; @@ -182,13 +184,18 @@ int LuaVoxelManip::l_update_map(lua_State *L) if (o->is_mapgen_vm) return 0; + Environment *env = getEnv(L); + if (!env) + return 0; + + Map *map = &(env->getMap()); + // TODO: Optimize this by using Mapgen::calcLighting() instead std::map<v3s16, MapBlock *> lighting_mblocks; std::map<v3s16, MapBlock *> *mblocks = &o->modified_blocks; lighting_mblocks.insert(mblocks->begin(), mblocks->end()); - Map *map = &(get_scriptapi(L)->getEnv()->getMap()); map->updateLighting(lighting_mblocks, *mblocks); MapEditEvent event; @@ -228,7 +235,7 @@ int LuaVoxelManip::create_object(lua_State *L) { NO_MAP_LOCK_REQUIRED; - Environment *env = get_scriptapi(L)->getEnv(); + Environment *env = getEnv(L); if (!env) return 0; @@ -278,7 +285,7 @@ void LuaVoxelManip::Register(lua_State *L) luaL_openlib(L, 0, methods, 0); // fill methodtable lua_pop(L, 1); // drop methodtable - // Can be created from Lua (VoxelManip() + // Can be created from Lua (VoxelManip()) lua_register(L, className, create_object); } @@ -294,5 +301,3 @@ const luaL_reg LuaVoxelManip::methods[] = { luamethod(LuaVoxelManip, set_lighting), {0,0} }; - -REGISTER_LUA_REF(LuaVoxelManip); diff --git a/src/script/lua_api/l_vmanip.h b/src/script/lua_api/l_vmanip.h index a7791e56b..d2f035a3e 100644 --- a/src/script/lua_api/l_vmanip.h +++ b/src/script/lua_api/l_vmanip.h @@ -20,19 +20,18 @@ with this program; if not, write to the Free Software Foundation, Inc., #ifndef L_VMANIP_H_ #define L_VMANIP_H_ -extern "C" { -#include <lua.h> -#include <lauxlib.h> -} - +#include "lua_api/l_base.h" #include "irr_v3d.h" -#include "map.h" +#include <map> + +class Map; +class MapBlock; +class ManualMapVoxelManipulator; /* VoxelManip */ -class LuaVoxelManip -{ +class LuaVoxelManip : public ModApiBase { private: ManualMapVoxelManipulator *vm; std::map<v3s16, MapBlock *> modified_blocks; @@ -67,4 +66,4 @@ public: static void Register(lua_State *L); }; -#endif // L_VMANIP_H_ +#endif /* L_VMANIP_H_ */ diff --git a/src/script/lua_api/luaapi.cpp b/src/script/lua_api/luaapi.cpp deleted file mode 100644 index 26fb0c318..000000000 --- a/src/script/lua_api/luaapi.cpp +++ /dev/null @@ -1,955 +0,0 @@ -/* -Minetest -Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com> - -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. -*/ - -extern "C" { -#include "lua.h" -#include "lauxlib.h" -} - -#include "lua_api/l_base.h" -#include "common/c_internal.h" -#include "server.h" -#include "common/c_converter.h" -#include "common/c_content.h" -#include "lua_api/luaapi.h" -#include "settings.h" -#include "tool.h" -#include "rollback.h" -#include "log.h" -#include "emerge.h" -#include "main.h" //required for g_settings - -struct EnumString ModApiBasic::es_OreType[] = -{ - {ORE_SCATTER, "scatter"}, - {ORE_SHEET, "sheet"}, - {ORE_CLAYLIKE, "claylike"}, - {0, NULL}, -}; - -struct EnumString ModApiBasic::es_DecorationType[] = -{ - {DECO_SIMPLE, "simple"}, - {DECO_SCHEMATIC, "schematic"}, - {DECO_LSYSTEM, "lsystem"}, - {0, NULL}, -}; - -struct EnumString ModApiBasic::es_Rotation[] = -{ - {ROTATE_0, "0"}, - {ROTATE_90, "90"}, - {ROTATE_180, "180"}, - {ROTATE_270, "270"}, - {ROTATE_RAND, "random"}, - {0, NULL}, -}; - - -ModApiBasic::ModApiBasic() : ModApiBase() { -} - -bool ModApiBasic::Initialize(lua_State* L,int top) { - - bool retval = true; - - retval &= API_FCT(debug); - retval &= API_FCT(log); - retval &= API_FCT(request_shutdown); - retval &= API_FCT(get_server_status); - - retval &= API_FCT(register_biome); - - retval &= API_FCT(setting_set); - retval &= API_FCT(setting_get); - retval &= API_FCT(setting_getbool); - retval &= API_FCT(setting_save); - - retval &= API_FCT(chat_send_all); - retval &= API_FCT(chat_send_player); - retval &= API_FCT(show_formspec); - - retval &= API_FCT(get_player_privs); - retval &= API_FCT(get_player_ip); - retval &= API_FCT(get_ban_list); - retval &= API_FCT(get_ban_description); - retval &= API_FCT(ban_player); - retval &= API_FCT(unban_player_or_ip); - retval &= API_FCT(get_password_hash); - retval &= API_FCT(notify_authentication_modified); - - retval &= API_FCT(get_dig_params); - retval &= API_FCT(get_hit_params); - - retval &= API_FCT(get_current_modname); - retval &= API_FCT(get_modpath); - retval &= API_FCT(get_modnames); - - retval &= API_FCT(get_worldpath); - retval &= API_FCT(is_singleplayer); - retval &= API_FCT(sound_play); - retval &= API_FCT(sound_stop); - - retval &= API_FCT(rollback_get_last_node_actor); - retval &= API_FCT(rollback_revert_actions_by); - - retval &= API_FCT(register_ore); - retval &= API_FCT(register_decoration); - retval &= API_FCT(create_schematic); - retval &= API_FCT(place_schematic); - - return retval; -} - -// debug(...) -// Writes a line to dstream -int ModApiBasic::l_debug(lua_State *L) -{ - NO_MAP_LOCK_REQUIRED; - // Handle multiple parameters to behave like standard lua print() - int n = lua_gettop(L); - lua_getglobal(L, "tostring"); - for(int i = 1; i <= n; i++){ - /* - Call tostring(i-th argument). - This is what print() does, and it behaves a bit - differently from directly calling lua_tostring. - */ - lua_pushvalue(L, -1); /* function to be called */ - lua_pushvalue(L, i); /* value to print */ - lua_call(L, 1, 1); - const char *s = lua_tostring(L, -1); - if(i>1) - dstream << "\t"; - if(s) - dstream << s; - lua_pop(L, 1); - } - dstream << std::endl; - return 0; -} - -// log([level,] text) -// Writes a line to the logger. -// The one-argument version logs to infostream. -// The two-argument version accept a log level: error, action, info, or verbose. -int ModApiBasic::l_log(lua_State *L) -{ - NO_MAP_LOCK_REQUIRED; - std::string text; - LogMessageLevel level = LMT_INFO; - if(lua_isnone(L, 2)) - { - text = lua_tostring(L, 1); - } - else - { - std::string levelname = luaL_checkstring(L, 1); - text = luaL_checkstring(L, 2); - if(levelname == "error") - level = LMT_ERROR; - else if(levelname == "action") - level = LMT_ACTION; - else if(levelname == "verbose") - level = LMT_VERBOSE; - } - log_printline(level, text); - return 0; -} - -// request_shutdown() -int ModApiBasic::l_request_shutdown(lua_State *L) -{ - getServer(L)->requestShutdown(); - return 0; -} - -// get_server_status() -int ModApiBasic::l_get_server_status(lua_State *L) -{ - NO_MAP_LOCK_REQUIRED; - lua_pushstring(L, wide_to_narrow(getServer(L)->getStatusString()).c_str()); - return 1; -} - -// register_biome({lots of stuff}) -int ModApiBasic::l_register_biome(lua_State *L) -{ - int index = 1; - luaL_checktype(L, index, LUA_TTABLE); - - BiomeDefManager *bmgr = getServer(L)->getEmergeManager()->biomedef; - if (!bmgr) { - verbosestream << "register_biome: BiomeDefManager not active" << std::endl; - return 0; - } - - enum BiomeTerrainType terrain = (BiomeTerrainType)getenumfield(L, index, - "terrain_type", es_BiomeTerrainType, BIOME_TERRAIN_NORMAL); - Biome *b = bmgr->createBiome(terrain); - - b->name = getstringfield_default(L, index, "name", - "<no name>"); - b->nname_top = getstringfield_default(L, index, "node_top", - "mapgen_dirt_with_grass"); - b->nname_filler = getstringfield_default(L, index, "node_filler", - "mapgen_dirt"); - b->nname_water = getstringfield_default(L, index, "node_water", - "mapgen_water_source"); - b->nname_dust = getstringfield_default(L, index, "node_dust", - "air"); - b->nname_dust_water = getstringfield_default(L, index, "node_dust_water", - "mapgen_water_source"); - - b->depth_top = getintfield_default(L, index, "depth_top", 1); - b->depth_filler = getintfield_default(L, index, "depth_filler", 3); - b->height_min = getintfield_default(L, index, "height_min", 0); - b->height_max = getintfield_default(L, index, "height_max", 0); - b->heat_point = getfloatfield_default(L, index, "heat_point", 0.); - b->humidity_point = getfloatfield_default(L, index, "humidity_point", 0.); - - b->flags = 0; //reserved - b->c_top = CONTENT_IGNORE; - b->c_filler = CONTENT_IGNORE; - b->c_water = CONTENT_IGNORE; - b->c_dust = CONTENT_IGNORE; - b->c_dust_water = CONTENT_IGNORE; - - verbosestream << "register_biome: " << b->name << std::endl; - bmgr->addBiome(b); - - return 0; -} - -// setting_set(name, value) -int ModApiBasic::l_setting_set(lua_State *L) -{ - NO_MAP_LOCK_REQUIRED; - const char *name = luaL_checkstring(L, 1); - const char *value = luaL_checkstring(L, 2); - g_settings->set(name, value); - return 0; -} - -// setting_get(name) -int ModApiBasic::l_setting_get(lua_State *L) -{ - NO_MAP_LOCK_REQUIRED; - const char *name = luaL_checkstring(L, 1); - try{ - std::string value = g_settings->get(name); - lua_pushstring(L, value.c_str()); - } catch(SettingNotFoundException &e){ - lua_pushnil(L); - } - return 1; -} - -// setting_getbool(name) -int ModApiBasic::l_setting_getbool(lua_State *L) -{ - NO_MAP_LOCK_REQUIRED; - const char *name = luaL_checkstring(L, 1); - try{ - bool value = g_settings->getBool(name); - lua_pushboolean(L, value); - } catch(SettingNotFoundException &e){ - lua_pushnil(L); - } - return 1; -} - -// setting_save() -int ModApiBasic::l_setting_save(lua_State *L) -{ - NO_MAP_LOCK_REQUIRED; - getServer(L)->saveConfig(); - return 0; -} - -// chat_send_all(text) -int ModApiBasic::l_chat_send_all(lua_State *L) -{ - NO_MAP_LOCK_REQUIRED; - const char *text = luaL_checkstring(L, 1); - // Get server from registry - Server *server = getServer(L); - // Send - server->notifyPlayers(narrow_to_wide(text)); - return 0; -} - -// chat_send_player(name, text, prepend) -int ModApiBasic::l_chat_send_player(lua_State *L) -{ - NO_MAP_LOCK_REQUIRED; - const char *name = luaL_checkstring(L, 1); - const char *text = luaL_checkstring(L, 2); - bool prepend = true; - - if (lua_isboolean(L, 3)) - prepend = lua_toboolean(L, 3); - - // Get server from registry - Server *server = getServer(L); - // Send - server->notifyPlayer(name, narrow_to_wide(text), prepend); - return 0; -} - -// get_player_privs(name, text) -int ModApiBasic::l_get_player_privs(lua_State *L) -{ - NO_MAP_LOCK_REQUIRED; - const char *name = luaL_checkstring(L, 1); - // Get server from registry - Server *server = getServer(L); - // Do it - lua_newtable(L); - int table = lua_gettop(L); - std::set<std::string> privs_s = server->getPlayerEffectivePrivs(name); - for(std::set<std::string>::const_iterator - i = privs_s.begin(); i != privs_s.end(); i++){ - lua_pushboolean(L, true); - lua_setfield(L, table, i->c_str()); - } - lua_pushvalue(L, table); - return 1; -} - -// get_player_ip() -int ModApiBasic::l_get_player_ip(lua_State *L) -{ - NO_MAP_LOCK_REQUIRED; - const char * name = luaL_checkstring(L, 1); - Player *player = getEnv(L)->getPlayer(name); - if(player == NULL) - { - lua_pushnil(L); // no such player - return 1; - } - try - { - Address addr = getServer(L)->getPeerAddress(getEnv(L)->getPlayer(name)->peer_id); - std::string ip_str = addr.serializeString(); - lua_pushstring(L, ip_str.c_str()); - return 1; - } - catch(con::PeerNotFoundException) // unlikely - { - dstream << __FUNCTION_NAME << ": peer was not found" << std::endl; - lua_pushnil(L); // error - return 1; - } -} - -// get_ban_list() -int ModApiBasic::l_get_ban_list(lua_State *L) -{ - NO_MAP_LOCK_REQUIRED; - lua_pushstring(L, getServer(L)->getBanDescription("").c_str()); - return 1; -} - -// get_ban_description() -int ModApiBasic::l_get_ban_description(lua_State *L) -{ - NO_MAP_LOCK_REQUIRED; - const char * ip_or_name = luaL_checkstring(L, 1); - lua_pushstring(L, getServer(L)->getBanDescription(std::string(ip_or_name)).c_str()); - return 1; -} - -// ban_player() -int ModApiBasic::l_ban_player(lua_State *L) -{ - NO_MAP_LOCK_REQUIRED; - const char * name = luaL_checkstring(L, 1); - Player *player = getEnv(L)->getPlayer(name); - if(player == NULL) - { - lua_pushboolean(L, false); // no such player - return 1; - } - try - { - Address addr = getServer(L)->getPeerAddress(getEnv(L)->getPlayer(name)->peer_id); - std::string ip_str = addr.serializeString(); - getServer(L)->setIpBanned(ip_str, name); - } - catch(con::PeerNotFoundException) // unlikely - { - dstream << __FUNCTION_NAME << ": peer was not found" << std::endl; - lua_pushboolean(L, false); // error - return 1; - } - lua_pushboolean(L, true); - return 1; -} - -// unban_player_or_ip() -int ModApiBasic::l_unban_player_or_ip(lua_State *L) -{ - NO_MAP_LOCK_REQUIRED; - const char * ip_or_name = luaL_checkstring(L, 1); - getServer(L)->unsetIpBanned(ip_or_name); - lua_pushboolean(L, true); - return 1; -} - -// show_formspec(playername,formname,formspec) -int ModApiBasic::l_show_formspec(lua_State *L) -{ - NO_MAP_LOCK_REQUIRED; - const char *playername = luaL_checkstring(L, 1); - const char *formname = luaL_checkstring(L, 2); - const char *formspec = luaL_checkstring(L, 3); - - if(getServer(L)->showFormspec(playername,formspec,formname)) - { - lua_pushboolean(L, true); - }else{ - lua_pushboolean(L, false); - } - return 1; -} - -// get_dig_params(groups, tool_capabilities[, time_from_last_punch]) -int ModApiBasic::l_get_dig_params(lua_State *L) -{ - NO_MAP_LOCK_REQUIRED; - std::map<std::string, int> groups; - read_groups(L, 1, groups); - ToolCapabilities tp = read_tool_capabilities(L, 2); - if(lua_isnoneornil(L, 3)) - push_dig_params(L, getDigParams(groups, &tp)); - else - push_dig_params(L, getDigParams(groups, &tp, - luaL_checknumber(L, 3))); - return 1; -} - -// get_hit_params(groups, tool_capabilities[, time_from_last_punch]) -int ModApiBasic::l_get_hit_params(lua_State *L) -{ - NO_MAP_LOCK_REQUIRED; - std::map<std::string, int> groups; - read_groups(L, 1, groups); - ToolCapabilities tp = read_tool_capabilities(L, 2); - if(lua_isnoneornil(L, 3)) - push_hit_params(L, getHitParams(groups, &tp)); - else - push_hit_params(L, getHitParams(groups, &tp, - luaL_checknumber(L, 3))); - return 1; -} - -// get_current_modname() -int ModApiBasic::l_get_current_modname(lua_State *L) -{ - NO_MAP_LOCK_REQUIRED; - lua_getfield(L, LUA_REGISTRYINDEX, "minetest_current_modname"); - return 1; -} - -// get_modpath(modname) -int ModApiBasic::l_get_modpath(lua_State *L) -{ - NO_MAP_LOCK_REQUIRED; - std::string modname = luaL_checkstring(L, 1); - // Do it - if(modname == "__builtin"){ - std::string path = getServer(L)->getBuiltinLuaPath(); - lua_pushstring(L, path.c_str()); - return 1; - } - const ModSpec *mod = getServer(L)->getModSpec(modname); - if(!mod){ - lua_pushnil(L); - return 1; - } - lua_pushstring(L, mod->path.c_str()); - return 1; -} - -// get_modnames() -// the returned list is sorted alphabetically for you -int ModApiBasic::l_get_modnames(lua_State *L) -{ - NO_MAP_LOCK_REQUIRED; - // Get a list of mods - std::list<std::string> mods_unsorted, mods_sorted; - getServer(L)->getModNames(mods_unsorted); - - // Take unsorted items from mods_unsorted and sort them into - // mods_sorted; not great performance but the number of mods on a - // server will likely be small. - for(std::list<std::string>::iterator i = mods_unsorted.begin(); - i != mods_unsorted.end(); ++i) - { - bool added = false; - for(std::list<std::string>::iterator x = mods_sorted.begin(); - x != mods_sorted.end(); ++x) - { - // I doubt anybody using Minetest will be using - // anything not ASCII based :) - if((*i).compare(*x) <= 0) - { - mods_sorted.insert(x, *i); - added = true; - break; - } - } - if(!added) - mods_sorted.push_back(*i); - } - - // Get the table insertion function from Lua. - lua_getglobal(L, "table"); - lua_getfield(L, -1, "insert"); - int insertion_func = lua_gettop(L); - - // Package them up for Lua - lua_newtable(L); - int new_table = lua_gettop(L); - std::list<std::string>::iterator i = mods_sorted.begin(); - while(i != mods_sorted.end()) - { - lua_pushvalue(L, insertion_func); - lua_pushvalue(L, new_table); - lua_pushstring(L, (*i).c_str()); - if(lua_pcall(L, 2, 0, 0) != 0) - { - script_error(L, "error: %s", lua_tostring(L, -1)); - } - ++i; - } - return 1; -} - -// get_worldpath() -int ModApiBasic::l_get_worldpath(lua_State *L) -{ - NO_MAP_LOCK_REQUIRED; - std::string worldpath = getServer(L)->getWorldPath(); - lua_pushstring(L, worldpath.c_str()); - return 1; -} - -// sound_play(spec, parameters) -int ModApiBasic::l_sound_play(lua_State *L) -{ - NO_MAP_LOCK_REQUIRED; - SimpleSoundSpec spec; - read_soundspec(L, 1, spec); - ServerSoundParams params; - read_server_sound_params(L, 2, params); - s32 handle = getServer(L)->playSound(spec, params); - lua_pushinteger(L, handle); - return 1; -} - -// sound_stop(handle) -int ModApiBasic::l_sound_stop(lua_State *L) -{ - NO_MAP_LOCK_REQUIRED; - int handle = luaL_checkinteger(L, 1); - getServer(L)->stopSound(handle); - return 0; -} - -// is_singleplayer() -int ModApiBasic::l_is_singleplayer(lua_State *L) -{ - NO_MAP_LOCK_REQUIRED; - lua_pushboolean(L, getServer(L)->isSingleplayer()); - return 1; -} - -// get_password_hash(name, raw_password) -int ModApiBasic::l_get_password_hash(lua_State *L) -{ - NO_MAP_LOCK_REQUIRED; - std::string name = luaL_checkstring(L, 1); - std::string raw_password = luaL_checkstring(L, 2); - std::string hash = translatePassword(name, - narrow_to_wide(raw_password)); - lua_pushstring(L, hash.c_str()); - return 1; -} - -// notify_authentication_modified(name) -int ModApiBasic::l_notify_authentication_modified(lua_State *L) -{ - NO_MAP_LOCK_REQUIRED; - std::string name = ""; - if(lua_isstring(L, 1)) - name = lua_tostring(L, 1); - getServer(L)->reportPrivsModified(name); - return 0; -} - -// rollback_get_last_node_actor(p, range, seconds) -> actor, p, seconds -int ModApiBasic::l_rollback_get_last_node_actor(lua_State *L) -{ - v3s16 p = read_v3s16(L, 1); - int range = luaL_checknumber(L, 2); - int seconds = luaL_checknumber(L, 3); - Server *server = getServer(L); - IRollbackManager *rollback = server->getRollbackManager(); - v3s16 act_p; - int act_seconds = 0; - std::string actor = rollback->getLastNodeActor(p, range, seconds, &act_p, &act_seconds); - lua_pushstring(L, actor.c_str()); - push_v3s16(L, act_p); - lua_pushnumber(L, act_seconds); - return 3; -} - -// rollback_revert_actions_by(actor, seconds) -> bool, log messages -int ModApiBasic::l_rollback_revert_actions_by(lua_State *L) -{ - std::string actor = luaL_checkstring(L, 1); - int seconds = luaL_checknumber(L, 2); - Server *server = getServer(L); - IRollbackManager *rollback = server->getRollbackManager(); - std::list<RollbackAction> actions = rollback->getRevertActions(actor, seconds); - std::list<std::string> log; - bool success = server->rollbackRevertActions(actions, &log); - // Push boolean result - lua_pushboolean(L, success); - // Get the table insert function and push the log table - lua_getglobal(L, "table"); - lua_getfield(L, -1, "insert"); - int table_insert = lua_gettop(L); - lua_newtable(L); - int table = lua_gettop(L); - for(std::list<std::string>::const_iterator i = log.begin(); - i != log.end(); i++) - { - lua_pushvalue(L, table_insert); - lua_pushvalue(L, table); - lua_pushstring(L, i->c_str()); - if(lua_pcall(L, 2, 0, 0)) - script_error(L, "error: %s", lua_tostring(L, -1)); - } - lua_remove(L, -2); // Remove table - lua_remove(L, -2); // Remove insert - return 2; -} - -int ModApiBasic::l_register_ore(lua_State *L) -{ - int index = 1; - luaL_checktype(L, index, LUA_TTABLE); - - EmergeManager *emerge = getServer(L)->getEmergeManager(); - - enum OreType oretype = (OreType)getenumfield(L, index, - "ore_type", es_OreType, ORE_SCATTER); - Ore *ore = createOre(oretype); - if (!ore) { - errorstream << "register_ore: ore_type " - << oretype << " not implemented"; - return 0; - } - - ore->ore_name = getstringfield_default(L, index, "ore", ""); - ore->ore_param2 = (u8)getintfield_default(L, index, "ore_param2", 0); - ore->clust_scarcity = getintfield_default(L, index, "clust_scarcity", 1); - ore->clust_num_ores = getintfield_default(L, index, "clust_num_ores", 1); - ore->clust_size = getintfield_default(L, index, "clust_size", 0); - ore->height_min = getintfield_default(L, index, "height_min", 0); - ore->height_max = getintfield_default(L, index, "height_max", 0); - ore->flags = getflagsfield(L, index, "flags", flagdesc_ore); - ore->nthresh = getfloatfield_default(L, index, "noise_threshhold", 0.); - - lua_getfield(L, index, "wherein"); - if (lua_istable(L, -1)) { - int i = lua_gettop(L); - lua_pushnil(L); - while(lua_next(L, i) != 0) { - ore->wherein_names.push_back(lua_tostring(L, -1)); - lua_pop(L, 1); - } - } else if (lua_isstring(L, -1)) { - ore->wherein_names.push_back(lua_tostring(L, -1)); - } else { - ore->wherein_names.push_back(""); - } - lua_pop(L, 1); - - lua_getfield(L, index, "noise_params"); - ore->np = read_noiseparams(L, -1); - lua_pop(L, 1); - - ore->noise = NULL; - - if (ore->clust_scarcity <= 0 || ore->clust_num_ores <= 0) { - errorstream << "register_ore: clust_scarcity and clust_num_ores" - "must be greater than 0" << std::endl; - delete ore; - return 0; - } - - emerge->ores.push_back(ore); - - verbosestream << "register_ore: ore '" << ore->ore_name - << "' registered" << std::endl; - return 0; -} - -// register_decoration({lots of stuff}) -int ModApiBasic::l_register_decoration(lua_State *L) -{ - int index = 1; - luaL_checktype(L, index, LUA_TTABLE); - - EmergeManager *emerge = getServer(L)->getEmergeManager(); - BiomeDefManager *bdef = emerge->biomedef; - - enum DecorationType decotype = (DecorationType)getenumfield(L, index, - "deco_type", es_DecorationType, -1); - if (decotype == -1) { - errorstream << "register_decoration: unrecognized " - "decoration placement type"; - return 0; - } - - Decoration *deco = createDecoration(decotype); - if (!deco) { - errorstream << "register_decoration: decoration placement type " - << decotype << " not implemented"; - return 0; - } - - deco->c_place_on = CONTENT_IGNORE; - deco->place_on_name = getstringfield_default(L, index, "place_on", "ignore"); - deco->fill_ratio = getfloatfield_default(L, index, "fill_ratio", 0.02); - deco->sidelen = getintfield_default(L, index, "sidelen", 8); - if (deco->sidelen <= 0) { - errorstream << "register_decoration: sidelen must be " - "greater than 0" << std::endl; - delete deco; - return 0; - } - - lua_getfield(L, index, "noise_params"); - deco->np = read_noiseparams(L, -1); - lua_pop(L, 1); - - lua_getfield(L, index, "biomes"); - if (lua_istable(L, -1)) { - lua_pushnil(L); - while (lua_next(L, -2)) { - const char *s = lua_tostring(L, -1); - u8 biomeid = bdef->getBiomeIdByName(s); - if (biomeid) - deco->biomes.insert(biomeid); - - lua_pop(L, 1); - } - lua_pop(L, 1); - } - - switch (decotype) { - case DECO_SIMPLE: { - DecoSimple *dsimple = (DecoSimple *)deco; - dsimple->c_deco = CONTENT_IGNORE; - dsimple->c_spawnby = CONTENT_IGNORE; - dsimple->spawnby_name = getstringfield_default(L, index, "spawn_by", "air"); - dsimple->deco_height = getintfield_default(L, index, "height", 1); - dsimple->deco_height_max = getintfield_default(L, index, "height_max", 0); - dsimple->nspawnby = getintfield_default(L, index, "num_spawn_by", -1); - - lua_getfield(L, index, "decoration"); - if (lua_istable(L, -1)) { - lua_pushnil(L); - while (lua_next(L, -2)) { - const char *s = lua_tostring(L, -1); - std::string str(s); - dsimple->decolist_names.push_back(str); - - lua_pop(L, 1); - } - } else if (lua_isstring(L, -1)) { - dsimple->deco_name = std::string(lua_tostring(L, -1)); - } else { - dsimple->deco_name = std::string("air"); - } - lua_pop(L, 1); - - if (dsimple->deco_height <= 0) { - errorstream << "register_decoration: simple decoration height" - " must be greater than 0" << std::endl; - delete dsimple; - return 0; - } - - break; } - case DECO_SCHEMATIC: { - DecoSchematic *dschem = (DecoSchematic *)deco; - dschem->flags = getflagsfield(L, index, "flags", flagdesc_deco_schematic); - dschem->rotation = (Rotation)getenumfield(L, index, - "rotation", es_Rotation, ROTATE_0); - - lua_getfield(L, index, "replacements"); - if (lua_istable(L, -1)) { - int i = lua_gettop(L); - lua_pushnil(L); - while (lua_next(L, i) != 0) { - // key at index -2 and value at index -1 - lua_rawgeti(L, -1, 1); - std::string replace_from = lua_tostring(L, -1); - lua_pop(L, 1); - lua_rawgeti(L, -1, 2); - std::string replace_to = lua_tostring(L, -1); - lua_pop(L, 1); - dschem->replacements[replace_from] = replace_to; - // removes value, keeps key for next iteration - lua_pop(L, 1); - } - } - lua_pop(L, 1); - - lua_getfield(L, index, "schematic"); - if (!read_schematic(L, -1, dschem, getServer(L))) { - delete dschem; - return 0; - } - lua_pop(L, -1); - - if (!dschem->filename.empty() && !dschem->loadSchematicFile()) { - errorstream << "register_decoration: failed to load schematic file '" - << dschem->filename << "'" << std::endl; - delete dschem; - return 0; - } - break; } - case DECO_LSYSTEM: { - //DecoLSystem *decolsystem = (DecoLSystem *)deco; - - break; } - } - - emerge->decorations.push_back(deco); - - verbosestream << "register_decoration: decoration '" << deco->getName() - << "' registered" << std::endl; - return 0; -} - -// create_schematic(p1, p2, probability_list, filename) -int ModApiBasic::l_create_schematic(lua_State *L) -{ - DecoSchematic dschem; - - Map *map = &(getEnv(L)->getMap()); - INodeDefManager *ndef = getServer(L)->getNodeDefManager(); - - v3s16 p1 = read_v3s16(L, 1); - v3s16 p2 = read_v3s16(L, 2); - sortBoxVerticies(p1, p2); - - std::vector<std::pair<v3s16, u8> > probability_list; - if (lua_istable(L, 3)) { - lua_pushnil(L); - while (lua_next(L, 3)) { - if (lua_istable(L, -1)) { - lua_getfield(L, -1, "pos"); - v3s16 pos = read_v3s16(L, -1); - lua_pop(L, 1); - - u8 prob = getintfield_default(L, -1, "prob", 0xFF); - probability_list.push_back(std::make_pair(pos, prob)); - } - - lua_pop(L, 1); - } - } - - dschem.filename = std::string(lua_tostring(L, 4)); - - if (!dschem.getSchematicFromMap(map, p1, p2)) { - errorstream << "create_schematic: failed to get schematic " - "from map" << std::endl; - return 0; - } - - dschem.applyProbabilities(&probability_list, p1); - - dschem.saveSchematicFile(ndef); - actionstream << "create_schematic: saved schematic file '" - << dschem.filename << "'." << std::endl; - - return 1; -} - - -// place_schematic(p, schematic, rotation, replacement) -int ModApiBasic::l_place_schematic(lua_State *L) -{ - DecoSchematic dschem; - - Map *map = &(getEnv(L)->getMap()); - INodeDefManager *ndef = getServer(L)->getNodeDefManager(); - - v3s16 p = read_v3s16(L, 1); - if (!read_schematic(L, 2, &dschem, getServer(L))) - return 0; - - Rotation rot = ROTATE_0; - if (lua_isstring(L, 3)) - string_to_enum(es_Rotation, (int &)rot, std::string(lua_tostring(L, 3))); - - dschem.rotation = rot; - - if (lua_istable(L, 4)) { - int index = 4; - lua_pushnil(L); - while (lua_next(L, index) != 0) { - // key at index -2 and value at index -1 - lua_rawgeti(L, -1, 1); - std::string replace_from = lua_tostring(L, -1); - lua_pop(L, 1); - lua_rawgeti(L, -1, 2); - std::string replace_to = lua_tostring(L, -1); - lua_pop(L, 1); - dschem.replacements[replace_from] = replace_to; - // removes value, keeps key for next iteration - lua_pop(L, 1); - } - } - - if (!dschem.filename.empty()) { - if (!dschem.loadSchematicFile()) { - errorstream << "place_schematic: failed to load schematic file '" - << dschem.filename << "'" << std::endl; - return 0; - } - dschem.resolveNodeNames(ndef); - } - - dschem.placeStructure(map, p); - - return 1; -} - - -ModApiBasic modapibasic_prototype; diff --git a/src/script/scripting_game.cpp b/src/script/scripting_game.cpp new file mode 100644 index 000000000..dfbf471d2 --- /dev/null +++ b/src/script/scripting_game.cpp @@ -0,0 +1,99 @@ +/* +Minetest +Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com> + +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 "scripting_game.h" +#include "log.h" +#include "cpp_api/s_internal.h" +#include "lua_api/l_base.h" +#include "lua_api/l_craft.h" +#include "lua_api/l_env.h" +#include "lua_api/l_inventory.h" +#include "lua_api/l_item.h" +#include "lua_api/l_mapgen.h" +#include "lua_api/l_nodemeta.h" +#include "lua_api/l_nodetimer.h" +#include "lua_api/l_noise.h" +#include "lua_api/l_object.h" +#include "lua_api/l_particles.h" +#include "lua_api/l_rollback.h" +#include "lua_api/l_server.h" +#include "lua_api/l_util.h" +#include "lua_api/l_vmanip.h" + +extern "C" { +#include "lualib.h" +} + +GameScripting::GameScripting(Server* server) +{ + setServer(server); + + // setEnv(env) is called by ScriptApiEnv::initializeEnvironment() + // once the environment has been created + + //TODO add security + + luaL_openlibs(getStack()); + + SCRIPTAPI_PRECHECKHEADER + + // Create the main minetest table + lua_newtable(L); + + lua_newtable(L); + lua_setfield(L, -2, "object_refs"); + + lua_newtable(L); + lua_setfield(L, -2, "luaentities"); + + lua_setglobal(L, "minetest"); + + // Initialize our lua_api modules + lua_getglobal(L, "minetest"); + int top = lua_gettop(L); + InitializeModApi(L, top); + lua_pop(L, 1); + + infostream << "SCRIPTAPI: initialized game modules" << std::endl; +} + +void GameScripting::InitializeModApi(lua_State *L, int top) +{ + // Initialize mod api modules + ModApiCraft::Initialize(L, top); + ModApiEnvMod::Initialize(L, top); + ModApiInventory::Initialize(L, top); + ModApiItemMod::Initialize(L, top); + ModApiMapgen::Initialize(L, top); + ModApiParticles::Initialize(L, top); + ModApiRollback::Initialize(L, top); + ModApiServer::Initialize(L, top); + ModApiUtil::Initialize(L, top); + + // Register reference classes (userdata) + InvRef::Register(L); + LuaItemStack::Register(L); + LuaPerlinNoise::Register(L); + LuaPerlinNoiseMap::Register(L); + LuaPseudoRandom::Register(L); + LuaVoxelManip::Register(L); + NodeMetaRef::Register(L); + NodeTimerRef::Register(L); + ObjectRef::Register(L); +} diff --git a/src/script/cpp_api/scriptapi.h b/src/script/scripting_game.h index bbd0bdda7..ed6567922 100644 --- a/src/script/cpp_api/scriptapi.h +++ b/src/script/scripting_game.h @@ -17,66 +17,37 @@ with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#ifndef SCRIPTAPI_H_ -#define SCRIPTAPI_H_ - -#include <map> -#include <set> -#include <vector> +#ifndef SCRIPTING_GAME_H_ +#define SCRIPTING_GAME_H_ #include "cpp_api/s_base.h" -#include "cpp_api/s_player.h" +#include "cpp_api/s_entity.h" #include "cpp_api/s_env.h" -#include "cpp_api/s_node.h" #include "cpp_api/s_inventory.h" -#include "cpp_api/s_entity.h" - -class ModApiBase; +#include "cpp_api/s_node.h" +#include "cpp_api/s_player.h" +#include "cpp_api/s_server.h" /*****************************************************************************/ -/* Scriptapi <-> Core Interface */ +/* Scripting <-> Game Interface */ /*****************************************************************************/ -class ScriptApi +class GameScripting : virtual public ScriptApiBase, - public ScriptApiPlayer, + public ScriptApiDetached, + public ScriptApiEntity, public ScriptApiEnv, public ScriptApiNode, - public ScriptApiDetached, - public ScriptApiEntity + public ScriptApiPlayer, + public ScriptApiServer { public: - ScriptApi(); - ScriptApi(Server* server); - ~ScriptApi(); - - // Returns true if script handled message - bool on_chat_message(const std::string &name, const std::string &message); - - /* server */ - void on_shutdown(); + GameScripting(Server* server); - /* auth */ - bool getAuth(const std::string &playername, - std::string *dst_password, std::set<std::string> *dst_privs); - void createAuth(const std::string &playername, - const std::string &password); - bool setPassword(const std::string &playername, - const std::string &password); - - /** register a lua api module to scriptapi */ - static bool registerModApiModule(ModApiBase* prototype); - /** load a mod **/ - bool loadMod(const std::string &scriptpath,const std::string &modname); + // use ScriptApiBase::loadMod() to load mods private: - void getAuthHandler(); - void readPrivileges(int index,std::set<std::string> &result); - - bool scriptLoad(const char *path); - - static std::vector<ModApiBase*>* m_mod_api_modules; - + void InitializeModApi(lua_State *L, int top); }; -#endif /* SCRIPTAPI_H_ */ +#endif /* SCRIPTING_GAME_H_ */ diff --git a/src/script/scripting_mainmenu.cpp b/src/script/scripting_mainmenu.cpp new file mode 100644 index 000000000..47461e7ca --- /dev/null +++ b/src/script/scripting_mainmenu.cpp @@ -0,0 +1,65 @@ +/* +Minetest +Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com> + +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 "scripting_mainmenu.h" +#include "log.h" +#include "filesys.h" +#include "cpp_api/s_internal.h" +#include "lua_api/l_base.h" +#include "lua_api/l_mainmenu.h" +#include "lua_api/l_util.h" + +extern "C" { +#include "lualib.h" +} + +MainMenuScripting::MainMenuScripting(GUIEngine* guiengine) +{ + setGuiEngine(guiengine); + + //TODO add security + + luaL_openlibs(getStack()); + + SCRIPTAPI_PRECHECKHEADER + + lua_pushstring(L, DIR_DELIM); + lua_setglobal(L, "DIR_DELIM"); + + lua_newtable(L); + lua_setglobal(L, "gamedata"); + + lua_newtable(L); + lua_setglobal(L, "engine"); + + // Initialize our lua_api modules + lua_getglobal(L, "engine"); + int top = lua_gettop(L); + InitializeModApi(L, top); + lua_pop(L, 1); + + infostream << "SCRIPTAPI: initialized mainmenu modules" << std::endl; +} + +void MainMenuScripting::InitializeModApi(lua_State *L, int top) +{ + // Initialize mod api modules + ModApiMainMenu::Initialize(L, top); + ModApiUtil::Initialize(L, top); +} diff --git a/src/script/scripting_mainmenu.h b/src/script/scripting_mainmenu.h new file mode 100644 index 000000000..7592c8e23 --- /dev/null +++ b/src/script/scripting_mainmenu.h @@ -0,0 +1,45 @@ +/* +Minetest +Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com> + +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 SCRIPTING_MAINMENU_H_ +#define SCRIPTING_MAINMENU_H_ + +#include "cpp_api/s_base.h" +#include "cpp_api/s_mainmenu.h" + +/*****************************************************************************/ +/* Scripting <-> Main Menu Interface */ +/*****************************************************************************/ + +class MainMenuScripting + : virtual public ScriptApiBase, + public ScriptApiMainMenu +{ +public: + MainMenuScripting(GUIEngine* guiengine); + + // use ScriptApiBase::loadMod() or ScriptApiBase::loadScript() + // to load scripts + +private: + void InitializeModApi(lua_State *L, int top); +}; + + +#endif /* SCRIPTING_MAINMENU_H_ */ |