]> git.lizzy.rs Git - Crafter.git/blob - mods/redstone/init.lua
f9875bf8f8ec7efc9e01065440565b4b49f53418
[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                 if temp_pool then
239                         for _,order in pairs(order) do
240                                 n_pos = add_vec(pos,order)
241                                 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
242                                         temp_pool2 = pool[n_pos.x][n_pos.y][n_pos.z]
243                                         if temp_pool2 then
244                                                 if (not temp_pool2.directional_activator and temp_pool2.torch) or 
245                                                 (temp_pool2.dust and temp_pool2.dust > 0) or 
246                                                 (temp_pool2.torch_directional and vector.equals(temp_pool2.output, pos)) then
247                                                         if activator_table[temp_pool.name] and activator_table[temp_pool.name].activate then
248                                                                 activator_table[temp_pool.name].activate(pos)
249                                                         end
250                                                         return
251                                                 end
252                                         end
253                                 end
254                         end     
255                         if activator_table[temp_pool.name] and activator_table[temp_pool.name].deactivate then
256                                 activator_table[temp_pool.name].deactivate(pos)
257                         end
258                 end
259         end
260 end
261
262 -- directional activators
263 local n_pos
264 local temp_pool
265 local temp_pool2
266 local input
267 local ignore
268 local directional_activator = function(pos)
269         
270         ignore = false
271         input = nil
272         temp_pool = nil
273         temp_pool2 = nil
274
275         if not (pool[pos.x] and pool[pos.x][pos.y] and pool[pos.x][pos.y][pos.z]) then return end
276         
277         temp_pool = pool[pos.x][pos.y][pos.z]
278         
279         if not temp_pool then ignore = true end
280
281         if not ignore then
282                 input = temp_pool.input
283         end
284
285         if not input then ignore = true end
286
287         if not ignore then
288                 input = temp_pool.input
289         end
290
291         if not ignore and pool and pool[input.x] and pool[input.x][input.y] and pool[input.x][input.y][input.z] then
292                 temp_pool2 = pool[input.x][input.y][input.z]
293         else
294                 ignore = true
295         end
296
297         if not temp_pool2 then ignore = true end
298
299         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 
300         (not temp_pool2.directional_activator and temp_pool2.torch) or (temp_pool2.capacitor and temp_pool2.capacitor > 0))  then
301                 if activator_table[temp_pool.name].activate then
302                         activator_table[temp_pool.name].activate(pos)
303                         return
304                 end
305                 return
306         end
307
308         if activator_table[temp_pool.name].deactivate then
309                 activator_table[temp_pool.name].deactivate(pos)
310         end
311 end
312
313 --make redstone wire pass on current one level lower than it is
314 local i
315 local index
316 local passed_on_level
317 local x,y,z
318 local function redstone_distribute(pos,power,mem_map,output)
319
320         power = power - 1
321
322         --directional torches
323         if output then
324                 x=output.x
325                 y=output.y
326                 z=output.z
327                 if mem_map.dust[x] and mem_map.dust[x][y] and mem_map.dust[x][y][z] then
328                         if mem_map.dust[x][y][z].dust < power then
329                                 mem_map.dust[x][y][z].dust = power
330                                 redstone_distribute(new_vec(x,y,z),power,mem_map,nil)
331                         end
332                 end
333         else
334                 --redstone and torch
335                 for _,order in pairs(order) do
336                         i = add_vec(pos,order)
337                         x=i.x
338                         y=i.y
339                         z=i.z
340                         if mem_map.dust[x] and mem_map.dust[x][y] and mem_map.dust[x][y][z] then
341                                 if mem_map.dust[x][y][z].dust < power then
342                                         mem_map.dust[x][y][z].dust = power
343                                         redstone_distribute(new_vec(x,y,z),power,mem_map,nil)
344                                 end
345                         end
346                 end
347         end
348         return(mem_map)
349 end
350
351
352 --[[
353                      , 
354                 ,.  | \ 
355                |: \ ; :\ 
356                :' ;\| ::\ 
357                 \ : | `::\ 
358                 _)  |   `:`. 
359               ,' , `.    ;: ; 
360             ,' ;:  ;"'  ,:: |_ 
361            /,   ` .    ;::: |:`-.__ 
362         _,' _o\  ,::.`:' ;  ;   . ' 
363     _,-'           `:.          ;""\, 
364  ,-'                     ,:         `-;, 
365  \,                       ;:           ;--._ 
366   `.______,-,----._     ,' ;:        ,/ ,  ,` 
367          / /,-';'  \     ; `:      ,'/,::.::: 
368        ,',;-'-'_,--;    ;   :.   ,',',;:::::: 
369       ( /___,-'     `.     ;::,,'o/  ,::::::: 
370        `'             )    ;:,'o /  ;"-   -:: 
371                       \__ _,'o ,'         ,:: 
372                          ) `--'       ,..:::: 
373                          ; `.        ,::::::: 
374                           ;  ``::.    ::::::: 
375 ]]-- sic em boy!
376 local i
377 local index
378 local function dust_sniff(pos,mem_map,boundary,single,origin,ignore)
379         if not single then
380                 --print("all position index--")
381                 for _,order in pairs(order) do
382                         i = add_vec(pos,order)
383
384                         if not mem_map[i.x] then mem_map[i.x] = {} end
385                         if not mem_map[i.x][i.y] then mem_map[i.x][i.y] = {} end
386
387                         if not mem_map[i.x][i.y][i.z] then
388                                 if i and boundary and boundary[i.x] and boundary[i.x][i.y] and boundary[i.x][i.y][i.z] then
389                                         index = boundary[i.x][i.y][i.z]
390
391                                         if index.dust then
392
393                                                 mem_map[i.x][i.y][i.z] = true
394
395                                                 if not mem_map.dust[i.x] then mem_map.dust[i.x] = {} end
396                                                 if not mem_map.dust[i.x][i.y] then mem_map.dust[i.x][i.y] = {} end
397
398                                                 mem_map.dust[i.x][i.y][i.z] = index
399
400                                                 dust_sniff(i,mem_map,boundary)
401                                         
402                                         elseif index.torch and index.torch > 1 then
403                                                 if index.torch_directional and vec_equals(pos,index.output) then
404                                                         
405                                                         mem_map[i.x][i.y][i.z] = true
406
407                                                         if not mem_map.torch[i.x] then mem_map.torch[i.x] = {} end
408                                                         if not mem_map.torch[i.x][i.y] then mem_map.torch[i.x][i.y] = {} end
409
410                                                         mem_map.torch[i.x][i.y][i.z] = index
411
412                                                         
413                                                 elseif not index.torch_directional then
414
415                                                         mem_map[i.x][i.y][i.z] = true
416
417                                                         if not mem_map.torch[i.x] then mem_map.torch[i.x] = {} end
418                                                         if not mem_map.torch[i.x][i.y] then mem_map.torch[i.x][i.y] = {} end
419
420                                                         mem_map.torch[i.x][i.y][i.z] = index
421                                                 end
422                                         end
423
424                                         if index.activator then
425                                                 mem_map[i.x][i.y][i.z] = true
426
427                                                 if not mem_map.activator[i.x] then mem_map.activator[i.x] = {} end
428                                                 if not mem_map.activator[i.x][i.y] then mem_map.activator[i.x][i.y] = {} end
429
430                                                 mem_map.activator[i.x][i.y][i.z] = index
431                                         elseif index.directional_activator and vec_equals(pos,index.input) then
432
433                                                 mem_map[i.x][i.y][i.z] = true
434
435                                                 if not mem_map.activator[i.x] then mem_map.activator[i.x] = {} end
436                                                 if not mem_map.activator[i.x][i.y] then mem_map.activator[i.x][i.y] = {} end
437
438                                                 mem_map.activator[i.x][i.y][i.z] = index
439                                         end
440                                 end
441                         end
442                 end
443         else
444                 --print("single position index")
445                 
446                 i = pos
447
448
449                 if not mem_map[i.x] then mem_map[i.x] = {} end
450                 if not mem_map[i.x][i.y] then mem_map[i.x][i.y] = {} end
451
452                 if not mem_map[i.x][i.y][i.z] then
453                         if i and boundary and boundary[i.x] and boundary[i.x][i.y] and boundary[i.x][i.y][i.z] then
454                                 index = boundary[i.x][i.y][i.z]
455                                 if index.dust then
456
457                                         mem_map[i.x][i.y][i.z] = true
458
459                                         if not mem_map.dust[i.x] then mem_map.dust[i.x] = {} end
460                                         if not mem_map.dust[i.x][i.y] then mem_map.dust[i.x][i.y] = {} end
461
462                                         mem_map.dust[i.x][i.y][i.z] = index
463
464                                         dust_sniff(i,mem_map,boundary)
465                                 
466                                 elseif index.torch and index.torch > 1 then
467                                         if index.torch_directional and (vec_equals(origin,index.output) or ignore) then
468                                                 
469                                                 mem_map[i.x][i.y][i.z] = true
470
471                                                 if not mem_map.torch[i.x] then mem_map.torch[i.x] = {} end
472                                                 if not mem_map.torch[i.x][i.y] then mem_map.torch[i.x][i.y] = {} end
473
474                                                 mem_map.torch[i.x][i.y][i.z] = index
475
476                                                 
477                                         elseif not index.torch_directional then
478
479                                                 mem_map[i.x][i.y][i.z] = true
480
481                                                 if not mem_map.torch[i.x] then mem_map.torch[i.x] = {} end
482                                                 if not mem_map.torch[i.x][i.y] then mem_map.torch[i.x][i.y] = {} end
483
484                                                 mem_map.torch[i.x][i.y][i.z] = index
485                                         end
486                                 end
487
488                                 if index.activator then
489                                         mem_map[i.x][i.y][i.z] = true
490
491                                         if not mem_map.activator[i.x] then mem_map.activator[i.x] = {} end
492                                         if not mem_map.activator[i.x][i.y] then mem_map.activator[i.x][i.y] = {} end
493
494                                         mem_map.activator[i.x][i.y][i.z] = index
495                                 elseif index.directional_activator and (vec_equals(origin,index.input) or ignore) then
496
497                                         mem_map[i.x][i.y][i.z] = true
498
499                                         if not mem_map.activator[i.x] then mem_map.activator[i.x] = {} end
500                                         if not mem_map.activator[i.x][i.y] then mem_map.activator[i.x][i.y] = {} end
501
502                                         mem_map.activator[i.x][i.y][i.z] = index
503                                 end
504                         end
505                 end
506         end
507         return mem_map
508 end
509
510 --make all power sources push power out
511 local pos
512 local node
513 local power
514 local boundary
515 local dust_detected
516 local dust_map
517 local pos3
518 local temp_pool3
519 local directional
520 local function calculate(pos,is_capacitor)
521         if not is_capacitor then
522                 boundary = create_boundary_box(pos)
523                 dust_map = {}
524
525                 dust_map.dust = {}
526                 dust_map.torch = {}
527                 dust_map.activator = {}
528
529                 dust_detected = false
530
531                 directional = false
532
533                 if boundary[pos.x] and boundary[pos.x][pos.y] and boundary[pos.x][pos.y][pos.z] then
534                         if boundary[pos.x][pos.y][pos.z].torch_directional or boundary[pos.x][pos.y][pos.z].directional_activator then
535                                 directional = true
536                         end
537                 end
538
539                 -- sniff all possible dust within boundaries
540                 if not directional then
541                         dust_sniff(pos,dust_map,boundary)
542                         for _,pos2 in pairs(order) do
543                                 pos3 = add_vec(pos,pos2)
544                                 if boundary[pos3.x] and boundary[pos3.x][pos3.y] and boundary[pos3.x][pos3.y][pos3.z] and
545                                         not (dust_map[pos3.x] and dust_map[pos3.x][pos3.y] and dust_map[pos3.x][pos3.y][pos3.z]) then
546                                         temp_pool3 = boundary[pos3.x][pos3.y][pos3.z]
547                                         if temp_pool3.dust then
548                                                 dust_sniff(pos3,dust_map,boundary)
549                                         end
550                                 end
551                         end
552                 else
553                         dust_sniff(pos,dust_map,boundary,true,pos,true)
554
555                         local input = boundary[pos.x][pos.y][pos.z].input
556                         local output = boundary[pos.x][pos.y][pos.z].output
557
558                         if input and boundary[input.x] and boundary[input.x][input.y] and boundary[input.x][input.y][input.z] then
559                                 dust_sniff(input,dust_map,boundary,true,pos)
560                         end
561                         if output and boundary[output.x] and boundary[output.x][output.y] and boundary[output.x][output.y][output.z] then
562                                 dust_sniff(output,dust_map,boundary,true,pos)
563                         end
564                 end
565                 --do torches
566                 for x,datax in pairs(dust_map.torch) do
567                         for y,datay in pairs(datax) do
568                                 for z,data in pairs(datay) do
569                                         if data.torch then
570                                                 if data.torch_directional then
571                                                         redstone_distribute(new_vec(x,y,z),data.torch,dust_map,data.output)
572                                                 else
573                                                         redstone_distribute(new_vec(x,y,z),data.torch,dust_map)
574                                                 end
575                                         end
576                                 end
577                         end
578                 end
579
580                 --set dust, set pool memory
581                 for x,datax in pairs(dust_map.dust) do
582                         for y,datay in pairs(datax) do
583                                 for z,data in pairs(datay) do
584                                         if data.dust and data.dust ~= data.origin then
585                                                 swap_node(new_vec(x,y,z),{name="redstone:dust_"..data.dust})
586                                                 data_injection(new_vec(x,y,z),data)
587                                         end
588                                 end
589                         end
590                 end
591                 
592                 --activators
593                 --this must be run at the end
594                 for x,datax in pairs(dust_map.activator) do
595                         for y,datay in pairs(datax) do
596                                 for z,data in pairs(datay) do
597                                         if data.directional_activator then
598                                                 directional_activator(new_vec(x,y,z))
599                                         elseif data.activator then
600                                                 non_directional_activator(new_vec(x,y,z))
601                                         end
602                                 end
603                         end
604                 end
605         else
606                 capacitor_sniff(pos)
607         end
608 end
609
610
611 function redstone.inject(pos,data)
612         data_injection(pos,data)
613 end
614
615
616 local recursion_check = {}
617 local bad_node
618 function redstone.update(pos,is_capacitor)
619         local s_pos = minetest.serialize(pos)
620         if not recursion_check[s_pos] then
621                 recursion_check[s_pos] = 0
622         end
623         recursion_check[s_pos] = recursion_check[s_pos] + 1
624         if recursion_check[s_pos] > 25 then
625                 --print(recursion_check[s_pos])
626                 minetest.after(0,function()
627                         bad_node = minetest.get_node(pos).name
628                         bad_node = minetest.get_node_drops(bad_node, "main:rubypick")
629                         for _,nodey in pairs(bad_node) do
630                                 minetest.throw_item(pos,nodey)
631                         end
632                         minetest.remove_node(pos)
633                         data_injection(pos,nil)
634                         redstone.update(pos)
635                 end)
636                 return
637         end
638
639         calculate(pos,is_capacitor)
640 end
641
642
643 local level
644 local pos2
645 local power
646 local max
647 local function player_detector_calculation()
648         for _,pos in pairs(player_detection_table) do
649                 level = pool[pos.x][pos.y][pos.z].torch
650                 max = 0
651                 for _,player in ipairs(minetest.get_connected_players()) do
652                         pos2 = player:get_pos()
653                         power = floor(17-vector_distance(pos2,pos))
654                         if power > 16 then
655                                 power = 16
656                         elseif power < 0 then
657                                 power = 0
658                         end
659
660                         if power > max then
661                                 max = power
662                         end
663                 end
664
665                 if max ~= level then
666                         swap_node(pos,{name="redstone:player_detector_"..max})
667                         redstone.inject(pos,{
668                                 name = "redstone:player_detector_"..max,
669                                 torch = max,
670                         })
671                         redstone.update(pos)
672                 end
673         end
674 end
675
676 minetest.register_globalstep(function()
677         player_detector_calculation()
678         recursion_check = {}
679 end)
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
715
716 minetest.register_craftitem("redstone:dust", {
717         description = "Redstone Dust",
718         inventory_image = "redstone_dust_item.png",
719         wield_image = "redstone_dust_item.png",
720         wield_scale = {x = 1, y = 1, z = 1 + 1/16},
721         liquids_pointable = false,
722         on_place = function(itemstack, placer, pointed_thing)
723                 if not pointed_thing.type == "node" then
724                         return
725                 end             
726                 local sneak = placer:get_player_control().sneak
727                 local noddef = registered_nodes[get_node(pointed_thing.under).name]
728                 if not sneak and noddef.on_rightclick then
729                         minetest.item_place(itemstack, placer, pointed_thing)
730                         return
731                 end
732                 
733                 local _,worked = minetest.item_place(ItemStack("redstone:dust_0"), placer, pointed_thing)
734                 if worked then
735                         itemstack:take_item()
736                         return(itemstack)
737                 end
738         end,
739 })
740
741 --15 power levels 15 being the highest
742 for i = 0,15 do
743
744         local color = floor(255 * (i/15))
745         
746         minetest.register_node("redstone:dust_"..i,{
747                 description = "Redstone Dust",
748                 wield_image = "redstone_dust_item.png",
749                 tiles = {
750                         "redstone_dust_main.png^[colorize:red:"..color, "redstone_turn.png^[colorize:red:"..color,
751                         "redstone_t.png^[colorize:red:"..color, "redstone_cross.png^[colorize:red:"..color
752                 },
753                 power=i,
754                 drawtype = "raillike",
755                 paramtype = "light",
756                 sunlight_propagates = true,
757                 is_ground_content = false,
758                 walkable = false,
759                 node_placement_prediction = "",
760                 selection_box = {
761                         type = "fixed",
762                         fixed = {-1/2, -1/2, -1/2, 1/2, -1/2+1/16, 1/2},
763                 },
764                 sounds = main.stoneSound(),
765                 groups={dig_immediate=1,attached_node=1,redstone_dust=1,redstone=1,redstone_power=i},
766                 drop="redstone:dust",
767                 on_construct = function(pos)
768                         data_injection(pos,{dust=i})
769                         calculate(pos)
770                 end,
771                 after_destruct = function(pos)
772                         data_injection(pos,nil)
773                         calculate(pos)
774                 end,
775                 connects_to = {"group:redstone"},
776         })
777
778         minetest.register_lbm({
779         name = "redstone:"..i,
780                 nodenames = {"redstone:dust_"..i},
781                 run_at_every_load = true,
782         action = function(pos)
783                         data_injection(pos,{dust=i})
784         end,
785     })
786 end