Repeaters: Set correct lock state on placement
[MineClone/MineClone2.git] / mods / ITEMS / REDSTONE / mesecons_delayer / init.lua
blob87e7918d162113cf4a9dba908725d471dd03ad8e
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)
6 end
7 return rules
8 end
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)
14 end
15 return rules
16 end
18 -- Return the sides of a delayer.
19 -- Those are used to toggle the lock state.
20 local delayer_get_sides = function(node)
21 local rules = {
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)
27 end
28 return rules
29 end
31 local check_lock_repeater = function(pos, node)
32 -- Check the repeater at pos and look if there is
33 -- a repeater in its facing direction and sideways.
34 -- If yes, lock the second repeater.
35 local r = delayer_get_output_rules(node)[1]
36 local lpos = vector.add(pos, r)
37 local lnode = minetest.get_node(lpos)
38 local ldef = minetest.registered_nodes[lnode.name]
39 local g = minetest.get_item_group(lnode.name, "redstone_repeater")
40 if g >= 1 and g <= 4 then
41 local lrs = delayer_get_input_rules(lnode)
42 local fail = false
43 for _, lr in pairs(lrs) do
44 if lr.x == r.x or lr.z == r.z then
45 fail = true
46 break
47 end
48 end
49 if not fail then
50 minetest.swap_node(lpos, {name=ldef.delayer_lockstate, param2=lnode.param2})
51 return true
52 end
53 end
54 return false
55 end
57 local check_unlock_repeater = function(pos, node)
58 -- Unlock repeater
59 local r = delayer_get_output_rules(node)[1]
60 local lpos = vector.add(pos, r)
61 local lnode = minetest.get_node(lpos)
62 local ldef = minetest.registered_nodes[lnode.name]
63 local g = minetest.get_item_group(lnode.name, "redstone_repeater")
64 if g == 5 then
65 local lrs = delayer_get_input_rules(lnode)
66 local fail = false
67 for _, lr in pairs(lrs) do
68 if lr.x == r.x or lr.z == r.z then
69 fail = true
70 break
71 end
72 end
73 if not fail then
74 if mesecon.is_powered(lpos) then
75 minetest.swap_node(lpos, {name="mesecons_delayer:delayer_on_1", param2=lnode.param2})
76 mesecon.queue:add_action(lpos, "receptor_on", {delayer_get_output_rules(lnode)}, ldef.delayer_time, nil)
77 else
78 minetest.swap_node(lpos, {name="mesecons_delayer:delayer_off_1", param2=lnode.param2})
79 mesecon.queue:add_action(lpos, "receptor_off", {delayer_get_output_rules(lnode)}, ldef.delayer_time, nil)
80 end
81 return true
82 end
83 end
84 return false
85 end
87 -- Functions that are called after the delay time
88 local delayer_activate = function(pos, node)
89 local def = minetest.registered_nodes[node.name]
90 local time = def.delayer_time
91 minetest.swap_node(pos, {name=def.delayer_onstate, param2=node.param2})
92 mesecon.queue:add_action(pos, "receptor_on", {delayer_get_output_rules(node)}, time, nil)
94 check_lock_repeater(pos, node)
95 end
97 local delayer_deactivate = function(pos, node)
98 local def = minetest.registered_nodes[node.name]
99 local time = def.delayer_time
100 minetest.swap_node(pos, {name=def.delayer_offstate, param2=node.param2})
101 mesecon.queue:add_action(pos, "receptor_off", {delayer_get_output_rules(node)}, time, nil)
103 check_unlock_repeater(pos, node)
106 -- Register the 2 (states) x 4 (delay times) delayers
108 for i = 1, 4 do
109 local groups = {}
110 if i == 1 then
111 groups = {dig_immediate=3,dig_by_water=1,destroy_by_lava_flow=1,dig_by_piston=1,attached_node=1,redstone_repeater=i}
112 else
113 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}
116 local delaytime
117 if i == 1 then delaytime = 0.1
118 elseif i == 2 then delaytime = 0.2
119 elseif i == 3 then delaytime = 0.3
120 elseif i == 4 then delaytime = 0.4
123 local boxes
124 if i == 1 then
125 boxes = {
126 { -8/16, -8/16, -8/16, 8/16, -6/16, 8/16 }, -- the main slab
127 { -1/16, -6/16, 6/16, 1/16, -1/16, 4/16}, -- still torch
128 { -1/16, -6/16, 0/16, 1/16, -1/16, 2/16}, -- moved torch
130 elseif i == 2 then
131 boxes = {
132 { -8/16, -8/16, -8/16, 8/16, -6/16, 8/16 }, -- the main slab
133 { -1/16, -6/16, 6/16, 1/16, -1/16, 4/16}, -- still torch
134 { -1/16, -6/16, -2/16, 1/16, -1/16, 0/16}, -- moved torch
136 elseif i == 3 then
137 boxes = {
138 { -8/16, -8/16, -8/16, 8/16, -6/16, 8/16 }, -- the main slab
139 { -1/16, -6/16, 6/16, 1/16, -1/16, 4/16}, -- still torch
140 { -1/16, -6/16, -4/16, 1/16, -1/16, -2/16}, -- moved torch
142 elseif i == 4 then
143 boxes = {
144 { -8/16, -8/16, -8/16, 8/16, -6/16, 8/16 }, -- the main slab
145 { -1/16, -6/16, 6/16, 1/16, -1/16, 4/16}, -- still torch
146 { -1/16, -6/16, -6/16, 1/16, -1/16, -4/16}, -- moved torch
150 local help, longdesc, usagehelp, icon, on_construct
151 if i == 1 then
152 help = true
153 longdesc = "Redstone repeaters are versatile redstone components which delay redstone signals and only allow redstone signals to travel through one direction. The delay of the signal is indicated by the redstone torches and is between 0.1 and 0.4 seconds long."
154 usagehelp = "To power a redstone repeater, send a signal in “arrow” direction. To change the delay, rightclick the redstone repeater. The delay is changed in steps of 0.1 seconds."
155 icon = "mesecons_delayer_item.png"
156 on_construct = function(pos)
157 local node = minetest.get_node(pos)
158 local sides = delayer_get_sides(node)
159 for s=1, #sides do
160 local spos = vector.add(pos, sides[s])
161 local snode = minetest.get_node(spos)
162 local g = minetest.get_item_group(snode.name, "redstone_repeater")
163 local sdef = minetest.registered_nodes[snode.name]
164 if g ~= 0 and sdef.mesecons.receptor.state == mesecon.state.on then
165 if mesecon.is_powered(pos, delayer_get_input_rules(node)[1]) ~= false then
166 minetest.swap_node(pos, {name="mesecons_delayer:delayer_on_locked", param2 = node.param2})
167 else
168 minetest.swap_node(pos, {name="mesecons_delayer:delayer_off_locked", param2 = node.param2})
170 break
174 else
175 help = false
178 local on_rotate
179 if minetest.get_modpath("screwdriver") then
180 on_rotate = screwdriver.disallow
184 minetest.register_node("mesecons_delayer:delayer_off_"..tostring(i), {
185 description = "Redstone Repeater",
186 inventory_image = icon,
187 wield_image = icon,
188 _doc_items_create_entry = help,
189 _doc_items_longdesc = longdesc,
190 _doc_items_usagehelp = usagehelp,
191 drawtype = "nodebox",
192 tiles = {
193 "mesecons_delayer_off.png",
194 "mcl_stairs_stone_slab_top.png",
195 "mesecons_delayer_sides_off.png",
196 "mesecons_delayer_sides_off.png",
197 "mesecons_delayer_ends_off.png",
198 "mesecons_delayer_ends_off.png",
200 wield_image = "mesecons_delayer_off.png",
201 walkable = true,
202 selection_box = {
203 type = "fixed",
204 fixed = { -8/16, -8/16, -8/16, 8/16, -6/16, 8/16 },
206 collision_box = {
207 type = "fixed",
208 fixed = { -8/16, -8/16, -8/16, 8/16, -6/16, 8/16 },
210 node_box = {
211 type = "fixed",
212 fixed = boxes
214 groups = groups,
215 paramtype = "light",
216 paramtype2 = "facedir",
217 sunlight_propagates = false,
218 is_ground_content = false,
219 drop = 'mesecons_delayer:delayer_off_1',
220 on_rightclick = function (pos, node)
221 if node.name=="mesecons_delayer:delayer_off_1" then
222 minetest.swap_node(pos, {name="mesecons_delayer:delayer_off_2", param2=node.param2})
223 elseif node.name=="mesecons_delayer:delayer_off_2" then
224 minetest.swap_node(pos, {name="mesecons_delayer:delayer_off_3", param2=node.param2})
225 elseif node.name=="mesecons_delayer:delayer_off_3" then
226 minetest.swap_node(pos, {name="mesecons_delayer:delayer_off_4", param2=node.param2})
227 elseif node.name=="mesecons_delayer:delayer_off_4" then
228 minetest.swap_node(pos, {name="mesecons_delayer:delayer_off_1", param2=node.param2})
230 end,
231 on_construct = on_construct,
232 delayer_time = delaytime,
233 delayer_onstate = "mesecons_delayer:delayer_on_"..tostring(i),
234 delayer_lockstate = "mesecons_delayer:delayer_off_locked",
235 sounds = mcl_sounds.node_sound_stone_defaults(),
236 mesecons = {
237 receptor =
239 state = mesecon.state.off,
240 rules = delayer_get_output_rules
242 effector =
244 rules = delayer_get_input_rules,
245 action_on = delayer_activate
248 on_rotate = on_rotate,
252 minetest.register_node("mesecons_delayer:delayer_on_"..tostring(i), {
253 description = "Redstone Repeater (Powered)",
254 _doc_items_create_entry = false,
255 drawtype = "nodebox",
256 tiles = {
257 "mesecons_delayer_on.png",
258 "mcl_stairs_stone_slab_top.png",
259 "mesecons_delayer_sides_on.png",
260 "mesecons_delayer_sides_on.png",
261 "mesecons_delayer_ends_on.png",
262 "mesecons_delayer_ends_on.png",
264 walkable = true,
265 selection_box = {
266 type = "fixed",
267 fixed = { -8/16, -8/16, -8/16, 8/16, -6/16, 8/16 },
269 collision_box = {
270 type = "fixed",
271 fixed = { -8/16, -8/16, -8/16, 8/16, -6/16, 8/16 },
273 node_box = {
274 type = "fixed",
275 fixed = boxes
277 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},
278 paramtype = "light",
279 paramtype2 = "facedir",
280 sunlight_propagates = false,
281 is_ground_content = false,
282 drop = 'mesecons_delayer:delayer_off_1',
283 on_rightclick = function (pos, node)
284 if node.name=="mesecons_delayer:delayer_on_1" then
285 minetest.swap_node(pos, {name="mesecons_delayer:delayer_on_2",param2=node.param2})
286 elseif node.name=="mesecons_delayer:delayer_on_2" then
287 minetest.swap_node(pos, {name="mesecons_delayer:delayer_on_3",param2=node.param2})
288 elseif node.name=="mesecons_delayer:delayer_on_3" then
289 minetest.swap_node(pos, {name="mesecons_delayer:delayer_on_4",param2=node.param2})
290 elseif node.name=="mesecons_delayer:delayer_on_4" then
291 minetest.swap_node(pos, {name="mesecons_delayer:delayer_on_1",param2=node.param2})
293 end,
294 after_dig_node = function(pos, oldnode, oldmetadata, digger)
295 check_unlock_repeater(pos, oldnode)
296 end,
297 delayer_time = delaytime,
298 delayer_offstate = "mesecons_delayer:delayer_off_"..tostring(i),
299 delayer_lockstate = "mesecons_delayer:delayer_on_locked",
300 sounds = mcl_sounds.node_sound_stone_defaults(),
301 mesecons = {
302 receptor =
304 state = mesecon.state.on,
305 rules = delayer_get_output_rules
307 effector =
309 rules = delayer_get_input_rules,
310 action_off = delayer_deactivate
313 on_rotate = on_rotate,
319 -- Locked repeater
321 minetest.register_node("mesecons_delayer:delayer_off_locked", {
322 description = "Redstone Repeater (Locked)",
323 inventory_image = icon,
324 wield_image = icon,
325 _doc_items_create_entry = false,
326 drawtype = "nodebox",
327 -- FIXME: Textures of torch and the lock bar overlap. Nodeboxes are (sadly) not suitable for this.
328 -- So this needs to be turned into a mesh.
329 tiles = {
330 "mesecons_delayer_locked_off.png",
331 "mcl_stairs_stone_slab_top.png",
332 "mesecons_delayer_sides_locked_off.png",
333 "mesecons_delayer_sides_locked_off.png",
334 "mesecons_delayer_front_locked_off.png",
335 "mesecons_delayer_end_locked_off.png",
337 wield_image = "mesecons_delayer_locked_off.png",
338 walkable = true,
339 selection_box = {
340 type = "fixed",
341 fixed = { -8/16, -8/16, -8/16, 8/16, -6/16, 8/16 },
343 collision_box = {
344 type = "fixed",
345 fixed = { -8/16, -8/16, -8/16, 8/16, -6/16, 8/16 },
347 node_box = {
348 type = "fixed",
349 fixed = {
350 { -8/16, -8/16, -8/16, 8/16, -6/16, 8/16 }, -- the main slab
351 { -1/16, -6/16, 6/16, 1/16, -1/16, 4/16}, -- still torch
352 { -6/16, -6/16, 0/16, 6/16, -4/16, 2/16}, -- lock
355 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},
356 paramtype = "light",
357 paramtype2 = "facedir",
358 sunlight_propagates = false,
359 is_ground_content = false,
360 drop = 'mesecons_delayer:delayer_off_1',
361 delayer_time = 0.1,
362 sounds = mcl_sounds.node_sound_stone_defaults(),
363 mesecons = {
364 receptor =
366 state = mesecon.state.off,
367 rules = delayer_get_output_rules
369 effector =
371 rules = delayer_get_input_rules,
374 on_rotate = on_rotate,
377 minetest.register_node("mesecons_delayer:delayer_on_locked", {
378 description = "Redstone Repeater (Locked, Powered)",
379 _doc_items_create_entry = false,
380 drawtype = "nodebox",
381 tiles = {
382 "mesecons_delayer_locked_on.png",
383 "mcl_stairs_stone_slab_top.png",
384 "mesecons_delayer_sides_locked_on.png",
385 "mesecons_delayer_sides_locked_on.png",
386 "mesecons_delayer_front_locked_on.png",
387 "mesecons_delayer_end_locked_on.png",
389 walkable = true,
390 selection_box = {
391 type = "fixed",
392 fixed = { -8/16, -8/16, -8/16, 8/16, -6/16, 8/16 },
394 collision_box = {
395 type = "fixed",
396 fixed = { -8/16, -8/16, -8/16, 8/16, -6/16, 8/16 },
398 node_box = {
399 type = "fixed",
400 fixed = {
401 { -8/16, -8/16, -8/16, 8/16, -6/16, 8/16 }, -- the main slab
402 { -1/16, -6/16, 6/16, 1/16, -1/16, 4/16}, -- still torch
403 { -6/16, -6/16, 0/16, 6/16, -4/16, 2/16}, -- lock
406 after_dig_node = function(pos, oldnode, oldmetadata, digger)
407 check_unlock_repeater(pos, oldnode)
408 end,
409 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},
410 paramtype = "light",
411 paramtype2 = "facedir",
412 sunlight_propagates = false,
413 is_ground_content = false,
414 drop = 'mesecons_delayer:delayer_off_1',
415 delayer_time = 0.1,
416 sounds = mcl_sounds.node_sound_stone_defaults(),
417 mesecons = {
418 receptor =
420 state = mesecon.state.on,
421 rules = delayer_get_output_rules
423 effector =
425 rules = delayer_get_input_rules,
428 on_rotate = on_rotate,
431 minetest.register_craft({
432 output = "mesecons_delayer:delayer_off_1",
433 recipe = {
434 {"mesecons_torch:mesecon_torch_on", "mesecons:redstone", "mesecons_torch:mesecon_torch_on"},
435 {"mcl_core:stone","mcl_core:stone", "mcl_core:stone"},
439 -- Add entry aliases for the Help
440 if minetest.get_modpath("doc") then
441 doc.add_entry_alias("nodes", "mesecons_delayer:delayer_off_1", "nodes", "mesecons_delayer:delayer_off_2")
442 doc.add_entry_alias("nodes", "mesecons_delayer:delayer_off_1", "nodes", "mesecons_delayer:delayer_off_3")
443 doc.add_entry_alias("nodes", "mesecons_delayer:delayer_off_1", "nodes", "mesecons_delayer:delayer_off_4")
444 doc.add_entry_alias("nodes", "mesecons_delayer:delayer_off_1", "nodes", "mesecons_delayer:delayer_off_locked")
445 doc.add_entry_alias("nodes", "mesecons_delayer:delayer_off_1", "nodes", "mesecons_delayer:delayer_on_1")
446 doc.add_entry_alias("nodes", "mesecons_delayer:delayer_off_1", "nodes", "mesecons_delayer:delayer_on_2")
447 doc.add_entry_alias("nodes", "mesecons_delayer:delayer_off_1", "nodes", "mesecons_delayer:delayer_on_3")
448 doc.add_entry_alias("nodes", "mesecons_delayer:delayer_off_1", "nodes", "mesecons_delayer:delayer_on_4")
449 doc.add_entry_alias("nodes", "mesecons_delayer:delayer_off_1", "nodes", "mesecons_delayer:delayer_on_locked")