diff --git a/mcl_comparators/depends.txt b/mcl_comparators/depends.txt index 2cc05ce..822b876 100644 --- a/mcl_comparators/depends.txt +++ b/mcl_comparators/depends.txt @@ -1,4 +1,5 @@ mesecons mcl_sounds +mcl_jukebox doc? screwdriver? diff --git a/mcl_comparators/init.lua b/mcl_comparators/init.lua index aa7179d..63a694b 100644 --- a/mcl_comparators/init.lua +++ b/mcl_comparators/init.lua @@ -46,13 +46,14 @@ local function comparator_turnon(params) end function comparator_removevoltage(pos, link, voltage) - local frontiers = {{pos = pos, link = link}} - local signals = {} - local rec_on = {} + local cur_vol = voltage+1 minetest.log("action", mesecon.postostring(pos) .. "-->" .. "comparator_removevoltage" .. " v="..cur_vol) + local frontiers = {{pos = pos, link = link, voltage=cur_vol}} + + local depth = 1 while frontiers[1] do local f = table.remove(frontiers, 1) @@ -63,7 +64,7 @@ function comparator_removevoltage(pos, link, voltage) local tmp_vol = (meta:get_string("mesecon_voltage")~="" and meta:get_int("mesecon_voltage") or 15) - if tmp_vol=1 then + if tmp_vol=1 then --solange spannung niedriger wird cur_vol = tmp_vol meta:set_int("mesecon_voltage", 0) @@ -72,7 +73,7 @@ function comparator_removevoltage(pos, link, voltage) local np = vector.add(f.pos, r) -- check neighbors for _, l in pairs(mesecon.rules_link_rule_all(f.pos, r)) do - table.insert(frontiers, {pos = np, link = l}) + table.insert(frontiers, {pos = np, link = l, voltage=cur_vol}) end end end @@ -106,62 +107,104 @@ end -- weather pos has an inventory that contains at least one item -local function container_inventory_nonempty(pos) +local function container_inventory_nonempty(pos, rule) -- https://minecraft.fandom.com/wiki/Redstone_Comparator#Measure_block_state -- signal strength = floor(1 + ((sum of all slots' fullnesses) / (number of slots in container)) × 14) -- fullness of a slot = number of items in slot / max stack size for this type of item - - - + local invnode = minetest.get_node(pos) + local invnodedef = minetest.registered_nodes[invnode.name] -- Ignore stale nodes - if not invnodedef then return 0 end + if not invnodedef then return 0, false end + minetest.log("action", mesecon.postostring(pos) .. "-->" .. "container_inventory_nonempty.1") + -- Only accept containers. When a container is dug, it's inventory -- seems to stay. and we don't want to accept the inventory of an air -- block - if not invnodedef.groups.container then return 0 end + if not invnodedef.groups.container then + if minetest.get_item_group(invnode.name, "opaque") == 1 and rule then + minetest.log("action", mesecon.postostring(pos) .. "-->" .. "container_inventory_nonempty.2") + --found opaque block -> check next block + local backback_pos = vector.add(pos, rule) + local bb_voltage, _ = container_inventory_nonempty(backback_pos, nil) + return bb_voltage, true + else + return 0, false + end + end + minetest.log("action", mesecon.postostring(pos) .. "-->" .. "container_inventory_nonempty.3") local inv = minetest.get_inventory({type="node", pos=pos}) - if not inv then return 0 end + if not inv then return 0, false end - + minetest.log("action", mesecon.postostring(pos) .. "-->" .. "container_inventory_nonempty.4") --minetest.log("action", mesecon.postostring(pos) .. "-->" .. "container_inventory_nonempty.inv= " .. mesecon.tabletostring(inv:get_lists())) - local item_count = 0 - local inv_space = 0 - - for listname, _ in pairs(inv:get_lists()) do - - --minetest.log("action", mesecon.postostring(pos) .. "-->" .. "container_inventory_nonempty.inv.size= " .. inv:get_size(listname)) - - local stack = inv:get_stack(listname, 1) - - --minetest.log("action", mesecon.postostring(pos) .. "-->" .. "container_inventory_nonempty.inv.stack1= " .. mesecon.tabletostring(stack)) - --minetest.log("action", mesecon.postostring(pos) .. "-->" .. "container_inventory_nonempty.inv.stack1.max= " .. stack:get_stack_max()) - --minetest.log("action", mesecon.postostring(pos) .. "-->" .. "container_inventory_nonempty.inv.stack1.count= " .. stack:get_count()) - - local st_size = inv:get_size(listname) - inv_space = inv_space + (64 * st_size) - for i = 1,st_size do - local stack = inv:get_stack(listname, i) - item_count = item_count + (stack:get_count() * 64 / stack:get_stack_max()) + if invnode.name=="mcl_jukebox:jukebox" then + if not inv:is_empty("main") then + -- Jukebox contains a disc: Stop music and remove disc + local record = inv:get_stack("main", 1) + minetest.log("action", mesecon.postostring(pos) .. "-->" .. "container_inventory_nonempty.juke="..mesecon.tabletostring(record:get_name())) + if mcl_jukebox.registered_records[record:get_name()] then + minetest.log("action", mesecon.postostring(pos) .. "-->" .. "container_inventory_nonempty.juke="..mesecon.tabletostring(mcl_jukebox.registered_records[record:get_name()])) + local ident = mcl_jukebox.registered_records[record:get_name()][3] + local t = { + id_13 = 1, + id_cat = 2, + id_blocks = 3, + id_chirp = 4, + id_far = 5, + id_mall = 6, + id_mellohi = 7, + id_stal = 8, + id_strad = 9, + id_ward = 10, + id_11 = 11, + id_wait = 12, + id_Pigstep = 13, + } + local vol = t["id_"..ident] + minetest.log("action", mesecon.postostring(pos) .. "-->" .. "container_inventory_nonempty.juke "..ident.."="..vol) + if vol then return vol, false end + end end - --if not inv:is_empty(listname) then return true, 15 end - end - - --minetest.log("action", mesecon.postostring(pos) .. "-->" .. "container_inventory_nonempty.inv_space= " .. inv_space) - --minetest.log("action", mesecon.postostring(pos) .. "-->" .. "container_inventory_nonempty.item_count= " .. item_count) - - if item_count>0 then - local voltage = math.floor(1 + (item_count/inv_space*14)) - --minetest.log("action", mesecon.postostring(pos) .. "-->" .. "container_inventory_nonempty.voltage= " .. voltage) - return voltage - end + else + local item_count = 0 + local inv_space = 0 - return 0 + + for listname, _ in pairs(inv:get_lists()) do + + minetest.log("action", mesecon.postostring(pos) .. "-->" .. "container_inventory_nonempty.inv.size= " .. inv:get_size(listname)) + + local stack = inv:get_stack(listname, 1) + + minetest.log("action", mesecon.postostring(pos) .. "-->" .. "container_inventory_nonempty.inv.stack1= " .. mesecon.tabletostring(stack)) + minetest.log("action", mesecon.postostring(pos) .. "-->" .. "container_inventory_nonempty.inv.stack1.max= " .. stack:get_stack_max()) + minetest.log("action", mesecon.postostring(pos) .. "-->" .. "container_inventory_nonempty.inv.stack1.count= " .. stack:get_count()) + + local st_size = inv:get_size(listname) + inv_space = inv_space + (64 * st_size) + for i = 1,st_size do + local stack = inv:get_stack(listname, i) + item_count = item_count + (stack:get_count() * 64 / stack:get_stack_max()) + end + --if not inv:is_empty(listname) then return true, 15 end + end + + minetest.log("action", mesecon.postostring(pos) .. "-->" .. "container_inventory_nonempty.inv_space= " .. inv_space) + minetest.log("action", mesecon.postostring(pos) .. "-->" .. "container_inventory_nonempty.item_count= " .. item_count) + + if item_count>0 then + local voltage = math.floor(1 + (item_count/inv_space*14)) + minetest.log("action", mesecon.postostring(pos) .. "-->" .. "container_inventory_nonempty.voltage= " .. voltage) + return voltage, false + end + end + return 0, false end -- weather pos has an constant signal output for the comparator @@ -178,18 +221,21 @@ local function comparator_desired_on(pos, node) local voltage = 0 if back_rule then local back_pos = vector.add(pos, back_rule) - --local _, vo_back = mesecon.is_power_on(back_pos) - local _, _, vo_back = mesecon.is_powered(back_pos) + local _, _, vo_back = mesecon.is_powered(pos, back_rule) - - local vo_coin = container_inventory_nonempty(back_pos) + local vo_coin, spread = container_inventory_nonempty(back_pos, back_rule) local vo_sso = static_signal_output(back_pos) + if vo_coin>=1 and spread and vo_back<15 then + --container through opaque block and block is powerd less than 15 -> ignore powered block + vo_back=0 + end + voltage = math.max(vo_back, vo_coin, vo_sso) + minetest.log("action", mesecon.postostring(pos) .. "-->" .. "comparator_desired_on1.voltage= " .. voltage .. " vb="..vo_back.." vc="..vo_coin.." vs="..vo_sso) end - --minetest.log("action", mesecon.postostring(pos) .. "-->" .. "comparator_desired_on1.voltage= " .. voltage .. "state="..tostring(state)) -- if back input is off, we don't need to check side inputs if voltage<1 then return false, 0 end @@ -204,15 +250,15 @@ local function comparator_desired_on(pos, node) end end - --minetest.log("action", mesecon.postostring(pos) .. "-->" .. "comparator_desired_on2.voltage= " .. voltage .. "state="..tostring(state)) + minetest.log("action", mesecon.postostring(pos) .. "-->" .. "comparator_desired_on2.voltage= " .. voltage) if mode == "comp" then -- Comparators in comparison mode if side_voltage > voltage then - --minetest.log("action", mesecon.postostring(pos) .. "-->" .. "comparator_desired_on3.voltage= " .. voltage .. "state="..tostring(state)) + minetest.log("action", mesecon.postostring(pos) .. "-->" .. "comparator_desired_on3.voltage= " .. voltage) return false, 0 else - --minetest.log("action", mesecon.postostring(pos) .. "-->" .. "comparator_desired_on4.voltage= " .. voltage .. "state="..tostring(state)) + minetest.log("action", mesecon.postostring(pos) .. "-->" .. "comparator_desired_on4.voltage= " .. voltage) return true, voltage end end @@ -474,7 +520,7 @@ minetest.register_abm({ "mcl_comparators:comparator_off_comp", "mcl_comparators:comparator_off_sub", }, - neighbors = {"group:container", "group:comparator_signal"}, + neighbors = {"group:container", "group:comparator_signal", "group:opaque", "mcl_jukebox:jukebox"}, interval = 1, chance = 1, action = update_self, diff --git a/mesecons/internal.lua b/mesecons/internal.lua index 9ac3b76..93f8ff3 100644 --- a/mesecons/internal.lua +++ b/mesecons/internal.lua @@ -396,6 +396,9 @@ function mesecon.turnon(pos, link, voltage) minetest.log("action", pos.x .. "/" .. pos.y .. "/" .. pos.z .. "-->" .. "turnon.voltage.input1="..(voltage or "nil")) voltage = voltage or 15 minetest.log("action", pos.x .. "/" .. pos.y .. "/" .. pos.z .. "-->" .. "turnon.voltage.input2="..voltage) + + local pn = get_node_force(pos) + --if pn and minetest.get_item_group(pn.name, "opaque") == 1 then link.spread=true end local frontiers = {{pos = pos, link = link, voltage = voltage}} local depth = 1 @@ -686,12 +689,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 + return false, false, 0, false end local node = get_node_force(pos) local rules = mesecon.get_any_inputrules(node) if not rules then - return false, false, 0 + return false, false, 0, false end if not home_pos then home_pos = pos @@ -702,8 +705,10 @@ function mesecon.is_powered(pos, rule, depth, sourcepos, home_pos) sourcepos = {} end - local function power_walk(pos, home_pos, sourcepos, rulenames, rule, depth, voltage) + local function power_walk(pos, home_pos, sourcepos, rulenames, rule, depth, voltage, fc) local spread = false + local cond = fc + minetest.log("action", mesecon.postostring(pos) .. "-->" .. "power_walk.rulenames=" .. mesecon.tabletostring(rulenames)) for _, rname in pairs(rulenames) do local np = vector.add(pos, rname) local nn = get_node_force(np) @@ -721,12 +726,21 @@ function mesecon.is_powered(pos, rule, depth, sourcepos, home_pos) if depth == 0 or spread_tmp then local meta = minetest.get_meta(np) - --minetest.log("action", mesecon.postostring(np) .. "-->" .. "is_powered.voltage0=" .. voltage) - voltage = math.max(voltage, meta:get_string("mesecon_voltage")~="" and meta:get_int("mesecon_voltage") or 15) + + + 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) + 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 @@ -735,42 +749,47 @@ function mesecon.is_powered(pos, rule, depth, sourcepos, home_pos) 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 = mesecon.is_powered(np, nil, depth + 1, sourcepos, home_pos) + 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 mesecon.mergetable(sourcepos, more_sourcepos) - voltage = math.max(voltage, more_voltage) + if more_voltage>voltage then + voltage = more_voltage + cond = more_cond + minetest.log("action", mesecon.postostring(np) .. "-->" .. "is_powered.cond1=" .. tostring(cond)) + end end end end - return sourcepos, spread, voltage + minetest.log("action", mesecon.postostring(pos) .. "-->" .. "is_powered.cond2=" .. tostring(cond)) + return sourcepos, spread, voltage, cond end local v = 0 - + local fromConductor = false local spread = 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 = power_walk(pos, home_pos, sourcepos, rulenames, rule, depth, v) + sourcepos, spread_temp, v, fromConductor = power_walk(pos, home_pos, sourcepos, rulenames, rule, depth, v, fromConductor) if spread_temp then spread = true end end else local rulenames = mesecon.rules_link_rule_all_inverted(pos, rule) - sourcepos, spread, v = power_walk(pos, home_pos, sourcepos, rulenames, rule, depth, v) + sourcepos, spread, v, fromConductor = power_walk(pos, home_pos, sourcepos, rulenames, rule, depth, v) end -- Return FALSE if not powered, return list of sources if is powered - minetest.log("action", pos.x .. "/" .. pos.y .. "/" .. pos.z .. "-->" .. "is_powered.voltage4=" .. v) + minetest.log("action", mesecon.postostring(pos) .. "-->" .. "is_powered.voltage4=" .. v .. " fC="..tostring(fromConductor).." spread="..tostring(spread)) if (#sourcepos == 0) then - return false, false, 0 + return false, false, 0, false else - return sourcepos, spread, v + return sourcepos, spread, v, fromConductor end end diff --git a/mesecons/services.lua b/mesecons/services.lua index b2ddfe4..24ae7d5 100644 --- a/mesecons/services.lua +++ b/mesecons/services.lua @@ -22,13 +22,15 @@ function mesecon.on_placenode(pos, node) -- if placed conductor is an onstate one if mesecon.is_conductor(node.name) then pos.conductor=true - local sources, _, voltage = mesecon.is_powered(pos) - minetest.log("action", mesecon.postostring(pos) .. "-->" .. "on_placenode.voltage=" .. voltage) + local sources, _, voltage, fromConductor = mesecon.is_powered(pos) + minetest.log("action", mesecon.postostring(pos) .. "-->" .. "on_placenode.voltage=" .. voltage .. " fC="..tostring(fromConductor)) minetest.log("action", mesecon.postostring(pos) .. "-->" .. "on_placenode.sources=" .. mesecon.tabletostring(sources)) if sources and voltage>=1 then + voltage = fromConductor and voltage-1 or voltage + minetest.log("action", mesecon.postostring(pos) .. "-->" .. "on_placenode.voltage2=" .. voltage ) local meta = minetest.get_meta(pos) - meta:set_int("mesecon_voltage", voltage-1) + meta:set_int("mesecon_voltage", voltage) -- also call receptor_on if itself is powered already, so that neighboring -- conductors will be activated (when pushing an on-conductor with a piston) @@ -41,9 +43,9 @@ function mesecon.on_placenode(pos, node) minetest.log("action", mesecon.postostring(pos) .. "-->" .. " on_placenode.for_turnon2=" .. mesecon.tabletostring(s) .. " nnode.name=" ..nnode.name) - mesecon.turnon(pos, rule, voltage-1) + mesecon.turnon(pos, rule, voltage) end - mesecon.receptor_on (pos, mesecon.conductor_get_rules(node), voltage-2) + mesecon.receptor_on (pos, mesecon.conductor_get_rules(node), voltage-1) elseif mesecon.is_conductor_on(node) then minetest.swap_node(pos, {name = mesecon.get_conductor_off(node)}) end @@ -51,6 +53,7 @@ function mesecon.on_placenode(pos, node) -- Effectors: Send changesignal and activate or deactivate if mesecon.is_effector(node.name) then + minetest.log("action", mesecon.postostring(pos) .. "-->" .. " on_placenode.is_effector") local powered_rules = {} local unpowered_rules = {} @@ -76,18 +79,48 @@ function mesecon.on_placenode(pos, node) end if minetest.get_item_group(node.name, "opaque") == 1 then - local neighbors = mesecon.mcl_get_neighbors(pos) - local is_powered, direct_source = mesecon.is_powered(pos) + local is_powered, direct_source, voltage = mesecon.is_powered(pos) 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_on(nnode.name) and minetest.get_item_group(nnode.name, "redstone_torch") == 0 then + 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 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