forked from minetest-mods/mesecons
		
	Merge pull request #112 from khonkhortisan/multi_rules
Multi rules Merged for near-future textures to be merged cleanly.
This commit is contained in:
		@@ -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)
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
 
 | 
			
		||||
@@ -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)
 | 
			
		||||
 
 | 
			
		||||
@@ -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}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user