Merge remote-tracking branch 'origin/master' into mineclone5

This commit is contained in:
kay27 2021-04-09 02:15:15 +04:00
commit bc16c33dde
1 changed files with 76 additions and 73 deletions

View File

@ -47,28 +47,35 @@
-- mesecon.rotate_rules_down(rules) -- mesecon.rotate_rules_down(rules)
-- These functions return rules that have been rotated in the specific direction -- These functions return rules that have been rotated in the specific direction
local equals = vector.equals
local get_node_force = mesecon.get_node_force
local receptor_get_rules = mesecon.receptor_get_rules
local invertRule = mesecon.invertRule
local copy, insert = table.copy, table.insert
local registered_nodes = minetest.registered_nodes
-- General -- General
function mesecon.get_effector(nodename) function mesecon.get_effector(nodename)
if minetest.registered_nodes[nodename] if registered_nodes[nodename]
and minetest.registered_nodes[nodename].mesecons and registered_nodes[nodename].mesecons
and minetest.registered_nodes[nodename].mesecons.effector then and registered_nodes[nodename].mesecons.effector then
return minetest.registered_nodes[nodename].mesecons.effector return registered_nodes[nodename].mesecons.effector
end end
end end
function mesecon.get_receptor(nodename) function mesecon.get_receptor(nodename)
if minetest.registered_nodes[nodename] if registered_nodes[nodename]
and minetest.registered_nodes[nodename].mesecons and registered_nodes[nodename].mesecons
and minetest.registered_nodes[nodename].mesecons.receptor then and registered_nodes[nodename].mesecons.receptor then
return minetest.registered_nodes[nodename].mesecons.receptor return registered_nodes[nodename].mesecons.receptor
end end
end end
function mesecon.get_conductor(nodename) function mesecon.get_conductor(nodename)
if minetest.registered_nodes[nodename] if registered_nodes[nodename]
and minetest.registered_nodes[nodename].mesecons and registered_nodes[nodename].mesecons
and minetest.registered_nodes[nodename].mesecons.conductor then and registered_nodes[nodename].mesecons.conductor then
return minetest.registered_nodes[nodename].mesecons.conductor return registered_nodes[nodename].mesecons.conductor
end end
end end
@ -103,13 +110,14 @@ end
-- Receptors -- Receptors
-- Nodes that can power mesecons -- Nodes that can power mesecons
function mesecon.is_receptor_on(nodename) local function is_receptor_on(nodename)
local receptor = mesecon.get_receptor(nodename) local receptor = mesecon.get_receptor(nodename)
if receptor and receptor.state == mesecon.state.on then if receptor and receptor.state == mesecon.state.on then
return true return true
end end
return false return false
end end
mesecon.is_receptor_on = is_receptor_on
function mesecon.is_receptor_off(nodename) function mesecon.is_receptor_off(nodename)
local receptor = mesecon.get_receptor(nodename) local receptor = mesecon.get_receptor(nodename)
@ -186,7 +194,7 @@ end
-- Activation: -- Activation:
mesecon.queue:add_function("activate", function (pos, rulename) mesecon.queue:add_function("activate", function (pos, rulename)
local node = mesecon.get_node_force(pos) local node = get_node_force(pos)
if not node then return end if not node then return end
local effector = mesecon.get_effector(node.name) local effector = mesecon.get_effector(node.name)
@ -198,7 +206,7 @@ end)
function mesecon.activate(pos, node, rulename, depth) 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 pairs(mesecon.effector_get_rules(node)) do
mesecon.activate(pos, node, rule, depth + 1) mesecon.activate(pos, node, rule, depth + 1)
end end
return return
@ -209,7 +217,7 @@ end
-- Deactivation -- Deactivation
mesecon.queue:add_function("deactivate", function (pos, rulename) mesecon.queue:add_function("deactivate", function (pos, rulename)
local node = mesecon.get_node_force(pos) local node = get_node_force(pos)
if not node then return end if not node then return end
local effector = mesecon.get_effector(node.name) local effector = mesecon.get_effector(node.name)
@ -221,7 +229,7 @@ end)
function mesecon.deactivate(pos, node, rulename, depth) 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 pairs(mesecon.effector_get_rules(node)) do
mesecon.deactivate(pos, node, rule, depth + 1) mesecon.deactivate(pos, node, rule, depth + 1)
end end
return return
@ -232,7 +240,7 @@ end
-- Change -- Change
mesecon.queue:add_function("change", function (pos, rulename, changetype) mesecon.queue:add_function("change", function (pos, rulename, changetype)
local node = mesecon.get_node_force(pos) local node = get_node_force(pos)
if not node then return end if not node then return end
local effector = mesecon.get_effector(node.name) local effector = mesecon.get_effector(node.name)
@ -244,7 +252,7 @@ end)
function mesecon.changesignal(pos, node, rulename, newstate, depth) 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 pairs(mesecon.effector_get_rules(node)) do
mesecon.changesignal(pos, node, rule, newstate, depth + 1) mesecon.changesignal(pos, node, rule, newstate, depth + 1)
end end
return return
@ -356,15 +364,15 @@ end
-- some more general high-level stuff -- some more general high-level stuff
function mesecon.is_power_on(pos, rulename) function mesecon.is_power_on(pos, rulename)
local node = mesecon.get_node_force(pos) local node = get_node_force(pos)
if node and (mesecon.is_conductor_on(node, rulename) or mesecon.is_receptor_on(node.name)) then if node and (mesecon.is_conductor_on(node, rulename) or is_receptor_on(node.name)) then
return true return true
end end
return false return false
end end
function mesecon.is_power_off(pos, rulename) function mesecon.is_power_off(pos, rulename)
local node = mesecon.get_node_force(pos) local node = get_node_force(pos)
if node and (mesecon.is_conductor_off(node, rulename) or mesecon.is_receptor_off(node.name)) then if node and (mesecon.is_conductor_off(node, rulename) or mesecon.is_receptor_off(node.name)) then
return true return true
end end
@ -381,7 +389,7 @@ function mesecon.turnon(pos, link)
local depth = 1 local depth = 1
while frontiers[1] do while frontiers[1] do
local f = table.remove(frontiers, 1) local f = table.remove(frontiers, 1)
local node = mesecon.get_node_force(f.pos) local node = get_node_force(f.pos)
if not node then if not node then
-- Area does not exist; do nothing -- Area does not exist; do nothing
@ -389,10 +397,10 @@ function mesecon.turnon(pos, link)
local rules = mesecon.conductor_get_rules(node) local rules = mesecon.conductor_get_rules(node)
-- Call turnon on neighbors -- Call turnon on neighbors
for _, r in ipairs(mesecon.rule2meta(f.link, rules)) do for _, r in pairs(mesecon.rule2meta(f.link, rules)) do
local np = vector.add(f.pos, r) local np = vector.add(f.pos, r)
for _, l in ipairs(mesecon.rules_link_rule_all(f.pos, r)) do for _, l in pairs(mesecon.rules_link_rule_all(f.pos, r)) do
table.insert(frontiers, {pos = np, link = l}) insert(frontiers, {pos = np, link = l})
end end
end end
@ -406,12 +414,12 @@ function mesecon.turnon(pos, link)
if node and f.link.spread and minetest.get_item_group(node.name, "opaque") == 1 then if node and f.link.spread and minetest.get_item_group(node.name, "opaque") == 1 then
-- Call turnon on neighbors -- Call turnon on neighbors
-- Warning: A LOT of nodes need to be looked at for this to work -- Warning: A LOT of nodes need to be looked at for this to work
for _, r in ipairs(mesecon.rule2meta(f.link, mesecon.rules.mcl_alldirs_spread)) do for _, r in pairs(mesecon.rule2meta(f.link, mesecon.rules.mcl_alldirs_spread)) do
local np = vector.add(f.pos, r) local np = vector.add(f.pos, r)
for _, l in ipairs(mesecon.rules_link_rule_all(f.pos, r)) do for _, l in pairs(mesecon.rules_link_rule_all(f.pos, r)) do
local nlink = table.copy(l) local nlink = copy(l)
nlink.spread = false nlink.spread = false
table.insert(frontiers, {pos = np, link = nlink}) insert(frontiers, {pos = np, link = nlink})
end end
end end
end end
@ -443,33 +451,33 @@ function mesecon.turnoff(pos, link)
local depth = 1 local depth = 1
while frontiers[1] do while frontiers[1] do
local f = table.remove(frontiers, 1) local f = table.remove(frontiers, 1)
local node = mesecon.get_node_force(f.pos) local node = get_node_force(f.pos)
if not node then if not node then
-- No-op -- No-op
elseif mesecon.is_conductor_on(node, f.link) then elseif mesecon.is_conductor_on(node, f.link) then
local rules = mesecon.conductor_get_rules(node) local rules = mesecon.conductor_get_rules(node)
for _, r in ipairs(mesecon.rule2meta(f.link, rules)) do for _, r in pairs(mesecon.rule2meta(f.link, rules)) do
local np = vector.add(f.pos, r) local np = vector.add(f.pos, r)
-- Check if an onstate receptor is connected. If that is the case, -- Check if an onstate receptor is connected. If that is the case,
-- abort this turnoff process by returning false. `receptor_off` will -- abort this turnoff process by returning false. `receptor_off` will
-- discard all the changes that we made in the voxelmanip: -- discard all the changes that we made in the voxelmanip:
for _, l in ipairs(mesecon.rules_link_rule_all_inverted(f.pos, r)) do for _, l in pairs(mesecon.rules_link_rule_all_inverted(f.pos, r)) do
if mesecon.is_receptor_on(mesecon.get_node_force(np).name) then if is_receptor_on(get_node_force(np).name) then
return false return false
end end
end end
-- Call turnoff on neighbors -- Call turnoff on neighbors
for _, l in ipairs(mesecon.rules_link_rule_all(f.pos, r)) do for _, l in pairs(mesecon.rules_link_rule_all(f.pos, r)) do
table.insert(frontiers, {pos = np, link = l}) insert(frontiers, {pos = np, link = l})
end end
end end
mesecon.swap_node_force(f.pos, mesecon.get_conductor_off(node, f.link)) mesecon.swap_node_force(f.pos, mesecon.get_conductor_off(node, f.link))
elseif mesecon.is_effector(node.name) then elseif mesecon.is_effector(node.name) then
table.insert(signals, { insert(signals, {
pos = f.pos, pos = f.pos,
node = node, node = node,
link = f.link, link = f.link,
@ -480,27 +488,22 @@ function mesecon.turnoff(pos, link)
if node and f.link.spread and minetest.get_item_group(node.name, "opaque") == 1 then if node and f.link.spread and minetest.get_item_group(node.name, "opaque") == 1 then
-- Call turnoff on neighbors -- Call turnoff on neighbors
-- Warning: A LOT of nodes need to be looked at for this to work -- Warning: A LOT of nodes need to be looked at for this to work
for _, r in ipairs(mesecon.rule2meta(f.link, mesecon.rules.mcl_alldirs_spread)) do local fpos = f.pos
local np = vector.add(f.pos, r) for _, r in pairs(mesecon.rule2meta(f.link, mesecon.rules.mcl_alldirs_spread)) do
local n = mesecon.get_node_force(np) local np = {x=fpos.x+r.x, y=fpos.y+r.y, z=fpos.z+r.z}
local n = get_node_force(np)
if not n then if n and is_receptor_on(n.name) then
mcl_explosions.explode(f.pos, 10) local receptorrules = receptor_get_rules(n)
return
end
if mesecon.is_receptor_on(n.name) then
local receptorrules = mesecon.receptor_get_rules(n)
for _, rr in pairs(receptorrules) do for _, rr in pairs(receptorrules) do
if rr.spread and vector.equals(mesecon.invertRule(rr), r) then if rr.spread and equals(invertRule(rr), r) then
return false return false
end end
end end
end end
for _, l in ipairs(mesecon.rules_link_rule_all(f.pos, r)) do for _, l in pairs(mesecon.rules_link_rule_all(fpos, r)) do
local nlink = table.copy(l) local nlink = copy(l)
nlink.spread = false nlink.spread = false
table.insert(frontiers, {pos = np, link = nlink}) insert(frontiers, {pos = np, link = nlink})
end end
end end
end end
@ -508,7 +511,7 @@ function mesecon.turnoff(pos, link)
depth = depth + 1 depth = depth + 1
end end
for _, sig in ipairs(signals) do for _, sig in pairs(signals) do
mesecon.changesignal(sig.pos, sig.node, sig.link, mesecon.state.off, sig.depth) 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 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) mesecon.deactivate(sig.pos, sig.node, sig.link, sig.depth)
@ -522,19 +525,19 @@ end
-- outputnode (receptor or conductor) at position `output` and has an output in direction `rule` -- outputnode (receptor or conductor) at position `output` and has an output in direction `rule`
function mesecon.rules_link_rule_all(output, rule) function mesecon.rules_link_rule_all(output, rule)
local input = vector.add(output, rule) local input = vector.add(output, rule)
local inputnode = mesecon.get_node_force(input) local inputnode = get_node_force(input)
local inputrules = mesecon.get_any_inputrules(inputnode) local inputrules = mesecon.get_any_inputrules(inputnode)
if not inputrules then if not inputrules then
return {} return {}
end end
local rules = {} local rules = {}
for _, inputrule in ipairs(mesecon.flattenrules(inputrules)) do for _, inputrule in pairs(mesecon.flattenrules(inputrules)) do
-- Check if input accepts from output -- Check if input accepts from output
if vector.equals(vector.add(input, inputrule), output) then if equals(vector.add(input, inputrule), output) then
local newrule = table.copy(inputrule) local newrule = copy(inputrule)
newrule.spread = rule.spread newrule.spread = rule.spread
table.insert(rules, newrule) insert(rules, newrule)
end end
end end
@ -545,19 +548,19 @@ end
-- inputnode (effector or conductor) at position `input` and has an input in direction `rule` -- inputnode (effector or conductor) at position `input` and has an input in direction `rule`
function mesecon.rules_link_rule_all_inverted(input, rule) function mesecon.rules_link_rule_all_inverted(input, rule)
local output = vector.add(input, rule) local output = vector.add(input, rule)
local outputnode = mesecon.get_node_force(output) local outputnode = get_node_force(output)
local outputrules = mesecon.get_any_outputrules(outputnode) local outputrules = mesecon.get_any_outputrules(outputnode)
if not outputrules then if not outputrules then
return {} return {}
end end
local rules = {} local rules = {}
for _, outputrule in ipairs(mesecon.flattenrules(outputrules)) do for _, outputrule in pairs(mesecon.flattenrules(outputrules)) do
if vector.equals(vector.add(output, outputrule), input) then if equals(vector.add(output, outputrule), input) then
local newrule = table.copy(outputrule) local newrule = copy(outputrule)
newrule = mesecon.invertRule(newrule) newrule = invertRule(newrule)
newrule.spread = rule.spread newrule.spread = rule.spread
table.insert(rules, newrule) insert(rules, newrule)
end end
end end
return rules return rules
@ -568,7 +571,7 @@ function mesecon.is_powered(pos, rule, depth, sourcepos, home_pos)
if depth > 1 then if depth > 1 then
return false, false return false, false
end end
local node = mesecon.get_node_force(pos) local node = get_node_force(pos)
local rules = mesecon.get_any_inputrules(node) local rules = mesecon.get_any_inputrules(node)
if not rules then if not rules then
return false, false return false, false
@ -584,23 +587,23 @@ function mesecon.is_powered(pos, rule, depth, sourcepos, home_pos)
local function power_walk(pos, home_pos, sourcepos, rulenames, rule, depth) local function power_walk(pos, home_pos, sourcepos, rulenames, rule, depth)
local spread = false local spread = false
for _, rname in ipairs(rulenames) do for _, rname in pairs(rulenames) do
local np = vector.add(pos, rname) local np = vector.add(pos, rname)
local nn = mesecon.get_node_force(np) local nn = get_node_force(np)
if (mesecon.is_conductor_on (nn, mesecon.invertRule(rname)) if (mesecon.is_conductor_on (nn, invertRule(rname))
or mesecon.is_receptor_on (nn.name)) then or is_receptor_on (nn.name)) then
if not vector.equals(home_pos, np) then if not equals(home_pos, np) then
local rulez = mesecon.get_any_outputrules(nn) local rulez = mesecon.get_any_outputrules(nn)
local spread_tmp = false local spread_tmp = false
for r=1, #rulez do for r=1, #rulez do
if vector.equals(mesecon.invertRule(rname), rulez[r]) then if equals(invertRule(rname), rulez[r]) then
if rulez[r].spread then if rulez[r].spread then
spread_tmp = true spread_tmp = true
end end
end end
end end
if depth == 0 or spread_tmp then if depth == 0 or spread_tmp then
table.insert(sourcepos, np) insert(sourcepos, np)
if spread_tmp then if spread_tmp then
spread = true spread = true
end end
@ -618,7 +621,7 @@ function mesecon.is_powered(pos, rule, depth, sourcepos, home_pos)
local spread = false local spread = false
if not rule then if not rule then
for _, rule in ipairs(mesecon.flattenrules(rules)) do for _, rule in pairs(mesecon.flattenrules(rules)) do
local spread_temp local spread_temp
local rulenames = mesecon.rules_link_rule_all_inverted(pos, rule) local rulenames = mesecon.rules_link_rule_all_inverted(pos, rule)
sourcepos, spread_temp = power_walk(pos, home_pos, sourcepos, rulenames, rule, depth) sourcepos, spread_temp = power_walk(pos, home_pos, sourcepos, rulenames, rule, depth)