diff --git a/doc/lua_api.txt b/doc/lua_api.txt index 4e328ac76..774b1e992 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -4002,6 +4002,13 @@ Definition tables ^ Node destructor; called after removing node ^ Not called for bulk node placement (i.e. schematics and VoxelManip) ^ default: nil ]] + on_flood = func(pos, oldnode, newnode), --[[ + ^ Called when a liquid (newnode) is about to flood oldnode, if + ^ it has `floodable = true` in the nodedef. Not called for bulk + ^ node placement (i.e. schematics and VoxelManip) or air nodes. If + ^ return true the node is not flooded, but on_flood callback will + ^ most likely be called over and over again every liquid update + ^ interval. Default: nil ]] after_place_node = func(pos, placer, itemstack, pointed_thing) --[[ ^ Called after constructing node when node was placed using diff --git a/src/map.cpp b/src/map.cpp index 8754813dd..75dcee350 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -44,6 +44,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "database.h" #include "database-dummy.h" #include "database-sqlite3.h" +#include "script/serverscripting.h" #include #include #if USE_LEVELDB @@ -637,7 +638,8 @@ s32 Map::transforming_liquid_size() { return m_transforming_liquid.size(); } -void Map::transformLiquids(std::map &modified_blocks) +void Map::transformLiquids(std::map &modified_blocks, + ServerEnvironment *env) { DSTACK(FUNCTION_NAME); //TimeTaker timer("transformLiquids()"); @@ -897,8 +899,16 @@ void Map::transformLiquids(std::map &modified_blocks) // set the liquid level and flow bit to 0 n0.param2 = ~(LIQUID_LEVEL_MASK | LIQUID_FLOW_DOWN_MASK); } + + // change the node. n0.setContent(new_node_content); + // on_flood() the node + if (floodable_node != CONTENT_AIR) { + if (env->getScriptIface()->node_on_flood(p0, n00, n0)) + continue; + } + // Ignore light (because calling voxalgo::update_lighting_nodes) n0.setLight(LIGHTBANK_DAY, 0, m_nodedef); n0.setLight(LIGHTBANK_NIGHT, 0, m_nodedef); diff --git a/src/map.h b/src/map.h index 739cdb59b..4d7079823 100644 --- a/src/map.h +++ b/src/map.h @@ -266,7 +266,8 @@ public: // For debug printing. Prints "Map: ", "ServerMap: " or "ClientMap: " virtual void PrintInfo(std::ostream &out); - void transformLiquids(std::map & modified_blocks); + void transformLiquids(std::map & modified_blocks, + ServerEnvironment *env); /* Node metadata diff --git a/src/script/cpp_api/s_node.cpp b/src/script/cpp_api/s_node.cpp index adad01e45..2723f84e1 100644 --- a/src/script/cpp_api/s_node.cpp +++ b/src/script/cpp_api/s_node.cpp @@ -178,6 +178,27 @@ void ScriptApiNode::node_on_destruct(v3s16 p, MapNode node) lua_pop(L, 1); // Pop error handler } +bool ScriptApiNode::node_on_flood(v3s16 p, MapNode node, MapNode newnode) +{ + SCRIPTAPI_PRECHECKHEADER + + int error_handler = PUSH_ERROR_HANDLER(L); + + INodeDefManager *ndef = getServer()->ndef(); + + // Push callback function on stack + if (!getItemCallback(ndef->get(node).name.c_str(), "on_flood")) + return false; + + // Call function + push_v3s16(L, p); + pushnode(L, node, ndef); + pushnode(L, newnode, ndef); + PCALL_RES(lua_pcall(L, 3, 1, error_handler)); + lua_remove(L, error_handler); + return (bool) lua_isboolean(L, -1) && (bool) lua_toboolean(L, -1) == true; +} + void ScriptApiNode::node_after_destruct(v3s16 p, MapNode node) { SCRIPTAPI_PRECHECKHEADER diff --git a/src/script/cpp_api/s_node.h b/src/script/cpp_api/s_node.h index fe1180cb3..eb127909d 100644 --- a/src/script/cpp_api/s_node.h +++ b/src/script/cpp_api/s_node.h @@ -42,6 +42,7 @@ public: ServerActiveObject *digger); void node_on_construct(v3s16 p, MapNode node); void node_on_destruct(v3s16 p, MapNode node); + bool node_on_flood(v3s16 p, MapNode node, MapNode newnode); void node_after_destruct(v3s16 p, MapNode node); bool node_on_timer(v3s16 p, MapNode node, f32 dtime); void node_on_receive_fields(v3s16 p, diff --git a/src/server.cpp b/src/server.cpp index a921423d2..ac6265d09 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -599,7 +599,7 @@ void Server::AsyncRunStep(bool initial_step) ScopeProfiler sp(g_profiler, "Server: liquid transform"); std::map modified_blocks; - m_env->getMap().transformLiquids(modified_blocks); + m_env->getMap().transformLiquids(modified_blocks, m_env); #if 0 /* Update lighting