[minetest-mod-mesecons] 01/03: New upstream version 2016.09.13

Julien Puydt julien.puydt at laposte.net
Sat Sep 17 18:16:11 UTC 2016


This is an automated email from the git hooks/post-receive script.

jpuydt-guest pushed a commit to branch master
in repository minetest-mod-mesecons.

commit 9bcd93be9b9bfad2f44fdbe4531e827f8a26c209
Author: Julien Puydt <julien.puydt at laposte.net>
Date:   Sat Sep 17 10:36:42 2016 +0200

    New upstream version 2016.09.13
---
 README.md                                          |   1 +
 documentation.json                                 |   2 +-
 mesecons/actionqueue.lua                           |   6 +-
 mesecons/doc/mesecon/description.html              |   1 -
 mesecons/init.lua                                  |  45 ++---
 mesecons/internal.lua                              | 200 +++++++--------------
 mesecons/legacy.lua                                |  38 ++--
 mesecons/services.lua                              |  11 +-
 .../textures/jeija_close_window.png                | Bin
 .../textures/jeija_microcontroller_bottom.png      | Bin
 .../textures/jeija_microcontroller_sides.png       | Bin
 mesecons/util.lua                                  | 176 +++++++++++++++---
 mesecons_luacontroller/init.lua                    |   2 -
 mesecons_mvps/init.lua                             |   1 -
 mesecons_random/init.lua                           |   2 +-
 mesecons_receiver/init.lua                         |  10 +-
 mesecons_wires/depends.txt                         |   1 +
 mesecons_wires/doc/mesecon/description.html        |   1 +
 .../doc/mesecon/preview.png                        | Bin
 .../doc/mesecon/recipe.png                         | Bin
 mesecons/wires.lua => mesecons_wires/init.lua      |   7 +-
 21 files changed, 258 insertions(+), 246 deletions(-)

diff --git a/README.md b/README.md
index ff08403..37cd2d5 100644
--- a/README.md
+++ b/README.md
@@ -53,6 +53,7 @@ These awesome people made Mesecons possible!
 
 | Contributor     | Contribution                     |
 | --------------- | -------------------------------- |
+| Hawk777         | Code for VoxelManip caching      |
 | Jat15           | Various tweaks.                  |
 | Jeija           | **Main developer! Everything.**  |
 | Jordach         | Noteblock sounds.                |
diff --git a/documentation.json b/documentation.json
index 8cc0254..711f7d2 100644
--- a/documentation.json
+++ b/documentation.json
@@ -1,6 +1,6 @@
 {
 	"Conductors" : {
-		"Mesecon" : "mesecons/doc/mesecon",
+		"Mesecon" : "mesecons_wires/doc/mesecon",
 		"Insulated Wire" : "mesecons_insulated/doc/insulated",
 		"T-Junction" : "mesecons_extrawires/doc/tjunction",
 		"Crossing" : "mesecons_extrawires/doc/crossing",
diff --git a/mesecons/actionqueue.lua b/mesecons/actionqueue.lua
index e300ea7..f3479ce 100644
--- a/mesecons/actionqueue.lua
+++ b/mesecons/actionqueue.lua
@@ -87,7 +87,11 @@ minetest.register_globalstep(function (dtime)
 end)
 
 function mesecon.queue:execute(action)
-	mesecon.queue.funcs[action.func](action.pos, unpack(action.params))
+	-- ignore if action queue function name doesn't exist,
+	-- (e.g. in case the action queue savegame was written by an old mesecons version)
+	if mesecon.queue.funcs[action.func] then
+		mesecon.queue.funcs[action.func](action.pos, unpack(action.params))
+	end
 end
 
 
diff --git a/mesecons/doc/mesecon/description.html b/mesecons/doc/mesecon/description.html
deleted file mode 100644
index a22ec65..0000000
--- a/mesecons/doc/mesecon/description.html
+++ /dev/null
@@ -1 +0,0 @@
- Mesecons are the wires, use them to connect effectors with receptors.
diff --git a/mesecons/init.lua b/mesecons/init.lua
index 3ab4f4a..83e611b 100644
--- a/mesecons/init.lua
+++ b/mesecons/init.lua
@@ -3,7 +3,7 @@
 -- |  \/  | |___ ____  |___ |      |    | | \  | |____
 -- |      | |        | |    |      |    | |  \ |     |
 -- |      | |___ ____| |___ |____  |____| |   \| ____|
--- by Jeija, Uberi (Temperest), sfan5, VanessaE
+-- by Jeija, Uberi (Temperest), sfan5, VanessaE, Hawk777 and contributors
 --
 --
 --
@@ -11,7 +11,7 @@
 -- See the documentation on the forum for additional information, especially about crafting
 --
 --
--- For developer documentation see the Developers' section on mesecons.TK
+-- For basic development resources, see http://mesecons.net/developers.html
 --
 --
 --
@@ -70,19 +70,11 @@ dofile(minetest.get_modpath("mesecons").."/internal.lua");
 -- these are the only functions you need to remember
 
 mesecon.queue:add_function("receptor_on", function (pos, rules)
-	rules = rules or mesecon.rules.default
+	mesecon.vm_begin()
 
-	-- if area (any of the rule targets) is not loaded, keep trying and call this again later
-	for _, rule in ipairs(mesecon.flattenrules(rules)) do
-		local np = vector.add(pos, rule)
-		-- if area is not loaded, keep trying
-		if minetest.get_node_or_nil(np) == nil then
-			mesecon.queue:add_action(pos, "receptor_on", {rules}, nil, rules)
-			return
-		end
-	end
+	rules = rules or mesecon.rules.default
 
-	-- execute action
+	-- Call turnon on all linking positions
 	for _, rule in ipairs(mesecon.flattenrules(rules)) do
 		local np = vector.add(pos, rule)
 		local rulenames = mesecon.rules_link_rule_all(pos, rule)
@@ -90,6 +82,8 @@ mesecon.queue:add_function("receptor_on", function (pos, rules)
 			mesecon.turnon(np, rulename)
 		end
 	end
+
+	mesecon.vm_commit()
 end)
 
 function mesecon.receptor_on(pos, rules)
@@ -99,23 +93,21 @@ end
 mesecon.queue:add_function("receptor_off", function (pos, rules)
 	rules = rules or mesecon.rules.default
 
-	-- if area (any of the rule targets) is not loaded, keep trying and call this again later
-	for _, rule in ipairs(mesecon.flattenrules(rules)) do
-		local np = vector.add(pos, rule)
-		if minetest.get_node_or_nil(np) == nil then
-			mesecon.queue:add_action(pos, "receptor_off", {rules}, nil, rules)
-			return
-		end
-	end
-
+	-- Call turnoff on all linking positions
 	for _, rule in ipairs(mesecon.flattenrules(rules)) do
 		local np = vector.add(pos, rule)
 		local rulenames = mesecon.rules_link_rule_all(pos, rule)
 		for _, rulename in ipairs(rulenames) do
-			if not mesecon.connected_to_receptor(np, mesecon.invertRule(rule)) then
-				mesecon.turnoff(np, rulename)
+			mesecon.vm_begin()
+			mesecon.changesignal(np, minetest.get_node(np), rulename, mesecon.state.off, 2)
+
+			-- Turnoff returns true if turnoff process was successful, no onstate receptor
+			-- was found along the way. Commit changes that were made in voxelmanip. If turnoff
+			-- returns true, an onstate receptor was found, abort voxelmanip transaction.
+			if (mesecon.turnoff(np, rulename)) then
+				mesecon.vm_commit()
 			else
-				mesecon.changesignal(np, minetest.get_node(np), rulename, mesecon.state.off, 2)
+				mesecon.vm_abort()
 			end
 		end
 	end
@@ -132,8 +124,5 @@ print("[OK] Mesecons")
 -- To be removed in future releases
 dofile(minetest.get_modpath("mesecons").."/legacy.lua");
 
---The actual wires
-dofile(minetest.get_modpath("mesecons").."/wires.lua");
-
 --Services like turnoff receptor on dignode and so on
 dofile(minetest.get_modpath("mesecons").."/services.lua");
diff --git a/mesecons/internal.lua b/mesecons/internal.lua
index d479852..e5ba91e 100644
--- a/mesecons/internal.lua
+++ b/mesecons/internal.lua
@@ -37,11 +37,6 @@
 -- HIGH-LEVEL Internals
 -- mesecon.is_power_on(pos)				--> Returns true if pos emits power in any way
 -- mesecon.is_power_off(pos)				--> Returns true if pos does not emit power in any way
--- mesecon.turnon(pos, link) 				--> link is the input rule that caused calling turnon, turns on every connected node, iterative
--- mesecon.turnoff(pos, link)				--> link is the input rule that caused calling turnoff, turns off every connected node, iterative
--- mesecon.connected_to_receptor(pos, link)		--> Returns true if pos is connected to a receptor directly or via conductors, iterative
--- mesecon.rules_link(output, input, dug_outputrules)	--> Returns true if outputposition + outputrules = inputposition and inputposition + inputrules = outputposition (if the two positions connect)
--- mesecon.rules_link_anydir(outp., inp., d_outpr.)	--> Same as rules mesecon.rules_link but also returns true if output and input are swapped
 -- mesecon.is_powered(pos)				--> Returns true if pos is powered by a receptor or a conductor
 
 -- RULES ROTATION helpers
@@ -76,7 +71,7 @@ function mesecon.get_conductor(nodename)
 	end
 end
 
-function mesecon.get_any_outputrules (node)
+function mesecon.get_any_outputrules(node)
 	if not node then return nil end
 
 	if mesecon.is_conductor(node.name) then
@@ -86,7 +81,7 @@ function mesecon.get_any_outputrules (node)
 	end
 end
 
-function mesecon.get_any_inputrules (node)
+function mesecon.get_any_inputrules(node)
 	if not node then return nil end
 
 	if mesecon.is_conductor(node.name) then
@@ -96,7 +91,7 @@ function mesecon.get_any_inputrules (node)
 	end
 end
 
-function mesecon.get_any_rules (node)
+function mesecon.get_any_rules(node)
 	return mesecon.mergetable(mesecon.get_any_inputrules(node) or {},
 		mesecon.get_any_outputrules(node) or {})
 end
@@ -371,38 +366,32 @@ function mesecon.is_power_off(pos, rulename)
 	return false
 end
 
+-- Turn off an equipotential section starting at `pos`, which outputs in the direction of `link`.
+-- Breadth-first search. Map is abstracted away in a voxelmanip.
+-- Follow all all conductor paths replacing conductors that were already
+-- looked at, activating / changing all effectors along the way.
 function mesecon.turnon(pos, link)
 	local frontiers = {{pos = pos, link = link}}
 
 	local depth = 1
-	while frontiers[depth] do
-		local f = frontiers[depth]
+	while frontiers[1] do
+		local f = table.remove(frontiers, 1)
 		local node = mesecon.get_node_force(f.pos)
 
-		-- area not loaded, postpone action
 		if not node then
-			mesecon.queue:add_action(f.pos, "turnon", {link}, nil, true)
+			-- Area does not exist; do nothing
 		elseif mesecon.is_conductor_off(node, f.link) then
 			local rules = mesecon.conductor_get_rules(node)
 
-			minetest.swap_node(f.pos, {name = mesecon.get_conductor_on(node, f.link),
-				param2 = node.param2})
-
-			-- call turnon on neighbors: normal rules
+			-- Call turnon on neighbors
 			for _, r in ipairs(mesecon.rule2meta(f.link, rules)) do
 				local np = vector.add(f.pos, r)
-
-				-- area not loaded, postpone action
-				if not mesecon.get_node_force(np) then
-					mesecon.queue:add_action(np, "turnon", {rulename},
-						nil, true)
-				else
-					local links = mesecon.rules_link_rule_all(f.pos, r)
-					for _, l in ipairs(links) do
-						table.insert(frontiers, {pos = np, link = l})
-					end
+				for _, l in ipairs(mesecon.rules_link_rule_all(f.pos, r)) do
+					table.insert(frontiers, {pos = np, link = l})
 				end
 			end
+
+			mesecon.swap_node_force(f.pos, mesecon.get_conductor_on(node, f.link))
 		elseif mesecon.is_effector(node.name) then
 			mesecon.changesignal(f.pos, node, f.link, mesecon.state.on, depth)
 			if mesecon.is_effector_off(node.name) then
@@ -413,141 +402,81 @@ function mesecon.turnon(pos, link)
 	end
 end
 
-mesecon.queue:add_function("turnon", function (pos, rulename, recdepth)
-	mesecon.turnon(pos, rulename, recdepth)
-end)
-
+-- Turn on an equipotential section starting at `pos`, which outputs in the direction of `link`.
+-- Breadth-first search. Map is abstracted away in a voxelmanip.
+-- Follow all all conductor paths replacing conductors that were already
+-- looked at, deactivating / changing all effectors along the way.
+-- In case an onstate receptor is discovered, abort the process by returning false, which will
+-- cause `receptor_off` to discard all changes made in the voxelmanip.
+-- Contrary to turnon, turnoff has to cache all change and deactivate signals so that they will only
+-- be called in the very end when we can be sure that no conductor was found along the path.
+--
+-- Signal table entry structure:
+-- {
+--	pos = position of effector,
+--	node = node descriptor (name, param1 and param2),
+--	link = link the effector is connected to,
+--	depth = indicates order in which signals wire fired, higher is later
+-- }
 function mesecon.turnoff(pos, link)
 	local frontiers = {{pos = pos, link = link}}
+	local signals = {}
 
 	local depth = 1
-	while frontiers[depth] do
-		local f = frontiers[depth]
+	while frontiers[1] do
+		local f = table.remove(frontiers, 1)
 		local node = mesecon.get_node_force(f.pos)
 
-		-- area not loaded, postpone action
 		if not node then
-			mesecon.queue:add_action(f.pos, "turnoff", {link}, nil, true)
+			-- Area does not exist; do nothing
 		elseif mesecon.is_conductor_on(node, f.link) then
 			local rules = mesecon.conductor_get_rules(node)
-
-			minetest.swap_node(f.pos, {name = mesecon.get_conductor_off(node, f.link),
-				param2 = node.param2})
-
-			-- call turnoff on neighbors: normal rules
 			for _, r in ipairs(mesecon.rule2meta(f.link, rules)) do
 				local np = vector.add(f.pos, r)
 
-				-- area not loaded, postpone action
-				if not mesecon.get_node_force(np) then
-					mesecon.queue:add_action(np, "turnoff", {rulename},
-						nil, true)
-				else
-					local links = mesecon.rules_link_rule_all(f.pos, r)
-					for _, l in ipairs(links) do
-						table.insert(frontiers, {pos = np, link = l})
+				-- Check if an onstate receptor is connected. If that is the case,
+				-- abort this turnoff process by returning false. `receptor_off` will
+				-- discard all the changes that we made in the voxelmanip:
+				for _, l in ipairs(mesecon.rules_link_rule_all_inverted(f.pos, r)) do
+					if mesecon.is_receptor_on(mesecon.get_node_force(np).name) then
+						return false
 					end
 				end
-			end
-		elseif mesecon.is_effector(node.name) then
-			mesecon.changesignal(f.pos, node, f.link, mesecon.state.off, depth)
-			if mesecon.is_effector_on(node.name) and not mesecon.is_powered(f.pos) then
-				mesecon.deactivate(f.pos, node, f.link, depth)
-			end
-		end
-		depth = depth + 1
-	end
-end
-
-mesecon.queue:add_function("turnoff", function (pos, rulename, recdepth)
-	mesecon.turnoff(pos, rulename, recdepth)
-end)
-
-
-function mesecon.connected_to_receptor(pos, link)
-	local node = mesecon.get_node_force(pos)
-	if not node then return false end
-
-	-- Check if conductors around are connected
-	local rules = mesecon.get_any_inputrules(node)
-	if not rules then return false end
-
-	for _, rule in ipairs(mesecon.rule2meta(link, rules)) do
-		local links = mesecon.rules_link_rule_all_inverted(pos, rule)
-		for _, l in ipairs(links) do
-			local np = vector.add(pos, l)
-			if mesecon.find_receptor_on(np, mesecon.invertRule(l)) then
-				return true
-			end
-		end
-	end
 
-	return false
-end
-
-function mesecon.find_receptor_on(pos, link)
-	local frontiers = {{pos = pos, link = link}}
-	local checked = {}
-
-	-- List of positions that have been searched for onstate receptors
-	local depth = 1
-	while frontiers[depth] do
-		local f = frontiers[depth]
-		local node = mesecon.get_node_force(f.pos)
-
-		if not node then return false end
-		if mesecon.is_receptor_on(node.name) then return true end
-		if mesecon.is_conductor_on(node, f.link) then
-			local rules = mesecon.conductor_get_rules(node)
-
-			-- call turnoff on neighbors: normal rules
-			for _, r in ipairs(mesecon.rule2meta(f.link, rules)) do
-				local np = vector.add(f.pos, r)
-
-				local links = mesecon.rules_link_rule_all_inverted(f.pos, r)
-				for _, l in ipairs(links) do
-					local checkedstring = np.x..np.y..np.z..l.x..l.y..l.z
-					if not checked[checkedstring] then
-						table.insert(frontiers, {pos = np, link = l})
-						checked[checkedstring] = true
-					end
+				-- Call turnoff on neighbors
+				for _, l in ipairs(mesecon.rules_link_rule_all(f.pos, r)) do
+					table.insert(frontiers, {pos = np, link = l})
 				end
 			end
 
+			mesecon.swap_node_force(f.pos, mesecon.get_conductor_off(node, f.link))
+		elseif mesecon.is_effector(node.name) then
+			table.insert(signals, {
+				pos = f.pos,
+				node = node,
+				link = f.link,
+				depth = depth
+			})
 		end
 		depth = depth + 1
 	end
-end
-
-function mesecon.rules_link(output, input, dug_outputrules) --output/input are positions (outputrules optional, used if node has been dug), second return value: the name of the affected input rule
-	local outputnode = mesecon.get_node_force(output)
-	local inputnode = mesecon.get_node_force(input)
-
-	local outputrules = dug_outputrules or mesecon.get_any_outputrules (outputnode)
-	local inputrules = mesecon.get_any_inputrules (inputnode)
-	if not outputrules or not inputrules then
-		return
-	end
 
-	for _, outputrule in ipairs(mesecon.flattenrules(outputrules)) do
-		-- Check if output sends to input
-		if vector.equals(vector.add(output, outputrule), input) then
-			for _, inputrule in ipairs(mesecon.flattenrules(inputrules)) do
-				-- Check if input accepts from output
-				if  vector.equals(vector.add(input, inputrule), output) then
-					return true, inputrule
-				end
-			end
+	for _, sig in ipairs(signals) do
+		mesecon.changesignal(sig.pos, sig.node, sig.link, mesecon.state.off, sig.depth)
+		if mesecon.is_effector_on(sig.node.name) and not mesecon.is_powered(sig.pos) then
+			mesecon.deactivate(sig.pos, sig.node, sig.link, sig.depth)
 		end
 	end
 
-	return false
+	return true
 end
 
+-- Get all linking inputrules of inputnode (effector or conductor) that is connected to
+-- outputnode (receptor or conductor) at position `output` and has an output in direction `rule`
 function mesecon.rules_link_rule_all(output, rule)
 	local input = vector.add(output, rule)
 	local inputnode = mesecon.get_node_force(input)
-	local inputrules = mesecon.get_any_inputrules (inputnode)
+	local inputrules = mesecon.get_any_inputrules(inputnode)
 	if not inputrules then
 		return {}
 	end
@@ -563,11 +492,12 @@ function mesecon.rules_link_rule_all(output, rule)
 	return rules
 end
 
+-- Get all linking outputnodes of outputnode (receptor or conductor) that is connected to
+-- inputnode (effector or conductor) at position `input` and has an input in direction `rule`
 function mesecon.rules_link_rule_all_inverted(input, rule)
-	--local irule = mesecon.invertRule(rule)
 	local output = vector.add(input, rule)
 	local outputnode = mesecon.get_node_force(output)
-	local outputrules = mesecon.get_any_outputrules (outputnode)
+	local outputrules = mesecon.get_any_outputrules(outputnode)
 	if not outputrules then
 		return {}
 	end
@@ -581,10 +511,6 @@ function mesecon.rules_link_rule_all_inverted(input, rule)
 	return rules
 end
 
-function mesecon.rules_link_anydir(pos1, pos2)
-	return mesecon.rules_link(pos1, pos2) or mesecon.rules_link(pos2, pos1)
-end
-
 function mesecon.is_powered(pos, rule)
 	local node = mesecon.get_node_force(pos)
 	local rules = mesecon.get_any_inputrules(node)
diff --git a/mesecons/legacy.lua b/mesecons/legacy.lua
index 6d8ccca..ad7093a 100644
--- a/mesecons/legacy.lua
+++ b/mesecons/legacy.lua
@@ -1,30 +1,14 @@
--- Ugly hack to prevent breaking compatibility with other mods
--- Just remove the following two functions to delete the hack, to be done when other mods have updated
-function mesecon.receptor_on(self, pos, rules)
-	if (self.receptor_on) then
-		print("[Mesecons] Warning: A mod with mesecon support called mesecon:receptor_on.")
-		print("[Mesecons]          If you are the programmer of this mod, please update it ")
-		print("[Mesecons]          to use mesecon.receptor_on instead. mesecon:* is deprecated")
-		print("[Mesecons]          Otherwise, please make sure you're running the latest version")
-		print("[Mesecons]          of that mod and inform the mod creator.")
-	else
-		rules = pos
-		pos = self
-	end
-	mesecon.queue:add_action(pos, "receptor_on", {rules}, nil, rules)
-end
+-- Un-forceload any forceloaded mapblocks from older versions of Mesecons which
+-- used forceloading instead of VoxelManipulators.
+local BLOCKSIZE = 16
 
-function mesecon.receptor_off(self, pos, rules)
-	if (self.receptor_off) then
-		print("[Mesecons] Warning: A mod with mesecon support called mesecon:receptor_off.")
-		print("[Mesecons]          If you are the programmer of this mod, please update it ")
-		print("[Mesecons]          to use mesecon.receptor_off instead. mesecon:* is deprecated")
-		print("[Mesecons]          Otherwise, please make sure you're running the latest version")
-		print("[Mesecons]          of that mod and inform the mod creator.")
-	else
-		rules = pos
-		pos = self
-	end
-	mesecon.queue:add_action(pos, "receptor_off", {rules}, nil, rules)
+-- convert block hash --> node position
+local function unhash_blockpos(hash)
+	return vector.multiply(minetest.get_position_from_hash(hash), BLOCKSIZE)
 end
 
+local old_forceloaded_blocks = mesecon.file2table("mesecon_forceloaded")
+for hash, _ in pairs(old_forceloaded_blocks) do
+	minetest.forceload_free_block(unhash_blockpos(hash))
+end
+os.remove(minetest.get_worldpath()..DIR_DELIM.."mesecon_forceloaded")
diff --git a/mesecons/services.lua b/mesecons/services.lua
index 343410a..1abbc0c 100644
--- a/mesecons/services.lua
+++ b/mesecons/services.lua
@@ -1,7 +1,7 @@
 -- Dig and place services
 
-mesecon.on_placenode = function (pos, node)
-	mesecon.update_autoconnect(pos, node)
+mesecon.on_placenode = function(pos, node)
+	mesecon.execute_autoconnect_hooks_now(pos, node)
 
 	-- Receptors: Send on signal when active
 	if mesecon.is_receptor_on(node.name) then
@@ -52,16 +52,15 @@ mesecon.on_placenode = function (pos, node)
 	end
 end
 
-mesecon.on_dignode = function (pos, node)
+mesecon.on_dignode = function(pos, node)
 	if mesecon.is_conductor_on(node) then
 		mesecon.receptor_off(pos, mesecon.conductor_get_rules(node))
 	elseif mesecon.is_receptor_on(node.name) then
 		mesecon.receptor_off(pos, mesecon.receptor_get_rules(node))
 	end
-	mesecon.queue:add_action(pos, "update_autoconnect", {node})
-end
 
-mesecon.queue:add_function("update_autoconnect", mesecon.update_autoconnect)
+	mesecon.execute_autoconnect_hooks_queue(pos, node)
+end
 
 minetest.register_on_placenode(mesecon.on_placenode)
 minetest.register_on_dignode(mesecon.on_dignode)
diff --git a/mesecons_commandblock/textures/jeija_close_window.png b/mesecons/textures/jeija_close_window.png
similarity index 100%
rename from mesecons_commandblock/textures/jeija_close_window.png
rename to mesecons/textures/jeija_close_window.png
diff --git a/mesecons_microcontroller/textures/jeija_microcontroller_bottom.png b/mesecons/textures/jeija_microcontroller_bottom.png
similarity index 100%
rename from mesecons_microcontroller/textures/jeija_microcontroller_bottom.png
rename to mesecons/textures/jeija_microcontroller_bottom.png
diff --git a/mesecons_microcontroller/textures/jeija_microcontroller_sides.png b/mesecons/textures/jeija_microcontroller_sides.png
similarity index 100%
rename from mesecons_microcontroller/textures/jeija_microcontroller_sides.png
rename to mesecons/textures/jeija_microcontroller_sides.png
diff --git a/mesecons/util.lua b/mesecons/util.lua
index 3827dce..c9ba7fc 100644
--- a/mesecons/util.lua
+++ b/mesecons/util.lua
@@ -219,7 +219,7 @@ function mesecon.table2file(filename, table)
 	f:close()
 end
 
--- Forceloading: Force server to load area if node is nil
+-- Block position "hashing" (convert to integer) functions for voxelmanip cache
 local BLOCKSIZE = 16
 
 -- convert node position --> block hash
@@ -236,40 +236,160 @@ local function unhash_blockpos(hash)
 	return vector.multiply(minetest.get_position_from_hash(hash), BLOCKSIZE)
 end
 
-mesecon.forceloaded_blocks = {}
+-- Maps from a hashed mapblock position (as returned by hash_blockpos) to a
+-- table.
+--
+-- Contents of the table are:
+-- “vm” → the VoxelManipulator
+-- “va” → the VoxelArea
+-- “data” → the data array
+-- “param1” → the param1 array
+-- “param2” → the param2 array
+-- “dirty” → true if data has been modified
+--
+-- Nil if no VM-based transaction is in progress.
+local vm_cache = nil
+
+-- Starts a VoxelManipulator-based transaction.
+--
+-- During a VM transaction, calls to vm_get_node and vm_swap_node operate on a
+-- cached copy of the world loaded via VoxelManipulators. That cache can later
+-- be committed to the real map by means of vm_commit or discarded by means of
+-- vm_abort.
+function mesecon.vm_begin()
+	vm_cache = {}
+end
 
--- get node and force-load area
-function mesecon.get_node_force(pos)
+-- Finishes a VoxelManipulator-based transaction, freeing the VMs and map data
+-- and writing back any modified areas.
+function mesecon.vm_commit()
+	for hash, tbl in pairs(vm_cache) do
+		if tbl.dirty then
+			local vm = tbl.vm
+			vm:set_data(tbl.data)
+			vm:write_to_map()
+			vm:update_map()
+		end
+	end
+	vm_cache = nil
+end
+
+-- Finishes a VoxelManipulator-based transaction, freeing the VMs and throwing
+-- away any modified areas.
+function mesecon.vm_abort()
+	vm_cache = nil
+end
+
+-- Gets the cache entry covering a position, populating it if necessary.
+local function vm_get_or_create_entry(pos)
 	local hash = hash_blockpos(pos)
+	local tbl = vm_cache[hash]
+	if not tbl then
+		local vm = minetest.get_voxel_manip(pos, pos)
+		local min_pos, max_pos = vm:get_emerged_area()
+		local va = VoxelArea:new{MinEdge = min_pos, MaxEdge = max_pos}
+		tbl = {vm = vm, va = va, data = vm:get_data(), param1 = vm:get_light_data(), param2 = vm:get_param2_data(), dirty = false}
+		vm_cache[hash] = tbl
+	end
+	return tbl
+end
 
-	if mesecon.forceloaded_blocks[hash] == nil then
-		-- if no more forceload spaces are available, try again next time
-		if minetest.forceload_block(pos) then
-			mesecon.forceloaded_blocks[hash] = 0
-		end
+-- Gets the node at a given position during a VoxelManipulator-based
+-- transaction.
+function mesecon.vm_get_node(pos)
+	local tbl = vm_get_or_create_entry(pos)
+	local index = tbl.va:indexp(pos)
+	local node_value = tbl.data[index]
+	if node_value == core.CONTENT_IGNORE then
+		return nil
 	else
-		mesecon.forceloaded_blocks[hash] = 0
+		local node_param1 = tbl.param1[index]
+		local node_param2 = tbl.param2[index]
+		return {name = minetest.get_name_from_content_id(node_value), param1 = node_param1, param2 = node_param2}
 	end
+end
 
-	return minetest.get_node_or_nil(pos)
+-- Sets a node’s name during a VoxelManipulator-based transaction.
+--
+-- Existing param1, param2, and metadata are left alone.
+function mesecon.vm_swap_node(pos, name)
+	local tbl = vm_get_or_create_entry(pos)
+	local index = tbl.va:indexp(pos)
+	tbl.data[index] = minetest.get_content_id(name)
+	tbl.dirty = true
 end
 
-minetest.register_globalstep(function (dtime)
-	for hash, time in pairs(mesecon.forceloaded_blocks) do
-		-- unload forceloaded blocks after 10 minutes without usage
-		if (time > mesecon.setting("forceload_timeout", 600)) then
-			minetest.forceload_free_block(unhash_blockpos(hash))
-			mesecon.forceloaded_blocks[hash] = nil
-		else
-			mesecon.forceloaded_blocks[hash] = time + dtime
+-- Gets the node at a given position, regardless of whether it is loaded or
+-- not, respecting a transaction if one is in progress.
+--
+-- Outside a VM transaction, if the mapblock is not loaded, it is pulled into
+-- the server’s main map data cache and then accessed from there.
+--
+-- Inside a VM transaction, the transaction’s VM cache is used.
+function mesecon.get_node_force(pos)
+	if vm_cache then
+		return mesecon.vm_get_node(pos)
+	else
+		local node = minetest.get_node_or_nil(pos)
+		if node == nil then
+			-- Node is not currently loaded; use a VoxelManipulator to prime
+			-- the mapblock cache and try again.
+			minetest.get_voxel_manip(pos, pos)
+			node = minetest.get_node_or_nil(pos)
 		end
+		return node
+	end
+end
+
+-- Swaps the node at a given position, regardless of whether it is loaded or
+-- not, respecting a transaction if one is in progress.
+--
+-- Outside a VM transaction, if the mapblock is not loaded, it is pulled into
+-- the server’s main map data cache and then accessed from there.
+--
+-- Inside a VM transaction, the transaction’s VM cache is used.
+--
+-- This function can only be used to change the node’s name, not its parameters
+-- or metadata.
+function mesecon.swap_node_force(pos, name)
+	if vm_cache then
+		return mesecon.vm_swap_node(pos, name)
+	else
+		-- This serves to both ensure the mapblock is loaded and also hand us
+		-- the old node table so we can preserve param2.
+		local node = mesecon.get_node_force(pos)
+		node.name = name
+		minetest.swap_node(pos, node)
+	end
+end
+
+-- Autoconnect Hooks
+-- Nodes like conductors may change their appearance and their connection rules
+-- right after being placed or after being dug, e.g. the default wires use this
+-- to automatically connect to linking nodes after placement.
+-- After placement, the update function will be executed immediately so that the
+-- possibly changed rules can be taken into account when recalculating the circuit.
+-- After digging, the update function will be queued and executed after
+-- recalculating the circuit. The update function must take care of updating the
+-- node at the given position itself, but also all of the other nodes the given
+-- position may have (had) a linking connection to.
+mesecon.autoconnect_hooks = {}
+
+-- name: A unique name for the hook, e.g. "foowire". Used to name the actionqueue function.
+-- fct: The update function with parameters function(pos, node)
+function mesecon.register_autoconnect_hook(name, fct)
+	mesecon.autoconnect_hooks[name] = fct
+	mesecon.queue:add_function("autoconnect_hook_"..name, fct)
+end
+
+function mesecon.execute_autoconnect_hooks_now(pos, node)
+	for _, fct in pairs(mesecon.autoconnect_hooks) do
+		fct(pos, node)
 	end
-end)
-
--- Store and read the forceloaded blocks to / from a file
--- so that those blocks are remembered when the game
--- is restarted
-mesecon.forceloaded_blocks = mesecon.file2table("mesecon_forceloaded")
-minetest.register_on_shutdown(function()
-	mesecon.table2file("mesecon_forceloaded", mesecon.forceloaded_blocks)
-end)
+end
+
+function mesecon.execute_autoconnect_hooks_queue(pos, node)
+	for name in pairs(mesecon.autoconnect_hooks) do
+		mesecon.queue:add_action(pos, "autoconnect_hook_"..name, {node})
+	end
+end
diff --git a/mesecons_luacontroller/init.lua b/mesecons_luacontroller/init.lua
index 458286f..7d76b26 100644
--- a/mesecons_luacontroller/init.lua
+++ b/mesecons_luacontroller/init.lua
@@ -20,8 +20,6 @@
 -- The Sandbox
 -- The whole code of the controller runs in a sandbox,
 -- a very restricted environment.
--- However, as this does not prevent you from using e.g. loops,
--- we need to check for these prohibited commands first.
 -- Actually the only way to damage the server is to
 -- use too much memory from the sandbox.
 -- You can add more functions to the environment
diff --git a/mesecons_mvps/init.lua b/mesecons_mvps/init.lua
index 1707408..2c6161b 100644
--- a/mesecons_mvps/init.lua
+++ b/mesecons_mvps/init.lua
@@ -200,7 +200,6 @@ end
 mesecon.register_on_mvps_move(function(moved_nodes)
 	for _, n in ipairs(moved_nodes) do
 		mesecon.on_placenode(n.pos, n.node)
-		mesecon.update_autoconnect(n.pos)
 	end
 end)
 
diff --git a/mesecons_random/init.lua b/mesecons_random/init.lua
index e37886b..4c1d299 100644
--- a/mesecons_random/init.lua
+++ b/mesecons_random/init.lua
@@ -9,7 +9,7 @@ minetest.register_node("mesecons_random:removestone", {
 	mesecons = {effector = {
 		action_on = function (pos, node)
 			minetest.remove_node(pos)
-			mesecon.update_autoconnect(pos)
+			mesecon.on_dignode(pos, node)
 		end
 	}}
 })
diff --git a/mesecons_receiver/init.lua b/mesecons_receiver/init.lua
index 36f4659..9284e57 100644
--- a/mesecons_receiver/init.lua
+++ b/mesecons_receiver/init.lua
@@ -104,13 +104,8 @@ function mesecon.receiver_place(rcpt_pos)
 
 	if string.find(nn.name, "mesecons:wire_") ~= nil then
 		minetest.dig_node(pos)
-		if mesecon.is_power_on(rcpt_pos) then
-			minetest.set_node(pos, {name = "mesecons_receiver:receiver_on", param2 = node.param2})
-			mesecon.receptor_on(pos, receiver_get_rules(node))
-		else
-			minetest.set_node(pos, {name = "mesecons_receiver:receiver_off", param2 = node.param2})
-		end
-		mesecon.update_autoconnect(pos)
+		minetest.set_node(pos, {name = "mesecons_receiver:receiver_off", param2 = node.param2})
+		mesecon.on_placenode(pos, nn)
 	end
 end
 
@@ -121,7 +116,6 @@ function mesecon.receiver_remove(rcpt_pos, dugnode)
 		minetest.dig_node(pos)
 		local node = {name = "mesecons:wire_00000000_off"}
 		minetest.set_node(pos, node)
-		mesecon.update_autoconnect(pos)
 		mesecon.on_placenode(pos, node)
 	end
 end
diff --git a/mesecons_wires/depends.txt b/mesecons_wires/depends.txt
new file mode 100644
index 0000000..acaa924
--- /dev/null
+++ b/mesecons_wires/depends.txt
@@ -0,0 +1 @@
+mesecons
diff --git a/mesecons_wires/doc/mesecon/description.html b/mesecons_wires/doc/mesecon/description.html
new file mode 100644
index 0000000..f217be9
--- /dev/null
+++ b/mesecons_wires/doc/mesecon/description.html
@@ -0,0 +1 @@
+Mesecons are the wires, use them to connect effectors with receptors.
diff --git a/mesecons/doc/mesecon/preview.png b/mesecons_wires/doc/mesecon/preview.png
similarity index 100%
rename from mesecons/doc/mesecon/preview.png
rename to mesecons_wires/doc/mesecon/preview.png
diff --git a/mesecons/doc/mesecon/recipe.png b/mesecons_wires/doc/mesecon/recipe.png
similarity index 100%
rename from mesecons/doc/mesecon/recipe.png
rename to mesecons_wires/doc/mesecon/recipe.png
diff --git a/mesecons/wires.lua b/mesecons_wires/init.lua
similarity index 97%
rename from mesecons/wires.lua
rename to mesecons_wires/init.lua
index d77904e..879cfa1 100644
--- a/mesecons/wires.lua
+++ b/mesecons_wires/init.lua
@@ -91,10 +91,7 @@ local update_on_place_dig = function (pos, node)
 	end
 end
 
-function mesecon.update_autoconnect(pos, node)
-	if (not node) then node = minetest.get_node(pos) end
-	update_on_place_dig(pos, node)
-end
+mesecon.register_autoconnect_hook("wire", update_on_place_dig)
 
 -- ############################
 -- ## Wire node registration ##
@@ -204,7 +201,7 @@ register_wires = function()
 			groups_off["not_in_creative_inventory"] = 1
 		end
 
-		mesecon.register_node("mesecons:wire_"..nodeid, {
+		mesecon.register_node(":mesecons:wire_"..nodeid, {
 			description = "Mesecon",
 			drawtype = "nodebox",
 			inventory_image = "mesecons_wire_inv.png",

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-games/minetest-mod-mesecons.git



More information about the Pkg-games-commits mailing list