232 lines
6.3 KiB
Lua
232 lines
6.3 KiB
Lua
|
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)
|