2 minetest,vector,math,table,pairs
4 minetest,vector,math,table,pairs
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
22 local floor = math.floor
25 local new_vec = vector.new
26 local add_vec = vector.add
27 local sub_vec = vector.subtract
28 local vector_distance = vector.distance
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")
56 --set the data for powered states
57 local get_local_power = function(pos)
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
70 if get_meta(add_vec(new_vec(x,y,z),pos)):get_int("redstone_power") > 0 then
82 local get_powered_state_directional = function(pos)
83 pos = sub_vec(pos,facedir_to_dir(get_node(pos).param2))
84 power = get_item_group(get_node(pos).name, "redstone_power")
86 power = get_meta(pos):get_int("redstone_power")
92 local redstone_activate = function(pos,power)
94 node = get_node(pos).name
95 if registered_nodes[node].redstone_activation then
96 registered_nodes[node].redstone_activation(pos)
102 local redstone_deactivate = function(pos,power)
104 node = get_node(pos).name
105 if registered_nodes[node].redstone_deactivation then
106 registered_nodes[node].redstone_deactivation(pos)
111 --collect all nodes that are local to the modified
112 --node of redstone dust and store in memory
113 local function get_group(i,gotten_group)
114 return(get_item_group(get_node(i).name, gotten_group))
118 local localredstone = {}
120 localredstone.injector = function(i)
121 if get_node(i).name == "air" then
125 if r_index[i.x] and r_index[i.x][i.y] then
126 if r_index[i.x][i.y][i.z] then
132 if get_group(i,"redstone_dust") > 0 then
133 --add data to both maps
134 if not r_index[i.x] then r_index[i.x] = {} end
135 if not r_index[i.x][i.y] then r_index[i.x][i.y] = {} end
136 r_index[i.x][i.y][i.z] = {dust = true,level = 0}
137 --the data to the 3d array must be written to memory before this is executed
138 --or a stack overflow occurs!!!
139 localredstone.collector(i)
141 --index power sources
142 if get_group(i,"redstone_torch") > 0 then
143 if not r_index[i.x] then r_index[i.x] = {} end
144 if not r_index[i.x][i.y] then r_index[i.x][i.y] = {} end
145 r_index[i.x][i.y][i.z] = {torch = true,power=get_group(i,"redstone_power")}
147 --index directional power sources (Like repeaters/comparators)
148 --only outputs forwards
149 if get_group(i,"torch_directional") > 0 then
150 if not r_index[i.x] then r_index[i.x] = {} end
151 if not r_index[i.x][i.y] then r_index[i.x][i.y] = {} end
152 r_index[i.x][i.y][i.z] = {torch_directional = true, dir = get_node(i).param2 , power = get_group(i,"redstone_power")}
155 --index directional activators (Like repeaters/comparators)
156 --only accepts input from the back
157 if get_group(i,"redstone_activation_directional") > 0 then
158 --print("indexing directional")
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
163 a_index[i.x][i.y][i.z].redstone_activation = true
164 a_index[i.x][i.y][i.z].directional = true
167 --index objects that activate
168 if get_group(i,"redstone_activation") > 0 then
169 if not a_index[i.x] then a_index[i.x] = {} end
170 if not a_index[i.x][i.y] then a_index[i.x][i.y] = {} end
171 if not a_index[i.x][i.y][i.z] then a_index[i.x][i.y][i.z] = {} end
172 a_index[i.x][i.y][i.z].redstone_activation = true
175 --sneaky way to make levers and buttons work
176 if get_meta(i):get_int("redstone_power") > 0 then
177 if not r_index[i.x] then r_index[i.x] = {} end
178 if not r_index[i.x][i.y] then r_index[i.x][i.y] = {} end
179 r_index[i.x][i.y][i.z] = {torch = true,power=get_meta(i):get_int("redstone_power")}
183 localredstone.collector = function(pos)
187 if abs(x)+abs(z) == 1 then
188 localredstone.injector(add_vec(pos,new_vec(x,y,z)))
196 function redstone.collect_info(pos)
197 localredstone.injector(pos)
198 localredstone.collector(pos)
202 --check if index table contains items
203 --then execute an update
204 minetest.register_globalstep(function(dtime)
205 --if indexes exist then calculate redstone
206 if (r_index and next(r_index)) or (a_index and next(a_index)) then
207 --create the old version to help with deactivation calculation
209 --clear the index to avoid cpu looping wasting processing power
215 --make all power sources push power out
228 function redstone.calculate()
229 speed_test = minetest.get_us_time()/1000000
231 --pathfind through memory map
232 for x,index_x in pairs(r_index) do
233 for y,index_y in pairs(index_x) do
234 for z,data in pairs(index_y) do
235 --allow data values for torches
237 redstone.pathfind(new_vec(x,y,z),data.power)
238 r_index[x][y][z] = nil
239 elseif data.torch_directional then
240 redstone.pathfind(new_vec(x,y,z),data.power,data.dir)
241 r_index[x][y][z] = nil
247 print("total torch calc time:"..minetest.get_us_time()/1000000-speed_test)
251 --reassemble the table into a position list minetest can understand
252 --run through and set dust
253 for x,datax in pairs(r_index) do
254 for y,datay in pairs(datax) do
255 for z,index in pairs(datay) do
256 --print(get_node(new_vec(x,y,z)).name)
257 if index and index.dust then
258 minetest.set_node(new_vec(x,y,z),{name="redstone:dust_"..index.level})
264 for x,datax in pairs(a_index) do
265 for y,datay in pairs(datax) do
266 for z,index in pairs(datay) do
267 --directional activators
268 if index.directional == true then
269 power = get_powered_state_directional(new_vec(x,y,z))
272 redstone_activate(new_vec(x,y,z),power)
273 elseif power == 0 then
274 redstone_deactivate(new_vec(x,y,z),power)
277 --non directional activators
279 power = get_local_power(new_vec(x,y,z))
282 redstone_activate(new_vec(x,y,z),power)
283 elseif power == 0 then
284 redstone_deactivate(new_vec(x,y,z),power)
293 --make redstone wire pass on current one level lower than it is
296 local passed_on_level
297 local function redstone_pathfinder(source,source_level,direction)
298 --directional torches
301 --print("starting direction")
302 i = add_vec(source,facedir_to_dir(direction))
303 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
304 index = r_index[i.x][i.y][i.z]
307 passed_on_level = source_level - 1
308 if passed_on_level > 0 then
309 r_index[i.x][i.y][i.z].level = passed_on_level
310 redstone_pathfinder(i,passed_on_level,nil,origin)
319 if abs(x)+abs(z) == 1 then
320 i = add_vec(source,new_vec(x,y,z))
321 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
322 index = r_index[i.x][i.y][i.z]
324 passed_on_level = source_level - 1
325 if passed_on_level > 0 and index.level < source_level then
326 r_index[i.x][i.y][i.z].level = passed_on_level
327 redstone_pathfinder(i,passed_on_level,nil)
337 function redstone.pathfind(source,source_level,direction)
338 redstone_pathfinder(source,source_level,direction)
348 ----------------------------------------------------------------------------
382 minetest.register_craftitem("redstone:dust", {
383 description = "Redstone Dust",
384 inventory_image = "redstone_dust_item.png",
385 wield_image = "redstone_dust_item.png",
386 wield_scale = {x = 1, y = 1, z = 1 + 1/16},
387 liquids_pointable = false,
388 on_place = function(itemstack, placer, pointed_thing)
389 if not pointed_thing.type == "node" then
392 local sneak = placer:get_player_control().sneak
393 local noddef = registered_nodes[get_node(pointed_thing.under).name]
394 if not sneak and noddef.on_rightclick then
395 minetest.item_place(itemstack, placer, pointed_thing)
399 local _,worked = minetest.item_place(ItemStack("redstone:dust_0"), placer, pointed_thing)
401 itemstack:take_item()
406 --minetest.add_node(pointed_thing.above, {name="redstone:dust_0"})
407 --itemstack:take_item(1)
408 --minetest.sound_play("stone", {pos=pointed_thing.above})
414 --8 power levels 8 being the highest
417 local coloring = floor(color)
418 minetest.register_node("redstone:dust_"..i,{
419 description = "Redstone Dust",
420 wield_image = "redstone_dust_item.png",
422 "redstone_dust_main.png^[colorize:red:"..coloring, "redstone_turn.png^[colorize:red:"..coloring,
423 "redstone_t.png^[colorize:red:"..coloring, "redstone_cross.png^[colorize:red:"..coloring
426 drawtype = "raillike",
428 sunlight_propagates = true,
429 is_ground_content = false,
431 node_placement_prediction = "",
434 fixed = {-1/2, -1/2, -1/2, 1/2, -1/2+1/16, 1/2},
436 sounds = main.stoneSound(),
437 groups={dig_immediate=1,attached_node=1,redstone_dust=1,redstone=1,redstone_power=i},
438 drop="redstone:dust",
439 on_construct = function(pos)
440 redstone.collect_info(pos)
442 after_destruct = function(pos)
443 --redstone.remove(pos,registered_nodes[get_node(pos).name].power)
444 redstone.collect_info(pos)
446 connects_to = {"group:redstone"},