X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=mods%2Fredstone%2Finit.lua;h=74c4f34f5a593cb1c8703a5a8a9387515999b06a;hb=9b547ff83a37f254c6a112ee3107d0e45a19224e;hp=c3977d9a649c09d623977bc4b67f12474ff6b8cf;hpb=d58a836db3954ee77be759ce7ee6826a35e56037;p=Crafter.git diff --git a/mods/redstone/init.lua b/mods/redstone/init.lua index c3977d9..74c4f34 100644 --- a/mods/redstone/init.lua +++ b/mods/redstone/init.lua @@ -1,384 +1,709 @@ ---[[ -might have to calculate this in a local memory table then set the nodes using a voxelmanip -]]-- +--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 = {} + +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 ----set a torch source +-- 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.."/wire.lua") +dofile(path.."/functions.lua") dofile(path.."/torch.lua") -dofile(path.."/switches.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.."/capacitors.lua") +dofile(path.."/breaker.lua") -redstone = {} -local r_index = {} +--this is written out manually so that +--math.abs is not needed +local order = { + {x=0,y=0,z=0}, -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 + {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) -end +--[[ + _ __ + ___ | ' \ + ___ \ / ___ ,'\_ | .-. \ /| + \ / | |,'__ \ ,'\_ | \ | | | | ,' |_ /| + _ | | | |\/ \ \ | \ | |\_| _ | |_| | _ '-. .-',' |_ _ +// | | | |____| | | |\_|| |__ // | | ,'_`. | | '-. .-',' `. ,'\_ +\\_| |_,' .-, _ | | | | |\ \ // .| |\_/ | / \ || | | | / |\ \| \ + `-. .-'| |/ / | | | | | | \ \// | | | | | || | | | | |_\ || |\_| + | | | || \_| | | | /_\ \ / | |` | | | || | | | | .---'| | + | | | |\___,_\ /_\ _ // | | | \_/ || | | | | | /\| | + /_\ | | //_____// .||` _ `._,' | | | | \ `-' /| | + /_\ `------' \ | /-\ND _ `.\ | | `._,' /_\ + \| |HE `.\ + __ _ _ __ _ + / |__| /_\ |\ /| |_) |_ |_) + \__ | | / \ | \/ | |_) |__ | \ + _ _ + (_)|- ___ __ __ __ + | /\ |__)| |_ (_ + | /--\|__)|__|____) +]]-- -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) + +local table_3d +local temp_pool +local function create_boundary_box(pos) + table_3d = {} + for x = pos.x-16,pos.x+16 do + if pool[x] then + for y = pos.y-16,pos.y+16 do + if pool[x][y] then + for z = pos.z-16,pos.z+16 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-16 or x == pos.x+16 or + y == pos.y-16 or y == pos.y+16 or + z == pos.z-16 or z == pos.z+16) 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 +local i +local index +local function capacitor_pathfind(source,mem_map) + for _,order in pairs(order) do -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) + 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 - 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) - end + --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 - 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 + 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 - 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 + return(mem_map) +end - 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 index.dust then - data[p_pos] = minetest.get_content_id("redstone:dust_"..index.level) + +--[[ + , + ,. | \ + |: \ ; :\ + :' ;\| ::\ + \ : | `::\ + _) | `:`. + ,' , `. ;: ; + ,' ;: ;"' ,:: |_ + /, ` . ;::: |:`-.__ + _,' _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 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) - 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) + else + --print("single position index") + + i = pos + + + 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(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 + return mem_map 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) +--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 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 - 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) + --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 + + --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 + + --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 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 + 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 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(17-vector_distance(pos2,pos)) + if power > 16 then + power = 16 + 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 + +minetest.register_globalstep(function() + player_detector_calculation() + recursion_check = {} +end) ---------------------------------------------------------------------------- @@ -424,31 +749,33 @@ minetest.register_craftitem("redstone:dust", { on_place = function(itemstack, placer, pointed_thing) if not pointed_thing.type == "node" then return + end + local sneak = placer:get_player_control().sneak + 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 end - local pos = pointed_thing.above - if minetest.registered_nodes[minetest.get_node({x=pos.x,y=pos.y-1,z=pos.z}).name].walkable and minetest.get_node(pointed_thing.above).name == "air" then - minetest.add_node(pointed_thing.above, {name="redstone:dust_0"}) - itemstack:take_item(1) - --print(minetest.get_node(pointed_thing.above).param1) - --minetest.after(0,function(pointed_thing) - -- redstone.add(pos) - --end,pointed_thing) + + local _,worked = minetest.item_place(ItemStack("redstone:dust_0"), placer, pointed_thing) + if worked then + itemstack:take_item() return(itemstack) end end, }) +--15 power levels 15 being the highest +for i = 0,15 do ---8 power levels 8 being the highest -local color = 0 -for i = 0,8 do - local coloring = math.floor(color) + local color = floor(255 * (i/15)) + 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", @@ -461,16 +788,26 @@ for i = 0,8 do type = "fixed", fixed = {-1/2, -1/2, -1/2, 1/2, -1/2+1/16, 1/2}, }, - groups={dig_immediate=1,attached=1,redstone_dust=1,redstone=1,redstone_power=i}, + sounds = main.stoneSound(), + 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