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 = {
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)
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}
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
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
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
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
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)
----------------------------------------------------------------------------