summaryrefslogtreecommitdiff
path: root/mesecons
diff options
context:
space:
mode:
authorkhonkhortisan <khonkhortisan@gmail.com>2013-08-27 22:22:30 -0700
committerkhonkhortisan <khonkhortisan@gmail.com>2013-08-27 22:22:30 -0700
commit913e355a718c41551fe0e29ff1356e11d669ac73 (patch)
treea1ae8ead16928c75e5d27c7b1191e3bb033b24a5 /mesecons
parent96011bc71816b5e9eb2cc6c86f009198dfb1146c (diff)
parent885899cbaf6ccb2d22a3495131204ea0d01131ed (diff)
downloadmesecons-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.lua6
-rw-r--r--mesecons/internal.lua132
-rw-r--r--mesecons/services.lua2
-rw-r--r--mesecons/util.lua137
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}