Add monitor dashboard functionality to inventory manager
This commit is contained in:
@@ -4,6 +4,179 @@
|
|||||||
local DROPPER_NAME = "minecraft:dropper_9"
|
local DROPPER_NAME = "minecraft:dropper_9"
|
||||||
local BARREL_NAME = "minecraft:barrel_0"
|
local BARREL_NAME = "minecraft:barrel_0"
|
||||||
local POLL_INTERVAL = 2 -- seconds between barrel checks
|
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
|
-- Inventory helpers
|
||||||
@@ -194,9 +367,16 @@ local function main()
|
|||||||
print("[WARN] Barrel not found: " .. BARREL_NAME)
|
print("[WARN] Barrel not found: " .. BARREL_NAME)
|
||||||
end
|
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("")
|
print("")
|
||||||
|
|
||||||
-- Run barrel watcher and command prompt in parallel
|
-- Run barrel watcher, dashboard, and command prompt in parallel
|
||||||
parallel.waitForAny(
|
parallel.waitForAny(
|
||||||
-- Task 1: Watch barrel for new items
|
-- Task 1: Watch barrel for new items
|
||||||
function()
|
function()
|
||||||
@@ -206,7 +386,15 @@ local function main()
|
|||||||
end
|
end
|
||||||
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()
|
function()
|
||||||
while true do
|
while true do
|
||||||
local items = showCatalogue()
|
local items = showCatalogue()
|
||||||
|
|||||||
Reference in New Issue
Block a user