---[[
+local
+minetest,vector,math,table,pairs
+=
+minetest,vector,math,table,pairs
-redstone powder is raillike
+-- 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
-check if solid block above
---if so, do not conduct above
+local swap_node = minetest.swap_node
+local registered_nodes
+minetest.register_on_mods_loaded(function()
+ registered_nodes = minetest.registered_nodes
+end)
-uses height level to do powerlevel
+-- math class
+local abs = math.abs
+local floor = math.floor
-uses lightlevel
-a function for adding and removing redstone level
+-- vector library
+local new_vec = vector.new
+local add_vec = vector.add
+local sub_vec = vector.subtract
+local vector_distance = vector.distance
-]]--
+--this is written out manually so that
+--math.abs is not needed
+local order = {
+ {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},
----set a torch source
+ {x=1, y=-1, z=0}, {x=-1, y=-1, z= 0},
+ {x=0, y=-1, z=1}, {x= 0, y=-1, z=-1},
+}
+-- redstone class
+redstone = {}
+
+local speed_test
+local r_index = {}
+local a_index = {}
+local check_table = {}
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")
-redstone = {}
---3d plane direct neighbor
-function redstone.update(pos,oldnode)
- local old_max_level = minetest.registered_nodes[minetest.get_node(pos).name].power
- --recover old info
- if not old_max_level then
- print("recovering")
- old_max_level = minetest.registered_nodes[oldnode.name].power
- end
-
- local max_level = 0
- for x = -1,1 do
- for y = -1,1 do
- for z = -1,1 do
- if math.abs(x)+math.abs(y)+math.abs(z) == 1 then
- local pos2 = vector.add(pos,vector.new(x,y,z))
- local level2 = minetest.registered_nodes[minetest.get_node(pos2).name].power
- if level2 and level2 > max_level then
- max_level = level2 - 1
- end
- end
- end
- end
- end
-
- --print(max_level)
- if old_max_level and old_max_level > max_level then
- max_level = 0
- end
- --change to dust
- if minetest.get_node_group(minetest.get_node(pos).name, "redstone_dust") > 0 then
- minetest.set_node(pos, {name="redstone:dust_"..max_level})
- end
-
- for x = -1,1 do
- for y = -1,1 do
- for z = -1,1 do
- if math.abs(x)+math.abs(y)+math.abs(z) == 1 then
- local pos2 = vector.add(pos,vector.new(x,y,z))
- local level2 = minetest.registered_nodes[minetest.get_node(pos2).name].power
- if level2 and (level2 < max_level or level2 < old_max_level) then
- redstone.update(pos2)
- end
- end
- end
- end
- end
+--set the data for powered states
+local get_local_power = function(pos)
+ for _,order in pairs(order) do
+ --print(get_node(add_vec(new_vec(x,y,z),pos)).name)
+ if get_item_group(get_node(add_vec(new_vec(order.x,order.y,order.z),pos)).name, "redstone_power") > 0 then
+ return(1)
+ end
+ if get_meta(add_vec(new_vec(order.x,order.y,order.z),pos)):get_int("redstone_power") > 0 then
+ return(1)
+ end
+ end
+ return(0)
+end
+
+local power
+local pos
+local node
+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")
+ end
+ return(power)
+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)
+ end
+ end)
+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)
+ end
+ end)
+end
+
+--collect all nodes that are local to the modified
+--node of redstone dust and store in memory
+local localredstone = {}
+local node
+localredstone.injector = function(i,origin)
+ node = get_node(i).name
+ if node == "air" then
+ return
+ end
+
+ if r_index[i.x] and r_index[i.x][i.y] and r_index[i.x][i.y][i.z] then
+ return
+ end
+
+ if vector_distance(i,origin) > 9 then
+ return
+ end
+
+ --index dust
+ if get_item_group(node,"redstone_dust") > 0 then
+ if vector_distance(i,origin) <= 8 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}
+
+ if not check_table[i.x] then check_table[i.x] = {} end
+ if not check_table[i.x][i.y] then check_table[i.x][i.y] = {} end
+ check_table[i.x][i.y][i.z] = get_item_group(node,"redstone_power")
+
+ --the data to the 3d array must be written to memory before this is executed
+ --or a stack overflow occurs!!!
+ localredstone.collector(i,origin)
+ return
+ else
+ 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_item_group(node,"redstone_power")}
+ end
+ end
+ --index power sources
+ if get_item_group(node,"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_item_group(node,"redstone_power")}
+ end
+ --index directional power sources (Like repeaters/comparators)
+ --only outputs forwards
+ if get_item_group(node,"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_item_group(node,"redstone_power")}
+ end
+
+ --index directional activators (Like repeaters/comparators)
+ --only accepts input from the back
+ if get_item_group(node,"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
+ end
+
+ --index objects that activate
+ if get_item_group(node,"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
+ 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")}
+ end
+end
+
+localredstone.collector = function(pos,origin)
+ for _,order in pairs(order) do
+ localredstone.injector(add_vec(pos,new_vec(order.x,order.y,order.z)),origin)
+ end
+end
+
+
+--check if index table contains items
+--then execute an update
+local function redstone_algorithm()
+ --if indexes exist then calculate redstone
+ --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 = {}
+ check_table = {}
+end
+
+
+function redstone.collect_info(pos)
+ if r_index[pos.x] and r_index[pos.x][pos.y] and r_index[pos.x][pos.y][pos.z] then
+ return
+ end
+ localredstone.injector(pos,pos)
+ localredstone.collector(pos,pos)
+
+ redstone_algorithm()
+end
+
+
+--make all power sources push power out
+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)
+
+
+
+ --reassemble the table into a position list minetest can understand
+ --run through and set dust
+ --local count = 0
+
+ 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 and index.level ~= check_table[x][y][z] then
+ --count = count + 1
+ swap_node(new_vec(x,y,z),{name="redstone:dust_"..index.level})
+ end
+ end
+ end
+ end
+ --print("set "..count.." nodes")
+
+ 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))
+ --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
+ end
+ end
+ end
+ end
+ 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,direction)
+ --directional torches
+
+ 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)
+ end
+ end
+ end
+ else
+ --redstone and torch
+ for _,order in pairs(order) do
+ i = add_vec(source,new_vec(order.x,order.y,order.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
+ --print(minetest.get_node(i).name)
+ 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)
+ end
+ end
+ end
+ end
+ end
+end
+function redstone.pathfind(source,source_level,direction)
+ redstone_pathfinder(source,source_level,direction)
+end
+
+
+
+
+
+
+
+
+----------------------------------------------------------------------------
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
minetest.register_craftitem("redstone:dust", {
- description = "Redstone Dust",
- inventory_image = "redstone_dust_item.png",
- wield_image = "redstone_dust_item.png",
- wield_scale = {x = 1, y = 1, z = 1 + 1/16},
- liquids_pointable = false,
- on_place = function(itemstack, placer, pointed_thing)
- if not pointed_thing.type == "node" then
- 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)
- minetest.punch_node(pointed_thing.above)
- end,pointed_thing)
- return(itemstack)
- end
- end,
-})
+ description = "Redstone Dust",
+ inventory_image = "redstone_dust_item.png",
+ wield_image = "redstone_dust_item.png",
+ wield_scale = {x = 1, y = 1, z = 1 + 1/16},
+ liquids_pointable = false,
+ 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 _,worked = minetest.item_place(ItemStack("redstone:dust_0"), placer, pointed_thing)
+ if worked then
+ 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
for i = 0,8 do
- local coloring = math.floor(color)
- 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
- },
- power=i,
- drawtype = "raillike",
- paramtype = "light",
- sunlight_propagates = true,
- is_ground_content = false,
- walkable = false,
- node_placement_prediction = "",
- selection_box = {
- type = "fixed",
- fixed = {-1/2, -1/2, -1/2, 1/2, -1/2+1/16, 1/2},
- },
- groups={instant=1,attached=1,redstone_dust=1,redstone=1},
- drop="redstone:dust",
- on_punch = function(pos, node, puncher, pointed_thing)
- redstone.update(pos)
- end,
- on_dig = function(pos, node, digger)
- minetest.node_dig(pos, node, digger)
- redstone.update(pos,node)
- end,
- })
- color= color +31.875
+ local coloring = floor(color)
+ 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
+ },
+ power=i,
+ drawtype = "raillike",
+ paramtype = "light",
+ sunlight_propagates = true,
+ is_ground_content = false,
+ walkable = false,
+ node_placement_prediction = "",
+ selection_box = {
+ type = "fixed",
+ fixed = {-1/2, -1/2, -1/2, 1/2, -1/2+1/16, 1/2},
+ },
+ 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)
+ end,
+ after_destruct = function(pos)
+ --redstone.remove(pos,registered_nodes[get_node(pos).name].power)
+ redstone.collect_info(pos)
+ end,
+ connects_to = {"group:redstone"},
+ })
+ color= color +31.875
end
-