diff options
Diffstat (limited to 'src/script/common')
-rw-r--r-- | src/script/common/c_internal.cpp | 102 |
1 files changed, 18 insertions, 84 deletions
diff --git a/src/script/common/c_internal.cpp b/src/script/common/c_internal.cpp index f22e9b0ff..2866cfe86 100644 --- a/src/script/common/c_internal.cpp +++ b/src/script/common/c_internal.cpp @@ -66,101 +66,35 @@ void script_error(lua_State *L) // 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 +// - replaces the table and arguments with 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); - int rv = lua_gettop(L) - nargs - 1; - lua_insert(L, rv); - - // Insert error handler after return value + // Insert error handler lua_pushcfunction(L, script_error_handler); - int errorhandler = rv + 1; + int errorhandler = lua_gettop(L) - nargs - 1; lua_insert(L, errorhandler); - // Stack now looks like this: - // ... <return value = nil> <error handler> <table> <arg#1> <arg#2> ... <arg#n> - - int table = errorhandler + 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, errorhandler)) - script_error(L); - - // 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); - } + // Insert minetest.run_callbacks between error handler and table + lua_getglobal(L, "minetest"); + lua_getfield(L, -1, "run_callbacks"); + lua_remove(L, -2); + lua_insert(L, errorhandler + 1); - // 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; + // Insert mode after table + lua_pushnumber(L, (int) mode); + lua_insert(L, errorhandler + 3); - // value removed, keep key for next iteration - } - - // Remove stuff from stack, leaving only the return value - lua_settop(L, rv); + // Stack now looks like this: + // ... <error handler> <run_callbacks> <table> <mode> <arg#1> <arg#2> ... <arg#n> - // 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); - } + if (lua_pcall(L, nargs + 2, 1, errorhandler)) { + script_error(L); } + + lua_remove(L, -2); // Remove error handler } |