local get_content_id = minetest.get_content_id
local get_voxel_manip = minetest.get_voxel_manip
local after = minetest.after
+
+local swap_node = minetest.swap_node
local registered_nodes
minetest.register_on_mods_loaded(function()
registered_nodes = minetest.registered_nodes
local sub_vec = vector.subtract
local vector_distance = vector.distance
+--this is written out manually so that
+--math.abs is not needed
+local order = {
+ {x=1, y=0, z=0}, {x=-1, y=0, z= 0},
+ {x=0, y=0, z=1}, {x= 0, y=0, z=-1},
+
+ {x=0, y=1, z=0}, {x= 0, y=-1, z=0},
+
+ {x=1, y=1, z=0}, {x=-1, y=1, z= 0},
+ {x=0, y=1, z=1}, {x= 0, y=1, z=-1},
+
+ {x=1, y=-1, z=0}, {x=-1, y=-1, z= 0},
+ {x=0, y=-1, z=1}, {x= 0, y=-1, z=-1},
+}
+
-- redstone class
redstone = {}
local r_index = {}
local a_index = {}
+local check_table = {}
local path = minetest.get_modpath("redstone")
dofile(path.."/functions.lua")
--set the data for powered states
local get_local_power = function(pos)
- if not pos then
- return
- end
- for x = -1,1 do
- for y = -1,1 do
- for z = -1,1 do
- --index only direct neighbors
- if abs(x)+abs(z)+abs(y) == 1 then
- --print(get_node(add_vec(new_vec(x,y,z),pos)).name)
- if get_item_group(get_node(add_vec(new_vec(x,y,z),pos)).name, "redstone_power") > 0 then
- return(1)
- end
+ for _,order in pairs(order) do
+ --print(get_node(add_vec(new_vec(x,y,z),pos)).name)
+ if get_item_group(get_node(add_vec(new_vec(order.x,order.y,order.z),pos)).name, "redstone_power") > 0 then
+ return(1)
+ end
+ if get_meta(add_vec(new_vec(order.x,order.y,order.z),pos)):get_int("redstone_power") > 0 then
+ return(1)
end
- end
- end
end
return(0)
end
+local power
+local pos
+local node
local get_powered_state_directional = function(pos)
- return(get_item_group(get_node(sub_vec(pos,facedir_to_dir(get_node(pos).param2))).name, "redstone_power"))
+ pos = sub_vec(pos,facedir_to_dir(get_node(pos).param2))
+ power = get_item_group(get_node(pos).name, "redstone_power")
+ if power == 0 then
+ power = get_meta(pos):get_int("redstone_power")
+ end
+ return(power)
end
local node
--collect all nodes that are local to the modified
--node of redstone dust and store in memory
-local function get_group(i,gotten_group)
- return(get_item_group(get_node(i).name, gotten_group))
-end
-
-
local localredstone = {}
+local node
+localredstone.injector = function(i,origin)
+ node = get_node(i).name
+ if node == "air" then
+ return
+ end
-localredstone.injector = function(i)
- if get_node(i).name == "air" then
+ if r_index[i.x] and r_index[i.x][i.y] and r_index[i.x][i.y][i.z] then
return
end
- if r_index[i.x] and r_index[i.x][i.y] then
- if r_index[i.x][i.y][i.z] then
- return
- end
+ if vector_distance(i,origin) > 9 then
+ return
end
--index dust
- if get_group(i,"redstone_dust") > 0 then
- --add data to both maps
- if not r_index[i.x] then r_index[i.x] = {} end
- if not r_index[i.x][i.y] then r_index[i.x][i.y] = {} end
- r_index[i.x][i.y][i.z] = {dust = true,level = 0}
- --the data to the 3d array must be written to memory before this is executed
- --or a stack overflow occurs!!!
- localredstone.collector(i)
+ if get_item_group(node,"redstone_dust") > 0 then
+ if vector_distance(i,origin) <= 8 then
+ --add data to both maps
+ if not r_index[i.x] then r_index[i.x] = {} end
+ if not r_index[i.x][i.y] then r_index[i.x][i.y] = {} end
+ r_index[i.x][i.y][i.z] = {dust = true,level = 0}
+
+ if not check_table[i.x] then check_table[i.x] = {} end
+ if not check_table[i.x][i.y] then check_table[i.x][i.y] = {} end
+ check_table[i.x][i.y][i.z] = get_item_group(node,"redstone_power")
+
+ --the data to the 3d array must be written to memory before this is executed
+ --or a stack overflow occurs!!!
+ localredstone.collector(i,origin)
+ return
+ else
+ if not r_index[i.x] then r_index[i.x] = {} end
+ if not r_index[i.x][i.y] then r_index[i.x][i.y] = {} end
+ r_index[i.x][i.y][i.z] = {torch = true,power=get_item_group(node,"redstone_power")}
+ end
end
--index power sources
- if get_group(i,"redstone_torch") > 0 then
+ if get_item_group(node,"redstone_torch") > 0 then
if not r_index[i.x] then r_index[i.x] = {} end
if not r_index[i.x][i.y] then r_index[i.x][i.y] = {} end
- r_index[i.x][i.y][i.z] = {torch = true,power=get_group(i,"redstone_power")}
+ r_index[i.x][i.y][i.z] = {torch = true,power=get_item_group(node,"redstone_power")}
end
--index directional power sources (Like repeaters/comparators)
--only outputs forwards
- if get_group(i,"torch_directional") > 0 then
+ if get_item_group(node,"torch_directional") > 0 then
if not r_index[i.x] then r_index[i.x] = {} end
if not r_index[i.x][i.y] then r_index[i.x][i.y] = {} end
- r_index[i.x][i.y][i.z] = {torch_directional = true, dir = get_node(i).param2 , power = get_group(i,"redstone_power")}
+ r_index[i.x][i.y][i.z] = {torch_directional = true, dir = get_node(i).param2 , power = get_item_group(node,"redstone_power")}
end
--index directional activators (Like repeaters/comparators)
--only accepts input from the back
- if get_group(i,"redstone_activation_directional") > 0 then
+ if get_item_group(node,"redstone_activation_directional") > 0 then
--print("indexing directional")
if not a_index[i.x] then a_index[i.x] = {} end
if not a_index[i.x][i.y] then a_index[i.x][i.y] = {} end
end
--index objects that activate
- if get_group(i,"redstone_activation") > 0 then
+ if get_item_group(node,"redstone_activation") > 0 then
if not a_index[i.x] then a_index[i.x] = {} end
if not a_index[i.x][i.y] then a_index[i.x][i.y] = {} end
if not a_index[i.x][i.y][i.z] then a_index[i.x][i.y][i.z] = {} end
a_index[i.x][i.y][i.z].redstone_activation = true
end
-end
-localredstone.collector = function(pos)
- for x = -1,1 do
- for y = -1,1 do
- for z = -1,1 do
- if abs(x)+abs(y)+abs(z) == 1 then
- localredstone.injector(add_vec(pos,new_vec(x,y,z)))
- end
- end
- end
+ --sneaky way to make levers and buttons work
+ if get_meta(i):get_int("redstone_power") > 0 then
+ if not r_index[i.x] then r_index[i.x] = {} end
+ if not r_index[i.x][i.y] then r_index[i.x][i.y] = {} end
+ r_index[i.x][i.y][i.z] = {torch = true,power=get_meta(i):get_int("redstone_power")}
end
end
-
-function redstone.collect_info(pos)
- localredstone.injector(pos)
- localredstone.collector(pos)
+localredstone.collector = function(pos,origin)
+ for _,order in pairs(order) do
+ localredstone.injector(add_vec(pos,new_vec(order.x,order.y,order.z)),origin)
+ end
end
--check if index table contains items
--then execute an update
-minetest.register_globalstep(function(dtime)
+local function redstone_algorithm()
--if indexes exist then calculate redstone
- if (r_index and next(r_index)) or (a_index and next(a_index)) then
- --create the old version to help with deactivation calculation
- redstone.calculate()
- --clear the index to avoid cpu looping wasting processing power
- r_index = {}
- a_index = {}
+ --create the old version to help with deactivation calculation
+ redstone.calculate()
+ --clear the index to avoid cpu looping wasting processing power
+ r_index = {}
+ a_index = {}
+ check_table = {}
+end
+
+
+function redstone.collect_info(pos)
+ if r_index[pos.x] and r_index[pos.x][pos.y] and r_index[pos.x][pos.y][pos.z] then
+ return
end
-end)
+ localredstone.injector(pos,pos)
+ localredstone.collector(pos,pos)
---make all power sources push power out
-local x_min
-local x_max
-local y_min
-local y_max
-local z_min
-local z_max
-local initial_check
+ redstone_algorithm()
+end
+--make all power sources push power out
local pos
local node
local power
function redstone.calculate()
- speed_test = minetest.get_us_time()/1000000
+ --speed_test = minetest.get_us_time()/1000000
--pathfind through memory map
for x,index_x in pairs(r_index) do
end
end
- print("total torch calc time:"..minetest.get_us_time()/1000000-speed_test)
+ --print("total torch calc time:"..minetest.get_us_time()/1000000-speed_test)
--reassemble the table into a position list minetest can understand
--run through and set dust
+ --local count = 0
+
for x,datax in pairs(r_index) do
for y,datay in pairs(datax) do
for z,index in pairs(datay) do
--print(get_node(new_vec(x,y,z)).name)
- if index and index.dust then
- minetest.set_node(new_vec(x,y,z),{name="redstone:dust_"..index.level})
+ if index and index.dust and index.level ~= check_table[x][y][z] then
+ --count = count + 1
+ swap_node(new_vec(x,y,z),{name="redstone:dust_"..index.level})
end
end
end
end
+ --print("set "..count.." nodes")
for x,datax in pairs(a_index) do
for y,datay in pairs(datax) do
--non directional activators
else
power = get_local_power(new_vec(x,y,z))
+ --print(power)
if power then
if power > 0 then
redstone_activate(new_vec(x,y,z),power)
passed_on_level = source_level - 1
if passed_on_level > 0 then
r_index[i.x][i.y][i.z].level = passed_on_level
- redstone_pathfinder(i,passed_on_level,nil,origin)
+ redstone_pathfinder(i,passed_on_level,nil)
end
end
end
else
--redstone and torch
- for x = -1,1 do
- for y = -1,1 do
- for z = -1,1 do
- if not (abs(x)+abs(z) > 1) or (abs(x)+abs(z) == 0) then
- i = add_vec(source,new_vec(x,y,z))
- 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
- index = r_index[i.x][i.y][i.z]
- if index.dust then
- passed_on_level = source_level - 1
- if passed_on_level > 0 and index.level < source_level then
- r_index[i.x][i.y][i.z].level = passed_on_level
- redstone_pathfinder(i,passed_on_level,nil)
- end
+ for _,order in pairs(order) do
+ i = add_vec(source,new_vec(order.x,order.y,order.z))
+ 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
+ --print(minetest.get_node(i).name)
+ index = r_index[i.x][i.y][i.z]
+ if index.dust then
+ passed_on_level = source_level - 1
+ if passed_on_level > 0 and index.level < source_level then
+ r_index[i.x][i.y][i.z].level = passed_on_level
+ redstone_pathfinder(i,passed_on_level,nil)
end
end
end
end
- end
- end
end
end
function redstone.pathfind(source,source_level,direction)