diff --git a/mesecons/internal.lua b/mesecons/internal.lua index cee90d2..d62df1f 100644 --- a/mesecons/internal.lua +++ b/mesecons/internal.lua @@ -240,7 +240,10 @@ function mesecon.changesignal(pos, node, rulename, newstate, depth) return end - mesecon.queue:add_action(pos, "change", {rulename, newstate}, nil, rulename, 1 / depth) + -- Include "change" in overwritecheck so that it cannot be overwritten + -- by "active" / "deactivate" that will be called upon the node at the same time. + local overwritecheck = {"change", rulename} + mesecon.queue:add_action(pos, "change", {rulename, newstate}, nil, overwritecheck, 1 / depth) end -- Conductors @@ -514,10 +517,7 @@ function mesecon.rules_link(output, input, dug_outputrules) --output/input are p for _, inputrule in ipairs(mesecon.flattenrules(inputrules)) do -- Check if input accepts from output if mesecon.cmpPos(mesecon.addPosRule(input, inputrule), output) then - if inputrule.sx == nil or outputrule.sx == nil - or mesecon.cmpSpecial(inputrule, outputrule) then - return true, inputrule - end + return true, inputrule end end end @@ -537,10 +537,7 @@ function mesecon.rules_link_rule_all(output, rule) for _, inputrule in ipairs(mesecon.flattenrules(inputrules)) do -- Check if input accepts from output if mesecon.cmpPos(mesecon.addPosRule(input, inputrule), output) then - if inputrule.sx == nil or rule.sx == nil - or mesecon.cmpSpecial(inputrule, rule) then - table.insert(rules, inputrule) - end + table.insert(rules, inputrule) end end return rules @@ -558,10 +555,7 @@ function mesecon.rules_link_rule_all_inverted(input, rule) for _, outputrule in ipairs(mesecon.flattenrules(outputrules)) do if mesecon.cmpPos(mesecon.addPosRule(output, outputrule), input) then - if outputrule.sx == nil or rule.sx == nil - or mesecon.cmpSpecial(outputrule, rule) then - table.insert(rules, mesecon.invertRule(outputrule)) - end + table.insert(rules, mesecon.invertRule(outputrule)) end end return rules @@ -612,20 +606,11 @@ end function mesecon.rotate_rules_right(rules) local nr = {} for i, rule in ipairs(rules) do - if rule.sx then - table.insert(nr, { - x = -rule.z, - y = rule.y, - z = rule.x, - sx = -rule.sz, - sy = rule.sy, - sz = rule.sx}) - else - table.insert(nr, { - x = -rule.z, - y = rule.y, - z = rule.x}) - end + table.insert(nr, { + x = -rule.z, + y = rule.y, + z = rule.x, + name = rule.name}) end return nr end @@ -633,20 +618,11 @@ end function mesecon.rotate_rules_left(rules) local nr = {} for i, rule in ipairs(rules) do - if rule.sx then - table.insert(nr, { - x = rule.z, - y = rule.y, - z = -rule.x, - sx = rule.sz, - sy = rule.sy, - sz = -rule.sx}) - else - table.insert(nr, { - x = rule.z, - y = rule.y, - z = -rule.x}) - end + table.insert(nr, { + x = rule.z, + y = rule.y, + z = -rule.x, + name = rule.name}) end return nr end @@ -654,20 +630,11 @@ end function mesecon.rotate_rules_down(rules) local nr = {} for i, rule in ipairs(rules) do - if rule.sx then - table.insert(nr, { - x = -rule.y, - y = rule.x, - z = rule.z, - sx = -rule.sy, - sy = rule.sx, - sz = rule.sz}) - else - table.insert(nr, { - x = -rule.y, - y = rule.x, - z = rule.z}) - end + table.insert(nr, { + x = -rule.y, + y = rule.x, + z = rule.z, + name = rule.name}) end return nr end @@ -675,20 +642,11 @@ end function mesecon.rotate_rules_up(rules) local nr = {} for i, rule in ipairs(rules) do - if rule.sx then - table.insert(nr, { - x = rule.y, - y = -rule.x, - z = rule.z, - sx = rule.sy, - sy = -rule.sx, - sz = rule.sz}) - else - table.insert(nr, { - x = rule.y, - y = -rule.x, - z = rule.z}) - end + table.insert(nr, { + x = rule.y, + y = -rule.x, + z = rule.z, + name = rule.name}) end return nr end diff --git a/mesecons/services.lua b/mesecons/services.lua index 36d9b80..215fb31 100644 --- a/mesecons/services.lua +++ b/mesecons/services.lua @@ -27,12 +27,27 @@ mesecon.on_placenode = function (pos, node) -- Effectors: Send changesignal and activate or deactivate if mesecon.is_effector(node.name) then - if mesecon.is_powered(pos) then - mesecon.changesignal(pos, node, mesecon.effector_get_rules(node), "on", 1) - mesecon.activate(pos, node, nil, 1) + local powered_rules = {} + local unpowered_rules = {} + + -- for each input rule, check if powered + for _, r in ipairs(mesecon.effector_get_rules(node)) do + local powered = mesecon.is_powered(pos, r) + if powered then table.insert(powered_rules, r) + else table.insert(unpowered_rules, r) end + + local state = powered and mesecon.state.on or mesecon.state.off + mesecon.changesignal(pos, node, r, state, 1) + end + + if (#powered_rules > 0) then + for _, r in ipairs(powered_rules) do + mesecon.activate(pos, node, r, 1) + end else - mesecon.changesignal(pos, node, mesecon.effector_get_rules(node), "off", 1) - mesecon.deactivate(pos, node, nil, 1) + for _, r in ipairs(unpowered_rules) do + mesecon.deactivate(pos, node, r, 1) + end end end end diff --git a/mesecons/util.lua b/mesecons/util.lua index 11cc95a..a64e00c 100644 --- a/mesecons/util.lua +++ b/mesecons/util.lua @@ -62,7 +62,7 @@ function mesecon.rule2bit(findrule, allrules) end for m,metarule in ipairs( allrules) do for _, rule in ipairs(metarule ) do - if mesecon.cmpPos(findrule, rule) and mesecon.cmpSpecial(findrule, rule) then + if mesecon.cmpPos(findrule, rule) then return m end end @@ -82,7 +82,7 @@ function mesecon.rule2metaindex(findrule, allrules) for m, metarule in ipairs( allrules) do for _, rule in ipairs(metarule ) do - if mesecon.cmpPos(findrule, rule) and mesecon.cmpSpecial(findrule, rule) then + if mesecon.cmpPos(findrule, rule) then return m end end @@ -153,7 +153,7 @@ function mesecon.set_bit(binary,bit,value) end function mesecon.invertRule(r) - return {x = -r.x, y = -r.y, z = -r.z, sx = r.sx, sy = r.sy, sz = r.sz} + return {x = -r.x, y = -r.y, z = -r.z} end function mesecon.addPosRule(p, r) @@ -164,10 +164,6 @@ function mesecon.cmpPos(p1, p2) return (p1.x == p2.x and p1.y == p2.y and p1.z == p2.z) end -function mesecon.cmpSpecial(r1, r2) - return (r1.sx == r2.sx and r1.sy == r2.sy and r1.sz == r2.sz) -end - function mesecon.tablecopy(table) -- deep table copy if type(table) ~= "table" then return table end -- no need to copy local newtable = {} diff --git a/mesecons_gates/init.lua b/mesecons_gates/init.lua index 345c32c..2b6771a 100644 --- a/mesecons_gates/init.lua +++ b/mesecons_gates/init.lua @@ -1,222 +1,124 @@ -function gate_rotate_rules(node) +local nodebox = { + type = "fixed", + fixed = {{-8/16, -8/16, -8/16, 8/16, -7/16, 8/16 }}, +} + +local function gate_rotate_rules(node, rules) for rotations = 0, node.param2 - 1 do rules = mesecon.rotate_rules_left(rules) end return rules end -function gate_get_output_rules(node) - rules = {{x=1, y=0, z=0}} - return gate_rotate_rules(node) +local function gate_get_output_rules(node) + return gate_rotate_rules(node, {{x=1, y=0, z=0}}) end -function gate_get_input_rules_oneinput(node) - rules = {{x=-1, y=0, z=0}, {x=1, y=0, z=0}} - return gate_rotate_rules(node) +local function gate_get_input_rules_oneinput(node) + return gate_rotate_rules(node, {{x=-1, y=0, z=0}}) end -function gate_get_input_rules_twoinputs(node) - rules = { - {x=0, y=0, z=1}, - {x=0, y=0, z=-1}, - {x=1, y=0, z=0}} - return gate_rotate_rules(node) +local function gate_get_input_rules_twoinputs(node) + return gate_rotate_rules(node, {{x=0, y=0, z=1, name="input1"}, + {x=0, y=0, z=-1, name="input2"}}) end -function update_gate(pos, node, rulename, newstate) - yc_update_real_portstates(pos, node, rulename, newstate) - gate = get_gate(pos) - L = rotate_ports( - yc_get_real_portstates(pos), - minetest.get_node(pos).param2 - ) - if gate == "diode" then - set_gate(pos, L.a) - elseif gate == "not" then - set_gate(pos, not L.a) - elseif gate == "nand" then - set_gate(pos, not(L.b and L.d)) - elseif gate == "and" then - set_gate(pos, L.b and L.d) - elseif gate == "xor" then - set_gate(pos, (L.b and not L.d) or (not L.b and L.d)) +local function set_gate(pos, node, state) + local gate = minetest.registered_nodes[node.name] + + if mesecon.do_overheat(pos) then + minetest.remove_node(pos) + mesecon.receptor_off(pos, gate_get_output_rules(node)) + minetest.add_item(pos, gate.drop) + elseif state then + minetest.swap_node(pos, {name = gate.onstate, param2=node.param2}) + mesecon.receptor_on(pos, gate_get_output_rules(node)) + else + minetest.swap_node(pos, {name = gate.offstate, param2=node.param2}) + mesecon.receptor_off(pos, gate_get_output_rules(node)) end end -function set_gate(pos, on) - gate = get_gate(pos) - local meta = minetest.get_meta(pos) - if on ~= gate_state(pos) then - if mesecon.do_overheat(pos) then - pop_gate(pos) - else - local node = minetest.get_node(pos) - if on then - minetest.swap_node(pos, {name = "mesecons_gates:"..gate.."_on", param2=node.param2}) - mesecon.receptor_on(pos, - gate_get_output_rules(node)) - else - minetest.swap_node(pos, {name = "mesecons_gates:"..gate.."_off", param2=node.param2}) - mesecon.receptor_off(pos, - gate_get_output_rules(node)) - end - end - end -end +local function update_gate(pos, node, link, newstate) + local gate = minetest.registered_nodes[node.name] -function get_gate(pos) - return minetest.registered_nodes[minetest.get_node(pos).name].mesecons_gate -end - -function gate_state(pos) - name = minetest.get_node(pos).name - return string.find(name, "_on") ~= nil -end - -function pop_gate(pos) - gate = get_gate(pos) - minetest.remove_node(pos) - minetest.after(0.2, function (pos) - mesecon.receptor_off(pos, mesecon.rules.flat) - end , pos) -- wait for pending parsings - minetest.add_item(pos, "mesecons_gates:"..gate.."_off") -end - -function rotate_ports(L, param2) - for rotations=0, param2-1 do - port = L.a - L.a = L.b - L.b = L.c - L.c = L.d - L.d = port - end - return L -end - -gates = { -{name = "diode", inputnumber = 1}, -{name = "not" , inputnumber = 1}, -{name = "nand" , inputnumber = 2}, -{name = "and" , inputnumber = 2}, -{name = "xor" , inputnumber = 2}} - -local onoff, drop, nodename, description, groups -for _, gate in ipairs(gates) do if gate.inputnumber == 1 then - get_rules = gate_get_input_rules_oneinput + set_gate(pos, node, gate.assess(newstate == "on")) elseif gate.inputnumber == 2 then - get_rules = gate_get_input_rules_twoinputs - end - for on = 0, 1 do - nodename = "mesecons_gates:"..gate.name - if on == 1 then - onoff = "on" - drop = nodename.."_off" - nodename = nodename.."_"..onoff - description = "You hacker you!" - groups = {dig_immediate=2, not_in_creative_inventory=1, overheat = 1} - else - onoff = "off" - drop = nil - nodename = nodename.."_"..onoff - description = gate.name.." Gate" - groups = {dig_immediate=2, overheat = 1} - end + local meta = minetest.get_meta(pos) + meta:set_int(link.name, newstate == "on" and 1 or 0) - tiles = "jeija_microcontroller_bottom.png^".. - "jeija_gate_"..onoff..".png^".. - "jeija_gate_"..gate.name..".png" - - node_box = { - type = "fixed", - fixed = { - {-8/16, -8/16, -8/16, 8/16, -7/16, 8/16 }, - }, - } - - local mesecon_state - if on == 1 then - mesecon_state = mesecon.state.on - else - mesecon_state = mesecon.state.off - end - - minetest.register_node(nodename, { - description = description, - paramtype = "light", - paramtype2 = "facedir", - drawtype = "nodebox", - tiles = {tiles}, - inventory_image = tiles, - selection_box = node_box, - node_box = node_box, - walkable = true, - on_construct = function(pos) - local meta = minetest.get_meta(pos) - update_gate(pos) - end, - groups = groups, - drop = drop, - sounds = default.node_sound_stone_defaults(), - mesecons_gate = gate.name, - mesecons = - { - receptor = - { - state = mesecon_state, - rules = gate_get_output_rules - }, - effector = - { - rules = get_rules, - action_change = update_gate - } - } - }) + local val1 = meta:get_int("input1") == 1 + local val2 = meta:get_int("input2") == 1 + set_gate(pos, node, gate.assess(val1, val2)) end end -minetest.register_craft({ - output = 'mesecons_gates:diode_off', - recipe = { - {'', '', ''}, - {'mesecons:mesecon', 'mesecons_torch:mesecon_torch_on', 'mesecons_torch:mesecon_torch_on'}, - {'', '', ''}, - }, -}) +function register_gate(name, inputnumber, assess, recipe) + local get_inputrules = inputnumber == 2 and gate_get_input_rules_twoinputs or + gate_get_input_rules_oneinput + local description = "Mesecons Logic Gate: "..name -minetest.register_craft({ - output = 'mesecons_gates:not_off', - recipe = { - {'', '', ''}, - {'mesecons:mesecon', 'mesecons_torch:mesecon_torch_on', 'mesecons:mesecon'}, - {'', '', ''}, - }, -}) + local basename = "mesecons_gates:"..name + mesecon.register_node(basename, { + description = description, + inventory_image = "jeija_gate_off.png^jeija_gate_"..name..".png", + paramtype = "light", + paramtype2 = "facedir", + drawtype = "nodebox", + drop = basename.."_off", + selection_box = nodebox, + node_box = nodebox, + walkable = true, + sounds = default.node_sound_stone_defaults(), + assess = assess, + onstate = basename.."_on", + offstate = basename.."_off", + inputnumber = inputnumber + },{ + tiles = {"jeija_microcontroller_bottom.png^".."jeija_gate_off.png^".. + "jeija_gate_"..name..".png"}, + groups = {dig_immediate = 2}, + mesecons = { receptor = { + state = "off", + rules = gate_get_output_rules + }, effector = { + rules = get_inputrules, + action_change = update_gate + }} + },{ + tiles = {"jeija_microcontroller_bottom.png^".."jeija_gate_on.png^".. + "jeija_gate_"..name..".png"}, + groups = {dig_immediate = 2, not_in_creative_inventory = 1}, + mesecons = { receptor = { + state = "on", + rules = gate_get_output_rules + }, effector = { + rules = get_inputrules, + action_change = update_gate + }} + }) -minetest.register_craft({ - output = 'mesecons_gates:and_off', - recipe = { - {'mesecons:mesecon', '', ''}, - {'', 'mesecons_materials:silicon', 'mesecons:mesecon'}, - {'mesecons:mesecon', '', ''}, - }, -}) + minetest.register_craft({output = basename.."_off", recipe = recipe}) +end -minetest.register_craft({ - output = 'mesecons_gates:nand_off', - recipe = { - {'mesecons:mesecon', '', ''}, - {'', 'mesecons_materials:silicon', 'mesecons_torch:mesecon_torch_on'}, - {'mesecons:mesecon', '', ''}, - }, -}) +register_gate("diode", 1, function (input) return input end, + {{"mesecons:mesecon", "mesecons_torch:mesecon_torch_on", "mesecons_torch:mesecon_torch_on"}}) -minetest.register_craft({ - output = 'mesecons_gates:xor_off', - recipe = { - {'mesecons:mesecon', '', ''}, - {'', 'mesecons_materials:silicon', 'mesecons_materials:silicon'}, - {'mesecons:mesecon', '', ''}, - }, -}) +register_gate("not", 1, function (input) return not input end, + {{"mesecons:mesecon", "mesecons_torch:mesecon_torch_on", "mesecons:mesecon"}}) + +register_gate("and", 2, function (val1, val2) return val1 and val2 end, + {{"mesecons:mesecon", "", ""}, + {"", "mesecons_materials:silicon", "mesecons:mesecon"}, + {"mesecons:mesecon", "", ""}}) + +register_gate("nand", 2, function (val1, val2) return not (val1 and val2) end, + {{"mesecons:mesecon", "", ""}, + {"", "mesecons_materials:silicon", "mesecons_torch:mesecon_torch_on"}, + {"mesecons:mesecon", "", ""}}) + +register_gate("xor", 2, function (val1, val2) return (val1 or val2) and not (val1 and val2) end, + {{"mesecons:mesecon", "", ""}, + {"", "mesecons_materials:silicon", "mesecons_materials:silicon"}, + {"mesecons:mesecon", "", ""}}) diff --git a/mesecons_mvps/init.lua b/mesecons_mvps/init.lua index 163ad28..bcbda17 100644 --- a/mesecons_mvps/init.lua +++ b/mesecons_mvps/init.lua @@ -94,7 +94,7 @@ function mesecon.mvps_push(pos, dir, maximum) -- pos: pos of mvps; dir: directio -- add nodes for _, n in ipairs(nodes) do - np = mesecon.addPosRule(n.pos, dir) + local np = mesecon.addPosRule(n.pos, dir) minetest.add_node(np, n.node) minetest.get_meta(np):from_table(n.meta) end @@ -123,8 +123,8 @@ mesecon.register_on_mvps_move(function(moved_nodes) end) function mesecon.mvps_pull_single(pos, dir) -- pos: pos of mvps; direction: direction of pull (matches push direction for sticky pistons) - np = mesecon.addPosRule(pos, dir) - nn = minetest.get_node(np) + local np = mesecon.addPosRule(pos, dir) + local nn = minetest.get_node(np) if ((not minetest.registered_nodes[nn.name]) --unregistered node or minetest.registered_nodes[nn.name].liquidtype == "none") --non-liquid node diff --git a/mesecons_pistons/init.lua b/mesecons_pistons/init.lua index b247039..71e63e7 100644 --- a/mesecons_pistons/init.lua +++ b/mesecons_pistons/init.lua @@ -55,8 +55,8 @@ piston_get_direction = function(dir, node) end local piston_remove_pusher = function(pos, node) - pistonspec = minetest.registered_nodes[node.name].mesecons_piston - dir = piston_get_direction(pistonspec.dir, node) + local pistonspec = minetest.registered_nodes[node.name].mesecons_piston + local dir = piston_get_direction(pistonspec.dir, node) local pusherpos = mesecon.addPosRule(pos, dir) local pushername = minetest.get_node(pusherpos).name @@ -100,9 +100,9 @@ local piston_off = function(pos, node) piston_remove_pusher(pos, node) if pistonspec.sticky then - dir = piston_get_direction(pistonspec.dir, node) - pullpos = mesecon.addPosRule(pos, dir) - stack = mesecon.mvps_pull_single(pullpos, dir) + local dir = piston_get_direction(pistonspec.dir, node) + local pullpos = mesecon.addPosRule(pos, dir) + local stack = mesecon.mvps_pull_single(pullpos, dir) mesecon.mvps_process_stack(pos, dir, stack) end end