diff --git a/.luarc.json b/.luarc.json index a32b301..7558f41 100644 --- a/.luarc.json +++ b/.luarc.json @@ -1,6 +1,5 @@ { "workspace.library": [ "./lib/cc-tweaked/", - "./lib/basalt/Basalt" ] } diff --git a/main.lua b/main.lua new file mode 100644 index 0000000..ffd4181 --- /dev/null +++ b/main.lua @@ -0,0 +1,231 @@ +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 + -- printError("Couldn't open DB file!\n" .. settings.get("ccVault.file")) + 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 + sleep(2) + 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.") + 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.") + return + elseif sItemInfo.count <= 0 then + print("Index is out of date!\nWait for index update to resolve this error.") + return + elseif not sItemInfo.count then + print("Index is out of date!\nWait for index update to resolve this error.") + 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 .. ".") + 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!") + 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!") + break + else + table.remove(itemIndex[tItem], 1) + end + elseif not moved then + print("Item not found!") + 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)