Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- -- Powah Reactor Monitoring System
- -- Based on the multi-monitor interface framework
- -- Configuration
- local MONITOR_WIDTH = 5 -- 5 monitors wide
- local MONITOR_HEIGHT = 3 -- 3 monitors high
- local REACTOR_NAME = "powah:reactor_part_0" -- Change this to match your reactor's peripheral name
- local SPEAKER_NAME = "speaker" -- Change this to match your speaker's peripheral name
- local CHECK_INTERVAL = 5 -- Check fuel every 5 seconds
- -- Global variables
- local monitors = {}
- local reactor = nil
- local speaker = nil
- local totalWidth = 0
- local totalHeight = 0
- local buttons = {}
- local alertMuted = false
- local fuelEmpty = false
- local lastFuelAmount = 0
- -- Initialize the system
- function init()
- -- Find monitors - improved detection
- local allPeripherals = peripheral.getNames()
- local monitorCount = 0
- -- Print all available peripherals for debugging
- print("Available peripherals:")
- for _, name in ipairs(allPeripherals) do
- print("- " .. name .. " (" .. peripheral.getType(name) .. ")")
- end
- -- First try the standard naming convention with a wider range
- for i = 0, 15 do -- Try a wider range of indices
- local name = "monitor_" .. i
- if peripheral.isPresent(name) then
- print("Found monitor: " .. name)
- monitors[monitorCount+1] = peripheral.wrap(name)
- monitors[monitorCount+1].setTextScale(0.5)
- monitors[monitorCount+1].clear()
- monitorCount = monitorCount + 1
- end
- end
- -- If we didn't find enough monitors, look for any monitor peripherals
- if monitorCount < (MONITOR_WIDTH * MONITOR_HEIGHT) then
- for _, name in ipairs(allPeripherals) do
- -- Check if it's a monitor and not already in our list
- if peripheral.getType(name) == "monitor" then
- local alreadyAdded = false
- for _, existingMonitor in pairs(monitors) do
- if peripheral.getName(existingMonitor) == name then
- alreadyAdded = true
- break
- end
- end
- if not alreadyAdded and monitorCount < (MONITOR_WIDTH * MONITOR_HEIGHT) then
- monitorCount = monitorCount + 1
- monitors[monitorCount] = peripheral.wrap(name)
- monitors[monitorCount].setTextScale(0.5)
- monitors[monitorCount].clear()
- print("Added monitor: " .. name)
- end
- end
- end
- end
- if monitorCount < (MONITOR_WIDTH * MONITOR_HEIGHT) then
- print("Warning: Not all monitors detected. Found " .. monitorCount .. "/" .. (MONITOR_WIDTH * MONITOR_HEIGHT))
- -- If we found at least one monitor, let's continue anyway
- if monitorCount > 0 then
- print("Continuing with available monitors...")
- -- Adjust the expected dimensions based on what we have
- MONITOR_WIDTH = 1
- MONITOR_HEIGHT = monitorCount
- else
- return false
- end
- else
- print("Successfully connected to " .. monitorCount .. " monitors")
- end
- -- Find Powah Reactor
- reactor = peripheral.wrap(REACTOR_NAME)
- if not reactor then
- print("Error: Powah Reactor not found! Trying to find it automatically...")
- -- Try to find it automatically
- reactor = peripheral.find("powah_reactor")
- if not reactor then
- print("Error: Could not find any Powah Reactor!")
- return false
- else
- print("Found Powah Reactor: " .. peripheral.getName(reactor))
- end
- else
- print("Connected to Powah Reactor: " .. REACTOR_NAME)
- end
- -- Find Speaker
- speaker = peripheral.wrap(SPEAKER_NAME)
- if not speaker then
- print("Warning: Speaker not found! Trying to find it automatically...")
- -- Try to find it automatically
- speaker = peripheral.find("speaker")
- if not speaker then
- print("Warning: Could not find any speaker. Alerts will be visual only.")
- else
- print("Found Speaker: " .. peripheral.getName(speaker))
- end
- else
- print("Connected to Speaker: " .. SPEAKER_NAME)
- end
- -- Get monitor dimensions
- if monitorCount > 0 then
- local w, h = monitors[1].getSize()
- totalWidth = w * MONITOR_WIDTH
- totalHeight = h * MONITOR_HEIGHT
- print("Total display size: " .. totalWidth .. "x" .. totalHeight)
- end
- return true
- end
- -- Convert global coordinates to monitor-specific coordinates
- function getMonitorAt(x, y)
- if x < 1 or y < 1 or x > totalWidth or y > totalHeight then
- return nil
- end
- local monitorWidth = totalWidth / MONITOR_WIDTH
- local monitorHeight = totalHeight / MONITOR_HEIGHT
- local monX = math.ceil(x / monitorWidth)
- local monY = math.ceil(y / monitorHeight)
- local index = (monY - 1) * MONITOR_WIDTH + monX
- -- Check if the monitor exists at this index
- if not monitors[index] then
- print("Warning: No monitor found at index " .. index .. " (position " .. monX .. "," .. monY .. ")")
- return nil
- end
- local relX = (x - 1) % monitorWidth + 1
- local relY = (y - 1) % monitorHeight + 1
- return monitors[index], relX, relY
- end
- -- Clear all monitors
- function clearScreen()
- for _, monitor in pairs(monitors) do
- monitor.clear()
- end
- end
- -- Write text at global coordinates
- function writeText(x, y, text, textColor, bgColor)
- local monitor, relX, relY = getMonitorAt(x, y)
- if monitor then
- if textColor then monitor.setTextColor(textColor) end
- if bgColor then monitor.setBackgroundColor(bgColor) end
- monitor.setCursorPos(relX, relY)
- monitor.write(text)
- end
- end
- -- Draw a filled rectangle
- function fillRect(startX, startY, endX, endY, color)
- for y = startY, endY do
- for x = startX, endX do
- local monitor, relX, relY = getMonitorAt(x, y)
- if monitor then
- monitor.setBackgroundColor(color)
- monitor.setCursorPos(relX, relY)
- monitor.write(" ")
- end
- end
- end
- end
- -- Draw a button with text
- function drawButton(x, y, width, height, text, bgColor, textColor)
- fillRect(x, y, x + width - 1, y + height - 1, bgColor or colors.blue)
- -- Center the text
- local textX = x + math.floor((width - #text) / 2)
- local textY = y + math.floor(height / 2)
- writeText(textX, textY, text, textColor or colors.white, bgColor or colors.blue)
- return {
- x = x,
- y = y,
- width = width,
- height = height,
- text = text
- }
- end
- -- Check if coordinates are within a button
- function isInButton(button, x, y)
- return x >= button.x and x < button.x + button.width and
- y >= button.y and y < button.y + button.height
- end
- -- Draw a centered title
- function drawTitle(y, text, color)
- local textX = math.floor((totalWidth - #text) / 2) + 1
- writeText(textX, y, text, color or colors.yellow, colors.black)
- end
- -- Get reactor fuel information
- function getReactorInfo()
- if not reactor then
- return {
- fuelAmount = 0,
- maxFuelAmount = 1,
- energyStored = 0,
- maxEnergyStored = 1,
- generating = 0,
- active = false
- }
- end
- local info = {
- fuelAmount = 0,
- maxFuelAmount = 64,
- energyStored = 0,
- maxEnergyStored = 1000000,
- generating = 0,
- active = false
- }
- -- Try to get fuel information
- if reactor.list then
- local items = reactor.list()
- for slot, item in pairs(items) do
- -- Check for uraninite
- if item.name and item.name:find("uraninite") then
- info.fuelAmount = info.fuelAmount + item.count
- if item.maxCount then
- info.maxFuelAmount = item.maxCount * 8 -- Assuming 8 fuel slots
- end
- end
- end
- end
- -- Get energy information
- if reactor.getEnergy then
- info.energyStored = reactor.getEnergy()
- info.maxEnergyStored = reactor.getEnergyCapacity() or 1000000
- end
- -- Get generation rate
- if reactor.getGenerationRate then
- info.generating = reactor.getGenerationRate()
- end
- -- Get active status
- if reactor.isActive then
- info.active = reactor.isActive()
- else
- info.active = (info.fuelAmount > 0)
- end
- return info
- end
- -- Play alert sound
- function playAlert()
- if speaker and not alertMuted then
- speaker.playNote("block.note_block.bell", 1.0, 1.0)
- sleep(0.2)
- speaker.playNote("block.note_block.bell", 1.0, 0.8)
- sleep(0.2)
- speaker.playNote("block.note_block.bell", 1.0, 0.6)
- end
- end
- -- Draw the main monitoring screen
- function drawMonitoringScreen()
- clearScreen()
- buttons = {}
- -- Draw title
- drawTitle(2, "Powah Reactor Monitoring System", colors.yellow)
- -- Get reactor info
- local info = getReactorInfo()
- -- Calculate fuel percentage
- local fuelPercent = (info.fuelAmount / info.maxFuelAmount) * 100
- -- Draw fuel gauge background
- local gaugeWidth = math.floor(totalWidth * 0.8)
- local gaugeHeight = 3
- local gaugeX = math.floor((totalWidth - gaugeWidth) / 2)
- local gaugeY = 6
- fillRect(gaugeX, gaugeY, gaugeX + gaugeWidth - 1, gaugeY + gaugeHeight - 1, colors.gray)
- -- Draw fuel gauge fill
- local fillWidth = math.floor((fuelPercent / 100) * gaugeWidth)
- if fillWidth > 0 then
- local fillColor = colors.green
- if fuelPercent < 25 then
- fillColor = colors.red
- elseif fuelPercent < 50 then
- fillColor = colors.orange
- end
- fillRect(gaugeX, gaugeY, gaugeX + fillWidth - 1, gaugeY + gaugeHeight - 1, fillColor)
- end
- -- Draw fuel text
- local fuelText = string.format("Uraninite: %d / %d (%.1f%%)",
- info.fuelAmount,
- info.maxFuelAmount,
- fuelPercent)
- writeText(math.floor((totalWidth - #fuelText) / 2), gaugeY + 1, fuelText, colors.white)
- -- Draw status information
- local statusY = gaugeY + gaugeHeight + 2
- local statusColor = colors.white
- -- Reactor status
- local statusText = "Reactor Status: "
- if info.active then
- statusText = statusText .. "Active"
- statusColor = colors.green
- else
- statusText = statusText .. "Inactive"
- statusColor = colors.red
- end
- writeText(math.floor((totalWidth - #statusText) / 2), statusY, statusText, statusColor)
- -- Energy information
- local energyY = statusY + 2
- local energyPercent = (info.energyStored / info.maxEnergyStored) * 100
- local energyText = string.format("Energy: %.1f%% (%.1f FE/t)",
- energyPercent,
- info.generating)
- writeText(math.floor((totalWidth - #energyText) / 2), energyY, energyText, colors.white)
- -- Alert status
- local alertY = energyY + 2
- local alertText = "Fuel Alert: "
- if fuelEmpty then
- alertText = alertText .. "FUEL EMPTY!"
- writeText(math.floor((totalWidth - #alertText) / 2), alertY, alertText, colors.red)
- -- Draw mute button
- local buttonText = alertMuted and "Unmute Alert" or "Mute Alert"
- local muteButton = drawButton(
- math.floor(totalWidth / 2) - 8,
- alertY + 2,
- 16,
- 3,
- buttonText,
- alertMuted and colors.gray or colors.red
- )
- muteButton.action = "toggle_mute"
- table.insert(buttons, muteButton)
- -- Play alert if not muted and fuel is empty
- if not alertMuted and info.fuelAmount == 0 and os.clock() % 10 < 5 then
- playAlert()
- end
- else
- alertText = alertText .. "Normal"
- writeText(math.floor((totalWidth - #alertText) / 2), alertY, alertText, colors.green)
- end
- -- Draw refresh button
- local refreshButton = drawButton(
- totalWidth - 12,
- totalHeight - 4,
- 10,
- 3,
- "Refresh",
- colors.blue
- )
- refreshButton.action = "refresh"
- table.insert(buttons, refreshButton)
- -- Draw last updated time
- local timeText = "Last updated: " .. textutils.formatTime(os.time(), true)
- writeText(2, totalHeight - 1, timeText, colors.lightGray)
- -- Check if fuel status has changed
- local currentlyEmpty = (info.fuelAmount == 0)
- if currentlyEmpty ~= fuelEmpty then
- fuelEmpty = currentlyEmpty
- if fuelEmpty then
- -- Fuel just ran out
- playAlert()
- else
- -- Fuel was added back
- alertMuted = false
- end
- end
- -- Store last fuel amount
- lastFuelAmount = info.fuelAmount
- end
- -- Handle touch events
- function handleTouch(x, y)
- for _, button in ipairs(buttons) do
- if isInButton(button, x, y) then
- if button.action == "toggle_mute" then
- alertMuted = not alertMuted
- drawMonitoringScreen()
- elseif button.action == "refresh" then
- drawMonitoringScreen()
- end
- break
- end
- end
- end
- -- Main program
- function run()
- if not init() then
- print("Failed to initialize the system")
- return
- end
- -- Draw initial screen
- drawMonitoringScreen()
- -- Main event loop with periodic updates
- local lastUpdateTime = os.clock()
- while true do
- -- Check if it's time for a periodic update
- local currentTime = os.clock()
- if currentTime - lastUpdateTime >= CHECK_INTERVAL then
- drawMonitoringScreen()
- lastUpdateTime = currentTime
- end
- -- Handle events
- local event, side, x, y = os.pullEvent("monitor_touch")
- handleTouch(x, y)
- end
- end
- -- Start the program
- run()
Add Comment
Please, Sign In to add comment