]> git.lizzy.rs Git - Crafter.git/blob - mods/redstone/init.lua
1998fb4469b2c6db6c72c160e2966c401ba7f329
[Crafter.git] / mods / redstone / init.lua
1 local 
2 minetest,vector,math,table,pairs,next
3 =
4 minetest,vector,math,table,pairs,next
5
6 -- minetest class
7 local get_node        = minetest.get_node
8 local get_item_group  = minetest.get_item_group
9 local get_meta        = minetest.get_meta
10 local facedir_to_dir  = minetest.facedir_to_dir
11 local content_id      = minetest.get_name_from_content_id
12 local get_content_id  = minetest.get_content_id
13 local get_voxel_manip = minetest.get_voxel_manip
14 local after           = minetest.after
15
16 local swap_node       = minetest.swap_node
17 local registered_nodes
18 minetest.register_on_mods_loaded(function()
19         registered_nodes  = minetest.registered_nodes
20 end)
21
22 -- math class
23 local abs   = math.abs
24 local floor = math.floor
25 local ceil   = math.ceil
26
27 -- vector library
28 local new_vec         = vector.new
29 local add_vec         = vector.add
30 local sub_vec         = vector.subtract
31 local vector_distance = vector.distance
32 local vec_equals      = vector.equals
33
34 local activator_table = {} -- this holds the translation data of activator tables (activator functions)
35 local capacitor_table = {}
36 local player_detection_table = {}
37
38 -- redstone class
39 redstone = {}
40
41 redstone.player_detector_add = function(pos)
42         player_detection_table[minetest.serialize(pos)] = pos
43 end
44
45 redstone.player_detector_remove = function(pos)
46         player_detection_table[minetest.serialize(pos)] = nil
47 end
48
49
50 -- enables mods to create data functions
51 function redstone.register_activator(data)
52         activator_table[data.name] = {
53                 activate   = data.activate,
54                 deactivate = data.deactivate
55         }
56 end
57
58 -- enables mods to create data functions
59 function redstone.register_capacitor(data)
60         capacitor_table[data.name] = {
61                 off = data.off,
62                 on  = data.on
63         }
64 end
65
66 local path = minetest.get_modpath("redstone")
67 dofile(path.."/functions.lua")
68 dofile(path.."/torch.lua")
69 dofile(path.."/lever.lua")
70 dofile(path.."/button.lua")
71 dofile(path.."/repeater.lua")
72 dofile(path.."/light.lua")
73 dofile(path.."/piston.lua")
74 --dofile(path.."/comparator.lua")
75 dofile(path.."/craft.lua")
76 --dofile(path.."/ore.lua")
77 dofile(path.."/inverter.lua")
78 dofile(path.."/player_detector.lua")
79 dofile(path.."/space_maker.lua")
80 --dofile(path.."/pressure_plate.lua")
81 dofile(path.."/capacitors.lua")
82
83
84 --this is written out manually so that
85 --math.abs is not needed
86 local order = {
87         {x=0,y=0,z=0},
88
89         {x=1, y=0, z=0}, {x=-1, y=0, z= 0},
90         {x=0, y=0, z=1}, {x= 0, y=0, z=-1},
91
92         {x=0, y=1, z=0}, {x= 0, y=-1, z=0},
93
94         {x=1, y=1, z=0}, {x=-1, y=1, z= 0},
95         {x=0, y=1, z=1}, {x= 0, y=1, z=-1},
96
97         {x=1, y=-1, z=0}, {x=-1, y=-1, z= 0},
98         {x=0, y=-1, z=1}, {x= 0, y=-1, z=-1},
99 }
100
101 --thanks to RhodiumToad for helping me figure out a good method to do this
102
103 local pool = {} -- this holds all redstone data (literal 3d virtual memory map)
104
105
106 local function data_injection(pos,data)
107         -- add data into 3d memory
108         if data then
109                 if not pool[pos.x] then pool[pos.x] = {} end
110                 if not pool[pos.x][pos.y] then pool[pos.x][pos.y] = {} end
111                 pool[pos.x][pos.y][pos.z] = data
112         --delete data from 3d memory
113         else
114                 if pool and pool[pos.x] and pool[pos.x][pos.y] then
115                         pool[pos.x][pos.y][pos.z] = data
116                         if pool[pos.x][pos.y] and not next(pool[pos.x][pos.y]) then
117                                 pool[pos.x][pos.y] = nil
118                                 -- only run this if y axis is empty
119                                 if pool[pos.x] and not next(pool[pos.x]) then
120                                         pool[pos.x] = nil
121                                 end
122                         end
123                 end
124         end
125 end
126
127 local table_3d
128 local temp_pool
129 local function create_boundary_box(pos)
130         table_3d = {}
131         for x = pos.x-16,pos.x+16 do
132                 if pool[x] then
133                         for y = pos.y-16,pos.y+16 do
134                                 if pool[x][y] then
135                                         for z = pos.z-16,pos.z+16 do
136                                                 temp_pool = pool[x][y][z]
137                                                 if temp_pool then
138                                                         if not table_3d[x] then table_3d[x] = {} end
139                                                         if not table_3d[x][y] then table_3d[x][y] = {} end
140
141                                                         if (x == pos.x-16 or x == pos.x+16 or 
142                                                         y == pos.y-16 or y == pos.y+16 or 
143                                                         z == pos.z-16 or z == pos.z+16) and 
144                                                         temp_pool.dust and temp_pool.dust > 1 then
145                                                                 table_3d[x][y][z] = {torch=temp_pool.dust}
146                                                         else
147                                                                 if temp_pool.dust then
148                                                                         table_3d[x][y][z] = {dust=0,origin=temp_pool.dust}
149                                                                 else
150                                                                         table_3d[x][y][z] = temp_pool
151                                                                 end
152                                                         end
153                                                 end
154                                         end
155                                 end
156                         end
157                 end
158         end
159         return(table_3d)
160 end
161
162 local i
163 local index
164 local function capacitor_pathfind(source,mem_map)
165         for _,order in pairs(order) do
166
167                 i = add_vec(source,order)
168                 if not mem_map[i.x] then mem_map[i.x] = {} end
169                 if not mem_map[i.x][i.y] then mem_map[i.x][i.y] = {} end
170
171                 if not mem_map[i.x][i.y][i.z] then
172
173                         if i and pool and pool[i.x] and pool[i.x][i.y] and pool[i.x][i.y][i.z] then
174                                 index = pool[i.x][i.y][i.z]
175                                 if index.capacitor then
176                                         mem_map[i.x][i.y][i.z] = {name = index.name, capacitor = 0, source = index.source}
177                                         if index.source then
178                                                 mem_map.found = true
179                                         end
180                                         capacitor_pathfind(i,mem_map)
181                                 end
182                         end
183                 end
184         end
185         return mem_map
186 end
187
188 local table_3d
189 local found
190 local temp_pool
191 local function capacitor_sniff(pos)
192         table_3d = {}
193         table_3d = capacitor_pathfind(pos,table_3d)
194         found = table_3d.found
195         table_3d.found = nil
196         if found then
197                 for x,datax in pairs(table_3d) do
198                         for y,datay in pairs(datax) do
199                                 for z,data in pairs(datay) do
200                                         temp_pool = pool[x][y][z]
201                                         if temp_pool then
202                                                 temp_pool.capacitor = 1
203                                                 if capacitor_table[temp_pool.name] then
204                                                         swap_node(new_vec(x,y,z),{name=capacitor_table[temp_pool.name].on})
205                                                         redstone.update(new_vec(x,y,z))
206                                                 end
207                                         end
208                                 end
209                         end
210                 end
211         else
212                 for x,datax in pairs(table_3d) do
213                         for y,datay in pairs(datax) do
214                                 for z,data in pairs(datay) do
215                                         temp_pool = pool[x][y][z]
216                                         if temp_pool then
217                                                 temp_pool.capacitor = 0
218                                                 if capacitor_table[temp_pool.name] then
219                                                         swap_node(new_vec(x,y,z),{name=capacitor_table[temp_pool.name].off})
220                                                         redstone.update(new_vec(x,y,z))
221                                                 end
222                                         end
223                                 end
224                         end
225                 end
226         end
227 end
228
229
230
231 -- activators
232 local n_pos
233 local temp_pool
234 local temp_pool2
235 local non_directional_activator = function(pos)
236         if pool[pos.x] and pool[pos.x][pos.y] and pool[pos.x][pos.y][pos.z] then
237                 temp_pool = pool[pos.x][pos.y][pos.z]
238                 for _,order in pairs(order) do
239                         n_pos = add_vec(pos,order)
240                         if pool[n_pos.x] and pool[n_pos.x][n_pos.y] and pool[n_pos.x][n_pos.y][n_pos.z] then
241                                 temp_pool2 = pool[n_pos.x][n_pos.y][n_pos.z]
242                                 if temp_pool2 then
243                                         if (not temp_pool2.directional_activator and temp_pool2.torch) or 
244                                         (temp_pool2.dust and temp_pool2.dust > 0) or 
245                                         (temp_pool2.torch_directional and vector.equals(temp_pool2.output, pos)) then
246                                                 if activator_table[temp_pool.name].activate then
247                                                         activator_table[temp_pool.name].activate(pos)
248                                                 end
249                                                 return
250                                         end
251                                 end
252                         end
253                 end     
254                 if activator_table[temp_pool.name].deactivate then
255                         activator_table[temp_pool.name].deactivate(pos)
256                 end
257         end
258 end
259
260 -- directional activators
261 local n_pos
262 local temp_pool
263 local temp_pool2
264 local input
265 local ignore
266 local directional_activator = function(pos)
267         
268         ignore = false
269         input = nil
270         temp_pool = nil
271         temp_pool2 = nil
272
273         if not (pool[pos.x] and pool[pos.x][pos.y] and pool[pos.x][pos.y][pos.z]) then return end
274         
275         temp_pool = pool[pos.x][pos.y][pos.z]
276         
277         if not temp_pool then ignore = true end
278
279         if not ignore then
280                 input = temp_pool.input
281         end
282
283         if not input then ignore = true end
284
285         if not ignore then
286                 input = temp_pool.input
287         end
288
289         if not ignore and pool and pool[input.x] and pool[input.x][input.y] and pool[input.x][input.y][input.z] then
290                 temp_pool2 = pool[input.x][input.y][input.z]
291         else
292                 ignore = true
293         end
294
295         if not temp_pool2 then ignore = true end
296
297         if not ignore and ((temp_pool2.dust and temp_pool2.dust > 0) or (temp_pool2.torch and temp_pool2.directional_activator and temp_pool2.dir == temp_pool.dir) or 
298         (not temp_pool2.directional_activator and temp_pool2.torch) or (temp_pool2.capacitor and temp_pool2.capacitor > 0))  then
299                 if activator_table[temp_pool.name].activate then
300                         activator_table[temp_pool.name].activate(pos)
301                         return
302                 end
303                 return
304         end
305
306         if activator_table[temp_pool.name].deactivate then
307                 activator_table[temp_pool.name].deactivate(pos)
308         end
309 end
310
311 --make redstone wire pass on current one level lower than it is
312 local i
313 local index
314 local passed_on_level
315 local x,y,z
316 local function redstone_distribute(pos,power,mem_map,output)
317
318         power = power - 1
319
320         --directional torches
321         if output then
322                 x=output.x
323                 y=output.y
324                 z=output.z
325                 if mem_map.dust[x] and mem_map.dust[x][y] and mem_map.dust[x][y][z] then
326                         if mem_map.dust[x][y][z].dust < power then
327                                 mem_map.dust[x][y][z].dust = power
328                                 redstone_distribute(new_vec(x,y,z),power,mem_map,nil)
329                         end
330                 end
331         else
332                 --redstone and torch
333                 for _,order in pairs(order) do
334                         i = add_vec(pos,order)
335                         x=i.x
336                         y=i.y
337                         z=i.z
338                         if mem_map.dust[x] and mem_map.dust[x][y] and mem_map.dust[x][y][z] then
339                                 if mem_map.dust[x][y][z].dust < power then
340                                         mem_map.dust[x][y][z].dust = power
341                                         redstone_distribute(new_vec(x,y,z),power,mem_map,nil)
342                                 end
343                         end
344                 end
345         end
346         return(mem_map)
347 end
348
349
350 --[[
351                      , 
352                 ,.  | \ 
353                |: \ ; :\ 
354                :' ;\| ::\ 
355                 \ : | `::\ 
356                 _)  |   `:`. 
357               ,' , `.    ;: ; 
358             ,' ;:  ;"'  ,:: |_ 
359            /,   ` .    ;::: |:`-.__ 
360         _,' _o\  ,::.`:' ;  ;   . ' 
361     _,-'           `:.          ;""\, 
362  ,-'                     ,:         `-;, 
363  \,                       ;:           ;--._ 
364   `.______,-,----._     ,' ;:        ,/ ,  ,` 
365          / /,-';'  \     ; `:      ,'/,::.::: 
366        ,',;-'-'_,--;    ;   :.   ,',',;:::::: 
367       ( /___,-'     `.     ;::,,'o/  ,::::::: 
368        `'             )    ;:,'o /  ;"-   -:: 
369                       \__ _,'o ,'         ,:: 
370                          ) `--'       ,..:::: 
371                          ; `.        ,::::::: 
372                           ;  ``::.    ::::::: 
373 ]]-- sic em boy!
374 local i
375 local index
376 local function dust_sniff(pos,mem_map,boundary,single,origin,ignore)
377         if not single then
378                 --print("all position index--")
379                 for _,order in pairs(order) do
380                         i = add_vec(pos,order)
381
382                         if not mem_map[i.x] then mem_map[i.x] = {} end
383                         if not mem_map[i.x][i.y] then mem_map[i.x][i.y] = {} end
384
385                         if not mem_map[i.x][i.y][i.z] then
386                                 if i and boundary and boundary[i.x] and boundary[i.x][i.y] and boundary[i.x][i.y][i.z] then
387                                         index = boundary[i.x][i.y][i.z]
388
389                                         if index.dust then
390
391                                                 mem_map[i.x][i.y][i.z] = true
392
393                                                 if not mem_map.dust[i.x] then mem_map.dust[i.x] = {} end
394                                                 if not mem_map.dust[i.x][i.y] then mem_map.dust[i.x][i.y] = {} end
395
396                                                 mem_map.dust[i.x][i.y][i.z] = index
397
398                                                 dust_sniff(i,mem_map,boundary)
399                                         
400                                         elseif index.torch and index.torch > 1 then
401                                                 if index.torch_directional and vec_equals(pos,index.output) then
402                                                         
403                                                         mem_map[i.x][i.y][i.z] = true
404
405                                                         if not mem_map.torch[i.x] then mem_map.torch[i.x] = {} end
406                                                         if not mem_map.torch[i.x][i.y] then mem_map.torch[i.x][i.y] = {} end
407
408                                                         mem_map.torch[i.x][i.y][i.z] = index
409
410                                                         
411                                                 elseif not index.torch_directional then
412
413                                                         mem_map[i.x][i.y][i.z] = true
414
415                                                         if not mem_map.torch[i.x] then mem_map.torch[i.x] = {} end
416                                                         if not mem_map.torch[i.x][i.y] then mem_map.torch[i.x][i.y] = {} end
417
418                                                         mem_map.torch[i.x][i.y][i.z] = index
419                                                 end
420                                         end
421
422                                         if index.activator then
423                                                 mem_map[i.x][i.y][i.z] = true
424
425                                                 if not mem_map.activator[i.x] then mem_map.activator[i.x] = {} end
426                                                 if not mem_map.activator[i.x][i.y] then mem_map.activator[i.x][i.y] = {} end
427
428                                                 mem_map.activator[i.x][i.y][i.z] = index
429                                         elseif index.directional_activator and vec_equals(pos,index.input) then
430
431                                                 mem_map[i.x][i.y][i.z] = true
432
433                                                 if not mem_map.activator[i.x] then mem_map.activator[i.x] = {} end
434                                                 if not mem_map.activator[i.x][i.y] then mem_map.activator[i.x][i.y] = {} end
435
436                                                 mem_map.activator[i.x][i.y][i.z] = index
437                                         end
438                                 end
439                         end
440                 end
441         else
442                 --print("single position index")
443                 
444                 i = pos
445
446
447                 if not mem_map[i.x] then mem_map[i.x] = {} end
448                 if not mem_map[i.x][i.y] then mem_map[i.x][i.y] = {} end
449
450                 if not mem_map[i.x][i.y][i.z] then
451                         if i and boundary and boundary[i.x] and boundary[i.x][i.y] and boundary[i.x][i.y][i.z] then
452                                 index = boundary[i.x][i.y][i.z]
453                                 if index.dust then
454
455                                         mem_map[i.x][i.y][i.z] = true
456
457                                         if not mem_map.dust[i.x] then mem_map.dust[i.x] = {} end
458                                         if not mem_map.dust[i.x][i.y] then mem_map.dust[i.x][i.y] = {} end
459
460                                         mem_map.dust[i.x][i.y][i.z] = index
461
462                                         dust_sniff(i,mem_map,boundary)
463                                 
464                                 elseif index.torch and index.torch > 1 then
465                                         if index.torch_directional and (vec_equals(origin,index.output) or ignore) then
466                                                 
467                                                 mem_map[i.x][i.y][i.z] = true
468
469                                                 if not mem_map.torch[i.x] then mem_map.torch[i.x] = {} end
470                                                 if not mem_map.torch[i.x][i.y] then mem_map.torch[i.x][i.y] = {} end
471
472                                                 mem_map.torch[i.x][i.y][i.z] = index
473
474                                                 
475                                         elseif not index.torch_directional then
476
477                                                 mem_map[i.x][i.y][i.z] = true
478
479                                                 if not mem_map.torch[i.x] then mem_map.torch[i.x] = {} end
480                                                 if not mem_map.torch[i.x][i.y] then mem_map.torch[i.x][i.y] = {} end
481
482                                                 mem_map.torch[i.x][i.y][i.z] = index
483                                         end
484                                 end
485
486                                 if index.activator then
487                                         mem_map[i.x][i.y][i.z] = true
488
489                                         if not mem_map.activator[i.x] then mem_map.activator[i.x] = {} end
490                                         if not mem_map.activator[i.x][i.y] then mem_map.activator[i.x][i.y] = {} end
491
492                                         mem_map.activator[i.x][i.y][i.z] = index
493                                 elseif index.directional_activator and (vec_equals(origin,index.input) or ignore) then
494
495                                         mem_map[i.x][i.y][i.z] = true
496
497                                         if not mem_map.activator[i.x] then mem_map.activator[i.x] = {} end
498                                         if not mem_map.activator[i.x][i.y] then mem_map.activator[i.x][i.y] = {} end
499
500                                         mem_map.activator[i.x][i.y][i.z] = index
501                                 end
502                         end
503                 end
504         end
505         return mem_map
506 end
507
508 --make all power sources push power out
509 local pos
510 local node
511 local power
512 local boundary
513 local dust_detected
514 local dust_map
515 local pos3
516 local temp_pool3
517 local directional
518 local function calculate(pos,is_capacitor)
519         if not is_capacitor then
520                 boundary = create_boundary_box(pos)
521                 dust_map = {}
522
523                 dust_map.dust = {}
524                 dust_map.torch = {}
525                 dust_map.activator = {}
526
527                 dust_detected = false
528
529                 directional = false
530
531                 if boundary[pos.x] and boundary[pos.x][pos.y] and boundary[pos.x][pos.y][pos.z] then
532                         if boundary[pos.x][pos.y][pos.z].torch_directional or boundary[pos.x][pos.y][pos.z].directional_activator then
533                                 directional = true
534                         end
535                 end
536
537                 -- sniff all possible dust within boundaries
538                 if not directional then
539                         dust_sniff(pos,dust_map,boundary)
540                         for _,pos2 in pairs(order) do
541                                 pos3 = add_vec(pos,pos2)
542                                 if boundary[pos3.x] and boundary[pos3.x][pos3.y] and boundary[pos3.x][pos3.y][pos3.z] and
543                                         not (dust_map[pos3.x] and dust_map[pos3.x][pos3.y] and dust_map[pos3.x][pos3.y][pos3.z]) then
544                                         temp_pool3 = boundary[pos3.x][pos3.y][pos3.z]
545                                         if temp_pool3.dust then
546                                                 dust_sniff(pos3,dust_map,boundary)
547                                         end
548                                 end
549                         end
550                 else
551                         dust_sniff(pos,dust_map,boundary,true,pos,true)
552
553                         local input = boundary[pos.x][pos.y][pos.z].input
554                         local output = boundary[pos.x][pos.y][pos.z].output
555
556                         if input and boundary[input.x] and boundary[input.x][input.y] and boundary[input.x][input.y][input.z] then
557                                 dust_sniff(input,dust_map,boundary,true,pos)
558                         end
559                         if output and boundary[output.x] and boundary[output.x][output.y] and boundary[output.x][output.y][output.z] then
560                                 dust_sniff(output,dust_map,boundary,true,pos)
561                         end
562                 end
563                 --do torches
564                 for x,datax in pairs(dust_map.torch) do
565                         for y,datay in pairs(datax) do
566                                 for z,data in pairs(datay) do
567                                         if data.torch then
568                                                 if data.torch_directional then
569                                                         redstone_distribute(new_vec(x,y,z),data.torch,dust_map,data.output)
570                                                 else
571                                                         redstone_distribute(new_vec(x,y,z),data.torch,dust_map)
572                                                 end
573                                         end
574                                 end
575                         end
576                 end
577
578                 --set dust, set pool memory
579                 for x,datax in pairs(dust_map.dust) do
580                         for y,datay in pairs(datax) do
581                                 for z,data in pairs(datay) do
582                                         if data.dust and data.dust ~= data.origin then
583                                                 swap_node(new_vec(x,y,z),{name="redstone:dust_"..data.dust})
584                                                 data_injection(new_vec(x,y,z),data)
585                                         end
586                                 end
587                         end
588                 end
589                 
590                 --activators
591                 --this must be run at the end
592                 for x,datax in pairs(dust_map.activator) do
593                         for y,datay in pairs(datax) do
594                                 for z,data in pairs(datay) do
595                                         if data.directional_activator then
596                                                 directional_activator(new_vec(x,y,z))
597                                         elseif data.activator then
598                                                 non_directional_activator(new_vec(x,y,z))
599                                         end
600                                 end
601                         end
602                 end
603         else
604                 capacitor_sniff(pos)
605         end
606 end
607
608
609 function redstone.inject(pos,data)
610         data_injection(pos,data)
611 end
612
613
614 local recursion_check = {}
615 local bad_node
616 function redstone.update(pos,is_capacitor)
617         local s_pos = minetest.serialize(pos)
618         if not recursion_check[s_pos] then
619                 recursion_check[s_pos] = 0
620         end
621         recursion_check[s_pos] = recursion_check[s_pos] + 1
622         if recursion_check[s_pos] > 25 then
623                 --print(recursion_check[s_pos])
624                 minetest.after(0,function()
625                         bad_node = minetest.get_node(pos).name
626                         bad_node = minetest.get_node_drops(bad_node, "main:rubypick")
627                         for _,nodey in pairs(bad_node) do
628                                 minetest.throw_item(pos,nodey)
629                         end
630                         minetest.remove_node(pos)
631                         data_injection(pos,nil)
632                         redstone.update(pos)
633                 end)
634                 return
635         end
636
637         calculate(pos,is_capacitor)
638 end
639
640
641 local level
642 local pos2
643 local power
644 local max
645 local function player_detector_calculation()
646         for _,pos in pairs(player_detection_table) do
647                 level = pool[pos.x][pos.y][pos.z].torch
648                 max = 0
649                 for _,player in ipairs(minetest.get_connected_players()) do
650                         pos2 = player:get_pos()
651                         power = floor(17-vector_distance(pos2,pos))
652                         if power > 16 then
653                                 power = 16
654                         elseif power < 0 then
655                                 power = 0
656                         end
657
658                         if power > max then
659                                 max = power
660                         end
661                 end
662
663                 if max ~= level then
664                         swap_node(pos,{name="redstone:player_detector_"..max})
665                         redstone.inject(pos,{
666                                 name = "redstone:player_detector_"..max,
667                                 torch = max,
668                         })
669                         redstone.update(pos)
670                 end
671         end
672 end
673
674 minetest.register_globalstep(function()
675         player_detector_calculation()
676         recursion_check = {}
677 end)
678
679
680 ----------------------------------------------------------------------------
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714 minetest.register_craftitem("redstone:dust", {
715         description = "Redstone Dust",
716         inventory_image = "redstone_dust_item.png",
717         wield_image = "redstone_dust_item.png",
718         wield_scale = {x = 1, y = 1, z = 1 + 1/16},
719         liquids_pointable = false,
720         on_place = function(itemstack, placer, pointed_thing)
721                 if not pointed_thing.type == "node" then
722                         return
723                 end             
724                 local sneak = placer:get_player_control().sneak
725                 local noddef = registered_nodes[get_node(pointed_thing.under).name]
726                 if not sneak and noddef.on_rightclick then
727                         minetest.item_place(itemstack, placer, pointed_thing)
728                         return
729                 end
730                 
731                 local _,worked = minetest.item_place(ItemStack("redstone:dust_0"), placer, pointed_thing)
732                 if worked then
733                         itemstack:take_item()
734                         return(itemstack)
735                 end
736         end,
737 })
738
739 --15 power levels 15 being the highest
740 for i = 0,15 do
741
742         local color = floor(255 * (i/15))
743         
744         minetest.register_node("redstone:dust_"..i,{
745                 description = "Redstone Dust",
746                 wield_image = "redstone_dust_item.png",
747                 tiles = {
748                         "redstone_dust_main.png^[colorize:red:"..color, "redstone_turn.png^[colorize:red:"..color,
749                         "redstone_t.png^[colorize:red:"..color, "redstone_cross.png^[colorize:red:"..color
750                 },
751                 power=i,
752                 drawtype = "raillike",
753                 paramtype = "light",
754                 sunlight_propagates = true,
755                 is_ground_content = false,
756                 walkable = false,
757                 node_placement_prediction = "",
758                 selection_box = {
759                         type = "fixed",
760                         fixed = {-1/2, -1/2, -1/2, 1/2, -1/2+1/16, 1/2},
761                 },
762                 sounds = main.stoneSound(),
763                 groups={dig_immediate=1,attached_node=1,redstone_dust=1,redstone=1,redstone_power=i},
764                 drop="redstone:dust",
765                 on_construct = function(pos)
766                         data_injection(pos,{dust=i})
767                         calculate(pos)
768                 end,
769                 after_destruct = function(pos)
770                         data_injection(pos,nil)
771                         calculate(pos)
772                 end,
773                 connects_to = {"group:redstone"},
774         })
775
776         minetest.register_lbm({
777         name = "redstone:"..i,
778                 nodenames = {"redstone:dust_"..i},
779                 run_at_every_load = true,
780         action = function(pos)
781                         data_injection(pos,{dust=i})
782         end,
783     })
784 end