summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mesecons/actionqueue.lua28
-rw-r--r--mesecons/init.lua14
-rw-r--r--mesecons/internal.lua58
-rw-r--r--mesecons/services.lua6
-rw-r--r--mesecons/util.lua1
5 files changed, 63 insertions, 44 deletions
diff --git a/mesecons/actionqueue.lua b/mesecons/actionqueue.lua
index 9d31426..a00054a 100644
--- a/mesecons/actionqueue.lua
+++ b/mesecons/actionqueue.lua
@@ -6,15 +6,19 @@ end
-- If add_action with twice the same overwritecheck and same position are called, the first one is overwritten
-- use overwritecheck nil to never overwrite, but just add the event to the queue
-function mesecon.queue:add_action(pos, func, params, time, overwritecheck)
+-- priority specifies the order actions are executed within one globalstep, highest by default
+-- should be between 0 and 1
+function mesecon.queue:add_action(pos, func, params, time, overwritecheck, priority)
-- Create Action Table:
time = time or 0 -- time <= 0 --> execute, time > 0 --> wait time until execution
+ priority = priority or 1
overwritecheck = overwritecheck or {}
action = { pos=mesecon:tablecopy(pos),
func=func,
params=mesecon:tablecopy(params),
time=time,
- owcheck=mesecon:tablecopy(overwritecheck)}
+ owcheck=(overwritecheck and mesecon:tablecopy(overwritecheck)) or nil,
+ priority=priority}
--print(dump(action))
-- if not using the queue, (MESECONS_GLOBALSTEP off), just execute the function an we're done
@@ -42,6 +46,18 @@ end
-- this makes sure that resuming mesecons circuits when restarting minetest works fine
-- However, even that does not work in some cases, that's why we delay the time the globalsteps
-- start to be execute by 5 seconds
+local get_highest_priority = function (actions)
+ local highestp = 0, highesti
+ for i, ac in ipairs(actions) do
+ if ac.priority > highestp then
+ highestp = ac.priority
+ highesti = i
+ end
+ end
+
+ return highesti
+end
+
local m_time = 0
minetest.register_globalstep(function (dtime)
m_time = m_time + dtime
@@ -53,10 +69,14 @@ minetest.register_globalstep(function (dtime)
if action.time > 0 then
action.time = action.time - dtime
table.insert(mesecon.queue.actions, action) -- will be handled another time
- else -- execute and remove
- mesecon.queue:execute(action)
end
end
+
+ while(#actions > 0) do -- execute highest priorities first, until all are executed
+ local hp = get_highest_priority(actions)
+ mesecon.queue:execute(actions[hp])
+ table.remove(actions, hp)
+ end
end)
function mesecon.queue:execute(action)
diff --git a/mesecons/init.lua b/mesecons/init.lua
index 8facf73..4d4819c 100644
--- a/mesecons/init.lua
+++ b/mesecons/init.lua
@@ -79,12 +79,18 @@ dofile(minetest.get_modpath("mesecons").."/legacy.lua");
mesecon.queue:add_function("receptor_on", function (pos, rules)
rules = rules or mesecon.rules.default
+ -- if area (any of the neighbors) is not loaded, keep trying and call this again later
for _, rule in ipairs(mesecon:flattenrules(rules)) do
local np = mesecon:addPosRule(pos, rule)
- -- if area is not loaded, keep trying
- if minetest.env:get_node_or_nil(np) == nil then
+ if minetest.get_node_or_nil(np) == nil then
mesecon.queue:add_action(pos, "receptor_on", {rules})
+ return
end
+ end
+
+ -- execute action
+ for _, rule in ipairs(mesecon:flattenrules(rules)) do
+ local np = mesecon:addPosRule(pos, rule)
local rulenames = mesecon:rules_link_rule_all(pos, rule)
for _, rulename in ipairs(rulenames) do
mesecon:turnon(np, rulename)
@@ -100,7 +106,7 @@ mesecon.queue:add_function("receptor_off", function (pos, rules)
rules = rules or mesecon.rules.default
for _, rule in ipairs(mesecon:flattenrules(rules)) do
local np = mesecon:addPosRule(pos, rule)
- if minetest.env:get_node_or_nil(np) == nil then
+ if minetest.get_node_or_nil(np) == nil then
mesecon.queue:add_action(pos, "receptor_off", {rules})
end
local rulenames = mesecon:rules_link_rule_all(pos, rule)
@@ -108,7 +114,7 @@ mesecon.queue:add_function("receptor_off", function (pos, rules)
if not mesecon:connected_to_receptor(np, mesecon:invertRule(rule)) then
mesecon:turnoff(np, rulename)
else
- mesecon:changesignal(np, minetest.get_node(np), rulename, mesecon.state.off)
+ mesecon:changesignal(np, minetest.get_node(np), rulename, mesecon.state.off, 1)
end
end
end
diff --git a/mesecons/internal.lua b/mesecons/internal.lua
index f575c83..f713a7c 100644
--- a/mesecons/internal.lua
+++ b/mesecons/internal.lua
@@ -22,9 +22,9 @@
-- mesecon:effector_get_rules(node) --> Returns the input rules of the effector (mesecon.rules.default if none specified)
-- SIGNALS
--- mesecon:activate(pos, node) --> Activates the effector node at the specific pos (calls nodedef.mesecons.effector.action_on)
--- mesecon:deactivate(pos, node) --> Deactivates the effector node at the specific pos (calls nodedef.mesecons.effector.action_off)
--- mesecon:changesignal(pos, node, rulename, newstate) --> Changes the effector node at the specific pos (calls nodedef.mesecons.effector.action_change)
+-- mesecon:activate(pos, node, recdepth) --> Activates the effector node at the specific pos (calls nodedef.mesecons.effector.action_on), higher recdepths are executed later
+-- mesecon:deactivate(pos, node, recdepth) --> Deactivates the effector node at the specific pos (calls nodedef.mesecons.effector.action_off), "
+-- mesecon:changesignal(pos, node, rulename, newstate) --> Changes the effector node at the specific pos (calls nodedef.mesecons.effector.action_change), "
-- RULES
-- mesecon:add_rules(name, rules) | deprecated? --> Saves rules table by name
@@ -41,8 +41,8 @@
-- 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, rulename) --> Returns true whatever there is at pos. Calls itself for connected nodes (if pos is a conductor) --> recursive, the rulename is the name of the input rule that caused calling turnon
--- mesecon:turnoff(pos, rulename) --> Turns off whatever there is at pos. Calls itself for connected nodes (if pos is a conductor) --> recursive, the rulename is the name of the input rule that caused calling turnoff
+-- mesecon:turnon(pos, rulename) --> Returns true whatever there is at pos. Calls itself for connected nodes (if pos is a conductor) --> recursive, the rulename is the name of the input rule that caused calling turnon; Uses third parameter recdepth internally to determine how far away the current node is from the initial pos as it uses recursion
+-- mesecon:turnoff(pos, rulename) --> Turns off whatever there is at pos. Calls itself for connected nodes (if pos is a conductor) --> recursive, the rulename is the name of the input rule that caused calling turnoff; Uses third parameter recdepth internally to determine how far away the current node is from the initial pos as it uses recursion
-- mesecon:connected_to_receptor(pos) --> Returns true if pos is connected to a receptor directly or via conductors; calls itself if pos is a conductor --> recursive
-- 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
@@ -191,14 +191,14 @@ mesecon.queue:add_function("activate", function (pos, rulename)
end
end)
-function mesecon:activate(pos, node, rulename)
+function mesecon:activate(pos, node, rulename, recdepth)
if rulename == nil then
for _,rule in ipairs(mesecon:effector_get_rules(node)) do
- mesecon:activate(pos, node, rule)
+ mesecon:activate(pos, node, rule, recdepth + 1)
end
return
end
- mesecon.queue:add_action(pos, "activate", {rulename}, nil, rulename)
+ mesecon.queue:add_action(pos, "activate", {rulename}, nil, rulename, 1 / recdepth)
end
@@ -212,14 +212,14 @@ mesecon.queue:add_function("deactivate", function (pos, rulename)
end
end)
-function mesecon:deactivate(pos, node, rulename)
+function mesecon:deactivate(pos, node, rulename, recdepth)
if rulename == nil then
for _,rule in ipairs(mesecon:effector_get_rules(node)) do
- mesecon:deactivate(pos, node, rule)
+ mesecon:deactivate(pos, node, rule, recdepth + 1)
end
return
end
- mesecon.queue:add_action(pos, "deactivate", {rulename}, nil, rulename)
+ mesecon.queue:add_action(pos, "deactivate", {rulename}, nil, rulename, 1 / recdepth)
end
@@ -233,15 +233,15 @@ mesecon.queue:add_function("change", function (pos, rulename, changetype)
end
end)
-function mesecon:changesignal(pos, node, rulename, newstate)
+function mesecon:changesignal(pos, node, rulename, newstate, recdepth)
if rulename == nil then
for _,rule in ipairs(mesecon:effector_get_rules(node)) do
- mesecon:changesignal(pos, node, rule, newstate)
+ mesecon:changesignal(pos, node, rule, newstate, recdepth + 1)
end
return
end
- mesecon.queue:add_action(pos, "change", {rulename, newstate}, nil, rulename)
+ mesecon.queue:add_action(pos, "change", {rulename, newstate}, nil, rulename, 1 / recdepth)
end
-- #########
@@ -365,7 +365,8 @@ function mesecon:is_power_off(pos, rulename)
return false
end
-function mesecon:turnon(pos, rulename)
+function mesecon:turnon(pos, rulename, recdepth)
+ recdepth = recdepth or 2
local node = minetest.get_node(pos)
if mesecon:is_conductor_off(node, rulename) then
@@ -374,7 +375,7 @@ function mesecon:turnon(pos, rulename)
if not rulename then
for _, rule in ipairs(mesecon:flattenrules(rules)) do
if mesecon:connected_to_receptor(pos, rule) then
- mesecon:turnon(pos, rule)
+ mesecon:turnon(pos, rule, recdepth + 1)
end
end
return
@@ -387,32 +388,23 @@ function mesecon:turnon(pos, rulename)
local rulenames = mesecon:rules_link_rule_all(pos, rule)
for _, rulename in ipairs(rulenames) do
- mesecon:turnon(np, rulename)
+ mesecon:turnon(np, rulename, recdepth + 1)
end
end
elseif mesecon:is_effector(node.name) then
- mesecon:changesignal(pos, node, rulename, mesecon.state.on)
+ mesecon:changesignal(pos, node, rulename, mesecon.state.on, recdepth)
if mesecon:is_effector_off(node.name) then
- mesecon:activate(pos, node, rulename)
+ mesecon:activate(pos, node, rulename, recdepth)
end
end
end
-function mesecon:turnoff(pos, rulename)
+function mesecon:turnoff(pos, rulename, recdepth)
+ recdepth = recdepth or 0
local node = minetest.get_node(pos)
if mesecon:is_conductor_on(node, rulename) then
local rules = mesecon:conductor_get_rules(node)
- --[[
- if not rulename then
- for _, rule in ipairs(mesecon:flattenrules(rules)) do
- if mesecon:is_powered(pos, rule) then
- mesecon:turnoff(pos, rule)
- end
- end
- return
- end
- --]]
minetest.swap_node(pos, {name = mesecon:get_conductor_off(node, rulename), param2 = node.param2})
for _, rule in ipairs(mesecon:rule2meta(rulename, rules)) do
@@ -420,14 +412,14 @@ function mesecon:turnoff(pos, rulename)
local rulenames = mesecon:rules_link_rule_all(pos, rule)
for _, rulename in ipairs(rulenames) do
- mesecon:turnoff(np, rulename)
+ mesecon:turnoff(np, rulename, recdepth + 1)
end
end
elseif mesecon:is_effector(node.name) then
- mesecon:changesignal(pos, node, rulename, mesecon.state.off)
+ mesecon:changesignal(pos, node, rulename, mesecon.state.off, recdepth)
if mesecon:is_effector_on(node.name)
and not mesecon:is_powered(pos) then
- mesecon:deactivate(pos, node, rulename)
+ mesecon:deactivate(pos, node, rulename, recdepth + 1)
end
end
end
diff --git a/mesecons/services.lua b/mesecons/services.lua
index 29b5183..de0c8b6 100644
--- a/mesecons/services.lua
+++ b/mesecons/services.lua
@@ -6,13 +6,13 @@ mesecon.on_placenode = function (pos, node)
mesecon:turnon (pos)
--mesecon:receptor_on (pos, mesecon:conductor_get_rules(node))
else
- mesecon:changesignal(pos, node, mesecon:effector_get_rules(node), "on")
- mesecon:activate(pos, node)
+ mesecon:changesignal(pos, node, mesecon:effector_get_rules(node), "on", 1)
+ mesecon:activate(pos, node, nil, 1)
end
elseif mesecon:is_conductor_on(node) then
minetest.swap_node(pos, {name = mesecon:get_conductor_off(node)})
elseif mesecon:is_effector_on (node.name) then
- mesecon:deactivate(pos, node)
+ mesecon:deactivate(pos, node, nil, 1)
end
end
diff --git a/mesecons/util.lua b/mesecons/util.lua
index ad2a4ae..91d435a 100644
--- a/mesecons/util.lua
+++ b/mesecons/util.lua
@@ -169,6 +169,7 @@ function mesecon:cmpSpecial(r1, r2)
end
function mesecon:tablecopy(table) -- deep table copy
+ if type(table) ~= "table" then return table end -- no need to copy
local newtable = {}
for idx, item in pairs(table) do