local files = {} local VERSION = "0.76" local SYS_NAME = "Dralib" local CONF_OPTS = { "power.conf", } files["lib/dralib.lua"] = "local dralib = {}\r\ dralib.Renderer = {}\r\ \r\ local w, h, vH\r\ local target = term\r\ local setCursor, setBG, setFG, write\r\ local Buffer = {}\r\ \r\ function dralib.Renderer.setTarget(newTarget)\r\ target = newTarget\r\ target.cacheW, target.cacheH = target.getSize()\r\ w, h = target.getSize()\r\ vH = math.floor(h * 1.5)\r\ setCursor = target.setCursorPos\r\ setBG = target.setBackgroundColor\r\ setFG = target.setTextColor\r\ write = target.write\r\ dralib.Renderer.init()\r\ end\r\ \r\ function dralib.Renderer.getBufferCell(x, y)\r\ if Buffer[y] and Buffer[y][x] then\r\ return Buffer[y][x]\r\ end\r\ return nil\r\ end\r\ \r\ function dralib.Renderer.init()\r\ if not w or not h then dralib.Renderer.setTarget(term) end\r\ Buffer = {} \r\ for y = 1, h do\r\ Buffer[y] = {}\r\ for x = 1, w do\r\ Buffer[y][x] = {colors.black, colors.black, \" \"}\r\ end\r\ end\r\ end\r\ \r\ function dralib.Renderer.set(x, y, col)\r\ if x < 1 or x > w or y < 1 or y > vH then return end\r\ if not Buffer[1] then dralib.Renderer.init() end\r\ local group = math.floor((y - 1) / 3)\r\ local subY = (y - 1) % 3\r\ \r\ if subY == 0 then\r\ local row = group * 2 + 1\r\ if Buffer[row] then\r\ Buffer[row][x][1] = col\r\ Buffer[row][x][3] = \"\\143\"\r\ end\r\ elseif subY == 1 then\r\ local rowA, rowB = group * 2 + 1, group * 2 + 2\r\ if Buffer[rowA] then Buffer[rowA][x][2] = col end\r\ if Buffer[rowB] then\r\ Buffer[rowB][x][1] = col\r\ Buffer[rowB][x][3] = \"\\131\"\r\ end\r\ elseif subY == 2 then\r\ local row = group * 2 + 2\r\ if Buffer[row] then Buffer[row][x][2] = col end\r\ end\r\ end\r\ \r\ function dralib.Renderer.drawRLE(sizex, sizey, rle_string, startX, startY, color)\r\ local first, counts = rle_string:match(\"^(%d):(.+)$\")\r\ if not first then return end\r\ \r\ local bit = tonumber(first)\r\ local x, y = 0, 0\r\ for count in counts:gmatch(\"(%d+)\") do\r\ for i = 1, tonumber(count) do\r\ if bit == 1 then\r\ dralib.Renderer.set(startX + x, startY + y, color)\r\ end\r\ x = x + 1\r\ if x >= sizex then \r\ x = 0\r\ y = y + 1 \r\ end\r\ end\r\ bit = 1 - bit\r\ end\r\ end\r\ \r\ function dralib.Renderer.saveRLE(data_table)\r\ local firstBit = data_table[1] or 0\r\ local result = { tostring(firstBit) }\r\ local current = firstBit\r\ local count = 0\r\ for _, val in ipairs(data_table) do\r\ if val == current then\r\ count = count + 1\r\ else\r\ table.insert(result, count)\r\ current = val\r\ count = 1\r\ end\r\ end\r\ table.insert(result, count)\r\ return result[1] .. \":\" .. table.concat({select(2, unpack(result))}, \"_\")\r\ end\r\ \r\ function dralib.Renderer.drawCircle(centerX, centerY, radius, col)\r\ local r2 = (radius + 0.25) * (radius + 0.25)\r\ for dy = -radius, radius do\r\ local dx = math.floor(math.sqrt(math.max(0, r2 - dy * dy)))\r\ dralib.Renderer.set(centerX - dx, centerY + dy, col)\r\ dralib.Renderer.set(centerX + dx, centerY + dy, col)\r\ end\r\ for dx = -radius, radius do\r\ local dy = math.floor(math.sqrt(math.max(0, r2 - dx * dx)))\r\ dralib.Renderer.set(centerX + dx, centerY - dy, col)\r\ dralib.Renderer.set(centerX + dx, centerY + dy, col)\r\ end\r\ end\r\ function dralib.Renderer.drawFilledCircle(centerX, centerY, radius, col)\r\ local r2 = (radius + 0.25) * (radius + 0.25)\r\ \r\ for dy = -radius, radius do\r\ local dx = math.floor(math.sqrt(math.max(0, r2 - (dy * dy))))\r\ \r\ local startX = centerX - dx\r\ local endX = centerX + dx\r\ \r\ for x = startX, endX do\r\ dralib.Renderer.set(x, centerY + dy, col)\r\ end\r\ end\r\ end\r\ \r\ function dralib.Renderer.render()\r\ for y = 1, h do\r\ for x = 1, w do\r\ local cell = Buffer[y][x]\r\ if cell[3] ~= \" \" or cell[2] ~= colors.black then\r\ setCursor(x, y)\r\ setFG(cell[1])\r\ setBG(cell[2])\r\ write(cell[3])\r\ end\r\ end\r\ end\r\ end\r\ \r\ function dralib.Renderer.clear(col)\r\ local c = col or colors.black\r\ for y = 1, h do\r\ for x = 1, w do Buffer[y][x] = {c, c, \" \"} end\r\ end\r\ end\r\ dralib.GUI = {}\r\ \r\ function dralib.GUI.new(display)\r\ local self = {}\r\ local clickZones = {}\r\ dralib.Renderer.setTarget(display)\r\ \r\ function self.reset()\r\ clickZones = {}\r\ end\r\ \r\ function self.clear()\r\ display.setBackgroundColor(colors.black)\r\ display.setTextColor(colors.white)\r\ display.clear()\r\ display.setCursorPos(1,1)\r\ self.reset()\r\ end\r\ \r\ function self.registerArea(x, y, w, h, onClick)\r\ table.insert(clickZones, {x=x, y=y, w=w, h=h, onClick=onClick})\r\ end\r\ \r\ function self.handleEvent(event, p1, p2, p3)\r\ if event ~= \"mouse_click\" and event ~= \"monitor_touch\" then\r\ return false\r\ end\r\ \r\ local x = tonumber(p2) or 0\r\ local y = tonumber(p3) or 0\r\ \r\ for _, zone in ipairs(clickZones) do\r\ if x >= zone.x and x <= (zone.x + zone.w - 1) and\r\ y >= zone.y and y <= (zone.y + zone.h - 1) then\r\ if zone.onClick then\r\ zone.onClick()\r\ return true\r\ end\r\ end\r\ end\r\ return false\r\ end\r\ \r\ function self.inputKeyboard(title, prompt, startX, startY, limit)\r\ local input = \"\"\r\ local typing = true\r\ local btnW, btnH = 3, 2 \r\ local limit = limit or 14\r\ local startX = startX or 1\r\ local startY = startY or 1\r\ local rows = {\r\ {\"1\",\"2\",\"3\",\"4\",\"5\",\"6\",\"7\",\"8\",\"9\",\"0\"},\r\ {\"q\",\"w\",\"e\",\"r\",\"t\",\"y\",\"u\",\"i\",\"o\",\"p\"},\r\ {\"a\",\"s\",\"d\",\"f\",\"g\",\"h\",\"j\",\"k\",\"l\"},\r\ {\"z\",\"x\",\"c\",\"v\",\"b\",\"n\",\"m\",\"-\"}\r\ }\r\ local needsRedraw = true\r\ while typing do\r\ if needsRedraw then\r\ self.reset()\r\ display.setBackgroundColor(colors.black)\r\ display.setTextColor(colors.yellow)\r\ for i = 0, 13 do\r\ display.setCursorPos(startX, startY + i)\r\ display.write(string.rep(\" \", 38))\r\ end\r\ display.setCursorPos(48, 3)\r\ display.setBackgroundColor(colors.red)\r\ display.setTextColor(colors.white)\r\ display.write(\" X \")\r\ self.registerArea(48, 3, 3, 1, function() \r\ input = nil \r\ typing = false \r\ end)\r\ display.setBackgroundColor(colors.black)\r\ display.setCursorPos(startX, startY)\r\ display.write(title)\r\ display.setCursorPos(startX, startY + 1)\r\ display.write(prompt .. \":\")\r\ display.setCursorPos(startX, startY + 3)\r\ display.setTextColor(colors.white)\r\ display.write(\"> \" .. input .. \"_\" .. string.rep(\" \", limit - #input))\r\ for rIdx, row in ipairs(rows) do\r\ local rowOffset = (rIdx - 1) * 1 \r\ for cIdx, char in ipairs(row) do\r\ local bX = startX + rowOffset + (cIdx - 1) * btnW\r\ local bY = (startY + 5) + (rIdx - 1) * btnH\r\ local isEven = (rIdx + cIdx) % 2 == 0\r\ display.setBackgroundColor(isEven and colors.gray or colors.lightGray)\r\ display.setTextColor(colors.white)\r\ for ty = 0, btnH - 1 do\r\ display.setCursorPos(bX, bY + ty)\r\ display.write(string.rep(\" \", btnW))\r\ end\r\ display.setCursorPos(bX + 1, bY + math.floor(btnH/2))\r\ display.write(char)\r\ self.registerArea(bX, bY, btnW, btnH, function() \r\ if #input < limit then input = input .. char end \r\ end)\r\ end\r\ end\r\ local controlY = (startY + 5) + (#rows * btnH)\r\ local controls = { \r\ {label=\"[UNDO]\", val=\"back\", x=startX, w=7, c=colors.red},\r\ {label=\"[ SPACE ]\", val=\" \", x=startX + 7, w=15, c=colors.blue},\r\ {label=\"[ACCEPT]\", val=\"done\", x=startX + 22, w=9, c=colors.green}\r\ } \r\ for _, ctrl in ipairs(controls) do\r\ display.setBackgroundColor(ctrl.c)\r\ display.setTextColor(colors.white)\r\ display.setCursorPos(ctrl.x, controlY)\r\ display.write(string.rep(\" \", ctrl.w))\r\ display.setCursorPos(ctrl.x + (math.floor((ctrl.w - #ctrl.label)/2)), controlY)\r\ display.write(ctrl.label) \r\ self.registerArea(ctrl.x, controlY, ctrl.w, 1, function()\r\ if ctrl.val == \"done\" then typing = false\r\ elseif ctrl.val == \"back\" then input = input:sub(1, -2)\r\ elseif #input < limit then input = input .. ctrl.val end\r\ end)\r\ end\r\ needsRedraw = false\r\ end\r\ local event, p1, p2, p3 = os.pullEvent()\r\ if event ~= \"timer\" then\r\ needsRedraw = true\r\ if not self.handleEvent(event, p1, p2 or 0, p3 or 0) then\r\ if event == \"char\" and #input < limit then \r\ input = input .. p1\r\ elseif event == \"key\" then\r\ if p1 == keys.backspace then input = input:sub(1, -2)\r\ elseif p1 == keys.enter then typing = false end\r\ end\r\ end\r\ end\r\ end \r\ return input\r\ end\r\ \r\ function self.openWindow(menuTree)\r\ local backgroundClickZones = clickZones\r\ local menuStack = { menuTree }\r\ local windowOpen = true\r\ self.closeWindow = function()\r\ windowOpen = false\r\ display.setBackgroundColor(colors.black)\r\ display.clear()\r\ self.reset()\r\ end\r\ local needsRedraw = true\r\ while windowOpen do\r\ if needsRedraw then\r\ display.setBackgroundColor(colors.gray)\r\ for y = 3, 18 do\r\ display.setCursorPos(11, y)\r\ display.write(string.rep(\" \", 40))\r\ end\r\ display.setBackgroundColor(colors.black)\r\ for y = 4, 17 do\r\ display.setCursorPos(12, y)\r\ display.write(string.rep(\" \", 38))\r\ end\r\ local currentMenu = menuStack[#menuStack]\r\ display.setCursorPos(12, 3)\r\ display.setTextColor(colors.cyan)\r\ display.setBackgroundColor(colors.gray)\r\ local titleText = (type(currentMenu.title) == \"function\" and currentMenu.title() or currentMenu.title) or \"MENU\"\r\ display.write(\" \" .. (#menuStack > 1 and \"< \" or \"\") .. titleText:upper() .. \" \")\r\ display.setCursorPos(48, 3)\r\ display.setBackgroundColor(colors.red)\r\ display.setTextColor(colors.white)\r\ display.write(\" X \")\r\ clickZones = {}\r\ self.registerArea(48, 3, 3, 1, function() \r\ display.setBackgroundColor(colors.black)\r\ windowOpen = false\r\ display.clear()\r\ end)\r\ if currentMenu.customRender then\r\ currentMenu.customRender()\r\ else\r\ local startY = 4\r\ for i, item in ipairs(currentMenu.items or {}) do\r\ if startY > 17 then break end\r\ display.setCursorPos(13, startY)\r\ display.setBackgroundColor(colors.black)\r\ display.setTextColor(colors.white)\r\ display.write(tostring(type(item.label) == \"function\" and item.label() or item.label))\r\ self.registerArea(13, startY, 30, 1, function()\r\ if item.submenu then table.insert(menuStack, item.submenu)\r\ elseif item.action then if item.action() then windowOpen = false end display.setBackgroundColor(colors.black) end\r\ end)\r\ startY = startY + 1\r\ end\r\ end\r\ needsRedraw = false\r\ end\r\ local event, p1, p2, p3 = os.pullEvent()\r\ if event ~= \"timer\" then\r\ needsRedraw = true\r\ self.handleEvent(event, p1, p2, p3)\r\ elseif event == \"timer\" then\r\ local currentMenu = menuStack[#menuStack]\r\ if currentMenu and currentMenu.customRender then\r\ needsRedraw = true\r\ end\r\ end\r\ end\r\ clickZones = backgroundClickZones\r\ return true\r\ end\r\ return self\r\ end\r\ \r\ return dralib" files["dracore.lua"] = "_G.OS_VERSION = \"0.76\"\r\ local dralib = require(\"lib/dralib\")\r\ local lastCoreUpdate = 0\r\ local coreData = { input = 0, output = 0 }\r\ local running = true\r\ local screens = {}\r\ local configPath = \"power.conf\"\r\ local activeRegions = {}\r\ local scrollState = {}\r\ for i = 1, 10 do\r\ scrollState[i] = { offset = 0, direction = 1, pause = 0 }\r\ end\r\ for i = 1, 10 do\r\ activeRegions[i] = {active = false, bg = colors.gray, name = \"Region \" .. i, link = nil }\r\ end\r\ \r\ local allColors = {\r\ colors.white, colors.orange, colors.magenta, colors.lightBlue,\r\ colors.yellow, colors.lime, colors.pink, colors.gray,\r\ colors.lightGray, colors.cyan, colors.purple, colors.blue,\r\ colors.brown, colors.green, colors.red, colors.black\r\ }\r\ local function formatEnergy(n)\r\ if n >= 10^18 then return string.format(\"%.1f ERF\", n / 10^18) end\r\ if n >= 10^15 then return string.format(\"%.1f PRF\", n / 10^15) end\r\ if n >= 10^12 then return string.format(\"%.1f TRF\", n / 10^12) end\r\ if n >= 10^9 then return string.format(\"%.1f GRF\", n / 10^9) end\r\ if n >= 10^6 then return string.format(\"%.1f MRF\", n / 10^6) end\r\ if n >= 10^3 then return string.format(\"%.1f kRF\", n / 10^3) end\r\ return n .. \" RF\"\r\ end\r\ local function formatTime(seconds)\r\ if seconds <= 0 or seconds == math.huge then return \"Infinite\" end\r\ local units = {\r\ {singular = \"epoch\", plural = \"epochs\", sec = 31536000000000},\r\ {singular = \"millennium\", plural = \"millennia\", sec = 31536000000},\r\ {singular = \"year\", plural = \"years\", sec = 31536000},\r\ {singular = \"month\", plural = \"months\", sec = 2592000},\r\ {singular = \"day\", plural = \"days\", sec = 86400},\r\ {singular = \"hour\", plural = \"hours\", sec = 3600},\r\ {singular = \"minute\", plural = \"minutes\", sec = 60}\r\ }\r\ local parts = {}\r\ for _, u in ipairs(units) do\r\ if seconds >= u.sec then\r\ local val = math.floor(seconds / u.sec)\r\ local label = (val == 1) and u.singular or u.plural\r\ table.insert(parts, val .. \" \" .. label)\r\ seconds = seconds % u.sec\r\ end\r\ if #parts == 2 then break end\r\ end\r\ return #parts > 0 and table.concat(parts, \" \") or \"< 1 minute\"\r\ end\r\ local function saveConfig()\r\ local f = fs.open(configPath, \"w\")\r\ f.write(textutils.serialize(activeRegions))\r\ f.close()\r\ end\r\ \r\ local function loadConfig()\r\ if fs.exists(configPath) then\r\ local f = fs.open(configPath, \"r\")\r\ local data = textutils.unserialize(f.readAll())\r\ f.close()\r\ if type(data) == \"table\" then\r\ for i = 1, 10 do\r\ if data[i] ~= nil then\r\ if type(data[i]) == \"boolean\" then\r\ activeRegions[i].active = data[i]\r\ elseif type(data[i]) == \"table\" then\r\ activeRegions[i] = data[i]\r\ end\r\ end\r\ end\r\ end\r\ end\r\ end\r\ loadConfig()\r\ local function refreshCoreData()\r\ if os.clock() - lastCoreUpdate > 1 then\r\ local core = peripheral.find(\"draconic_rf_core\") or peripheral.find(\"draconic_rf_storage\") \r\ if core and core.getInputPerTick then\r\ coreData.input = core.getInputPerTick() or 0\r\ coreData.output = core.getOutputPerTick() or 0\r\ else\r\ coreData.input = 0\r\ coreData.output = 0\r\ end\r\ lastCoreUpdate = os.clock()\r\ end\r\ end\r\ local function setupScreen(side)\r\ local device = side == \"term\" and term or peripheral.wrap(side)\r\ if device and device.getSize then\r\ screens[side] = {\r\ device = device,\r\ gui = dralib.GUI.new(device)\r\ }\r\ end\r\ end\r\ local function openSwapMenu(side, currentId)\r\ local screen = screens[side]\r\ local isInput = currentId <= 5\r\ local order = isInput and {4, 2, 1, 3, 5} or {9, 7, 6, 8, 10}\r\ \r\ screen.gui.openWindow({\r\ title = \"Select New Slot\",\r\ customRender = function()\r\ local startY = 4\r\ local frameStart = 13\r\ local frameEnd = 48\r\ local btnW = frameEnd - frameStart\r\ \r\ for i, targetId in ipairs(order) do\r\ local target = activeRegions[targetId]\r\ local y = startY + ((i - 1) * 3)\r\ local isSelected = (targetId == currentId)\r\ screen.device.setCursorPos(frameStart, y)\r\ if isSelected then\r\ screen.device.setBackgroundColor(colors.yellow)\r\ screen.device.setTextColor(colors.black)\r\ else\r\ screen.device.setBackgroundColor(target.active and target.bg or colors.gray)\r\ screen.device.setTextColor(target.active and colors.white or colors.lightGray)\r\ end\r\ local topLabel = \" SLOT \" .. targetId .. (isSelected and \" [SELECTED]\" or \"\")\r\ screen.device.setCursorPos(frameStart, y)\r\ screen.device.write(topLabel .. string.rep(\" \", btnW - #topLabel))\r\ local bottomLabel = target.active and (\" \" .. target.name) or \" (EMPTY)\"\r\ screen.device.setCursorPos(frameStart, y + 1)\r\ screen.device.write(bottomLabel .. string.rep(\" \", btnW - #bottomLabel))\r\ screen.gui.registerArea(frameStart, y, btnW, 2, function()\r\ if isSelected then return end\r\ local temp = activeRegions[targetId]\r\ activeRegions[targetId] = activeRegions[currentId]\r\ activeRegions[currentId] = temp\r\ saveConfig()\r\ screen.gui.closeWindow() \r\ end)\r\ end\r\ end\r\ })\r\ end\r\ local function Openregionmenu(side, regionId)\r\ local screen = screens[side]\r\ screen.gui.openWindow({\r\ title = function() return activeRegions[regionId].name end,\r\ customRender = function()\r\ if activeRegions[regionId].link then\r\ screen.device.setCursorPos(13, 4)\r\ screen.device.setBackgroundColor(colors.black)\r\ screen.device.setTextColor(colors.gray)\r\ screen.device.write(\"Linked: \" .. activeRegions[regionId].link)\r\ end\r\ local btnX, btnY, btnW = 13, 6, 20\r\ screen.device.setCursorPos(btnX, btnY)\r\ screen.device.setBackgroundColor(colors.gray)\r\ screen.device.setTextColor(colors.white)\r\ screen.device.write(string.rep(\" \", btnW))\r\ screen.device.setCursorPos(btnX + 3, btnY)\r\ screen.device.write(\"RENAME CONDUIT\")\r\ screen.gui.registerArea(btnX, btnY, btnW, 1, function()\r\ local newName = screen.gui.inputKeyboard(\"Rename\", \"Enter Name\", 12, 4, 15)\r\ if newName then\r\ activeRegions[regionId].name = newName\r\ saveConfig()\r\ end\r\ end)\r\ screen.device.setCursorPos(13, 16)\r\ screen.device.setBackgroundColor(colors.red)\r\ screen.device.setTextColor(colors.white)\r\ screen.device.write(\" [ DELETE CONDUIT ] \")\r\ screen.gui.registerArea(13, 16, 20, 1, function()\r\ activeRegions[regionId].active = false\r\ activeRegions[regionId].bg = colors.gray\r\ activeRegions[regionId].name = \"Region \" .. regionId\r\ activeRegions[regionId].link = nil\r\ saveConfig()\r\ screen.gui.closeWindow()\r\ end)\r\ screen.device.setCursorPos(13, 8)\r\ screen.device.setBackgroundColor(colors.gray)\r\ screen.device.setTextColor(colors.white)\r\ screen.device.write(string.rep(\" \", 19))\r\ screen.device.setCursorPos(13, 9)\r\ screen.device.write(string.rep(\" \", 19))\r\ screen.device.setCursorPos(17, 9)\r\ screen.device.write(\"CHANGE SLOT\")\r\ screen.gui.registerArea(13, 8, 19, 2, function()\r\ openSwapMenu(side, regionId)\r\ end)\r\ local gridW, gridH = 2, 8\r\ local cellW = 3\r\ local startX, startY = 42, 7\r\ screen.device.setBackgroundColor(activeRegions[regionId].bg)\r\ for y = -1, gridH do\r\ screen.device.setCursorPos(startX - 1, startY + y)\r\ screen.device.write(string.rep(\" \", (gridW * cellW) + 2))\r\ end\r\ screen.device.setCursorPos(44, 4)\r\ screen.device.write(\" \")\r\ screen.device.setCursorPos(44, 5)\r\ screen.device.write(\" \") \r\ screen.device.setCursorPos(44, 16)\r\ screen.device.write(\" \")\r\ screen.device.setCursorPos(44, 17)\r\ screen.device.write(\" \")\r\ for i, col in ipairs(allColors) do\r\ local row = math.floor((i - 1) / gridW)\r\ local colIdx = (i - 1) % gridW\r\ local x, y = startX + (colIdx * cellW), startY + row\r\ screen.device.setBackgroundColor(col)\r\ screen.device.setCursorPos(x, y)\r\ screen.device.write(string.rep(\" \", cellW))\r\ screen.gui.registerArea(x, y, cellW, 1, function()\r\ activeRegions[regionId].bg = col\r\ saveConfig()\r\ end)\r\ end\r\ end\r\ })\r\ drawInterface(side)\r\ end\r\ local function openOptionsMenu(side)\r\ local screen = screens[side]\r\ local function getLinkOwner(addr)\r\ for _, reg in ipairs(activeRegions) do\r\ if reg.link == addr then return reg.name end\r\ end\r\ return nil\r\ end\r\ local function openMeterLinkMenu(rangeStart, rangeEnd, title)\r\ local screen = screens[side]\r\ local currentPage = 1\r\ local itemsPerPage = 6\r\ local lastUpdate = os.clock()\r\ local cachedRates = {}\r\ local function getLinkData(addr)\r\ for id, reg in ipairs(activeRegions) do\r\ if reg.link == addr then return reg, id end\r\ end\r\ return nil, nil\r\ end\r\ local function refreshMeterData()\r\ local names = peripheral.getNames()\r\ for _, name in ipairs(names) do\r\ if peripheral.getType(name) == \"energymeter\" then\r\ local m = peripheral.wrap(name)\r\ cachedRates[name] = m and m.getTransferRate and m.getTransferRate() or 0\r\ end\r\ end\r\ lastUpdate = os.clock()\r\ end\r\ refreshMeterData()\r\ screen.gui.openWindow({\r\ title = title,\r\ customRender = function()\r\ if os.clock() - lastUpdate > 60 then\r\ refreshMeterData()\r\ end\r\ local names = peripheral.getNames()\r\ local meterList = {}\r\ for _, name in ipairs(names) do\r\ if peripheral.getType(name) == \"energymeter\" then\r\ table.insert(meterList, name)\r\ end\r\ end\r\ local startY, frameStart, frameEnd = 5, 13, 48\r\ local buttonWidth = frameEnd - frameStart\r\ local nameStartCol = 33\r\ local totalPages = math.max(1, math.ceil(#meterList / itemsPerPage))\r\ local firstIdx = (currentPage - 1) * itemsPerPage + 1\r\ local lastIdx = math.min(firstIdx + itemsPerPage - 1, #meterList)\r\ for i = firstIdx, lastIdx do\r\ local name = meterList[i]\r\ local region, regionId = getLinkData(name)\r\ local rate = cachedRates[name] or 0\r\ local y = startY + ((i - firstIdx) * 2)\r\ local meterID = name:match(\"_(%d+)$\") or \"?\"\r\ screen.device.setCursorPos(frameStart, y)\r\ if region then\r\ screen.device.setBackgroundColor(region.bg)\r\ screen.device.setTextColor(rate > 0 and colors.black or colors.black)\r\ else\r\ screen.device.setBackgroundColor(colors.lightGray)\r\ screen.device.setTextColor(colors.black)\r\ end\r\ local rateStr = \"[\" .. formatEnergy(rate) .. \"/t]\"\r\ local idStr = \" ID:\" .. meterID\r\ local prefix = idStr .. \" \" .. rateStr\r\ screen.device.write(prefix .. string.rep(\" \", nameStartCol - (frameStart + #prefix)))\r\ screen.device.setCursorPos(nameStartCol, y)\r\ local displayName = region and (\"(\" .. region.name .. \")\") or name\r\ local remainingSpace = frameEnd - nameStartCol\r\ local nameStr = displayName .. string.rep(\" \", remainingSpace - #displayName)\r\ screen.device.write(nameStr:sub(1, remainingSpace))\r\ if not region then\r\ screen.gui.registerArea(frameStart, y, buttonWidth, 1, function()\r\ local newName = screen.gui.inputKeyboard(\"Name Conduit\", \"Enter Name\", 12, 4, 15)\r\ if newName then\r\ for slot = rangeStart, rangeEnd do\r\ if not activeRegions[slot].active then\r\ activeRegions[slot].active = true\r\ activeRegions[slot].link = name\r\ activeRegions[slot].conduitID = slot\r\ activeRegions[slot].bg = colors.gray\r\ activeRegions[slot].name = newName\r\ saveConfig()\r\ screen.gui.closeWindow()\r\ return\r\ end\r\ end\r\ end\r\ end)\r\ end\r\ end\r\ if totalPages > 1 then\r\ local navY = 17\r\ local pageStatus = \"Page \" .. currentPage .. \"/\" .. totalPages\r\ screen.device.setBackgroundColor(colors.black)\r\ screen.device.setTextColor(colors.white)\r\ screen.device.setCursorPos(26 - (#pageStatus / 2), navY)\r\ screen.device.write(pageStatus)\r\ if currentPage > 1 then\r\ screen.device.setCursorPos(frameStart, navY)\r\ screen.device.setBackgroundColor(colors.gray)\r\ screen.device.write(\" < PREV \")\r\ screen.gui.registerArea(frameStart, navY, 8, 1, function() currentPage = currentPage - 1 end)\r\ end\r\ if currentPage < totalPages then\r\ screen.device.setCursorPos(frameEnd - 8, navY)\r\ screen.device.setBackgroundColor(colors.gray)\r\ screen.device.write(\" NEXT > \")\r\ screen.gui.registerArea(frameEnd - 8, navY, 8, 1, function() currentPage = currentPage + 1 end)\r\ end\r\ end\r\ end\r\ })\r\ end\r\ screen.gui.openWindow({\r\ title = \"Settings\",\r\ customRender = function()\r\ local ix, iy = 15, 6\r\ screen.device.setBackgroundColor(colors.green)\r\ screen.device.setTextColor(colors.white)\r\ screen.device.setCursorPos(ix, iy)\r\ screen.device.write(\" ADD INPUT \")\r\ screen.device.setCursorPos(ix, iy + 1)\r\ screen.device.write(\" CONDUIT \")\r\ screen.gui.registerArea(ix, iy, 12, 2, function()\r\ openMeterLinkMenu(1, 5, \"Select Input Meter\")\r\ end)\r\ local ox, oy = 33, 6\r\ screen.device.setBackgroundColor(colors.blue)\r\ screen.device.setTextColor(colors.white)\r\ screen.device.setCursorPos(ox, oy)\r\ screen.device.write(\" ADD OUTPUT \")\r\ screen.device.setCursorPos(ox, oy + 1)\r\ screen.device.write(\" CONDUIT \")\r\ screen.gui.registerArea(ox, oy, 12, 2, function()\r\ openMeterLinkMenu(6, 10, \"Select Output Meter\")\r\ end)\r\ end\r\ })\r\ drawInterface(side)\r\ end\r\ local function updateEnergyDisplay(side)\r\ local screen = screens[side]\r\ if not screen then return end\r\ local device = screen.device\r\ local w, h = device.getSize()\r\ local positions = {\r\ [1] = {x = 2, y = 10}, [2] = {x = 3, y = 8}, [3] = {x = 4, y = 12},\r\ [4] = {x = 5, y = 6}, [5] = {x = 6, y = 14}, [6] = {x = 38, y = 10},\r\ [7] = {x = 38, y = 8}, [8] = {x = 38, y = 12}, [9] = {x = 37, y = 6},\r\ [10] = {x = 36, y = 14}\r\ } \r\ for id, pos in pairs(positions) do\r\ local region = activeRegions[id]\r\ if region.active and region.link then\r\ local m = peripheral.wrap(region.link)\r\ local rate = (m and m.getTransferRate) and m.getTransferRate() or 0 \r\ local energyStr = formatEnergy(rate) .. \"/t\"\r\ local displayStr = (#energyStr <= 11) and (energyStr .. string.rep(\" \", 11 - #energyStr)) or string.sub(energyStr, 1, 11)\r\ device.setCursorPos(pos.x, pos.y)\r\ device.setBackgroundColor(colors.black)\r\ device.setTextColor(region.bg)\r\ device.write(displayStr)\r\ end\r\ end\r\ refreshCoreData()\r\ dralib.Renderer.setTarget(device)\r\ local totalCoreIn = coreData.input\r\ local currentX = 1\r\ if totalCoreIn <= 0 then\r\ for x = 1, w do dralib.Renderer.set(x, 28, colors.gray) end\r\ else\r\ for i = 1, 5 do\r\ local reg = activeRegions[i]\r\ if reg.active and reg.link then\r\ local m = peripheral.wrap(reg.link)\r\ local rate = (m and m.getTransferRate) and m.getTransferRate() or 0\r\ if rate > 0 then\r\ local segmentWidth = math.floor((rate / totalCoreIn) * w)\r\ for x = 1, segmentWidth do\r\ if currentX <= w then\r\ dralib.Renderer.set(currentX, 28, reg.bg)\r\ currentX = currentX + 1\r\ end\r\ end\r\ end\r\ end\r\ end\r\ while currentX <= w do\r\ dralib.Renderer.set(currentX, 28, colors.gray)\r\ currentX = currentX + 1\r\ end\r\ end\r\ local core = peripheral.find(\"draconic_rf_storage\") or peripheral.find(\"draconic_rf_core\")\r\ if core then\r\ local stored = core.getEnergyStored()\r\ local max = core.getMaxEnergyStored()\r\ local pct = (stored / max) * 100\r\ dralib.Renderer.drawFilledCircle(26, 14, 9, colors.black)\r\ local steps = {1, 4, 9, 17, 23, 35, 48, 63, 80, 100}\r\ local dynamicRadius = 0\r\ for i, threshold in ipairs(steps) do\r\ if pct >= threshold then dynamicRadius = i end\r\ end\r\ local coreColor = (pct >= 85) and colors.orange or colors.red\r\ if dynamicRadius > 0 then\r\ dralib.Renderer.drawFilledCircle(26, 14, dynamicRadius, coreColor)\r\ end\r\ end\r\ dralib.Renderer.render()\r\ local timeStr = \" Balanced \"\r\ if core then\r\ local stored = core.getEnergyStored()\r\ local max = core.getMaxEnergyStored()\r\ local net = coreData.input - coreData.output \r\ if net > 0 then\r\ local seconds = (max - stored) / (net * 20)\r\ timeStr = \"Full in: \" .. formatTime(seconds)\r\ elseif net < 0 then\r\ local seconds = stored / (math.abs(net) * 20)\r\ timeStr = \"Empty in: \" .. formatTime(seconds)\r\ else\r\ timeStr = \"Balanced\"\r\ end\r\ end\r\ local targetLen = 41\r\ local paddingTotal = targetLen - #timeStr\r\ local leftPad = math.floor(paddingTotal / 2)\r\ local rightPad = paddingTotal - leftPad\r\ local paddedTime = string.rep(\" \", leftPad) .. timeStr .. string.rep(\" \", rightPad)\r\ device.setBackgroundColor(colors.black) \r\ device.setTextColor(colors.green)\r\ local inStr = \"IN:\" .. formatEnergy(coreData.input) .. \"t\"\r\ device.setCursorPos(8 - (#inStr / 2), 17)\r\ device.write(inStr .. \" \")\r\ device.setTextColor(colors.red)\r\ local outStr = \"OUT:\" .. formatEnergy(coreData.output) .. \"t\" \r\ device.setCursorPos(45 - (#outStr / 2), 17)\r\ device.write(outStr .. \" \") \r\ device.setTextColor(colors.white)\r\ device.setCursorPos(math.floor(w / 2) - (targetLen / 2), 18)\r\ device.write(paddedTime)\r\ end\r\ function drawInterface(side)\r\ local screen = screens[side]\r\ local device = screen.device\r\ local w, h = device.getSize()\r\ screen.gui.reset()\r\ dralib.Renderer.setTarget(device)\r\ dralib.Renderer.clear(colors.black)\r\ local function injectIfActive(id, x1, y1, w1, x2, y2, w2)\r\ if activeRegions[id].active then\r\ local col = activeRegions[id].bg\r\ for x = x1, x1 + w1 - 1 do\r\ local cell = dralib.Renderer.getBufferCell(x, y1)\r\ if cell then cell[2] = col end\r\ end\r\ if y1 ~= y2 or x1 ~= x2 then\r\ for x = x2, x2 + w2 - 1 do\r\ local cell = dralib.Renderer.getBufferCell(x, y2)\r\ if cell then cell[2] = col end\r\ end\r\ end\r\ end\r\ end\r\ local function drawNameIfActive(id, x, y)\r\ local region = activeRegions[id]\r\ if not region.active then return end\r\ \r\ local maxW = 11\r\ local name = region.name\r\ local displayStr = \"\"\r\ \r\ if #name <= maxW then\r\ displayStr = name .. string.rep(\" \", maxW - #name)\r\ else\r\ displayStr = string.sub(name, 1, maxW)\r\ end\r\ \r\ screens[side].device.setCursorPos(x, y)\r\ screens[side].device.setBackgroundColor(region.bg)\r\ screens[side].device.setTextColor(colors.black)\r\ screens[side].device.write(displayStr)\r\ end\r\ local function regTouchIfActive(id, x1, y1, w1, x2, y2, w2, h_ov, y_off)\r\ if activeRegions[id].active then\r\ local minX = math.min(x1, x2)\r\ local minY = math.min(y1, y2) + (y_off or 0)\r\ local maxX = math.max(x1 + w1, x2 + w2)\r\ local clickH = h_ov or (math.max(y1, y2) - minY) + 1\r\ screen.gui.registerArea(minX, minY, maxX - minX, clickH, function()\r\ Openregionmenu(side, id)\r\ end)\r\ end\r\ end\r\ dralib.Renderer.setTarget(device)\r\ dralib.Renderer.clear(colors.black)\r\ for x = 1, 51 do dralib.Renderer.set(x, 1, colors.gray) end\r\ dralib.Renderer.drawCircle(26, 14, 11, colors.red)\r\ injectIfActive(1, 1, 9, 14, 1, 9, 14) \r\ injectIfActive(2, 1, 6, 3, 3, 7, 13) \r\ injectIfActive(3, 1, 12, 3, 3, 11, 13)\r\ injectIfActive(4, 1, 4, 5, 5, 5, 12) \r\ injectIfActive(5, 1, 14, 5, 5, 13, 12)\r\ injectIfActive(6, 38, 9, 14, 38, 9, 14)\r\ injectIfActive(7, 49, 6, 3, 37, 7, 13)\r\ injectIfActive(8, 49, 12, 3, 37, 11, 13)\r\ injectIfActive(9, 47, 4, 5, 36, 5, 12) \r\ injectIfActive(10, 47, 14, 5, 36, 13, 12)\r\ dralib.Renderer.render()\r\ regTouchIfActive(1, 1, 9, 14, 1, 9, 14, 3, -1)\r\ regTouchIfActive(2, 1, 6, 3, 3, 7, 13)\r\ regTouchIfActive(3, 1, 12, 3, 3, 11, 13)\r\ regTouchIfActive(4, 1, 4, 5, 5, 5, 12)\r\ regTouchIfActive(5, 1, 14, 5, 5, 13, 12)\r\ regTouchIfActive(6, 38, 9, 14, 38, 9, 14, 3, -1)\r\ regTouchIfActive(7, 49, 6, 3, 37, 7, 13)\r\ regTouchIfActive(8, 49, 12, 3, 37, 11, 13)\r\ regTouchIfActive(9, 47, 4, 5, 35, 5, 12)\r\ regTouchIfActive(10, 47, 14, 5, 35, 13, 12) \r\ drawNameIfActive(1, 2, 9)\r\ drawNameIfActive(2, 3, 7)\r\ drawNameIfActive(3, 3, 11)\r\ drawNameIfActive(4, 5, 5)\r\ drawNameIfActive(5, 5, 13)\r\ drawNameIfActive(6, 38, 9)\r\ drawNameIfActive(7, 38, 7)\r\ drawNameIfActive(8, 38, 11)\r\ drawNameIfActive(9, 37, 5)\r\ drawNameIfActive(10, 37, 13)\r\ local core = peripheral.find(\"draconic_rf_storage\")\r\ device.setCursorPos(2, 1)\r\ if core then\r\ local stored = formatEnergy(core.getEnergyStored())\r\ local max = formatEnergy(core.getMaxEnergyStored()) \r\ device.setBackgroundColor(colors.gray)\r\ device.setTextColor(colors.lightGray)\r\ device.write(\"[\")\r\ device.setTextColor(colors.orange)\r\ device.write(stored)\r\ device.setTextColor(colors.lightGray)\r\ device.write(\"/\")\r\ device.setTextColor(colors.orange)\r\ device.write(max)\r\ device.setTextColor(colors.lightGray)\r\ device.write(\"]\")\r\ else\r\ device.setTextColor(colors.red)\r\ device.write(\"[ CORE NOT FOUND ]\")\r\ end\r\ device.setCursorPos(w - 9, 1)\r\ device.setBackgroundColor(colors.gray)\r\ device.setTextColor(colors.cyan)\r\ device.write(\"[Options]\")\r\ screen.gui.registerArea(w - 9, 1, 9, 1, function() openOptionsMenu(side) end)\r\ screen.device.setBackgroundColor(colors.black)\r\ updateEnergyDisplay(side) \r\ energyTimer = os.startTimer(0.5)\r\ end\r\ local function initAll()\r\ term.setBackgroundColor(colors.black)\r\ term.clear()\r\ term.setCursorPos(1, 1)\r\ screens = {} \r\ setupScreen(\"term\") \r\ for _, side in ipairs(peripheral.getNames()) do\r\ if peripheral.getType(side) == \"monitor\" then \r\ setupScreen(side) \r\ local m = peripheral.wrap(side)\r\ if m then \r\ m.setTextScale(1)\r\ m.setBackgroundColor(colors.black)\r\ m.clear()\r\ end\r\ end\r\ end\r\ for side, _ in pairs(screens) do \r\ dralib.Renderer.setTarget(screens[side].device)\r\ dralib.Renderer.clear(colors.black)\r\ drawInterface(side) \r\ end\r\ end\r\ \r\ initAll()\r\ \r\ local energyTimer = os.startTimer(0.5)\r\ local fullRedrawTimer = os.startTimer(5)\r\ \r\ while running do\r\ local event, p1, p2, p3 = os.pullEvent() \r\ if event == \"mouse_click\" or event == \"monitor_touch\" then\r\ local side = (event == \"mouse_click\") and \"term\" or p1\r\ if screens[side] then \r\ screens[side].gui.handleEvent(event, p1, p2, p3)\r\ for s, _ in pairs(screens) do drawInterface(s) end\r\ end\r\ elseif event == \"em_data_changed\" then\r\ for side, _ in pairs(screens) do\r\ if not ((energyTimer or 0) <= 0.4) then\r\ energyTimer = os.startTimer(0.2)\r\ end\r\ end\r\ elseif event == \"timer\" then\r\ if p1 == energyTimer then\r\ for side, _ in pairs(screens) do \r\ updateEnergyDisplay(side)\r\ end\r\ energyTimer = os.startTimer(0.5)\r\ \r\ elseif p1 == fullRedrawTimer then\r\ for side, _ in pairs(screens) do \r\ drawInterface(side)\r\ end\r\ fullRedrawTimer = os.startTimer(5)\r\ energyTimer = os.startTimer(0.5)\r\ end\r\ elseif event == \"peripheral\" or event == \"peripheral_detach\" then\r\ initAll()\r\ end\r\ end" files["startup.lua"] = "local target = \"dracore.lua\"\ local function getFiles()\ local files = {\"shell\"}\ for _, f in ipairs(fs.list(\"/\")) do\ local ext = f:match(\"^.+(%..+)$\")\ if not fs.isDir(f) and f ~= \"startup.lua\" and f ~= \"shell\" and (not ext or ext == \".lua\") then\ table.insert(files, f)\ end\ end\ return files\ end\ local function setBar(y, text, w)\ term.setCursorPos(1, y)\ term.setBackgroundColor(colors.blue)\ term.setTextColor(colors.white)\ term.clearLine()\ term.setCursorPos(math.floor((w - #text) / 2) + 1, y)\ term.write(text)\ end\ local function save(new)\ local lines, f = {}, fs.open(\"startup.lua\", \"r\")\ for line in f.readLine do table.insert(lines, line:find(\"^local target\") and 'local target = \"'..new..'\"' or line) end\ f.close()\ f = fs.open(\"startup.lua\", \"w\")\ for _, l in ipairs(lines) do f.write(l .. \"\\n\") end\ f.close()\ os.reboot()\ end\ local w, h = term.getSize()\ local isCol = term.isColor()\ term.clear()\ local logo = {\".______.\", \"/ \\\\\", \"| energy * |\", \"|__________|\", \"EPA POL PREV\"}\ for i, v in ipairs(logo) do\ term.setCursorPos(37 + (i<3 and 3-i or 0), i)\ if i == 4 then\ term.setTextColor(16) term.write(\"|\") term.setTextColor(8192) term.write(\"__________\") term.setTextColor(16) term.write(\"|\")\ else\ term.setTextColor(i < 4 and 16 or 8192) term.write(v)\ end\ end\ term.setTextColor(1)\ term.setCursorPos(1, 1) term.write(os.version()..\" (C) 2026\")\ term.setCursorPos(1, 2) term.write(\"ID: \"..os.getComputerID())\ term.setCursorPos(1, 5) term.write(\"CPU: CraftCPU \"..(isCol and \"64\" or \"32\")..\"-Bit\")\ term.setCursorPos(1, 6) term.write(\"Arch: Lua 5.1 VM\")\ term.setCursorPos(1, h) term.write(\"Press Q for BIOS\")\ local inMenu = false\ for i = 0, (isCol and 1024 or 512), (isCol and 96 or 48) do\ term.setCursorPos(1, 8) term.write(\"RAM Test: \"..i..\"K OK\")\ local t = os.startTimer(0.03)\ while true do\ local e, k = os.pullEvent()\ if e == \"key\" and k == keys.q then inMenu = true break\ elseif e == \"timer\" and k == t then break end\ end\ if inMenu then break end\ end\ term.setCursorPos(1, 10) term.write(\"Booting: \"..target)\ if inMenu then\ local files, sel = getFiles(), 1\ while true do\ term.setBackgroundColor(colors.lightGray)\ term.clear()\ setBar(1, \"CMOS SETUP\", w)\ setBar(h-1, \"L-Click: Boot | R-Click: Default\", w)\ setBar(h, \"Arrows: Nav | Enter: Boot\", w)\ for i, f in ipairs(files) do\ term.setCursorPos(3, 2+i)\ term.setBackgroundColor(i == sel and 16384 or 256)\ term.setTextColor(i == sel and 1 or 2048)\ term.write(\" \"..f..(f == target and \" (def) \" or \" \"))\ end\ local e, p1, p2, p3 = os.pullEvent()\ if e == \"key\" then\ if p1 == keys.up then sel = (sel > 1) and sel - 1 or #files\ elseif p1 == keys.down then sel = (sel < #files) and sel + 1 or 1\ elseif p1 == keys.enter then target = files[sel] break\ elseif p1 == keys.s then save(files[sel]) end\ elseif (e == \"mouse_click\" or e == \"monitor_touch\") and p1 <= 2 then\ for i = 1, #files do\ if p3 == 2+i then\ if p1 == 2 then save(files[i]) else sel = i if e == \"mouse_click\" then target = files[i] goto boot end end\ end\ end\ end\ end\ end\ ::boot::\ term.setBackgroundColor(32768) term.setTextColor(1) term.clear()\ term.setCursorPos(1, 1) shell.run(target)\ " local term = term local monitor = peripheral.find("monitor") local w, h = term.getSize() if monitor then monitor.setTextScale(1) end local multiTerm = {} local targets = {term} if monitor then table.insert(targets, monitor) end local functions = {"write", "scroll", "setCursorPos", "setCursorBlink", "setBackgroundColor", "setTextColor", "clear", "clearLine", "setTextScale"} for _, name in ipairs(functions) do multiTerm[name] = function(...) for _, t in ipairs(targets) do if t[name] then t[name](...) end end end end multiTerm.getSize = function() return term.getSize() end local term = multiTerm local mode = "INSTALL" for path in pairs(files) do if fs.exists(path) then mode = "UPDATE" break end end local function drawBackground() term.setBackgroundColor(colors.blue) term.clear() term.setCursorPos(1, 1) term.setTextColor(colors.white) term.write(SYS_NAME .. " " .. VERSION .. " Setup") term.setCursorPos(1, 2) term.write(string.rep("=", w)) term.setCursorPos(1, h) term.setBackgroundColor(colors.lightGray) term.setTextColor(colors.black) term.clearLine() term.write(" ENTER=Continue F3=Exit") end local function drawWindow(x, y, width, height, title) term.setBackgroundColor(colors.black) for i = 1, height do term.setCursorPos(x + 1, y + i) term.write(string.rep(" ", width)) end term.setBackgroundColor(colors.lightGray) term.setTextColor(colors.black) for i = 0, height - 1 do term.setCursorPos(x, y + i) term.write(string.rep(" ", width)) end term.setCursorPos(x, y); term.write(string.rep("-", width)) term.setCursorPos(x, y + height - 1); term.write(string.rep("-", width)) if title then term.setCursorPos(x + (width / 2) - (#title / 2) - 1, y) term.write(" " .. title .. " ") end end local function getSettings() local autostart = true local resetList = {} for _, v in ipairs(CONF_OPTS) do resetList[v] = false end while true do drawBackground() term.setBackgroundColor(colors.blue) term.setTextColor(colors.white) term.setCursorPos(5, 4) term.write("Configure " .. SYS_NAME .. " installation.") term.setCursorPos(5, 5) term.write("Your user data will not be affected.") local winH = #CONF_OPTS + 7 drawWindow(8, 7, 36, winH, "Configuration") local optX, optY = 10, 9 term.setCursorPos(optX, optY) term.write(autostart and "[X] Run at startup" or "[ ] Run at startup") local i = 1 for _, file in ipairs(CONF_OPTS) do term.setCursorPos(optX, optY + i) term.write(resetList[file] and "[X] Reset " .. file or "[ ] Reset " .. file) i = i + 1 end local btnY = optY + i + 1 term.setBackgroundColor(colors.gray) term.setTextColor(colors.white) term.setCursorPos(optX, btnY); term.write(" " .. mode .. " ") term.setCursorPos(optX + 15, btnY); term.write(" CANCEL ") local event, p1, p2, p3 = os.pullEvent() if event == "key" then if p1 == keys.enter then return true, autostart, resetList elseif p1 == keys.f3 then return false end elseif event == "mouse_click" then local mx, my = p2, p3 if my == optY and mx >= optX and mx <= optX + 20 then autostart = not autostart elseif my > optY and my <= optY + #CONF_OPTS then local idx = my - optY local fname = CONF_OPTS[idx] resetList[fname] = not resetList[fname] elseif my == btnY then if mx >= optX and mx <= optX + 10 then return true, autostart, resetList elseif mx >= optX + 15 and mx <= optX + 25 then return false end end end end end local proceed, useAutostart, resetList = getSettings() if not proceed then term.setBackgroundColor(colors.black); term.clear(); term.setCursorPos(1,1) print("Setup cancelled."); return end for file, reset in pairs(resetList) do if reset and fs.exists(file) then fs.delete(file) end end drawBackground() drawWindow(8, 8, 36, 6, mode .. " IN PROGRESS") local total = 0 for _ in pairs(files) do total = total + 1 end local count = 0 for path, data in pairs(files) do if path ~= "startup.lua" or useAutostart then count = count + 1 term.setCursorPos(10, 10) term.write("Writing: " .. path:sub(1, 20) .. "...") local progress = math.floor((count / total) * 30) term.setCursorPos(10, 12) term.setBackgroundColor(colors.gray); term.write(string.rep(" ", 30)) term.setCursorPos(10, 12) term.setBackgroundColor(colors.black); term.write(string.rep(" ", progress)) local dir = path:match("(.+)/") if dir and not fs.exists(dir) then fs.makeDir(dir) end local f = fs.open(path, "w") f.write(data) f.close() sleep(0.05) end end drawBackground() drawWindow(10, 8, 32, 6, "Success") term.setCursorPos(12, 10); term.write(SYS_NAME .. " installed.") term.setCursorPos(12, 12); term.write("Press any key to reboot.") os.pullEvent() os.reboot()