Move script_run_callbacks to Lua
parent
96f753a108
commit
a0dce51af6
|
@ -314,6 +314,45 @@ minetest.register_item(":", {
|
||||||
groups = {not_in_creative_inventory=1},
|
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
|
-- Callback registration
|
||||||
--
|
--
|
||||||
|
|
|
@ -66,101 +66,35 @@ void script_error(lua_State *L)
|
||||||
// Then push nargs arguments.
|
// Then push nargs arguments.
|
||||||
// Then call this function, which
|
// Then call this function, which
|
||||||
// - runs the callbacks
|
// - runs the callbacks
|
||||||
// - removes the table and arguments from the lua stack
|
// - replaces the table and arguments with the return value,
|
||||||
// - pushes the return value, computed depending on mode
|
// computed depending on mode
|
||||||
void script_run_callbacks(lua_State *L, int nargs, RunCallbacksMode 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);
|
assert(lua_gettop(L) >= nargs + 1);
|
||||||
|
|
||||||
lua_pushnil(L);
|
// Insert error handler
|
||||||
int rv = lua_gettop(L) - nargs - 1;
|
|
||||||
lua_insert(L, rv);
|
|
||||||
|
|
||||||
// Insert error handler after return value
|
|
||||||
lua_pushcfunction(L, script_error_handler);
|
lua_pushcfunction(L, script_error_handler);
|
||||||
int errorhandler = rv + 1;
|
int errorhandler = lua_gettop(L) - nargs - 1;
|
||||||
lua_insert(L, errorhandler);
|
lua_insert(L, errorhandler);
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
|
||||||
|
// Insert mode after table
|
||||||
|
lua_pushnumber(L, (int) mode);
|
||||||
|
lua_insert(L, errorhandler + 3);
|
||||||
|
|
||||||
// Stack now looks like this:
|
// Stack now looks like this:
|
||||||
// ... <return value = nil> <error handler> <table> <arg#1> <arg#2> ... <arg#n>
|
// ... <error handler> <run_callbacks> <table> <mode> <arg#1> <arg#2> ... <arg#n>
|
||||||
|
|
||||||
int table = errorhandler + 1;
|
if (lua_pcall(L, nargs + 2, 1, errorhandler)) {
|
||||||
int arg = table + 1;
|
script_error(L);
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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_remove(L, -2); // Remove error handler
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue