diff options
Diffstat (limited to 'src/script/common')
-rw-r--r-- | src/script/common/CMakeLists.txt | 7 | ||||
-rw-r--r-- | src/script/common/c_content.cpp | 9 | ||||
-rw-r--r-- | src/script/common/c_content.h | 13 | ||||
-rw-r--r-- | src/script/common/c_internal.cpp | 109 | ||||
-rw-r--r-- | src/script/common/c_internal.h | 56 | ||||
-rw-r--r-- | src/script/common/c_types.h | 20 |
6 files changed, 146 insertions, 68 deletions
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: |