]> git.lizzy.rs Git - Crafter.git/blobdiff - mods/redstone/init.lua
Remove debug info
[Crafter.git] / mods / redstone / init.lua
index 3a10b53223890491dac1e6a16b5ae29b1b071d0a..80b2fa4e5fc71a7d78f8aa21c64fc3d726a5d7ec 100644 (file)
@@ -29,6 +29,47 @@ local add_vec         = vector.add
 local sub_vec         = vector.subtract
 local vector_distance = vector.distance
 
+local activator_table = {} -- this holds the translation data of activator tables (activator functions)
+local capacitor_table = {}
+
+-- redstone class
+redstone = {}
+
+-- enables mods to create data functions
+function redstone.register_activator(data)
+       activator_table[data.name] = {
+               activate   = data.activate,
+               deactivate = data.deactivate
+       }
+end
+
+-- enables mods to create data functions
+function redstone.register_capacitor(data)
+       capacitor_table[data.name] = {
+               off = data.off,
+               on  = data.on
+       }
+end
+
+local path = minetest.get_modpath("redstone")
+dofile(path.."/functions.lua")
+--dofile(path.."/wire.lua")
+dofile(path.."/torch.lua")
+dofile(path.."/lever.lua")
+dofile(path.."/button.lua")
+dofile(path.."/repeater.lua")
+dofile(path.."/light.lua")
+dofile(path.."/piston.lua")
+--dofile(path.."/comparator.lua")
+dofile(path.."/craft.lua")
+--dofile(path.."/ore.lua")
+dofile(path.."/inverter.lua")
+--dofile(path.."/player_detector.lua")
+--dofile(path.."/space_maker.lua")
+--dofile(path.."/pressure_plate.lua")
+dofile(path.."/capacitors.lua")
+
+
 --this is written out manually so that
 --math.abs is not needed
 local order = {
@@ -48,6 +89,28 @@ local order = {
 
 local pool = {} -- this holds all redstone data (literal 3d virtual memory map)
 
+
+local function data_injection(pos,data)
+       -- add data into 3d memory
+       if data then
+               if not pool[pos.x] then pool[pos.x] = {} end
+               if not pool[pos.x][pos.y] then pool[pos.x][pos.y] = {} end
+               pool[pos.x][pos.y][pos.z] = data
+       --delete data from 3d memory
+       else
+               if pool and pool[pos.x] and pool[pos.x][pos.y] then
+                       pool[pos.x][pos.y][pos.z] = data
+                       if pool[pos.x][pos.y] and not next(pool[pos.x][pos.y]) then
+                               pool[pos.x][pos.y] = nil
+                               -- only run this if y axis is empty
+                               if pool[pos.x] and not next(pool[pos.x]) then
+                                       pool[pos.x] = nil
+                               end
+                       end
+               end
+       end
+end
+
 local table_3d
 local temp_pool
 local function create_boundary_box(pos)
@@ -62,14 +125,11 @@ local function create_boundary_box(pos)
                                                        if not table_3d[x] then table_3d[x] = {} end
                                                        if not table_3d[x][y] then table_3d[x][y] = {} end
 
-                                                       if x == pos.x-9 or x == pos.x+9 or 
+                                                       if (x == pos.x-9 or x == pos.x+9 or 
                                                        y == pos.y-9 or y == pos.y+9 or 
-                                                       z == pos.z-9 or z == pos.z+9 then
-                                                               if temp_pool.dust then
-                                                                       table_3d[x][y][z] = {torch=temp_pool.dust}
-                                                               else
-                                                                       table_3d[x][y][z] = temp_pool
-                                                               end
+                                                       z == pos.z-9 or z == pos.z+9) and 
+                                                       temp_pool.dust and temp_pool.dust > 1 then
+                                                               table_3d[x][y][z] = {torch=temp_pool.dust}
                                                        else
                                                                if temp_pool.dust then
                                                                        table_3d[x][y][z] = {dust=0,origin=temp_pool.dust}
@@ -87,23 +147,65 @@ local function create_boundary_box(pos)
 end
 
 
+local function capacitor_pathfind(source,mem_map)
+       for _,order in pairs(order) do
 
-local function data_injection(pos,data)
-       -- add data into 3d memory
-       if data then
-               if not pool[pos.x] then pool[pos.x] = {} end
-               if not pool[pos.x][pos.y] then pool[pos.x][pos.y] = {} end
-               pool[pos.x][pos.y][pos.z] = data
-       --delete data from 3d memory
+               i = add_vec(source,order)
+               if not mem_map[i.x] then mem_map[i.x] = {} end
+               if not mem_map[i.x][i.y] then mem_map[i.x][i.y] = {} end
+
+               if not mem_map[i.x][i.y][i.z] then
+
+                       if i and pool and pool[i.x] and pool[i.x][i.y] and pool[i.x][i.y][i.z] then
+                               index = pool[i.x][i.y][i.z]
+                               if index.capacitor then
+                                       mem_map[i.x][i.y][i.z] = {name = index.name, capacitor = 0, source = index.source}
+                                       if index.source then
+                                               mem_map.found = true
+                                       end
+                                       capacitor_pathfind(i,mem_map)
+                               end
+                       end
+               end
+       end
+       return mem_map,found
+end
+
+local table_3d
+local found
+local temp_pool
+local function capacitor_sniff(pos)
+       table_3d = {}
+       table_3d = capacitor_pathfind(pos,table_3d)
+       found = table_3d.found
+       table_3d.found = nil
+       if found then
+               for x,datax in pairs(table_3d) do
+                       for y,datay in pairs(datax) do
+                               for z,data in pairs(datay) do
+                                       temp_pool = pool[x][y][z]
+                                       if temp_pool then
+                                               temp_pool.capacitor = 1
+                                               if capacitor_table[temp_pool.name] then
+                                                       swap_node(new_vec(x,y,z),{name=capacitor_table[temp_pool.name].on})
+                                                       redstone.update(new_vec(x,y,z))
+                                               end
+                                       end
+                               end
+                       end
+               end
        else
-               if pool and pool[pos.x] and pool[pos.x][pos.y] then
-                       pool[pos.x][pos.y][pos.z] = data
-                       
-                       if pool[pos.x][pos.y] and not next(pool[pos.x][pos.y]) then
-                               pool[pos.x][pos.y] = nil
-                               -- only run this if y axis is empty
-                               if pool[pos.x] and not next(pool[pos.x]) then
-                                       pool[pos.x] = nil
+               for x,datax in pairs(table_3d) do
+                       for y,datay in pairs(datax) do
+                               for z,data in pairs(datay) do
+                                       temp_pool = pool[x][y][z]
+                                       if temp_pool then
+                                               temp_pool.capacitor = 0
+                                               if capacitor_table[temp_pool.name] then
+                                                       swap_node(new_vec(x,y,z),{name=capacitor_table[temp_pool.name].off})
+                                                       redstone.update(new_vec(x,y,z))
+                                               end
+                                       end
                                end
                        end
                end
@@ -111,36 +213,94 @@ local function data_injection(pos,data)
 end
 
 
--- redstone class
-redstone = {}
 
-local path = minetest.get_modpath("redstone")
---dofile(path.."/functions.lua")
---dofile(path.."/wire.lua")
-dofile(path.."/torch.lua")
---dofile(path.."/lever.lua")
---dofile(path.."/button.lua")
---dofile(path.."/repeater.lua")
---dofile(path.."/light.lua")
---dofile(path.."/piston.lua")
---dofile(path.."/comparator.lua")
---dofile(path.."/craft.lua")
---dofile(path.."/ore.lua")
---dofile(path.."/inverter.lua")
---dofile(path.."/player_detector.lua")
---dofile(path.."/space_maker.lua")
---dofile(path.."/pressure_plate.lua")
+-- activators
+local n_pos
+local temp_pool
+local temp_pool2
+local non_directional_activator = function(pos)
+       if pool[pos.x] and pool[pos.x][pos.y] and pool[pos.x][pos.y][pos.z] then
+               temp_pool = pool[pos.x][pos.y][pos.z]
+               for _,order in pairs(order) do
+                       n_pos = add_vec(pos,order)
+                       if pool[n_pos.x] and pool[n_pos.x][n_pos.y] and pool[n_pos.x][n_pos.y][n_pos.z] then
+                               temp_pool2 = pool[n_pos.x][n_pos.y][n_pos.z]
+                               if temp_pool2 then
+                                       if (not temp_pool2.directional_activator and temp_pool2.torch) or 
+                                       (temp_pool2.dust and temp_pool2.dust > 0) or 
+                                       (temp_pool2.torch_directional and vector.equals(temp_pool2.output, pos)) then
+                                               if activator_table[temp_pool.name].activate then
+                                                       activator_table[temp_pool.name].activate(pos)
+                                               end
+                                               return
+                                       end
+                               end
+                       end
+               end     
+               if activator_table[temp_pool.name].deactivate then
+                       activator_table[temp_pool.name].deactivate(pos)
+               end
+       end
+end
+
+-- directional activators
+local n_pos
+local temp_pool
+local temp_pool2
+local input
+local ignore
+local directional_activator = function(pos)
+       
+       ignore = false
+       input = nil
+       temp_pool2 = nil
+
+       temp_pool = pool[pos.x][pos.y][pos.z]
+       
+       if not temp_pool then ignore = true end
+
+       if not ignore then
+               input = temp_pool.input
+       end
+
+       if not input then ignore = true end
+
+       if not ignore then
+               input = temp_pool.input
+       end
+
+       if not ignore and pool and pool[input.x] and pool[input.x][input.y] and pool[input.x][input.y][input.z] then
+               temp_pool2 = pool[input.x][input.y][input.z]
+       else
+               ignore = true
+       end
+
+       if not temp_pool2 then ignore = true end
+
+       if not ignore and ((temp_pool2.dust and temp_pool2.dust > 0) or (temp_pool2.torch and temp_pool2.directional_activator and temp_pool2.dir == temp_pool.dir) or 
+       (not temp_pool2.directional_activator and temp_pool2.torch) or (temp_pool2.capacitor and temp_pool2.capacitor > 0))  then
+               if activator_table[temp_pool.name].activate then
+                       activator_table[temp_pool.name].activate(pos)
+                       return
+               end
+               return
+       end
 
+       if activator_table[temp_pool.name].deactivate then
+               activator_table[temp_pool.name].deactivate(pos)
+       end
+end
 
 --make redstone wire pass on current one level lower than it is
 local i
 local index
 local passed_on_level
-local function redstone_pathfinder(source,source_level,boundary,direction)
+local function redstone_pathfinder(source,source_level,boundary,output)
+       if not source_level then return end
        --directional torches
-       if direction then
-               i = add_vec(source,facedir_to_dir(direction))
-               if boundary and boundary[i.x][i.y][i.z] then
+       if output then
+               i = output
+               if i and boundary and boundary[i.x] and boundary[i.x][i.y] and boundary[i.x][i.y][i.z] then
                        index = boundary[i.x][i.y][i.z]
                        --dust
                        if index.dust then
@@ -154,19 +314,14 @@ local function redstone_pathfinder(source,source_level,boundary,direction)
        else
                --redstone and torch
                for _,order in pairs(order) do
-                       i = add_vec(source,new_vec(order.x,order.y,order.z))
+                       i = add_vec(source,order)
                        if i and boundary and boundary[i.x] and boundary[i.x][i.y] and boundary[i.x][i.y][i.z] then
                                index = boundary[i.x][i.y][i.z]
-
                                if index.dust then
-
                                        passed_on_level = source_level - 1
-
                                        if passed_on_level > 0 and index.dust < source_level then
                                                boundary[i.x][i.y][i.z].dust = passed_on_level
-
                                                redstone_pathfinder(i,passed_on_level,boundary,nil)
-
                                        end
                                end
                        end
@@ -176,83 +331,64 @@ local function redstone_pathfinder(source,source_level,boundary,direction)
 end
 
 
+
+
 --make all power sources push power out
 local pos
 local node
 local power
-
 local boundary
-local function calculate(pos)
-
-       boundary = create_boundary_box(pos)
-
-       --pathfind through memory map   
-       for x,index_x in pairs(boundary) do
-               for y,index_y in pairs(index_x) do
-                       for z,data in pairs(index_y) do
-                               --allow data values for torches
-                               if data.torch then
-                                       redstone_pathfinder(new_vec(x,y,z),data.torch,boundary)
-                                       boundary[x][y][z] = nil
-                               elseif data.torch_directional then
-                                       redstone_pathfinder(new_vec(x,y,z),data.torch,boundary,data.dir)
-                                       boundary[x][y][z] = nil
-                               end
-                       end
-               end
-       end
-
-       --reassemble the table into a position list minetest can understand
-       --run through and set dust
-       for x,datax in pairs(boundary) do
-               for y,datay in pairs(datax) do
-                       for z,data in pairs(datay) do
-                               --print(dump(data))
-                               if data.dust and data.dust ~= data.origin then
-                                       --print("setting:" ..data.dust)
-                                       swap_node(new_vec(x,y,z),{name="redstone:dust_"..data.dust})
+local function calculate(pos,is_capacitor)
+       if not is_capacitor then
+               boundary = create_boundary_box(pos)
+               --pathfind through memory map   
+               for x,index_x in pairs(boundary) do
+                       for y,index_y in pairs(index_x) do
+                               for z,data in pairs(index_y) do
+                                       --allow data values for torches
+                                       if data.torch and not data.torch_directional then
+                                               redstone_pathfinder(new_vec(x,y,z),data.torch,boundary)
+                                               boundary[x][y][z] = nil
+                                       elseif data.torch_directional then
+                                               redstone_pathfinder(new_vec(x,y,z),data.torch,boundary,data.output)
+                                       end
                                end
                        end
                end
-       end
-       --[[
-       for x,datax in pairs(boundary) do
-               for y,datay in pairs(datax) do
-                       for z,data in pairs(datay) do
-                               --directional activators
-                               if data.directional == true then
-                                       power = get_powered_state_directional(new_vec(x,y,z))
-                                       if power then
-                                               if power > 0 then
-                                                       redstone_activate(new_vec(x,y,z),power)
-                                               elseif power == 0 then
-                                                       redstone_deactivate(new_vec(x,y,z),power)
-                                               end
+               --reassemble the table into a position list minetest can understand
+               --run through and set dust
+               for x,datax in pairs(boundary) do
+                       for y,datay in pairs(datax) do
+                               for z,data in pairs(datay) do
+                                       if data.dust and data.dust ~= data.origin then
+                                               swap_node(new_vec(x,y,z),{name="redstone:dust_"..data.dust})
                                        end
-                               --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)
-                                               elseif power == 0 then
-                                                       redstone_deactivate(new_vec(x,y,z),power)
-                                               end
+                                       --write data back to memory pool
+                                       pool[x][y][z] = data
+
+                                       if data.dust then
+                                               --delete the data to speed up next loop
+                                               boundary[x][y][z] = nil
                                        end
                                end
                        end
                end
-       end
-       ]]--
 
-       for x,index_x in pairs(boundary) do
-               for y,index_y in pairs(index_x) do
-                       for z,data in pairs(index_y) do
-                               --write data back to memory pool
-                               pool[x][y][z] = data
+               
+               --this must be done after the memory is written
+               for x,datax in pairs(boundary) do
+                       for y,datay in pairs(datax) do
+                               for z,data in pairs(datay) do
+                                       if data.directional_activator then
+                                               directional_activator(new_vec(x,y,z))
+                                       elseif data.activator then
+                                               non_directional_activator(new_vec(x,y,z))
+                                       end
+                               end
                        end
                end
+       else
+               capacitor_sniff(pos)
        end
 end
 
@@ -262,13 +398,35 @@ function redstone.inject(pos,data)
 end
 
 
-function redstone.update(pos)
-       calculate(pos)
-end
-
-
+local recursion_check = {}
+local bad_node
+function redstone.update(pos,is_capacitor)
+       local s_pos = minetest.serialize(pos)
+       if not recursion_check[s_pos] then
+               recursion_check[s_pos] = 0
+       end
+       recursion_check[s_pos] = recursion_check[s_pos] + 1
+       --print(recursion_check[s_pos])
+       if recursion_check[s_pos] > 6 then
+               minetest.after(0,function()
+                       bad_node = minetest.get_node(pos).name
+                       bad_node = minetest.get_node_drops(bad_node, "main:rubypick")
+                       for _,nodey in pairs(bad_node) do
+                               minetest.throw_item(pos,nodey)
+                       end
+                       minetest.dig_node(pos)
+                       data_injection(pos,nil)
+                       redstone.update(pos)
+               end)
+               return
+       end
 
+       calculate(pos,is_capacitor)
+end
 
+minetest.register_globalstep(function()
+       recursion_check = {}
+end)
 
 
 ----------------------------------------------------------------------------