From d7270210d04d6c770a40db91ce16a672de8d9890 Mon Sep 17 00:00:00 2001
From: FaceDeer <derksenmobile@gmail.com>
Date: Sun, 15 Oct 2017 00:33:54 -0600
Subject: callbacks moved to after full Digtron layout write is finished

---
 class_layout.lua | 68 +++++++++++++++++++++++++++++++++++++++-----------------
 1 file changed, 48 insertions(+), 20 deletions(-)

(limited to 'class_layout.lua')

diff --git a/class_layout.lua b/class_layout.lua
index c340060..83f3c8b 100644
--- a/class_layout.lua
+++ b/class_layout.lua
@@ -319,13 +319,43 @@ function DigtronLayout.can_write_layout_image(self)
 end
 
 function DigtronLayout.write_layout_image(self, player)
+
+	-- We need to call on_dignode and on_placenode for dug and placed nodes,
+	-- but that triggers falling nodes (sand and whatnot) and destroys Digtrons
+	-- if done during mid-write. So we need to defer the calls until after the
+	-- Digtron has been fully written.
+	
+	local dug_nodes = {}
+	local placed_nodes = {}
+
 	-- destroy the old digtron
 	local oldpos, _ = self.old_pos_pointset:pop()
 	while oldpos ~= nil do
 		local old_node = minetest.get_node(oldpos)
 		local old_meta = minetest.get_meta(oldpos)
-		local old_def = minetest.registered_nodes[old_node.name]
 		minetest.remove_node(oldpos)
+		table.insert(dug_nodes, {oldpos, old_node, old_meta})
+		oldpos, _ = self.old_pos_pointset:pop()
+	end		
+
+	-- create the new one
+	for k, node_image in pairs(self.all) do
+		local new_pos = node_image.pos
+		local new_node = node_image.node
+		local old_node = minetest.get_node(new_pos)
+		minetest.set_node(new_pos, new_node)
+		minetest.get_meta(new_pos):from_table(node_image.meta)
+		
+		table.insert(placed_nodes, {new_pos, new_node, old_node})
+	end
+	
+	
+	for _, dug_node in pairs(dug_nodes) do
+		local old_pos = dug_node[1]
+		local old_node = dug_node[2]
+		local old_meta = dug_node[3]
+
+		minetest.log("action", string.format("%s removes Digtron component %s at (%d, %d, %d)", player:get_player_name(), old_node.name, old_pos.x, old_pos.y, old_pos.z))
 		
 		if modpath_awards then
 			-- We're about to tell the awards mod that we're digging a node, but we
@@ -336,26 +366,23 @@ function DigtronLayout.write_layout_image(self, player)
 		
 		for _, callback in ipairs(minetest.registered_on_dignodes) do
 			-- Copy pos and node because callback can modify them
-			local pos_copy = {x=oldpos.x, y=oldpos.y, z=oldpos.z}
+			local pos_copy = {x=old_pos.x, y=old_pos.y, z=old_pos.z}
 			local oldnode_copy = {name=old_node.name, param1=old_node.param1, param2=old_node.param2}
 			callback(pos_copy, oldnode_copy, player)
 		end
-		
-		minetest.log("action", string.format("%s removes Digtron component %s at (%d, %d, %d)", player:get_player_name(), old_node.name, oldpos.x, oldpos.y, oldpos.z))
-		if old_def.after_dig_node ~= nil then
-			old_def.after_dig_node(oldpos, old_node, old_meta, player)
-		end
-		oldpos, _ = self.old_pos_pointset:pop()
-	end		
 
-	-- create the new one
-	for k, node_image in pairs(self.all) do
-		local new_pos = node_image.pos
-		local new_node = node_image.node
-		local old_node = minetest.get_node(new_pos)
-		minetest.set_node(new_pos, new_node)
-		minetest.get_meta(new_pos):from_table(node_image.meta)
-		minetest.log("action", string.format("%s adds Digtron component %s at (%d, %d, %d)", player:get_player_name(), node_image.node.name, node_image.pos.x, node_image.pos.y, node_image.pos.z))
+		local old_def = minetest.registered_nodes[old_node.name]
+		if old_def ~= nil and old_def.after_dig_node ~= nil then
+			old_def.after_dig_node(old_pos, old_node, old_meta, player)
+		end
+	end
+	
+	for _, placed_node in pairs(placed_nodes) do
+		local new_pos = placed_node[1]
+		local new_node = placed_node[2]
+		local old_node = placed_node[3]
+	
+		minetest.log("action", string.format("%s adds Digtron component %s at (%d, %d, %d)", player:get_player_name(), new_node.name, new_pos.x, new_pos.y, new_pos.z))
 
 		if modpath_awards then
 			-- We're about to tell the awards mod that we're placing a node, but we
@@ -372,10 +399,11 @@ function DigtronLayout.write_layout_image(self, player)
 			callback(pos_copy, newnode_copy, player, oldnode_copy)
 		end
 
-		local new_def = minetest.registered_nodes[node_image.node.name]
-		if new_def.after_place_node ~= nil then
-			new_def.after_place_node(node_image.pos, player)
+		local new_def = minetest.registered_nodes[new_node.name]
+		if new_def ~= nil and new_def.after_place_node ~= nil then
+			new_def.after_place_node(new_pos, player)
 		end
+
 	end
 end
 
-- 
cgit v1.2.3