From ffc4dd7cb7d438fe192d2e6bbb7c6f207a930828 Mon Sep 17 00:00:00 2001 From: Henry Behrendt Date: Sat, 28 Aug 2021 10:14:32 +0200 Subject: [PATCH] comparator and repeater(delayer) send through opaque blocks --- mcl_comparators/init.lua | 1 + mesecons/init.lua | 11 +++-- mesecons/internal.lua | 96 +++++++++++++++++++++------------------ mesecons/services.lua | 94 +++++++++++++++++++++++--------------- mesecons_delayer/init.lua | 4 +- 5 files changed, 121 insertions(+), 85 deletions(-) diff --git a/mcl_comparators/init.lua b/mcl_comparators/init.lua index d17907e..6ad28e8 100644 --- a/mcl_comparators/init.lua +++ b/mcl_comparators/init.lua @@ -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, diff --git a/mesecons/init.lua b/mesecons/init.lua index e1d127a..a3a902b 100644 --- a/mesecons/init.lua +++ b/mesecons/init.lua @@ -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) diff --git a/mesecons/internal.lua b/mesecons/internal.lua index 93f8ff3..4a789d9 100644 --- a/mesecons/internal.lua +++ b/mesecons/internal.lua @@ -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 diff --git a/mesecons/services.lua b/mesecons/services.lua index 24ae7d5..b61bb60 100644 --- a/mesecons/services.lua +++ b/mesecons/services.lua @@ -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 diff --git a/mesecons_delayer/init.lua b/mesecons_delayer/init.lua index fc12c0a..a88b392 100644 --- a/mesecons_delayer/init.lua +++ b/mesecons_delayer/init.lua @@ -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 = {