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
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"))
82 local redstone_activate = function(pos,power)
84 node = get_node(pos).name
85 if registered_nodes[node].redstone_activation then
86 registered_nodes[node].redstone_activation(pos)
92 local redstone_deactivate = function(pos,power)
94 node = get_node(pos).name
95 if registered_nodes[node].redstone_deactivation then
96 registered_nodes[node].redstone_deactivation(pos)
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))
108 local localredstone = {}
110 localredstone.injector = function(i)
111 if get_node(i).name == "air" then
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
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)
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")}
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")}
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
153 a_index[i.x][i.y][i.z].redstone_activation = true
154 a_index[i.x][i.y][i.z].directional = true
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
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}
173 localredstone.collector = function(pos)
177 if abs(x)+abs(z) == 1 then
178 localredstone.injector(add_vec(pos,new_vec(x,y,z)))
186 function redstone.collect_info(pos)
187 localredstone.injector(pos)
188 localredstone.collector(pos)
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
199 --clear the index to avoid cpu looping wasting processing power
205 --make all power sources push power out
218 function redstone.calculate()
219 speed_test = minetest.get_us_time()/1000000
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
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
237 print("total torch calc time:"..minetest.get_us_time()/1000000-speed_test)
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})
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))
262 redstone_activate(new_vec(x,y,z),power)
263 elseif power == 0 then
264 redstone_deactivate(new_vec(x,y,z),power)
267 --non directional activators
269 power = get_local_power(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)
283 --make redstone wire pass on current one level lower than it is
286 local passed_on_level
287 local function redstone_pathfinder(source,source_level,direction)
288 --directional torches
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]
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)
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]
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)
327 function redstone.pathfind(source,source_level,direction)
328 redstone_pathfinder(source,source_level,direction)
338 ----------------------------------------------------------------------------
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
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)
389 local _,worked = minetest.item_place(ItemStack("redstone:dust_0"), placer, pointed_thing)
391 itemstack:take_item()
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})
404 --8 power levels 8 being the highest
407 local coloring = floor(color)
408 minetest.register_node("redstone:dust_"..i,{
409 description = "Redstone Dust",
410 wield_image = "redstone_dust_item.png",
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
416 drawtype = "raillike",
418 sunlight_propagates = true,
419 is_ground_content = false,
421 node_placement_prediction = "",
424 fixed = {-1/2, -1/2, -1/2, 1/2, -1/2+1/16, 1/2},
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)
432 after_destruct = function(pos)
433 --redstone.remove(pos,registered_nodes[get_node(pos).name].power)
434 redstone.collect_info(pos)
436 connects_to = {"group:redstone"},