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