Move script_run_callbacks to Lua
authorShadowNinja <shadowninja@minetest.net>
Sun, 8 Dec 2013 03:03:07 +0000 (22:03 -0500)
committerShadowNinja <shadowninja@minetest.net>
Sun, 8 Dec 2013 03:03:07 +0000 (22:03 -0500)
builtin/misc_register.lua
src/script/common/c_internal.cpp

index 54022a36138894f007bf30b5232f9920642a7c22..249d272eb579aa663b6502b9f276560555cc6d2a 100644 (file)
@@ -314,6 +314,45 @@ minetest.register_item(":", {
        groups = {not_in_creative_inventory=1},
 })
 
+
+function minetest.run_callbacks(callbacks, mode, ...)
+       assert(type(callbacks) == "table")
+       local cb_len = #callbacks
+       if cb_len == 0 then
+               if mode == 2 or mode == 3 then
+                       return true
+               elseif mode == 4 or mode == 5 then
+                       return false
+               end
+       end
+       local ret = nil
+       for i = 1, cb_len do
+               local cb_ret = callbacks[i](...)
+
+               if mode == 0 and i == 1 then
+                       ret = cb_ret
+               elseif mode == 1 and i == cb_len then
+                       ret = cb_ret
+               elseif mode == 2 then
+                       if not cb_ret or i == 1 then
+                               ret = cb_ret
+                       end
+               elseif mode == 3 then
+                       if cb_ret then
+                               return cb_ret
+                       end
+                       ret = cb_ret
+               elseif mode == 4 then
+                       if (cb_ret and not ret) or i == 1 then
+                               ret = cb_ret
+                       end
+               elseif mode == 5 and cb_ret then
+                       return cb_ret
+               end
+       end
+       return ret
+end
+
 --
 -- Callback registration
 --
index f22e9b0ff948782a4a909d8ae65217333ad75ba1..2866cfe86449cc7f78f7b07fe8ae787ba81c7d26 100644 (file)
@@ -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
 }