]> git.lizzy.rs Git - dragonfireclient.git/blobdiff - src/script/cpp_api/s_env.cpp
Add minetest.register_lbm() to run code on block load only
[dragonfireclient.git] / src / script / cpp_api / s_env.cpp
index 9c733773a6d14ed8ab11cf3e5663f5d08b0982d6..35b7b36f211792749abfa19088649c1c9a207cfb 100644 (file)
@@ -86,13 +86,12 @@ void ScriptApiEnv::initializeEnvironment(ServerEnvironment *env)
        setEnv(env);
 
        /*
-               Add ActiveBlockModifiers to environment
+               Add {Loading,Active}BlockModifiers to environment
        */
 
        // Get core.registered_abms
        lua_getglobal(L, "core");
        lua_getfield(L, -1, "registered_abms");
-       luaL_checktype(L, -1, LUA_TTABLE);
        int registered_abms = lua_gettop(L);
 
        if(lua_istable(L, registered_abms)){
@@ -143,14 +142,108 @@ void ScriptApiEnv::initializeEnvironment(ServerEnvironment *env)
                        int trigger_chance = 50;
                        getintfield(L, current_abm, "chance", trigger_chance);
 
-                       LuaABM *abm = new LuaABM(L, id, trigger_contents,
-                                       required_neighbors, trigger_interval, trigger_chance);
+                       bool simple_catch_up = true;
+                       getboolfield(L, current_abm, "catch_up", simple_catch_up);
+
+                       LuaABM *abm = new LuaABM(L, id, trigger_contents, required_neighbors,
+                               trigger_interval, trigger_chance, simple_catch_up);
 
                        env->addActiveBlockModifier(abm);
 
                        // removes value, keeps key for next iteration
                        lua_pop(L, 1);
                }
+       } else {
+               lua_pop(L, 1);
+               throw LuaError("core.registered_abms was not a lua table, as expected.");
        }
        lua_pop(L, 1);
+
+       // Get core.registered_lbms
+       lua_getglobal(L, "core");
+       lua_getfield(L, -1, "registered_lbms");
+       int registered_lbms = lua_gettop(L);
+
+       if (!lua_istable(L, registered_lbms)) {
+               lua_pop(L, 1);
+               throw LuaError("core.registered_lbms was not a lua table, as expected.");
+       }
+
+       lua_pushnil(L);
+       while (lua_next(L, registered_lbms)) {
+               // key at index -2 and value at index -1
+               int id = lua_tonumber(L, -2);
+               int current_lbm = lua_gettop(L);
+
+               std::set<std::string> trigger_contents;
+               lua_getfield(L, current_lbm, "nodenames");
+               if (lua_istable(L, -1)) {
+                       int table = lua_gettop(L);
+                       lua_pushnil(L);
+                       while (lua_next(L, table)) {
+                               // key at index -2 and value at index -1
+                               luaL_checktype(L, -1, LUA_TSTRING);
+                               trigger_contents.insert(lua_tostring(L, -1));
+                               // removes value, keeps key for next iteration
+                               lua_pop(L, 1);
+                       }
+               } else if (lua_isstring(L, -1)) {
+                       trigger_contents.insert(lua_tostring(L, -1));
+               }
+               lua_pop(L, 1);
+
+               std::string name;
+               getstringfield(L, current_lbm, "name", name);
+
+               bool run_at_every_load = getboolfield_default(L, current_lbm,
+                       "run_at_every_load", false);
+
+               LuaLBM *lbm = new LuaLBM(L, id, trigger_contents, name,
+                       run_at_every_load);
+
+               env->addLoadingBlockModifierDef(lbm);
+
+               // removes value, keeps key for next iteration
+               lua_pop(L, 1);
+       }
+       lua_pop(L, 1);
+}
+
+void ScriptApiEnv::on_emerge_area_completion(
+       v3s16 blockpos, int action, ScriptCallbackState *state)
+{
+       Server *server = getServer();
+
+       // 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
+       MutexAutoLock envlock(server->m_env_mutex);
+
+       SCRIPTAPI_PRECHECKHEADER
+
+       int error_handler = PUSH_ERROR_HANDLER(L);
+
+       lua_rawgeti(L, LUA_REGISTRYINDEX, state->callback_ref);
+       luaL_checktype(L, -1, LUA_TFUNCTION);
+
+       push_v3s16(L, blockpos);
+       lua_pushinteger(L, action);
+       lua_pushinteger(L, state->refcount);
+       lua_rawgeti(L, LUA_REGISTRYINDEX, state->args_ref);
+
+       setOriginDirect(state->origin.c_str());
+
+       try {
+               PCALL_RES(lua_pcall(L, 4, 0, error_handler));
+       } catch (LuaError &e) {
+               server->setAsyncFatalError(e.what());
+       }
+
+       lua_pop(L, 1); // Pop error handler
+
+       if (state->refcount == 0) {
+               luaL_unref(L, LUA_REGISTRYINDEX, state->callback_ref);
+               luaL_unref(L, LUA_REGISTRYINDEX, state->args_ref);
+       }
 }