diff --git a/cargo-elevator.lua b/cargo-elevator.lua new file mode 100644 index 0000000..6aadb4b --- /dev/null +++ b/cargo-elevator.lua @@ -0,0 +1,165 @@ +-- program to manage a cargo elevator +-- yes, i am aware i could just use the computer to transfer packages at this +-- point, but where's the fun in that? + +local FLOORS = { + { + match = function (input) + local first_char = string.sub(input, 1, 1) + return first_char == "A" or first_char == "W" + end, + detect = function () + return redstone.getInput("top") + end, + call = function () + redstone.setOutput("top", true) + os.sleep(0.5) + redstone.setOutput("top", false) + end, + storage = "create:item_vault_17", + elevator_storage = "create:portable_storage_interface_11", + }, + { + match = function (input) + local first_char = string.sub(input, 1, 1) + return first_char == "F" + end, + detect = function () + local relay = "redstone_relay_21" + return peripheral.call(relay, "getInput", "top") + end, + call = function () + local relay = "redstone_relay_21" + peripheral.call(relay, "setOutput", "top", true) + os.sleep(0.5) + peripheral.call(relay, "setOutput", "top", false) + end, + storage = "create:item_vault_18", + elevator_storage = "create:portable_storage_interface_8", + }, + { + match = function (input) + local first_char = string.sub(input, 1, 1) + return first_char == "L" + end, + detect = function () + local relay = "redstone_relay_22" + return peripheral.call(relay, "getInput", "top") + end, + call = function () + local relay = "redstone_relay_22" + peripheral.call(relay, "setOutput", "top", true) + os.sleep(0.5) + peripheral.call(relay, "setOutput", "top", false) + end, + storage = "create:item_vault_19", + elevator_storage = "create:portable_storage_interface_9", + }, + { + match = function (input) + local first_char = string.sub(input, 1, 1) + return first_char == "E" + end, + detect = function () + local relay = "redstone_relay_23" + return peripheral.call(relay, "getInput", "top") + end, + call = function () + local relay = "redstone_relay_23" + peripheral.call(relay, "setOutput", "top", true) + os.sleep(0.5) + peripheral.call(relay, "setOutput", "top", false) + end, + storage = "create:item_vault_20", + elevator_storage = "create:portable_storage_interface_10", + }, +} + +local SLEEP_T = 5 + +local PKG_QUEUE = { + insert = function (self, floor_i) + local is_in = function (item, list) + for _, l_item in ipairs(list) do + if l_item == item then return true end + end + return false + end + if not is_in(floor_i, self.queue) then + table.insert(self.queue, floor_i) + end + end, + check_floors = function (self, floors) + for i, floor in pairs(floors) do + if #(peripheral.call(floor.storage, "list")) > 0 then + self:insert(i) + end + end + end, + check_cargo = function (self, inv, floors) + for slot, item in pairs(peripheral.call(inv, "list")) do + local item_detail = peripheral.call(inv, "getItemDetail", slot) + for i, floor in ipairs(floors) do + if item_detail.package ~= nil and + floor.match(item_detail.package.getAddress()) then + self:insert(i) + break + end + end + end + end, + transfer_all = function (self, src, dest, floors) + -- assumption: this always transfers into the cargo box + for slot, item in pairs(peripheral.call(src, "list")) do + local item_detail = peripheral.call(src, "getItemDetail", slot) + for i, floor in ipairs(floors) do + if item_detail.package ~= nil and + floor.match(item_detail.package.getAddress()) then + self:insert(i) + peripheral.call(src, "pushItems", dest, slot) + break + end + end + end + end, + transfer_matching = function (self, src, dest, match_f) + -- assumption: this always transfers out of the cargo box + for slot, item in pairs(peripheral.call(src, "list")) do + local item_detail = peripheral.call(src, "getItemDetail", slot) + if item_detail.package ~= nil and + match_f(item_detail.package.getAddress()) then + peripheral.call(src, "pushItems", dest, slot) + end + end + end, + get_next_floor = function (self) + return table.remove(self.queue, 1) + end, + queue = {}, +} + +function run (floors, queue, first_run) + local next_floor = nil + queue:check_floors(floors) + for i, floor in pairs(floors) do + if floor.detect() then + if first_run then + queue:check_cargo(floor.elevator_storage, floors) + end + queue:transfer_all(floor.storage, floor.elevator_storage, floors) + queue:transfer_matching( + floor.elevator_storage, floor.storage, floor.match + ) + next_floor = queue:get_next_floor() + end + end + if next_floor ~= nil then + floors[next_floor].call() + end + os.sleep(SLEEP_T) + return run(floors, queue, false) +end + +if arg ~= nil and arg[1] == "run" then + run(FLOORS, PKG_QUEUE, true) +end