comparator and repeater(delayer) send through opaque blocks

This commit is contained in:
Henry Behrendt 2021-08-28 10:14:32 +02:00
parent 5be1c15dd8
commit ffc4dd7cb7
5 changed files with 121 additions and 85 deletions

View File

@ -464,6 +464,7 @@ for _, mode in pairs{"comp", "sub"} do
receptor = {
state = state,
rules = comparator_get_output_rules,
opaquespread = (state==mesecon.state.on),
},
effector = {
rules = comparator_get_input_rules,

View File

@ -69,16 +69,21 @@ dofile(minetest.get_modpath("mesecons").."/internal.lua");
-- API
-- these are the only functions you need to remember
mesecon.queue:add_function("receptor_on", function (pos, rules, voltage)
mesecon.queue:add_function("receptor_on", function (pos, rules, voltage, opaquespread)
mesecon.vm_begin()
rules = rules or mesecon.rules.default
local node = mesecon.get_node_force(pos)
local os=opaquespread or mesecon.is_receptor_opaquespread(node.name)
-- Call turnon on all linking positions
for _, rule in pairs(mesecon.flattenrules(rules)) do
local np = vector.add(pos, rule)
local rulenames = mesecon.rules_link_rule_all(pos, rule)
for _, rulename in pairs(rulenames) do
if os then rulename.opaquespread=os end
minetest.log("action", mesecon.postostring(pos) .. "-->" .. "receptor_on-> ".."np="..mesecon.postostring(np).." link="..mesecon.tabletostring(rulename).. " v=" .. (voltage or "nil"))
mesecon.turnon(np, rulename, voltage)
end
end
@ -86,8 +91,8 @@ mesecon.queue:add_function("receptor_on", function (pos, rules, voltage)
mesecon.vm_commit()
end)
function mesecon.receptor_on(pos, rules, voltage)
mesecon.queue:add_action(pos, "receptor_on", {rules, voltage}, nil, rules)
function mesecon.receptor_on(pos, rules, voltage, opaquespread)
mesecon.queue:add_action(pos, "receptor_on", {rules, voltage, opaquespread}, nil, rules)
end
mesecon.queue:add_function("receptor_off", function (pos, rules)

View File

@ -153,6 +153,12 @@ local function receptor_get_rules(node)
end
mesecon.receptor_get_rules = receptor_get_rules
function mesecon.is_receptor_opaquespread(nodename)
local receptor = mesecon.get_receptor(nodename)
return receptor and receptor.opaquespread
end
-- Effectors
-- Nodes that can be powered by mesecons
function mesecon.is_effector_on(nodename)
@ -519,7 +525,7 @@ function mesecon.turnon(pos, link, voltage)
local np = vector.add(f.pos, r)
for _, l in pairs(mesecon.rules_link_rule_all(f.pos, r)) do
local nlink = copy(l)
nlink.spread = false
if not f.link.opaquespread then nlink.spread = false end
minetest.log("action", mesecon.postostring(f.pos) .. "-->" .. "turnon.insert.spread-> ".. mesecon.postostring(np) .. " link="..mesecon.tabletostring(nlink).. " v=" .. f.voltage)
insert(frontiers, {pos = np, link = nlink, voltage=f.voltage})
@ -689,12 +695,12 @@ end
function mesecon.is_powered(pos, rule, depth, sourcepos, home_pos)
if depth == nil then depth = 0 end
if depth > 1 then
return false, false, 0, false
return false, false, 0, false, false
end
local node = get_node_force(pos)
local rules = mesecon.get_any_inputrules(node)
if not rules then
return false, false, 0, false
return false, false, 0, false, false
end
if not home_pos then
home_pos = pos
@ -705,7 +711,7 @@ function mesecon.is_powered(pos, rule, depth, sourcepos, home_pos)
sourcepos = {}
end
local function power_walk(pos, home_pos, sourcepos, rulenames, rule, depth, voltage, fc)
local function power_walk(pos, home_pos, sourcepos, rulenames, rule, depth, voltage, fc, os)
local spread = false
local cond = fc
minetest.log("action", mesecon.postostring(pos) .. "-->" .. "power_walk.rulenames=" .. mesecon.tabletostring(rulenames))
@ -715,81 +721,83 @@ function mesecon.is_powered(pos, rule, depth, sourcepos, home_pos)
if (mesecon.is_conductor_on (nn, invertRule(rname)) or is_receptor_on (nn.name)) then
if not equals(home_pos, np) then
local rulez = mesecon.get_any_outputrules(nn)
local spread_tmp = false
for r=1, #rulez do
if equals(invertRule(rname), rulez[r]) then
if rulez[r].spread then
spread_tmp = true
end
end
end
if depth == 0 or spread_tmp then
local meta = minetest.get_meta(np)
local nvol = meta:get_string("mesecon_voltage")~="" and meta:get_int("mesecon_voltage") or 15
minetest.log("action", mesecon.postostring(np) .. "-->" .. "is_powered.voltage0=" .. voltage.."<-->"..nvol)
if nvol>voltage then
voltage = nvol
cond = mesecon.is_conductor(nn.name)
minetest.log("action", mesecon.postostring(np) .. "-->" .. "is_powered.cond0=" .. tostring(cond))
end
--voltage = math.max(voltage, nvol)
--minetest.log("action", mesecon.postostring(np) .. "-->" .. "is_powered.voltage1=" .. meta:get_string("mesecon_voltage"))
--minetest.log("action", mesecon.postostring(np) .. "-->" .. "is_powered.voltage2=" .. (meta:get_string("mesecon_voltage")~="" and meta:get_int("mesecon_voltage") or 15))
minetest.log("action", mesecon.postostring(np) .. "-->" .. "is_powered.voltage3=" .. voltage.." "..nn.name.." "..tostring(mesecon.is_conductor(nn.name)))
insert(sourcepos, np)
if spread_tmp then
spread = true
--has output connected to me
local spread_tmp = rulez[r].spread
if depth == 0 or spread_tmp then
local meta = minetest.get_meta(np)
local nvol = meta:get_string("mesecon_voltage")~="" and meta:get_int("mesecon_voltage") or 15
minetest.log("action", mesecon.postostring(np) .. "-->" .. "power_walk.voltage0=" .. voltage.."<-->"..nvol)
if nvol>voltage then
voltage = nvol
cond = mesecon.is_conductor(nn.name)
minetest.log("action", mesecon.postostring(np) .. "-->" .. "power_walk.cond0=" .. tostring(cond))
end
os = os or mesecon.is_receptor_opaquespread(nn.name)
--voltage = math.max(voltage, nvol)
--minetest.log("action", mesecon.postostring(np) .. "-->" .. "power_walk.voltage1=" .. meta:get_string("mesecon_voltage"))
--minetest.log("action", mesecon.postostring(np) .. "-->" .. "power_walk.voltage2=" .. (meta:get_string("mesecon_voltage")~="" and meta:get_int("mesecon_voltage") or 15))
minetest.log("action", mesecon.postostring(np) .. "-->" .. "power_walk.voltage3=" .. voltage.." "..nn.name.." "..tostring(mesecon.is_conductor(nn.name))..tostring(os))
np.opaquespread=mesecon.is_receptor_opaquespread(nn.name)
insert(sourcepos, np)
if spread_tmp then spread = true end
end
end
end
end
elseif depth == 0 and minetest.get_item_group(nn.name, "opaque") == 1 and not pos.conductor then
minetest.log("action", mesecon.postostring(np) .. "-->" .. "is_powered.elseif.is_conductor=" .. tostring(mesecon.is_conductor(pos)))
local more_sourcepos, more_spread, more_voltage, more_cond = mesecon.is_powered(np, nil, depth + 1, sourcepos, home_pos)
if more_sourcepos and #more_sourcepos > 0 and more_voltage>=1 then
--elseif depth == 0 and minetest.get_item_group(nn.name, "opaque") == 1 and not pos.conductor then
elseif depth == 0 and minetest.get_item_group(nn.name, "opaque") == 1 then
minetest.log("action", mesecon.postostring(np) .. "-->" .. "power_walk.elseif.is_conductor=" .. tostring(mesecon.is_conductor(pos)))
local more_sourcepos, more_spread, more_voltage, more_cond, more_os = mesecon.is_powered(np, nil, depth + 1, sourcepos, home_pos, os)
if more_sourcepos and #more_sourcepos > 0 and more_voltage>=1 and (not pos.conductor or more_os) then
mesecon.mergetable(sourcepos, more_sourcepos)
if more_voltage>voltage then
voltage = more_voltage
cond = more_cond
minetest.log("action", mesecon.postostring(np) .. "-->" .. "is_powered.cond1=" .. tostring(cond))
os=more_os
minetest.log("action", mesecon.postostring(np) .. "-->" .. "power_walk.cond1=" .. tostring(cond))
end
end
end
end
minetest.log("action", mesecon.postostring(pos) .. "-->" .. "is_powered.cond2=" .. tostring(cond))
return sourcepos, spread, voltage, cond
minetest.log("action", mesecon.postostring(pos) .. "-->" .. "power_walk.cond2=" .. tostring(cond).." opaquespread="..tostring(os).." depth="..tostring(depth))
return sourcepos, spread, voltage, cond, os
end
local v = 0
local fromConductor = false
local spread = false
local opaquespread = false
if not rule then
for _, rule in pairs(mesecon.flattenrules(rules)) do
local spread_temp
local rulenames = mesecon.rules_link_rule_all_inverted(pos, rule)
sourcepos, spread_temp, v, fromConductor = power_walk(pos, home_pos, sourcepos, rulenames, rule, depth, v, fromConductor)
if next(rulenames) ~= nil then sourcepos, spread_temp, v, fromConductor, opaquespread = power_walk(pos, home_pos, sourcepos, rulenames, rule, depth, v, fromConductor, opaquespread) end
if spread_temp then
spread = true
end
end
else
local rulenames = mesecon.rules_link_rule_all_inverted(pos, rule)
sourcepos, spread, v, fromConductor = power_walk(pos, home_pos, sourcepos, rulenames, rule, depth, v)
sourcepos, spread, v, fromConductor, opaquespread = power_walk(pos, home_pos, sourcepos, rulenames, rule, depth, v, opaquespread)
end
-- Return FALSE if not powered, return list of sources if is powered
minetest.log("action", mesecon.postostring(pos) .. "-->" .. "is_powered.voltage4=" .. v .. " fC="..tostring(fromConductor).." spread="..tostring(spread))
if (#sourcepos == 0) then
return false, false, 0, false
minetest.log("action", mesecon.postostring(pos) .. "-->" .. "is_powered.voltage4=" .. "0")
return false, false, 0, false, false
else
return sourcepos, spread, v, fromConductor
minetest.log("action", mesecon.postostring(pos) .. "-->" .. "is_powered.voltage5=" .. v .. " fC="..tostring(fromConductor).." spread="..tostring(spread).." os="..tostring(opaquespread))
return sourcepos, spread, v, fromConductor, opaquespread
end
end

View File

@ -79,48 +79,68 @@ function mesecon.on_placenode(pos, node)
end
if minetest.get_item_group(node.name, "opaque") == 1 then
local is_powered, direct_source, voltage = mesecon.is_powered(pos)
local is_powered, direct_source, voltage, _, opaquespread = mesecon.is_powered(pos)
minetest.log("action", mesecon.postostring(pos) .. "-->" .. " on_placenode.is_powered="..mesecon.tabletostring(is_powered))
minetest.log("action", mesecon.postostring(pos) .. "-->" .. " on_placenode.opaquespread="..tostring(opaquespread))
if is_powered and direct_source then
local neighbors = mesecon.mcl_get_neighbors(pos)
for n=1, #neighbors do
local npos = neighbors[n].pos
local nnode = minetest.get_node(npos)
minetest.log("action", mesecon.postostring(pos) .. "-->" .. " on_placenode.is_powered" .. "name="..nnode.name .. " effoff="..tostring(mesecon.is_effector_off(nnode.name)).." redtorch="..tostring(minetest.get_item_group(nnode.name, "redstone_torch")))
if mesecon.is_conductor_off(nnode) then
--mesecon.receptor_on(npos, mesecon.conductor_get_rules(nnode))
-- Redstone torch is a special case and must be ignored
elseif mesecon.is_effector_off(nnode.name) and minetest.get_item_group(nnode.name, "redstone_torch") == 0 then
mesecon.changesignal(npos, nnode, neighbors[n].link, mesecon.state.on, 1)
mesecon.activate(npos, nnode, neighbors[n].link, 1)
elseif mesecon.is_effector(nnode.name) and minetest.get_item_group(nnode.name, "redstone_torch") == 0 then
--eigen funktion für comparator schreiben
minetest.log("action", mesecon.postostring(pos) .. "--> on_placenode.is_effector: node.name->"..node.name.." f->".. mesecon.tabletostring(f))
if opaquespread then
mesecon.receptor_on(pos, nil, voltage)
else
local neighbors = mesecon.mcl_get_neighbors(pos)
for n=1, #neighbors do
local npos = neighbors[n].pos
local nnode = minetest.get_node(npos)
if mesecon.is_conductor_off(nnode) and opaquespread then
minetest.log("action", mesecon.postostring(npos) .. "-->" .. " on_placenode.is_conductor_off"
.. " name="..nnode.name
.. " effoff="..tostring(mesecon.is_effector_off(nnode.name))
.. " redtorch="..tostring(minetest.get_item_group(nnode.name, "redstone_torch"))
.. " opaquespread=" .. tostring(opaquespread)
)
if voltage<1 then
--ausschalten
--if mesecon.is_effector_on(node.name) then
minetest.log("action", mesecon.postostring(pos) .. "--> on_placenode.is_effector_on")
--mesecon.changesignal(f.pos, node, f.link, mesecon.state.off, depth)
--mesecon.deactivate(f.pos, node, f.link, depth)
mesecon.changesignal(npos, nnode, neighbors[n].link, mesecon.state.on, 1)
mesecon.deactivate(npos, nnode, neighbors[n].link, 1)
--end
else
--einschalten
minetest.log("action", mesecon.postostring(pos) .. "--> on_placenode.is_effector_off")
--mesecon.receptor_on(npos, mesecon.conductor_get_rules(nnode), voltage-1)
-- Redstone torch is a special case and must be ignored
elseif mesecon.is_effector_off(nnode.name) and minetest.get_item_group(nnode.name, "redstone_torch") == 0 then
minetest.log("action", mesecon.postostring(npos) .. "-->" .. " on_placenode.is_effector_off"
.. " name="..nnode.name
.. " effoff="..tostring(mesecon.is_effector_off(nnode.name))
.. " redtorch="..tostring(minetest.get_item_group(nnode.name, "redstone_torch"))
.. " opaquespread=" .. tostring(opaquespread)
)
mesecon.changesignal(npos, nnode, neighbors[n].link, mesecon.state.on, 1)
mesecon.activate(npos, nnode, neighbors[n].link, 1)
elseif mesecon.is_effector(nnode.name) and minetest.get_item_group(nnode.name, "redstone_torch") == 0 then
--eigen funktion für comparator schreiben
minetest.log("action", mesecon.postostring(npos) .. "-->" .. " on_placenode.is_comparator_off"
.. " name="..nnode.name
.. " effoff="..tostring(mesecon.is_effector_off(nnode.name))
.. " redtorch="..tostring(minetest.get_item_group(nnode.name, "redstone_torch"))
.. " opaquespread=" .. tostring(opaquespread)
)
minetest.log("action", mesecon.postostring(npos) .. "--> on_placenode.is_effector: node.name->"..nnode.name)
if voltage<1 then
--ausschalten
--if mesecon.is_effector_on(node.name) then
minetest.log("action", mesecon.postostring(pos) .. "--> on_placenode.is_effector_on")
--mesecon.changesignal(f.pos, node, f.link, mesecon.state.off, depth)
--mesecon.deactivate(f.pos, node, f.link, depth)
mesecon.changesignal(npos, nnode, neighbors[n].link, mesecon.state.on, 1)
mesecon.deactivate(npos, nnode, neighbors[n].link, 1)
--end
else
--einschalten
minetest.log("action", mesecon.postostring(pos) .. "--> on_placenode.is_effector_off")
mesecon.changesignal(npos, nnode, neighbors[n].link, mesecon.state.on, 1)
mesecon.activate(npos, nnode, neighbors[n].link, 1)
end
end
end
end
end

View File

@ -359,6 +359,7 @@ for i = 1, 4 do
receptor = {
state = mesecon.state.on,
rules = delayer_get_output_rules,
opaquespread = true,
},
effector = {
rules = delayer_get_input_rules,
@ -472,7 +473,8 @@ minetest.register_node("mesecons_delayer:delayer_on_locked", {
receptor =
{
state = mesecon.state.on,
rules = delayer_get_output_rules
rules = delayer_get_output_rules,
opaquespread = true,
},
effector =
{