X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=mods%2Fredstone%2Finit.lua;h=b9030461ab204cc63e99c3428f695c7155762846;hb=db3e7e0a4d893c156e354568eb1ed724a30f8379;hp=fd374e38a8f8f454131e0966db940dcc5cb4d38e;hpb=8b69253cf871ac13782d8b5b0bc30ed1b42c91d0;p=Crafter.git diff --git a/mods/redstone/init.lua b/mods/redstone/init.lua index fd374e3..b903046 100644 --- a/mods/redstone/init.lua +++ b/mods/redstone/init.lua @@ -1,7 +1,9 @@ +--if you attempt to read this, god bless you + local -minetest,vector,math,table,pairs +minetest,vector,math,table,pairs,next = -minetest,vector,math,table,pairs +minetest,vector,math,table,pairs,next -- minetest class local get_node = minetest.get_node @@ -12,6 +14,8 @@ 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 @@ -20,330 +24,711 @@ 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 speed_test +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 -local r_index = {} -local a_index = {} + +-- 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") ---set the data for powered states -local get_local_power = function(pos) - if not pos then - return - end - for x = -1,1 do - for y = -1,1 do - for z = -1,1 do - --index only direct neighbors - if abs(x)+abs(z)+abs(y) == 1 then - --print(get_node(add_vec(new_vec(x,y,z),pos)).name) - if get_item_group(get_node(add_vec(new_vec(x,y,z),pos)).name, "redstone_power") > 0 then - return(1) - end - if get_meta(add_vec(new_vec(x,y,z),pos)):get_int("redstone_power") > 0 then - return(1) +--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(0) end -local power -local pos -local get_powered_state_directional = function(pos) - pos = sub_vec(pos,facedir_to_dir(get_node(pos).param2)) - power = get_item_group(get_node(pos).name, "redstone_power") - if power == 0 then - power = get_meta(pos):get_int("redstone_power") +--[[ + _ __ + ___ | ' \ + ___ \ / ___ ,'\_ | .-. \ /| + \ / | |,'__ \ ,'\_ | \ | | | | ,' |_ /| + _ | | | |\/ \ \ | \ | |\_| _ | |_| | _ '-. .-',' |_ _ +// | | | |____| | | |\_|| |__ // | | ,'_`. | | '-. .-',' `. ,'\_ +\\_| |_,' .-, _ | | | | |\ \ // .| |\_/ | / \ || | | | / |\ \| \ + `-. .-'| |/ / | | | | | | \ \// | | | | | || | | | | |_\ || |\_| + | | | || \_| | | | /_\ \ / | |` | | | || | | | | .---'| | + | | | |\___,_\ /_\ _ // | | | \_/ || | | | | | /\| | + /_\ | | //_____// .||` _ `._,' | | | | \ `-' /| | + /_\ `------' \ | /-\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(power) + return(table_3d) end -local node -local redstone_activate = function(pos,power) - after(0,function() - node = get_node(pos).name - if registered_nodes[node].redstone_activation then - registered_nodes[node].redstone_activation(pos) +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 + + 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) + end + return mem_map end -local node -local redstone_deactivate = function(pos,power) - after(0,function() - node = get_node(pos).name - if registered_nodes[node].redstone_deactivation then - registered_nodes[node].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) + end end ---collect all nodes that are local to the modified ---node of redstone dust and store in memory -local function get_group(i,gotten_group) - return(get_item_group(get_node(i).name, gotten_group)) + + +-- 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 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 -local localredstone = {} + 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 -localredstone.injector = function(i) - if get_node(i).name == "air" then - return + if not ignore then + input = temp_pool.input end - if r_index[i.x] and r_index[i.x][i.y] then - if r_index[i.x][i.y][i.z] then - return - end - end + if not input then ignore = true end - --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} - --the data to the 3d array must be written to memory before this is executed - --or a stack overflow occurs!!! - localredstone.collector(i) - 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")} + if not ignore then + input = temp_pool.input 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 a_index[i.x] then a_index[i.x] = {} end - if not a_index[i.x][i.y] then a_index[i.x][i.y] = {} end - if not a_index[i.x][i.y][i.z] then a_index[i.x][i.y][i.z] = {} end - - a_index[i.x][i.y][i.z].redstone_activation = true - a_index[i.x][i.y][i.z].directional = true + + 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 - - --index objects that activate - if get_group(i,"redstone_activation") > 0 then - if not a_index[i.x] then a_index[i.x] = {} end - if not a_index[i.x][i.y] then a_index[i.x][i.y] = {} end - if not a_index[i.x][i.y][i.z] then a_index[i.x][i.y][i.z] = {} end - a_index[i.x][i.y][i.z].redstone_activation = true + + 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 - --sneaky way to make levers and buttons work - if get_meta(i):get_int("redstone_power") > 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_meta(i):get_int("redstone_power")} + if activator_table[temp_pool.name] and activator_table[temp_pool.name].deactivate then + activator_table[temp_pool.name].deactivate(pos) end end -localredstone.collector = function(pos) - for x = -1,1 do - for y = -1,1 do - for z = -1,1 do - if abs(x)+abs(z) == 1 then - localredstone.injector(add_vec(pos,new_vec(x,y,z))) +--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) + + power = power - 1 + + --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 - end - end + return(mem_map) end -function redstone.collect_info(pos) - localredstone.injector(pos) - localredstone.collector(pos) -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 ---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)) or (a_index and next(a_index)) then - --create the old version to help with deactivation calculation - redstone.calculate() - --clear the index to avoid cpu looping wasting processing power - r_index = {} - a_index = {} - end -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] ---make all power sources push power out -local x_min -local x_max -local y_min -local y_max -local z_min -local z_max -local initial_check + if index.dust then + mem_map[i.x][i.y][i.z] = true -local pos -local node -local power -function redstone.calculate() - speed_test = minetest.get_us_time()/1000000 - - --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(new_vec(x,y,z),data.power) - r_index[x][y][z] = nil - elseif data.torch_directional then - redstone.pathfind(new_vec(x,y,z),data.power,data.dir) - r_index[x][y][z] = nil - end - end - end - end - - print("total torch calc time:"..minetest.get_us_time()/1000000-speed_test) + 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 - --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 - --print(get_node(new_vec(x,y,z)).name) - if index and index.dust then - minetest.set_node(new_vec(x,y,z),{name="redstone:dust_"..index.level}) + 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 + else + --print("single position index") + + i = pos - for x,datax in pairs(a_index) do - for y,datay in pairs(datax) do - for z,index in pairs(datay) do - --directional activators - if index.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 - end - --non directional activators - else - power = get_local_power(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 + + 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 -local i -local index -local passed_on_level -local function redstone_pathfinder(source,source_level,direction) - --directional torches +--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 - if direction then - --print("starting direction") - i = add_vec(source,facedir_to_dir(direction)) - if r_index and r_index[i.x] and r_index[i.x][i.y] and r_index[i.x][i.y][i.z] then - index = r_index[i.x][i.y][i.z] - --dust - if index.dust then - passed_on_level = source_level - 1 - if passed_on_level > 0 then - r_index[i.x][i.y][i.z].level = passed_on_level - redstone_pathfinder(i,passed_on_level,nil,origin) + -- 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 - if abs(x)+abs(z) == 1 then - i = add_vec(source,new_vec(x,y,z)) - if r_index and r_index[i.x] and r_index[i.x][i.y] and r_index[i.x][i.y][i.z] then - index = r_index[i.x][i.y][i.z] - if index.dust then - passed_on_level = source_level - 1 - if passed_on_level > 0 and index.level < source_level then - r_index[i.x][i.y][i.z].level = passed_on_level - redstone_pathfinder(i,passed_on_level,nil) + --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.pathfind(source,source_level,direction) - redstone_pathfinder(source,source_level,direction) + + +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) + ---------------------------------------------------------------------------- @@ -401,26 +786,20 @@ minetest.register_craftitem("redstone:dust", { 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, }) ---8 power levels 8 being the highest -local color = 0 +--15 power levels 15 being the highest for i = 0,8 do - local coloring = 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", @@ -437,13 +816,22 @@ for i = 0,8 do 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,registered_nodes[get_node(pos).name].power) - redstone.collect_info(pos) + 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