]> git.lizzy.rs Git - Crafter.git/blobdiff - mods/redstone/init.lua
Make redstone do "y corrners" (diagonal facedir binary)
[Crafter.git] / mods / redstone / init.lua
index 5db9a2b2f9621888807c1716af568bcd98a9045f..fbc25a9944dcd08ff3b9d32f48251a6302273900 100644 (file)
@@ -27,6 +27,21 @@ local add_vec         = vector.add
 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 = {}
 
@@ -34,6 +49,7 @@ local speed_test
 
 local r_index = {}
 local a_index = {}
+local check_table = {}
 
 local path = minetest.get_modpath("redstone")
 dofile(path.."/functions.lua")
@@ -58,21 +74,14 @@ 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
-                       if get_meta(add_vec(new_vec(x,y,z),pos)):get_int("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
@@ -110,11 +119,15 @@ end
 
 --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)
-       node = get_node(i).name
-       if node == "air" then
+
+localredstone.injector = function(i,origin)
+       if get_node(i).name == "air" then
                return
        end
 
@@ -124,34 +137,49 @@ localredstone.injector = function(i)
                end
        end
 
-       --index dust
-       if get_item_group(node,"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 vector_distance(i,origin) > 9 then
                return
        end
+
+       --index dust
+       if get_group(i,"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_group(i,"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_group(i,"redstone_power")}
+               end
+       end
        --index power sources
-       if get_item_group(node,"redstone_torch") > 0 then
+       if get_group(i,"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_item_group(node,"redstone_power")}
+               r_index[i.x][i.y][i.z] = {torch = true,power=get_group(i,"redstone_power")}
        end     
        --index directional power sources (Like repeaters/comparators)
        --only outputs forwards
-       if get_item_group(node,"torch_directional") > 0 then
+       if get_group(i,"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_item_group(node,"redstone_power")}
+               r_index[i.x][i.y][i.z] = {torch_directional = true, dir = get_node(i).param2 , power = get_group(i,"redstone_power")}
        end
        
        --index directional activators (Like repeaters/comparators)
        --only accepts input from the back
-       if get_item_group(node,"redstone_activation_directional") > 0 then
+       if get_group(i,"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
@@ -162,7 +190,7 @@ localredstone.injector = function(i)
        end
        
        --index objects that activate
-       if get_item_group(node,"redstone_activation") > 0 then
+       if get_group(i,"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
@@ -177,37 +205,36 @@ localredstone.injector = function(i)
        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(z) == 1 then
-                       localredstone.injector(add_vec(pos,new_vec(x,y,z)))
-               end
-       end
-       end
+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
 
 
-function redstone.collect_info(pos)
-       localredstone.injector(pos)
-       localredstone.collector(pos)
-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)
+
+       redstone_algorithm()
+end
+
 
 --make all power sources push power out
 local x_min
@@ -247,16 +274,20 @@ function redstone.calculate()
 
        --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
+                               if index and index.dust and index.level ~= check_table[x][y][z] then
+                                       count = count + 1
                                        minetest.set_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
@@ -304,31 +335,26 @@ local function redstone_pathfinder(source,source_level,direction)
                                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 abs(x)+abs(z) == 1 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)