]> git.lizzy.rs Git - Crafter.git/blob - mods/redstone/init.lua
c7cc7f010886b425d16dddc02ae10e3036a9be7f
[Crafter.git] / mods / redstone / init.lua
1 local 
2 minetest,vector,math,table,pairs,next
3 =
4 minetest,vector,math,table,pairs,next
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
16 local swap_node       = minetest.swap_node
17 local registered_nodes
18 minetest.register_on_mods_loaded(function()
19         registered_nodes  = minetest.registered_nodes
20 end)
21
22 -- math class
23 local abs   = math.abs
24 local floor = math.floor
25
26 -- vector library
27 local new_vec         = vector.new
28 local add_vec         = vector.add
29 local sub_vec         = vector.subtract
30 local vector_distance = vector.distance
31
32 --this is written out manually so that
33 --math.abs is not needed
34 local order = {
35         {x=1, y=0, z=0}, {x=-1, y=0, z= 0},
36         {x=0, y=0, z=1}, {x= 0, y=0, z=-1},
37
38         {x=0, y=1, z=0}, {x= 0, y=-1, z=0},
39
40         {x=1, y=1, z=0}, {x=-1, y=1, z= 0},
41         {x=0, y=1, z=1}, {x= 0, y=1, z=-1},
42
43         {x=1, y=-1, z=0}, {x=-1, y=-1, z= 0},
44         {x=0, y=-1, z=1}, {x= 0, y=-1, z=-1},
45 }
46
47 --thanks to RhodiumToad for helping me figure out a good method to do this
48
49 local pool = {} -- this holds all redstone data (literal 3d virtual memory map)
50
51 local table_3d
52 local temp_pool
53 local function create_boundary_box(pos)
54         table_3d = {}
55         for x = pos.x-9,pos.x+9 do
56                 if pool[x] then
57                         for y = pos.y-9,pos.y+9 do
58                                 if pool[x][y] then
59                                         for z = pos.z-9,pos.z+9 do
60                                                 temp_pool = pool[x][y][z]
61                                                 if temp_pool then
62                                                         if not table_3d[x] then table_3d[x] = {} end
63                                                         if not table_3d[x][y] then table_3d[x][y] = {} end
64
65                                                         if x == pos.x-9 or x == pos.x+9 or 
66                                                         y == pos.y-9 or y == pos.y+9 or 
67                                                         z == pos.z-9 or z == pos.z+9 then
68                                                                 if temp_pool.dust then
69                                                                         table_3d[x][y][z] = {torch=temp_pool.dust}
70                                                                 else
71                                                                         table_3d[x][y][z] = temp_pool
72                                                                 end
73                                                         else
74                                                                 if temp_pool.dust then
75                                                                         table_3d[x][y][z] = {dust=0,origin=temp_pool.dust}
76                                                                 else
77                                                                         table_3d[x][y][z] = temp_pool
78                                                                 end
79                                                         end
80                                                 end
81                                         end
82                                 end
83                         end
84                 end
85         end
86         return(table_3d)
87 end
88
89
90
91 local function data_injection(pos,data)
92         -- add data into 3d memory
93         if data then
94                 if not pool[pos.x] then pool[pos.x] = {} end
95                 if not pool[pos.x][pos.y] then pool[pos.x][pos.y] = {} end
96                 pool[pos.x][pos.y][pos.z] = data
97         --delete data from 3d memory
98         else
99                 if pool and pool[pos.x] and pool[pos.x][pos.y] then
100                         pool[pos.x][pos.y][pos.z] = data
101                         
102                         --if not pool[pos.x][pos.y] then
103                         --      pool[pos.x][pos.y] = nil
104                         --      -- only run this if y axis is empty
105                         --      if not pool[pos.x] then
106                         --              pool[pos.x] = nil
107                         --      end
108                         --end
109                 end
110         end
111 end
112
113
114 -- redstone class
115 redstone = {}
116
117 local path = minetest.get_modpath("redstone")
118 --dofile(path.."/functions.lua")
119 --dofile(path.."/wire.lua")
120 dofile(path.."/torch.lua")
121 --dofile(path.."/lever.lua")
122 --dofile(path.."/button.lua")
123 --dofile(path.."/repeater.lua")
124 --dofile(path.."/light.lua")
125 --dofile(path.."/piston.lua")
126 --dofile(path.."/comparator.lua")
127 --dofile(path.."/craft.lua")
128 --dofile(path.."/ore.lua")
129 --dofile(path.."/inverter.lua")
130 --dofile(path.."/player_detector.lua")
131 --dofile(path.."/space_maker.lua")
132 --dofile(path.."/pressure_plate.lua")
133
134
135 --make redstone wire pass on current one level lower than it is
136 local i
137 local index
138 local passed_on_level
139 local function redstone_pathfinder(source,source_level,boundary,direction)
140         --directional torches
141         if direction then
142                 i = add_vec(source,facedir_to_dir(direction))
143                 if boundary and boundary[i.x][i.y][i.z] then
144                         index = boundary[i.x][i.y][i.z]
145                         --dust
146                         if index.dust then
147                                 passed_on_level = source_level - 1
148                                 if passed_on_level > 0 then
149                                         boundary[i.x][i.y][i.z].dust = passed_on_level
150                                         redstone_pathfinder(i,passed_on_level,boundary,nil)
151                                 end
152                         end
153                 end
154         else
155                 --redstone and torch
156                 for _,order in pairs(order) do
157                         i = add_vec(source,new_vec(order.x,order.y,order.z))
158                         if i and boundary and boundary[i.x] and boundary[i.x][i.y] and boundary[i.x][i.y][i.z] then
159                                 index = boundary[i.x][i.y][i.z]
160
161                                 if index.dust then
162
163                                         passed_on_level = source_level - 1
164
165                                         if passed_on_level > 0 and index.dust < source_level then
166                                                 boundary[i.x][i.y][i.z].dust = passed_on_level
167
168                                                 redstone_pathfinder(i,passed_on_level,boundary,nil)
169
170                                         end
171                                 end
172                         end
173                 end
174         end
175         return(boundary)
176 end
177
178
179 --make all power sources push power out
180 local pos
181 local node
182 local power
183
184 local boundary
185 local function calculate(pos)
186
187         boundary = create_boundary_box(pos)
188         --print(dump(boundary))
189
190         --pathfind through memory map   
191         for x,index_x in pairs(boundary) do
192                 for y,index_y in pairs(index_x) do
193                         for z,data in pairs(index_y) do
194                                 --allow data values for torches
195                                 if data.torch then
196                                         redstone_pathfinder(new_vec(x,y,z),data.torch,boundary)
197                                         boundary[x][y][z] = nil
198                                 elseif data.torch_directional then
199                                         redstone_pathfinder(new_vec(x,y,z),data.torch,boundary,data.dir)
200                                         boundary[x][y][z] = nil
201                                 end
202                         end
203                 end
204         end
205
206         --reassemble the table into a position list minetest can understand
207         --run through and set dust
208         for x,datax in pairs(boundary) do
209                 for y,datay in pairs(datax) do
210                         for z,data in pairs(datay) do
211                                 --print(dump(data))
212                                 if data.dust and data.dust ~= data.origin then
213                                         --print("setting:" ..data.dust)
214                                         swap_node(new_vec(x,y,z),{name="redstone:dust_"..data.dust})
215                                 end
216                         end
217                 end
218         end
219         --[[
220         for x,datax in pairs(boundary) do
221                 for y,datay in pairs(datax) do
222                         for z,data in pairs(datay) do
223                                 --directional activators
224                                 if data.directional == true then
225                                         power = get_powered_state_directional(new_vec(x,y,z))
226                                         if power then
227                                                 if power > 0 then
228                                                         redstone_activate(new_vec(x,y,z),power)
229                                                 elseif power == 0 then
230                                                         redstone_deactivate(new_vec(x,y,z),power)
231                                                 end
232                                         end
233                                 --non directional activators
234                                 else
235                                         power = get_local_power(new_vec(x,y,z))
236                                         --print(power)
237                                         if power then
238                                                 if power > 0 then
239                                                         redstone_activate(new_vec(x,y,z),power)
240                                                 elseif power == 0 then
241                                                         redstone_deactivate(new_vec(x,y,z),power)
242                                                 end
243                                         end
244                                 end
245                         end
246                 end
247         end
248         ]]--
249
250         for x,index_x in pairs(boundary) do
251                 for y,index_y in pairs(index_x) do
252                         for z,data in pairs(index_y) do
253                                 --write data back to memory pool
254                                 pool[x][y][z] = data
255                         end
256                 end
257         end
258 end
259
260
261 function redstone.inject(pos,data)
262         data_injection(pos,data)
263 end
264
265
266 function redstone.update(pos)
267         calculate(pos)
268 end
269
270
271
272
273
274
275 ----------------------------------------------------------------------------
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309 minetest.register_craftitem("redstone:dust", {
310         description = "Redstone Dust",
311         inventory_image = "redstone_dust_item.png",
312         wield_image = "redstone_dust_item.png",
313         wield_scale = {x = 1, y = 1, z = 1 + 1/16},
314         liquids_pointable = false,
315         on_place = function(itemstack, placer, pointed_thing)
316                 if not pointed_thing.type == "node" then
317                         return
318                 end             
319                 local sneak = placer:get_player_control().sneak
320                 local noddef = registered_nodes[get_node(pointed_thing.under).name]
321                 if not sneak and noddef.on_rightclick then
322                         minetest.item_place(itemstack, placer, pointed_thing)
323                         return
324                 end
325                 
326                 local _,worked = minetest.item_place(ItemStack("redstone:dust_0"), placer, pointed_thing)
327                 if worked then
328                         itemstack:take_item()
329                         return(itemstack)
330                 end
331
332
333                         --minetest.add_node(pointed_thing.above, {name="redstone:dust_0"})
334                         --itemstack:take_item(1)
335                         --minetest.sound_play("stone", {pos=pointed_thing.above})
336                         --return(itemstack)
337                 --end
338         end,
339 })
340
341 --8 power levels 8 being the highest
342 local color = 0
343 for i = 0,8 do
344         local coloring = floor(color)
345         minetest.register_node("redstone:dust_"..i,{
346                 description = "Redstone Dust",
347                 wield_image = "redstone_dust_item.png",
348                 tiles = {
349                         "redstone_dust_main.png^[colorize:red:"..coloring, "redstone_turn.png^[colorize:red:"..coloring,
350                         "redstone_t.png^[colorize:red:"..coloring, "redstone_cross.png^[colorize:red:"..coloring
351                 },
352                 power=i,
353                 drawtype = "raillike",
354                 paramtype = "light",
355                 sunlight_propagates = true,
356                 is_ground_content = false,
357                 walkable = false,
358                 node_placement_prediction = "",
359                 selection_box = {
360                         type = "fixed",
361                         fixed = {-1/2, -1/2, -1/2, 1/2, -1/2+1/16, 1/2},
362                 },
363                 sounds = main.stoneSound(),
364                 groups={dig_immediate=1,attached_node=1,redstone_dust=1,redstone=1,redstone_power=i},
365                 drop="redstone:dust",
366                 on_construct = function(pos)
367                         data_injection(pos,{dust=i})
368                         calculate(pos)
369                 end,
370                 after_destruct = function(pos)
371                         data_injection(pos,nil)
372                         calculate(pos)
373                 end,
374                 connects_to = {"group:redstone"},
375         })
376         color= color +31.875
377 end