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