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