aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAuke Kok <sofar@foo-projects.org>2017-04-19 23:10:39 -0700
committerparamat <mat.gregory@virginmedia.com>2017-04-22 01:23:51 +0100
commitcca58fe0fd1aac4246a23e1fc4f8469bdd280c6d (patch)
tree0dad1131f8cb0d9ec8c7bc7e35f4e3fc378c4ca0
parent8464da75857c1556f64984c0b014300638e38d4f (diff)
downloadminetest-cca58fe0fd1aac4246a23e1fc4f8469bdd280c6d.tar.gz
minetest-cca58fe0fd1aac4246a23e1fc4f8469bdd280c6d.tar.bz2
minetest-cca58fe0fd1aac4246a23e1fc4f8469bdd280c6d.zip
Add on_flood() callback.
This callback is called if a liquid definitely floods a non-air node on the map. The callback arguments are (pos, oldnode, newnode) and can return a `bool` value indicating whether flooding the node should be cancelled (`return true` will prevent the node from flooding). Documentation is added, the callback function was tested with a modified minetest_game. Note that `return true` will likely cause the node's `on_flood()` callback to be called every second until the node gets removed, so care must be taken to prevent many callbacks from using this return value. The current default liquid update interval is 1.0 seconds, which isn't unmanageable. The larger aim of this patch is to remove the lava cooling ABM, which is a significant cost to idle servers that have lava on their map. This callback will be much more efficient.
-rw-r--r--doc/lua_api.txt7
-rw-r--r--src/map.cpp12
-rw-r--r--src/map.h3
-rw-r--r--src/script/cpp_api/s_node.cpp21
-rw-r--r--src/script/cpp_api/s_node.h1
-rw-r--r--src/server.cpp2
6 files changed, 43 insertions, 3 deletions
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 <deque>
#include <queue>
#if USE_LEVELDB
@@ -637,7 +638,8 @@ s32 Map::transforming_liquid_size() {
return m_transforming_liquid.size();
}
-void Map::transformLiquids(std::map<v3s16, MapBlock*> &modified_blocks)
+void Map::transformLiquids(std::map<v3s16, MapBlock*> &modified_blocks,
+ ServerEnvironment *env)
{
DSTACK(FUNCTION_NAME);
//TimeTaker timer("transformLiquids()");
@@ -897,8 +899,16 @@ void Map::transformLiquids(std::map<v3s16, MapBlock*> &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<v3s16, MapBlock*> & modified_blocks);
+ void transformLiquids(std::map<v3s16, MapBlock*> & 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<v3s16, MapBlock*> modified_blocks;
- m_env->getMap().transformLiquids(modified_blocks);
+ m_env->getMap().transformLiquids(modified_blocks, m_env);
#if 0
/*
Update lighting