local reindexFreq = 1 -- Per minute (0.5 to index every 2 minutes, ...) local indexUpdated = false local items local outputSlots local item -- User choice local count -- User choice local chests = { peripheral.find("inventory") } for i, chest in ipairs(chests) do if peripheral.getName(chest) == settings.get("ccVault.outputInventory") then table.remove(chests, i) break end end -- Functions local getOutputSize local indexChests local loadIndex local getItemNames local userInput local indexRefresh local storageLoop local transfer function getOutputSize() if peripheral.getType(settings.get("ccVault.outputInventory")) == "create:depot" then outputSlots = 1 else outputSlots = peripheral.call(settings.get("ccVault.outputInventory"), "size") end end -- Function to populate the index function indexChests() while true do local itemIndex = {} for _, chest in ipairs(chests) do for slot, item in pairs(chest.list()) do if not itemIndex[item.name] then itemIndex[item.name] = {} end table.insert(itemIndex[item.name], { chest = peripheral.getName(chest), slot = slot }) end end if fs.exists(settings.get("ccVault.file")) then local db = fs.open(settings.get("ccVault.file"), "r") if not db then printError("Couldn't open index databse!") else if textutils.unserializeJSON(db.readAll()) == itemIndex then db.close() else db.close() db = fs.open(settings.get("ccVault.file"), "w") if not db then printError("Couldn't write index databse!") else db.write(textutils.serializeJSON(itemIndex)) db.close() indexUpdated = true end end end else local db = fs.open(settings.get("ccVault.file"), "w") db = fs.open(settings.get("ccVault.file"), "w") if not db then printError("Couldn't write index databse!") else db.write(textutils.serializeJSON(itemIndex)) db.close() indexUpdated = true end end sleep(60 / reindexFreq) end end function loadIndex() local itemIndex local db = fs.open(settings.get("ccVault.file"), "r") if not db then print("Index file not found. It probably wasn't created yet.") local iCount = 0 write("Waiting until indexing is finished") while not db do if iCount >= 3 then term.setCursorPos(term.getCursorPos[1], 1) write("Waiting until indexing is finished.") iCount = 0 else write(".") iCount = iCount + 1 end db = fs.open(settings.get("ccVault.file"), "r") sleep(5) end end itemIndex = textutils.unserializeJSON(db.readAll()) db.close() term.clear() term.setCursorPos(1, 1) return itemIndex end function indexRefresh() sleep(60 / reindexFreq) end function storageLoop() local itemIndex = loadIndex() while true do if indexUpdated then itemIndex = loadIndex() indexUpdated = false end items = getItemNames(itemIndex) parallel.waitForAny(userInput, indexRefresh) if item then if count == 0 or not count then count = 64 end transfer(item, count, itemIndex) item = nil count = nil end term.clear() term.setCursorPos(1, 1) end end ---@param tItem string ---@param maxCount integer ---@param itemIndex table function transfer(tItem, maxCount, itemIndex) local transfered = 0 -- Stored item info local exists = itemIndex[tItem] ~= nil if exists then exists = itemIndex[tItem][1] end if not exists then print("Item not found.\nTry to wait for index update.") sleep(3) return end local sItemInfo = peripheral.call(itemIndex[tItem][1]["chest"], "getItemDetail", itemIndex[tItem][1]["slot"]) if not sItemInfo then print("Index is out of date!\nWait for index update to resolve this error.") sleep(3) return elseif sItemInfo.count <= 0 then print("Index is out of date!\nWait for index update to resolve this error.") sleep(3) return elseif not sItemInfo.count then print("Index is out of date!\nWait for index update to resolve this error.") sleep(3) return end while transfered < count do if not itemIndex[tItem][1] then if transfered > 0 then print("Not enough of `" .. tItem .. "` was found.\nTransfered only " .. transfered .. ".") sleep(3) end break end ---@type ccTweaked.peripheral.item local lastSlot = peripheral.call(settings.get("ccVault.outputInventory"), "getItemDetail", outputSlots) if lastSlot then if lastSlot.count > 0 then print("Output inventory is full!") sleep(3) return end end if sItemInfo.name == tItem then local moved = peripheral.call(itemIndex[tItem][1]["chest"], "pushItems", settings.get("ccVault.outputInventory"), itemIndex[tItem][1]["slot"], maxCount) if moved == sItemInfo.count then transfered = transfered + moved table.remove(itemIndex[tItem], 1) elseif moved == 0 then if peripheral.call(settings.get("ccVault.outputInventory"), "size") == transfered then print("Output inventory is full!") sleep(3) break else table.remove(itemIndex[tItem], 1) end elseif not moved then print("Item not found!") sleep(3) break else transfered = transfered + moved end else table.remove(itemIndex[tItem], 1) end end end ---@param itemIndex table -- Index table of all the items ---@return table names Table of strings function getItemNames(itemIndex) local names = {} for name, _ in pairs(itemIndex) do table.insert(names, name) end return names end ---@param items table Table of all item names as strings function userInput() local completion = require "cc.completion" local input = read(nil, nil, function(text) return completion.choice(text, items) end) if not input then item, count = nil, nil end input = input .. " " local parsedInput = {} for w in input:gmatch("(.-) ") do table.insert(parsedInput, w) end -- item, count = string.match(input, "([^%s]+) (%d+)") item = parsedInput[1] count = tonumber(parsedInput[2]) end getOutputSize() parallel.waitForAny(indexChests, storageLoop)