Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- -- pastebin run v9vZhxFR
- local chests = { peripheral.find("ironchest:obsidian_chest") }
- local monitor = peripheral.find("monitor")
- local modemName = "bottom"
- local inventory = {}
- -- Util ---
- function TableSize(tab)
- if tab == nil then
- return 0
- end
- local tabSize = 0
- for aTab, bTab in pairs(tab) do
- tabSize = tabSize + 1
- end
- return tabSize
- end
- function Ternary(cond, T, F)
- if cond then
- return T
- else
- return F
- end
- end
- function Log(msg)
- print(msg)
- end
- function Err(e)
- Log("ERROR!")
- Log(textutils.serialize(e))
- error(e)
- end
- --- Inventory file ---
- function Save()
- local invFile = fs.open("inventory", "w")
- invFile.write(textutils.serialise(inventory))
- invFile.close()
- end
- function Load()
- local invFile = fs.open("inventory", "r")
- if invFile == nil then
- return
- end
- inventory = textutils.unserialise(invFile.readAll())
- invFile.close()
- end
- --- Inventory mapping ---
- function MapInventory()
- inventory["items"] = {}
- inventory["itemLimits"] = {}--max stack size per item type, interact with this via GetItemLimit(chestName, slot, itemNbt)
- inventory["partialStacks"] = {}--stacks that are not completly full or empty, should try to store or get from these first
- inventory["itemCounts"] = {}
- inventory["itemNames"] = {}
- for chestName, chest in pairs(chests) do
- Log("Mapping inventory: " .. tostring(chestName) .. " / " .. tostring(table.getn(chests)))
- local chestItems = chest.list()
- for slot = 1, chest.size() do
- --local item = chest.getItemDetail(slot)
- local item = chestItems[slot]
- if item == nil then
- SetSlot("", 0, chestName, slot)
- else
- SetSlot(item.nbt, item.count, chestName, slot)
- AddItemCount(item.nbt, item.count)
- end
- end
- end
- Save()
- Log("Inventory mapped")
- end
- -- Get all locations of an item
- function GetItemInv(itemNbt)
- if inventory["items"][itemNbt] == nil then
- inventory["items"][itemNbt] = {}
- end
- if itemNbt ~= "" then
- if inventory["partialStacks"][itemNbt] == nil then
- inventory["partialStacks"][itemNbt] = {}
- end
- if inventory["itemCounts"][itemNbt] == nil then
- inventory["itemCounts"][itemNbt] = 0
- end
- end
- return inventory["items"][itemNbt]
- end
- function AddItemCount(itemNbt, count)
- GetItemInv(itemNbt)
- inventory["itemCounts"][itemNbt] = inventory["itemCounts"][itemNbt] + count
- end
- function GetItemLimit(chestName, slot, itemNbt)
- if inventory["itemLimits"][itemNbt] == nil then
- local itemDetail = nil
- if chests[chestName] ~= nil then
- itemDetail = chests[chestName].getItemDetail(slot)
- else
- itemDetail = peripheral.wrap(chestName).getItemDetail(slot)
- end
- if itemDetail ~= nil then
- inventory["itemLimits"][itemNbt] = itemDetail.maxCount
- else
- return 64
- end
- end
- return inventory["itemLimits"][itemNbt]
- end
- function GetItemName(chestName, slot, itemNbt)
- if inventory["itemNames"][itemNbt] == nil then
- if chestName == nil or slot == nil then
- return nil
- end
- local itemDetail = nil
- if chests[chestName] ~= nil then
- itemDetail = chests[chestName].getItemDetail(slot)
- else
- itemDetail = peripheral.wrap(chestName).getItemDetail(slot)
- end
- if itemDetail ~= nil then
- inventory["itemNames"][itemNbt] = itemDetail.displayName
- else
- return nil
- end
- end
- return inventory["itemNames"][itemNbt]
- end
- -- Set a slot in the chests for where an item is
- function SetSlot(itemNbt, count, chestName, slot)
- if count < 0 then
- Err({
- ["type"] = "Neg slot",
- ["itemNbt"] = itemNbt,
- ["itemCount"] = count,
- ["chestName"] = chestName,
- ["chestSlot"] = slot
- })
- end
- --set new value in items table
- GetItemInv(itemNbt)
- if inventory["items"][name][chestName] == nil then
- inventory["items"][name][chestName] = {}
- end
- if itemNbt ~= "" then
- if inventory["partialStacks"][itemNbt][chestName] == nil then
- inventory["partialStacks"][itemNbt][chestName] = {}
- end
- end
- GetItemInv("")
- if inventory["items"][""][chestName] == nil then
- inventory["items"][""][chestName] = {}
- end
- if count == 0 then
- if itemNbt ~= "" then
- inventory["items"][itemNbt][chestName][slot] = nil
- inventory["partialStacks"][itemNbt][chestName][slot] = nil
- end
- inventory["items"][""][chestName][slot] = 0
- else
- inventory["items"][itemNbt][chestName][slot] = count
- inventory["items"][""][chestName][slot] = nil
- if itemNbt ~= "" then
- if count < GetItemLimit(chestName, slot, itemNbt) then
- inventory["partialStacks"][itemNbt][chestName][slot] = true
- else
- inventory["partialStacks"][itemNbt][chestName][slot] = nil
- end
- end
- end
- GetItemName(chestName, slot, itemNbt)--will set it if not on there
- --Save()
- end
- --- Get free slots avaliable ---
- function CountEmptySlots()
- if inventory.items[""] == nil then
- return 0
- end
- local emptySlotCount = 0
- for ecsn, ecs in pairs(inventory.items[""]) do
- for esn, es in pairs(ecs) do
- emptySlotCount = emptySlotCount + 1
- end
- end
- return emptySlotCount
- end
- --- IO ---
- -- Take from outChest and store
- function Store(fromChest, fromSlot, toMove)
- if CountEmptySlots() == 0 then
- Log("Inventory full")
- return 0
- end
- local item = peripheral.wrap(fromChest).getItemDetail(fromSlot)
- if item ~= nil then
- local totalMoved = 0
- local maxStackSize = GetItemLimit(fromChest, fromSlot, item.nbt)--peripheral.wrap(fromChest).getItemLimit(fromSlot)
- if toMove == nil then
- toMove = maxStackSize
- end
- toMove = math.min(item.count, toMove)
- Log("Storing " .. tostring(toMove) .. " " .. item.nbt)
- function StoreToSlot(slotItemNbt)
- local itemInv = GetItemInv(slotItemNbt)
- for chestName, chestSlots in pairs(itemInv) do
- for slot, count in pairs(chestSlots) do
- if count < maxStackSize then
- local moved = chests[chestName].pullItems(fromChest, fromSlot, toMove, slot)
- toMove = toMove - moved
- totalMoved = totalMoved + moved
- if moved > 0 then
- SetSlot(item.nbt, count + moved, chestName, slot)
- end
- if toMove == 0 then
- return true
- end
- if toMove < 0 then
- Err({
- ["type"] = "Over move",
- ["chestName"] = chestName,
- ["slotName"] = slotName,
- ["itemNbt"] = item.nbt,
- ["slotItemNbt"] = slotItemNbt,
- ["totalToMove"] = toMove,
- ["fromChest"] = fromChest,
- ["fromSlot"] = fromSlot
- })
- end
- end
- end
- end
- return false
- end
- if maxStackSize ~= 1 and StoreToSlot(item.nbt) then
- Log("Stored " .. tostring(totalMoved) .. " " .. item.nbt)
- AddItemCount(item.nbt, totalMoved)
- return totalMoved
- elseif StoreToSlot("") then
- Log("Stored " .. tostring(totalMoved) .. " " .. item.nbt)
- AddItemCount(item.nbt, totalMoved)
- return totalMoved
- else
- Err({
- ["type"] = "Desync"
- })
- end
- end
- Log("Was asked to store slot but is empty")
- return 0
- end
- -- Get from storage to outChest by name
- function Get(itemNbt, count, toChest, toSlot)
- Log("Getting " .. tostring(count) .. " " .. itemNbt)
- local totalMoved = 0
- local itemInv = GetItemInv(itemNbt)--gets all slots where this item should be from file
- for chestName, chestSlots in pairs(itemInv) do
- for slotName, slotCount in pairs(chestSlots) do
- local slotItemDetail = chests[chestName].getItemDetail(slotName)
- if slotItemDetail == nil or slotItemDetail.nbt ~= itemNbt or slotItemDetail.count ~= slotCount then
- Err({
- ["type"] = "Slot desync",
- ["chestName"] = chestName,
- ["slotName"] = slotName,
- ["expectedItemNbt"] = itemNbt,
- ["expectedItemCount"] = slotCount,
- ["actualItemNbt"] = Ternary(slotItemDetail == nil, "Air", slotItemDetail.nbt),
- ["actualItemCount"] = Ternary(slotItemDetail == nil, 0, slotItemDetail.count),
- })
- end
- local moved = chests[chestName].pushItems(toChest, slotName, count - totalMoved, toSlot)
- totalMoved = totalMoved + moved
- --Log("Get item")
- --Log(itemNbt)
- if moved == 0 then
- --cant move any more as output slot full / diffrent item
- Log("Got " .. tostring(totalMoved) .. " " .. itemNbt)
- AddItemCount(itemNbt, -totalMoved)
- return totalMoved
- end
- SetSlot(itemNbt, slotCount - moved, chestName, slotName)
- if count == totalMoved then
- Log("Got " .. tostring(totalMoved) .. " " .. itemNbt)
- AddItemCount(itemNbt, -totalMoved)
- return totalMoved
- end
- if totalMoved > count then
- Err({
- ["type"] = "Over move",
- ["chestName"] = chestName,
- ["slotName"] = slotName,
- ["itemNbt"] = itemNbt,
- ["totalToMove"] = count,
- ["toChest"] = toChest,
- ["toSlot"] = toSlot
- })
- end
- end
- end
- Log("Got " .. tostring(totalMoved) .. " " .. itemNbt)
- AddItemCount(itemNbt, -totalMoved)
- return totalMoved
- end
- --- Queue ---
- local Queue = {}
- function Network()
- while true do
- local id, msg = rednet.receive("inv")
- msg["fromID"] = id
- table.insert(Queue, msg)
- sleep(0)
- end
- end
- function ProcessQueue()
- function ProcessItem(msg)
- if msg["action"] == "store" then
- if msg["chest"] == nil then
- rednet.send(msg["fromID"], {
- ["instructionRef"] = msg["instructionRef"],
- ["status"] = "fail",
- ["message"] = "Missing 'chest'"
- }, "invResp")
- return
- end
- if peripheral.wrap(msg["chest"]) == nil then
- rednet.send(msg["fromID"], {
- ["instructionRef"] = msg["instructionRef"],
- ["status"] = "fail",
- ["message"] = "Cant find 'chest'"
- }, "invResp")
- return
- end
- if msg["slot"] == nil then
- rednet.send(msg["fromID"], {
- ["instructionRef"] = msg["instructionRef"],
- ["status"] = "fail",
- ["message"] = "Missing 'slot'"
- }, "invResp")
- return
- end
- local moved = 0
- if msg["count"] == nil then
- moved = Store(msg["chest"], msg["slot"])
- else
- moved = Store(msg["chest"], msg["slot"], msg["count"])
- end
- rednet.send(msg["fromID"], {
- ["instructionRef"] = msg["instructionRef"],
- ["status"] = "success",
- ["moved"] = moved
- }, "invResp")
- return
- end
- if msg["action"] == "get" then
- if msg["nbt"] == nil then
- rednet.send(msg["fromID"], {
- ["instructionRef"] = msg["instructionRef"],
- ["status"] = "fail",
- ["message"] = "Missing 'nbt'"
- }, "invResp")
- return
- end
- if msg["chest"] == nil then
- rednet.send(msg["fromID"], {
- ["instructionRef"] = msg["instructionRef"],
- ["status"] = "fail",
- ["message"] = "Missing 'chest'"
- }, "invResp")
- return
- end
- if peripheral.wrap(msg["chest"]) == nil then
- rednet.send(msg["fromID"], {
- ["instructionRef"] = msg["instructionRef"],
- ["status"] = "fail",
- ["message"] = "Cant find 'chest'"
- }, "invResp")
- return
- end
- if msg["count"] == nil then
- msg["count"] = 1
- end
- local moved = 0
- if msg["slot"] == nil then
- moved = Get(msg["nbt"], msg["count"], msg["chest"])
- else
- moved = Get(msg["nbt"], msg["count"], msg["chest"], msg["slot"])
- end
- rednet.send(msg["fromID"], {
- ["instructionRef"] = msg["instructionRef"],
- ["status"] = "success",
- ["moved"] = moved
- }, "invResp")
- return
- end
- if msg["action"] == "count" then
- if msg["nbt"] == nil then
- rednet.send(msg["fromID"], {
- ["instructionRef"] = msg["instructionRef"],
- ["status"] = "fail",
- ["message"] = "Missing 'nbt'"
- }, "invResp")
- return
- end
- local count = inventory["itemCounts"][msg["nbt"]]
- if count == nil then
- count = 0
- end
- rednet.send(msg["fromID"], {
- ["instructionRef"] = msg["instructionRef"],
- ["status"] = "success",
- ["count"] = count
- }, "invResp")
- return
- end
- if msg["action"] == "getCounts" then
- rednet.send(msg["fromID"], {
- ["instructionRef"] = msg["instructionRef"],
- ["status"] = "success",
- ["name"] = inventory["itemCounts"]
- }, "invResp")
- return
- end
- if msg["action"] == "getName" then
- if msg["nbt"] == nil then
- rednet.send(msg["fromID"], {
- ["instructionRef"] = msg["instructionRef"],
- ["status"] = "fail",
- ["message"] = "Missing 'nbt'"
- }, "invResp")
- return
- end
- rednet.send(msg["fromID"], {
- ["instructionRef"] = msg["instructionRef"],
- ["status"] = "success",
- ["name"] = GetItemName(nil, nil, msg["nbt"])
- }, "invResp")
- return
- end
- if msg["action"] == "getNames" then
- rednet.send(msg["fromID"], {
- ["instructionRef"] = msg["instructionRef"],
- ["status"] = "success",
- ["name"] = inventory["itemNames"]
- }, "invResp")
- return
- end
- end
- while true do
- if TableSize(Queue) > 0 then
- ProcessItem(table.remove(Queue))
- sleep(0)
- else
- sleep(0.1)
- end
- end
- end
- --- Run ---
- MapInventory()
- --Load()
- rednet.open(modemName)
- parallel.waitForAny(Network, ProcessQueue)
- Save()
Add Comment
Please, Sign In to add comment