Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- -- Script for Bunker Control
- local component = require("component")
- local thread = require("thread")
- local event = require("event")
- local term = require("term")
- local serialization = require("serialization")
- local sides = require("sides")
- local colors = require("colors")
- local os = require("os")
- local computer = require("computer")
- local math = require("math")
- local modem = component.modem
- local gpu = component.gpu
- local sg = component.stargate
- local zpm = component.zpmhub
- local tunnel = component.tunnel
- local reds = component.redstone
- local data = component.data
- local count = component.countdown
- local keyboard = require("keyboard")
- local lastMessageId = nil
- local shared = { status = nil, stop = false }
- local seenStrings = {}
- local seenStrings2 = {}
- IDC = "1337"
- user = ""
- Local_Name = "Omega Site"
- Short_Name = "[Omega]"
- running = true
- tesla = false
- lights = false
- iris_status = false
- charging = false
- lockdown = true
- dialingyes = false
- gotthecode = false
- zpms_up = false
- lockDetected = false
- valid = false
- lab = "1439d23f-eecc-4cc6-86f6-adb828a402aa"
- local mcolors = {
- [0] = "White", "Orange", "Magenta", "Light Blue", "Yellow", "Lime",
- "Pink", "Gray", "Light Gray", "Cyan", "Purple", "Blue", "Brown",
- "Green", "Red", "Black"
- }
- power = false
- -- Configuration
- beacon = true
- modem.open(123)
- local screenWidth, screenHeight = gpu.getResolution()
- local function loadGlyphTable(path)
- local chunk, err = loadfile(path)
- if not chunk then
- error("Failed to load glyph file: " .. err)
- end
- local success, result = pcall(chunk)
- if not success then
- error("Error running glyph file: " .. result)
- end
- if type(result) ~= "table" then
- error("Glyph file did not return a table!")
- end
- return result
- end
- local GlyphImages = loadGlyphTable("/home/glyphsUN.lua")
- local default_messages = {
- {
- from = "Omega Site",
- shrt = "[Omega]",
- user = "Unknown entity",
- to = Local_Name,
- header = "ComE",
- message = "",
- timestamp = 7
- },
- {
- from = "Alpha Site",
- shrt = "[ALERT]",
- user = "Rosewood, Head of Security",
- to = Local_Name,
- header = "LOCKDOWN INITIATED",
- message = "",
- timestamp = 6
- },
- {
- from = "Laboratory 1",
- shrt = "[Lab 1]",
- user = "Jack, Shipment officer",
- to = Local_Name,
- header = "Missing Shipment",
- message = "",
- timestamp = 5
- },
- {
- from = "Laboratory 2",
- shrt = "[Lab 2]",
- user = "Doctor Greywall",
- to = Local_Name,
- header = "Lab results",
- message = "",
- timestamp = 4
- },
- {
- from = "Omega Site",
- shrt = "[Omega]",
- user = "Bryan Haddoc",
- to = Local_Name,
- header = "Iris installed",
- message = "",
- timestamp = 3
- },
- {
- from = "High Command",
- shrt = "[High cmd]",
- user = "Secretary General Coldwell",
- to = Local_Name,
- header = "Increased activity READ ME",
- message = "",
- timestamp = 2
- },
- {
- from = "Laboratory 2",
- shrt = "[Lab 2]",
- user = "Doctor Greywall",
- to = Local_Name,
- header = "Eggsacks",
- message = "",
- timestamp = 1
- },
- }
- function drawMessageBox(message_data)
- local screenWidth, _ = gpu.getResolution()
- -- Prepare message lines
- local lines = {
- "New message received from " .. message_data.from,
- "Subject: " .. message_data.shrt .. " " .. message_data.header,
- "Message: " .. message_data.message,
- "User: " .. message_data.user
- }
- -- Determine max line length
- local maxLength = 0
- for _, line in ipairs(lines) do
- if #line > maxLength then
- maxLength = #line
- end
- end
- -- Box styling
- local padding = 2
- local boxWidth = maxLength + padding * 2
- local boxHeight = #lines + 2 -- top + bottom border
- local startX = screenWidth - boxWidth + 1
- local startY = 1
- -- Draw top border
- gpu.set(startX, startY, "┌" .. string.rep("─", boxWidth - 2) .. "┐")
- -- Draw box sides and empty space
- for i = 1, boxHeight - 2 do
- gpu.set(startX, startY + i, "│" .. string.rep(" ", boxWidth - 2) .. "│")
- end
- -- Draw bottom border
- gpu.set(startX, startY + boxHeight - 1, "└" .. string.rep("─", boxWidth - 2) .. "┘")
- -- Write text inside the box
- for i, line in ipairs(lines) do
- gpu.set(startX + padding, startY + i, line)
- end
- end
- -- UI Drawing Function
- local function draw_ui()
- term.clear()
- print("Omega Site Control")
- print("[SPACE] Toggle Emergency Beacon [" .. (beacon and "ON" or "OFF") .. "]")
- print("[D] Toggle Perimeter Defense[" .. (tesla and "ON" or "OFF") .. "]")
- print("[L] Toggle Perimeter Lights[" .. (lights and "ON" or "OFF") .. "]")
- print("[U] Update orders from high command")
- print("[M] Messages")
- print("[C] Charge Gate")
- print("[Q] Dialing Menu")
- end
- -- UI Drawing Function messages
- local function draw_ui_messages()
- term.clear()
- print("Messages")
- print("[R] Read messages")
- print("[S] Send message")
- print("[E] Exit")
- end
- -- UI Drawing Function dialing
- local function draw_ui_dialing()
- term.clear()
- print("Dialing Menu")
- if not dialingyes then
- if lockdown then
- print("[WARNING] Lockdown in effect, iris will turn on when dialing out!")
- print("[L] Disable Lockdown")
- elseif not lockdown then
- print("[L] Enable Lockdown")
- end
- print("\n[1] Dial Epsilon Site")
- print("[2] Dial Laboratory 1")
- print("[3] Dial Laboratory 2")
- print("[4] Dial Alpha Site")
- print("[5] Dial High Command")
- print("[E] Exit")
- elseif dialingyes then
- print("Dialing: ") -- Fix later, in the middle of the screen and an abort function
- print("[E] Exit")
- end
- end
- local function is_floppy_valid()
- local privFile = io.open("/rPrivate.key", "r")
- if not privFile then
- print("[✘] Missing /rPrivate.key!")
- return false
- end
- local privSerialized = privFile:read("*a")
- privFile:close()
- local rPrivate = data.deserializeKey(serialization.unserialize(privSerialized), "ec-private")
- for address in component.list("disk_drive") do
- local drive = component.proxy(address)
- local ok, present = pcall(function() return not drive.isEmpty() end)
- if not ok then
- print("[DEBUG] Error calling isEmpty(): " .. tostring(present))
- elseif present then
- local fsAddress = drive.media()
- if fsAddress then
- local fs = component.proxy(fsAddress)
- if fs.exists("/key.dat") then
- local f = fs.open("/key.dat", "r")
- if f then
- local content = fs.read(f, math.huge)
- fs.close(f)
- if content then
- local packet = serialization.unserialize(content)
- local sPublic = data.deserializeKey(serialization.unserialize(packet.header.sPublic), "ec-public")
- local iv = packet.header.iv
- local encryptedData = packet.data
- local sharedKey = data.md5(data.ecdh(rPrivate, sPublic))
- local decrypted = data.decrypt(encryptedData, sharedKey, iv)
- if decrypted then
- local result = serialization.unserialize(decrypted)
- if result == "supersecretpassword" then
- return true
- else
- end
- else
- end
- else
- end
- else
- end
- else
- end
- else
- end
- else
- end
- end
- return false
- end
- local function sendscore(score, player)
- modem.send(lab, 123, "score", score, player)
- end
- local function place_cmd_chest()
- modem.send(lab, 123, "place")
- end
- local function check_scoreboard_cmd(scoreboard)
- if type(user) == "string" and not seenStrings[user] then
- modem.send(lab, 123, "check_scoreboard", user, scoreboard)
- seenStrings[user] = true
- end
- end
- local function decryptkey()
- term.clear()
- print("HIGH CMD SECURITY KEY NEEDED")
- print("Place the Floppy Disk Security key inside the Disk Drive")
- print("Press [E] to exit.")
- local animY = 6 -- Row to draw the blinking text
- while true do
- local visible = math.floor(os.clock() * 1.5) % 2 == 0
- local msg = "Waiting for Security Key..."
- local x = math.floor((screenWidth - #msg) / 2)
- if visible then
- gpu.set(x, animY, msg)
- else
- gpu.set(x, animY, string.rep(" ", #msg))
- end
- if is_floppy_valid() then
- print("\n[✔] Valid Security Key Detected.")
- lockdown = false
- sendscore("not_lockdown", user)
- os.sleep(1)
- return true
- end
- local ev, _, _, code = event.pull(0.1, "key_down")
- if ev == "key_down" then
- print("You pressed key ID:", code)
- if code == keyboard.keys.e then
- print("[✖] Authorization Aborted.")
- return false
- end
- end
- os.sleep(0.1)
- end
- end
- local function sendsound(sound, pos)
- modem.send(lab, 123, "sound", sound, pos)
- end
- local function power_lab()
- if power then
- labmessage = "power_on"
- modem.send(lab, 123, labmessage)
- elseif not power then
- labmessage = "power_off"
- modem.send(lab, 123, labmessage)
- end
- end
- local function generator(_, _, _, _, redvalue, mcolor)
- if mcolors[mcolor] == "Brown" and redvalue < 1 then
- power = false
- power_lab()
- if tesla then
- tesla = not tesla
- reds.setBundledOutput(sides.bottom, colors.yellow, 0)
- end
- if lights then
- lights = not lights
- reds.setBundledOutput(sides.bottom, colors.green, 255)
- end
- sg.disengageGate()
- computer.shutdown(true)
- elseif mcolors[mcolor] == "Brown" and redvalue > 0 then
- power = true
- power_lab()
- end
- end
- -- Function to send commands
- local function send_command(address, value, header)
- local data = {
- from = Local_Name,
- shrt = Short_Name,
- user = user,
- to = address,
- header = header,
- message = value,
- timestamp = os.time()
- }
- local serialized_data = serialization.serialize(data)
- tunnel.send(serialized_data)
- end
- local function handle_incomingwh()
- if not iris_status then
- iris_status = true
- if not charging then
- zpm.toggleSlots()
- zpms_up = true
- end
- sg.toggleIris()
- print("INCOMING WORMHOLE!.")
- end
- epsil = false
- end
- local function handle_idccode(_, _, _, code)
- if code == IDC then
- if not gotthecode then
- if iris_status then
- iris_status = false
- sg.toggleIris()
- zpm.toggleSlots()
- gotthecode = true
- zpms_up = false
- end
- end
- end
- end
- local function handle_closingwh()
- if iris_status then
- sg.toggleIris()
- iris_status = false
- if zpms_up then
- zpm.toggleSlots()
- zpms_up = false
- end
- end
- gotthecode = false
- end
- function drawLine(x1, y1, x2, y2, char)
- local dx = math.abs(x2 - x1)
- local dy = math.abs(y2 - y1)
- local sx = x1 < x2 and 1 or -1
- local sy = y1 < y2 and 1 or -1
- local err = dx - dy
- while true do
- gpu.set(x1, y1, char)
- if x1 == x2 and y1 == y2 then break end
- local e2 = 2 * err
- if e2 > -dy then err = err - dy; x1 = x1 + sx end
- if e2 < dx then err = err + dx; y1 = y1 + sy end
- end
- end
- -- Thread function
- local function gateStatusThread()
- while not shared.stop do
- shared.status = { sg.getGateStatus() }
- os.sleep(1) -- Adjust frequency as needed
- end
- end
- local function clocktimer()
- local screenWidth, screenHeight = gpu.getResolution()
- local centerX = math.floor(screenWidth / 2)
- local centerY = math.floor(screenHeight / 2)
- local radius = 10
- local aspectX = 2
- shared.stop = false
- local statusThread = thread.create(gateStatusThread)
- -- Clear and draw clock face
- term.clear()
- for angle = 0, 2 * math.pi, math.pi / 120 do
- local x = centerX + math.floor(math.cos(angle) * radius * aspectX)
- local y = centerY + math.floor(math.sin(angle) * radius)
- gpu.set(x, y, "●")
- end
- -- Draw center
- gpu.set(centerX, centerY, "•")
- -- Prepare digital clock line area
- local digitalY = centerY + radius + 2
- gpu.fill(1, digitalY, screenWidth, 1, " ")
- local startTime = computer.uptime()
- local duration = 60
- count.setCountdown(1200)
- -- Animate hand and digital countdown
- while true do
- local gateStatus = shared.status and shared.status[1]
- local elapsed = computer.uptime() - startTime
- local timeLeft = duration - elapsed
- if timeLeft <= 0 then break end
- if gateStatus ~= "unstable" and gateStatus ~= "open" then count.setCountdown(0) break end
- local angle = -(2 * math.pi / duration) * timeLeft - math.pi / 2
- local endX = centerX + math.floor(math.cos(angle) * (radius - 1) * aspectX)
- local endY = centerY + math.floor(math.sin(angle) * (radius - 1))
- -- Draw hand
- drawLine(centerX, centerY, endX, endY, "*")
- -- Format and print digital timer
- local ms = math.floor((timeLeft % 1) * 100)
- local sec = math.floor(timeLeft) % 60
- local timeStr = string.format("%02d:%02d", sec, ms)
- local textX = math.floor((screenWidth - #timeStr) / 2)
- gpu.set(textX, digitalY, string.rep(" ", #timeStr))
- gpu.set(textX, digitalY, timeStr)
- os.sleep(0.05)
- -- Clear hand
- drawLine(centerX, centerY, endX, endY, " ")
- end
- -- Shutdown gate
- sg.disengageGate()
- epsil = false
- -- Clean up the thread
- shared.stop = true
- statusThread:kill()
- valid = false
- end
- local function dialout()
- if lockdown then
- if sg.getIrisState() == "OPENED" or "OPENING" then
- iris_status = true
- if not zpms_up then
- zpm.toggleSlots()
- zpms_up = true
- end
- sg.toggleIris()
- end
- end
- if not lockdown then
- if epsil then
- sendscore("dialed_puzzle", user)
- end
- end
- valid = true
- sg.engageGate()
- clocktimer()
- os.sleep(1.5)
- end
- local function checkiris()
- local irisstate = sg.getIrisState()
- local gateStatus, openState, _, _ = sg.getGateStatus()
- if (irisstate == "CLOSED" or irisstate == "CLOSING") and irisstate ~= "OPEN" and irisstate ~= "OPENING" then
- if gateStatus == "open" then
- iris_status = true
- elseif gateStatus == "idle" then
- sg.toggleIris()
- zpm.toggleSlots()
- end
- elseif (irisstate == "OPENED" or irisstate == "OPENING") and irisstate ~= "CLOSED" and irisstate ~= "CLOSING" then
- end
- end
- function errormessage(ER)
- local screenWidth, screenHeight = gpu.getResolution()
- -- Split multiline message into table of lines
- local lines = {}
- for line in ER:gmatch("[^\n]+") do
- table.insert(lines, line)
- end
- -- Box styling
- local padding = 2
- local maxLength = 0
- for _, line in ipairs(lines) do
- if #line > maxLength then maxLength = #line end
- end
- local boxWidth = maxLength + padding * 2
- local boxHeight = #lines + padding * 2
- -- Centered position (same logic as drawChargingProgress)
- local boxX = math.floor((screenWidth - boxWidth) / 2)
- local boxY = math.floor((screenHeight - boxHeight) / 2)
- -- Draw top border
- gpu.set(boxX, boxY, "┌" .. string.rep("─", boxWidth - 2) .. "┐")
- -- Draw [ERROR] centered at the top
- local errorLabel = "[ERROR]"
- local errorX = boxX + math.floor((boxWidth - #errorLabel) / 2)
- gpu.set(errorX, boxY + 1, errorLabel)
- -- Draw sides and content
- for i = 1, boxHeight - 2 do
- local lineY = boxY + i + 1
- local lineContent = lines[i - 1] or ""
- local line = "│" .. string.rep(" ", padding) .. lineContent .. string.rep(" ", boxWidth - #lineContent - padding * 2) .. "│"
- gpu.set(boxX, lineY, line)
- end
- -- Draw bottom border
- gpu.set(boxX, boxY + boxHeight - 1, "└" .. string.rep("─", boxWidth - 2) .. "┘")
- -- Optional: Pause before clearing
- os.sleep(5)
- -- Clear box area (restore background)
- for i = 0, boxHeight - 1 do
- gpu.set(boxX, boxY + i, string.rep(" ", boxWidth))
- end
- end
- local function handle_closefail(_, _, reason)
- print("SG Failed: ".. reason)
- end
- local function handle_failure(_, _, reason)
- print("SG Failed: ".. reason)
- end
- local function handle_unidialer()
- if not valid then
- if sg.getIrisState() == "OPENED" or "OPENING" then
- iris_status = true
- if not zpms_up then
- zpm.toggleSlots()
- zpms_up = true
- end
- sg.toggleIris()
- end
- ::unistop::
- local status, failur, description = sg.disengageGate()
- if not status then
- goto unistop
- else
- ermessage = "Unauthorized dialing with Universe Dialer.\nStopping dialing..."
- errormessage(ermessage)
- end
- end
- end
- -- Internal draw counter
- local glyphSpacing = 14 -- horizontal space per glyph block
- local glyphStartX = 14 -- starting X position
- local glyphStartY = 10 -- starting Y position
- local function displayglyph(name)
- local glyphImage = GlyphImages[name]
- if not glyphImage then
- print("[!] Unknown glyph from GlyphImages: " .. tostring(glyphName))
- print("[!] Glyph we are trying to print: " .. name)
- return
- end
- -- Calculate current glyph X position based on count
- local xPos = glyphStartX + (glyphDrawCount * glyphSpacing)
- local yPos = glyphStartY
- -- Draw each line of the glyph vertically
- local lineOffset = 0
- for line in glyphImage:gmatch("[^\r\n]+") do
- gpu.set(xPos, yPos + lineOffset, line)
- lineOffset = lineOffset + 1
- end
- -- Move the cursor for the next glyph
- glyphDrawCount = glyphDrawCount + 1
- end
- -- Function to engage a symbol and wait for confirmation
- local function engageSymbolAndWait(glyph, expectedSymbolCount)
- local success = false
- lockDetected = false
- -- Define the event handler function
- local function onGlyphEngaged(_, _, _, symbolCount, lock, glyphName)
- if glyphName == glyph and symbolCount == expectedSymbolCount then
- displayglyph(glyphName)
- success = true
- end
- -- If this is the last glyph, confirm `lock` is true
- if lock then
- lockDetected = true
- end
- end
- -- Call `sg.engageSymbol` and wait for confirmation
- local result = sg.engageSymbol(glyph)
- if result ~= "stargate_spin" then
- ermessage = "Failed to initiate glyph engagement: " .. glyph .. "\nError Details: " .. (result and result.stargate_failure or "No failure info")
- errormessage(ermessage)
- return false, false
- end
- event.listen("stargate_spin_chevron_engaged", onGlyphEngaged)
- -- Wait for the event to confirm success
- local timeout = 20 -- Timeout in seconds
- local elapsed = 0
- while not success and elapsed < timeout do
- os.sleep(0.1)
- elapsed = elapsed + 0.1
- end
- -- Cleanup the event listener
- event.ignore("stargate_spin_chevron_engaged", onGlyphEngaged)
- if not success then
- ermessage = "Timeout waiting for glyph engagement: " .. glyph
- errormessage(ermessage)
- return false, false
- elseif success then
- return true, lockDetected
- end
- end
- local function formatNumberWithDots(n)
- local s = tostring(n)
- local formatted = s:reverse():gsub("(%d%d%d)", "%1."):reverse()
- if formatted:sub(1, 1) == "." then
- formatted = formatted:sub(2)
- end
- return formatted
- end
- local function dialgate(address)
- term.clear()
- AddressBuffer = address
- glyphDrawCount = 0
- local requirement = sg.getEnergyRequiredToDial(table.unpack(AddressBuffer))
- local stored_energy = sg.getEnergyStored()
- local total_energy_required = requirement.open + (requirement.keepAlive * 1200)
- if type(requirement) == "table" and requirement.canOpen == false then
- ermessage = "NOT ENOUGH POWER TO OPEN: ".. formatNumberWithDots(total_energy_required).." RF NEEDED"
- errormessage(ermessage)
- elseif stored_energy > total_energy_required then
- sendsound("jsg:universe_dialer_start_dial", "@a[x=636,y=71,z=498,dx=3,dy=2,dz=6]")
- for i, glyph in ipairs(address) do
- local gateStatus = sg.getGateStatus()
- local success, lock = engageSymbolAndWait(glyph, i)
- if not success then
- return
- end
- if lock then
- dialout()
- end
- os.sleep(1)
- end
- elseif stored_energy < total_energy_required then
- ermessage = "NOT ENOUGH POWER TO OPEN: ".. formatNumberWithDots(total_energy_required).." RF NEEDED"
- errormessage(ermessage)
- end
- end
- -- Function to read messages
- local function read_message()
- local path = "/messages.dat"
- local file = io.open(path, "r")
- if not file then
- print("No messages found.")
- os.sleep(2)
- return
- end
- local content = file:read("*a")
- file:close()
- local messages = serialization.unserialize(content)
- if not messages or #messages == 0 then
- print("Inbox empty.")
- os.sleep(2)
- return
- end
- -- Sort by timestamp descending (newest first)
- table.sort(messages, function(a, b)
- return tonumber(a.timestamp) > tonumber(b.timestamp)
- end)
- while true do
- term.clear()
- print("Inbox")
- print("︱NEWEST︱")
- for i, msg in ipairs(messages) do
- print(string.format("[%d] ︱ %s %s ︱", i, msg.shrt or "", msg.header or ""))
- end
- print("︱OLDEST︱")
- print("")
- print("[E] Exit")
- local answer = io.read()
- if answer == "e" or answer == "E" then
- break
- else
- local index = tonumber(answer)
- if index and messages[index] then
- local msg = messages[index]
- term.clear()
- print(string.format("︱ %s %s ︱", msg.shrt or "", msg.header or ""))
- print("")
- print(msg.message or "")
- print("")
- print(msg.user or "Unknown sender")
- print("")
- print("[E] Exit")
- local _ = io.read()
- end
- end
- end
- end
- -- Function to send messages
- local function send_message()
- ::continue1::
- term.clear()
- print("Pick receiver")
- print("[1] Epsilon Site")
- print("[2] Laboratory 1")
- print("[3] Laboratory 2")
- print("[4] High Command")
- print("[E] Exit")
- local answer = io.read()
- if answer == "1" then
- send_to = "Epsilon Site"
- print("Epsilon Site Confirmed, please type the subject of your message and press enter")
- print("")
- local header = io.read()
- term.clear()
- print("Subject: " .. header)
- print("")
- print("Please type your message")
- print("")
- local message = io.read()
- term.clear()
- print("From: " .. Local_Name)
- print("Subject: " .. header)
- print("Message: " .. message)
- print("")
- print("Do you want to send this message to ".. send_to .."?")
- io.write("Y/n: ")
- local answer = io.read()
- if answer == "Y" or answer == "y" then
- send_command(send_to, message, header)
- end
- term.clear()
- goto continue1
- elseif answer == "2" then
- send_to = "Laboratory 1"
- term.clear()
- print("Laboratory 1 Confirmed, please type the subject of your message and press enter")
- print("")
- local header = io.read()
- term.clear()
- print("Subject: " .. header)
- print("")
- print("Please type your message")
- print("")
- local message = io.read()
- term.clear()
- print("From: " .. Local_Name)
- print("Subject: " .. header)
- print("Message: " .. message)
- print("")
- print("Do you want to send this message to ".. send_to .."?")
- io.write("Y/n: ")
- local answer = io.read()
- if answer == "Y" or answer == "y" then
- send_command(send_to, message, header)
- end
- term.clear()
- goto continue1
- elseif answer == "3" then
- send_to = "Laboratory 2"
- term.clear()
- print("Laboratory 2 Confirmed, please type the subject of your message and press enter")
- print("")
- local header = io.read()
- term.clear()
- print("Subject: " .. header)
- print("")
- print("Please type your message")
- print("")
- local message = io.read()
- term.clear()
- print("From: " .. Local_Name)
- print("Subject: " .. header)
- print("Message: " .. message)
- print("")
- print("Do you want to send this message to ".. send_to .."?")
- io.write("Y/n: ")
- local answer = io.read()
- if answer == "Y" or answer == "y" then
- send_command(send_to, message, header)
- end
- term.clear()
- goto continue1
- elseif answer == "4" then
- send_to = "High Command"
- term.clear()
- print("High Command Confirmed, please type the subject of your message and press enter.")
- print("")
- local header = io.read()
- term.clear()
- print("Subject: " .. header)
- print("")
- print("Please type your message")
- print("")
- local message = io.read()
- term.clear()
- print("From: " .. Local_Name)
- print("Subject: " .. header)
- print("Message: " .. message)
- print("")
- print("Do you want to send this message to ".. send_to .."?")
- io.write("Y/n: ")
- local answer = io.read()
- if answer == "Y" or answer == "y" then
- send_command(send_to, message, header)
- end
- term.clear()
- goto continue1
- elseif answer == "e" or answer == "E" then
- else
- goto continue1
- end
- end
- local function init_message_file()
- local path = "/messages.dat"
- local f = io.open(path, "r")
- if not f then
- -- Save default messages to file
- local file = io.open(path, "w")
- if file then
- file:write(serialization.serialize(default_messages))
- file:close()
- end
- else
- f:close()
- end
- end
- local function save_message(message_data)
- local filepath = "/messages.dat"
- local messages = {}
- -- Load existing messages if file exists
- local file = io.open(filepath, "r")
- if file then
- local content = file:read("*a")
- file:close()
- if content and #content > 0 then
- messages = serialization.unserialize(content) or {}
- end
- end
- -- Add new message
- table.insert(messages, message_data)
- -- Sort by timestamp
- table.sort(messages, function(a, b)
- return a.timestamp < b.timestamp
- end)
- -- Save updated messages back to file
- file = io.open(filepath, "w")
- if file then
- file:write(serialization.serialize(messages))
- file:close()
- end
- end
- local function getpowerstatus()
- if reds.getBundledInput(sides.bottom, colors.brown) > 0 then
- power = true
- return "power_on"
- else
- power = false
- return "power_off"
- end
- end
- local function handle_modem_message(_, _, from, port, _, message, data, playern, scoreboar)
- if port == 123 or port == 0 then
- if message == "error" then
- print("")
- print("[ERROR] " .. data)
- elseif message == "sent_message" then
- print("")
- print("Sent message to " .. data)
- elseif message == "new_message" then
- local message_data = serialization.unserialize(data)
- if message_data.timestamp ~= lastMessageId then
- lastMessageId = message_data.timestamp
- drawMessageBox(message_data)
- save_message(message_data)
- end
- elseif message == "code" then
- print("[Code] " .. data)
- if data == IDC then
- if iris_status then
- iris_status = false
- sg.toggleIris()
- zpm.toggleSlots()
- end
- end
- elseif message == "lockdown" then
- lockdown = true
- elseif message == "getpowerstatus" then
- local status = getpowerstatus()
- modem.send(lab, 123, "powerstatus", status)
- elseif message == "scoreboard_checked" then
- if type(playern) == "string" and not seenStrings2[playern] then
- seenStrings2[playern] = true
- if data < 1 then
- if scoreboar == "power" then
- place_cmd_chest()
- end
- end
- end
- end
- end
- end
- function drawChargingProgress()
- local screenWidth, screenHeight = gpu.getResolution()
- local label = "Charging Gate..."
- local labelX = math.floor((screenWidth - #label) / 2) + 1
- local labelY = math.floor(screenHeight / 2)
- -- Progress bar settings
- local barWidth = 30
- local barX = math.floor((screenWidth - barWidth) / 2) + 1
- local barY = labelY + 2
- local totalTime = 34 -- seconds
- local updateRate = 0.1 -- how often to update in seconds
- local steps = math.floor(totalTime / updateRate)
- -- Clear label and bar area
- for i = 0, 3 do
- gpu.set(1, labelY + i, string.rep(" ", screenWidth))
- end
- -- Draw label
- gpu.set(labelX, labelY, label)
- -- Progress bar loop
- for i = 0, steps do
- if iris_status then
- draw_ui()
- term.setCursor(1, barY + 2)
- print("[!] Charging aborted: Iris status triggered.")
- return end
- local filled = math.floor((i / steps) * barWidth)
- local empty = barWidth - filled
- gpu.set(barX, barY, "[" .. string.rep("█", filled) .. string.rep(" ", empty) .. "]")
- os.sleep(updateRate)
- end
- end
- local function chargegate()
- charging = true
- zpms_up = true
- zpm.toggleSlots()
- drawChargingProgress()
- if not iris_status then
- zpm.toggleSlots()
- zpms_up = false
- end
- charging = false
- end
- -- Keyboard Input Listener
- local function key_listener(_, _, char, code, playerName)
- local key = string.char(char)
- user = playerName
- check_scoreboard_cmd("power")
- event.ignore("key_down", key_listener)
- if key == "u" then
- term.clear()
- print("Connecting to central network...")
- os.sleep(3)
- print("[ERROR] No connection")
- os.sleep(0.5)
- print("[ERROR] Diagnosing...")
- os.sleep(3)
- print("[✔] Receiver [ONLINE]")
- print("[✔] Transmitter [ONLINE]")
- print("[ERROR] High Command blocked or not responding")
- print("[⚠] Can not receive orders!")
- print("")
- print("Please follow standard Emergency Procedures")
- os.sleep(8)
- draw_ui()
- elseif key == "d" then
- if power then
- if tesla then
- tesla = not tesla
- reds.setBundledOutput(sides.bottom, colors.yellow, 0)
- draw_ui()
- print("Turned Off Perimeter Defense")
- elseif not tesla then
- tesla = not tesla
- reds.setBundledOutput(sides.bottom, colors.yellow, 255)
- draw_ui()
- print("Turned On Perimeter Defense")
- end
- elseif not power then
- print("[ERROR] ZPM Offline, Cannot turn on Perimeter Defense")
- end
- elseif key == "l" then
- if power then
- if lights then
- lights = not lights
- reds.setBundledOutput(sides.bottom, colors.green, 255)
- draw_ui()
- print("Turned Off Perimeter Lights")
- elseif not lights then
- lights = not lights
- reds.setBundledOutput(sides.bottom, colors.green, 0)
- draw_ui()
- print("Turned On Perimeter Lights")
- end
- elseif not power then
- print("[ERROR] ZPM Offline, Cannot turn on Perimeter Lights")
- end
- elseif key == "q" then
- if power then
- ::continue3::
- draw_ui_dialing()
- local answer = io.read()
- if answer == "l" or answer == "L" then
- if lockdown then
- decryptkey()
- elseif not lockdown then
- lockdown = true
- end
- goto continue3
- elseif answer == "1" then
- DialEpsilon = {"Glyph 24","Glyph 13","Glyph 30","Glyph 11","Glyph 6","Glyph 12","Glyph 2","Glyph 15","Glyph 17"}
- epsil = true
- dialgate(DialEpsilon)
- goto continue3
- elseif answer == "2" then
- send_message()
- goto continue3
- elseif answer == "3" then
- send_message()
- goto continue3
- elseif answer == "4" then
- send_message()
- goto continue3
- elseif answer == "5" then
- send_message()
- goto continue3
- elseif answer == "e" or answer == "E" then
- draw_ui()
- else
- goto continue3
- end
- elseif not power then
- print("[ERROR] ZPM Offline, Cannot dial")
- end
- elseif code == 57 then
- if beacon then
- print("Confirm Beacon Shutdown")
- io.write("Y/n: ")
- local answer = io.read()
- if answer == "y" or answer == "Y" then
- beacon = not beacon
- print("Confirmed")
- os.sleep(3)
- draw_ui()
- else
- print("Aborted!")
- os.sleep(3)
- draw_ui()
- end
- elseif not beacon then
- beacon = not beacon
- draw_ui()
- print("Emergency Beacon Online!")
- end
- elseif key == "m" then
- ::continue::
- draw_ui_messages()
- local answer = io.read()
- if answer == "r" or answer == "R" then
- read_message()
- goto continue
- elseif answer == "s" or answer == "S" then
- send_message()
- goto continue
- elseif answer == "e" or answer == "E" then
- draw_ui()
- else
- goto continue
- end
- elseif key == "c" then
- if power then
- if iris_status then
- print("[!] Cannot Charge when Iris is up!.")
- elseif not iris_status then
- chargegate()
- draw_ui()
- end
- elseif not power then
- print("[ERROR] ZPM Offline, Cannot charge")
- end
- end
- event.listen("key_down", key_listener)
- end
- if reds.getBundledOutput(sides.bottom, colors.yellow) > 0 then
- tesla = true
- end
- if reds.getBundledOutput(sides.bottom, colors.green) < 1 then
- lights = true
- end
- init_message_file()
- local status = getpowerstatus()
- sg.engageGate()
- checkiris()
- draw_ui()
- messages = event.listen("modem_message", handle_modem_message)
- incomingwh = event.listen("stargate_incoming_wormhole", handle_incomingwh)
- gotcode = event.listen("received_code", handle_idccode)
- closingwh = event.listen("stargate_wormhole_closed_fully", handle_closingwh)
- unidialer = event.listen("stargate_open", handle_unidialer)
- failure = event.listen("stargate_failed", handle_failure)
- closefail = event.listen("stargate_close", handle_closefail)
- powergenerator = event.listen("redstone_changed", generator)
- event.listen("key_down", key_listener)
- while running do
- os.sleep(0.5)
- end
- os.sleep(1)
- os.exit()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement