aboutsummaryrefslogtreecommitdiff
path: root/src/script/common
diff options
context:
space:
mode:
Diffstat (limited to 'src/script/common')
-rw-r--r--src/script/common/CMakeLists.txt7
-rw-r--r--src/script/common/c_content.cpp9
-rw-r--r--src/script/common/c_content.h13
-rw-r--r--src/script/common/c_internal.cpp109
-rw-r--r--src/script/common/c_internal.h56
-rw-r--r--src/script/common/c_types.h20
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: