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