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 = { receptor = {
state = state, state = state,
rules = comparator_get_output_rules, rules = comparator_get_output_rules,
opaquespread = (state==mesecon.state.on),
}, },
effector = { effector = {
rules = comparator_get_input_rules, rules = comparator_get_input_rules,

View File

@ -69,16 +69,21 @@ dofile(minetest.get_modpath("mesecons").."/internal.lua");
-- API -- API
-- these are the only functions you need to remember -- 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() mesecon.vm_begin()
rules = rules or mesecon.rules.default 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 -- Call turnon on all linking positions
for _, rule in pairs(mesecon.flattenrules(rules)) do for _, rule in pairs(mesecon.flattenrules(rules)) do
local np = vector.add(pos, rule) local np = vector.add(pos, rule)
local rulenames = mesecon.rules_link_rule_all(pos, rule) local rulenames = mesecon.rules_link_rule_all(pos, rule)
for _, rulename in pairs(rulenames) do 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) mesecon.turnon(np, rulename, voltage)
end end
end end
@ -86,8 +91,8 @@ mesecon.queue:add_function("receptor_on", function (pos, rules, voltage)
mesecon.vm_commit() mesecon.vm_commit()
end) end)
function mesecon.receptor_on(pos, rules, voltage) function mesecon.receptor_on(pos, rules, voltage, opaquespread)
mesecon.queue:add_action(pos, "receptor_on", {rules, voltage}, nil, rules) mesecon.queue:add_action(pos, "receptor_on", {rules, voltage, opaquespread}, nil, rules)
end end
mesecon.queue:add_function("receptor_off", function (pos, rules) mesecon.queue:add_function("receptor_off", function (pos, rules)

View File

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

View File

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

View File

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