2012-12-15 18:45:51 +01:00
-- Internal.lua - The core of mesecons
--
-- For more practical developer resources see mesecons.tk
--
-- Function overview
-- mesecon:get_effector(nodename) --> Returns the mesecons.effector -specifictation in the nodedef by the nodename
-- mesecon:get_receptor(nodename) --> Returns the mesecons.receptor -specifictation in the nodedef by the nodename
-- mesecon:get_conductor(nodename) --> Returns the mesecons.conductor-specifictation in the nodedef by the nodename
-- mesecon:get_any_inputrules (node) --> Returns the rules of a node if it is a conductor or an effector
-- mesecon:get_any_outputrules (node) --> Returns the rules of a node if it is a conductor or a receptor
-- RECEPTORS
-- mesecon:is_receptor(nodename) --> Returns true if nodename is a receptor
-- mesecon:is_receptor_on(nodename) --> Returns true if nodename is an receptor with state = mesecon.state.on
-- mesecon:is_receptor_off(nodename) --> Returns true if nodename is an receptor with state = mesecon.state.off
-- mesecon:receptor_get_rules(node) --> Returns the rules of the receptor (mesecon.rules.default if none specified)
-- EFFECTORS
-- mesecon:is_effector(nodename) --> Returns true if nodename is an effector
-- mesecon:is_effector_on(nodename) --> Returns true if nodename is an effector with nodedef.mesecons.effector.action_off
-- mesecon:is_effector_off(nodename) --> Returns true if nodename is an effector with nodedef.mesecons.effector.action_on
-- mesecon:effector_get_rules(node) --> Returns the input rules of the effector (mesecon.rules.default if none specified)
-- SIGNALS
-- mesecon:activate(pos, node) --> Activates the effector node at the specific pos (calls nodedef.mesecons.effector.action_on)
-- mesecon:deactivate(pos, node) --> Deactivates the effector node at the specific pos (calls nodedef.mesecons.effector.action_off)
2013-01-19 22:18:28 +01:00
-- mesecon:changesignal(pos, node, rulename, newstate) --> Changes the effector node at the specific pos (calls nodedef.mesecons.effector.action_change)
2012-12-15 18:45:51 +01:00
-- RULES
-- mesecon:add_rules(name, rules) | deprecated? --> Saves rules table by name
-- mesecon:get_rules(name, rules) | deprecated? --> Loads rules table with name
-- CONDUCTORS
-- mesecon:is_conductor(nodename) --> Returns true if nodename is a conductor
2014-01-04 14:15:41 +01:00
-- mesecon:is_conductor_on(node) --> Returns true if node is a conductor with state = mesecon.state.on
-- mesecon:is_conductor_off(node) --> Returns true if node is a conductor with state = mesecon.state.off
-- mesecon:get_conductor_on(node_off) --> Returns the onstate nodename of the conductor
-- mesecon:get_conductor_off(node_on) --> Returns the offstate nodename of the conductor
2012-12-15 18:45:51 +01:00
-- mesecon:conductor_get_rules(node) --> Returns the input+output rules of a conductor (mesecon.rules.default if none specified)
-- HIGH-LEVEL Internals
-- mesecon:is_power_on(pos) --> Returns true if pos emits power in any way
-- mesecon:is_power_off(pos) --> Returns true if pos does not emit power in any way
2012-12-19 17:34:05 +01:00
-- mesecon:turnon(pos, rulename) --> Returns true whatever there is at pos. Calls itself for connected nodes (if pos is a conductor) --> recursive, the rulename is the name of the input rule that caused calling turnon
-- mesecon:turnoff(pos, rulename) --> Turns off whatever there is at pos. Calls itself for connected nodes (if pos is a conductor) --> recursive, the rulename is the name of the input rule that caused calling turnoff
2012-12-15 18:45:51 +01:00
-- mesecon:connected_to_receptor(pos) --> Returns true if pos is connected to a receptor directly or via conductors; calls itself if pos is a conductor --> recursive
-- mesecon:rules_link(output, input, dug_outputrules) --> Returns true if outputposition + outputrules = inputposition and inputposition + inputrules = outputposition (if the two positions connect)
-- mesecon:rules_link_anydir(outp., inp., d_outpr.) --> Same as rules mesecon:rules_link but also returns true if output and input are swapped
-- mesecon:is_powered(pos) --> Returns true if pos is powered by a receptor or a conductor
-- RULES ROTATION helpsers
-- mesecon:rotate_rules_right(rules)
-- mesecon:rotate_rules_left(rules)
-- mesecon:rotate_rules_up(rules)
-- mesecon:rotate_rules_down(rules)
-- These functions return rules that have been rotated in the specific direction
-- General
function mesecon : get_effector ( nodename )
if minetest.registered_nodes [ nodename ]
and minetest.registered_nodes [ nodename ] . mesecons
and minetest.registered_nodes [ nodename ] . mesecons.effector then
return minetest.registered_nodes [ nodename ] . mesecons.effector
end
end
2012-08-13 11:58:04 +02:00
2012-12-15 18:45:51 +01:00
function mesecon : get_receptor ( nodename )
2012-12-08 19:02:34 +01:00
if minetest.registered_nodes [ nodename ]
2012-12-08 17:50:25 +01:00
and minetest.registered_nodes [ nodename ] . mesecons
2012-12-15 18:45:51 +01:00
and minetest.registered_nodes [ nodename ] . mesecons.receptor then
return minetest.registered_nodes [ nodename ] . mesecons.receptor
2012-12-08 14:14:04 +01:00
end
2012-12-15 18:45:51 +01:00
end
function mesecon : get_conductor ( nodename )
if minetest.registered_nodes [ nodename ]
and minetest.registered_nodes [ nodename ] . mesecons
and minetest.registered_nodes [ nodename ] . mesecons.conductor then
return minetest.registered_nodes [ nodename ] . mesecons.conductor
end
end
function mesecon : get_any_outputrules ( node )
if mesecon : is_conductor ( node.name ) then
return mesecon : conductor_get_rules ( node )
elseif mesecon : is_receptor ( node.name ) then
return mesecon : receptor_get_rules ( node )
2012-08-13 11:58:04 +02:00
end
return false
end
2012-12-15 18:45:51 +01:00
function mesecon : get_any_inputrules ( node )
if mesecon : is_conductor ( node.name ) then
return mesecon : conductor_get_rules ( node )
elseif mesecon : is_effector ( node.name ) then
return mesecon : effector_get_rules ( node )
end
return false
end
-- Receptors
-- Nodes that can power mesecons
function mesecon : is_receptor_on ( nodename )
local receptor = mesecon : get_receptor ( nodename )
if receptor and receptor.state == mesecon.state . on then
2012-12-08 14:14:04 +01:00
return true
end
2012-12-15 18:45:51 +01:00
return false
end
function mesecon : is_receptor_off ( nodename )
local receptor = mesecon : get_receptor ( nodename )
if receptor and receptor.state == mesecon.state . off then
return true
end
return false
end
function mesecon : is_receptor ( nodename )
local receptor = mesecon : get_receptor ( nodename )
if receptor then
return true
2012-08-13 11:58:04 +02:00
end
return false
end
function mesecon : receptor_get_rules ( node )
2012-12-15 18:45:51 +01:00
local receptor = mesecon : get_receptor ( node.name )
if receptor then
local rules = receptor.rules
2012-12-08 21:56:09 +01:00
if type ( rules ) == ' function ' then
2012-12-08 14:14:04 +01:00
return rules ( node )
2012-12-08 21:56:09 +01:00
elseif rules then
2012-12-08 14:14:04 +01:00
return rules
end
end
2012-12-21 16:22:25 +01:00
2012-12-08 21:56:09 +01:00
return mesecon.rules . default
2012-08-13 11:58:04 +02:00
end
2012-08-13 20:17:45 +02:00
-- Effectors
2012-12-08 21:56:09 +01:00
-- Nodes that can be powered by mesecons
2012-08-13 20:17:45 +02:00
function mesecon : is_effector_on ( nodename )
2012-12-15 18:45:51 +01:00
local effector = mesecon : get_effector ( nodename )
if effector and effector.action_off then
2012-12-08 14:14:04 +01:00
return true
end
2012-08-13 20:17:45 +02:00
return false
end
function mesecon : is_effector_off ( nodename )
2012-12-15 18:45:51 +01:00
local effector = mesecon : get_effector ( nodename )
if effector and effector.action_on then
2012-12-08 14:14:04 +01:00
return true
end
2012-08-13 20:17:45 +02:00
return false
end
function mesecon : is_effector ( nodename )
2012-12-15 18:45:51 +01:00
local effector = mesecon : get_effector ( nodename )
if effector then
2012-12-08 14:14:04 +01:00
return true
end
2012-12-15 18:45:51 +01:00
return false
2012-08-13 20:17:45 +02:00
end
2012-12-15 18:45:51 +01:00
function mesecon : effector_get_rules ( node )
local effector = mesecon : get_effector ( node.name )
if effector then
local rules = effector.rules
2012-12-08 21:56:09 +01:00
if type ( rules ) == ' function ' then
2012-12-08 14:14:04 +01:00
return rules ( node )
2012-12-08 21:56:09 +01:00
elseif rules then
2012-12-08 14:14:04 +01:00
return rules
end
end
2012-12-08 21:56:09 +01:00
return mesecon.rules . default
2012-08-13 16:49:14 +02:00
end
2012-08-13 11:58:04 +02:00
--Signals
2012-12-19 17:34:05 +01:00
function mesecon : activate ( pos , node , rulename )
2013-06-05 06:40:53 +02:00
if MESECONS_GLOBALSTEP then
if rulename == nil then
for _ , rule in ipairs ( mesecon : effector_get_rules ( node ) ) do
mesecon : activate ( pos , node , rule )
end
return
end
add_action ( pos , " on " , rulename )
else
local effector = mesecon : get_effector ( node.name )
if effector and effector.action_on then
effector.action_on ( pos , node , rulename )
end
2012-09-05 23:52:09 +02:00
end
2012-08-13 11:58:04 +02:00
end
2012-12-19 17:34:05 +01:00
function mesecon : deactivate ( pos , node , rulename )
2013-06-05 06:40:53 +02:00
if MESECONS_GLOBALSTEP then
if rulename == nil then
for _ , rule in ipairs ( mesecon : effector_get_rules ( node ) ) do
mesecon : deactivate ( pos , node , rule )
end
return
end
add_action ( pos , " off " , rulename )
else
local effector = mesecon : get_effector ( node.name )
if effector and effector.action_off then
effector.action_off ( pos , node , rulename )
end
2012-09-05 23:52:09 +02:00
end
2012-08-13 11:58:04 +02:00
end
2013-01-19 22:18:28 +01:00
function mesecon : changesignal ( pos , node , rulename , newstate )
2013-06-05 06:40:53 +02:00
newstate = newstate or " on "
--rulename = rulename or mesecon.rules.default
if MESECONS_GLOBALSTEP then
if rulename == nil then
for _ , rule in ipairs ( mesecon : effector_get_rules ( node ) ) do
mesecon : changesignal ( pos , node , rule , newstate )
end
return
end
add_action ( pos , " c " .. newstate , rulename )
else
local effector = mesecon : get_effector ( node.name )
if effector and effector.action_change then
effector.action_change ( pos , node , rulename , newstate )
end
end
end
function execute_actions ( dtime )
local nactions = mesecon.to_update
mesecon.to_update = { }
for _ , i in ipairs ( nactions ) do
2013-11-30 22:13:00 -05:00
node = minetest.get_node ( i.pos )
2013-06-05 06:40:53 +02:00
if node.name == " ignore " then
add_action ( i.pos , i.action , i.rname )
else
effector = mesecon : get_effector ( node.name )
if i.action == " on " then
if effector and effector.action_on then
effector.action_on ( i.pos , node , i.rname )
end
elseif i.action == " off " then
if effector and effector.action_off then
effector.action_off ( i.pos , node , i.rname )
end
elseif i.action == " con " then
if effector and effector.action_change then
effector.action_change ( i.pos , node , i.rname , " on " )
end
elseif i.action == " coff " then
if effector and effector.action_change then
effector.action_change ( i.pos , node , i.rname , " off " )
end
end
end
end
local nactions = mesecon.r_to_update
mesecon.r_to_update = { }
for _ , i in ipairs ( nactions ) do
if i.action == " on " then
mesecon : receptor_on_i ( i.pos , i.rules )
else
mesecon : receptor_off_i ( i.pos , i.rules )
end
end
end
minetest.register_globalstep ( execute_actions )
function add_action ( pos , action , rname )
for _ , i in ipairs ( mesecon.to_update ) do
if i.pos . x == pos.x and i.pos . y == pos.y and i.pos . z == pos.z and i.rname . x == rname.x and i.rname . y == rname.y and i.rname . z == rname.z then
if ( i.action == " on " and action == " on " ) or ( i.action == " off " and action == " off " ) then
--nothing
elseif i.action == " coff " and action == " on " then i.action = " on "
elseif i.action == " con " and action == " off " then i.action = " off "
else
if action == " on " or action == " con " then i.action = " con " end
if action == " off " or action == " coff " then i.action = " coff " end
end
break
end
2012-09-05 23:52:09 +02:00
end
2013-06-05 06:40:53 +02:00
mesecon.to_update [ # mesecon.to_update + 1 ] = { pos = pos , action = action , rname = rname }
2012-08-13 11:58:04 +02:00
end
--Rules
function mesecon : add_rules ( name , rules )
2012-12-10 19:46:24 +01:00
mesecon.rules [ name ] = rules
2012-08-13 11:58:04 +02:00
end
function mesecon : get_rules ( name )
2012-12-10 19:46:24 +01:00
return mesecon.rules [ name ]
2012-08-13 11:58:04 +02:00
end
2012-12-08 21:56:09 +01:00
-- Conductors
2012-08-13 11:58:04 +02:00
2014-01-04 14:15:41 +01:00
function mesecon : is_conductor_on ( node , rulename )
local conductor = mesecon : get_conductor ( node.name )
2013-06-19 19:38:34 -07:00
if conductor then
if conductor.state then
return conductor.state == mesecon.state . on
end
if conductor.states then
if not rulename then
2014-01-04 14:15:41 +01:00
return mesecon : getstate ( node.name , conductor.states ) ~= 1
2013-06-19 19:38:34 -07:00
end
2014-01-04 14:15:41 +01:00
local bit = mesecon : rule2bit ( rulename , mesecon : conductor_get_rules ( node ) )
local binstate = mesecon : getbinstate ( node.name , conductor.states )
2013-06-19 19:38:34 -07:00
return mesecon : get_bit ( binstate , bit )
end
2012-08-13 11:58:04 +02:00
end
return false
end
2014-01-04 14:15:41 +01:00
function mesecon : is_conductor_off ( node , rulename )
local conductor = mesecon : get_conductor ( node.name )
2013-06-19 19:38:34 -07:00
if conductor then
if conductor.state then
return conductor.state == mesecon.state . off
end
if conductor.states then
if not rulename then
2014-01-04 14:15:41 +01:00
return mesecon : getstate ( node.name , conductor.states ) == 1
2013-06-19 19:38:34 -07:00
end
2014-01-04 14:15:41 +01:00
local bit = mesecon : rule2bit ( rulename , mesecon : conductor_get_rules ( node ) )
local binstate = mesecon : getbinstate ( node.name , conductor.states )
2013-06-19 19:38:34 -07:00
return not mesecon : get_bit ( binstate , bit )
end
2012-08-13 11:58:04 +02:00
end
return false
end
2012-12-15 18:45:51 +01:00
function mesecon : is_conductor ( nodename )
local conductor = mesecon : get_conductor ( nodename )
if conductor then
2012-12-08 14:14:04 +01:00
return true
end
2012-08-13 11:58:04 +02:00
return false
end
2014-01-04 14:15:41 +01:00
function mesecon : get_conductor_on ( node_off , rulename )
local conductor = mesecon : get_conductor ( node_off.name )
2012-12-15 18:45:51 +01:00
if conductor then
2013-06-19 19:38:34 -07:00
if conductor.onstate then
return conductor.onstate
end
if conductor.states then
2014-01-04 14:15:41 +01:00
local bit = mesecon : rule2bit ( rulename , mesecon : conductor_get_rules ( node_off ) )
local binstate = mesecon : getbinstate ( node_off.name , conductor.states )
2013-06-19 19:38:34 -07:00
binstate = mesecon : set_bit ( binstate , bit , " 1 " )
return conductor.states [ tonumber ( binstate , 2 ) + 1 ]
end
2012-08-13 11:58:04 +02:00
end
2013-06-19 19:38:34 -07:00
return offstate
2012-08-13 11:58:04 +02:00
end
2014-01-04 14:15:41 +01:00
function mesecon : get_conductor_off ( node_on , rulename )
local conductor = mesecon : get_conductor ( node_on.name )
2012-12-15 18:45:51 +01:00
if conductor then
2013-06-19 19:38:34 -07:00
if conductor.offstate then
return conductor.offstate
end
if conductor.states then
2014-01-04 14:15:41 +01:00
local bit = mesecon : rule2bit ( rulename , mesecon : conductor_get_rules ( node_on ) )
local binstate = mesecon : getbinstate ( node_on.name , conductor.states )
2013-06-19 19:38:34 -07:00
binstate = mesecon : set_bit ( binstate , bit , " 0 " )
return conductor.states [ tonumber ( binstate , 2 ) + 1 ]
end
2012-12-15 18:45:51 +01:00
end
2013-06-19 19:38:34 -07:00
return onstate
2012-08-16 21:24:06 +02:00
end
function mesecon : conductor_get_rules ( node )
2012-12-15 18:45:51 +01:00
local conductor = mesecon : get_conductor ( node.name )
if conductor then
local rules = conductor.rules
2012-12-08 21:56:09 +01:00
if type ( rules ) == ' function ' then
2012-12-08 14:14:04 +01:00
return rules ( node )
2012-12-08 21:56:09 +01:00
elseif rules then
2012-12-08 14:14:04 +01:00
return rules
end
end
2012-12-08 21:56:09 +01:00
return mesecon.rules . default
2012-08-16 21:24:06 +02:00
end
2012-12-15 18:45:51 +01:00
-- some more general high-level stuff
2013-06-19 19:38:34 -07:00
function mesecon : is_power_on ( pos , rulename )
2013-11-30 22:13:00 -05:00
local node = minetest.get_node ( pos )
2014-01-04 14:15:41 +01:00
if mesecon : is_conductor_on ( node , rulename ) or mesecon : is_receptor_on ( node.name ) then
2012-08-13 11:58:04 +02:00
return true
end
return false
end
2013-06-19 19:38:34 -07:00
function mesecon : is_power_off ( pos , rulename )
2013-11-30 22:13:00 -05:00
local node = minetest.get_node ( pos )
2014-01-04 14:15:41 +01:00
if mesecon : is_conductor_off ( node , rulename ) or mesecon : is_receptor_off ( node.name ) then
2012-08-13 20:17:45 +02:00
return true
2012-08-13 11:58:04 +02:00
end
2012-08-13 20:17:45 +02:00
return false
2012-08-13 11:58:04 +02:00
end
2012-12-19 17:34:05 +01:00
function mesecon : turnon ( pos , rulename )
2013-11-30 22:13:00 -05:00
local node = minetest.get_node ( pos )
2014-01-04 15:52:52 +01:00
2014-01-04 14:15:41 +01:00
if mesecon : is_conductor_off ( node , rulename ) then
2012-08-16 21:24:06 +02:00
local rules = mesecon : conductor_get_rules ( node )
2012-08-13 11:58:04 +02:00
2013-06-19 19:38:34 -07:00
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
2014-01-04 14:15:41 +01:00
minetest.add_node ( pos , { name = mesecon : get_conductor_on ( node , rulename ) , param2 = node.param2 } )
2013-06-19 19:38:34 -07:00
for _ , rule in ipairs ( mesecon : rule2meta ( rulename , rules ) ) do
2012-12-08 21:56:09 +01:00
local np = mesecon : addPosRule ( pos , rule )
2014-01-04 15:52:52 +01:00
local link , rulename = mesecon : rules_link_rule ( pos , rule )
2012-08-16 21:24:06 +02:00
2012-12-19 17:34:05 +01:00
if link then
mesecon : turnon ( np , rulename )
2012-08-16 21:24:06 +02:00
end
2012-08-13 11:58:04 +02:00
end
2012-12-16 11:58:43 +01:00
elseif mesecon : is_effector ( node.name ) then
2013-01-19 22:18:28 +01:00
mesecon : changesignal ( pos , node , rulename , mesecon.state . on )
2012-12-08 17:50:25 +01:00
if mesecon : is_effector_off ( node.name ) then
2012-12-19 17:34:05 +01:00
mesecon : activate ( pos , node , rulename )
2012-12-08 17:50:25 +01:00
end
2012-08-13 11:58:04 +02:00
end
end
2012-12-19 17:34:05 +01:00
function mesecon : turnoff ( pos , rulename )
2013-11-30 22:13:00 -05:00
local node = minetest.get_node ( pos )
2012-08-13 11:58:04 +02:00
2014-01-04 14:15:41 +01:00
if mesecon : is_conductor_on ( node , rulename ) then
2012-12-08 17:50:25 +01:00
local rules = mesecon : conductor_get_rules ( node )
2013-06-19 19:38:34 -07:00
--[[
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
--]]
2014-01-04 14:15:41 +01:00
minetest.add_node ( pos , { name = mesecon : get_conductor_off ( node , rulename ) , param2 = node.param2 } )
2012-08-13 11:58:04 +02:00
2013-06-19 19:38:34 -07:00
for _ , rule in ipairs ( mesecon : rule2meta ( rulename , rules ) ) do
2012-12-08 21:56:09 +01:00
local np = mesecon : addPosRule ( pos , rule )
2014-01-04 15:52:52 +01:00
local link , rulename = mesecon : rules_link_rule ( pos , rule )
2012-08-16 21:24:06 +02:00
2012-12-19 17:34:05 +01:00
if link then
mesecon : turnoff ( np , rulename )
2012-08-16 21:24:06 +02:00
end
2012-08-13 11:58:04 +02:00
end
2012-12-16 11:58:43 +01:00
elseif mesecon : is_effector ( node.name ) then
2013-01-19 22:18:28 +01:00
mesecon : changesignal ( pos , node , rulename , mesecon.state . off )
2012-12-08 17:50:25 +01:00
if mesecon : is_effector_on ( node.name )
and not mesecon : is_powered ( pos ) then
2012-12-19 17:34:05 +01:00
mesecon : deactivate ( pos , node , rulename )
2012-12-08 17:50:25 +01:00
end
2012-08-13 11:58:04 +02:00
end
end
2013-06-19 19:38:34 -07:00
function mesecon : connected_to_receptor ( pos , rulename )
2013-11-30 22:13:00 -05:00
local node = minetest.get_node ( pos )
2012-12-27 09:28:04 +01:00
-- Check if conductors around are connected
local rules = mesecon : get_any_inputrules ( node )
if not rules then return false end
2013-06-19 19:38:34 -07:00
for _ , rule in ipairs ( mesecon : rule2meta ( rulename , rules ) ) do
2012-12-27 09:28:04 +01:00
local np = mesecon : addPosRule ( pos , rule )
if mesecon : rules_link ( np , pos ) then
2013-06-19 19:38:34 -07:00
if mesecon : find_receptor_on ( np , { } , mesecon : invertRule ( rule ) ) then
2012-12-27 09:28:04 +01:00
return true
end
end
end
return false
end
2012-12-15 18:45:51 +01:00
2013-06-19 19:38:34 -07:00
function mesecon : find_receptor_on ( pos , checked , rulename )
2013-11-30 22:13:00 -05:00
local node = minetest.get_node ( pos )
2012-08-16 21:24:06 +02:00
2012-12-27 09:28:04 +01:00
if mesecon : is_receptor_on ( node.name ) then
2014-01-04 15:52:52 +01:00
-- add current position to checked
table.insert ( checked , { x = pos.x , y = pos.y , z = pos.z } )
2012-12-27 09:28:04 +01:00
return true
end
2012-12-15 18:45:51 +01:00
if mesecon : is_conductor ( node.name ) then
local rules = mesecon : conductor_get_rules ( node )
2014-01-04 15:52:52 +01:00
local metaindex = mesecon : rule2metaindex ( rulename , rules )
-- find out if node has already been checked (to prevent from endless loop)
for _ , cp in ipairs ( checked ) do
if mesecon : cmpPos ( cp , pos ) and cp.metaindex == metaindex then
return false , checked
end
end
-- add current position to checked
table.insert ( checked , { x = pos.x , y = pos.y , z = pos.z , metaindex = metaindex } )
2013-06-19 19:38:34 -07:00
for _ , rule in ipairs ( mesecon : rule2meta ( rulename , rules ) ) do
2012-12-15 18:45:51 +01:00
local np = mesecon : addPosRule ( pos , rule )
if mesecon : rules_link ( np , pos ) then
2013-06-19 19:38:34 -07:00
if mesecon : find_receptor_on ( np , checked , mesecon : invertRule ( rule ) ) then
2012-12-15 18:45:51 +01:00
return true
end
2012-08-13 11:58:04 +02:00
end
end
2014-01-04 15:52:52 +01:00
else
-- 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
return false , checked
end
end
table.insert ( checked , { x = pos.x , y = pos.y , z = pos.z } )
2012-08-13 11:58:04 +02:00
end
2012-12-15 18:45:51 +01:00
2012-12-27 09:28:04 +01:00
return false
2012-08-13 11:58:04 +02:00
end
2012-12-19 17:34:05 +01:00
function mesecon : rules_link ( output , input , dug_outputrules ) --output/input are positions (outputrules optional, used if node has been dug), second return value: the name of the affected input rule
2013-11-30 22:13:00 -05:00
local outputnode = minetest.get_node ( output )
local inputnode = minetest.get_node ( input )
2012-12-15 18:45:51 +01:00
local outputrules = dug_outputrules or mesecon : get_any_outputrules ( outputnode )
local inputrules = mesecon : get_any_inputrules ( inputnode )
if not outputrules or not inputrules then
return
2012-08-16 21:24:06 +02:00
end
2013-06-19 19:38:34 -07:00
for _ , outputrule in ipairs ( mesecon : flattenrules ( outputrules ) ) do
2012-12-15 18:45:51 +01:00
-- Check if output sends to input
if mesecon : cmpPos ( mesecon : addPosRule ( output , outputrule ) , input ) then
2013-06-19 19:38:34 -07:00
for _ , inputrule in ipairs ( mesecon : flattenrules ( inputrules ) ) do
2012-12-15 18:45:51 +01:00
-- Check if input accepts from output
if mesecon : cmpPos ( mesecon : addPosRule ( input , inputrule ) , output ) then
2014-01-04 15:52:52 +01:00
if inputrule.sx == nil or outputrule.sx == nil or mesecon : cmpSpecial ( inputrule , outputrule ) then
2014-01-04 14:15:41 +01:00
return true , inputrule
end
2012-08-13 11:58:04 +02:00
end
end
end
end
return false
end
2014-01-04 15:52:52 +01:00
function mesecon : rules_link_rule ( output , rule ) --output/input are positions (outputrules optional, used if node has been dug), second return value: the name of the affected input rule
local input = mesecon : addPosRule ( output , rule )
local inputnode = minetest.get_node ( input )
local inputrules = mesecon : get_any_inputrules ( inputnode )
if not inputrules then
return
end
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
return true , inputrule
end
end
end
return false
end
2012-12-15 18:45:51 +01:00
function mesecon : rules_link_anydir ( pos1 , pos2 )
2012-08-16 21:24:06 +02:00
return mesecon : rules_link ( pos1 , pos2 ) or mesecon : rules_link ( pos2 , pos1 )
end
2013-06-19 19:38:34 -07:00
function mesecon : is_powered ( pos , rule )
2013-11-30 22:13:00 -05:00
local node = minetest.get_node ( pos )
2012-12-15 18:45:51 +01:00
local rules = mesecon : get_any_inputrules ( node )
if not rules then return false end
2012-08-16 21:24:06 +02:00
2013-06-19 19:38:34 -07:00
if not rule then
for _ , rule in ipairs ( mesecon : flattenrules ( rules ) ) do
local np = mesecon : addPosRule ( pos , rule )
2013-11-30 22:13:00 -05:00
local nn = minetest.get_node ( np )
2013-06-19 19:38:34 -07:00
2014-01-04 14:15:41 +01:00
if ( mesecon : is_conductor_on ( nn , mesecon : invertRule ( rule ) ) or mesecon : is_receptor_on ( nn.name ) )
2013-06-19 19:38:34 -07:00
and mesecon : rules_link ( np , pos ) then
return true
end
end
else
2012-12-15 18:45:51 +01:00
local np = mesecon : addPosRule ( pos , rule )
2013-11-30 22:13:00 -05:00
local nn = minetest.get_node ( np )
2012-08-13 11:58:04 +02:00
2014-01-04 14:15:41 +01:00
if ( mesecon : is_conductor_on ( nn , mesecon : invertRule ( rule ) ) or mesecon : is_receptor_on ( nn.name ) )
2012-12-15 18:45:51 +01:00
and mesecon : rules_link ( np , pos ) then
2012-08-13 11:58:04 +02:00
return true
end
end
2012-08-16 21:24:06 +02:00
return false
end
2012-08-13 20:17:45 +02:00
--Rules rotation Functions:
function mesecon : rotate_rules_right ( rules )
2012-12-28 07:33:16 +01:00
local nr = { }
2012-09-05 23:52:09 +02:00
for i , rule in ipairs ( rules ) do
2014-01-04 14:15:41 +01:00
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
2012-08-13 20:17:45 +02:00
end
return nr
end
function mesecon : rotate_rules_left ( rules )
2012-12-28 07:33:16 +01:00
local nr = { }
2012-09-05 23:52:09 +02:00
for i , rule in ipairs ( rules ) do
2014-01-04 14:15:41 +01:00
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
2012-08-13 20:17:45 +02:00
end
return nr
end
function mesecon : rotate_rules_down ( rules )
2012-12-28 07:33:16 +01:00
local nr = { }
2012-09-05 23:52:09 +02:00
for i , rule in ipairs ( rules ) do
2014-01-04 14:15:41 +01:00
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
2012-08-13 20:17:45 +02:00
end
return nr
end
function mesecon : rotate_rules_up ( rules )
2012-12-28 07:33:16 +01:00
local nr = { }
2012-09-05 23:52:09 +02:00
for i , rule in ipairs ( rules ) do
2014-01-04 14:15:41 +01:00
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
2012-08-13 20:17:45 +02:00
end
return nr
end