Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- -- LemonOS: Pocket Shell for Lemonphone
- -- by ChatGPT (GPT-5)
- -- Features: Persistent settings, live clock, distance-based signal bars, auto-netchat install
- -- ===== CONFIG PATHS =====
- local CONFIG_PATH = "/lemonos.cfg"
- local NETCHAT_PATH = "/netchat"
- local STARTUP_PATH = "/startup.lua"
- -- ===== FIRMWARE INFO =====
- local firmware = {
- device = "Lemonphone",
- version = "LemonOS 2.0"
- }
- -- ===== SETTINGS =====
- local config = {
- username = "User",
- accentColor = colors.yellow,
- bgColor = colors.black,
- rednetSide = "back"
- }
- -- ===== CONFIG LOAD/SAVE =====
- local function saveConfig()
- local file = fs.open(CONFIG_PATH, "w")
- if file then
- file.write(textutils.serialize(config))
- file.close()
- end
- end
- local function loadConfig()
- if fs.exists(CONFIG_PATH) then
- local file = fs.open(CONFIG_PATH, "r")
- if file then
- local data = file.readAll()
- file.close()
- local ok, tbl = pcall(textutils.unserialize, data)
- if ok and type(tbl) == "table" then
- for k, v in pairs(tbl) do config[k] = v end
- end
- end
- end
- end
- loadConfig()
- -- ===== AUTO-DOWNLOAD NETCHAT =====
- if not fs.exists(NETCHAT_PATH) then
- print("Downloading netchat...")
- if http then
- local ok, resp = pcall(http.get, "https://pastebin.com/raw/KeRK2UWE")
- if ok and resp then
- local content = resp.readAll()
- resp.close()
- local file = fs.open(NETCHAT_PATH, "w")
- file.write(content)
- file.close()
- print("netchat installed!")
- else
- print("Failed to download netchat.")
- end
- else
- print("HTTP API not enabled.")
- end
- -- set startup to run firm.lpsw
- local file = fs.open(STARTUP_PATH, "w")
- file.write('shell.run("firm.lpsw")')
- file.close()
- end
- -- ===== INITIALIZE REDNET =====
- if peripheral.find("modem") then
- rednet.open(config.rednetSide)
- else
- rednet.close(config.rednetSide)
- end
- -- ===== GLOBAL SIGNAL VARIABLE =====
- local signalStrength = 0 -- 1–3 bars
- -- ===== UTILITIES =====
- local function centerText(y, text, color)
- local w = term.getSize()
- local x = math.floor((w - #text) / 2)
- term.setCursorPos(x, y)
- if color then term.setTextColor(color) end
- term.write(text)
- term.setTextColor(colors.white)
- end
- -- Map distance to signal bars
- local function distanceToBars(distance)
- if distance <= 5 then
- return 3
- elseif distance <= 20 then
- return 2
- else
- return 1
- end
- end
- -- ===== ASYNC SIGNAL UPDATER =====
- local function updateSignal()
- while true do
- local strength = 0
- if rednet.isOpen(config.rednetSide) then
- local peers = {}
- local ids = rednet.lookup("lemonphone_ping") or {}
- for _, id in ipairs(ids) do
- local ok = pcall(rednet.send, id, "ping", 0.1)
- if ok then
- local d = math.abs(os.getComputerID() - id) -- simple heuristic for distance
- table.insert(peers, d)
- end
- end
- if #peers > 0 then
- table.sort(peers)
- strength = distanceToBars(peers[1])
- end
- end
- signalStrength = strength
- sleep(5)
- end
- end
- -- Draw signal bars based on latest value
- local function drawSignalBars()
- local barChar = "|"
- local maxBars = 3
- for i = 1, maxBars do
- if i <= signalStrength then
- term.setTextColor(colors.lime)
- else
- term.setTextColor(colors.gray)
- end
- term.write(barChar)
- end
- term.setTextColor(colors.white)
- end
- -- ===== TOP BAR =====
- local function drawTopBar()
- local w = term.getSize()
- term.setCursorPos(1,1)
- term.setBackgroundColor(config.accentColor)
- term.clearLine()
- -- Left: signal
- term.setCursorPos(2,1)
- if rednet.isOpen(config.rednetSide) then
- drawSignalBars()
- term.write(" Net")
- else
- term.setTextColor(colors.red)
- term.write("X NoNet")
- term.setTextColor(colors.black)
- end
- -- Right: time/date
- local timeStr = textutils.formatTime(os.time(), true)
- local dateStr = os.date("%b %d")
- local clock = timeStr .. " | " .. dateStr
- term.setCursorPos(w - #clock - 1, 1)
- term.setTextColor(colors.black)
- term.write(clock)
- end
- -- ===== MENU =====
- local function drawMenu(selected)
- local apps = {
- {name="Messages", cmd="netchat"},
- {name="Worm", cmd="worm"},
- {name="Falling Blocks", cmd="falling"},
- {name="Redirection", cmd="redirection"},
- {name="Settings", cmd="settings"},
- {name="About Lemonphone", cmd="about"},
- {name="Shutdown", cmd="shutdown"}
- }
- local startY = 4
- term.setTextColor(colors.white)
- for i, app in ipairs(apps) do
- term.setCursorPos(4, startY + i - 1)
- if i == selected then
- term.setBackgroundColor(colors.gray)
- term.setTextColor(colors.black)
- else
- term.setBackgroundColor(config.bgColor)
- term.setTextColor(colors.white)
- end
- term.clearLine()
- term.setCursorPos(4, startY + i - 1)
- term.write(app.name)
- end
- term.setBackgroundColor(config.bgColor)
- return apps
- end
- -- ===== SETTINGS MENU =====
- local function openSettings()
- while true do
- term.setBackgroundColor(config.bgColor)
- term.clear()
- centerText(3, "Settings", config.accentColor)
- term.setCursorPos(2,5)
- term.write("1. Change Username")
- term.setCursorPos(2,6)
- term.write("2. Change Accent Color")
- term.setCursorPos(2,7)
- term.write("3. Back")
- local _, key = os.pullEvent("key")
- if key == keys.one then
- term.setCursorPos(2,9)
- term.clearLine()
- term.write("Enter new username: ")
- config.username = read()
- saveConfig()
- elseif key == keys.two then
- term.setCursorPos(2,9)
- term.clearLine()
- term.write("Color name (e.g. yellow): ")
- local colorName = read()
- if colors[colorName] then
- config.accentColor = colors[colorName]
- saveConfig()
- else
- term.setCursorPos(2,10)
- term.write("Invalid color.")
- sleep(1)
- end
- elseif key == keys.three then
- return
- end
- end
- end
- -- ===== ABOUT PAGE =====
- local function aboutLemonphone()
- term.setBackgroundColor(config.bgColor)
- term.clear()
- centerText(3,"About Lemonphone", config.accentColor)
- term.setCursorPos(2,5)
- term.write("Device: " .. firmware.device)
- term.setCursorPos(2,6)
- term.write("Firmware: " .. firmware.version)
- term.setCursorPos(2,8)
- term.write("Press any key to return...")
- os.pullEvent("key")
- end
- -- ===== MAIN LOOP =====
- local function mainLoop()
- local selected = 1
- local refreshRate = 1.0
- local timer = os.startTimer(refreshRate)
- while true do
- term.setBackgroundColor(config.bgColor)
- term.clear()
- drawTopBar()
- centerText(3, config.username .. "'s Lemonphone", config.accentColor)
- local apps = drawMenu(selected)
- local event, key = os.pullEvent()
- if event == "key" then
- if key == keys.up then selected = math.max(1, selected-1)
- elseif key == keys.down then selected = math.min(#apps, selected+1)
- elseif key == keys.enter then
- local chosen = apps[selected]
- if chosen.name == "Settings" then openSettings()
- elseif chosen.name == "About Lemonphone" then aboutLemonphone()
- else
- term.setBackgroundColor(config.bgColor)
- term.clear()
- term.setCursorPos(1,1)
- shell.run(chosen.cmd)
- end
- end
- elseif event == "timer" then
- timer = os.startTimer(refreshRate)
- drawTopBar()
- end
- end
- end
- -- ===== START SIGNAL UPDATER IN PARALLEL WITH MAIN LOOP =====
- parallel.waitForAny(updateSignal, mainLoop)
Add Comment
Please, Sign In to add comment