--- /dev/null
+-- cobble-loader.lua
+--
+-- cobble is moved to drawers from limited barrels, trying to keep the drawers
+-- full at all times. redstone signal is emitted from all sides of the computer
+-- when drawers are refilling. input barrels may be upgraded with void.
+
+-- the amount of time (in seconds) between attempted refills when refilling.
+local sleep_time_working = 5
+
+-- the amount of time (in seconds) between attempted refills when full.
+local sleep_time_idle = 5
+
+--------------------------------------------------------------------------------
+
+local outputs = {}
+local inputs = {}
+
+for _,address = in pairs(peripheral.getNames()) do
+ local is_drawer = string.match(address, "standard_drawers")
+ local is_barrel = string.match(address, "limited_barrel")
+ if is_drawer then
+ table.insert(outputs, address)
+ elseif is_barrel then
+ table.insert(inputs, address)
+ end
+end
+
+-- returns ordered list of outputs and how much cobble they have space for.
+-- ordered by free space in decreasing order.
+-- outputs with no empty space are not included in return table.
+-- calculates free space on the assumtion that outputs are drawers without void.
+local output_amounts = function()
+ local t = {}
+ for _,output in ipairs(outputs) do
+ local p = peripheral.wrap(output)
+ local item = p.getItemDetail(2)
+ local count =
+ item and item.name == "minecraft:cobblestone"
+ and item.count or 0
+ local free_space = p.getItemLimit(2) - count
+ if free_space > 0 then
+ table.insert(t, { address = output, free_space = free_space })
+ end
+ end
+ table.sort(t, function(a, b) return a.free_space > b.free_space end)
+ return t
+end
+
+-- returns ordered list of inputs and how much cobble they have available.
+-- ordered by cobble count in decreasing order.
+-- assumes inputs are limited barrels.
+local input_amounts = function()
+ local t = {}
+ for _,input in ipairs(inputs) do
+ local p = peripheral.wrap(input)
+ local item = p.getItemDetail(1)
+ local count =
+ item and item.name == "minecraft:cobblestone"
+ and item.count
+ table.insert(t, { address = input, count = count })
+ end
+ table.sort(t, function(a, b) return a.count > b.count end)
+ return t
+end
+
+-- moves as much cobble as possible to each output, returning whether or not
+-- there is space for more
+local move_cobble = function()
+ local to_move_total = 0
+ for _,output in ipairs(output_amounts()) do
+ local p = peripheral.wrap(output.address)
+ local to_move = output.free_space
+ to_move_total = to_move_total + output.free_space
+ for _,input in ipairs(input_amounts()) do
+ if to_move <= 0 then break end
+ local moved = p.pullItems(input, 1, math.min(input.count, to_move), 2)
+ -- moved may not be integer if pullItems failed.. look out
+ to_move = to_move - moved
+ to_move_total = to_move_total - moved
+ end
+ end
+ return to_move_total > 0
+end
+
+-- set redstone output on all sides simultaneously
+local generate_cobble = function(bool)
+ for _,side in ipairs({"top","bottom","left","right","front","back"}) do
+ rs.setOutput(side, bool)
+ end
+end
+
+-- main loop
+while true do
+ while move_cobble() do
+ generate_cobble(true)
+ os.sleep(sleep_time_working)
+ end
+ generate_cobble(false)
+ os.sleep(sleep_time_idle)
+end