diff --git a/inventoryManager.lua b/inventoryManager.lua index 766a10e..af9992a 100644 --- a/inventoryManager.lua +++ b/inventoryManager.lua @@ -8,6 +8,7 @@ local MONITOR_SIDE = "left" local SCAN_INTERVAL = 3 -- seconds between background scans local SMELT_INTERVAL = 3 -- seconds between furnace checks 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 @@ -239,6 +240,58 @@ local function refreshCache(onProgress) cache.furnaceCount = furnaceCount 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 ------------------------------------------------- @@ -1079,78 +1132,91 @@ local function main() print("Console shows log. Use the monitor to interact.") print("") - -- Initial scan with progress bar on monitor - print("[INIT] 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) + -- Try loading cached inventory from disk for instant startup + local cacheLoaded = loadCacheFromDisk() + if cacheLoaded then + print("[INIT] Loaded cached inventory (" .. #cache.itemList .. " types)") + print("[INIT] Background refresh starting...") 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 - print("[INIT] Done. Found " .. #cache.itemList .. " item types.") print("") parallel.waitForAny( -- Task 1: Background inventory scanner 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 sleep(SCAN_INTERVAL) pcall(refreshCache)