5 local path = minetest.get_modpath("redstone")
6 dofile(path.."/functions.lua")
7 dofile(path.."/wire.lua")
8 dofile(path.."/torch.lua")
9 dofile(path.."/lever.lua")
10 dofile(path.."/button.lua")
11 dofile(path.."/repeater.lua")
12 dofile(path.."/light.lua")
13 dofile(path.."/piston.lua")
14 dofile(path.."/comparator.lua")
15 dofile(path.."/craft.lua")
16 dofile(path.."/ore.lua")
17 dofile(path.."/inverter.lua")
18 dofile(path.."/player_detector.lua")
19 dofile(path.."/space_maker.lua")
20 dofile(path.."/pressure_plate.lua")
23 get_old_power = function(pos)
24 local meta = minetest.get_meta(pos)
25 local oldpower = meta:get_int("old_power")
28 --set the data for powered states
29 get_local_power = function(pos)
34 --index only direct neighbors
35 if not (math.abs(x)+math.abs(z) > 1) or (math.abs(x)+math.abs(z) == 0) then
36 --print(minetest.get_node(vector.add(vector.new(x,y,z),pos)).name)
37 local level = minetest.get_node_group(minetest.get_node(vector.add(vector.new(x,y,z),pos)).name, "redstone_power")
38 if level > max_level then
48 --this is used for a power state comparison
49 set_old_power = function(pos,level)
50 local meta = minetest.get_meta(pos)
51 meta:set_int("old_power",level)
54 get_powered_state_directional = function(pos)
55 local meta = minetest.get_meta(pos)
56 local node = minetest.get_node(pos)
57 local param2 = node.param2
58 local dir = minetest.facedir_to_dir(param2)
59 local input_pos = vector.subtract(pos,dir)
60 local behind_node = minetest.get_node(input_pos)
61 local level = minetest.get_node_group(behind_node.name, "redstone_power")
66 local redstone_activate = function(name,pos,power)
67 minetest.after(0,function(name,pos)
68 if minetest.registered_nodes[name].redstone_activation then
69 minetest.registered_nodes[name].redstone_activation(pos)
71 set_old_power(pos,power)
75 local redstone_deactivate = function(name,pos,power)
76 minetest.after(0,function(name,pos)
77 if minetest.registered_nodes[name].redstone_deactivation then
78 minetest.registered_nodes[name].redstone_deactivation(pos)
80 set_old_power(pos,power)
84 local redstone_update = function(name,pos,power)
85 minetest.after(0,function(name,pos,power)
86 if minetest.registered_nodes[name].redstone_update then
87 minetest.registered_nodes[name].redstone_update(pos)
89 set_old_power(pos,power)
97 --collect all nodes that are local to the modified
98 --node of redstone dust and store in memory
99 function redstone.collect_info(pos)
100 --if table.getn(r_index) == 0 then
101 --print("-----------------------")
102 --print("started indexing")
104 local get_node = minetest.get_node
105 local group = minetest.get_node_group
107 local function get_group(i,gotten_group)
108 return(group(get_node(i).name, gotten_group))
114 --index only direct neighbors
115 if not (math.abs(x)+math.abs(z) > 1) or (math.abs(x)+math.abs(z) == 0) then
117 local i = vector.add(pos,vector.new(x,y,z))
118 local execute_collection = true
119 if r_index[i.x] and r_index[i.x][i.y] then
120 if r_index[i.x][i.y][i.z] then
121 execute_collection = false
125 we run through the groups
126 1 redstone_torch overrides dust if defined
127 2 torch_directional overrides torch if defined
128 3 redstone activation is bolted on with directional overriding general
130 this is to prevent weird behavior
133 This new method also uses a table bolted onto the x,y,z positional data value
135 It's much easier to work with and modify
138 if execute_collection == true then
140 if get_group(i,"redstone_dust") > 0 then
141 --add data to both maps
142 if not r_index[i.x] then r_index[i.x] = {} end
143 if not r_index[i.x][i.y] then r_index[i.x][i.y] = {} end
144 r_index[i.x][i.y][i.z] = {dust = true,level = 0} --get_group(i,"redstone_power")}
145 --the data to the 3d array must be written to memory before this is executed
146 --or a stack overflow occurs!!!
147 --pass down info for activators
148 redstone.collect_info(i,get_group(i,"redstone_power"))
150 --index power sources
151 if get_group(i,"redstone_torch") > 0 then
152 if not r_index[i.x] then r_index[i.x] = {} end
153 if not r_index[i.x][i.y] then r_index[i.x][i.y] = {} end
154 r_index[i.x][i.y][i.z] = {torch = true,power=get_group(i,"redstone_power")}
156 --index directional power sources (Like repeaters/comparators)
157 --only outputs forwards
158 if get_group(i,"torch_directional") > 0 then
159 if not r_index[i.x] then r_index[i.x] = {} end
160 if not r_index[i.x][i.y] then r_index[i.x][i.y] = {} end
161 r_index[i.x][i.y][i.z] = {torch_directional = true, dir = get_node(i).param2 , power = get_group(i,"redstone_power")}
164 --index directional activators (Like repeaters/comparators)
165 --only accepts input from the back
166 if get_group(i,"redstone_activation_directional") > 0 then
167 --print("indexing directional")
168 if not r_index[i.x] then r_index[i.x] = {} end
169 if not r_index[i.x][i.y] then r_index[i.x][i.y] = {} end
170 if not r_index[i.x][i.y][i.z] then r_index[i.x][i.y][i.z] = {} end
171 --r_index[i.x][i.y][i.z].activate = false
172 r_index[i.x][i.y][i.z].redstone_activation = true
173 r_index[i.x][i.y][i.z].directional = true
174 r_index[i.x][i.y][i.z].dir = get_node(i).param2
177 --index objects that activate
178 if get_group(i,"redstone_activation") > 0 then
179 if not r_index[i.x] then r_index[i.x] = {} end
180 if not r_index[i.x][i.y] then r_index[i.x][i.y] = {} end
181 if not r_index[i.x][i.y][i.z] then r_index[i.x][i.y][i.z] = {} end
182 --r_index[i.x][i.y][i.z].activate = false
183 r_index[i.x][i.y][i.z].redstone_activation = true
184 r_index[i.x][i.y][i.z].name = get_node(i).name
187 --set_powered_state(i)
189 --local powered = get_powered_state(i)
192 --print("powered:"..powered,"oldpowered:"..old_powered)
194 --r_index[i.x][i.y][i.z].powered = powered
195 --r_index[i.x][i.y][i.z].old_powered = old_powered
197 --split this into update up and down
198 --if powered > old_powered then
199 -- r_index[i.x][i.y][i.z].deactivate = true
200 ---elseif powered > 0 and old_powered == 0 then
201 -- r_index[i.x][i.y][i.z].deactivate = true
212 --check if index table contains items
213 --then execute an update
214 minetest.register_globalstep(function(dtime)
215 --if indexes exist then calculate redstone
216 if r_index and next(r_index) then
217 --create the old version to help with deactivation calculation
218 r_copy = table.copy(r_index)
221 --clear the index to avoid cpu looping wasting processing power
225 --make all power sources push power out
226 function redstone.calculate()
227 --pathfind through memory map
228 for x,index_x in pairs(r_index) do
229 for y,index_y in pairs(index_x) do
230 for z,data in pairs(index_y) do
231 --allow data values for torches
233 redstone.pathfind(vector.new(x,y,z),data.power)
234 elseif data.torch_directional then
235 redstone.pathfind(vector.new(x,y,z),data.power,data.dir)
241 --calculate values for voxel manip
242 local x_min,x_max,y_min,y_max,z_min,z_max
243 for x,index_x in pairs(r_index) do
244 for y,index_y in pairs(index_x) do
245 for z,_ in pairs(index_y) do
246 --do this because the root (x) will always come first
255 if x < x_min then x_min = x end
256 if x > x_max then x_max = x end
257 if y < y_min then y_min = y end
258 if y > y_max then y_max = y end
259 if z < z_min then z_min = z end
260 if z > z_max then z_max = z end
265 local min = vector.new(x_min,y_min,z_min)
266 local max = vector.new(x_max,y_max,z_max)
267 local vm = minetest.get_voxel_manip()
268 local emin, emax = vm:read_from_map(min,max)
269 local area = VoxelArea:new{MinEdge=emin, MaxEdge=emax}
270 local data = vm:get_data()
271 local content_id = minetest.get_name_from_content_id
272 --reassemble the table into a position list minetest can understand
274 --run through and set dust
275 for x,datax in pairs(r_index) do
276 for y,datay in pairs(datax) do
277 for z,index in pairs(datay) do
278 local p_pos = area:index(x,y,z)
280 data[p_pos] = minetest.get_content_id("redstone:dust_"..index.level)
290 --run through activators
291 for x,datax in pairs(r_index) do
292 for y,datay in pairs(datax) do
293 for z,index in pairs(datay) do
294 local pos = vector.new(x,y,z)
295 local node = minetest.get_node(pos)
296 --directional activators
297 if index.redstone_activation == true and index.directional == true then
298 local power = get_powered_state_directional(pos)
299 local old_power = get_old_power(pos)
300 if power > 0 and old_power == 0 then
301 redstone_activate(node.name,pos,power)
302 elseif power == 0 and old_power > 0 then
303 redstone_deactivate(node.name,pos,power)
304 --do an update if state has not changed
305 elseif power > 0 and old_power > 0 then
306 redstone_update(node.name,pos,power)
307 elseif power == 0 and old_power == 0 then
308 redstone_update(node.name,pos,power)
310 --non directional activators
311 elseif index.redstone_activation == true then
312 local power = get_local_power(pos)
313 local old_power = get_old_power(pos)
314 if power > 0 and old_power == 0 then
315 redstone_activate(node.name,pos,power)
316 elseif power == 0 and old_power > 0 then
317 redstone_deactivate(node.name,pos,power)
318 --do an update if state has not changed
319 elseif power > 0 and old_power > 0 then
320 redstone_update(node.name,pos,power)
321 elseif power == 0 and old_power == 0 then
322 redstone_update(node.name,pos,power)
330 --make redstone wire pass on current one level lower than it is
331 function redstone.pathfind(source,source_level,direction)
332 --directional torches
334 --print("starting direction")
335 local dir = minetest.facedir_to_dir(direction)
336 local i = vector.add(source,dir)
337 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
338 local index = r_index[i.x][i.y][i.z]
341 local passed_on_level = source_level - 1
342 if passed_on_level > 0 then
343 r_index[i.x][i.y][i.z].level = passed_on_level
344 redstone.pathfind(i,passed_on_level)
353 local i = vector.add(source,vector.new(x,y,z))
354 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
355 local index = r_index[i.x][i.y][i.z]
357 local passed_on_level = source_level - 1
358 if passed_on_level > 0 and index.level < source_level then
359 r_index[i.x][i.y][i.z].level = passed_on_level
360 redstone.pathfind(i,passed_on_level)
377 ----------------------------------------------------------------------------
411 minetest.register_craftitem("redstone:dust", {
412 description = "Redstone Dust",
413 inventory_image = "redstone_dust_item.png",
414 wield_image = "redstone_dust_item.png",
415 wield_scale = {x = 1, y = 1, z = 1 + 1/16},
416 liquids_pointable = false,
417 on_place = function(itemstack, placer, pointed_thing)
418 if not pointed_thing.type == "node" then
421 local sneak = placer:get_player_control().sneak
422 local noddef = minetest.registered_nodes[minetest.get_node(pointed_thing.under).name]
423 if not sneak and noddef.on_rightclick then
424 minetest.item_place(itemstack, placer, pointed_thing)
428 local _,worked = minetest.item_place(ItemStack("redstone:dust_0"), placer, pointed_thing)
430 itemstack:take_item()
435 --minetest.add_node(pointed_thing.above, {name="redstone:dust_0"})
436 --itemstack:take_item(1)
437 --minetest.sound_play("stone", {pos=pointed_thing.above})
443 minetest.register_craft({
445 output = "redstone:dust",
446 recipe = {"redstone:dust"},
449 --8 power levels 8 being the highest
452 local coloring = math.floor(color)
453 minetest.register_node("redstone:dust_"..i,{
454 description = "Redstone Dust",
455 wield_image = "redstone_dust_item.png",
457 "redstone_dust_main.png^[colorize:red:"..coloring, "redstone_turn.png^[colorize:red:"..coloring,
458 "redstone_t.png^[colorize:red:"..coloring, "redstone_cross.png^[colorize:red:"..coloring
461 drawtype = "raillike",
463 sunlight_propagates = true,
464 is_ground_content = false,
466 node_placement_prediction = "",
469 fixed = {-1/2, -1/2, -1/2, 1/2, -1/2+1/16, 1/2},
471 sounds = main.stoneSound(),
472 groups={dig_immediate=1,attached_node=1,redstone_dust=1,redstone=1,redstone_power=i},
473 drop="redstone:dust",
474 on_construct = function(pos)
475 redstone.collect_info(pos)
477 after_destruct = function(pos)
478 --redstone.remove(pos,minetest.registered_nodes[minetest.get_node(pos).name].power)
479 redstone.collect_info(pos,i)
481 connects_to = {"group:redstone"},