]> git.lizzy.rs Git - Crafter.git/blob - mods/redstone/init.lua
2e74c74d49ca774d1c1cf5313f72a404d2bb503a
[Crafter.git] / mods / redstone / init.lua
1 local 
2 minetest,vector,math,table,pairs
3 =
4 minetest,vector,math,table,pairs
5
6 -- minetest class
7 local get_node        = minetest.get_node
8 local get_item_group  = minetest.get_item_group
9 local get_meta        = minetest.get_meta
10 local facedir_to_dir  = minetest.facedir_to_dir
11 local content_id      = minetest.get_name_from_content_id
12 local get_content_id  = minetest.get_content_id
13 local get_voxel_manip = minetest.get_voxel_manip
14 local after           = minetest.after
15 local registered_nodes
16 minetest.register_on_mods_loaded(function()
17         registered_nodes  = minetest.registered_nodes
18 end)
19
20 -- math class
21 local abs   = math.abs
22 local floor = math.floor
23
24 -- vector library
25 local new_vec         = vector.new
26 local add_vec         = vector.add
27 local sub_vec         = vector.subtract
28 local vector_distance = vector.distance
29
30 -- redstone class
31 redstone = {}
32
33 local speed_test
34
35 local r_index = {}
36 local a_index = {}
37
38 local path = minetest.get_modpath("redstone")
39 dofile(path.."/functions.lua")
40 dofile(path.."/wire.lua")
41 dofile(path.."/torch.lua")
42 dofile(path.."/lever.lua")
43 dofile(path.."/button.lua")
44 dofile(path.."/repeater.lua")
45 dofile(path.."/light.lua")
46 dofile(path.."/piston.lua")
47 dofile(path.."/comparator.lua")
48 dofile(path.."/craft.lua")
49 dofile(path.."/ore.lua")
50 dofile(path.."/inverter.lua")
51 dofile(path.."/player_detector.lua")
52 dofile(path.."/space_maker.lua")
53 dofile(path.."/pressure_plate.lua")
54
55
56 --set the data for powered states
57 local get_local_power = function(pos)
58         if not pos then
59                 return
60         end
61         for x = -1,1 do
62         for y = -1,1 do
63         for z = -1,1 do
64                 --index only direct neighbors
65                 if abs(x)+abs(z)+abs(y) == 1 then
66                         --print(get_node(add_vec(new_vec(x,y,z),pos)).name)
67                         if get_item_group(get_node(add_vec(new_vec(x,y,z),pos)).name, "redstone_power") > 0 then
68                                 return(1)
69                         end
70                 end
71         end
72         end
73         end     
74         return(0)
75 end
76
77 local get_powered_state_directional = function(pos)
78         return(get_item_group(get_node(sub_vec(pos,facedir_to_dir(get_node(pos).param2))).name, "redstone_power"))
79 end
80
81 local node
82 local redstone_activate = function(pos,power)
83         after(0,function()
84                 node = get_node(pos).name
85                 if registered_nodes[node].redstone_activation then
86                         registered_nodes[node].redstone_activation(pos)
87                 end
88         end)
89 end
90
91 local node
92 local redstone_deactivate = function(pos,power)
93         after(0,function()
94                 node = get_node(pos).name
95                 if registered_nodes[node].redstone_deactivation then
96                         registered_nodes[node].redstone_deactivation(pos)
97                 end
98         end)
99 end
100
101 --collect all nodes that are local to the modified
102 --node of redstone dust and store in memory
103 local function get_group(i,gotten_group)
104         return(get_item_group(get_node(i).name, gotten_group))
105 end
106
107
108 local localredstone = {}
109
110 localredstone.injector = function(i)
111         if get_node(i).name == "air" then
112                 return
113         end
114
115         if r_index[i.x] and r_index[i.x][i.y] then
116                 if r_index[i.x][i.y][i.z] then
117                         return
118                 end
119         end
120
121         --index dust
122         if get_group(i,"redstone_dust") > 0 then
123                 --add data to both maps
124                 if not r_index[i.x] then r_index[i.x] = {} end
125                 if not r_index[i.x][i.y] then r_index[i.x][i.y] = {} end
126                 r_index[i.x][i.y][i.z] = {dust = true,level = 0}
127                 --the data to the 3d array must be written to memory before this is executed
128                 --or a stack overflow occurs!!!
129                 localredstone.collector(i)
130         end
131         --index power sources
132         if get_group(i,"redstone_torch") > 0 then
133                 if not r_index[i.x] then r_index[i.x] = {} end
134                 if not r_index[i.x][i.y] then r_index[i.x][i.y] = {} end
135                 r_index[i.x][i.y][i.z] = {torch = true,power=get_group(i,"redstone_power")}
136         end     
137         --index directional power sources (Like repeaters/comparators)
138         --only outputs forwards
139         if get_group(i,"torch_directional") > 0 then
140                 if not r_index[i.x] then r_index[i.x] = {} end
141                 if not r_index[i.x][i.y] then r_index[i.x][i.y] = {} end
142                 r_index[i.x][i.y][i.z] = {torch_directional = true, dir = get_node(i).param2 , power = get_group(i,"redstone_power")}
143         end
144         
145         --index directional activators (Like repeaters/comparators)
146         --only accepts input from the back
147         if get_group(i,"redstone_activation_directional") > 0 then
148                 --print("indexing directional")
149                 if not a_index[i.x] then a_index[i.x] = {} end
150                 if not a_index[i.x][i.y] then a_index[i.x][i.y] = {} end
151                 if not a_index[i.x][i.y][i.z] then a_index[i.x][i.y][i.z] = {} end
152
153                 a_index[i.x][i.y][i.z].redstone_activation = true
154                 a_index[i.x][i.y][i.z].directional = true
155         end
156         
157         --index objects that activate
158         if get_group(i,"redstone_activation") > 0 then
159                 if not a_index[i.x] then a_index[i.x] = {} end
160                 if not a_index[i.x][i.y] then a_index[i.x][i.y] = {} end
161                 if not a_index[i.x][i.y][i.z] then a_index[i.x][i.y][i.z] = {} end
162                 a_index[i.x][i.y][i.z].redstone_activation = true
163         end
164
165         --sneaky way to make levers and buttons work
166         if get_meta(i):get_int("redstone_power") > 0 then
167                 if not r_index[i.x] then r_index[i.x] = {} end
168                 if not r_index[i.x][i.y] then r_index[i.x][i.y] = {} end
169                 r_index[i.x][i.y][i.z] = {torch = true,power=9}
170         end
171 end
172
173 localredstone.collector = function(pos)
174         for x = -1,1 do
175         for y = -1,1 do
176         for z = -1,1 do
177                 if abs(x)+abs(z) == 1 then
178                         localredstone.injector(add_vec(pos,new_vec(x,y,z)))
179                 end
180         end
181         end
182         end
183 end
184
185
186 function redstone.collect_info(pos)
187         localredstone.injector(pos)
188         localredstone.collector(pos)
189 end
190
191
192 --check if index table contains items
193 --then execute an update
194 minetest.register_globalstep(function(dtime)
195         --if indexes exist then calculate redstone
196         if (r_index and next(r_index)) or (a_index and next(a_index)) then
197                 --create the old version to help with deactivation calculation
198                 redstone.calculate()
199                 --clear the index to avoid cpu looping wasting processing power
200                 r_index = {}
201                 a_index = {}
202         end
203 end)
204
205 --make all power sources push power out
206 local x_min
207 local x_max
208 local y_min
209 local y_max
210 local z_min
211 local z_max
212 local initial_check
213
214
215 local pos
216 local node
217 local power
218 function redstone.calculate()
219         speed_test = minetest.get_us_time()/1000000
220
221         --pathfind through memory map   
222         for x,index_x in pairs(r_index) do
223                 for y,index_y in pairs(index_x) do
224                         for z,data in pairs(index_y) do
225                                 --allow data values for torches
226                                 if data.torch then
227                                         redstone.pathfind(new_vec(x,y,z),data.power)
228                                         r_index[x][y][z] = nil
229                                 elseif data.torch_directional then
230                                         redstone.pathfind(new_vec(x,y,z),data.power,data.dir)
231                                         r_index[x][y][z] = nil
232                                 end
233                         end
234                 end
235         end
236         
237         print("total torch calc time:"..minetest.get_us_time()/1000000-speed_test)
238
239
240
241         --reassemble the table into a position list minetest can understand
242         --run through and set dust
243         for x,datax in pairs(r_index) do
244                 for y,datay in pairs(datax) do
245                         for z,index in pairs(datay) do
246                                 --print(get_node(new_vec(x,y,z)).name)
247                                 if index and index.dust then
248                                         minetest.set_node(new_vec(x,y,z),{name="redstone:dust_"..index.level})
249                                 end
250                         end
251                 end
252         end
253
254         for x,datax in pairs(a_index) do
255                 for y,datay in pairs(datax) do
256                         for z,index in pairs(datay) do
257                                 --directional activators
258                                 if index.directional == true then
259                                         power = get_powered_state_directional(new_vec(x,y,z))
260                                         if power then
261                                                 if power > 0 then
262                                                         redstone_activate(new_vec(x,y,z),power)
263                                                 elseif power == 0 then
264                                                         redstone_deactivate(new_vec(x,y,z),power)
265                                                 end
266                                         end
267                                 --non directional activators
268                                 else
269                                         power = get_local_power(new_vec(x,y,z))
270                                         if power then
271                                                 if power > 0 then
272                                                         redstone_activate(new_vec(x,y,z),power)
273                                                 elseif power == 0 then
274                                                         redstone_deactivate(new_vec(x,y,z),power)
275                                                 end
276                                         end
277                                 end
278                         end
279                 end
280         end
281 end
282
283 --make redstone wire pass on current one level lower than it is
284 local i
285 local index
286 local passed_on_level
287 local function redstone_pathfinder(source,source_level,direction)
288         --directional torches
289
290         if direction then
291                 --print("starting direction")
292                 i = add_vec(source,facedir_to_dir(direction))
293                 if r_index and r_index[i.x] and r_index[i.x][i.y] and r_index[i.x][i.y][i.z] then
294                         index = r_index[i.x][i.y][i.z]
295                         --dust
296                         if index.dust  then
297                                 passed_on_level = source_level - 1
298                                 if passed_on_level > 0 then
299                                         r_index[i.x][i.y][i.z].level = passed_on_level
300                                         redstone_pathfinder(i,passed_on_level,nil,origin)
301                                 end
302                         end
303                 end
304         else
305                 --redstone and torch
306                 for x = -1,1 do
307                 for y = -1,1 do
308                 for z = -1,1 do
309                         if abs(x)+abs(z) == 1 then
310                                 i = add_vec(source,new_vec(x,y,z))
311                                 if r_index and r_index[i.x] and r_index[i.x][i.y] and r_index[i.x][i.y][i.z] then
312                                         index = r_index[i.x][i.y][i.z]                                  
313                                         if index.dust  then
314                                                 passed_on_level = source_level - 1
315                                                 if passed_on_level > 0 and index.level < source_level then
316                                                         r_index[i.x][i.y][i.z].level = passed_on_level
317                                                         redstone_pathfinder(i,passed_on_level,nil)
318                                                 end
319                                         end
320                                 end
321                         end
322                 end
323                 end
324                 end
325         end
326 end
327 function redstone.pathfind(source,source_level,direction)
328         redstone_pathfinder(source,source_level,direction)
329 end
330
331
332
333
334
335
336
337
338 ----------------------------------------------------------------------------
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372 minetest.register_craftitem("redstone:dust", {
373         description = "Redstone Dust",
374         inventory_image = "redstone_dust_item.png",
375         wield_image = "redstone_dust_item.png",
376         wield_scale = {x = 1, y = 1, z = 1 + 1/16},
377         liquids_pointable = false,
378         on_place = function(itemstack, placer, pointed_thing)
379                 if not pointed_thing.type == "node" then
380                         return
381                 end             
382                 local sneak = placer:get_player_control().sneak
383                 local noddef = registered_nodes[get_node(pointed_thing.under).name]
384                 if not sneak and noddef.on_rightclick then
385                         minetest.item_place(itemstack, placer, pointed_thing)
386                         return
387                 end
388                 
389                 local _,worked = minetest.item_place(ItemStack("redstone:dust_0"), placer, pointed_thing)
390                 if worked then
391                         itemstack:take_item()
392                         return(itemstack)
393                 end
394
395
396                         --minetest.add_node(pointed_thing.above, {name="redstone:dust_0"})
397                         --itemstack:take_item(1)
398                         --minetest.sound_play("stone", {pos=pointed_thing.above})
399                         --return(itemstack)
400                 --end
401         end,
402 })
403
404 --8 power levels 8 being the highest
405 local color = 0
406 for i = 0,8 do
407         local coloring = floor(color)
408         minetest.register_node("redstone:dust_"..i,{
409                 description = "Redstone Dust",
410                 wield_image = "redstone_dust_item.png",
411                 tiles = {
412                         "redstone_dust_main.png^[colorize:red:"..coloring, "redstone_turn.png^[colorize:red:"..coloring,
413                         "redstone_t.png^[colorize:red:"..coloring, "redstone_cross.png^[colorize:red:"..coloring
414                 },
415                 power=i,
416                 drawtype = "raillike",
417                 paramtype = "light",
418                 sunlight_propagates = true,
419                 is_ground_content = false,
420                 walkable = false,
421                 node_placement_prediction = "",
422                 selection_box = {
423                         type = "fixed",
424                         fixed = {-1/2, -1/2, -1/2, 1/2, -1/2+1/16, 1/2},
425                 },
426                 sounds = main.stoneSound(),
427                 groups={dig_immediate=1,attached_node=1,redstone_dust=1,redstone=1,redstone_power=i},
428                 drop="redstone:dust",
429                 on_construct = function(pos)
430                         redstone.collect_info(pos)
431                 end,
432                 after_destruct = function(pos)
433                         --redstone.remove(pos,registered_nodes[get_node(pos).name].power)
434                         redstone.collect_info(pos)
435                 end,
436                 connects_to = {"group:redstone"},
437         })
438         color= color +31.875
439 end