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