forked from minetest-mods/mesecons
Use an iterative algorithm for turnon() and turnoff(), fixes #160
This may also bring some performance benefit.
This commit is contained in:
parent
b5cc933287
commit
ffacbfde5a
@ -22,9 +22,9 @@
|
|||||||
-- mesecon:effector_get_rules(node) --> Returns the input rules of the effector (mesecon.rules.default if none specified)
|
-- mesecon:effector_get_rules(node) --> Returns the input rules of the effector (mesecon.rules.default if none specified)
|
||||||
|
|
||||||
-- SIGNALS
|
-- SIGNALS
|
||||||
-- 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:activate(pos, node, depth) --> Activates the effector node at the specific pos (calls nodedef.mesecons.effector.action_on), higher depths are executed later
|
||||||
-- mesecon:deactivate(pos, node, recdepth) --> Deactivates the effector node at the specific pos (calls nodedef.mesecons.effector.action_off), "
|
-- mesecon:deactivate(pos, node, depth) --> Deactivates the effector node at the specific pos (calls nodedef.mesecons.effector.action_off), higher depths are executed later
|
||||||
-- mesecon:changesignal(pos, node, rulename, newstate) --> Changes the effector node at the specific pos (calls nodedef.mesecons.effector.action_change), "
|
-- mesecon:changesignal(pos, node, rulename, newstate, depth) --> Changes the effector node at the specific pos (calls nodedef.mesecons.effector.action_change), higher depths are executed later
|
||||||
|
|
||||||
-- CONDUCTORS
|
-- CONDUCTORS
|
||||||
-- mesecon:is_conductor(nodename) --> Returns true if nodename is a conductor
|
-- mesecon:is_conductor(nodename) --> Returns true if nodename is a conductor
|
||||||
@ -187,14 +187,14 @@ mesecon.queue:add_function("activate", function (pos, rulename)
|
|||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
|
|
||||||
function mesecon:activate(pos, node, rulename, recdepth)
|
function mesecon:activate(pos, node, rulename, depth)
|
||||||
if rulename == nil then
|
if rulename == nil then
|
||||||
for _,rule in ipairs(mesecon:effector_get_rules(node)) do
|
for _,rule in ipairs(mesecon:effector_get_rules(node)) do
|
||||||
mesecon:activate(pos, node, rule, recdepth + 1)
|
mesecon:activate(pos, node, rule, depth + 1)
|
||||||
end
|
end
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
mesecon.queue:add_action(pos, "activate", {rulename}, nil, rulename, 1 / recdepth)
|
mesecon.queue:add_action(pos, "activate", {rulename}, nil, rulename, 1 / depth)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
@ -208,36 +208,36 @@ mesecon.queue:add_function("deactivate", function (pos, rulename)
|
|||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
|
|
||||||
function mesecon:deactivate(pos, node, rulename, recdepth)
|
function mesecon:deactivate(pos, node, rulename, depth)
|
||||||
if rulename == nil then
|
if rulename == nil then
|
||||||
for _,rule in ipairs(mesecon:effector_get_rules(node)) do
|
for _,rule in ipairs(mesecon:effector_get_rules(node)) do
|
||||||
mesecon:deactivate(pos, node, rule, recdepth + 1)
|
mesecon:deactivate(pos, node, rule, depth + 1)
|
||||||
end
|
end
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
mesecon.queue:add_action(pos, "deactivate", {rulename}, nil, rulename, 1 / recdepth)
|
mesecon.queue:add_action(pos, "deactivate", {rulename}, nil, rulename, 1 / depth)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
-- Change
|
-- Change
|
||||||
mesecon.queue:add_function("change", function (pos, rulename, changetype)
|
mesecon.queue:add_function("change", function (pos, rulename, changetype)
|
||||||
node = minetest.get_node(pos)
|
local node = minetest.get_node(pos)
|
||||||
effector = mesecon:get_effector(node.name)
|
local effector = mesecon:get_effector(node.name)
|
||||||
|
|
||||||
if effector and effector.action_change then
|
if effector and effector.action_change then
|
||||||
effector.action_change(pos, node, rulename, changetype)
|
effector.action_change(pos, node, rulename, changetype)
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
|
|
||||||
function mesecon:changesignal(pos, node, rulename, newstate, recdepth)
|
function mesecon:changesignal(pos, node, rulename, newstate, depth)
|
||||||
if rulename == nil then
|
if rulename == nil then
|
||||||
for _,rule in ipairs(mesecon:effector_get_rules(node)) do
|
for _,rule in ipairs(mesecon:effector_get_rules(node)) do
|
||||||
mesecon:changesignal(pos, node, rule, newstate, recdepth + 1)
|
mesecon:changesignal(pos, node, rule, newstate, depth + 1)
|
||||||
end
|
end
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
mesecon.queue:add_action(pos, "change", {rulename, newstate}, nil, rulename, 1 / recdepth)
|
mesecon.queue:add_action(pos, "change", {rulename, newstate}, nil, rulename, 1 / depth)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Conductors
|
-- Conductors
|
||||||
@ -349,93 +349,96 @@ function mesecon:is_power_off(pos, rulename)
|
|||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
function mesecon:turnon(pos, rulename, recdepth)
|
function mesecon:turnon(pos, link)
|
||||||
recdepth = recdepth or 2
|
local frontiers = {{pos = pos, link = link}}
|
||||||
if (recdepth > STACK_SIZE) then return end
|
|
||||||
local node = minetest.get_node(pos)
|
|
||||||
|
|
||||||
if(node.name == "ignore") then
|
local depth = 1
|
||||||
-- try turning on later again
|
while frontiers[depth] do
|
||||||
mesecon.queue:add_action(
|
local f = frontiers[depth]
|
||||||
pos, "turnon", {rulename, recdepth + 1}, nil, true)
|
local node = minetest.get_node_or_nil(f.pos)
|
||||||
|
|
||||||
|
-- area not loaded, postpone action
|
||||||
|
if not node then
|
||||||
|
mesecon.queue:add_action(f.pos, "turnon", {link}, nil, true)
|
||||||
end
|
end
|
||||||
|
|
||||||
if mesecon:is_conductor_off(node, rulename) then
|
if mesecon:is_conductor_off(node, f.link) then
|
||||||
local rules = mesecon:conductor_get_rules(node)
|
local rules = mesecon:conductor_get_rules(node)
|
||||||
|
|
||||||
if not rulename then
|
minetest.swap_node(f.pos, {name = mesecon:get_conductor_on(node, f.link),
|
||||||
for _, rule in ipairs(mesecon:flattenrules(rules)) do
|
param2 = node.param2})
|
||||||
if mesecon:connected_to_receptor(pos, rule) then
|
|
||||||
mesecon:turnon(pos, rule, recdepth + 1)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
minetest.swap_node(pos, {name = mesecon:get_conductor_on(node, rulename), param2 = node.param2})
|
-- call turnon on neighbors: normal rules
|
||||||
|
for _, r in ipairs(mesecon:rule2meta(f.link, rules)) do
|
||||||
|
local np = mesecon:addPosRule(f.pos, r)
|
||||||
|
|
||||||
for _, rule in ipairs(mesecon:rule2meta(rulename, rules)) do
|
-- area not loaded, postpone action
|
||||||
local np = mesecon:addPosRule(pos, rule)
|
if not minetest.get_node_or_nil(np) then
|
||||||
if(minetest.get_node(np).name == "ignore") then
|
mesecon.queue:add_action(np, "turnon", {rulename},
|
||||||
-- try turning on later again
|
nil, true)
|
||||||
mesecon.queue:add_action(
|
|
||||||
np, "turnon", {rulename, recdepth + 1}, nil, true)
|
|
||||||
else
|
else
|
||||||
local rulenames = mesecon:rules_link_rule_all(pos, rule)
|
local links = mesecon:rules_link_rule_all(f.pos, r)
|
||||||
|
for _, l in ipairs(links) do
|
||||||
for _, rulename in ipairs(rulenames) do
|
table.insert(frontiers, {pos = np, link = l})
|
||||||
mesecon:turnon(np, rulename, recdepth + 1)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
elseif mesecon:is_effector(node.name) then
|
elseif mesecon:is_effector(node.name) then
|
||||||
mesecon:changesignal(pos, node, rulename, mesecon.state.on, recdepth)
|
mesecon:changesignal(f.pos, node, f.link, mesecon.state.on, depth)
|
||||||
if mesecon:is_effector_off(node.name) then
|
if mesecon:is_effector_off(node.name) then
|
||||||
mesecon:activate(pos, node, rulename, recdepth)
|
mesecon:activate(f.pos, node, f.link, depth)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
depth = depth + 1
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
mesecon.queue:add_function("turnon", function (pos, rulename, recdepth)
|
mesecon.queue:add_function("turnon", function (pos, rulename, recdepth)
|
||||||
mesecon:turnon(pos, rulename, recdepth)
|
mesecon:turnon(pos, rulename, recdepth)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
function mesecon:turnoff(pos, rulename, recdepth)
|
function mesecon:turnoff(pos, link)
|
||||||
recdepth = recdepth or 2
|
local frontiers = {{pos = pos, link = link}}
|
||||||
if (recdepth > STACK_SIZE) then return end
|
|
||||||
local node = minetest.get_node(pos)
|
|
||||||
|
|
||||||
if(node.name == "ignore") then
|
local depth = 1
|
||||||
-- try turning on later again
|
while frontiers[depth] do
|
||||||
mesecon.queue:add_action(
|
local f = frontiers[depth]
|
||||||
pos, "turnoff", {rulename, recdepth + 1}, nil, true)
|
local node = minetest.get_node_or_nil(f.pos)
|
||||||
|
|
||||||
|
-- area not loaded, postpone action
|
||||||
|
if not node then
|
||||||
|
mesecon.queue:add_action(f.pos, "turnoff", {link}, nil, true)
|
||||||
end
|
end
|
||||||
|
|
||||||
if mesecon:is_conductor_on(node, rulename) then
|
if mesecon:is_conductor_on(node, f.link) then
|
||||||
local rules = mesecon:conductor_get_rules(node)
|
local rules = mesecon:conductor_get_rules(node)
|
||||||
minetest.swap_node(pos, {name = mesecon:get_conductor_off(node, rulename), param2 = node.param2})
|
|
||||||
|
|
||||||
for _, rule in ipairs(mesecon:rule2meta(rulename, rules)) do
|
minetest.swap_node(f.pos, {name = mesecon:get_conductor_off(node, f.link),
|
||||||
local np = mesecon:addPosRule(pos, rule)
|
param2 = node.param2})
|
||||||
if(minetest.get_node(np).name == "ignore") then
|
|
||||||
-- try turning on later again
|
-- call turnoff on neighbors: normal rules
|
||||||
mesecon.queue:add_action(
|
for _, r in ipairs(mesecon:rule2meta(f.link, rules)) do
|
||||||
np, "turnoff", {rulename, recdepth + 1}, nil, true)
|
local np = mesecon:addPosRule(f.pos, r)
|
||||||
|
|
||||||
|
-- area not loaded, postpone action
|
||||||
|
if not minetest.get_node_or_nil(np) then
|
||||||
|
mesecon.queue:add_action(np, "turnoff", {rulename},
|
||||||
|
nil, true)
|
||||||
else
|
else
|
||||||
local rulenames = mesecon:rules_link_rule_all(pos, rule)
|
local links = mesecon:rules_link_rule_all(f.pos, r)
|
||||||
|
for _, l in ipairs(links) do
|
||||||
for _, rulename in ipairs(rulenames) do
|
table.insert(frontiers, {pos = np, link = l})
|
||||||
mesecon:turnoff(np, rulename, recdepth + 1)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
elseif mesecon:is_effector(node.name) then
|
elseif mesecon:is_effector(node.name) then
|
||||||
mesecon:changesignal(pos, node, rulename, mesecon.state.off, recdepth)
|
mesecon:changesignal(f.pos, node, f.link, mesecon.state.off, depth)
|
||||||
if mesecon:is_effector_on(node.name)
|
if mesecon:is_effector_on(node.name) and not mesecon:is_powered(f.pos) then
|
||||||
and not mesecon:is_powered(pos) then
|
mesecon:deactivate(f.pos, node, f.link, depth)
|
||||||
mesecon:deactivate(pos, node, rulename, recdepth + 1)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
depth = depth + 1
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
mesecon.queue:add_function("turnoff", function (pos, rulename, recdepth)
|
mesecon.queue:add_function("turnoff", function (pos, rulename, recdepth)
|
||||||
|
@ -83,7 +83,6 @@ local merge_portstates = function (ports, vports)
|
|||||||
end
|
end
|
||||||
|
|
||||||
local generate_name = function (ports)
|
local generate_name = function (ports)
|
||||||
local overwrite = overwrite or {}
|
|
||||||
local d = ports.d and 1 or 0
|
local d = ports.d and 1 or 0
|
||||||
local c = ports.c and 1 or 0
|
local c = ports.c and 1 or 0
|
||||||
local b = ports.b and 1 or 0
|
local b = ports.b and 1 or 0
|
||||||
@ -271,7 +270,7 @@ local create_sandbox = function (code, env)
|
|||||||
if code:byte(1) == 27 then
|
if code:byte(1) == 27 then
|
||||||
return _, "You Hacker You! Don't use binary code!"
|
return _, "You Hacker You! Don't use binary code!"
|
||||||
end
|
end
|
||||||
f, msg = loadstring(code)
|
local f, msg = loadstring(code)
|
||||||
if not f then return _, msg end
|
if not f then return _, msg end
|
||||||
setfenv(f, env)
|
setfenv(f, env)
|
||||||
return f
|
return f
|
||||||
@ -321,7 +320,7 @@ lc_update = function (pos, event)
|
|||||||
-- create the sandbox and execute code
|
-- create the sandbox and execute code
|
||||||
local chunk, msg = create_sandbox (code, env)
|
local chunk, msg = create_sandbox (code, env)
|
||||||
if not chunk then return msg end
|
if not chunk then return msg end
|
||||||
local success, msg = pcall(f)
|
local success, msg = pcall(chunk)
|
||||||
if not success then return msg end
|
if not success then return msg end
|
||||||
if ports_invalid(env.port) then return ports_invalid(env.port) end
|
if ports_invalid(env.port) then return ports_invalid(env.port) end
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user