summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPerttu Ahola <celeron55@gmail.com>2012-06-05 23:51:37 +0300
committerPerttu Ahola <celeron55@gmail.com>2012-06-05 23:51:37 +0300
commit3a0562bebcb91d05fceb5a1f9ded539f77a625e4 (patch)
tree8b788689029fbeaf7880b628186b77c5f667845f
parentc3658e7c797cbf5b9d04a6d950505d37dcdd422b (diff)
downloadminetest-3a0562bebcb91d05fceb5a1f9ded539f77a625e4.tar.gz
minetest-3a0562bebcb91d05fceb5a1f9ded539f77a625e4.tar.bz2
minetest-3a0562bebcb91d05fceb5a1f9ded539f77a625e4.zip
Add after_destruct and cache the existence of on_construct, on_destruct and after_destruct for quick skipping when a node does not have them
-rw-r--r--doc/lua_api.txt7
-rw-r--r--games/minimal/mods/experimental/init.lua4
-rw-r--r--src/nodedef.cpp3
-rw-r--r--src/nodedef.h5
-rw-r--r--src/scriptapi.cpp65
-rw-r--r--src/scriptapi.h2
6 files changed, 74 insertions, 12 deletions
diff --git a/doc/lua_api.txt b/doc/lua_api.txt
index 5e0f2f118..e6e24b90a 100644
--- a/doc/lua_api.txt
+++ b/doc/lua_api.txt
@@ -1150,15 +1150,18 @@ Node definition (register_node)
on_destruct = func(pos),
^ Node destructor; always called before removing node
^ default: nil
+ after_destruct = func(pos, oldnode),
+ ^ Node destructor; always called after removing node
+ ^ default: nil
after_place_node = func(pos, placer),
^ Called after constructing node when node was placed using
- minetest.item_place_node
+ minetest.item_place_node / minetest.env:place_node
^ default: nil
after_dig_node = func(pos, oldnode, oldmetadata, digger),
^ oldmetadata is in table format
^ Called after destructing node when node was dug using
- minetest.node_dig
+ minetest.node_dig / minetest.env:dig_node
^ default: nil
can_dig = function(pos,player)
^ returns true if node can be dug, or false if not
diff --git a/games/minimal/mods/experimental/init.lua b/games/minimal/mods/experimental/init.lua
index ea11e6d3b..c8ffb25de 100644
--- a/games/minimal/mods/experimental/init.lua
+++ b/games/minimal/mods/experimental/init.lua
@@ -468,6 +468,10 @@ minetest.register_node("experimental:tester_node_1", {
experimental.print_to_everything("experimental:tester_node_1:on_destruct("..minetest.pos_to_string(pos)..")")
end,
+ after_destruct = function(pos)
+ experimental.print_to_everything("experimental:tester_node_1:after_destruct("..minetest.pos_to_string(pos)..")")
+ end,
+
after_dig_node = function(pos, oldnode, oldmetadata, digger)
experimental.print_to_everything("experimental:tester_node_1:after_dig_node("..minetest.pos_to_string(pos)..")")
end,
diff --git a/src/nodedef.cpp b/src/nodedef.cpp
index 2feec04f8..eaf061287 100644
--- a/src/nodedef.cpp
+++ b/src/nodedef.cpp
@@ -117,6 +117,9 @@ void ContentFeatures::reset()
visual_solidness = 0;
backface_culling = true;
#endif
+ has_on_construct = false;
+ has_on_destruct = false;
+ has_after_destruct = false;
/*
Actual data
diff --git a/src/nodedef.h b/src/nodedef.h
index 681606fd8..04f375043 100644
--- a/src/nodedef.h
+++ b/src/nodedef.h
@@ -144,6 +144,11 @@ struct ContentFeatures
bool backface_culling;
#endif
+ // Server-side cached callback existence for fast skipping
+ bool has_on_construct;
+ bool has_on_destruct;
+ bool has_after_destruct;
+
/*
Actual data
*/
diff --git a/src/scriptapi.cpp b/src/scriptapi.cpp
index 5091216dc..f53355f64 100644
--- a/src/scriptapi.cpp
+++ b/src/scriptapi.cpp
@@ -994,6 +994,18 @@ static ContentFeatures read_content_features(lua_State *L, int index)
index = lua_gettop(L) + 1 + index;
ContentFeatures f;
+
+ /* Cache existence of some callbacks */
+ lua_getfield(L, index, "on_construct");
+ if(!lua_isnil(L, -1)) f.has_on_construct = true;
+ lua_pop(L, 1);
+ lua_getfield(L, index, "on_destruct");
+ if(!lua_isnil(L, -1)) f.has_on_destruct = true;
+ lua_pop(L, 1);
+ lua_getfield(L, index, "after_destruct");
+ if(!lua_isnil(L, -1)) f.has_after_destruct = true;
+ lua_pop(L, 1);
+
/* Name */
getstringfield(L, index, "name", f.name);
@@ -3024,20 +3036,26 @@ private:
EnvRef *o = checkobject(L, 1);
ServerEnvironment *env = o->m_env;
if(env == NULL) return 0;
- // pos
+ INodeDefManager *ndef = env->getGameDef()->ndef();
+ // parameters
v3s16 pos = read_v3s16(L, 2);
- // content
- MapNode n = readnode(L, 3, env->getGameDef()->ndef());
+ MapNode n = readnode(L, 3, ndef);
// Do it
- // Call destructor
MapNode n_old = env->getMap().getNodeNoEx(pos);
- scriptapi_node_on_destruct(L, pos, n_old);
+ // Call destructor
+ if(ndef->get(n_old).has_on_destruct)
+ scriptapi_node_on_destruct(L, pos, n_old);
// Replace node
bool succeeded = env->getMap().addNodeWithEvent(pos, n);
+ if(succeeded){
+ // Call post-destructor
+ if(ndef->get(n_old).has_after_destruct)
+ scriptapi_node_after_destruct(L, pos, n_old);
+ // Call constructor
+ if(ndef->get(n).has_on_construct)
+ scriptapi_node_on_construct(L, pos, n);
+ }
lua_pushboolean(L, succeeded);
- // Call constructor
- if(succeeded)
- scriptapi_node_on_construct(L, pos, n);
return 1;
}
@@ -3053,14 +3071,22 @@ private:
EnvRef *o = checkobject(L, 1);
ServerEnvironment *env = o->m_env;
if(env == NULL) return 0;
+ INodeDefManager *ndef = env->getGameDef()->ndef();
+ // parameters
v3s16 pos = read_v3s16(L, 2);
// Do it
+ MapNode n_old = env->getMap().getNodeNoEx(pos);
// Call destructor
- MapNode n = env->getMap().getNodeNoEx(pos);
- scriptapi_node_on_destruct(L, pos, n);
+ if(ndef->get(n_old).has_on_destruct)
+ scriptapi_node_on_destruct(L, pos, n_old);
// Replace with air
// This is slightly optimized compared to addNodeWithEvent(air)
bool succeeded = env->getMap().removeNodeWithEvent(pos);
+ if(succeeded){
+ // Call post-destructor
+ if(ndef->get(n_old).has_after_destruct)
+ scriptapi_node_after_destruct(L, pos, n_old);
+ }
lua_pushboolean(L, succeeded);
// Air doesn't require constructor
return 1;
@@ -5143,6 +5169,25 @@ void scriptapi_node_on_destruct(lua_State *L, v3s16 p, MapNode node)
script_error(L, "error: %s", lua_tostring(L, -1));
}
+void scriptapi_node_after_destruct(lua_State *L, v3s16 p, MapNode node)
+{
+ realitycheck(L);
+ assert(lua_checkstack(L, 20));
+ StackUnroller stack_unroller(L);
+
+ INodeDefManager *ndef = get_server(L)->ndef();
+
+ // Push callback function on stack
+ if(!get_item_callback(L, ndef->get(node).name.c_str(), "after_destruct"))
+ return;
+
+ // Call function
+ push_v3s16(L, p);
+ pushnode(L, node, ndef);
+ if(lua_pcall(L, 2, 0, 0))
+ script_error(L, "error: %s", lua_tostring(L, -1));
+}
+
void scriptapi_node_on_receive_fields(lua_State *L, v3s16 p,
const std::string &formname,
const std::map<std::string, std::string> &fields,
diff --git a/src/scriptapi.h b/src/scriptapi.h
index 7b0bffdb5..59daa3aa0 100644
--- a/src/scriptapi.h
+++ b/src/scriptapi.h
@@ -86,6 +86,8 @@ bool scriptapi_node_on_dig(lua_State *L, v3s16 p, MapNode node,
void scriptapi_node_on_construct(lua_State *L, v3s16 p, MapNode node);
// Node destructor
void scriptapi_node_on_destruct(lua_State *L, v3s16 p, MapNode node);
+// Node post-destructor
+void scriptapi_node_after_destruct(lua_State *L, v3s16 p, MapNode node);
// Called when a metadata form returns values
void scriptapi_node_on_receive_fields(lua_State *L, v3s16 p,
const std::string &formname,