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 -- Disable neighbor effectors unless they are in a special ignore group
89 elseif mesecon
.is_effector_on(nnode
.name
) and mesecon
.is_powered(npos
) == false and minetest
.get_item_group(nnode
.name
, "mesecon_ignore_opaque_dig") == 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 mesecon
.on_blastnode
= function(pos
, node
)
99 local node
= minetest
.get_node(pos
)
100 minetest
.remove_node(pos
)
101 mesecon
.on_dignode(pos
, node
)
102 return minetest
.get_node_drops(node
.name
, "")
105 minetest
.register_on_placenode(mesecon
.on_placenode
)
106 minetest
.register_on_dignode(mesecon
.on_dignode
)
108 -- Overheating service for fast circuits
109 local OVERHEAT_MAX
= mesecon
.setting("overheat_max", 8)
110 local COOLDOWN_TIME
= mesecon
.setting("cooldown_time", 3.0)
111 local COOLDOWN_STEP
= mesecon
.setting("cooldown_granularity", 0.5)
112 local COOLDOWN_MULTIPLIER
= OVERHEAT_MAX
/ COOLDOWN_TIME
113 local cooldown_timer
= 0.0
114 local object_heat
= {}
116 -- returns true if heat is too high
117 function mesecon
.do_overheat(pos
)
118 local id
= minetest
.hash_node_position(pos
)
119 local heat
= (object_heat
[id
] or 0) + 1
120 object_heat
[id
] = heat
121 if heat
>= OVERHEAT_MAX
then
122 minetest
.log("action", "Node overheats at " .. minetest
.pos_to_string(pos
))
123 object_heat
[id
] = nil
129 function mesecon
.do_cooldown(pos
)
130 local id
= minetest
.hash_node_position(pos
)
131 object_heat
[id
] = nil
134 function mesecon
.get_heat(pos
)
135 local id
= minetest
.hash_node_position(pos
)
136 return object_heat
[id
] or 0
139 function mesecon
.move_hot_nodes(moved_nodes
)
141 for _
, n
in ipairs(moved_nodes
) do
142 local old_id
= minetest
.hash_node_position(n
.oldpos
)
143 local new_id
= minetest
.hash_node_position(n
.pos
)
144 new_heat
[new_id
] = object_heat
[old_id
]
145 object_heat
[old_id
] = nil
147 for id
, heat
in pairs(new_heat
) do
148 object_heat
[id
] = heat
152 local function global_cooldown(dtime
)
153 cooldown_timer
= cooldown_timer
+ dtime
154 if cooldown_timer
< COOLDOWN_STEP
then
155 return -- don't overload the CPU
157 local cooldown
= COOLDOWN_MULTIPLIER
* cooldown_timer
159 for id
, heat
in pairs(object_heat
) do
160 heat
= heat
- cooldown
162 object_heat
[id
] = nil -- free some RAM
164 object_heat
[id
] = heat
168 minetest
.register_globalstep(global_cooldown
)