diff options
Diffstat (limited to 'src/script')
-rw-r--r-- | src/script/cpp_api/s_base.h | 1 | ||||
-rw-r--r-- | src/script/cpp_api/s_env.cpp | 55 | ||||
-rw-r--r-- | src/script/lua_api/l_env.cpp | 40 | ||||
-rw-r--r-- | src/script/lua_api/l_env.h | 18 |
4 files changed, 112 insertions, 2 deletions
diff --git a/src/script/cpp_api/s_base.h b/src/script/cpp_api/s_base.h index ead385a43..f52474f00 100644 --- a/src/script/cpp_api/s_base.h +++ b/src/script/cpp_api/s_base.h @@ -83,6 +83,7 @@ public: protected: friend class LuaABM; + friend class LuaLBM; friend class InvRef; friend class ObjectRef; friend class NodeMetaRef; diff --git a/src/script/cpp_api/s_env.cpp b/src/script/cpp_api/s_env.cpp index a1b11bfe1..35b7b36f2 100644 --- a/src/script/cpp_api/s_env.cpp +++ b/src/script/cpp_api/s_env.cpp @@ -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)){ @@ -154,6 +153,58 @@ void ScriptApiEnv::initializeEnvironment(ServerEnvironment *env) // 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); } diff --git a/src/script/lua_api/l_env.cpp b/src/script/lua_api/l_env.cpp index b445b1eb9..f4ddc2afc 100644 --- a/src/script/lua_api/l_env.cpp +++ b/src/script/lua_api/l_env.cpp @@ -90,6 +90,46 @@ void LuaABM::trigger(ServerEnvironment *env, v3s16 p, MapNode n, lua_pop(L, 1); // Pop error handler } +void LuaLBM::trigger(ServerEnvironment *env, v3s16 p, MapNode n) +{ + GameScripting *scriptIface = env->getScriptIface(); + scriptIface->realityCheck(); + + lua_State *L = scriptIface->getStack(); + sanity_check(lua_checkstack(L, 20)); + StackUnroller stack_unroller(L); + + int error_handler = PUSH_ERROR_HANDLER(L); + + // Get registered_lbms + lua_getglobal(L, "core"); + lua_getfield(L, -1, "registered_lbms"); + luaL_checktype(L, -1, LUA_TTABLE); + lua_remove(L, -2); // Remove core + + // Get registered_lbms[m_id] + lua_pushnumber(L, m_id); + lua_gettable(L, -2); + FATAL_ERROR_IF(lua_isnil(L, -1), "Entry with given id not found in registered_lbms table"); + lua_remove(L, -2); // Remove registered_lbms + + scriptIface->setOriginFromTable(-1); + + // Call action + luaL_checktype(L, -1, LUA_TTABLE); + lua_getfield(L, -1, "action"); + luaL_checktype(L, -1, LUA_TFUNCTION); + lua_remove(L, -2); // Remove registered_lbms[m_id] + push_v3s16(L, p); + pushnode(L, n, env->getGameDef()->ndef()); + + int result = lua_pcall(L, 2, 0, error_handler); + if (result) + scriptIface->scriptError(result, "LuaLBM::trigger"); + + lua_pop(L, 1); // Pop error handler +} + void LuaEmergeAreaCallback(v3s16 blockpos, EmergeAction action, void *param) { ScriptCallbackState *state = (ScriptCallbackState *)param; diff --git a/src/script/lua_api/l_env.h b/src/script/lua_api/l_env.h index 4f8dfcd3c..0e385ffef 100644 --- a/src/script/lua_api/l_env.h +++ b/src/script/lua_api/l_env.h @@ -220,6 +220,24 @@ public: u32 active_object_count, u32 active_object_count_wider); }; +class LuaLBM : public LoadingBlockModifierDef +{ +private: + int m_id; +public: + LuaLBM(lua_State *L, int id, + const std::set<std::string> &trigger_contents, + const std::string &name, + bool run_at_every_load): + m_id(id) + { + this->run_at_every_load = run_at_every_load; + this->trigger_contents = trigger_contents; + this->name = name; + } + virtual void trigger(ServerEnvironment *env, v3s16 p, MapNode n); +}; + struct ScriptCallbackState { GameScripting *script; int callback_ref; |