2012-12-15 18:45:51 +01:00
-- Internal.lua - The core of mesecons
--
2014-11-23 09:43:24 +01:00
-- For more practical developer resources see http://mesecons.net/developers.php
2012-12-15 18:45:51 +01:00
--
-- Function overview
2014-11-23 09:43:24 +01:00
-- 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
2012-12-15 18:45:51 +01:00
-- RECEPTORS
2014-11-23 09:43:24 +01:00
-- 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)
2012-12-15 18:45:51 +01:00
-- EFFECTORS
2014-11-23 09:43:24 +01:00
-- 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)
2012-12-15 18:45:51 +01:00
-- SIGNALS
2014-11-23 09:43:24 +01:00
-- mesecon.activate(pos, node, depth) --> Activates the effector node at the specific pos (calls nodedef.mesecons.effector.action_on), higher depths are executed later
-- mesecon.deactivate(pos, node, depth) --> Deactivates the effector node at the specific pos (calls nodedef.mesecons.effector.action_off), higher depths are executed later
2014-11-22 15:42:22 +01:00
-- mesecon.changesignal(pos, node, rulename, newstate, depth) --> Changes the effector node at the specific pos (calls nodedef.mesecons.effector.action_change), higher depths are executed later
2012-12-15 18:45:51 +01:00
-- CONDUCTORS
2014-11-23 09:43:24 +01:00
-- mesecon.is_conductor(nodename) --> Returns true if nodename is a conductor
-- 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
-- mesecon.conductor_get_rules(node) --> Returns the input+output rules of a conductor (mesecon.rules.default if none specified)
2012-12-15 18:45:51 +01:00
-- HIGH-LEVEL Internals
2014-11-23 09:43:24 +01:00
-- 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
-- mesecon.turnon(pos, link) --> link is the input rule that caused calling turnon, turns on every connected node, iterative
-- mesecon.turnoff(pos, link) --> link is the input rule that caused calling turnoff, turns off every connected node, iterative
-- mesecon.connected_to_receptor(pos, link) --> Returns true if pos is connected to a receptor directly or via conductors, iterative
-- 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 helpers
2014-11-22 15:42:22 +01:00
-- mesecon.rotate_rules_right(rules)
-- mesecon.rotate_rules_left(rules)
-- mesecon.rotate_rules_up(rules)
-- mesecon.rotate_rules_down(rules)
2012-12-15 18:45:51 +01:00
-- These functions return rules that have been rotated in the specific direction
-- General
2014-11-22 15:42:22 +01:00
function mesecon . get_effector ( nodename )
2012-12-15 18:45:51 +01:00
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
2014-11-22 15:42:22 +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
2014-11-22 15:42:22 +01:00
function mesecon . get_conductor ( nodename )
2012-12-15 18:45:51 +01:00
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
2014-11-22 15:42:22 +01:00
function mesecon . get_any_outputrules ( node )
2016-02-19 12:11:38 +01:00
if not node then return nil end
2014-11-22 15:42:22 +01:00
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
end
2014-11-22 15:42:22 +01:00
function mesecon . get_any_inputrules ( node )
2016-02-19 12:11:38 +01:00
if not node then return nil end
2014-11-22 15:42:22 +01:00
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 )
2012-12-15 18:45:51 +01:00
end
2014-11-23 09:43:24 +01:00
end
function mesecon . get_any_rules ( node )
return mesecon.mergetable ( mesecon.get_any_inputrules ( node ) or { } ,
mesecon.get_any_outputrules ( node ) or { } )
2012-12-15 18:45:51 +01:00
end
-- Receptors
-- Nodes that can power mesecons
2014-11-22 15:42:22 +01:00
function mesecon . is_receptor_on ( nodename )
local receptor = mesecon.get_receptor ( nodename )
2012-12-15 18:45:51 +01:00
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
2014-11-22 15:42:22 +01:00
function mesecon . is_receptor_off ( nodename )
local receptor = mesecon.get_receptor ( nodename )
2012-12-15 18:45:51 +01:00
if receptor and receptor.state == mesecon.state . off then
return true
end
return false
end
2014-11-22 15:42:22 +01:00
function mesecon . is_receptor ( nodename )
local receptor = mesecon.get_receptor ( nodename )
2012-12-15 18:45:51 +01:00
if receptor then
return true
2012-08-13 11:58:04 +02:00
end
return false
end
2014-11-22 15:42:22 +01:00
function mesecon . receptor_get_rules ( node )
local receptor = mesecon.get_receptor ( node.name )
2012-12-15 18:45:51 +01:00
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
2014-11-22 15:42:22 +01:00
function mesecon . is_effector_on ( nodename )
local effector = mesecon.get_effector ( nodename )
2012-12-15 18:45:51 +01:00
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
2014-11-22 15:42:22 +01:00
function mesecon . is_effector_off ( nodename )
local effector = mesecon.get_effector ( nodename )
2012-12-15 18:45:51 +01:00
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
2014-11-22 15:42:22 +01:00
function mesecon . is_effector ( nodename )
local effector = mesecon.get_effector ( nodename )
2012-12-15 18:45:51 +01:00
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
2014-11-22 15:42:22 +01:00
function mesecon . effector_get_rules ( node )
local effector = mesecon.get_effector ( node.name )
2012-12-15 18:45:51 +01:00
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
2014-01-10 22:29:18 +01:00
-- #######################
-- # Signals (effectors) #
-- #######################
-- Activation:
mesecon.queue : add_function ( " activate " , function ( pos , rulename )
2016-02-19 12:11:38 +01:00
local node = mesecon.get_node_force ( pos )
if not node then return end
2014-11-22 17:12:48 +01:00
local effector = mesecon.get_effector ( node.name )
2014-01-10 22:29:18 +01:00
if effector and effector.action_on then
effector.action_on ( pos , node , rulename )
end
end )
2012-08-13 11:58:04 +02:00
2014-11-22 15:42:22 +01:00
function mesecon . activate ( pos , node , rulename , depth )
2014-01-10 22:29:18 +01:00
if rulename == nil then
2014-11-22 15:42:22 +01:00
for _ , rule in ipairs ( mesecon.effector_get_rules ( node ) ) do
mesecon.activate ( pos , node , rule , depth + 1 )
2013-06-05 06:40:53 +02:00
end
2014-01-10 22:29:18 +01:00
return
2012-09-05 23:52:09 +02:00
end
2014-11-22 14:47:18 +01:00
mesecon.queue : add_action ( pos , " activate " , { rulename } , nil , rulename , 1 / depth )
2012-08-13 11:58:04 +02:00
end
2014-01-10 22:29:18 +01:00
-- Deactivation
mesecon.queue : add_function ( " deactivate " , function ( pos , rulename )
2016-02-19 12:11:38 +01:00
local node = mesecon.get_node_force ( pos )
if not node then return end
2014-11-23 09:43:24 +01:00
local effector = mesecon.get_effector ( node.name )
2014-01-10 22:29:18 +01:00
if effector and effector.action_off then
effector.action_off ( pos , node , rulename )
2012-09-05 23:52:09 +02:00
end
2014-01-10 22:29:18 +01:00
end )
2012-08-13 11:58:04 +02:00
2014-11-22 15:42:22 +01:00
function mesecon . deactivate ( pos , node , rulename , depth )
2014-01-10 22:29:18 +01:00
if rulename == nil then
2014-11-22 15:42:22 +01:00
for _ , rule in ipairs ( mesecon.effector_get_rules ( node ) ) do
mesecon.deactivate ( pos , node , rule , depth + 1 )
2013-06-05 06:40:53 +02:00
end
2014-01-10 22:29:18 +01:00
return
2013-06-05 06:40:53 +02:00
end
2014-11-22 14:47:18 +01:00
mesecon.queue : add_action ( pos , " deactivate " , { rulename } , nil , rulename , 1 / depth )
2013-06-05 06:40:53 +02:00
end
2014-01-10 22:29:18 +01:00
-- Change
mesecon.queue : add_function ( " change " , function ( pos , rulename , changetype )
2016-02-19 12:11:38 +01:00
local node = mesecon.get_node_force ( pos )
if not node then return end
2014-11-22 15:42:22 +01:00
local effector = mesecon.get_effector ( node.name )
2014-01-10 22:29:18 +01:00
if effector and effector.action_change then
effector.action_change ( pos , node , rulename , changetype )
2013-06-05 06:40:53 +02:00
end
2014-01-10 22:29:18 +01:00
end )
2013-06-05 06:40:53 +02:00
2014-11-22 15:42:22 +01:00
function mesecon . changesignal ( pos , node , rulename , newstate , depth )
2014-01-10 22:29:18 +01:00
if rulename == nil then
2014-11-22 15:42:22 +01:00
for _ , rule in ipairs ( mesecon.effector_get_rules ( node ) ) do
mesecon.changesignal ( pos , node , rule , newstate , depth + 1 )
2013-06-05 06:40:53 +02:00
end
2014-01-10 22:29:18 +01:00
return
2012-09-05 23:52:09 +02:00
end
2014-01-10 22:29:18 +01:00
2014-11-29 15:08:37 +01:00
-- 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 )
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-11-22 15:42:22 +01:00
function mesecon . is_conductor_on ( node , rulename )
2016-02-19 12:11:38 +01:00
if not node then return false end
2014-11-22 15:42:22 +01:00
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-11-22 15:42:22 +01:00
return mesecon.getstate ( node.name , conductor.states ) ~= 1
2013-06-19 19:38:34 -07:00
end
2014-11-22 15:42:22 +01:00
local bit = mesecon.rule2bit ( rulename , mesecon.conductor_get_rules ( node ) )
local binstate = mesecon.getbinstate ( node.name , conductor.states )
return mesecon.get_bit ( binstate , bit )
2013-06-19 19:38:34 -07:00
end
2012-08-13 11:58:04 +02:00
end
2016-02-19 12:11:38 +01:00
2012-08-13 11:58:04 +02:00
return false
end
2014-11-22 15:42:22 +01:00
function mesecon . is_conductor_off ( node , rulename )
2016-02-19 12:11:38 +01:00
if not node then return false end
2014-11-22 15:42:22 +01:00
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-11-22 15:42:22 +01:00
return mesecon.getstate ( node.name , conductor.states ) == 1
2013-06-19 19:38:34 -07:00
end
2014-11-22 15:42:22 +01:00
local bit = mesecon.rule2bit ( rulename , mesecon.conductor_get_rules ( node ) )
local binstate = mesecon.getbinstate ( node.name , conductor.states )
return not mesecon.get_bit ( binstate , bit )
2013-06-19 19:38:34 -07:00
end
2012-08-13 11:58:04 +02:00
end
2016-02-19 12:11:38 +01:00
2012-08-13 11:58:04 +02:00
return false
end
2014-11-22 15:42:22 +01:00
function mesecon . is_conductor ( nodename )
local conductor = mesecon.get_conductor ( nodename )
2012-12-15 18:45:51 +01:00
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-11-22 15:42:22 +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-11-22 15:42:22 +01:00
local bit = mesecon.rule2bit ( rulename , mesecon.conductor_get_rules ( node_off ) )
local binstate = mesecon.getbinstate ( node_off.name , conductor.states )
binstate = mesecon.set_bit ( binstate , bit , " 1 " )
2013-06-19 19:38:34 -07:00
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-11-22 15:42:22 +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-11-22 15:42:22 +01:00
local bit = mesecon.rule2bit ( rulename , mesecon.conductor_get_rules ( node_on ) )
local binstate = mesecon.getbinstate ( node_on.name , conductor.states )
binstate = mesecon.set_bit ( binstate , bit , " 0 " )
2013-06-19 19:38:34 -07:00
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
2014-11-22 15:42:22 +01:00
function mesecon . conductor_get_rules ( node )
local conductor = mesecon.get_conductor ( node.name )
2012-12-15 18:45:51 +01:00
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
2014-11-22 15:42:22 +01:00
function mesecon . is_power_on ( pos , rulename )
2016-02-19 12:11:38 +01:00
local node = mesecon.get_node_force ( pos )
2016-02-22 15:47:18 -08:00
if node and ( 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
2014-11-22 15:42:22 +01:00
function mesecon . is_power_off ( pos , rulename )
2016-02-19 12:11:38 +01:00
local node = mesecon.get_node_force ( pos )
2016-02-22 15:47:18 -08:00
if node and ( 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
2014-11-22 15:42:22 +01:00
function mesecon . turnon ( pos , link )
2014-11-22 14:47:18 +01:00
local frontiers = { { pos = pos , link = link } }
2013-06-19 19:38:34 -07:00
2014-11-22 14:47:18 +01:00
local depth = 1
while frontiers [ depth ] do
local f = frontiers [ depth ]
2016-02-19 12:11:38 +01:00
local node = mesecon.get_node_force ( f.pos )
2013-06-19 19:38:34 -07:00
2014-11-22 14:47:18 +01:00
-- area not loaded, postpone action
if not node then
mesecon.queue : add_action ( f.pos , " turnon " , { link } , nil , true )
2014-11-23 09:43:24 +01:00
elseif mesecon.is_conductor_off ( node , f.link ) then
2014-11-22 15:42:22 +01:00
local rules = mesecon.conductor_get_rules ( node )
2014-11-22 14:47:18 +01:00
2014-11-22 15:42:22 +01:00
minetest.swap_node ( f.pos , { name = mesecon.get_conductor_on ( node , f.link ) ,
2014-11-22 14:47:18 +01:00
param2 = node.param2 } )
-- call turnon on neighbors: normal rules
2014-11-22 15:42:22 +01:00
for _ , r in ipairs ( mesecon.rule2meta ( f.link , rules ) ) do
2016-02-14 20:55:50 +01:00
local np = vector.add ( f.pos , r )
2014-11-22 14:47:18 +01:00
-- area not loaded, postpone action
2016-02-19 12:11:38 +01:00
if not mesecon.get_node_force ( np ) then
2014-11-22 14:47:18 +01:00
mesecon.queue : add_action ( np , " turnon " , { rulename } ,
nil , true )
else
2014-11-22 15:42:22 +01:00
local links = mesecon.rules_link_rule_all ( f.pos , r )
2014-11-22 14:47:18 +01:00
for _ , l in ipairs ( links ) do
table.insert ( frontiers , { pos = np , link = l } )
end
2014-01-11 16:46:27 +01:00
end
2012-08-16 21:24:06 +02:00
end
2014-11-22 15:42:22 +01:00
elseif mesecon.is_effector ( node.name ) then
mesecon.changesignal ( f.pos , node , f.link , mesecon.state . on , depth )
if mesecon.is_effector_off ( node.name ) then
mesecon.activate ( f.pos , node , f.link , depth )
2014-11-22 14:47:18 +01:00
end
2012-08-13 11:58:04 +02:00
end
2014-11-22 14:47:18 +01:00
depth = depth + 1
2012-08-13 11:58:04 +02:00
end
end
2014-01-11 16:46:27 +01:00
mesecon.queue : add_function ( " turnon " , function ( pos , rulename , recdepth )
2014-11-22 15:42:22 +01:00
mesecon.turnon ( pos , rulename , recdepth )
2014-01-11 16:46:27 +01:00
end )
2014-11-22 15:42:22 +01:00
function mesecon . turnoff ( pos , link )
2014-11-22 14:47:18 +01:00
local frontiers = { { pos = pos , link = link } }
2012-08-13 11:58:04 +02:00
2014-11-22 14:47:18 +01:00
local depth = 1
while frontiers [ depth ] do
local f = frontiers [ depth ]
2016-02-19 12:11:38 +01:00
local node = mesecon.get_node_force ( f.pos )
2014-01-11 16:46:27 +01:00
2014-11-22 14:47:18 +01:00
-- area not loaded, postpone action
if not node then
mesecon.queue : add_action ( f.pos , " turnoff " , { link } , nil , true )
2014-11-23 09:43:24 +01:00
elseif mesecon.is_conductor_on ( node , f.link ) then
2014-11-22 15:42:22 +01:00
local rules = mesecon.conductor_get_rules ( node )
2014-11-22 14:47:18 +01:00
2014-11-22 15:42:22 +01:00
minetest.swap_node ( f.pos , { name = mesecon.get_conductor_off ( node , f.link ) ,
2014-11-22 14:47:18 +01:00
param2 = node.param2 } )
-- call turnoff on neighbors: normal rules
2014-11-22 15:42:22 +01:00
for _ , r in ipairs ( mesecon.rule2meta ( f.link , rules ) ) do
2016-02-14 20:55:50 +01:00
local np = vector.add ( f.pos , r )
2014-11-22 14:47:18 +01:00
-- area not loaded, postpone action
2016-02-19 12:11:38 +01:00
if not mesecon.get_node_force ( np ) then
2014-11-22 14:47:18 +01:00
mesecon.queue : add_action ( np , " turnoff " , { rulename } ,
nil , true )
else
2014-11-22 15:42:22 +01:00
local links = mesecon.rules_link_rule_all ( f.pos , r )
2014-11-22 14:47:18 +01:00
for _ , l in ipairs ( links ) do
table.insert ( frontiers , { pos = np , link = l } )
end
2014-01-11 16:46:27 +01:00
end
2012-08-16 21:24:06 +02:00
end
2014-11-22 15:42:22 +01:00
elseif mesecon.is_effector ( node.name ) then
mesecon.changesignal ( f.pos , node , f.link , mesecon.state . off , depth )
if mesecon.is_effector_on ( node.name ) and not mesecon.is_powered ( f.pos ) then
mesecon.deactivate ( f.pos , node , f.link , depth )
2014-11-22 14:47:18 +01:00
end
2012-08-13 11:58:04 +02:00
end
2014-11-22 14:47:18 +01:00
depth = depth + 1
2012-08-13 11:58:04 +02:00
end
end
2014-01-11 16:46:27 +01:00
mesecon.queue : add_function ( " turnoff " , function ( pos , rulename , recdepth )
2014-11-22 15:42:22 +01:00
mesecon.turnoff ( pos , rulename , recdepth )
2014-01-11 16:46:27 +01:00
end )
2012-08-13 11:58:04 +02:00
2014-11-22 17:12:48 +01:00
function mesecon . connected_to_receptor ( pos , link )
2016-02-19 12:11:38 +01:00
local node = mesecon.get_node_force ( pos )
if not node then return false end
2012-12-27 09:28:04 +01:00
-- Check if conductors around are connected
2014-11-22 15:42:22 +01:00
local rules = mesecon.get_any_inputrules ( node )
2012-12-27 09:28:04 +01:00
if not rules then return false end
2014-11-22 17:12:48 +01:00
for _ , rule in ipairs ( mesecon.rule2meta ( link , rules ) ) do
local links = mesecon.rules_link_rule_all_inverted ( pos , rule )
for _ , l in ipairs ( links ) do
2016-02-14 20:55:50 +01:00
local np = vector.add ( pos , l )
2014-11-22 17:12:48 +01:00
if mesecon.find_receptor_on ( np , mesecon.invertRule ( l ) ) 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
2014-11-22 17:12:48 +01:00
function mesecon . find_receptor_on ( pos , link )
local frontiers = { { pos = pos , link = link } }
local checked = { }
2012-08-16 21:24:06 +02:00
2014-11-22 17:12:48 +01:00
-- List of positions that have been searched for onstate receptors
local depth = 1
while frontiers [ depth ] do
local f = frontiers [ depth ]
2016-02-19 12:11:38 +01:00
local node = mesecon.get_node_force ( f.pos )
2012-12-27 09:28:04 +01:00
2014-11-23 09:43:24 +01:00
if not node then return false end
2014-11-22 17:12:48 +01:00
if mesecon.is_receptor_on ( node.name ) then return true end
if mesecon.is_conductor_on ( node , f.link ) then
local rules = mesecon.conductor_get_rules ( node )
-- call turnoff on neighbors: normal rules
for _ , r in ipairs ( mesecon.rule2meta ( f.link , rules ) ) do
2016-02-14 20:55:50 +01:00
local np = vector.add ( f.pos , r )
2014-11-22 17:12:48 +01:00
local links = mesecon.rules_link_rule_all_inverted ( f.pos , r )
for _ , l in ipairs ( links ) do
2014-11-22 20:49:54 +01:00
local checkedstring = np.x .. np.y .. np.z .. l.x .. l.y .. l.z
if not checked [ checkedstring ] then
2014-11-22 17:12:48 +01:00
table.insert ( frontiers , { pos = np , link = l } )
2014-11-22 20:49:54 +01:00
checked [ checkedstring ] = true
2014-11-22 17:12:48 +01:00
end
2012-12-15 18:45:51 +01:00
end
2012-08-13 11:58:04 +02:00
end
2015-10-04 13:30:34 +02:00
2012-08-13 11:58:04 +02:00
end
2014-11-22 17:12:48 +01:00
depth = depth + 1
2012-08-13 11:58:04 +02:00
end
end
2014-11-22 15:42:22 +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
2016-02-19 12:11:38 +01:00
local outputnode = mesecon.get_node_force ( output )
local inputnode = mesecon.get_node_force ( input )
2014-11-22 15:42:22 +01:00
local outputrules = dug_outputrules or mesecon.get_any_outputrules ( outputnode )
local inputrules = mesecon.get_any_inputrules ( inputnode )
2012-12-15 18:45:51 +01:00
if not outputrules or not inputrules then
return
2012-08-16 21:24:06 +02:00
end
2014-11-22 15:42:22 +01:00
for _ , outputrule in ipairs ( mesecon.flattenrules ( outputrules ) ) do
2012-12-15 18:45:51 +01:00
-- Check if output sends to input
2016-02-14 20:55:50 +01:00
if vector.equals ( vector.add ( output , outputrule ) , input ) then
2014-11-22 15:42:22 +01:00
for _ , inputrule in ipairs ( mesecon.flattenrules ( inputrules ) ) do
2012-12-15 18:45:51 +01:00
-- Check if input accepts from output
2016-02-14 20:55:50 +01:00
if vector.equals ( vector.add ( input , inputrule ) , output ) then
2014-11-29 15:08:37 +01:00
return true , inputrule
2012-08-13 11:58:04 +02:00
end
end
end
end
2016-02-19 12:11:38 +01:00
2012-08-13 11:58:04 +02:00
return false
end
2014-11-22 15:42:22 +01:00
function mesecon . rules_link_rule_all ( output , rule )
2016-02-14 20:55:50 +01:00
local input = vector.add ( output , rule )
2016-02-19 12:11:38 +01:00
local inputnode = mesecon.get_node_force ( input )
2014-11-22 15:42:22 +01:00
local inputrules = mesecon.get_any_inputrules ( inputnode )
2014-01-04 15:52:52 +01:00
if not inputrules then
2014-01-04 17:22:04 +01:00
return { }
2014-01-04 15:52:52 +01:00
end
2014-01-04 17:22:04 +01:00
local rules = { }
2015-10-04 13:30:34 +02:00
2014-11-22 15:42:22 +01:00
for _ , inputrule in ipairs ( mesecon.flattenrules ( inputrules ) ) do
2014-01-04 15:52:52 +01:00
-- Check if input accepts from output
2016-02-14 20:55:50 +01:00
if vector.equals ( vector.add ( input , inputrule ) , output ) then
2014-11-29 15:08:37 +01:00
table.insert ( rules , inputrule )
2014-01-04 15:52:52 +01:00
end
end
2016-02-19 12:11:38 +01:00
2014-01-04 17:22:04 +01:00
return rules
2014-01-04 15:52:52 +01:00
end
2014-11-22 15:42:22 +01:00
function mesecon . rules_link_rule_all_inverted ( input , rule )
--local irule = mesecon.invertRule(rule)
2016-02-14 20:55:50 +01:00
local output = vector.add ( input , rule )
2016-02-19 12:11:38 +01:00
local outputnode = mesecon.get_node_force ( output )
2014-11-22 15:42:22 +01:00
local outputrules = mesecon.get_any_outputrules ( outputnode )
2014-01-05 13:51:09 +01:00
if not outputrules then
return { }
end
local rules = { }
2015-10-04 13:30:34 +02:00
2014-11-22 15:42:22 +01:00
for _ , outputrule in ipairs ( mesecon.flattenrules ( outputrules ) ) do
2016-02-14 20:55:50 +01:00
if vector.equals ( vector.add ( output , outputrule ) , input ) then
2014-11-29 15:08:37 +01:00
table.insert ( rules , mesecon.invertRule ( outputrule ) )
2014-01-05 13:51:09 +01:00
end
end
return rules
end
2014-11-22 15:42:22 +01:00
function mesecon . rules_link_anydir ( pos1 , pos2 )
return mesecon.rules_link ( pos1 , pos2 ) or mesecon.rules_link ( pos2 , pos1 )
2012-08-16 21:24:06 +02:00
end
2014-11-22 15:42:22 +01:00
function mesecon . is_powered ( pos , rule )
2016-02-19 12:11:38 +01:00
local node = mesecon.get_node_force ( pos )
2014-11-22 15:42:22 +01:00
local rules = mesecon.get_any_inputrules ( node )
2012-12-15 18:45:51 +01:00
if not rules then return false end
2012-08-16 21:24:06 +02:00
2014-11-21 22:04:39 +01:00
-- List of nodes that send out power to pos
local sourcepos = { }
2013-06-19 19:38:34 -07:00
if not rule then
2014-11-22 15:42:22 +01:00
for _ , rule in ipairs ( mesecon.flattenrules ( rules ) ) do
local rulenames = mesecon.rules_link_rule_all_inverted ( pos , rule )
2014-01-05 13:51:09 +01:00
for _ , rname in ipairs ( rulenames ) do
2016-02-14 20:55:50 +01:00
local np = vector.add ( pos , rname )
2016-02-19 12:11:38 +01:00
local nn = mesecon.get_node_force ( np )
if ( mesecon.is_conductor_on ( nn , mesecon.invertRule ( rname ) )
or mesecon.is_receptor_on ( nn.name ) ) then
2014-11-21 22:04:39 +01:00
table.insert ( sourcepos , np )
2014-01-05 13:51:09 +01:00
end
2013-06-19 19:38:34 -07:00
end
end
else
2014-11-22 15:42:22 +01:00
local rulenames = mesecon.rules_link_rule_all_inverted ( pos , rule )
2014-01-05 13:51:09 +01:00
for _ , rname in ipairs ( rulenames ) do
2016-02-14 20:55:50 +01:00
local np = vector.add ( pos , rname )
2016-02-19 12:11:38 +01:00
local nn = mesecon.get_node_force ( np )
2014-11-22 15:42:22 +01:00
if ( mesecon.is_conductor_on ( nn , mesecon.invertRule ( rname ) )
or mesecon.is_receptor_on ( nn.name ) ) then
2014-11-29 10:56:09 +01:00
table.insert ( sourcepos , np )
2014-01-05 13:51:09 +01:00
end
2012-08-13 11:58:04 +02:00
end
end
2014-11-21 22:04:39 +01:00
-- Return FALSE if not powered, return list of sources if is powered
if ( # sourcepos == 0 ) then return false
else return sourcepos end
2012-08-16 21:24:06 +02:00
end
2012-08-13 20:17:45 +02:00
--Rules rotation Functions:
2014-11-22 15:42:22 +01:00
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-11-29 15:08:37 +01:00
table.insert ( nr , {
2015-10-04 13:30:34 +02:00
x = - rule.z ,
y = rule.y ,
2014-11-29 15:08:37 +01:00
z = rule.x ,
name = rule.name } )
2012-08-13 20:17:45 +02:00
end
return nr
end
2014-11-22 15:42:22 +01:00
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-11-29 15:08:37 +01:00
table.insert ( nr , {
2015-10-04 13:30:34 +02:00
x = rule.z ,
y = rule.y ,
2014-11-29 15:08:37 +01:00
z = - rule.x ,
name = rule.name } )
2012-08-13 20:17:45 +02:00
end
return nr
end
2014-11-22 15:42:22 +01:00
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-11-29 15:08:37 +01:00
table.insert ( nr , {
2015-10-04 13:30:34 +02:00
x = - rule.y ,
y = rule.x ,
2014-11-29 15:08:37 +01:00
z = rule.z ,
name = rule.name } )
2012-08-13 20:17:45 +02:00
end
return nr
end
2014-11-22 15:42:22 +01:00
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-11-29 15:08:37 +01:00
table.insert ( nr , {
2015-10-04 13:30:34 +02:00
x = rule.y ,
y = - rule.x ,
2014-11-29 15:08:37 +01:00
z = rule.z ,
name = rule.name } )
2012-08-13 20:17:45 +02:00
end
return nr
end