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.pu...@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

_______________________________________________
Pkg-games-commits mailing list
Pkg-games-commits@lists.alioth.debian.org
http://lists.alioth.debian.org/cgi-bin/mailman/listinfo/pkg-games-commits

Reply via email to