From 2c472a66d1d605eefb167f51529c287f868ffa9b Mon Sep 17 00:00:00 2001
From: Perttu Ahola <celeron55@gmail.com>
Date: Wed, 2 Jan 2013 23:17:52 +0200
Subject: [PATCH] Add ServerEnvironment::setNode()/removeNode() to allow
 setting nodes from the C++ side with proper script-defined
 initialization/destruction

---
 src/environment.cpp | 39 +++++++++++++++++++++++++++++++++++++++
 src/environment.h   |  4 ++++
 src/scriptapi.cpp   | 29 ++---------------------------
 3 files changed, 45 insertions(+), 27 deletions(-)

diff --git a/src/environment.cpp b/src/environment.cpp
index 5bf127a17..020d2b433 100644
--- a/src/environment.cpp
+++ b/src/environment.cpp
@@ -819,6 +819,45 @@ void ServerEnvironment::addActiveBlockModifier(ActiveBlockModifier *abm)
 	m_abms.push_back(ABMWithState(abm));
 }
 
+bool ServerEnvironment::setNode(v3s16 p, const MapNode &n)
+{
+	INodeDefManager *ndef = m_gamedef->ndef();
+	MapNode n_old = m_map->getNodeNoEx(p);
+	// Call destructor
+	if(ndef->get(n_old).has_on_destruct)
+		scriptapi_node_on_destruct(m_lua, p, n_old);
+	// Replace node
+	bool succeeded = m_map->addNodeWithEvent(p, n);
+	if(!succeeded)
+		return false;
+	// Call post-destructor
+	if(ndef->get(n_old).has_after_destruct)
+		scriptapi_node_after_destruct(m_lua, p, n_old);
+	// Call constructor
+	if(ndef->get(n).has_on_construct)
+		scriptapi_node_on_construct(m_lua, p, n);
+	return true;
+}
+
+bool ServerEnvironment::removeNode(v3s16 p)
+{
+	INodeDefManager *ndef = m_gamedef->ndef();
+	MapNode n_old = m_map->getNodeNoEx(p);
+	// Call destructor
+	if(ndef->get(n_old).has_on_destruct)
+		scriptapi_node_on_destruct(m_lua, p, n_old);
+	// Replace with air
+	// This is slightly optimized compared to addNodeWithEvent(air)
+	bool succeeded = m_map->removeNodeWithEvent(p);
+	if(!succeeded)
+		return false;
+	// Call post-destructor
+	if(ndef->get(n_old).has_after_destruct)
+		scriptapi_node_after_destruct(m_lua, p, n_old);
+	// Air doesn't require constructor
+	return true;
+}
+
 std::set<u16> ServerEnvironment::getObjectsInsideRadius(v3f pos, float radius)
 {
 	std::set<u16> objects;
diff --git a/src/environment.h b/src/environment.h
index 0cc53f9a6..d17edeacd 100644
--- a/src/environment.h
+++ b/src/environment.h
@@ -283,6 +283,10 @@ class ServerEnvironment : public Environment
 		Other stuff
 		-------------------------------------------
 	*/
+
+	// Script-aware node setters
+	bool setNode(v3s16 p, const MapNode &n);
+	bool removeNode(v3s16 p);
 	
 	// Find all active objects inside a radius around a point
 	std::set<u16> getObjectsInsideRadius(v3f pos, float radius);
diff --git a/src/scriptapi.cpp b/src/scriptapi.cpp
index a79622db3..04f741ad3 100644
--- a/src/scriptapi.cpp
+++ b/src/scriptapi.cpp
@@ -3540,20 +3540,7 @@ class EnvRef
 		v3s16 pos = read_v3s16(L, 2);
 		MapNode n = readnode(L, 3, ndef);
 		// Do it
-		MapNode n_old = env->getMap().getNodeNoEx(pos);
-		// 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);
-		}
+		bool succeeded = env->setNode(pos, n);
 		lua_pushboolean(L, succeeded);
 		return 1;
 	}
@@ -3574,20 +3561,8 @@ class EnvRef
 		// parameters
 		v3s16 pos = read_v3s16(L, 2);
 		// Do it
-		MapNode n_old = env->getMap().getNodeNoEx(pos);
-		// Call destructor
-		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);
-		}
+		bool succeeded = env->removeNode(pos);
 		lua_pushboolean(L, succeeded);
-		// Air doesn't require constructor
 		return 1;
 	}
 
-- 
GitLab