aboutsummaryrefslogtreecommitdiff
path: root/src/script
diff options
context:
space:
mode:
authorest31 <MTest31@outlook.com>2016-02-09 07:08:31 +0100
committerest31 <MTest31@outlook.com>2016-03-07 19:54:26 +0100
commitd494733839e9cf6cb557462326ed21e7a58816c7 (patch)
tree07ead00672b0096aa2a60938b769bf030bba2951 /src/script
parent88fbe7ca1e5451851ee0c7ab5524c39a7bb703c2 (diff)
downloadminetest-d494733839e9cf6cb557462326ed21e7a58816c7.tar.gz
minetest-d494733839e9cf6cb557462326ed21e7a58816c7.tar.bz2
minetest-d494733839e9cf6cb557462326ed21e7a58816c7.zip
Add minetest.register_lbm() to run code on block load only
Diffstat (limited to 'src/script')
-rw-r--r--src/script/cpp_api/s_base.h1
-rw-r--r--src/script/cpp_api/s_env.cpp55
-rw-r--r--src/script/lua_api/l_env.cpp40
-rw-r--r--src/script/lua_api/l_env.h18
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;