1 -- Dig and place services
3 mesecon
.on_placenode
= function(pos
, node
)
4 mesecon
.execute_autoconnect_hooks_now(pos
, node
)
6 -- Receptors: Send on signal when active
7 if mesecon
.is_receptor_on(node
.name
) then
8 mesecon
.receptor_on(pos
, mesecon
.receptor_get_rules(node
))
11 -- Conductors: Send turnon signal when powered or replace by respective offstate conductor
12 -- if placed conductor is an onstate one
13 if mesecon
.is_conductor(node
.name
) then
14 local sources
= mesecon
.is_powered(pos
)
16 -- also call receptor_on if itself is powered already, so that neighboring
17 -- conductors will be activated (when pushing an on-conductor with a piston)
18 for _
, s
in ipairs(sources
) do
19 local rule
= vector
.subtract(pos
, s
)
20 mesecon
.turnon(pos
, rule
)
22 mesecon
.receptor_on (pos
, mesecon
.conductor_get_rules(node
))
23 elseif mesecon
.is_conductor_on(node
) then
24 minetest
.swap_node(pos
, {name
= mesecon
.get_conductor_off(node
)})
28 -- Effectors: Send changesignal and activate or deactivate
29 if mesecon
.is_effector(node
.name
) then
30 local powered_rules
= {}
31 local unpowered_rules
= {}
33 -- for each input rule, check if powered
34 for _
, r
in ipairs(mesecon
.effector_get_rules(node
)) do
35 local powered
= mesecon
.is_powered(pos
, r
)
36 if powered
then table.insert(powered_rules
, r
)
37 else table.insert(unpowered_rules
, r
) end
39 local state
= powered
and mesecon
.state
.on
or mesecon
.state
.off
40 mesecon
.changesignal(pos
, node
, r
, state
, 1)
43 if (#powered_rules
> 0) then
44 for _
, r
in ipairs(powered_rules
) do
45 mesecon
.activate(pos
, node
, r
, 1)
48 for _
, r
in ipairs(unpowered_rules
) do
49 mesecon
.deactivate(pos
, node
, r
, 1)
54 if minetest
.get_item_group(node
.name
, "opaque") == 1 then
55 local neighbors
= mesecon
.mcl_get_neighbors(pos
)
56 local is_powered
, direct_source
= mesecon
.is_powered(pos
)
57 if is_powered
and direct_source
then
58 for n
=1, #neighbors
do
59 local npos
= neighbors
[n
].pos
60 local nnode
= minetest
.get_node(npos
)
61 if mesecon
.is_conductor_off(nnode
) then
62 mesecon
.receptor_on(npos
, mesecon
.conductor_get_rules(nnode
))
63 -- Redstone torch is a special case and must be ignored
64 elseif mesecon
.is_effector_on(nnode
.name
) and minetest
.get_item_group(nnode
.name
, "redstone_torch") == 0 then
65 mesecon
.changesignal(npos
, nnode
, neighbors
[n
].link
, mesecon
.state
.on
, 1)
66 mesecon
.activate(npos
, nnode
, neighbors
[n
].link
, 1)
73 mesecon
.on_dignode
= function(pos
, node
)
74 if mesecon
.is_conductor_on(node
) then
75 mesecon
.receptor_off(pos
, mesecon
.conductor_get_rules(node
))
76 elseif mesecon
.is_receptor_on(node
.name
) then
77 mesecon
.receptor_off(pos
, mesecon
.receptor_get_rules(node
))
79 if minetest
.get_item_group(node
.name
, "opaque") == 1 then
80 local sources
= mesecon
.is_powered(pos
)
81 local neighbors
= mesecon
.mcl_get_neighbors(pos
)
82 for n
=1, #neighbors
do
83 local npos
= neighbors
[n
].pos
84 local nlink
= neighbors
[n
].link
85 local nnode
= minetest
.get_node(npos
)
86 if mesecon
.is_conductor_on(nnode
) then
87 mesecon
.receptor_off(npos
, mesecon
.conductor_get_rules(nnode
))
88 -- Redstone torch is a special case and must be ignored
89 elseif mesecon
.is_effector_on(nnode
.name
) and mesecon
.is_powered(npos
) == false and minetest
.get_item_group(nnode
.name
, "redstone_torch") == 0 then
90 mesecon
.changesignal(npos
, nnode
, nlink
, mesecon
.state
.off
, 1)
91 mesecon
.deactivate(npos
, nnode
, nlink
, 1)
95 mesecon
.execute_autoconnect_hooks_queue(pos
, node
)
98 minetest
.register_on_placenode(mesecon
.on_placenode
)
99 minetest
.register_on_dignode(mesecon
.on_dignode
)
101 -- Overheating service for fast circuits
102 local OVERHEAT_MAX
= mesecon
.setting("overheat_max", 8)
103 local COOLDOWN_TIME
= mesecon
.setting("cooldown_time", 3.0)
104 local COOLDOWN_STEP
= mesecon
.setting("cooldown_granularity", 0.5)
105 local COOLDOWN_MULTIPLIER
= OVERHEAT_MAX
/ COOLDOWN_TIME
106 local cooldown_timer
= 0.0
107 local object_heat
= {}
109 -- returns true if heat is too high
110 function mesecon
.do_overheat(pos
)
111 local id
= minetest
.hash_node_position(pos
)
112 local heat
= (object_heat
[id
] or 0) + 1
113 object_heat
[id
] = heat
114 if heat
>= OVERHEAT_MAX
then
115 minetest
.log("action", "Node overheats at " .. minetest
.pos_to_string(pos
))
116 object_heat
[id
] = nil
122 function mesecon
.do_cooldown(pos
)
123 local id
= minetest
.hash_node_position(pos
)
124 object_heat
[id
] = nil
127 function mesecon
.get_heat(pos
)
128 local id
= minetest
.hash_node_position(pos
)
129 return object_heat
[id
] or 0
132 function mesecon
.move_hot_nodes(moved_nodes
)
134 for _
, n
in ipairs(moved_nodes
) do
135 local old_id
= minetest
.hash_node_position(n
.oldpos
)
136 local new_id
= minetest
.hash_node_position(n
.pos
)
137 new_heat
[new_id
] = object_heat
[old_id
]
138 object_heat
[old_id
] = nil
140 for id
, heat
in pairs(new_heat
) do
141 object_heat
[id
] = heat
145 local function global_cooldown(dtime
)
146 cooldown_timer
= cooldown_timer
+ dtime
147 if cooldown_timer
< COOLDOWN_STEP
then
148 return -- don't overload the CPU
150 local cooldown
= COOLDOWN_MULTIPLIER
* cooldown_timer
152 for id
, heat
in pairs(object_heat
) do
153 heat
= heat
- cooldown
155 object_heat
[id
] = nil -- free some RAM
157 object_heat
[id
] = heat
161 minetest
.register_globalstep(global_cooldown
)