---define the class
+--if you attempt to read this, god bless you
+
+local
+minetest,vector,math,table,pairs,next
+=
+minetest,vector,math,table,pairs,next
+
+-- minetest class
+local get_node = minetest.get_node
+local get_item_group = minetest.get_item_group
+local get_meta = minetest.get_meta
+local facedir_to_dir = minetest.facedir_to_dir
+local content_id = minetest.get_name_from_content_id
+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
+end)
+
+-- math class
+local abs = math.abs
+local floor = math.floor
+local ceil = math.ceil
+
+-- vector library
+local new_vec = vector.new
+local add_vec = vector.add
+local sub_vec = vector.subtract
+local vector_distance = vector.distance
+local vec_equals = vector.equals
+
+local activator_table = {} -- this holds the translation data of activator tables (activator functions)
+local capacitor_table = {}
+local player_detection_table = {}
+
+-- redstone class
redstone = {}
-local r_index = {}
+
+redstone.player_detector_add = function(pos)
+ player_detection_table[minetest.serialize(pos)] = pos
+end
+
+redstone.player_detector_remove = function(pos)
+ player_detection_table[minetest.serialize(pos)] = nil
+end
+
+
+-- 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.."/comparator.lua")
dofile(path.."/craft.lua")
-dofile(path.."/ore.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.."/pressure_plate.lua")
+dofile(path.."/capacitors.lua")
+dofile(path.."/breaker.lua")
+dofile(path.."/detector.lua")
-get_old_power = function(pos)
- local meta = minetest.get_meta(pos)
- local oldpower = meta:get_int("old_power")
- return(oldpower)
-end
---set the data for powered states
-get_local_power = function(pos)
- local max_level = 0
- for x = -1,1 do
- for y = -1,1 do
- for z = -1,1 do
- --index only direct neighbors
- if not (math.abs(x)+math.abs(z) > 1) or (math.abs(x)+math.abs(z) == 0) then
- --print(minetest.get_node(vector.add(vector.new(x,y,z),pos)).name)
- local level = minetest.get_node_group(minetest.get_node(vector.add(vector.new(x,y,z),pos)).name, "redstone_power")
- if level > max_level then
- max_level = level
+--this is written out manually so that
+--math.abs is not needed
+local order = {
+ {x=0,y=0,z=0},
+
+ {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},
+}
+
+--thanks to RhodiumToad for helping me figure out a good method to do this
+
+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
- end
- return(max_level)
end
---this is used for a power state comparison
-set_old_power = function(pos,level)
- local meta = minetest.get_meta(pos)
- meta:set_int("old_power",level)
+--[[
+ _ __
+ ___ | ' \
+ ___ \ / ___ ,'\_ | .-. \ /|
+ \ / | |,'__ \ ,'\_ | \ | | | | ,' |_ /|
+ _ | | | |\/ \ \ | \ | |\_| _ | |_| | _ '-. .-',' |_ _
+// | | | |____| | | |\_|| |__ // | | ,'_`. | | '-. .-',' `. ,'\_
+\\_| |_,' .-, _ | | | | |\ \ // .| |\_/ | / \ || | | | / |\ \| \
+ `-. .-'| |/ / | | | | | | \ \// | | | | | || | | | | |_\ || |\_|
+ | | | || \_| | | | /_\ \ / | |` | | | || | | | | .---'| |
+ | | | |\___,_\ /_\ _ // | | | \_/ || | | | | | /\| |
+ /_\ | | //_____// .||` _ `._,' | | | | \ `-' /| |
+ /_\ `------' \ | /-\ND _ `.\ | | `._,' /_\
+ \| |HE `.\
+ __ _ _ __ _
+ / |__| /_\ |\ /| |_) |_ |_)
+ \__ | | / \ | \/ | |_) |__ | \
+ _ _
+ (_)|- ___ __ __ __
+ | /\ |__)| |_ (_
+ | /--\|__)|__|____)
+]]--
+
+
+local table_3d
+local temp_pool
+local function create_boundary_box(pos)
+ table_3d = {}
+ for x = pos.x-9,pos.x+9 do
+ if pool[x] then
+ for y = pos.y-9,pos.y+9 do
+ if pool[x][y] then
+ for z = pos.z-9,pos.z+9 do
+ temp_pool = pool[x][y][z]
+ if temp_pool then
+ 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
+ y == pos.y-9 or y == pos.y+9 or
+ 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}
+ else
+ table_3d[x][y][z] = temp_pool
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+ return(table_3d)
end
-get_powered_state_directional = function(pos)
- local meta = minetest.get_meta(pos)
- local node = minetest.get_node(pos)
- local param2 = node.param2
- local dir = minetest.facedir_to_dir(param2)
- local input_pos = vector.subtract(pos,dir)
- local behind_node = minetest.get_node(input_pos)
- local level = minetest.get_node_group(behind_node.name, "redstone_power")
- return(level)
-end
+local i
+local index
+local function capacitor_pathfind(source,mem_map)
+ for _,order in pairs(order) do
+
+ 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
-local redstone_activate = function(name,pos,power)
- minetest.after(0,function(name,pos)
- if minetest.registered_nodes[name].redstone_activation then
- minetest.registered_nodes[name].redstone_activation(pos)
+ 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
- set_old_power(pos,power)
- end,name,pos,power)
+ return mem_map
end
-local redstone_deactivate = function(name,pos,power)
- minetest.after(0,function(name,pos)
- if minetest.registered_nodes[name].redstone_deactivation then
- minetest.registered_nodes[name].redstone_deactivation(pos)
+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
+ 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
- set_old_power(pos,power)
- end,name,pos,power)
end
-local redstone_update = function(name,pos,power)
- minetest.after(0,function(name,pos,power)
- if minetest.registered_nodes[name].redstone_update then
- minetest.registered_nodes[name].redstone_update(pos)
+
+
+-- 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]
+ if temp_pool then
+ 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] and 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] and activator_table[temp_pool.name].deactivate then
+ activator_table[temp_pool.name].deactivate(pos)
+ end
+ end
end
- set_old_power(pos,power)
- end,name,pos,power)
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_pool = nil
+ temp_pool2 = nil
+ if not (pool[pos.x] and pool[pos.x][pos.y] and pool[pos.x][pos.y][pos.z]) then return end
+
+ 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
---collect all nodes that are local to the modified
---node of redstone dust and store in memory
-function redstone.collect_info(pos)
- --if table.getn(r_index) == 0 then
- --print("-----------------------")
- --print("started indexing")
- --end
- local get_node = minetest.get_node
- local group = minetest.get_node_group
-
- local function get_group(i,gotten_group)
- return(group(get_node(i).name, gotten_group))
+ if not ignore then
+ input = temp_pool.input
end
-
- for x = -1,1 do
- for y = -1,1 do
- for z = -1,1 do
- --index only direct neighbors
- if not (math.abs(x)+math.abs(z) > 1) or (math.abs(x)+math.abs(z) == 0) then
- local r_type = ""
- local i = vector.add(pos,vector.new(x,y,z))
- local execute_collection = true
- if r_index[i.x] and r_index[i.x][i.y] then
- if r_index[i.x][i.y][i.z] then
- execute_collection = false
- end
- end
- --[[ EXPLANATION
- we run through the groups
- 1 redstone_torch overrides dust if defined
- 2 torch_directional overrides torch if defined
- 3 redstone activation is bolted on with directional overriding general
-
- this is to prevent weird behavior
-
-
- This new method also uses a table bolted onto the x,y,z positional data value
- what does this mean?
- It's much easier to work with and modify
- ]]--
-
- if execute_collection == true then
- --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} --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!!!
- --pass down info for activators
- redstone.collect_info(i,get_group(i,"redstone_power"))
- end
- --index power sources
- 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_group(i,"redstone_power")}
- end
- --index directional power sources (Like repeaters/comparators)
- --only outputs forwards
- 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_group(i,"redstone_power")}
- end
-
- --index directional activators (Like repeaters/comparators)
- --only accepts input from the back
- if get_group(i,"redstone_activation_directional") > 0 then
- --print("indexing directional")
- 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
- if not r_index[i.x][i.y][i.z] then r_index[i.x][i.y][i.z] = {} end
- --r_index[i.x][i.y][i.z].activate = false
- r_index[i.x][i.y][i.z].redstone_activation = true
- r_index[i.x][i.y][i.z].directional = true
- r_index[i.x][i.y][i.z].dir = get_node(i).param2
- end
-
- --index objects that activate
- if get_group(i,"redstone_activation") > 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
- if not r_index[i.x][i.y][i.z] then r_index[i.x][i.y][i.z] = {} end
- --r_index[i.x][i.y][i.z].activate = false
- r_index[i.x][i.y][i.z].redstone_activation = true
- r_index[i.x][i.y][i.z].name = get_node(i).name
-
-
- --set_powered_state(i)
-
- --local powered = get_powered_state(i)
-
-
- --print("powered:"..powered,"oldpowered:"..old_powered)
-
- --r_index[i.x][i.y][i.z].powered = powered
- --r_index[i.x][i.y][i.z].old_powered = old_powered
-
- --split this into update up and down
- --if powered > old_powered then
- -- r_index[i.x][i.y][i.z].deactivate = true
- ---elseif powered > 0 and old_powered == 0 then
- -- r_index[i.x][i.y][i.z].deactivate = true
- --end
- end
- end
- 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] and activator_table[temp_pool.name].activate then
+ activator_table[temp_pool.name].activate(pos)
+ return
+ end
+ return
end
+
+ if activator_table[temp_pool.name] and 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 x,y,z
+local function redstone_distribute(pos,power,mem_map,output)
---check if index table contains items
---then execute an update
-minetest.register_globalstep(function(dtime)
- --if indexes exist then calculate redstone
- if r_index and next(r_index) then
- --create the old version to help with deactivation calculation
- r_copy = table.copy(r_index)
- redstone.calculate()
- end
- --clear the index to avoid cpu looping wasting processing power
- r_index = {}
-end)
+ power = power - 1
---make all power sources push power out
-function redstone.calculate()
- --pathfind through memory map
- for x,index_x in pairs(r_index) 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.pathfind(vector.new(x,y,z),data.power)
- elseif data.torch_directional then
- redstone.pathfind(vector.new(x,y,z),data.power,data.dir)
+ --directional torches
+ if output then
+ x=output.x
+ y=output.y
+ z=output.z
+ if mem_map.dust[x] and mem_map.dust[x][y] and mem_map.dust[x][y][z] then
+ if mem_map.dust[x][y][z].dust < power then
+ mem_map.dust[x][y][z].dust = power
+ redstone_distribute(new_vec(x,y,z),power,mem_map,nil)
+ end
+ end
+ else
+ --redstone and torch
+ for _,order in pairs(order) do
+ i = add_vec(pos,order)
+ x=i.x
+ y=i.y
+ z=i.z
+ if mem_map.dust[x] and mem_map.dust[x][y] and mem_map.dust[x][y][z] then
+ if mem_map.dust[x][y][z].dust < power then
+ mem_map.dust[x][y][z].dust = power
+ redstone_distribute(new_vec(x,y,z),power,mem_map,nil)
end
end
end
end
-
- --calculate values for voxel manip
- local x_min,x_max,y_min,y_max,z_min,z_max
- for x,index_x in pairs(r_index) do
- for y,index_y in pairs(index_x) do
- for z,_ in pairs(index_y) do
- --do this because the root (x) will always come first
- if not x_min then
- x_min = x
- x_max = x
- y_min = y
- y_max = y
- z_min = z
- z_max = z
+ return(mem_map)
+end
+
+
+--[[
+ ,
+ ,. | \
+ |: \ ; :\
+ :' ;\| ::\
+ \ : | `::\
+ _) | `:`.
+ ,' , `. ;: ;
+ ,' ;: ;"' ,:: |_
+ /, ` . ;::: |:`-.__
+ _,' _o\ ,::.`:' ; ; . '
+ _,-' `:. ;""\,
+ ,-' ,: `-;,
+ \, ;: ;--._
+ `.______,-,----._ ,' ;: ,/ , ,`
+ / /,-';' \ ; `: ,'/,::.:::
+ ,',;-'-'_,--; ; :. ,',',;::::::
+ ( /___,-' `. ;::,,'o/ ,:::::::
+ `' ) ;:,'o / ;"- -::
+ \__ _,'o ,' ,::
+ ) `--' ,..::::
+ ; `. ,:::::::
+ ; ``::. :::::::
+]]-- sic em boy!
+local i
+local index
+local function dust_sniff(pos,mem_map,boundary,single,origin,ignore)
+ if not single then
+ --print("all position index--")
+ for _,order in pairs(order) do
+ i = add_vec(pos,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 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
+
+ mem_map[i.x][i.y][i.z] = true
+
+ if not mem_map.dust[i.x] then mem_map.dust[i.x] = {} end
+ if not mem_map.dust[i.x][i.y] then mem_map.dust[i.x][i.y] = {} end
+
+ mem_map.dust[i.x][i.y][i.z] = index
+
+ dust_sniff(i,mem_map,boundary)
+
+ elseif index.torch and index.torch > 1 then
+ if index.torch_directional and vec_equals(pos,index.output) then
+
+ mem_map[i.x][i.y][i.z] = true
+
+ if not mem_map.torch[i.x] then mem_map.torch[i.x] = {} end
+ if not mem_map.torch[i.x][i.y] then mem_map.torch[i.x][i.y] = {} end
+
+ mem_map.torch[i.x][i.y][i.z] = index
+
+
+ elseif not index.torch_directional then
+
+ mem_map[i.x][i.y][i.z] = true
+
+ if not mem_map.torch[i.x] then mem_map.torch[i.x] = {} end
+ if not mem_map.torch[i.x][i.y] then mem_map.torch[i.x][i.y] = {} end
+
+ mem_map.torch[i.x][i.y][i.z] = index
+ end
+ end
+
+ if index.activator then
+ mem_map[i.x][i.y][i.z] = true
+
+ if not mem_map.activator[i.x] then mem_map.activator[i.x] = {} end
+ if not mem_map.activator[i.x][i.y] then mem_map.activator[i.x][i.y] = {} end
+
+ mem_map.activator[i.x][i.y][i.z] = index
+ elseif index.directional_activator and vec_equals(pos,index.input) then
+
+ mem_map[i.x][i.y][i.z] = true
+
+ if not mem_map.activator[i.x] then mem_map.activator[i.x] = {} end
+ if not mem_map.activator[i.x][i.y] then mem_map.activator[i.x][i.y] = {} end
+
+ mem_map.activator[i.x][i.y][i.z] = index
+ end
end
- if x < x_min then x_min = x end
- if x > x_max then x_max = x end
- if y < y_min then y_min = y end
- if y > y_max then y_max = y end
- if z < z_min then z_min = z end
- if z > z_max then z_max = z end
end
end
- end
+ else
+ --print("single position index")
+
+ i = pos
- local min = vector.new(x_min,y_min,z_min)
- local max = vector.new(x_max,y_max,z_max)
- local vm = minetest.get_voxel_manip()
- local emin, emax = vm:read_from_map(min,max)
- local area = VoxelArea:new{MinEdge=emin, MaxEdge=emax}
- local data = vm:get_data()
- local content_id = minetest.get_name_from_content_id
- --reassemble the table into a position list minetest can understand
-
- --run through and set dust
- for x,datax in pairs(r_index) do
- for y,datay in pairs(datax) do
- for z,index in pairs(datay) do
- local p_pos = area:index(x,y,z)
+
+ 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 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
- data[p_pos] = minetest.get_content_id("redstone:dust_"..index.level)
+
+ mem_map[i.x][i.y][i.z] = true
+
+ if not mem_map.dust[i.x] then mem_map.dust[i.x] = {} end
+ if not mem_map.dust[i.x][i.y] then mem_map.dust[i.x][i.y] = {} end
+
+ mem_map.dust[i.x][i.y][i.z] = index
+
+ dust_sniff(i,mem_map,boundary)
+
+ elseif index.torch and index.torch > 1 then
+ if index.torch_directional and (vec_equals(origin,index.output) or ignore) then
+
+ mem_map[i.x][i.y][i.z] = true
+
+ if not mem_map.torch[i.x] then mem_map.torch[i.x] = {} end
+ if not mem_map.torch[i.x][i.y] then mem_map.torch[i.x][i.y] = {} end
+
+ mem_map.torch[i.x][i.y][i.z] = index
+
+
+ elseif not index.torch_directional then
+
+ mem_map[i.x][i.y][i.z] = true
+
+ if not mem_map.torch[i.x] then mem_map.torch[i.x] = {} end
+ if not mem_map.torch[i.x][i.y] then mem_map.torch[i.x][i.y] = {} end
+
+ mem_map.torch[i.x][i.y][i.z] = index
+ end
+ end
+
+ if index.activator then
+ mem_map[i.x][i.y][i.z] = true
+
+ if not mem_map.activator[i.x] then mem_map.activator[i.x] = {} end
+ if not mem_map.activator[i.x][i.y] then mem_map.activator[i.x][i.y] = {} end
+
+ mem_map.activator[i.x][i.y][i.z] = index
+ elseif index.directional_activator and (vec_equals(origin,index.input) or ignore) then
+
+ mem_map[i.x][i.y][i.z] = true
+
+ if not mem_map.activator[i.x] then mem_map.activator[i.x] = {} end
+ if not mem_map.activator[i.x][i.y] then mem_map.activator[i.x][i.y] = {} end
+
+ mem_map.activator[i.x][i.y][i.z] = index
end
end
end
end
- vm:set_data(data)
- vm:write_to_map()
-
-
-
- --run through activators
- for x,datax in pairs(r_index) do
- for y,datay in pairs(datax) do
- for z,index in pairs(datay) do
- local pos = vector.new(x,y,z)
- local node = minetest.get_node(pos)
- --directional activators
- if index.redstone_activation == true and index.directional == true then
- local power = get_powered_state_directional(pos)
- local old_power = get_old_power(pos)
- if power > 0 and old_power == 0 then
- redstone_activate(node.name,pos,power)
- elseif power == 0 and old_power > 0 then
- redstone_deactivate(node.name,pos,power)
- --do an update if state has not changed
- elseif power > 0 and old_power > 0 then
- redstone_update(node.name,pos,power)
- elseif power == 0 and old_power == 0 then
- redstone_update(node.name,pos,power)
+ return mem_map
+end
+
+--make all power sources push power out
+local pos
+local node
+local power
+local boundary
+local dust_detected
+local dust_map
+local pos3
+local temp_pool3
+local directional
+local function calculate(pos,is_capacitor)
+ if not is_capacitor then
+ boundary = create_boundary_box(pos)
+ dust_map = {}
+
+ dust_map.dust = {}
+ dust_map.torch = {}
+ dust_map.activator = {}
+
+ dust_detected = false
+
+ directional = false
+
+ if boundary[pos.x] and boundary[pos.x][pos.y] and boundary[pos.x][pos.y][pos.z] then
+ if boundary[pos.x][pos.y][pos.z].torch_directional or boundary[pos.x][pos.y][pos.z].directional_activator then
+ directional = true
+ end
+ end
+
+ -- sniff all possible dust within boundaries
+ if not directional then
+ dust_sniff(pos,dust_map,boundary)
+ for _,pos2 in pairs(order) do
+ pos3 = add_vec(pos,pos2)
+ if boundary[pos3.x] and boundary[pos3.x][pos3.y] and boundary[pos3.x][pos3.y][pos3.z] and
+ not (dust_map[pos3.x] and dust_map[pos3.x][pos3.y] and dust_map[pos3.x][pos3.y][pos3.z]) then
+ temp_pool3 = boundary[pos3.x][pos3.y][pos3.z]
+ if temp_pool3.dust then
+ dust_sniff(pos3,dust_map,boundary)
end
- --non directional activators
- elseif index.redstone_activation == true then
- local power = get_local_power(pos)
- local old_power = get_old_power(pos)
- if power > 0 and old_power == 0 then
- redstone_activate(node.name,pos,power)
- elseif power == 0 and old_power > 0 then
- redstone_deactivate(node.name,pos,power)
- --do an update if state has not changed
- elseif power > 0 and old_power > 0 then
- redstone_update(node.name,pos,power)
- elseif power == 0 and old_power == 0 then
- redstone_update(node.name,pos,power)
+ end
+ end
+ else
+ dust_sniff(pos,dust_map,boundary,true,pos,true)
+
+ local input = boundary[pos.x][pos.y][pos.z].input
+ local output = boundary[pos.x][pos.y][pos.z].output
+
+ if input and boundary[input.x] and boundary[input.x][input.y] and boundary[input.x][input.y][input.z] then
+ dust_sniff(input,dust_map,boundary,true,pos)
+ end
+ if output and boundary[output.x] and boundary[output.x][output.y] and boundary[output.x][output.y][output.z] then
+ dust_sniff(output,dust_map,boundary,true,pos)
+ end
+ end
+ --do torches
+ for x,datax in pairs(dust_map.torch) do
+ for y,datay in pairs(datax) do
+ for z,data in pairs(datay) do
+ if data.torch then
+ if data.torch_directional then
+ redstone_distribute(new_vec(x,y,z),data.torch,dust_map,data.output)
+ else
+ redstone_distribute(new_vec(x,y,z),data.torch,dust_map)
+ end
end
end
end
end
- end
-end
---make redstone wire pass on current one level lower than it is
-function redstone.pathfind(source,source_level,direction)
- --directional torches
- if direction then
- --print("starting direction")
- local dir = minetest.facedir_to_dir(direction)
- local i = vector.add(source,dir)
- 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
- local index = r_index[i.x][i.y][i.z]
- --dust
- if index.dust then
- local 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.pathfind(i,passed_on_level)
+ --set dust, set pool memory
+ for x,datax in pairs(dust_map.dust) 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})
+ data_injection(new_vec(x,y,z),data)
+ end
end
end
end
- else
- --redstone and torch
- for x = -1,1 do
- for y = -1,1 do
- for z = -1,1 do
- local i = vector.add(source,vector.new(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
- local index = r_index[i.x][i.y][i.z]
- if index.dust then
- local 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.pathfind(i,passed_on_level)
+
+ --activators
+ --this must be run at the end
+ for x,datax in pairs(dust_map.activator) 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
+
+
+function redstone.inject(pos,data)
+ data_injection(pos,data)
+end
+
+
+
+local level
+local pos2
+local power
+local max
+local function player_detector_calculation()
+ for _,pos in pairs(player_detection_table) do
+ level = pool[pos.x][pos.y][pos.z].torch
+ max = 0
+ for _,player in ipairs(minetest.get_connected_players()) do
+ pos2 = player:get_pos()
+ power = floor(11-vector_distance(pos2,pos))
+ if power > 9 then
+ power = 9
+ elseif power < 0 then
+ power = 0
+ end
+
+ if power > max then
+ max = power
+ end
end
+
+ if max ~= level then
+ swap_node(pos,{name="redstone:player_detector_"..max})
+ redstone.inject(pos,{
+ name = "redstone:player_detector_"..max,
+ torch = max,
+ })
+ redstone.update(pos)
end
end
end
+local recursion_check = {}
+local bad_node
+local queue = {}
+function redstone.update(pos,is_capacitor)
+ local count = table.getn(queue)
+ 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
+ if recursion_check[s_pos] > 25 then
+ --print(recursion_check[s_pos])
+ 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.remove_node(pos)
+ data_injection(pos,nil)
+ redstone.update(pos)
+ end)
+ return
+ end
+ calculate(pos,is_capacitor)
+end
+local dtime_goal = 0.02
+local sleep = 0
+minetest.register_globalstep(function(dtime)
+ player_detector_calculation()
+ recursion_check = {}
+ --[[
+ if dtime > dtime_goal then
+ sleep = dtime - dtime_goal
+ end
+ if sleep == 0 then
+ for index,element in pairs(queue) do
+ calculate(element.pos,element.is_capacitor)
+ end
-
+ queue = {}
+
+ else
+ sleep = sleep - dtime
+ if sleep <= 0 then
+ sleep = 0
+ end
+ end
+ ]]--
+end)
----------------------------------------------------------------------------
return
end
local sneak = placer:get_player_control().sneak
- local noddef = minetest.registered_nodes[minetest.get_node(pointed_thing.under).name]
+ local noddef = registered_nodes[get_node(pointed_thing.under).name]
if not sneak and noddef.on_rightclick then
minetest.item_place(itemstack, placer, pointed_thing)
return
itemstack:take_item()
return(itemstack)
end
-
-
- --minetest.add_node(pointed_thing.above, {name="redstone:dust_0"})
- --itemstack:take_item(1)
- --minetest.sound_play("stone", {pos=pointed_thing.above})
- --return(itemstack)
- --end
end,
})
-minetest.register_craft({
- type = "shapeless",
- output = "redstone:dust",
- recipe = {"redstone:dust"},
-})
-
---8 power levels 8 being the highest
-local color = 0
+--15 power levels 15 being the highest
for i = 0,8 do
- local coloring = math.floor(color)
+
+ local color = floor(255 * (i/8))
+
minetest.register_node("redstone:dust_"..i,{
description = "Redstone Dust",
wield_image = "redstone_dust_item.png",
tiles = {
- "redstone_dust_main.png^[colorize:red:"..coloring, "redstone_turn.png^[colorize:red:"..coloring,
- "redstone_t.png^[colorize:red:"..coloring, "redstone_cross.png^[colorize:red:"..coloring
+ "redstone_dust_main.png^[colorize:red:"..color, "redstone_turn.png^[colorize:red:"..color,
+ "redstone_t.png^[colorize:red:"..color, "redstone_cross.png^[colorize:red:"..color
},
power=i,
drawtype = "raillike",
groups={dig_immediate=1,attached_node=1,redstone_dust=1,redstone=1,redstone_power=i},
drop="redstone:dust",
on_construct = function(pos)
- redstone.collect_info(pos)
+ data_injection(pos,{dust=i})
+ calculate(pos)
end,
after_destruct = function(pos)
- --redstone.remove(pos,minetest.registered_nodes[minetest.get_node(pos).name].power)
- redstone.collect_info(pos,i)
+ data_injection(pos,nil)
+ calculate(pos)
end,
connects_to = {"group:redstone"},
})
- color= color +31.875
+
+ minetest.register_lbm({
+ name = "redstone:"..i,
+ nodenames = {"redstone:dust_"..i},
+ run_at_every_load = true,
+ action = function(pos)
+ data_injection(pos,{dust=i})
+ end,
+ })
end