diff --git a/inventoryManager.lua b/inventoryManager.lua index 83a5682..8e5fe6f 100644 --- a/inventoryManager.lua +++ b/inventoryManager.lua @@ -4,6 +4,179 @@ local DROPPER_NAME = "minecraft:dropper_9" local BARREL_NAME = "minecraft:barrel_0" local POLL_INTERVAL = 2 -- seconds between barrel checks +local MONITOR_SIDE = "left" +local DASH_REFRESH = 3 -- seconds between dashboard refreshes + +------------------------------------------------- +-- Monitor Dashboard +------------------------------------------------- + +local mon = nil + +local function setupMonitor() + mon = peripheral.wrap(MONITOR_SIDE) + if not mon then return false end + mon.setTextScale(0.5) + mon.clear() + return true +end + +-- Helpers +local function monWrite(x, y, text, fg, bg) + mon.setCursorPos(x, y) + if fg then mon.setTextColor(fg) end + if bg then mon.setBackgroundColor(bg) end + mon.write(text) +end + +local function monFill(y, color) + local w, _ = mon.getSize() + mon.setCursorPos(1, y) + mon.setBackgroundColor(color) + mon.write(string.rep(" ", w)) +end + +local function monCenter(y, text, fg, bg) + local w, _ = mon.getSize() + local x = math.floor((w - #text) / 2) + 1 + monWrite(x, y, text, fg, bg) +end + +local function monBar(x, y, width, ratio, barColor, bgColor) + local filled = math.floor(ratio * width) + mon.setCursorPos(x, y) + mon.setBackgroundColor(barColor) + mon.write(string.rep(" ", filled)) + mon.setBackgroundColor(bgColor) + mon.write(string.rep(" ", width - filled)) +end + +-- Draw the full dashboard +local function drawDashboard() + if not mon then return end + + local w, h = mon.getSize() + + -- Clear + mon.setBackgroundColor(colors.black) + mon.clear() + + -- ===== Title bar ===== + monFill(1, colors.blue) + monCenter(1, " ** INVENTORY MANAGER ** ", colors.white, colors.blue) + + -- ===== Status bar ===== + monFill(2, colors.gray) + local chests = getChests() + local dropperOk = peripheral.wrap(DROPPER_NAME) ~= nil + local barrelOk = peripheral.wrap(BARREL_NAME) ~= nil + + local statusParts = {} + table.insert(statusParts, string.format(" Chests: %d", #chests)) + table.insert(statusParts, dropperOk and "Dropper: OK" or "Dropper: --") + table.insert(statusParts, barrelOk and "Barrel: OK" or "Barrel: --") + local statusLine = table.concat(statusParts, " | ") + + monWrite(2, 2, statusLine, colors.white, colors.gray) + + -- Dropper/Barrel status indicators + local indicatorX = w - 10 + if indicatorX > #statusLine + 3 then + monWrite(indicatorX, 2, dropperOk and " \7 " or " x ", dropperOk and colors.lime or colors.red, colors.gray) + monWrite(indicatorX + 4, 2, barrelOk and " \7 " or " x ", barrelOk and colors.lime or colors.red, colors.gray) + end + + -- ===== Divider ===== + monFill(3, colors.lightBlue) + monCenter(3, string.rep("\140", math.min(w - 4, 60)), colors.cyan, colors.lightBlue) + + -- ===== Item catalogue ===== + local catalogue = buildCatalogue() + + -- Collect and sort items + local itemList = {} + local grandTotal = 0 + for itemName, sources in pairs(catalogue) do + local total = 0 + for _, s in ipairs(sources) do total = total + s.total end + grandTotal = grandTotal + total + table.insert(itemList, { name = itemName, total = total, sources = #sources }) + end + table.sort(itemList, function(a, b) return a.total > b.total end) + + -- Header row + local row = 5 + monFill(row, colors.gray) + monWrite(2, row, "#", colors.lightGray, colors.gray) + monWrite(5, row, "Item", colors.lightGray, colors.gray) + monWrite(w - 22, row, "Qty", colors.lightGray, colors.gray) + monWrite(w - 14, row, "Stock", colors.lightGray, colors.gray) + row = row + 1 + + -- Find max for bar scaling + local maxCount = 0 + for _, item in ipairs(itemList) do + if item.total > maxCount then maxCount = item.total end + end + if maxCount == 0 then maxCount = 1 end + + -- Item rows + local maxRows = h - row - 3 -- leave space for footer + for i, item in ipairs(itemList) do + if i > maxRows then break end + + local y = row + local short = item.name:gsub("^minecraft:", ""):gsub("_", " ") + -- Capitalize first letter + short = short:sub(1,1):upper() .. short:sub(2) + + -- Truncate if too long + local maxNameLen = w - 30 + if #short > maxNameLen then + short = short:sub(1, maxNameLen - 2) .. ".." + end + + -- Alternating row background + local rowBg = (i % 2 == 0) and colors.gray or colors.black + + monFill(y, rowBg) + + -- Index number + monWrite(2, y, string.format("%2d", i), colors.lightBlue, rowBg) + + -- Item name + monWrite(5, y, short, colors.white, rowBg) + + -- Quantity + local qtyStr = tostring(item.total) + monWrite(w - 22, y, qtyStr, colors.yellow, rowBg) + + -- Stock bar + local ratio = item.total / maxCount + local barColor = colors.lime + if ratio < 0.25 then barColor = colors.red + elseif ratio < 0.5 then barColor = colors.orange + end + monBar(w - 14, y, 12, ratio, barColor, rowBg == colors.gray and colors.lightGray or colors.gray) + + row = row + 1 + end + + -- ===== Footer ===== + local footerY = h - 1 + monFill(footerY, colors.gray) + monWrite(2, footerY, + string.format(" Total: %d items across %d types ", grandTotal, #itemList), + colors.white, colors.gray) + + -- Timestamp + local timeStr = textutils.formatTime(os.time(), true) + monWrite(w - #timeStr - 1, footerY, timeStr, colors.lightGray, colors.gray) + + -- Bottom accent + monFill(h, colors.blue) + monCenter(h, " \4 Auto-Sort Active \4 ", colors.lightBlue, colors.blue) +end ------------------------------------------------- -- Inventory helpers @@ -194,9 +367,16 @@ local function main() print("[WARN] Barrel not found: " .. BARREL_NAME) end + -- Setup monitor + if setupMonitor() then + print("[OK] Monitor found on: " .. MONITOR_SIDE) + else + print("[WARN] No monitor on " .. MONITOR_SIDE .. ". Dashboard disabled.") + end + print("") - -- Run barrel watcher and command prompt in parallel + -- Run barrel watcher, dashboard, and command prompt in parallel parallel.waitForAny( -- Task 1: Watch barrel for new items function() @@ -206,7 +386,15 @@ local function main() end end, - -- Task 2: Interactive command prompt + -- Task 2: Dashboard refresh + function() + while true do + pcall(drawDashboard) + sleep(DASH_REFRESH) + end + end, + + -- Task 3: Interactive command prompt function() while true do local items = showCatalogue()