diff options
author | khonkhortisan <khonkhortisan@gmail.com> | 2013-08-27 22:22:30 -0700 |
---|---|---|
committer | khonkhortisan <khonkhortisan@gmail.com> | 2013-08-27 22:22:30 -0700 |
commit | 913e355a718c41551fe0e29ff1356e11d669ac73 (patch) | |
tree | a1ae8ead16928c75e5d27c7b1191e3bb033b24a5 /mesecons | |
parent | 96011bc71816b5e9eb2cc6c86f009198dfb1146c (diff) | |
parent | 885899cbaf6ccb2d22a3495131204ea0d01131ed (diff) | |
download | mesecons-913e355a718c41551fe0e29ff1356e11d669ac73.tar mesecons-913e355a718c41551fe0e29ff1356e11d669ac73.tar.gz mesecons-913e355a718c41551fe0e29ff1356e11d669ac73.tar.bz2 mesecons-913e355a718c41551fe0e29ff1356e11d669ac73.tar.xz mesecons-913e355a718c41551fe0e29ff1356e11d669ac73.zip |
Merge pull request #112 from khonkhortisan/multi_rules
Multi rules
Merged for near-future textures to be merged cleanly.
Diffstat (limited to 'mesecons')
-rw-r--r-- | mesecons/init.lua | 6 | ||||
-rw-r--r-- | mesecons/internal.lua | 132 | ||||
-rw-r--r-- | mesecons/services.lua | 2 | ||||
-rw-r--r-- | mesecons/util.lua | 137 |
4 files changed, 240 insertions, 37 deletions
diff --git a/mesecons/init.lua b/mesecons/init.lua index 635725f..612a823 100644 --- a/mesecons/init.lua +++ b/mesecons/init.lua @@ -104,7 +104,7 @@ dofile(minetest.get_modpath("mesecons").."/legacy.lua"); function mesecon:receptor_on_i(pos, rules) rules = rules or mesecon.rules.default - for _, rule in ipairs(rules) do + for _, rule in ipairs(mesecon:flattenrules(rules)) do local np = mesecon:addPosRule(pos, rule) local link, rulename = mesecon:rules_link(pos, np, rules) if link then @@ -125,11 +125,11 @@ end function mesecon:receptor_off_i(pos, rules) rules = rules or mesecon.rules.default - for _, rule in ipairs(rules) do + for _, rule in ipairs(mesecon:flattenrules(rules)) do local np = mesecon:addPosRule(pos, rule) local link, rulename = mesecon:rules_link(pos, np, rules) if link then - if not mesecon:connected_to_receptor(np) then + if not mesecon:connected_to_receptor(np, mesecon:invertRule(rule)) then mesecon:turnoff(np, rulename) else mesecon:changesignal(np, minetest.env:get_node(np), rulename, mesecon.state.off) diff --git a/mesecons/internal.lua b/mesecons/internal.lua index 30991cd..ad0fef1 100644 --- a/mesecons/internal.lua +++ b/mesecons/internal.lua @@ -303,18 +303,38 @@ end -- Conductors -function mesecon:is_conductor_on(nodename) +function mesecon:is_conductor_on(nodename, rulename) local conductor = mesecon:get_conductor(nodename) - if conductor and conductor.state == mesecon.state.on then - return true + if conductor then + if conductor.state then + return conductor.state == mesecon.state.on + end + if conductor.states then + if not rulename then + return mesecon:getstate(nodename, conductor.states) ~= 1 + end + local bit = mesecon:rule2bit(rulename, mesecon:conductor_get_rules(minetest.registered_nodes[nodename])) + local binstate = mesecon:getbinstate(nodename, conductor.states) + return mesecon:get_bit(binstate, bit) + end end return false end -function mesecon:is_conductor_off(nodename) +function mesecon:is_conductor_off(nodename, rulename) local conductor = mesecon:get_conductor(nodename) - if conductor and conductor.state == mesecon.state.off then - return true + if conductor then + if conductor.state then + return conductor.state == mesecon.state.off + end + if conductor.states then + if not rulename then + return mesecon:getstate(nodename, conductor.states) == 1 + end + local bit = mesecon:rule2bit(rulename, mesecon:conductor_get_rules(minetest.registered_nodes[nodename])) + local binstate = mesecon:getbinstate(nodename, conductor.states) + return not mesecon:get_bit(binstate, bit) + end end return false end @@ -327,20 +347,36 @@ function mesecon:is_conductor(nodename) return false end -function mesecon:get_conductor_on(offstate) +function mesecon:get_conductor_on(offstate, rulename) local conductor = mesecon:get_conductor(offstate) if conductor then - return conductor.onstate + if conductor.onstate then + return conductor.onstate + end + if conductor.states then + local bit = mesecon:rule2bit(rulename, mesecon:conductor_get_rules(minetest.registered_nodes[offstate])) + local binstate = mesecon:getbinstate(offstate, conductor.states) + binstate = mesecon:set_bit(binstate, bit, "1") + return conductor.states[tonumber(binstate,2)+1] + end end - return false + return offstate end -function mesecon:get_conductor_off(onstate) +function mesecon:get_conductor_off(onstate, rulename) local conductor = mesecon:get_conductor(onstate) if conductor then - return conductor.offstate + if conductor.offstate then + return conductor.offstate + end + if conductor.states then + local bit = mesecon:rule2bit(rulename, mesecon:conductor_get_rules(minetest.registered_nodes[onstate])) + local binstate = mesecon:getbinstate(onstate, conductor.states) + binstate = mesecon:set_bit(binstate, bit, "0") + return conductor.states[tonumber(binstate,2)+1] + end end - return false + return onstate end function mesecon:conductor_get_rules(node) @@ -358,17 +394,17 @@ end -- some more general high-level stuff -function mesecon:is_power_on(pos) +function mesecon:is_power_on(pos, rulename) local node = minetest.env:get_node(pos) - if mesecon:is_conductor_on(node.name) or mesecon:is_receptor_on(node.name) then + if mesecon:is_conductor_on(node.name, rulename) or mesecon:is_receptor_on(node.name) then return true end return false end -function mesecon:is_power_off(pos) +function mesecon:is_power_off(pos, rulename) local node = minetest.env:get_node(pos) - if mesecon:is_conductor_off(node.name) or mesecon:is_receptor_off(node.name) then + if mesecon:is_conductor_off(node.name, rulename) or mesecon:is_receptor_off(node.name) then return true end return false @@ -377,11 +413,21 @@ end function mesecon:turnon(pos, rulename) local node = minetest.env:get_node(pos) - if mesecon:is_conductor_off(node.name) then + if mesecon:is_conductor_off(node.name, rulename) then local rules = mesecon:conductor_get_rules(node) - minetest.env:add_node(pos, {name = mesecon:get_conductor_on(node.name), param2 = node.param2}) - for _, rule in ipairs(rules) do + if not rulename then + for _, rule in ipairs(mesecon:flattenrules(rules)) do + if mesecon:connected_to_receptor(pos, rule) then + mesecon:turnon(pos, rule) + end + end + return + end + + minetest.env:add_node(pos, {name = mesecon:get_conductor_on(node.name, rulename), param2 = node.param2}) + + for _, rule in ipairs(mesecon:rule2meta(rulename, rules)) do local np = mesecon:addPosRule(pos, rule) local link, rulename = mesecon:rules_link(pos, np) @@ -400,11 +446,21 @@ end function mesecon:turnoff(pos, rulename) local node = minetest.env:get_node(pos) - if mesecon:is_conductor_on(node.name) then + if mesecon:is_conductor_on(node.name, rulename) then local rules = mesecon:conductor_get_rules(node) - minetest.env:add_node(pos, {name = mesecon:get_conductor_off(node.name), param2 = node.param2}) + --[[ + if not rulename then + for _, rule in ipairs(mesecon:flattenrules(rules)) do + if mesecon:is_powered(pos, rule) then + mesecon:turnoff(pos, rule) + end + end + return + end + --]] + minetest.env:add_node(pos, {name = mesecon:get_conductor_off(node.name, rulename), param2 = node.param2}) - for _, rule in ipairs(rules) do + for _, rule in ipairs(mesecon:rule2meta(rulename, rules)) do local np = mesecon:addPosRule(pos, rule) local link, rulename = mesecon:rules_link(pos, np) @@ -422,17 +478,17 @@ function mesecon:turnoff(pos, rulename) end -function mesecon:connected_to_receptor(pos) +function mesecon:connected_to_receptor(pos, rulename) local node = minetest.env:get_node(pos) -- Check if conductors around are connected local rules = mesecon:get_any_inputrules(node) if not rules then return false end - for _, rule in ipairs(rules) do + for _, rule in ipairs(mesecon:rule2meta(rulename, rules)) do local np = mesecon:addPosRule(pos, rule) if mesecon:rules_link(np, pos) then - if mesecon:find_receptor_on(np, {}) then + if mesecon:find_receptor_on(np, {}, mesecon:invertRule(rule)) then return true end end @@ -441,7 +497,7 @@ function mesecon:connected_to_receptor(pos) return false end -function mesecon:find_receptor_on(pos, checked) +function mesecon:find_receptor_on(pos, checked, rulename) -- find out if node has already been checked (to prevent from endless loop) for _, cp in ipairs(checked) do if mesecon:cmpPos(cp, pos) then @@ -459,10 +515,10 @@ function mesecon:find_receptor_on(pos, checked) if mesecon:is_conductor(node.name) then local rules = mesecon:conductor_get_rules(node) - for _, rule in ipairs(rules) do + for _, rule in ipairs(mesecon:rule2meta(rulename, rules)) do local np = mesecon:addPosRule(pos, rule) if mesecon:rules_link(np, pos) then - if mesecon:find_receptor_on(np, checked) then + if mesecon:find_receptor_on(np, checked, mesecon:invertRule(rule)) then return true end end @@ -481,10 +537,10 @@ function mesecon:rules_link(output, input, dug_outputrules) --output/input are p return end - for _, outputrule in ipairs(outputrules) do + for _, outputrule in ipairs(mesecon:flattenrules(outputrules)) do -- Check if output sends to input if mesecon:cmpPos(mesecon:addPosRule(output, outputrule), input) then - for _, inputrule in ipairs(inputrules) do + for _, inputrule in ipairs(mesecon:flattenrules(inputrules)) do -- Check if input accepts from output if mesecon:cmpPos(mesecon:addPosRule(input, inputrule), output) then return true, inputrule @@ -499,16 +555,26 @@ function mesecon:rules_link_anydir(pos1, pos2) return mesecon:rules_link(pos1, pos2) or mesecon:rules_link(pos2, pos1) end -function mesecon:is_powered(pos) +function mesecon:is_powered(pos, rule) local node = minetest.env:get_node(pos) local rules = mesecon:get_any_inputrules(node) if not rules then return false end - for _, rule in ipairs(rules) do + if not rule then + for _, rule in ipairs(mesecon:flattenrules(rules)) do + local np = mesecon:addPosRule(pos, rule) + local nn = minetest.env:get_node(np) + + if (mesecon:is_conductor_on (nn.name, mesecon:invertRule(rule)) or mesecon:is_receptor_on (nn.name)) + and mesecon:rules_link(np, pos) then + return true + end + end + else local np = mesecon:addPosRule(pos, rule) local nn = minetest.env:get_node(np) - if (mesecon:is_conductor_on (nn.name) or mesecon:is_receptor_on (nn.name)) + if (mesecon:is_conductor_on (nn.name, mesecon:invertRule(rule)) or mesecon:is_receptor_on (nn.name)) and mesecon:rules_link(np, pos) then return true end diff --git a/mesecons/services.lua b/mesecons/services.lua index 34413d1..a47b5ec 100644 --- a/mesecons/services.lua +++ b/mesecons/services.lua @@ -4,7 +4,7 @@ mesecon.on_placenode = function (pos, node) elseif mesecon:is_powered(pos) then if mesecon:is_conductor(node.name) then mesecon:turnon (pos) - mesecon:receptor_on (pos, mesecon:conductor_get_rules(node)) + --mesecon:receptor_on (pos, mesecon:conductor_get_rules(node)) else mesecon:changesignal(pos, node, mesecon:effector_get_rules(node), "on") mesecon:activate(pos, node) diff --git a/mesecons/util.lua b/mesecons/util.lua index 08b46d1..12d2af1 100644 --- a/mesecons/util.lua +++ b/mesecons/util.lua @@ -14,6 +14,143 @@ function mesecon:move_node(pos, newpos) minetest.env:get_meta(pos):from_table(meta) end +--[[ new functions: +mesecon:flattenrules(allrules) +mesecon:rule2bit(findrule, allrules) +mesecon:rule2meta(findrule, allrules) +dec2bin(n) +mesecon:getstate(nodename, states) +mesecon:getbinstate(nodename, states) +mesecon:get_bit(binary, bit) +mesecon:set_bit(binary, bit, value) +mesecon:invertRule(r) +--]] + +function mesecon:flattenrules(allrules) +--[[ + { + { + {xyz}, + {xyz}, + }, + { + {xyz}, + {xyz}, + }, + } +--]] + if allrules[1] and + allrules[1].x then + return allrules + end + + local shallowrules = {} + for _, metarule in ipairs( allrules) do + for _, rule in ipairs(metarule ) do + table.insert(shallowrules, rule) + end + end + return shallowrules +--[[ + { + {xyz}, + {xyz}, + {xyz}, + {xyz}, + } +--]] +end + +function mesecon:rule2bit(findrule, allrules) + --get the bit of the metarule the rule is in, or bit 1 + if (allrules[1] and + allrules[1].x) or + not findrule then + return 1 + end + for m,metarule in ipairs( allrules) do + for _, rule in ipairs(metarule ) do + if mesecon:cmpPos(findrule, rule) then + return m + end + end + end +end + +function mesecon:rule2meta(findrule, allrules) + --get the metarule the rule is in, or allrules + + if allrules[1].x then + return allrules + end + + if not(findrule) then + return mesecon:flattenrules(allrules) + end + + for m, metarule in ipairs( allrules) do + for _, rule in ipairs(metarule ) do + if mesecon:cmpPos(findrule, rule) then + return metarule + end + end + end +end + +if convert_base then + print( + "base2dec is tonumber(num,base1)\n".. + "commonlib needs dec2base(num,base2)\n".. + "and it needs base2base(num,base1,base2),\n".. + "which is dec2base(tonumber(num,base1),base2)" + ) +else + function dec2bin(n) + local x, y = math.floor(n / 2), n % 2 + if (n > 1) then + return dec2bin(x)..y + else + return ""..y + end + end +end + +function mesecon:getstate(nodename, states) + for state, name in ipairs(states) do + if name == nodename then + return state + end + end + error(nodename.." doesn't mention itself in "..dump(states)) +end + +function mesecon:getbinstate(nodename, states) + return dec2bin(mesecon:getstate(nodename, states)-1) +end + +function mesecon:get_bit(binary,bit) + bit = bit or 1 + local c = binary:len()-(bit-1) + return binary:sub(c,c) == "1" +end + +function mesecon:set_bit(binary,bit,value) + if value == "1" then + if not mesecon:get_bit(binary,bit) then + return dec2bin(tonumber(binary,2)+math.pow(2,bit-1)) + end + elseif value == "0" then + if mesecon:get_bit(binary,bit) then + return dec2bin(tonumber(binary,2)-math.pow(2,bit-1)) + end + end + return binary + +end + +function mesecon:invertRule(r) + return {x = -r.x, y = -r.y, z = -r.z} +end function mesecon:addPosRule(p, r) return {x = p.x + r.x, y = p.y + r.y, z = p.z + r.z} |