1 -- Function that get the input/output rules of the delayer
2 local delayer_get_output_rules
= function(node
)
3 local rules
= {{x
= -1, y
= 0, z
= 0, spread
=true}}
4 for i
= 0, node
.param2
do
5 rules
= mesecon
.rotate_rules_left(rules
)
10 local delayer_get_input_rules
= function(node
)
11 local rules
= {{x
= 1, y
= 0, z
= 0}}
12 for i
= 0, node
.param2
do
13 rules
= mesecon
.rotate_rules_left(rules
)
18 -- Return the sides of a delayer.
19 -- Those are used to toggle the lock state.
20 local delayer_get_sides
= function(node
)
22 {x
= 0, y
= 0, z
= -1},
23 {x
= 0, y
= 0, z
= 1},
25 for i
= 0, node
.param2
do
26 rules
= mesecon
.rotate_rules_left(rules
)
31 -- Make the repeater at pos try to lock any repeater it faces.
32 -- Returns true if a repeater was locked.
33 local check_lock_repeater
= function(pos
, node
)
34 -- Check the repeater at pos and look if it faces
35 -- a repeater placed sideways.
36 -- If yes, lock the second repeater.
37 local r
= delayer_get_output_rules(node
)[1]
38 local lpos
= vector
.add(pos
, r
)
39 local lnode
= minetest
.get_node(lpos
)
40 local ldef
= minetest
.registered_nodes
[lnode
.name
]
41 local g
= minetest
.get_item_group(lnode
.name
, "redstone_repeater")
42 if g
>= 1 and g
<= 4 then
43 local lrs
= delayer_get_input_rules(lnode
)
45 for _
, lr
in pairs(lrs
) do
46 if lr
.x
== r
.x
or lr
.z
== r
.z
then
52 minetest
.set_node(lpos
, {name
=ldef
.delayer_lockstate
, param2
=lnode
.param2
})
53 local meta
= minetest
.get_meta(lpos
)
54 meta
:set_int("delay", g
)
61 -- Make the repeater at pos try to unlock any repeater it faces.
62 -- Returns true if a repeater was unlocked.
63 local check_unlock_repeater
= function(pos
, node
)
64 -- Check the repeater at pos and look if it faces
65 -- a repeater placed sideways.
66 -- If yes, also check if the second repeater doesn't receive
67 -- a locking signal on the other side. If not, unlock the second repeater.
68 local r
= delayer_get_output_rules(node
)[1]
69 local lpos
= vector
.add(pos
, r
)
70 local lnode
= minetest
.get_node(lpos
)
71 local ldef
= minetest
.registered_nodes
[lnode
.name
]
72 local g
= minetest
.get_item_group(lnode
.name
, "redstone_repeater")
73 -- Are we facing a locked repeater?
75 -- First check the orientation of the faced repeater
76 local lrs
= delayer_get_input_rules(lnode
)
77 for _
, lr
in pairs(lrs
) do
78 if lr
.x
== r
.x
or lr
.z
== r
.z
then
79 -- Invalid orientation. Do nothing
83 -- Now we check if there's a powered repeater on the other side of the
85 -- To get to the other side, we just take another step in the direction which we already face.
86 local other_side
= vector
.add(lpos
, r
)
87 local other_node
= minetest
.get_node(other_side
)
88 if minetest
.get_item_group(other_node
.name
, "redstone_repeater") ~= 0 and mesecon
.is_receptor_on(other_node
.name
) then
89 -- Final check: The other repeater must also face the right way
90 local other_face
= delayer_get_output_rules(other_node
)[1]
91 local other_facing_pos
= vector
.add(other_side
, other_face
)
92 if vector
.equals(other_facing_pos
, lpos
) then
93 -- Powered repeater found AND it's facing the locked repeater. Do NOT unlock!
97 local lmeta
= minetest
.get_meta(lpos
)
98 local ldelay
= lmeta
:get_int("delay")
99 if tonumber(ldelay
) == nil or ldelay
< 1 or ldelay
> 4 then
102 if mesecon
.is_powered(lpos
, delayer_get_input_rules(lnode
)[1]) then
103 minetest
.set_node(lpos
, {name
="mesecons_delayer:delayer_on_"..ldelay
, param2
=lnode
.param2
})
104 mesecon
.queue
:add_action(lpos
, "receptor_on", {delayer_get_output_rules(lnode
)}, ldef
.delayer_time
, nil)
106 minetest
.set_node(lpos
, {name
="mesecons_delayer:delayer_off_"..ldelay
, param2
=lnode
.param2
})
107 mesecon
.queue
:add_action(lpos
, "receptor_off", {delayer_get_output_rules(lnode
)}, ldef
.delayer_time
, nil)
114 -- Functions that are called after the delay time
115 local delayer_activate
= function(pos
, node
)
116 local def
= minetest
.registered_nodes
[node
.name
]
117 local time
= def
.delayer_time
118 minetest
.set_node(pos
, {name
=def
.delayer_onstate
, param2
=node
.param2
})
119 mesecon
.queue
:add_action(pos
, "receptor_on", {delayer_get_output_rules(node
)}, time
, nil)
121 check_lock_repeater(pos
, node
)
124 local delayer_deactivate
= function(pos
, node
)
125 local def
= minetest
.registered_nodes
[node
.name
]
126 local time
= def
.delayer_time
127 minetest
.set_node(pos
, {name
=def
.delayer_offstate
, param2
=node
.param2
})
128 mesecon
.queue
:add_action(pos
, "receptor_off", {delayer_get_output_rules(node
)}, time
, nil)
130 check_unlock_repeater(pos
, node
)
133 -- Register the 2 (states) x 4 (delay times) delayers
138 groups
= {dig_immediate
=3,dig_by_water
=1,destroy_by_lava_flow
=1,dig_by_piston
=1,attached_node
=1,redstone_repeater
=i
}
140 groups
= {dig_immediate
=3,dig_by_water
=1,destroy_by_lava_flow
=1,dig_by_piston
=1,attached_node
=1,redstone_repeater
=i
,not_in_creative_inventory
=1}
144 if i
== 1 then delaytime
= 0.1
145 elseif i
== 2 then delaytime
= 0.2
146 elseif i
== 3 then delaytime
= 0.3
147 elseif i
== 4 then delaytime
= 0.4
153 { -8/16, -8/16, -8/16, 8/16, -6/16, 8/16 }, -- the main slab
154 { -1/16, -6/16, 6/16, 1/16, -1/16, 4/16}, -- still torch
155 { -1/16, -6/16, 0/16, 1/16, -1/16, 2/16}, -- moved torch
159 { -8/16, -8/16, -8/16, 8/16, -6/16, 8/16 }, -- the main slab
160 { -1/16, -6/16, 6/16, 1/16, -1/16, 4/16}, -- still torch
161 { -1/16, -6/16, -2/16, 1/16, -1/16, 0/16}, -- moved torch
165 { -8/16, -8/16, -8/16, 8/16, -6/16, 8/16 }, -- the main slab
166 { -1/16, -6/16, 6/16, 1/16, -1/16, 4/16}, -- still torch
167 { -1/16, -6/16, -4/16, 1/16, -1/16, -2/16}, -- moved torch
171 { -8/16, -8/16, -8/16, 8/16, -6/16, 8/16 }, -- the main slab
172 { -1/16, -6/16, 6/16, 1/16, -1/16, 4/16}, -- still torch
173 { -1/16, -6/16, -6/16, 1/16, -1/16, -4/16}, -- moved torch
177 local help
, longdesc
, usagehelp
, icon
, on_construct
180 longdesc
= "Redstone repeaters are versatile redstone components with multiple purposes: 1. They only allow signals to travel in one direction. 2. They delay the signal. 3. Optionally, they can lock their output in one state."
181 usagehelp
= "To power a redstone repeater, send a signal in “arrow” direction (the input). The signal goes out on the opposite side (the output) with a delay. To change the delay, rightclick the redstone repeater. The delay is between 0.1 and 0.4 seconds long and can be changed in steps of 0.1 seconds. It is indicated by the position of the moving redstone torch.".."\n"..
182 "To lock a repeater, send a signal from an adjacent repeater into one of its sides. While locked, the moving redstone torch disappears, the output doesn't change and the input signal is ignored."
183 icon
= "mesecons_delayer_item.png"
184 on_construct
= function(pos
)
185 local node
= minetest
.get_node(pos
)
186 local sides
= delayer_get_sides(node
)
188 local spos
= vector
.add(pos
, sides
[s
])
189 local snode
= minetest
.get_node(spos
)
190 local g
= minetest
.get_item_group(snode
.name
, "redstone_repeater")
191 local sdef
= minetest
.registered_nodes
[snode
.name
]
192 if g
~= 0 and mesecon
.is_receptor_on(snode
.name
) then
193 if mesecon
.is_powered(pos
, delayer_get_input_rules(node
)[1]) ~= false then
194 minetest
.set_node(pos
, {name
="mesecons_delayer:delayer_on_locked", param2
= node
.param2
})
196 minetest
.set_node(pos
, {name
="mesecons_delayer:delayer_off_locked", param2
= node
.param2
})
207 if minetest
.get_modpath("screwdriver") then
208 on_rotate
= screwdriver
.disallow
212 minetest
.register_node("mesecons_delayer:delayer_off_"..tostring(i
), {
213 description
= "Redstone Repeater",
214 inventory_image
= icon
,
216 _doc_items_create_entry
= help
,
217 _doc_items_longdesc
= longdesc
,
218 _doc_items_usagehelp
= usagehelp
,
219 drawtype
= "nodebox",
221 "mesecons_delayer_off.png",
222 "mcl_stairs_stone_slab_top.png",
223 "mesecons_delayer_sides_off.png",
224 "mesecons_delayer_sides_off.png",
225 "mesecons_delayer_ends_off.png",
226 "mesecons_delayer_ends_off.png",
228 wield_image
= "mesecons_delayer_off.png",
232 fixed
= { -8/16, -8/16, -8/16, 8/16, -6/16, 8/16 },
236 fixed
= { -8/16, -8/16, -8/16, 8/16, -6/16, 8/16 },
244 paramtype2
= "facedir",
245 sunlight_propagates
= false,
246 is_ground_content
= false,
247 drop
= 'mesecons_delayer:delayer_off_1',
248 on_rightclick
= function (pos
, node
)
249 if node
.name
=="mesecons_delayer:delayer_off_1" then
250 minetest
.set_node(pos
, {name
="mesecons_delayer:delayer_off_2", param2
=node
.param2
})
251 elseif node
.name
=="mesecons_delayer:delayer_off_2" then
252 minetest
.set_node(pos
, {name
="mesecons_delayer:delayer_off_3", param2
=node
.param2
})
253 elseif node
.name
=="mesecons_delayer:delayer_off_3" then
254 minetest
.set_node(pos
, {name
="mesecons_delayer:delayer_off_4", param2
=node
.param2
})
255 elseif node
.name
=="mesecons_delayer:delayer_off_4" then
256 minetest
.set_node(pos
, {name
="mesecons_delayer:delayer_off_1", param2
=node
.param2
})
259 on_construct
= on_construct
,
260 delayer_time
= delaytime
,
261 delayer_onstate
= "mesecons_delayer:delayer_on_"..tostring(i
),
262 delayer_lockstate
= "mesecons_delayer:delayer_off_locked",
263 sounds
= mcl_sounds
.node_sound_stone_defaults(),
267 state
= mesecon
.state
.off
,
268 rules
= delayer_get_output_rules
272 rules
= delayer_get_input_rules
,
273 action_on
= delayer_activate
276 on_rotate
= on_rotate
,
280 minetest
.register_node("mesecons_delayer:delayer_on_"..tostring(i
), {
281 description
= "Redstone Repeater (Powered)",
282 _doc_items_create_entry
= false,
283 drawtype
= "nodebox",
285 "mesecons_delayer_on.png",
286 "mcl_stairs_stone_slab_top.png",
287 "mesecons_delayer_sides_on.png",
288 "mesecons_delayer_sides_on.png",
289 "mesecons_delayer_ends_on.png",
290 "mesecons_delayer_ends_on.png",
295 fixed
= { -8/16, -8/16, -8/16, 8/16, -6/16, 8/16 },
299 fixed
= { -8/16, -8/16, -8/16, 8/16, -6/16, 8/16 },
305 groups
= {dig_immediate
= 3, dig_by_water
=1,destroy_by_lava_flow
=1, dig_by_piston
=1, attached_node
=1, redstone_repeater
=i
, not_in_creative_inventory
= 1},
307 paramtype2
= "facedir",
308 sunlight_propagates
= false,
309 is_ground_content
= false,
310 drop
= 'mesecons_delayer:delayer_off_1',
311 on_rightclick
= function (pos
, node
)
312 if node
.name
=="mesecons_delayer:delayer_on_1" then
313 minetest
.set_node(pos
, {name
="mesecons_delayer:delayer_on_2",param2
=node
.param2
})
314 elseif node
.name
=="mesecons_delayer:delayer_on_2" then
315 minetest
.set_node(pos
, {name
="mesecons_delayer:delayer_on_3",param2
=node
.param2
})
316 elseif node
.name
=="mesecons_delayer:delayer_on_3" then
317 minetest
.set_node(pos
, {name
="mesecons_delayer:delayer_on_4",param2
=node
.param2
})
318 elseif node
.name
=="mesecons_delayer:delayer_on_4" then
319 minetest
.set_node(pos
, {name
="mesecons_delayer:delayer_on_1",param2
=node
.param2
})
322 after_dig_node
= function(pos
, oldnode
)
323 check_unlock_repeater(pos
, oldnode
)
325 delayer_time
= delaytime
,
326 delayer_offstate
= "mesecons_delayer:delayer_off_"..tostring(i
),
327 delayer_lockstate
= "mesecons_delayer:delayer_on_locked",
328 sounds
= mcl_sounds
.node_sound_stone_defaults(),
332 state
= mesecon
.state
.on
,
333 rules
= delayer_get_output_rules
337 rules
= delayer_get_input_rules
,
338 action_off
= delayer_deactivate
341 on_rotate
= on_rotate
,
349 minetest
.register_node("mesecons_delayer:delayer_off_locked", {
350 description
= "Redstone Repeater (Locked)",
351 inventory_image
= icon
,
353 _doc_items_create_entry
= false,
354 drawtype
= "nodebox",
355 -- FIXME: Textures of torch and the lock bar overlap. Nodeboxes are (sadly) not suitable for this.
356 -- So this needs to be turned into a mesh.
358 "mesecons_delayer_locked_off.png",
359 "mcl_stairs_stone_slab_top.png",
360 "mesecons_delayer_sides_locked_off.png",
361 "mesecons_delayer_sides_locked_off.png",
362 "mesecons_delayer_front_locked_off.png",
363 "mesecons_delayer_end_locked_off.png",
365 wield_image
= "mesecons_delayer_locked_off.png",
369 fixed
= { -8/16, -8/16, -8/16, 8/16, -6/16, 8/16 },
373 fixed
= { -8/16, -8/16, -8/16, 8/16, -6/16, 8/16 },
378 { -8/16, -8/16, -8/16, 8/16, -6/16, 8/16 }, -- the main slab
379 { -1/16, -6/16, 6/16, 1/16, -1/16, 4/16}, -- still torch
380 { -6/16, -6/16, -1/16, 6/16, -4/16, 1/16}, -- lock
383 groups
= {dig_immediate
= 3, dig_by_water
=1,destroy_by_lava_flow
=1, dig_by_piston
=1, attached_node
=1, redstone_repeater
=5, not_in_creative_inventory
= 1},
385 paramtype2
= "facedir",
386 sunlight_propagates
= false,
387 is_ground_content
= false,
388 drop
= 'mesecons_delayer:delayer_off_1',
390 sounds
= mcl_sounds
.node_sound_stone_defaults(),
394 state
= mesecon
.state
.off
,
395 rules
= delayer_get_output_rules
399 rules
= delayer_get_input_rules
,
402 on_rotate
= on_rotate
,
405 minetest
.register_node("mesecons_delayer:delayer_on_locked", {
406 description
= "Redstone Repeater (Locked, Powered)",
407 _doc_items_create_entry
= false,
408 drawtype
= "nodebox",
410 "mesecons_delayer_locked_on.png",
411 "mcl_stairs_stone_slab_top.png",
412 "mesecons_delayer_sides_locked_on.png",
413 "mesecons_delayer_sides_locked_on.png",
414 "mesecons_delayer_front_locked_on.png",
415 "mesecons_delayer_end_locked_on.png",
420 fixed
= { -8/16, -8/16, -8/16, 8/16, -6/16, 8/16 },
424 fixed
= { -8/16, -8/16, -8/16, 8/16, -6/16, 8/16 },
429 { -8/16, -8/16, -8/16, 8/16, -6/16, 8/16 }, -- the main slab
430 { -1/16, -6/16, 6/16, 1/16, -1/16, 4/16}, -- still torch
431 { -6/16, -6/16, -1/16, 6/16, -4/16, 1/16}, -- lock
434 after_dig_node
= function(pos
, oldnode
)
435 check_unlock_repeater(pos
, oldnode
)
437 groups
= {dig_immediate
= 3, dig_by_water
=1,destroy_by_lava_flow
=1, dig_by_piston
=1, attached_node
=1, redstone_repeater
=5, not_in_creative_inventory
= 1},
439 paramtype2
= "facedir",
440 sunlight_propagates
= false,
441 is_ground_content
= false,
442 drop
= 'mesecons_delayer:delayer_off_1',
444 sounds
= mcl_sounds
.node_sound_stone_defaults(),
448 state
= mesecon
.state
.on
,
449 rules
= delayer_get_output_rules
453 rules
= delayer_get_input_rules
,
456 on_rotate
= on_rotate
,
459 minetest
.register_craft({
460 output
= "mesecons_delayer:delayer_off_1",
462 {"mesecons_torch:mesecon_torch_on", "mesecons:redstone", "mesecons_torch:mesecon_torch_on"},
463 {"mcl_core:stone","mcl_core:stone", "mcl_core:stone"},
467 -- Add entry aliases for the Help
468 if minetest
.get_modpath("doc") then
469 doc
.add_entry_alias("nodes", "mesecons_delayer:delayer_off_1", "nodes", "mesecons_delayer:delayer_off_2")
470 doc
.add_entry_alias("nodes", "mesecons_delayer:delayer_off_1", "nodes", "mesecons_delayer:delayer_off_3")
471 doc
.add_entry_alias("nodes", "mesecons_delayer:delayer_off_1", "nodes", "mesecons_delayer:delayer_off_4")
472 doc
.add_entry_alias("nodes", "mesecons_delayer:delayer_off_1", "nodes", "mesecons_delayer:delayer_off_locked")
473 doc
.add_entry_alias("nodes", "mesecons_delayer:delayer_off_1", "nodes", "mesecons_delayer:delayer_on_1")
474 doc
.add_entry_alias("nodes", "mesecons_delayer:delayer_off_1", "nodes", "mesecons_delayer:delayer_on_2")
475 doc
.add_entry_alias("nodes", "mesecons_delayer:delayer_off_1", "nodes", "mesecons_delayer:delayer_on_3")
476 doc
.add_entry_alias("nodes", "mesecons_delayer:delayer_off_1", "nodes", "mesecons_delayer:delayer_on_4")
477 doc
.add_entry_alias("nodes", "mesecons_delayer:delayer_off_1", "nodes", "mesecons_delayer:delayer_on_locked")