mirror of
https://github.com/luanti-org/luanti.git
synced 2025-08-06 17:41:04 +00:00
Add proff of concept for blocks callback.
This commit is contained in:
parent
a00b9cab36
commit
18c740712a
7 changed files with 212 additions and 0 deletions
|
@ -419,6 +419,40 @@ bool ScriptApiEnv::has_on_mapblocks_changed()
|
|||
return lua_objlen(L, -1) > 0;
|
||||
}
|
||||
|
||||
void ScriptApiEnv::block_callback(const v3s16 blockpos, ScriptCallbackState *state)
|
||||
{
|
||||
Server *server = getServer();
|
||||
|
||||
// This function should be executed with envlock held.
|
||||
// The caller (LuaClearObjectback in src/script/lua_api/l_env.cpp)
|
||||
// should have obtained the lock.
|
||||
// Note that the order of these locks is important! Envlock must *ALWAYS*
|
||||
// be acquired before attempting to acquire scriptlock, or else ServerThread
|
||||
// will try to acquire scriptlock after it already owns envlock, thus
|
||||
// deadlocking EmergeThread and ServerThread
|
||||
|
||||
SCRIPTAPI_PRECHECKHEADER
|
||||
|
||||
int error_handler = PUSH_ERROR_HANDLER(L);
|
||||
|
||||
lua_rawgeti(L, LUA_REGISTRYINDEX, state->callback_ref);
|
||||
|
||||
lua_pushnumber(L, hash_node_position(blockpos));
|
||||
lua_rawgeti(L, LUA_REGISTRYINDEX, state->args_ref);
|
||||
|
||||
setOriginDirect(state->origin.c_str());
|
||||
|
||||
try {
|
||||
PCALL_RES(lua_pcall(L, 2, 1, error_handler));
|
||||
|
||||
lua_pop(L, 2); // Pop callback result and error handler
|
||||
|
||||
} catch (LuaError &e) {
|
||||
// Note: don't throw here, we still need to run the cleanup code below
|
||||
server->setAsyncFatalError(e);
|
||||
}
|
||||
}
|
||||
|
||||
void ScriptApiEnv::triggerABM(int id, v3s16 p, MapNode n,
|
||||
u32 active_object_count, u32 active_object_count_wider)
|
||||
{
|
||||
|
|
|
@ -41,6 +41,9 @@ public:
|
|||
// Determines whether there are any on_mapblocks_changed callbacks
|
||||
bool has_on_mapblocks_changed();
|
||||
|
||||
// Calll Lua callback for block
|
||||
void block_callback(const v3s16 blockpos, ScriptCallbackState *state);
|
||||
|
||||
// Initializes environment and loads some definitions from Lua
|
||||
void initializeEnvironment(ServerEnvironment *env);
|
||||
|
||||
|
|
|
@ -155,6 +155,19 @@ void LuaEmergeAreaCallback(v3s16 blockpos, EmergeAction action, void *param)
|
|||
delete state;
|
||||
}
|
||||
|
||||
void LuaBlockCallback(const v3s16 blockpos, void *param)
|
||||
{
|
||||
ScriptCallbackState *state = static_cast<ScriptCallbackState *>(param);
|
||||
assert(state != NULL);
|
||||
assert(state->script != NULL);
|
||||
|
||||
// state must be protected by envlock
|
||||
//Server *server = state->script->getServer();
|
||||
//MutexAutoLock envlock(server->m_env_mutex);
|
||||
|
||||
state->script->block_callback(blockpos, state);
|
||||
}
|
||||
|
||||
/* Exported functions */
|
||||
|
||||
// set_node(pos, node)
|
||||
|
@ -1092,6 +1105,56 @@ int ModApiEnv::l_clear_objects(lua_State *L)
|
|||
return 0;
|
||||
}
|
||||
|
||||
// blocks_callback
|
||||
int ModApiEnv::l_blocks_callback(lua_State *L)
|
||||
{
|
||||
GET_ENV_PTR;
|
||||
|
||||
ScriptCallbackState *state = NULL;
|
||||
|
||||
BlocksCallbackConfig config;
|
||||
config.mode = CLEAR_OBJECTS_MODE_QUICK;
|
||||
config.callback = nullptr;
|
||||
if (lua_istable(L, 1)) {
|
||||
lua_getfield(L, 1, "mode");
|
||||
config.mode = (ClearObjectsMode)getenumfield(L, 1, "mode",
|
||||
ModApiEnv::es_ClearObjectsMode, config.mode);
|
||||
lua_pop(L, 1);
|
||||
|
||||
lua_getfield(L, 1, "callback");
|
||||
if (lua_isfunction(L, -1)) {
|
||||
config.callback = LuaBlockCallback;
|
||||
|
||||
int callback_ref = luaL_ref(L, LUA_REGISTRYINDEX);
|
||||
|
||||
lua_getfield(L, 1, "params");
|
||||
int args_ref = luaL_ref(L, LUA_REGISTRYINDEX);
|
||||
|
||||
state = new ScriptCallbackState;
|
||||
state->script = getServer(L)->getScriptIface();
|
||||
state->callback_ref = callback_ref;
|
||||
state->args_ref = args_ref;
|
||||
state->refcount = 1;
|
||||
state->origin = getScriptApiBase(L)->getOrigin();
|
||||
|
||||
config.param = static_cast<void *>(state);
|
||||
}
|
||||
else {
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
}
|
||||
|
||||
env->blocksCallback(config);
|
||||
|
||||
if (state) {
|
||||
luaL_unref(L, LUA_REGISTRYINDEX, state->callback_ref);
|
||||
luaL_unref(L, LUA_REGISTRYINDEX, state->args_ref);
|
||||
delete state;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// line_of_sight(pos1, pos2) -> true/false, pos
|
||||
int ModApiEnv::l_line_of_sight(lua_State *L)
|
||||
{
|
||||
|
@ -1419,6 +1482,7 @@ void ModApiEnv::Initialize(lua_State *L, int top)
|
|||
API_FCT(get_perlin_map);
|
||||
API_FCT(get_voxel_manip);
|
||||
API_FCT(clear_objects);
|
||||
API_FCT(blocks_callback);
|
||||
API_FCT(spawn_tree);
|
||||
API_FCT(find_path);
|
||||
API_FCT(line_of_sight);
|
||||
|
|
|
@ -195,6 +195,9 @@ private:
|
|||
// clear all objects in the environment
|
||||
static int l_clear_objects(lua_State *L);
|
||||
|
||||
// blocks_callback()
|
||||
static int l_blocks_callback(lua_State *L);
|
||||
|
||||
// spawn_tree(pos, treedef)
|
||||
static int l_spawn_tree(lua_State *L);
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue