summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeija <jeija@mesecons.net>2014-11-29 15:08:37 +0100
committerJeija <jeija@mesecons.net>2014-11-29 15:08:37 +0100
commitc326dc221a4ee6a1b55b681eb1456d7da62de7fb (patch)
tree60769bae80240ae8cf6947b48ea5eb5b5947ca9a
parentd2373eb6059fabc2e5116fb8a50ebc02e351d24d (diff)
downloadmesecons-c326dc221a4ee6a1b55b681eb1456d7da62de7fb.tar
mesecons-c326dc221a4ee6a1b55b681eb1456d7da62de7fb.tar.gz
mesecons-c326dc221a4ee6a1b55b681eb1456d7da62de7fb.tar.bz2
mesecons-c326dc221a4ee6a1b55b681eb1456d7da62de7fb.tar.xz
mesecons-c326dc221a4ee6a1b55b681eb1456d7da62de7fb.zip
Rewrite Logic Gates: Makes it super-easy to add new gates and cleans up code
Fix bugs in the Luacontroller (when placing, false input pin values were given) and fix variables leaking into the global environment in pistons.
-rw-r--r--mesecons/internal.lua96
-rw-r--r--mesecons/services.lua25
-rw-r--r--mesecons/util.lua10
-rw-r--r--mesecons_gates/init.lua298
-rw-r--r--mesecons_mvps/init.lua6
-rw-r--r--mesecons_pistons/init.lua10
6 files changed, 158 insertions, 287 deletions
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
+ if gate.inputnumber == 1 then
+ set_gate(pos, node, gate.assess(newstate == "on"))
+ elseif gate.inputnumber == 2 then
+ local meta = minetest.get_meta(pos)
+ meta:set_int(link.name, newstate == "on" and 1 or 0)
-function gate_state(pos)
- name = minetest.get_node(pos).name
- return string.find(name, "_on") ~= nil
+ local val1 = meta:get_int("input1") == 1
+ local val2 = meta:get_int("input2") == 1
+ set_gate(pos, node, gate.assess(val1, val2))
+ end
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")
+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
+
+ 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 = basename.."_off", recipe = recipe})
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
+register_gate("diode", 1, function (input) return input end,
+ {{"mesecons:mesecon", "mesecons_torch:mesecon_torch_on", "mesecons_torch:mesecon_torch_on"}})
-gates = {
-{name = "diode", inputnumber = 1},
-{name = "not" , inputnumber = 1},
-{name = "nand" , inputnumber = 2},
-{name = "and" , inputnumber = 2},
-{name = "xor" , inputnumber = 2}}
+register_gate("not", 1, function (input) return not input end,
+ {{"mesecons:mesecon", "mesecons_torch:mesecon_torch_on", "mesecons:mesecon"}})
-local onoff, drop, nodename, description, groups
-for _, gate in ipairs(gates) do
- if gate.inputnumber == 1 then
- get_rules = gate_get_input_rules_oneinput
- 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
-
- 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
- }
- }
- })
- end
-end
+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", "", ""}})
-minetest.register_craft({
- output = 'mesecons_gates:diode_off',
- recipe = {
- {'', '', ''},
- {'mesecons:mesecon', 'mesecons_torch:mesecon_torch_on', 'mesecons_torch:mesecon_torch_on'},
- {'', '', ''},
- },
-})
-
-minetest.register_craft({
- output = 'mesecons_gates:not_off',
- recipe = {
- {'', '', ''},
- {'mesecons:mesecon', 'mesecons_torch:mesecon_torch_on', 'mesecons:mesecon'},
- {'', '', ''},
- },
-})
-
-minetest.register_craft({
- output = 'mesecons_gates:and_off',
- recipe = {
- {'mesecons:mesecon', '', ''},
- {'', 'mesecons_materials:silicon', 'mesecons:mesecon'},
- {'mesecons:mesecon', '', ''},
- },
-})
-
-minetest.register_craft({
- output = 'mesecons_gates:nand_off',
- recipe = {
- {'mesecons:mesecon', '', ''},
- {'', 'mesecons_materials:silicon', 'mesecons_torch:mesecon_torch_on'},
- {'mesecons:mesecon', '', ''},
- },
-})
-
-minetest.register_craft({
- output = 'mesecons_gates:xor_off',
- recipe = {
- {'mesecons:mesecon', '', ''},
- {'', 'mesecons_materials:silicon', 'mesecons_materials:silicon'},
- {'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