-- Program to control a compacting storage made with create. -- NOTE: set block -> ingot refresh amount higher than the level desired in -- this program to prioritize using available resources before generating -- new ones -- constants local INVENTORY = "" local SLEEP_TIME = 30 local AMOUNT_PER = 63 -- the amount of item change per request local ITEM_TYPES = { "iron", "copper", "zinc", "gold", "electrum" } local PRIORITY = { "ingot", "block", "nugget" } function stacks (num) return 64 * num end -- TODO map targets to specific relays local target = {} target.iron = peripheral.wrap"" target.copper = peripheral.wrap"" target.zinc = peripheral.wrap"" target.gold = peripheral.wrap"" target.electrum = peripheral.wrap"" -- Levels local limits = {} for _, type in ipairs(ITEM_TYPES) do limits[type] = { "nugget" = { stacks(4), stacks(8) }, "ingot" = { stacks(4), stacks(8) }, "block" = { stacks(4), stacks(1000) } } end -- Map types of conversions to specific faces local convert = {} convert["nugget_to_ingot"] = "front" convert["ingot_to_block"] = "top" convert["block_to_ingot"] = "back" function sum_items (inv) -- organize list of item, count into item_type: (count_N, count_I, count_B) -- item name will be in form `{mod}:{item_type}_{form}` local result = {} for _, type in ipairs(ITEM_TYPES) do result[type] = {} end for slot, item in pairs(inv.list()) do local type, form = item.name:match".-:(%l-)_(%l*)" if result[type][form] == nil then result[type][form] = item.count else result[type][form] = result[type][form] + item.count end end return result end -- basic actions function request (item_type, conversion_type) target[item_type].setOutput(convert[conversion_type], true) os.sleep(0.05) target[item_type].setOutput(convert[conversion_type], false) end function request_multiple (item_type, conversion_type, count) if count < 1 then return end if count == 1 then return request(item_type, conversion_type) else request(item_type, conversion_type) os.sleep(1) return request_multiple(item_type, conversion_type, count - 1) end end -- fundamental actions function drain (type, form, amount) local conversion = nil if form == "nugget" then conversion = "nugget_to_ingot" elseif form == "ingot" then conversion = "ingot_to_block" end request_multiple(type, conversion, amount) end function fill (type, form, amount) local conversion = nil if dest == "block" then conversion = "ingot_to_block" elseif dest == "ingot" then if src == "nugget" then conversion = "nugget_to_ingot" elseif src == "block" then conversion = "block_to_ingot" end end request_multiple(type, conversion, amount) end -- making the decision what to do function should_drain (type, counts) local drain_form, amount = nil, 0 for _, form in ipairs(PRIORITY) do local diff = counts[form] - target[type][form][2] if diff > 0 then amount = math.ceil(diff / AMOUNT_PER) drain_form = form return drain_form, amount end end end function should_fill (type, counts) local fill_dest, fill_src, amount = nil, nil, 0 for _, form in ipairs(PRIORITY) do local diff = target[type][form][1] - counts[form] if diff > 0 then if fill_dest == nil then amount = math.ceil(diff / AMOUNT_PER) fill_dest = form end else fill_src = form end if fill_src ~= nil and fill_dest ~= nil then break end end return fill_dest, fill_src, amount end function decide_action (type, counts) -- using the levels of each form of the item, decide what to do for _, form in ipairs(PRIORITY) do local drain_form, drain_amt = should_drain(type, counts) local fill_dest, fill_src, fill_amt if drain_form ~= nil then drain(type, form, drain_amt) elseif fill_dest ~= nil then fill(type, form, fill_amt) end end end while true do -- 1. Sum items in inventory and organize by item type local items = sum_items(peripheral.wrap(INVENTORY)) -- 2. take one action for each item type per cycle for item_type, counts in pairs(items) do decide_action(item_type, counts) end -- sleep until next cycle os.sleep(SLEEP_TIME) end