Implement cache persistence for inventory data and enhance loading mechanism
This commit is contained in:
@@ -8,6 +8,7 @@ local MONITOR_SIDE = "left"
|
|||||||
local SCAN_INTERVAL = 3 -- seconds between background scans
|
local SCAN_INTERVAL = 3 -- seconds between background scans
|
||||||
local SMELT_INTERVAL = 3 -- seconds between furnace checks
|
local SMELT_INTERVAL = 3 -- seconds between furnace checks
|
||||||
local SMELT_RESERVE = 64 -- keep at least 1 stack of each raw material
|
local SMELT_RESERVE = 64 -- keep at least 1 stack of each raw material
|
||||||
|
local CACHE_FILE = ".inventory_cache" -- persistent cache file
|
||||||
|
|
||||||
-------------------------------------------------
|
-------------------------------------------------
|
||||||
-- Furnace types to manage
|
-- Furnace types to manage
|
||||||
@@ -239,6 +240,58 @@ local function refreshCache(onProgress)
|
|||||||
cache.furnaceCount = furnaceCount
|
cache.furnaceCount = furnaceCount
|
||||||
|
|
||||||
activity.scanning = false
|
activity.scanning = false
|
||||||
|
|
||||||
|
-- Persist cache to disk
|
||||||
|
pcall(function()
|
||||||
|
local data = {
|
||||||
|
catalogue = cache.catalogue,
|
||||||
|
itemList = cache.itemList,
|
||||||
|
grandTotal = cache.grandTotal,
|
||||||
|
chestCount = cache.chestCount,
|
||||||
|
totalSlots = cache.totalSlots,
|
||||||
|
usedSlots = cache.usedSlots,
|
||||||
|
freeSlots = cache.freeSlots,
|
||||||
|
usedRatio = cache.usedRatio,
|
||||||
|
dropperOk = cache.dropperOk,
|
||||||
|
barrelOk = cache.barrelOk,
|
||||||
|
furnaceCount = cache.furnaceCount,
|
||||||
|
savedAt = os.epoch("utc"),
|
||||||
|
}
|
||||||
|
local f = fs.open(CACHE_FILE, "w")
|
||||||
|
f.write(textutils.serialise(data))
|
||||||
|
f.close()
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Load cache from disk (returns true if loaded)
|
||||||
|
local function loadCacheFromDisk()
|
||||||
|
if not fs.exists(CACHE_FILE) then return false end
|
||||||
|
local ok, err = pcall(function()
|
||||||
|
local f = fs.open(CACHE_FILE, "r")
|
||||||
|
local raw = f.readAll()
|
||||||
|
f.close()
|
||||||
|
local data = textutils.unserialise(raw)
|
||||||
|
if data and data.catalogue and data.itemList then
|
||||||
|
cache.catalogue = data.catalogue
|
||||||
|
cache.itemList = data.itemList
|
||||||
|
cache.grandTotal = data.grandTotal or 0
|
||||||
|
cache.chestCount = data.chestCount or 0
|
||||||
|
cache.totalSlots = data.totalSlots or 0
|
||||||
|
cache.usedSlots = data.usedSlots or 0
|
||||||
|
cache.freeSlots = data.freeSlots or 0
|
||||||
|
cache.usedRatio = data.usedRatio or 0
|
||||||
|
cache.dropperOk = data.dropperOk or false
|
||||||
|
cache.barrelOk = data.barrelOk or false
|
||||||
|
cache.furnaceCount = data.furnaceCount or 0
|
||||||
|
else
|
||||||
|
error("invalid cache data")
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
if not ok then
|
||||||
|
print("[WARN] Could not load cache: " .. tostring(err))
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
-------------------------------------------------
|
-------------------------------------------------
|
||||||
@@ -1079,78 +1132,91 @@ local function main()
|
|||||||
print("Console shows log. Use the monitor to interact.")
|
print("Console shows log. Use the monitor to interact.")
|
||||||
print("")
|
print("")
|
||||||
|
|
||||||
-- Initial scan with progress bar on monitor
|
-- Try loading cached inventory from disk for instant startup
|
||||||
print("[INIT] Scanning inventories...")
|
local cacheLoaded = loadCacheFromDisk()
|
||||||
if mon then
|
if cacheLoaded then
|
||||||
local w, h = mon.getSize()
|
print("[INIT] Loaded cached inventory (" .. #cache.itemList .. " types)")
|
||||||
local buf = window.create(mon, 1, 1, w, h, false)
|
print("[INIT] Background refresh starting...")
|
||||||
|
|
||||||
local function drawBoot(current, total, chestName)
|
|
||||||
buf.setBackgroundColor(colors.black)
|
|
||||||
buf.clear()
|
|
||||||
|
|
||||||
-- Title
|
|
||||||
buf.setBackgroundColor(colors.blue)
|
|
||||||
buf.setCursorPos(1, 1)
|
|
||||||
buf.write(string.rep(" ", w))
|
|
||||||
local title = " INVENTORY MANAGER "
|
|
||||||
buf.setCursorPos(math.floor((w - #title) / 2) + 1, 1)
|
|
||||||
buf.setTextColor(colors.white)
|
|
||||||
buf.write(title)
|
|
||||||
|
|
||||||
-- Scanning label
|
|
||||||
local midY = math.floor(h / 2)
|
|
||||||
buf.setBackgroundColor(colors.black)
|
|
||||||
buf.setTextColor(colors.lightGray)
|
|
||||||
local label = "Scanning inventories..."
|
|
||||||
buf.setCursorPos(math.floor((w - #label) / 2) + 1, midY - 2)
|
|
||||||
buf.write(label)
|
|
||||||
|
|
||||||
-- Chest name
|
|
||||||
local short = chestName or ""
|
|
||||||
if #short > w - 4 then short = ".." .. short:sub(-(w - 6)) end
|
|
||||||
buf.setTextColor(colors.gray)
|
|
||||||
buf.setCursorPos(math.floor((w - #short) / 2) + 1, midY - 1)
|
|
||||||
buf.write(short)
|
|
||||||
|
|
||||||
-- Progress bar
|
|
||||||
local barW = math.min(w - 8, 40)
|
|
||||||
local barX = math.floor((w - barW) / 2) + 1
|
|
||||||
local ratio = total > 0 and (current / total) or 0
|
|
||||||
local filled = math.floor(ratio * barW)
|
|
||||||
|
|
||||||
buf.setCursorPos(barX, midY + 1)
|
|
||||||
buf.setBackgroundColor(colors.lime)
|
|
||||||
buf.write(string.rep(" ", filled))
|
|
||||||
buf.setBackgroundColor(colors.gray)
|
|
||||||
buf.write(string.rep(" ", barW - filled))
|
|
||||||
|
|
||||||
-- Percentage + count
|
|
||||||
buf.setBackgroundColor(colors.black)
|
|
||||||
buf.setTextColor(colors.white)
|
|
||||||
local pct = string.format("%d/%d (%d%%)", current, total, math.floor(ratio * 100))
|
|
||||||
buf.setCursorPos(math.floor((w - #pct) / 2) + 1, midY + 3)
|
|
||||||
buf.write(pct)
|
|
||||||
|
|
||||||
-- Bottom accent
|
|
||||||
buf.setCursorPos(1, h)
|
|
||||||
buf.setBackgroundColor(colors.blue)
|
|
||||||
buf.write(string.rep(" ", w))
|
|
||||||
|
|
||||||
buf.setVisible(true)
|
|
||||||
buf.setVisible(false)
|
|
||||||
end
|
|
||||||
|
|
||||||
refreshCache(drawBoot)
|
|
||||||
else
|
else
|
||||||
refreshCache()
|
-- No cache: do full scan with progress bar
|
||||||
|
print("[INIT] No cache found. Scanning inventories...")
|
||||||
|
if mon then
|
||||||
|
local w, h = mon.getSize()
|
||||||
|
local buf = window.create(mon, 1, 1, w, h, false)
|
||||||
|
|
||||||
|
local function drawBoot(current, total, chestName)
|
||||||
|
buf.setBackgroundColor(colors.black)
|
||||||
|
buf.clear()
|
||||||
|
|
||||||
|
-- Title
|
||||||
|
buf.setBackgroundColor(colors.blue)
|
||||||
|
buf.setCursorPos(1, 1)
|
||||||
|
buf.write(string.rep(" ", w))
|
||||||
|
local title = " INVENTORY MANAGER "
|
||||||
|
buf.setCursorPos(math.floor((w - #title) / 2) + 1, 1)
|
||||||
|
buf.setTextColor(colors.white)
|
||||||
|
buf.write(title)
|
||||||
|
|
||||||
|
-- Scanning label
|
||||||
|
local midY = math.floor(h / 2)
|
||||||
|
buf.setBackgroundColor(colors.black)
|
||||||
|
buf.setTextColor(colors.lightGray)
|
||||||
|
local label = "Scanning inventories..."
|
||||||
|
buf.setCursorPos(math.floor((w - #label) / 2) + 1, midY - 2)
|
||||||
|
buf.write(label)
|
||||||
|
|
||||||
|
-- Chest name
|
||||||
|
local short = chestName or ""
|
||||||
|
if #short > w - 4 then short = ".." .. short:sub(-(w - 6)) end
|
||||||
|
buf.setTextColor(colors.gray)
|
||||||
|
buf.setCursorPos(math.floor((w - #short) / 2) + 1, midY - 1)
|
||||||
|
buf.write(short)
|
||||||
|
|
||||||
|
-- Progress bar
|
||||||
|
local barW = math.min(w - 8, 40)
|
||||||
|
local barX = math.floor((w - barW) / 2) + 1
|
||||||
|
local ratio = total > 0 and (current / total) or 0
|
||||||
|
local filled = math.floor(ratio * barW)
|
||||||
|
|
||||||
|
buf.setCursorPos(barX, midY + 1)
|
||||||
|
buf.setBackgroundColor(colors.lime)
|
||||||
|
buf.write(string.rep(" ", filled))
|
||||||
|
buf.setBackgroundColor(colors.gray)
|
||||||
|
buf.write(string.rep(" ", barW - filled))
|
||||||
|
|
||||||
|
-- Percentage + count
|
||||||
|
buf.setBackgroundColor(colors.black)
|
||||||
|
buf.setTextColor(colors.white)
|
||||||
|
local pct = string.format("%d/%d (%d%%)", current, total, math.floor(ratio * 100))
|
||||||
|
buf.setCursorPos(math.floor((w - #pct) / 2) + 1, midY + 3)
|
||||||
|
buf.write(pct)
|
||||||
|
|
||||||
|
-- Bottom accent
|
||||||
|
buf.setCursorPos(1, h)
|
||||||
|
buf.setBackgroundColor(colors.blue)
|
||||||
|
buf.write(string.rep(" ", w))
|
||||||
|
|
||||||
|
buf.setVisible(true)
|
||||||
|
buf.setVisible(false)
|
||||||
|
end
|
||||||
|
|
||||||
|
refreshCache(drawBoot)
|
||||||
|
else
|
||||||
|
refreshCache()
|
||||||
|
end
|
||||||
|
print("[INIT] Done. Found " .. #cache.itemList .. " item types.")
|
||||||
end
|
end
|
||||||
print("[INIT] Done. Found " .. #cache.itemList .. " item types.")
|
|
||||||
print("")
|
print("")
|
||||||
|
|
||||||
parallel.waitForAny(
|
parallel.waitForAny(
|
||||||
-- Task 1: Background inventory scanner
|
-- Task 1: Background inventory scanner
|
||||||
function()
|
function()
|
||||||
|
-- If we loaded from disk cache, refresh immediately in background
|
||||||
|
if cacheLoaded then
|
||||||
|
pcall(refreshCache)
|
||||||
|
needsRedraw = true
|
||||||
|
print("[INIT] Background refresh complete. " .. #cache.itemList .. " types.")
|
||||||
|
end
|
||||||
while true do
|
while true do
|
||||||
sleep(SCAN_INTERVAL)
|
sleep(SCAN_INTERVAL)
|
||||||
pcall(refreshCache)
|
pcall(refreshCache)
|
||||||
|
|||||||
Reference in New Issue
Block a user