Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- --[[ LanteaCraft ]]--
- --[[ and SGCraft ]]--
- --[[ c c D H D ]]--
- --[[ by Dog ]]--
- --[[ aka HydrantHunter ]]--
- --[[ with help from ]]--
- --[[ Bomb Bloke ]]--
- --[[ pastebin jriyySTL ]]--
- local ccDHDVer = "1.5.02"
- --[[
- Tested with/requires:
- - Minecraft 1.7.10
- - LanteaCraft-1.7.10-70 || SGCraft1.95-mc1.7.10
- - ComputerCraft 1.73, 1.74, 1.75
- - An advanced computer with a wireless modem
- - 1 or more 3x and/or 1x advanced monitor arrays [optional]
- - gateLiaison running on a computer (standard or advanced, with a wireless modem) or a wireless turtle (standard or advanced)
- - 1 or more Biometric Locks (Gopher's Peripherals 2.2) [optional]
- ]]--
- --# Default Settings
- local settingsData = "/data/DHDconfig"
- local gateData = "/data/DHDgates"
- local gateHistory = "/data/DHDhistory"
- local lastGate = "/data/DHDlastCall"
- local dhdSettings = {
- highlight = true,
- password = "password",
- bio = { lock = false, func = "none", auth = 4, fAuth = 2, },
- gate = 65536,
- pSync = false,
- ecIris = false, --# open iris upon disconnect
- startIris = false, --# now used for incoming call auto-iris-close
- logs = true,
- }
- local updateStatus, secKernel, drawCLI, drawHeader, drawSettingsUI, drawWaitingIrisState, drawRatingList, assignRating, assignColor, pSyncClient, selectedGate, bCurX, bCurY, curColor, bColor, word, secWord
- local oldOsPullEvent --# reserved for bioLogin and lockdown mode, to temporarily suspend CTRL-T/terminate
- --# Peripherals
- local termX, termY = term.getSize() --# standard 51x19 / tab = 51x18
- local hardware = { modemSide = "none", bio = 0, listMon = 0, marquee = 0 } --# Modem, Biolock(s), and Monitor(s)
- local listMon, listMonSides = { }, { } --# List monitor
- local marquee, marqueeSides = { }, { } --# Marquee Monitor
- local thisGate --# this gate's address
- --# Status Info
- local gateStatus, secureStatus, displayState, runState, currentState, dialAddress = "QRY", "QRY", "list", "init", "init", "none"
- local menuState, kernelState, irisState, lcGate, fistAuth = false, false, false, false, false
- local configChange, gateChange, waitingForIris, gettingInput, redraw = false, false, false, false, false
- local currentEdit, incomingAddress, fuelGauge
- local chevronNumber, SG_MAXFUEL = 0, 203842
- --# Address Book
- local addressBook = { { name = "NEW GATE", addr = "ADDRESS", rating = "U", iris = "none", note = "short note", loc = { x = 99999, y = 99999, z = 99999, dim = "Overworld", }, }, }
- local gatePages, gatePage, listPages, listPage = 1, 1, 1, 1
- local pNum = tostring(gatePage) .. " of " .. tostring(gatePages)
- --# Call History
- local logPages, logPage = 1, 1
- local callHistory = { }
- local lastCall
- --# Color Definitions
- local white = colors.white
- local silver = colors.lightGray
- local gray = colors.gray
- local black = colors.black
- local brown = colors.brown
- local yellow = colors.yellow
- local orange = colors.orange
- local red = colors.red
- local magenta = colors.magenta
- local purple = colors.purple
- local blue = colors.blue
- local sky = colors.lightBlue
- local cyan = colors.cyan
- local lime = colors.lime
- local green = colors.green
- local function clearMonitors()
- if hardware.listMon > 0 then
- for i = 1, hardware.listMon do
- listMon[i].setBackgroundColor(black)
- listMon[i].clear()
- end
- end
- if hardware.marquee > 0 then
- for i = 1, hardware.marquee do
- marquee[i].setBackgroundColor(black)
- marquee[i].clear()
- end
- end
- end
- local function clearScreen(bgColor)
- term.setBackgroundColor(bgColor or black)
- term.clear()
- end
- local function clearLowerScreen(bgColor)
- term.setBackgroundColor(bgColor or black)
- local line = string.rep(" ", termX)
- for i = 5, termY do
- term.setCursorPos(1, i)
- term.write(line)
- end
- end
- local function shutDown()
- clearMonitors()
- if hardware.modemSide ~= "none" then
- if dhdSettings.pSync then
- rednet.unhost("pSync")
- end
- rednet.close(hardware.modemSide)
- end
- end
- local function recordSessionData() --# Human readable log files (last gate & history)
- local logAddress = incomingAddress or dialAddress --# set logAddress
- logAddress = #logAddress == 7 and logAddress .. thisGate:sub(8, 9) or logAddress --# if logAddress is 7 characters (it is in the same dimension) add thisGate's dimension to the end for logging
- local callDirection = incomingAddress and "Inbound" or "Outbound" --# set callDirection
- local callTime = textutils.formatTime(os.time(), false) --# format the time
- if #callTime == 7 then callTime = " " .. callTime end --# move single digit hour times to the right one space
- local dataLine = tostring(os.day()) .. " @ " .. callTime .. " <" .. callDirection .. "> " .. logAddress --# build the data line to be recorded
- local previousCall = fs.open(lastGate, "w") --# record last call
- previousCall.writeLine(dataLine)
- previousCall.close()
- if dhdSettings.logs then --# record call in main log file if logs is turned on
- local callArchive = fs.open(gateHistory, fs.exists(gateHistory) and "a" or "w")
- callArchive.writeLine(dataLine)
- callArchive.close()
- end
- end
- local function paginateGates()
- gatePages = math.ceil(#addressBook / 24)
- listPages = math.ceil(#addressBook / 8)
- end
- local function mergeAddressBooks(newGates)
- local matchFound = false --# use matchFound to indicate if a matching gate was found or not
- for i = 1, #newGates do --# start cycling through the 'new' list of gates
- for j = 1, #addressBook do --# search the address book for a matching address
- if newGates[i].addr == addressBook[j].addr then --# if the gate is already in the address book...
- matchFound = true --# ...set matchFound to true and...
- break --# stop the address book search loop and move on to the next gate in the 'new' list
- end
- end
- if not matchFound then --# if a match wasn't found...
- addressBook[#addressBook + 1] = { } --# initialize a new address book entry
- for k, v in pairs(newGates[i]) do --# loop through the gate entries...
- addressBook[#addressBook][k] = v --# ...and add them to the new address book entry
- end
- if not addressBook[#addressBook].iris then
- addressBook[#addressBook].iris = "none"
- end
- gateChange = true --# indicate that address book data has changed
- else
- matchFound = false --# if a match was found, reset the variable for the next iteration of the loop
- end
- end
- paginateGates() --# repaginate gates
- end
- local function pSync(pushpull) --# Sync addressBook with an advanced pocket computer running ccDialer
- if pushpull == "pPull" and secureStatus == "allclear" then
- sleep(0.1)
- rednet.send(pSyncClient, addressBook)
- elseif pushpull == "pPush" and secureStatus == "allclear" then
- local id, message = rednet.receive()
- if type(message) == "table" and message.program == "pSync" and id == pSyncClient then
- mergeAddressBooks(message.command)
- redraw = true
- drawCLI(true)
- end
- elseif pushpull == "QRY" then
- sleep(0.1)
- if secureStatus == "allclear" then
- rednet.send(pSyncClient, thisGate)
- else
- rednet.send(pSyncClient, "lockdown")
- end
- end
- end
- local function redrawInput() --# if we're getting input from the user, account for CLI redraws repositioning the cursor
- term.setTextColor(curColor) --# set the proper text color
- term.setBackgroundColor(bColor) --# set the proper background color
- term.setCursorPos(bCurX, bCurY) --# reposition the cursor
- term.write(secureStatus == "allclear" and word or secWord) --# re-write input to screen
- end
- local function netSend(thisCommand)
- if not rednet.isOpen(hardware.modemSide) then
- rednet.open(hardware.modemSide)
- end
- local dataPack = { program = "ccDHD", thisGate = thisGate, command = thisCommand }
- rednet.send(dhdSettings.gate, dataPack)
- end
- local function netReceive()
- while true do
- local id, message = rednet.receive()
- if type(message) == "table" then
- if message.program == "ccDHD" and id == dhdSettings.gate then
- if menuState then redraw = true end --# this is just to trigger the propper redraw later
- updateStatus(message)
- if message.gateStatus == "Disconnecting" and dhdSettings.ecIris and irisState and secureStatus == "allclear" then
- if runState == "Dial" or runState == "goPage" or runState == "importExport" or runState == "exodus" then
- drawWaitingIrisState(true)
- if gettingInput then redrawInput() end
- end
- netSend("iOPEN")
- waitingForIris = true
- end
- elseif message.program == "pSync" and dhdSettings.pSync then
- if message.command then
- pSyncClient = id
- if message.command == "pPull" or message.command == "pPush" then
- if thisGate == message.gate then
- pSync(message.command)
- if runState == "Dial" then return end --# cycle dhdKernel so we have the correct input routine (when forced out of a GateEdit during a pPush)
- end
- elseif message.command == "QRY" then
- pSync(message.command)
- else
- if #tostring(message.command) == 7 or #tostring(message.command) == 9 then
- if message.command ~= thisGate then
- if message.command ~= "endCall" and gateStatus == "Disconnected" then
- dialAddress = message.command
- netSend(message.command)
- elseif message.command == "endCall" then
- netSend(message.command)
- end
- end
- end
- end
- elseif message.password then
- local dataPack = { program = "pSync", password = message.password }
- rednet.send(dhdSettings.gate, dataPack)
- end
- end
- else
- if id == dhdSettings.gate and message == dhdSettings.password then
- if runState == "Dial" or runState == "goPage" or runState == "importExport" or runState == "exodus" then
- drawWaitingIrisState(true)
- if gettingInput then redrawInput() end
- end
- netSend("iOPEN")
- waitingForIris = true
- end
- end
- end
- end
- do
- local validStates = {
- Dial = true,
- Trim = true,
- DHDsettings = true,
- newPassword = true,
- GateEdit = true,
- goPage = true,
- goTrimPage = true,
- importExport = true,
- logs = true,
- clearLogs = true,
- goLogPage = true,
- exodus = true,
- }
- updateStatus = function(newInfo)
- local monUpdate = false
- if waitingForIris and irisState ~= newInfo.irisState then
- waitingForIris = false
- end
- irisState = newInfo.irisState
- local recordInfo = false
- if currentState == "DHD" then
- local iLength = #tostring(incomingAddress)
- if newInfo.gateStatus == "Connected" and gateStatus ~= newInfo.gateStatus and (dialAddress ~= "none" or iLength == 7 or iLength == 9) then
- recordInfo = true
- end
- else
- lcGate = newInfo.lcGate
- thisGate = newInfo.thisGate
- currentState = "DHD" --# one of the last steps of initialization - we don't record connections that are already established upon startup
- end
- secureStatus = newInfo.secureStatus
- fuelGauge = newInfo.fuelGauge
- if gateStatus ~= newInfo.gateStatus then monUpdate = true end
- if dialAddress ~= newInfo.dialAddress then monUpdate = true end
- if incomingAddress ~= newInfo.incomingAddress then monUpdate = true end
- if chevronNumber ~= newInfo.chevronNumber then monUpdate = true end
- gateStatus = newInfo.gateStatus
- dialAddress = newInfo.dialAddress
- incomingAddress = newInfo.incomingAddress
- chevronNumber = newInfo.chevronNumber
- --# Added for Yanniclord
- local rsSide = "none"
- if incomingAddress and gateStatus == "Dialing" and rsSide ~= "none" then
- rs.setOutput(rsSide, true)
- elseif incomingAddress and gateStatus == "Connected" and rsSide ~= "none" then
- rs.setOutput(rsSide, false)
- end
- if gateStatus == "Disconnected" or gateStatus == "Disconnecting" then
- if rsSide ~= "none" then rs.setOutput(rsSide, false) end
- end
- --# END
- local irisClose = false
- local irisManage = false
- --if incomingAddress and dhdSettings.startIris then irisClose = true end
- if lcGate then
- if incomingAddress and recordInfo and secureStatus == "allclear" then
- if dhdSettings.startIris then irisClose = true end
- irisManage = true
- end
- else
- if incomingAddress and (#incomingAddress == 7 or #incomingAddress == 9) and secureStatus == "allclear" and gateStatus == "Dialing" then
- if dhdSettings.startIris then irisClose = true end
- irisManage = true
- end
- end
- if irisManage then
- for i = 1, #addressBook do
- if addressBook[i].addr == incomingAddress or (addressBook[i].addr:sub(1, 7) == incomingAddress and addressBook[i].addr:sub(8, 9) == thisGate:sub(8, 9)) then
- if addressBook[i].iris == "open" then
- if irisState then
- if runState == "Dial" or runState == "goPage" or runState == "importExport" or runState == "exodus" then
- drawWaitingIrisState(true)
- if gettingInput then redrawInput() end
- end
- waitingForIris = true
- netSend("iOPEN")
- end
- irisClose = false
- elseif addressBook[i].iris == "close" then
- if not irisState then
- if runState == "Dial" or runState == "goPage" or runState == "importExport" or runState == "exodus" then
- drawWaitingIrisState()
- if gettingInput then redrawInput() end
- end
- waitingForIris = true
- netSend("iCLOSE")
- end
- irisClose = false
- end
- break
- end
- end
- end
- if incomingAddress and dhdSettings.startIris and irisClose and gateStatus == "Dialing" and not irisState then
- if runState == "Dial" or runState == "goPage" or runState == "importExport" or runState == "exodus" then
- drawWaitingIrisState()
- if gettingInput then redrawInput() end
- end
- waitingForIris = true
- netSend("iCLOSE")
- end
- if recordInfo then recordSessionData() end
- if validStates[runState] then
- drawCLI(monUpdate)
- end
- end
- end
- local function saveData(fileName, fileType)
- menuState = false
- if fs.exists("/disk") and fileName == ("/disk/data/DHDgates") then
- if not fs.exists("/disk/data") then fs.makeDir("/disk/data") end
- end
- local dhdData = fs.open(tostring(fileName), "w")
- if fileType == "cfg" then
- dhdData.write(textutils.serialize(dhdSettings))
- configChange = false
- elseif fileType == "gate" then
- dhdData.write(textutils.serialize(addressBook))
- if fileName == gateData then gateChange = false end
- end
- dhdData.close()
- end
- local function ingestData(fileName, fileType)
- if fileName == "logs" then --# Logs
- if fs.exists(gateHistory) then
- for log_entry in io.lines(gateHistory) do
- table.insert(callHistory, 1, log_entry)
- end
- logPage, logPages = 1, math.max(1, math.ceil(#callHistory / 11)) --# paginate call logs
- end
- if fs.exists(lastGate) then
- local dhdLast = fs.open(lastGate, "r")
- lastCall = dhdLast.readLine()
- dhdLast.close()
- end
- else
- if not fs.exists(fileName) then return end
- local dhdData = fs.open(fileName, "r")
- local dhdInfo = dhdData.readAll()
- dhdData.close()
- if fileType == "cfg" then --# Config
- dhdSettings = textutils.unserialize(dhdInfo)
- elseif fileType == "gate" then --# Address book (main or backup)
- for i = #addressBook, 1, -1 do
- addressBook[i] = nil
- end
- addressBook = textutils.unserialize(dhdInfo)
- gateChange = true --# a change has occured, even though gateChange *might* already be TRUE...
- local fixNames = false --# ...so we use fixNames to track if any *new* changes have occured
- for i = 1, #addressBook do
- if not addressBook[i].name then --# we've found an 'old' address book (before names were added)
- addressBook[i].name = addressBook[i].addr --# add name to entry
- fixNames = true --# note that changes have occured
- end
- if not addressBook[i].iris then --# we've found an 'old' address book (before iris control was added)
- addressBook[i].iris = "none" --# add default iris control setting to entry
- fixNames = true --# note that changes have occured
- end
- end
- paginateGates()
- gatePage, listPage = 1, 1
- if fixNames and fileName == gateData then saveData(gateData, "gate") end --# if we're working with the main address book and there are new changes, then save the updated address book
- if fileName == gateData then gateChange = false end --# if we're working with the main address book, not that there are no changes now (memory and disk match each other)
- end
- end
- end
- local function mergeData() --# merge two address books into one
- if not fs.exists("/disk/data/DHDgates") then return end
- local dhdData = fs.open("/disk/data/DHDgates", "r")
- local newGates = textutils.unserialize(dhdData.readAll())
- dhdData.close()
- mergeAddressBooks(newGates)
- end
- do
- local colorBurst = {
- B = { blue, "Base/Outpost/Hub" },
- H = { sky, "Home/Camp" },
- V = { brown, "Village" },
- M = { purple, "Misc/Special" },
- S = { green, "Safe/Secured" },
- C = { orange, "Caution" },
- D = { red, "Danger" },
- U = { silver, "Unknown/Unclassified" }
- }
- assignColor = function(gateNumber)
- return colorBurst[addressBook[gateNumber].rating][1]
- end
- assignRating = function(gateNumber)
- return colorBurst[addressBook[gateNumber].rating][2]
- end
- end
- local function makeLongName(name)
- return #name ~= 7 and name or table.concat({ name:sub(1, 1), " ", name:sub(2, 2), " ", name:sub(3, 3), " ", name:sub(4, 4), " ", name:sub(5, 5), " ", name:sub(6, 6), " ", name:sub(7) })
- end
- local function displayMarquee()
- if hardware.marquee > 0 then
- for i = 1, hardware.marquee do
- marquee[i].setTextScale(2)
- marquee[i].setBackgroundColor(black)
- marquee[i].clear()
- marquee[i].setTextColor(cyan)
- marquee[i].setCursorPos(1, 1)
- marquee[i].write("Stargate")
- marquee[i].setTextColor(yellow)
- marquee[i].setCursorPos(4, 2)
- marquee[i].write(thisGate)
- end
- end
- end
- local function displayAddressBook()
- if hardware.listMon > 0 then
- local firstGate = (listPage - 1) * 8 + 1
- for i = 1, hardware.listMon do
- local tmY = 1
- listMon[i].setTextScale(0.5)
- listMon[i].setBackgroundColor(black)
- listMon[i].clear()
- for j = firstGate, firstGate + 7 do
- if j > #addressBook then break end
- listMon[i].setCursorPos(4, tmY)
- listMon[i].setTextColor(assignColor(j))
- if (thisGate == addressBook[j].addr or addressBook[j].addr == thisGate:sub(1, 7)) and dhdSettings.highlight then
- listMon[i].setTextColor(gray)
- end
- listMon[i].write(addressBook[j].name)
- tmY = tmY + 1
- if tmY >= 9 then break end
- end
- listMon[i].setBackgroundColor(cyan)
- listMon[i].setTextColor(white)
- listMon[i].setCursorPos(1, 10)
- listMon[i].write(" /\\ \\/ ")
- end
- end
- end
- local function displayNotes(gateID)
- if hardware.listMon > 0 then
- for i = 1, hardware.listMon do
- listMon[i].setBackgroundColor(black)
- listMon[i].clear()
- if #addressBook[gateID].addr == 9 then
- listMon[i].setTextScale(0.5)
- listMon[i].setCursorPos(4, 5)
- else
- listMon[i].setTextScale(1)
- listMon[i].setCursorPos(1, 2)
- end
- listMon[i].setTextColor(assignColor(gateID))
- listMon[i].write(addressBook[gateID].addr)
- if addressBook[gateID].addr == thisGate or addressBook[gateID].addr == thisGate:sub(1, 7) then
- listMon[i].setTextColor(gray)
- if #addressBook[gateID].addr == 9 then
- listMon[i].setCursorPos(4, 7)
- listMon[i].write("THIS GATE")
- else
- listMon[i].setCursorPos(2, 4)
- listMon[i].write("THIS")
- listMon[i].setCursorPos(3, 5)
- listMon[i].write("GATE")
- end
- end
- end
- end
- if hardware.marquee > 0 then
- for i = 1, hardware.marquee do
- marquee[i].setTextScale(1)
- marquee[i].setBackgroundColor(black)
- marquee[i].clear()
- marquee[i].setCursorPos(1, 2)
- marquee[i].setTextColor(sky)
- marquee[i].write(addressBook[gateID].loc.dim)
- marquee[i].setCursorPos(1, 4)
- marquee[i].setTextColor(white)
- if #addressBook[gateID].note > 29 then
- marquee[i].write(addressBook[gateID].note:sub(1, 29))
- marquee[i].setCursorPos(2, 5)
- marquee[i].write(addressBook[gateID].note:sub(30, 43))
- else
- marquee[i].write(addressBook[gateID].note)
- end
- end
- end
- end
- local function displayStatus()
- if hardware.marquee > 0 then
- for i = 1, hardware.marquee do
- marquee[i].setTextScale(2)
- marquee[i].setBackgroundColor(black)
- marquee[i].setCursorPos(1, 1)
- if gateStatus == "Dialing" then
- if incomingAddress then --# incoming call
- marquee[i].setTextColor(secureStatus == "allclear" and yellow or red)
- marquee[i].write("Incoming from ")
- marquee[i].setTextColor(secureStatus == "allclear" and sky or orange)
- if lcGate then --# LanteaCraft
- marquee[i].setCursorPos(4, 2)
- marquee[i].write(incomingAddress .. string.rep(" ", 9))
- else --# SGCraft
- marquee[i].setCursorPos(#incomingAddress - 5, 2)
- if #incomingAddress == 7 then
- local longAddress = makeLongName(incomingAddress)
- marquee[i].write(longAddress:sub(1, chevronNumber * 2))
- marquee[i].setTextColor(gray)
- marquee[i].write(longAddress:sub((chevronNumber * 2) + 1, #longAddress))
- else
- marquee[i].write(incomingAddress:sub(1, chevronNumber))
- marquee[i].setTextColor(gray)
- marquee[i].write(incomingAddress:sub(chevronNumber + 1, #incomingAddress))
- end
- end
- else --# outgoing call
- marquee[i].setTextColor(sky)
- marquee[i].write("Dialing ")
- marquee[i].setCursorPos(#dialAddress - 5, 2)
- marquee[i].setTextColor(yellow)
- if #dialAddress == 7 then
- local longAddress = makeLongName(dialAddress)
- marquee[i].write(longAddress:sub(1, chevronNumber * 2))
- marquee[i].setTextColor(gray)
- marquee[i].write(longAddress:sub((chevronNumber * 2) + 1, #longAddress))
- else
- marquee[i].write(dialAddress:sub(1, chevronNumber))
- marquee[i].setTextColor(gray)
- marquee[i].write(dialAddress:sub(chevronNumber + 1, #dialAddress))
- end
- end
- elseif gateStatus == "Connected" then
- if incomingAddress then --# incoming call
- marquee[i].setTextColor(secureStatus == "allclear" and yellow or red)
- marquee[i].write("Incoming from ")
- marquee[i].setTextColor(secureStatus == "allclear" and sky or orange)
- marquee[i].setCursorPos(#incomingAddress - 5, 2)
- marquee[i].write(makeLongName(incomingAddress) .. string.rep(" ", 9))
- else --# outgoing call
- marquee[i].setTextColor(sky)
- if dialAddress ~= "none" and dialAddress ~= "n o n e" and gateStatus ~= "Disconnecting" then
- marquee[i].write("Connected to")
- marquee[i].setTextColor(yellow)
- marquee[i].setCursorPos(#dialAddress - 5, 2)
- marquee[i].write(makeLongName(dialAddress))
- end
- end
- elseif gateStatus == "Disconnecting" then
- marquee[i].clear()
- marquee[i].setTextColor(sky)
- marquee[i].write(gateStatus)
- end
- end
- end
- if gateStatus == "Disconnected" and secureStatus == "allclear" then
- if displayState == "list" then
- displayMarquee()
- displayAddressBook()
- elseif displayState == "info" then
- displayNotes(selectedGate)
- end
- end
- end
- local function drawElement(x, y, w, h, txtColor, bgColor, text)
- if type(w) == "string" then
- term.setCursorPos(x, y)
- term.setBackgroundColor(green) --# Switch (Neutral)
- term.write(" ")
- term.setBackgroundColor(gray)
- term.write(" ")
- term.setBackgroundColor(red)
- term.write(" ")
- elseif type(w) == "boolean" then
- term.setCursorPos(x, y)
- if w then --# Switch (ON)
- term.setBackgroundColor(green)
- term.write(" ")
- term.setBackgroundColor(gray)
- term.write(" ")
- else --# Switch (OFF)
- term.setBackgroundColor(gray)
- term.write(" ")
- term.setBackgroundColor(red)
- term.write(" ")
- end
- else
- if bgColor then term.setBackgroundColor(bgColor) end
- local deText = text and tostring(text) or ""
- if w > #deText or h > 1 then --# We're drawing something more than text
- local line = string.rep(" ", w) --# Define one line of the 'element' (box/rectangle/line-seg)
- for i = y, y + h - 1 do
- term.setCursorPos(x, i) --# Position cursor
- term.write(line) --# Draw 1 of h lines of the 'element' (box/rectangle/line-seg)
- end
- end
- if deText ~= "" then
- if txtColor then term.setTextColor(txtColor) end
- w = math.max(w, #deText) --# Ensure minimum length
- local xW = (x + math.floor(w / 2)) - math.floor(#deText / 2) --# Center the text horizontally
- local yH = y + math.floor(h / 2) --# Center the text vertically
- term.setCursorPos(xW, yH) --# Set the cursor position
- term.write(deText) --# Write the text
- end
- end
- end
- drawWaitingIrisState = function(_open)
- drawElement(43, 7, 1, 1, _open and orange or green, sky, "Iris")
- end
- do
- local runStates = {
- Dial = blue,
- goPage = blue,
- importExport = blue,
- exodus = blue,
- Trim = orange,
- goTrimPage = orange,
- GateEdit = brown,
- }
- drawHeader = function()
- local bgColor
- term.setBackgroundColor(black)
- term.setTextColor(white)
- if secureStatus == "allclear" then
- for k, v in pairs(runStates) do
- if tostring(k) == runState then
- bgColor = v
- end
- end
- elseif secureStatus == "lockdown" then
- bgColor = red
- end
- if (runState ~= "logs" and runState ~= "clearLogs" and runState ~= "goLogPage") or secureStatus == "lockdown" then --# header for all but logs
- drawElement(1, 1, termX, 1, white, bgColor, thisGate)
- else --# If we're viewing the logs, show the last call info instead of connect/iris info
- drawElement(1, 1, termX, 1, nil, yellow, "") --# yellow header
- drawElement(1, 2, termX, 3, nil, gray, "") --# sub-header body
- drawElement((termX / 2) - 7, 1, 16, 1, yellow, nil, thisGate .. " Logs") --# header text
- drawElement(2, 2, 1, 1, silver, nil, "Last Call:")
- drawElement(2, 4, 25, 1, nil, nil, "Day Time Vector Address")
- drawElement(termX - 6, 2, 7, 1, red, silver, " Close ")
- drawElement(termX - 6, 4, 7, 1, orange, nil, " Clear ")
- term.setBackgroundColor(gray)
- term.setTextColor(black)
- term.setCursorPos(2, 3)
- if not lastCall then
- term.write("none" .. string.rep(" ", 3) .. "none" .. string.rep(" ", 7) .. "none" .. string.rep(" ", 7) .. "none")
- else
- term.write(lastCall:sub(1, string.find(lastCall, "@") - 2)) --# Day
- term.setCursorPos(9, 3)
- term.write(lastCall:sub(string.find(lastCall, "@") + 2, string.find(lastCall, "M"))) --# Time
- term.setCursorPos(20, 3)
- local callDir = (lastCall:sub(string.find(lastCall, "<") + 1, string.find(lastCall, ">") - 1))
- term.write(callDir) --# Direction
- term.setTextColor(callDir == "Outbound" and sky or cyan)
- term.setCursorPos(31, 3)
- term.write(lastCall:sub(string.find(lastCall, ">") + 2)) --# Address
- end
- return
- end
- if (runState == "Dial" or runState == "importExport" or runState == "goPage" or runState == "exodus") and secureStatus == "allclear" then --# Dial mode gets the -DHD- menu
- drawElement(2, 1, 5, 1, white, black, "-DHD-") --# Drop down menu button
- end
- drawElement(1, 2, termX, 3, nil, gray, "") --# Draw 'status' area
- drawElement(2, 3, 7, 1, silver, nil, "Fuel:")
- drawElement(20, 3, 5, 1, nil, nil, "Gate:")
- --# Fuel & Gate Status
- if lcGate then
- drawElement(9, 3, 1, 1, fuelGauge and lime or orange, gray, fuelGauge and "YES" or "NO ") --# LC Fuel state
- else
- local fuelPercent = math.floor(fuelGauge / SG_MAXFUEL * 100)
- drawElement(9, 3, 1, 1, fuelPercent > 5 and lime or orange, gray, tostring(fuelPercent)) --# SG Fuel level
- term.setTextColor(silver)
- term.write("% ")
- end
- local allStatusColors = { ["Connected"] = orange, ["Disconnected"] = lime }
- local clearStatusColors = { ["Dialing"] = cyan, ["Disconnecting"] = sky }
- local tgColor = red
- for state, color in pairs(allStatusColors) do
- if gateStatus == state then tgColor = color break end
- end
- if secureStatus == "allclear" then
- for state, color in pairs(clearStatusColors) do
- if gateStatus == state then tgColor = color break end
- end
- end
- term.setTextColor(tgColor)
- term.setCursorPos(26, 3)
- if (gateStatus == "Connected" or gateStatus == "Dialing") and dialAddress == "none" then --# incoming calls
- if incomingAddress then
- if #incomingAddress > 0 then
- term.write("Incoming from ")
- term.setTextColor(yellow)
- if lcGate then
- term.write(incomingAddress)
- else
- term.write(incomingAddress:sub(1, chevronNumber))
- term.setTextColor(silver)
- term.write(incomingAddress:sub(chevronNumber + 1, #incomingAddress))
- end
- end
- else
- term.write(gateStatus)
- end
- else
- if gateStatus == "Connected" and dialAddress ~= "none" then --# outgoing calls and connection data
- term.write("Connected to ")
- term.setTextColor(yellow)
- term.write(dialAddress)
- else
- term.write(gateStatus)
- term.setCursorPos(34, 3)
- end
- if gateStatus == "Dialing" and chevronNumber <= 9 then --# dialing data
- term.setTextColor(yellow)
- term.write(dialAddress:sub(1, chevronNumber))
- term.setTextColor(silver)
- term.write(dialAddress:sub(chevronNumber + 1, #dialAddress))
- end
- end
- end
- end
- local function drawControlUI()
- local iColor
- if waitingForIris then iColor = irisState and orange or green end
- drawElement(42, 6, 10, 11, nil, gray, "") --# Control UI menu body
- if runState == "Dial" or runState == "goPage" or runState == "importExport" or runState == "exodus" then
- drawElement(43, 7, 1, 1, waitingForIris and iColor or white, sky, "Iris ") --# Iris
- drawElement(termX - 1, 7, 1, 1, nil, irisState and green or orange, " ") --# Iris pip
- drawElement(43, 9, 1, 1, black, orange, "END Call ") --# endCall
- drawElement(43, 11, 1, 1, orange, red, "LOCKDOWN ") --# Lockdown
- drawElement(43, 13, 1, 1, gateChange and lime or white, blue, "AddrBook ") --# Address Book
- drawElement(43, 15, 1, 1, white, green, "New Gate ") --# New Gate
- elseif runState == "Trim" then
- drawElement(43, 7, 9, 1, white, orange, " T R I M ") --# TRIM MODE
- drawElement(43, 8, 9, 1, nil, nil, " M O D E ")
- drawElement(43, 11, 9, 1, gateChange and white or gray, sky, "Reload ") --# Undo
- drawElement(43, 13, 9, 1, nil, green, "Save ") --# Commit
- drawElement(43, 15, 9, 1, white, red, "Close ") --# Exit Trim Mode
- end
- end
- local function drawNaviUI()
- pNum = tostring(gatePage) .. " of " .. tostring(gatePages)
- drawElement(((termX / 2) - 3) - (#pNum / 2) - 2, termY, #pNum, 1, silver, black, " " .. pNum .. " ")
- drawElement((termX / 2) - 16, termY, 7, 1, gray, nil, gatePage > 1 and "<< <" or " ")
- drawElement((termX / 2) + 2, termY, 7, 1, nil, nil, gatePage < gatePages and "> >>" or " ")
- end
- local function drawAddressBook() --# Gate Address Book (Dial / Trim)
- local magicNumber = ((gatePage - 1) * 23) + gatePage
- local xPos, yPos = 2, 6
- for i = magicNumber, #addressBook do
- if runState == "Dial" or runState == "goPage" or runState == "importExport" or runState == "exodus" then
- term.setBackgroundColor(assignColor(i))
- if ((dialAddress == addressBook[i].addr or (#dialAddress == 7 and dialAddress == addressBook[i].addr:sub(1, 7) and addressBook[i].addr:sub(8, 9) == thisGate:sub(8, 9)) or (#addressBook[i].addr == 7 and addressBook[i].addr == dialAddress:sub(1, 7) and dialAddress:sub(8, 9) == thisGate:sub(8, 9))) or (incomingAddress == addressBook[i].addr or (#tostring(incomingAddress) == 7 and incomingAddress == addressBook[i].addr:sub(1, 7) and addressBook[i].addr:sub(8, 9) == thisGate:sub(8, 9)) or (#addressBook[i].addr == 7 and addressBook[i].addr == tostring(incomingAddress):sub(1, 7) and tostring(incomingAddress):sub(8, 9) == thisGate:sub(8, 9)))) and ((#addressBook[i].addr == 9 and thisGate ~= addressBook[i].addr) or (#addressBook[i].addr == 7 and thisGate:sub(1, 7) ~= addressBook[i].addr)) then --# Highlight the gate being dialed
- term.setTextColor(black) --# currently dialing/conntected to this gate
- else
- term.setTextColor(white) --# not dialing/connected to this gate
- end
- if (thisGate == addressBook[i].addr or addressBook[i].addr == thisGate:sub(1, 7)) and dhdSettings.highlight then --# Highlight this gate / Dial
- term.setTextColor(silver) --# thisGate
- term.setBackgroundColor(gray)
- end
- elseif runState == "Trim" or runState == "goTrimPage" then
- term.setBackgroundColor(black)
- if ((#addressBook[i].addr == 9 and thisGate == addressBook[i].addr) or (#addressBook[i].addr == 7 and addressBook[i].addr == thisGate:sub(1, 7))) and dhdSettings.highlight then --# Highlight this gate / Trim
- term.setTextColor(gray) --# thisGate
- else
- term.setTextColor(assignColor(i))
- end
- end
- term.setCursorPos(xPos, yPos)
- term.write(string.rep(" ", math.floor((9 - #addressBook[i].name) / 2)) .. addressBook[i].name .. string.rep(" ", math.ceil((9 - #addressBook[i].name) / 2))) --# Gate Name
- yPos = yPos + 2
- if yPos > 16 then yPos = 6 xPos = xPos + 10 end
- if xPos > 32 then break end
- end
- end
- local function drawHelpUI()
- clearScreen() --# Body
- drawElement(1, 1, termX, 1, nil, cyan, "") --# Header
- drawElement((termX / 2) - 4, 1, 12, 1, cyan, gray, "ccDHD Help") --# Header text
- drawElement(1, termY, termX, 1, nil, nil, "") --# Footer
- local lowLine = "ccDHD ver. " .. ccDHDVer .. string.rep(" ", 5) .. "cc# " .. os.getComputerID()
- drawElement(2, termY, 1, 1, silver, nil, lowLine) --# Footer text
- local tmpLabel = os.getComputerLabel()
- drawElement(termX - #tmpLabel, termY, 1, 1, nil, nil, tmpLabel)
- drawElement(1, 2, termX, 1, nil, nil, "") --# Header/Separator
- drawElement(termX - 6, 2, 7, 1, red, silver, " Close ") --# Close button
- drawElement(1, 3, 14, termY - 3, nil, white, "") --# draw help left pane
- drawElement(2, 5, 1, 1, black, nil, "Main Screen")
- drawElement(2, 10, 1, 1, nil, nil, "AddrBook Btn")
- drawElement(2, 14, 1, 1, nil, nil, "Log Screen")
- drawElement(2, 6, 1, 1, gray, nil, "LEFT click")
- drawElement(2, 7, 1, 1, nil, nil, "RIGHT click")
- drawElement(2, 8, 1, 1, nil, nil, "MIDDLE click")
- drawElement(2, 11, 1, 1, nil, nil, "LEFT click")
- drawElement(2, 12, 1, 1, nil, nil, "RIGHT click")
- drawElement(2, 15, 1, 1, nil, nil, "LEFT click")
- drawElement(2, 16, 1, 1, nil, nil, "RIGHT click")
- drawElement(16, 6, 1, 1, silver, black, "an address to dial")
- drawElement(16, 7, 1, 1, nil, nil, "an address to view or edit details")
- drawElement(16, 8, 1, 1, nil, nil, "an address to enter TRIM mode")
- drawElement(16, 11, 1, 1, nil, nil, "to import/export/save address book")
- drawElement(16, 12, 1, 1, nil, nil, "to quick-save address book")
- drawElement(16, 15, 1, 1, nil, nil, "an address to dial")
- drawElement(16, 16, 1, 1, nil, nil, "an address to add to address book")
- end
- local function drawSettingsSwitches()
- --# Settings 1st column
- if hardware.bio > 0 then
- drawElement(22, 10, dhdSettings.bio.lock) --# Fistprint Authentication (Bioscanner)
- drawElement(2, 12, 1, 1, gray, black, "Bio: ") --# Biolock iris/lockdown function (this is separate from BioLogin)
- if dhdSettings.bio.func == "none" then
- drawElement(7, 12, 1, 1, silver, nil, "No Function")
- drawElement(22, 12, "MID")
- elseif dhdSettings.bio.func == "iris" then
- drawElement(7, 12, 1, 1, green, nil, "Iris ")
- drawElement(22, 12, true)
- elseif dhdSettings.bio.func == "lock" then
- drawElement(7, 12, 1, 1, red, nil, "Lockdown ")
- drawElement(22, 12, false)
- end
- drawElement(19 + dhdSettings.bio.auth, 14, 1, 1, black, silver, tostring(dhdSettings.bio.auth))
- drawElement(19 + dhdSettings.bio.fAuth, 16, 1, 1, nil, nil, tostring(dhdSettings.bio.fAuth))
- else
- drawElement(2, 10, 24, 7, gray, black, "No Biolock present")
- end
- --# Settings 2nd column
- drawElement(46, 6, dhdSettings.pSync) --# pSync
- drawElement(46, 10, dhdSettings.highlight) --# highlight gate
- drawElement(46, 12, dhdSettings.logs) --# Call logging
- drawElement(46, 14, dhdSettings.startIris) --# Startup Iris state
- drawElement(46, 16, dhdSettings.ecIris) --# endCall Iris state
- end
- do
- local labels = {
- "Lockdown pass",
- "Biolock Login",
- "Bio",
- "Bio Login Lvl",
- "Bio Func. Lvl",
- "pSync (ccDialer)",
- "Highlight Gate",
- "Call Logging",
- "Incoming Iris",
- "END Call Iris",
- }
- drawSettingsUI = function()
- drawElement(1, 1, termX, 1, nil, sky, "") --# Header
- drawElement(1, 2, termX, 3, nil, gray, "") --# Sub-Header
- drawElement(1, 8, termX, 1, nil, nil, "") --# Separator
- drawElement(19, 1, 16, 1, sky, nil, "ccDHD Settings") --# Title
- drawElement(1, termY, termX, 1, silver, nil, "ccDHD " .. ccDHDVer) --# Footer / Lowline
- drawElement(17, 3, 1, 1, nil, nil, "This Gate:") --# Header (This Gate)
- drawElement(28, 3, 1, 1, cyan, nil, thisGate) --# Header (thisGate)
- drawElement(45, 2, 7, 1, red, silver, " Close ") --# Close button
- drawElement(45, 4, 6, 1, configChange and lime or gray, nil, " Save ") --# Save button
- local xOffset, yOffset = 2, 6
- term.setTextColor(gray)
- term.setBackgroundColor(black)
- for i = 1, #labels do
- drawElement(xOffset, yOffset, 1, 1, nil, nil, labels[i])
- yOffset = yOffset + 2
- if yOffset == 8 then yOffset = 10 end
- if yOffset == 18 and xOffset == 2 then
- xOffset = 28
- yOffset = 6
- end
- end
- drawElement(17, 6, 1, 1, orange, nil, "*********") --# password
- if hardware.bio > 0 then
- drawElement(19, 14, 1, 1, gray, nil, "|-----|") --# Biolock login level
- drawElement(19, 16, 1, 1, nil, nil, "|-----|") --# Biolock iris/lockdown level
- end
- drawSettingsSwitches()
- end
- end
- local function drawSecureUI()
- if hardware.listMon > 0 then
- for i = 1, hardware.listMon do
- listMon[i].setBackgroundColor(black)
- listMon[i].setTextColor(red)
- listMon[i].setTextScale(0.5)
- listMon[i].clear()
- listMon[i].setCursorPos(1, 5)
- listMon[i].write("!! LOCKDOWN !!")
- end
- end
- if hardware.marquee > 0 then
- if incomingAddress then
- displayStatus()
- else
- for i = 1, hardware.marquee do
- marquee[i].setBackgroundColor(black)
- marquee[i].setTextColor(red)
- marquee[i].setTextScale(2)
- marquee[i].clear()
- marquee[i].setCursorPos(1, 1)
- marquee[i].write("!! LOCKDOWN !!")
- end
- end
- end
- clearLowerScreen()
- drawHeader()
- drawElement((termX / 2) - 7, 9, 1, 1, red, black, "!! LOCKDOWN !!")
- drawElement((termX / 2) - 10, 15, 1, 1, gray, nil, "password:")
- end
- local function drawPopUp()
- if runState == "clearLogs" then
- drawElement((termX / 2) - 5, math.floor(termY / 2) - 2, 13, 1, black, yellow, "Clear Logs?")
- drawElement((termX / 2) - 5, math.floor(termY / 2) - 1, 13, 3, nil, gray, "")
- drawElement((termX / 2) - 4, math.floor(termY / 2), 5, 1, nil, green, "YES")
- drawElement((termX / 2) + 2, math.floor(termY / 2), 5, 1, nil, red, "N O")
- elseif runState == "goPage" or runState == "goTrimPage" then
- drawElement((termX / 2) - 8, termY - 3, 8, 1, white, gray, " :Page: ")
- drawElement((termX / 2) - 8, termY - 2, 8, 2, nil, nil, "")
- drawElement((termX / 2) - 7, termY - 2, 6, 1, nil, black, "") --# input area bg
- elseif runState == "goLogPage" then
- drawElement((termX / 2) - 4, termY - 3, 8, 1, white, gray, " :Page: ")
- drawElement((termX / 2) - 4, termY - 2, 8, 2, nil, nil, "")
- drawElement((termX / 2) - 3, termY - 2, 6, 1, nil, black, "") --# input area bg
- elseif runState == "importExport" then
- drawElement((termX / 2) - 13, math.floor(termY / 2) - 1, 19, 1, white, blue, "Address Book Mgt.")
- drawElement((termX / 2) - 13, math.floor(termY / 2), 19, 7, nil, gray, "")
- if fs.exists("/disk/data/DHDgates") then
- drawElement((termX / 2) - 12, math.floor(termY / 2) + 1, 8, 1, black, yellow, "Import")
- drawElement((termX / 2) - 12, math.floor(termY / 2) + 3, 8, 1, white, purple, "Merge!")
- else
- drawElement((termX / 2) - 12, math.floor(termY / 2) + 1, 8, 1, gray, silver, "Import")
- drawElement((termX / 2) - 12, math.floor(termY / 2) + 3, 8, 1, nil, nil, "Merge!")
- end
- if fs.exists("/disk") then
- drawElement((termX / 2) - 3, math.floor(termY / 2) + 1, 8, 1, black, orange, "Export")
- else
- drawElement((termX / 2) - 3, math.floor(termY / 2) + 1, 8, 1, gray, silver, "Export")
- end
- if gateChange then
- drawElement((termX / 2) - 3, math.floor(termY / 2) + 3, 8, 1, white, green, "Save")
- else
- drawElement((termX / 2) - 3, math.floor(termY / 2) + 3, 8, 1, gray, silver, "Save")
- end
- drawElement((termX / 2) - 7, math.floor(termY / 2) + 5, 7, 1, white, red, "CLOSE")
- elseif runState == "newPassword" then
- drawElement((termX / 2) - 6, 6, 14, 1, white, blue, "Lockdown P/W")
- drawElement((termX / 2) - 6, 7, 14, 5, nil, silver, "") --# body
- drawElement((termX / 2) - 6, 7, 14, 1, black, nil, " OLD Password ")
- drawElement((termX / 2) - 6, 9, 14, 1, nil, nil, " NEW Password ")
- drawElement((termX / 2) - 5, 8, 12, 1, nil, black, "") --# oldPass input area bg
- drawElement((termX / 2) - 5, 10, 12, 1, nil, nil, "") --# newPass input area bg
- drawElement((termX / 2) - 3, 11, 8, 1, white, orange, "Cancel")
- elseif runState == "exodus" then
- if gateChange and not configChange then
- drawElement((termX / 2) - 13, math.floor(termY / 2) - 1, 19, 1, white, blue, "Save Addr Book?")
- elseif configChange and not gateChange then
- drawElement((termX / 2) - 13, math.floor(termY / 2) - 1, 19, 1, white, blue, "Save Settings?")
- else
- drawElement((termX / 2) - 13, math.floor(termY / 2) - 1, 19, 1, white, blue, "Save Gates & Cfg?")
- end
- drawElement((termX / 2) - 13, math.floor(termY / 2), 19, 3, nil, gray, "")
- drawElement((termX / 2) - 12, math.floor(termY / 2) + 1, 8, 1, nil, green, "Save")
- drawElement((termX / 2) - 3, math.floor(termY / 2) + 1, 8, 1, nil, orange, "Quit")
- end
- end
- local function drawMenu()
- menuState = true
- drawElement(2, 1, 5, 1, white, black, "_DHD_")
- drawElement(2, 2, 1, 9, nil, gray, "") --# dark gray line along left side of menu
- drawElement(2, 3, 1, 1, nil, sky, "") --# Settings pip
- drawElement(2, 5, 1, 1, nil, yellow, "") --# Logs pip
- drawElement(2, 7, 1, 1, nil, cyan, "") --# Help pip
- drawElement(2, 9, 1, 1, nil, red, "") --# Exit pip
- drawElement(3, 2, 9, 9, nil, silver, "") --# menu body
- drawElement(3, 3, 1, 1, gray, nil, "Settings")
- drawElement(3, 5, 1, 1, nil, nil, "View Logs")
- drawElement(3, 7, 9, 1, nil, nil, "DHD Help")
- drawElement(3, 9, 1, 1, nil, nil, " EXIT ")
- end
- do
- local ratings = {
- [1] = { rating = "B", color = blue, desc = "Base/Outpost/Hub" },
- [2] = { rating = "H", color = sky, desc = "Home/Camp" },
- [3] = { rating = "V", color = brown, desc = "Village" },
- [4] = { rating = "M", color = purple, desc = "Misc/Special" },
- [5] = { rating = "S", color = green, desc = "Safe/Secured" },
- [6] = { rating = "C", color = orange, desc = "Caution" },
- [7] = { rating = "D", color = red, desc = "Danger" },
- [8] = { rating = "U", color = silver, desc = "Unk/Unclassified" },
- }
- drawRatingList = function(gRating)
- local rColor
- drawElement(18, 6, 20, 1, white, brown, "Classification")
- drawElement(18, 7, 20, 10, nil, gray, "") --# menu body
- for i = 1, #ratings do
- if gRating == ratings[i].rating then
- rColor = gRating == "U" and white or ratings[i].color
- drawElement(37, i + 7, 1, 1, nil, ratings[i].color, "") --# selected rating color pip
- else
- rColor = silver
- end
- drawElement(18, i + 7, 1, 1, nil, ratings[i].color, "") --# color pip
- drawElement(20, i + 7, 1, 1, rColor, gray, ratings[i].desc)
- end
- end
- end
- drawCLI = function(_mon)
- --# Terminal output
- if menuState then
- if redraw or incomingAddress or dialAddress ~= "none" then
- drawHeader()
- drawAddressBook()
- if gateChange then drawControlUI() end
- drawNaviUI()
- end
- drawMenu()
- else
- if runState ~= "DHDsettings" and runState ~= "newPassword" and runState ~= "logs" and runState ~= "clearLogs" then
- drawHeader()
- end
- end
- redraw = false
- if not menuState then
- if runState == "goPage" or runState == "goTrimPage" or runState == "importExport" or runState == "exodus" then
- drawAddressBook()
- drawControlUI()
- drawPopUp()
- elseif runState == "Dial" or runState == "Trim" then
- if secureStatus == "lockdown" then
- drawSecureUI()
- else
- drawAddressBook()
- drawControlUI()
- drawNaviUI()
- end
- elseif runState == "DHDhelp" then
- drawHelpUI()
- end
- if gettingInput then redrawInput() end
- end
- --# Monitor output
- if _mon then
- if displayState == "list" and secureStatus == "allclear" then
- if hardware.marquee > 0 then
- displayStatus()
- end
- if hardware.listMon > 0 then
- displayAddressBook()
- end
- elseif displayState == "info" and secureStatus == "allclear" then
- if hardware.listMon > 0 and hardware.marquee > 0 then
- displayNotes(selectedGate)
- end
- end
- end
- end
- local function clearCallHistory()
- for i = #callHistory, 1, -1 do
- callHistory[i] = nil
- end
- end
- local function drawLogScreen()
- if logPage == logPages and logPages > 1 then
- clearLowerScreen()
- end
- drawElement(1, termY, termX, 1, nil, gray, "") --# Footer
- if not callHistory[1] then --# No logs to display
- drawElement(2, 6, 1, 1, gray, black, "No Logs")
- else --# Logs to display
- --# populate footer
- drawElement(11, termY, 7, 1, silver, nil, "<< <")
- term.setCursorPos(math.floor(termX / 2) - (math.floor((#tostring(logPage) + #tostring(logPages)) / 2) + 2), termY)
- term.write(tostring(logPage) .. " of " .. tostring(logPages) .. " ")
- drawElement(36, termY, 1, 1, nil, nil, "> >>")
- --# end of footer
- term.setBackgroundColor(black)
- local currentEntry = ((logPage - 1) * 11) + 1 --# Set the first entry to show (based on page number)
- local spacer = string.rep(" ", 9)
- for i = currentEntry, currentEntry + 10 do --# Display logs
- local callDir = callHistory[i]:sub(string.find(callHistory[i], "<") + 1, string.find(callHistory[i], ">") - 1)
- term.setTextColor(callDir == "Inbound" and gray or silver)
- term.setCursorPos(2, i - currentEntry + 6) --# position entry
- term.write(callHistory[i]:sub(1, string.find(callHistory[i], "@") - 2) .. " ") --# write day
- term.setCursorPos(9, i - currentEntry + 6) --# position entry
- term.write(callHistory[i]:sub(string.find(callHistory[i], "@") + 2, string.find(callHistory[i], "M"))) --# write time
- term.setCursorPos(20, i - currentEntry + 6) --# position entry
- term.write(callDir .. " ") --# write direction
- term.setCursorPos(31, i - currentEntry + 6) --# position entry
- local callAddr = callHistory[i]:sub(string.find(callHistory[i], ">") + 2) --# set address
- term.setTextColor(callDir == "Inbound" and cyan or sky)
- term.write(callAddr .. spacer) --# write address (and clear space for truncated entries)
- if i >= #callHistory then break end --# if we've reached the end of the log then stop the loop
- end
- end
- end
- local function drawGateData()
- if addressBook[currentEdit].addr == thisGate or (not lcGate and addressBook[currentEdit].addr == thisGate:sub(1, 7)) then
- drawElement((termX / 2), 8, 1, 1, gray, black, "< This Gate >")
- else
- drawElement((termX / 2), 8, 1, 1, nil, black, " ")
- end
- local xStr, yStr, zStr, ceStr = tostring(addressBook[currentEdit].loc.x), tostring(addressBook[currentEdit].loc.y), tostring(addressBook[currentEdit].loc.z), tostring(currentEdit)
- drawElement(11, 6, 1, 1, yellow, black, addressBook[currentEdit].name .. string.rep(" ", 9 - #addressBook[currentEdit].name)) --# Name
- drawElement(13, 14, 1, 1, nil, nil, addressBook[currentEdit].loc.dim .. string.rep(" ", 19 - #addressBook[currentEdit].loc.dim)) --# Dimension
- drawElement(11, 8, 1, 1, assignColor(currentEdit), nil, addressBook[currentEdit].addr .. " ") --# Address
- drawElement(18, 12, 1, 1, nil, nil, assignRating(currentEdit) .. string.rep(" ", 20 - #assignRating(currentEdit))) --# Classification
- drawElement(termX - 6, 6, 1, 1, white, nil, ceStr .. string.rep(" ", 5 - #ceStr)) --# Position in address book
- drawElement(8, 10, 1, 1, nil, nil, addressBook[currentEdit].note:sub(1, 43) .. string.rep(" ", 43 - #addressBook[currentEdit].note:sub(1, 43))) --# Note
- drawElement(15, 16, 1, 1, silver, nil, xStr .. string.rep(" ", 9 - #xStr)) --# X
- drawElement(28, 16, 1, 1, nil, nil, yStr .. string.rep(" ", 9 - #yStr)) --# Y
- drawElement(41, 16, 1, 1, nil, nil, zStr .. string.rep(" ", 9 - #zStr)) --# Z
- if addressBook[currentEdit].iris == "none" then --# Iris control
- drawElement(31, 6, "mid")
- elseif addressBook[currentEdit].iris == "open" then
- drawElement(31, 6, true)
- elseif addressBook[currentEdit].iris == "close" then
- drawElement(31, 6, false)
- end
- end
- local function drawGateLabels()
- clearLowerScreen()
- drawHeader()
- drawElement(2, 6, 1, 1, gray, black, "Name: Iris: #")
- drawElement(2, 8, 1, 1, nil, nil, "Address:")
- drawElement(2, 10, 1, 1, nil, nil, "Note:")
- drawElement(2, 12, 1, 1, nil, nil, "Classification:")
- drawElement(2, 14, 10, 1, nil, nil, "Dimension:")
- drawElement(2, 16, 1, 1, nil, nil, "Coords: x: y: z:")
- drawElement((termX / 2) - 8, termY - 1, 6, 1, gateChange and green or silver, gray, " Save ")
- drawElement((termX / 2) + 1, termY - 1, 7, 1, red, nil, " Close ")
- drawGateData()
- end
- local function addNewAddress(newAddress, fast)
- if #addressBook < 23976 then --# if the address book isn't yet full...
- addressBook[#addressBook + 1] = { name = newAddress or "NEW GATE", addr = newAddress or "ADDRESS", rating = "U", iris = "none", note = newAddress and "Added from logs" or "short note", loc = { x = 99999, y = 99999, z = 99999, dim = "Overworld", }, } --# ...create new entry
- paginateGates() --# paginate the address book
- gateChange = true --# indicate the address book has changed
- if fast then --# if it's a quick-add...
- if gatePage == gatePages then drawAddressBook() end --# ...redraw the address book if we're on the last page
- drawNaviUI() --# update the page navigation UI (page number)
- return
- end
- currentEdit = #addressBook --# set the entry number being edited
- drawGateLabels()
- else
- runState = "Dial"
- end
- end
- local function flashDial(gate, gX, gY, gateNum)
- local gColor = assignColor(gateNum)
- local gLabel = string.rep(" ", math.floor((9 - #gate) / 2)) .. gate .. string.rep(" ", math.ceil((9 - #gate) / 2))
- drawElement(gX, gY, 9, 1, gColor, black, gLabel)
- sleep(0.1)
- drawElement(gX, gY, 9, 1, black, gColor, gLabel)
- end
- local function flashChoice(x, y, tCo, bCo, label)
- drawElement(x, y, 1, 1, tCo, bCo, label)
- sleep(0.1)
- end
- local function clearLogsPopUp()
- drawPopUp()
- local _, mButton, mX, mY = os.pullEvent("mouse_click")
- if mY == math.floor(termY / 2) then
- if mX > termX / 2 - 5 and mX < termX / 2 and mButton == 1 then
- flashChoice((termX / 2) - 4, math.floor(termY / 2), green, white, " YES ")
- local clearLog = fs.open(gateHistory, "w")
- clearLog.close()
- clearCallHistory()
- logPage, logPages = 1, 1
- runState = "logs"
- clearLowerScreen()
- drawLogScreen()
- return
- elseif mX > termX / 2 and mX < termX / 2 + 6 and mButton == 1 then
- flashChoice((termX / 2) + 2, math.floor(termY / 2), red, white, " N O ")
- drawElement(termX / 2 - 5, math.floor(termY / 2) - 2, 13, 4, nil, black, "") --# clear dialogue box
- runState = "logs"
- drawLogScreen()
- return
- end
- end
- end
- local function saveAndQuitPopUp()
- local _, mButton, mX, mY = os.pullEvent("mouse_click")
- if mX > (termX / 2) - 14 and mX < (termX / 2) + 5 and mY > math.floor(termY / 2) - 2 and mY < math.floor(termY / 2) + 3 then
- if mX > (termX / 2) - 13 and mX < (termX / 2) - 5 and mY == math.floor(termY / 2) + 1 and mButton == 1 then
- flashChoice((termX / 2) - 12, math.floor(termY / 2) + 1, green, white, " Save ")
- if gateChange then
- saveData(gateData, "gate")
- end
- if configChange then
- saveData(settingsData, "cfg")
- end
- kernelState = false
- return true
- elseif mX > (termX / 2) - 4 and mX < (termX / 2) + 4 and mY == math.floor(termY / 2) + 1 and mButton == 1 then
- flashChoice((termX / 2) - 3, math.floor(termY / 2) + 1, orange, white, " Quit ")
- kernelState = false
- return true
- end
- else
- runState = "Dial"
- drawElement(2, 6, 39, 11, nil, black, "")
- drawAddressBook()
- return false
- end
- end
- local function importExportPopUp()
- while true do
- local _, mButton, mX, mY = os.pullEvent("mouse_click")
- if mX > (termX / 2) - 14 and mX < (termX / 2) + 5 and mY < math.floor(termY / 2) + 7 and mY > math.floor(termY / 2) - 2 then
- if mX > (termX / 2) - 13 and mX < termX / 2 - 5 and mY == math.floor(termY / 2) + 1 and mButton == 1 then
- if fs.exists("/disk/data/DHDgates") then
- flashChoice((termX / 2) - 12, math.floor(termY / 2) + 1, yellow, black, " Import ")
- ingestData("/disk/data/DHDgates", "gate")
- drawElement(2, 6, 39, 11, nil, nil, "")
- drawAddressBook()
- drawNaviUI()
- if displayState == "info" then displayState = "list" end
- displayAddressBook()
- displayMarquee()
- drawElement(43, 13, 1, 1, lime, blue, "AddrBook ")
- drawPopUp()
- end
- elseif mX > termX / 2 - 4 and mX < (termX / 2) + 4 and mY == math.floor(termY / 2) + 1 and mButton == 1 then
- if fs.exists("/disk") then
- flashChoice((termX / 2) - 3, math.floor(termY / 2) + 1, orange, black, " Export ")
- saveData("/disk/data/DHDgates", "gate")
- drawPopUp()
- end
- elseif mX > (termX / 2) - 13 and mX < (termX / 2) - 5 and mY == math.floor(termY / 2) + 3 and mButton == 1 then
- if fs.exists("/disk/data/DHDgates") then
- flashChoice((termX / 2) - 12, math.floor(termY / 2) + 3, purple, white, " Merge! ")
- mergeData()
- if gateChange then
- drawAddressBook()
- drawNaviUI()
- if displayState == "list" then displayAddressBook() end
- drawElement(43, 13, 1, 1, lime, blue, "AddrBook ")
- end
- drawPopUp()
- end
- elseif mX > (termX / 2) - 4 and mX < termX / 2 + 4 and mY == math.floor(termY / 2) + 3 and mButton == 1 and gateChange then
- flashChoice((termX / 2) - 3, math.floor(termY / 2) + 3, green, white, " Save ")
- saveData("/data/DHDgates", "gate")
- drawElement(43, 13, 1, 1, white, blue, "AddrBook ")
- drawPopUp()
- elseif mX > (termX / 2) - 8 and mX < (termX / 2) - 1 and mY == math.floor(termY / 2) + 5 and mButton == 1 then
- runState = "Dial"
- flashChoice((termX / 2) - 7, math.floor(termY / 2) + 5, red, white, " CLOSE ")
- drawElement(2, 6, 39, 11, nil, black, "")
- drawAddressBook()
- return
- end
- end
- end
- end
- local function readInput(curX, curY, cO, bG, _limit, gField, mask) --# cursor X, Y, text color, bg color, character limit, gate address field, character mask
- gettingInput = true
- local symbols = { ["A"] = true, ["B"] = true, ["C"] = true, ["D"] = true, ["E"] = true , ["F"] = true, ["G"] = true, ["H"] = true, ["I"] = true, ["J"] = true, ["K"] = true, ["L"] = true, ["M"] = true, ["N"] = true, ["O"] = true, ["P"] = true, ["Q"] = true, ["R"] = true, ["S"] = true, ["T"] = true, ["U"] = true, ["V"] = true, ["W"] = true, ["X"] = true, ["Y"] = true, ["Z"] = true, ["0"] = true, ["1"] = true, ["2"] = true, ["3"] = true, ["4"] = true, ["5"] = true, ["6"] = true, ["7"] = true, ["8"] = true, ["9"] = true, ["-"] = true, ["+"] = true }
- local passSymbols = { "!", "@", "#", "$", "%", "^", "&", "*", "?", "=", "+", "-", "_", "x", "X" }
- word = ""
- secWord = ""
- bCurX, bCurY = curX, curY
- local bgColor = bG or black
- curColor, bColor = cO, bgColor
- local pos = 0
- _limit = (_limit and type(_limit) == "number" and _limit > 0) and _limit or 43
- if type(mask) ~= "string" then mask = nil end
- term.setTextColor(curColor)
- term.setBackgroundColor(bgColor)
- term.setCursorBlink(true)
- term.setCursorPos(curX, curY)
- while true do
- local event, data, mX, mY = os.pullEvent()
- if event == "key" then
- if data == keys.backspace then
- curX = math.max(bCurX, curX - 1)
- pos = math.max(0, pos - 1)
- word = #word > 0 and word:sub(1, #word - 1) or ""
- if secureStatus == "lockdown" then
- secWord = #secWord > 0 and secWord:sub(1, #secWord - 1) or ""
- end
- drawElement(curX, curY, 1, 1, nil, bgColor, " ")
- term.setCursorPos(curX, curY)
- elseif data == keys.enter or data == keys.numPadEnter then
- if secureStatus == "lockdown" then
- drawElement(bCurX, bCurY, #word, 1, nil, bgColor, "")
- end
- break
- elseif data == keys.tab and runState == "newPassword" then
- break
- end
- elseif event == "char" and pos < _limit then
- local goodData = false
- if secureStatus == "lockdown" then
- local secSymbol = passSymbols[math.random(1, #passSymbols)]
- secWord = secWord .. secSymbol
- drawElement(curX, curY, 1, 1, cO, bgColor, secSymbol)
- goodData = true
- else
- if gField then
- local dUpper = data:upper()
- if symbols[dUpper] then
- drawElement(curX, curY, 1, 1, curColor, bgColor, dUpper)
- goodData = true
- end
- else
- if mask then
- drawElement(curX, curY, 1, 1, curColor, bgColor, mask)
- else
- drawElement(curX, curY, 1, 1, curColor, bgColor, data)
- end
- goodData = true
- end
- end
- if goodData then
- word = word .. data
- curX = curX + 1
- pos = pos + 1
- end
- elseif event == "paste" and pos < _limit then
- if pos + #data > _limit then
- data = data:sub(1, _limit - pos)
- end
- if secureStatus == "lockdown" then
- local secSymbols = { }
- for i = 1, #data do
- secSymbols[i] = passSymbols[math.random(1, #passSymbols)]
- end
- local newSec = table.concat(secSymbols)
- secWord = secWord .. newSec
- drawElement(curX, curY, 1, 1, curColor, bgColor, newSec)
- elseif gField then
- local newWord, glyph = { }, ""
- for i = 1, #data do
- glyph = string.upper(data:sub(i, i))
- if symbols[glyph] then
- newWord[i] = glyph
- else
- newWord[i] = "?"
- end
- end
- data = table.concat(newWord)
- drawElement(curX, curY, 1, 1, curColor, bgColor, data)
- else
- if mask then
- local maskTable = { }
- for i = 1, #data do
- maskTable[i] = mask
- end
- drawElement(curX, curY, 1, 1, curColor, bgColor, table.concat(maskTable))
- else
- drawElement(curX, curY, 1, 1, curColor, bgColor, data)
- end
- end
- word = word .. data
- curX = curX + #data
- pos = pos + #data
- elseif event == "mouse_click" and secureStatus == "allclear" then
- if runState == "newPassword" then
- if mY == 11 and mX > (termX / 2) - 4 and mX < (termX / 2) + 4 then
- term.setCursorBlink(false)
- gettingInput = false
- flashChoice((termX / 2) - 3, 11, orange, white, " Cancel ")
- runState = "DHDsettings"
- drawElement((termX / 2) - 6, 6, 14, 6, nil, black, "")
- drawSettingsUI()
- return
- elseif mX > (termX / 2) - 6 and mX < (termX / 2) + 6 and ((mY == 8 and bCurY == 10) or (mY == 10 and bCurY == 8)) then
- break
- end
- else
- if mY ~= curY or mX < bCurX or mX >= bCurX + _limit then
- break
- end
- end
- elseif event == "mouse_scroll" and runState == "GateEdit" and secureStatus == "allclear" then
- break
- end
- end
- term.setCursorBlink(false)
- gettingInput = false
- return word
- end
- local function goToLogPage()
- local newPage = tonumber(readInput((termX / 2 - 2), termY - 2, lime, nil, 4))
- drawElement((termX / 2) - 4, termY - 3, 8, 3, nil, nil, "")
- logPage = newPage or logPage
- logPage = math.max(1, logPage)
- logPage = math.min(logPage, logPages)
- if logPage == logPages and logPages > 1 then
- drawElement(2, 6, 39, 11, nil, nil, "")
- end
- runState = "logs"
- drawLogScreen()
- end
- local function goToPage()
- local newPage = tonumber(readInput((termX / 2 - 6), termY - 2, lime, nil, 4))
- drawElement((termX / 2) - 8, termY - 3, 8, 3, nil, nil, "")
- gatePage = newPage or gatePage
- gatePage = math.max(1, gatePage)
- gatePage = math.min(gatePage, gatePages)
- if gatePage == gatePages and gatePages > 1 then
- drawElement(2, 6, 39, 11, nil, nil, "")
- end
- runState = runState == "goPage" and "Dial" or "Trim"
- drawAddressBook()
- drawNaviUI()
- end
- local function changeLockdownPassword()
- drawPopUp()
- local oldPass, newPass, goodChange = "", "", false
- while true do
- drawElement((termX / 2) - 5, 8, 12, 1, nil, black, "") --# old password entry area
- oldPass = readInput((termX / 2) - 5, 8, yellow, black, 12, nil, "*")
- if runState == "DHDsettings" then return end
- if oldPass ~= "" then
- drawElement((termX / 2) - 5, 8, 1, 1, gray, nil, string.rep("*", #oldPass))
- end
- if newPass ~= "" and newPass ~= dhdSettings.password and oldPass == dhdSettings.password then
- goodChange = true
- break
- end
- drawElement((termX / 2) - 5, 10, 12, 1, nil, nil, "") --# new password entry area
- newPass = readInput((termX / 2) - 5, 10, yellow, black, 12, nil, "*")
- if runState == "DHDsettings" then return end
- if newPass ~= "" then
- drawElement((termX / 2) - 5, 10, 1, 1, gray, nil, string.rep("*", #newPass))
- end
- if newPass ~= "" and newPass ~= dhdSettings.password and oldPass == dhdSettings.password then
- goodChange = true
- break
- end
- end
- if goodChange then
- configChange = true
- dhdSettings.password = newPass
- runState = "DHDsettings"
- drawElement((termX / 2) - 6, 6, 14, 6, nil, nil, "") --# clear password change box
- drawSettingsUI()
- end
- end
- local function deleteGate(gateNum) --# TRIM mode: delete gate
- if #addressBook > 1 then --# Don't delete if only 1 gate remaining
- table.remove(addressBook, gateNum)
- gateChange = true
- drawElement(43, 11, 9, 1, white, sky, "Reload ") --# Reload
- drawElement(43, 13, 9, 1, nil, green, "Save ") --# Commit
- paginateGates()
- gatePage = math.min(gatePage, gatePages)
- listPage = math.min(listPage, listPages)
- if gatePage == gatePages then drawElement(2, 6, 39, 11, nil, black, "") end --# Clear gate entry area of screen
- end
- end
- local function editGate()
- while true do
- local _, mButton, mcX, mcY = os.pullEvent("mouse_click")
- if mcY == 6 and mButton == 1 then
- if mcX > 10 and mcX < 20 then --# Gate Name
- drawElement(11, 6, 1, 1, gray, black, addressBook[currentEdit].name)
- local newGateName = readInput(11, 6, yellow, black, 9)
- if newGateName ~= "" and newGateName ~= "nil" then
- addressBook[currentEdit].name = newGateName
- if addressBook[currentEdit].addr == "ADDRESS" and (#newGateName == 7 or #newGateName == 9) and not string.find(newGateName, " ") then
- addressBook[currentEdit].addr = string.upper(newGateName)
- end
- gateChange = true
- end
- drawElement(11, 6, 1, 1, yellow, black, addressBook[currentEdit].name .. string.rep(" ", 9 - #addressBook[currentEdit].name))
- elseif mcX > 30 and mcX < 35 then --# Iris control
- if addressBook[currentEdit].iris == "none" then
- addressBook[currentEdit].iris = "open"
- drawElement(31, 6, true)
- elseif addressBook[currentEdit].iris == "open" then
- addressBook[currentEdit].iris = "close"
- drawElement(31, 6, false)
- elseif addressBook[currentEdit].iris == "close" then
- addressBook[currentEdit].iris = "none"
- drawElement(31, 6, "mid")
- end
- gateChange = true
- elseif mcX > termX - 7 and mcX < termX - 6 + #tostring(currentEdit) then --# Address Book entry position (for reordering)
- drawElement(termX - 6, 6, 1, 1, gray, black, tostring(currentEdit))
- local oldPos = currentEdit
- local newPos = math.floor(tonumber(readInput(termX - 6, 6, white, black, 5)))
- if newPos and newPos > 0 and newPos <= #addressBook then
- local tempGateData = { }
- for k, v in pairs(addressBook[currentEdit]) do
- tempGateData[k] = v
- end
- table.remove(addressBook, currentEdit)
- table.insert(addressBook, newPos, tempGateData)
- currentEdit = newPos
- gateChange = true
- end
- drawElement(termX - 6, 6, 1, 1, white, black, tostring(currentEdit) .. string.rep(" ", 5 - #tostring(currentEdit)))
- end
- elseif mcY == 8 and mButton == 1 then
- if mcX > 10 and mcX < 20 then --# Gate Address
- drawElement(11, 8, 1, 1, gray, black, addressBook[currentEdit].addr)
- local newGate = string.upper(readInput(11, 8, yellow, black, 9, true))
- if newGate ~= "" and newGate ~= "NIL" and (#newGate == 7 or #newGate == 9) then
- addressBook[currentEdit].addr = newGate
- if addressBook[currentEdit].name == "NEW GATE" or addressBook[currentEdit].name == "Name" then
- addressBook[currentEdit].name = newGate
- drawElement(11, 6, 1, 1, yellow, black, addressBook[currentEdit].name .. string.rep(" ", 9 - #addressBook[currentEdit].name))
- end
- gateChange = true
- end
- drawElement(11, 8, 1, 1, assignColor(currentEdit), black, addressBook[currentEdit].addr .. " ")
- end
- elseif mcY == 10 and mButton == 1 then --# Edit Gate Note
- if mcX > 7 and mcX < 8 + #addressBook[currentEdit].note:sub(1, 43) then
- drawElement(8, 10, 1, 1, gray, black, addressBook[currentEdit].note:sub(1, 43))
- local newNote = tostring(readInput(8, 10, white, black, 43))
- if newNote ~= "" and newNote ~= "nil" then
- addressBook[currentEdit].note = newNote
- gateChange = true
- end
- drawElement(8, 10, 1, 1, white, black, addressBook[currentEdit].note:sub(1, 43) .. string.rep(" ", 43 - #addressBook[currentEdit].note:sub(1, 43)))
- end
- elseif mcY == 12 and mButton == 1 then --# Edit Gate Rating/Classification
- if mcX > 17 and mcX < 18 + #assignRating(currentEdit) then
- drawRatingList(addressBook[currentEdit].rating)
- local selected = false
- while true do
- local _, mcButton, mX, mY = os.pullEvent("mouse_click")
- if mX > 17 and mX < 38 and mY > 5 and mY < 17 then
- local gRatings = { "B", "H", "V", "M", "S", "C", "D", "U", }
- for i = 1, #gRatings do
- if mY == i + 7 then
- if addressBook[currentEdit].rating ~= gRatings[i] then
- addressBook[currentEdit].rating = gRatings[i]
- gateChange = true
- end
- selected = true
- break
- end
- end
- if selected then break end
- else
- break
- end
- end
- drawElement(18, 6, 20, 11, nil, black, "") --# clear rating popup
- if gateChange then
- drawElement((termX / 2) - 8, termY - 1, 6, 1, green, gray, "Save")
- end
- drawElement(11, 6, 1, 1, yellow, black, addressBook[currentEdit].name .. " ") --# clean up after the rating pop-up
- drawElement(11, 8, 1, 1, assignColor(currentEdit), nil, addressBook[currentEdit].addr .. " ")
- drawElement(18, 12, 1, 1, nil, nil, assignRating(currentEdit))
- drawElement(2, 14, 1, 1, gray, nil, "Dimension:")
- drawElement(12, 15, 2, 1, nil, nil, "x:")
- drawElement(25, 15, 2, 1, nil, nil, "y:")
- if addressBook[currentEdit].addr == thisGate or addressBook[currentEdit].addr == thisGate:sub(1, 7) then
- drawElement(termX / 2, 8, 1, 1, nil, nil, "< THIS GATE >")
- end
- drawElement(8, 10, 1, 1, white, nil, addressBook[currentEdit].note)
- drawElement(13, 14, 1, 1, yellow, nil, addressBook[currentEdit].loc.dim)
- drawElement(15, 15, 1, 1, silver, nil, addressBook[currentEdit].loc.x)
- drawElement(28, 15, 1, 1, nil, nil, addressBook[currentEdit].loc.y)
- drawElement(25, 6, 1, 1, gray, nil, "Iris:")
- if addressBook[currentEdit].iris == "none" then --# Iris control
- drawElement(31, 6, "mid")
- elseif addressBook[currentEdit].iris == "open" then
- drawElement(31, 6, true)
- elseif addressBook[currentEdit].iris == "close" then
- drawElement(31, 6, false)
- end
- end
- elseif mcY == 14 and mButton == 1 then --# Gate Dimension
- if mcX > 12 and mcX < 13 + #addressBook[currentEdit].loc.dim then
- drawElement(13, 14, 1, 1, gray, black, addressBook[currentEdit].loc.dim)
- local newDim = readInput(13, 14, yellow, black, 19)
- if newDim ~= "" and newDim ~= "nil" then
- addressBook[currentEdit].loc.dim = newDim
- drawElement(13, 14, 38, 1, yellow, black, "")
- gateChange = true
- end
- drawElement(13, 14, 1, 1, yellow, black, addressBook[currentEdit].loc.dim .. string.rep(" ", 19 - #addressBook[currentEdit].loc.dim))
- end
- elseif mcY == 15 and mButton == 1 then --# Gate X,Y,Z Coordinates
- if mcX > 14 and mcX < 15 + #tostring(addressBook[currentEdit].loc.x) then --# X coordinate
- local oldX = tostring(addressBook[currentEdit].loc.x)
- drawElement(15, 15, 1, 1, gray, black, oldX)
- local newX = tonumber(readInput(15, 15, silver, black, 9))
- if tostring(newX) ~= "" and newX ~= nil and newX ~= addressBook[currentEdit].loc.x then
- addressBook[currentEdit].loc.x = newX
- gateChange = true
- end
- drawElement(15, 15, 1, 1, silver, black, tostring(addressBook[currentEdit].loc.x) .. string.rep(" ", 9 - #tostring(addressBook[currentEdit].loc.x)))
- elseif mcX > 27 and mcX < 28 + #tostring(addressBook[currentEdit].loc.y) then --# Y coordinate
- local oldY = tostring(addressBook[currentEdit].loc.y)
- drawElement(28, 15, 1, 1, gray, black, oldY)
- local newY = tonumber(readInput(28, 15, silver, black, 9))
- if tostring(newY) ~= "" and newY ~= nil and newY ~= addressBook[currentEdit].loc.y then
- addressBook[currentEdit].loc.y = newY
- gateChange = true
- end
- drawElement(28, 15, 1, 1, silver, black, tostring(addressBook[currentEdit].loc.y) .. string.rep(" ", 9 - #tostring(addressBook[currentEdit].loc.y)))
- elseif mcX > 40 and mcX < 41 + #tostring(addressBook[currentEdit].loc.z) then --# Z coordinate
- local oldZ = tostring(addressBook[currentEdit].loc.z)
- drawElement(41, 15, 1, 1, gray, black, oldZ)
- local newZ = tonumber(readInput(41, 15, silver, black, 9))
- if tostring(newZ) ~= "" and newZ ~= nil and newZ ~= addressBook[currentEdit].loc.z then
- addressBook[currentEdit].loc.z = newZ
- gateChange = true
- end
- drawElement(41, 15, 1, 1, silver, black, tostring(addressBook[currentEdit].loc.z) .. string.rep(" ", 9 - #tostring(addressBook[currentEdit].loc.z)))
- end
- elseif mcY == (termY - 1) and mButton == 1 then --# Save Address Book
- if mcX > (termX / 2) - 9 and mcX < (termX / 2) - 3 and gateChange then
- flashChoice((termX / 2) - 8, termY - 1, white, green, " Save ")
- drawElement((termX / 2) - 8, termY - 1, 1, 1, silver, gray, " Save ")
- saveData(gateData, "gate")
- --return
- elseif mcX > termX / 2 and mcX < (termX / 2) + 7 then --# Exit View/Edit Screen
- runState = "Dial"
- flashChoice((termX / 2) + 1, termY - 1, white, red, " Close ")
- drawElement(2, 4, termX, termY, nil, black, "")
- drawCLI(true)
- return
- end
- end
- if gateChange then drawElement((termX / 2) - 8, termY - 1, 6, 1, green, gray, " Save ") end
- end
- end
- local function settingsChange()
- configChange = true
- drawElement(45, 4, 6, 1, lime, silver, " Save ")
- end
- local function editSettings()
- while true do
- local _, mButton, mcX, mcY = os.pullEvent("mouse_click")
- local cfgPos = { 5, 7, 9, 11, 13, 15 }
- local cfgSides = { "top", "bottom", "front", "back", "left", "right" }
- --# Close Settings (no save)
- if mcY == 2 and mcX > 44 and mButton == 1 then
- flashChoice(termX - 6, 2, white, red, " Close ")
- runState = "Dial"
- clearLowerScreen()
- drawCLI()
- return
- --# Save Settings
- elseif mcY == 4 and mcX > 44 and mButton == 1 and configChange then
- flashChoice(45, 4, white, green, " Save ")
- drawElement(45, 4, 1, 1, gray, silver, " Save ")
- saveData(settingsData, "cfg")
- configChange = false
- end
- --# Settings Column 1
- --# Change LOCKDOWN Password
- if mcY == 6 and mcX > 16 and mcX < 26 and mButton == 1 then
- runState = "newPassword"
- return
- --# Biolock ON/OFF
- elseif mcY == 10 and mcX > 21 and mcX < 26 and hardware.bio > 0 and mButton == 1 then
- dhdSettings.bio.lock = not dhdSettings.bio.lock
- drawElement(22, 10, dhdSettings.bio.lock)
- settingsChange()
- --# Bioscanner function (iris/lockdown)
- elseif mcY == 12 and mcX > 21 and mcX < 26 and hardware.bio > 0 and mButton == 1 then
- if dhdSettings.bio.func == "none" then
- dhdSettings.bio.func = "iris"
- drawElement(7, 12, 1, 1, green, black, "Iris ")
- drawElement(22, 12, true)
- elseif dhdSettings.bio.func == "iris" then
- dhdSettings.bio.func = "lock"
- drawElement(7, 12, 1, 1, red, black, "Lockdown ")
- drawElement(22, 12, false)
- elseif dhdSettings.bio.func == "lock" then
- dhdSettings.bio.func = "none"
- drawElement(7, 12, 1, 1, silver, black, "No Function")
- drawElement(22, 12, "MID")
- end
- settingsChange()
- --# Set Biolock login authorization level
- elseif mcY == 14 and mcX > 19 and mcX < 25 and hardware.bio > 0 and mButton == 1 then
- if dhdSettings.bio.auth ~= mcX - 19 then
- dhdSettings.bio.auth = mcX - 19
- drawElement(19, 14, 1, 1, gray, black, "|-----|")
- drawElement(19 + dhdSettings.bio.auth, 14, 1, 1, black, silver, tostring(dhdSettings.bio.auth))
- settingsChange()
- end
- --# Set Biolock iris/lockdown authorization level
- elseif mcY == 16 and mcX > 19 and mcX < 25 and hardware.bio > 0 and mButton == 1 then
- if dhdSettings.bio.fAuth ~= mcX - 19 then
- dhdSettings.bio.fAuth = mcX - 19
- drawElement(19, 16, 1, 1, gray, black, "|-----|")
- drawElement(19 + dhdSettings.bio.fAuth, 16, 1, 1, black, silver, tostring(dhdSettings.bio.fAuth))
- settingsChange()
- end
- --# Settings Column 2
- --# pSync ON/OFF for ccDialer
- elseif mcY == 6 and mcX > 45 and mcX < 50 and mButton == 1 then
- dhdSettings.pSync = not dhdSettings.pSync
- if dhdSettings.pSync then
- if not rednet.isOpen(hardware.modemSide) then
- rednet.open(hardware.modemSide)
- end
- drawElement(46, 6, 1, 1, nil, orange, " ") --# 'pSync initializing' switch position (orange)
- term.setBackgroundColor(gray)
- term.write(" ")
- drawElement(termX / 2 - 7, math.floor(termY / 2) - 2, 20, 1, white, blue, "pSync ")
- drawElement(termX / 2 - 7, math.floor(termY / 2) - 1, 20, 3, nil, silver, "Initializing...")
- rednet.host("pSync", thisGate)
- drawElement(termX / 2 - 7, math.floor(termY / 2) - 2, 20, 4, nil, black, "")
- drawSettingsUI()
- else
- rednet.unhost("pSync")
- drawElement(46, 6, false)
- end
- settingsChange()
- --# Highlight thisGate in Dial/Trim modes & on List monitor
- elseif mcY == 10 and mcX > 45 and mcX < 50 and mButton == 1 then
- dhdSettings.highlight = not dhdSettings.highlight
- drawElement(46, 10, dhdSettings.highlight)
- settingsChange()
- --# Call Logging (ON/OFF)
- elseif mcY == 12 and mcX > 45 and mcX < 50 and mButton == 1 then
- dhdSettings.logs = not dhdSettings.logs
- drawElement(46, 12, dhdSettings.logs)
- settingsChange()
- --# Startup Iris (CLOSED/OPEN)
- elseif mcY == 14 and mcX > 45 and mcX < 50 and mButton == 1 then
- dhdSettings.startIris = not dhdSettings.startIris
- drawElement(46, 14, dhdSettings.startIris)
- settingsChange()
- --# End Call Iris (CLOSED/OPEN)
- elseif mcY == 16 and mcX > 45 and mcX < 50 and mButton == 1 then
- dhdSettings.ecIris = not dhdSettings.ecIris
- drawElement(46, 16, dhdSettings.ecIris)
- settingsChange()
- end
- end
- end
- local function keyClick()
- while true do
- local _, evKey = os.pullEvent("key")
- if runState == "Dial" and evKey == 59 then --# HELP (F1)
- runState = "DHDhelp"
- drawHelpUI()
- return
- elseif runState == "DHDhelp" and evKey == 59 then
- flashChoice(termX - 6, 2, white, red, " Close ")
- runState = "Dial"
- clearLowerScreen()
- drawCLI()
- return
- elseif runState == "Dial" or runState == "Trim" then
- if evKey == 199 then --# HOME
- gatePage = 1
- drawAddressBook()
- drawNaviUI()
- elseif evKey == 207 then --# END
- gatePage = gatePages
- if gatePages > 1 then
- drawElement(2, 6, 39, 11, nil, black, "")
- end
- drawAddressBook()
- drawNaviUI()
- elseif evKey == 201 then --# pageUP
- gatePage = math.max(1, gatePage - 1)
- drawAddressBook()
- drawNaviUI()
- elseif evKey == 209 then --# pageDN
- gatePage = math.min(gatePage + 1, gatePages)
- if gatePage == gatePages and gatePages > 1 then
- drawElement(2, 6, 39, 11, nil, black, "")
- end
- drawAddressBook()
- drawNaviUI()
- end
- elseif runState == "logs" then
- if evKey == 199 then --# HOME
- logPage = 1
- drawLogScreen()
- elseif evKey == 207 then --# END
- logPage = logPages
- drawLogScreen()
- elseif evKey == 201 then --# pageUP
- logPage = math.max(1, logPage - 1)
- drawLogScreen()
- elseif evKey == 209 then --# pageDN
- logPage = math.min(logPage + 1, logPages)
- drawLogScreen()
- end
- end
- end
- end
- local function mClick()
- while true do
- local _, mButton, mcX, mcY = os.pullEvent("mouse_click")
- --# Menu & Menu Selections
- if menuState then
- if mcX > 1 and mcX < 12 then
- if mcY == 3 and mButton == 1 then
- flashChoice(3, 3, white, sky, "Settings ")
- runState = "DHDsettings"
- menuState = false
- clearLowerScreen()
- drawSettingsUI()
- return
- elseif mcY == 5 and mButton == 1 then
- flashChoice(3, 5, black, yellow, "View Logs")
- runState = "logs"
- menuState = false
- ingestData("logs")
- clearLowerScreen()
- drawHeader()
- drawLogScreen()
- return
- elseif mcY == 7 and mButton == 1 then
- flashChoice(3, 7, white, cyan, "DHD Help ")
- runState = "DHDhelp"
- menuState = false
- drawHelpUI()
- return
- elseif mcY == 9 and mButton == 1 then
- flashChoice(3, 9, white, red, " EXIT ")
- if gateChange or configChange then
- runState = "exodus"
- menuState = false
- drawElement(2, 5, 11, 6, nil, black, "") --# clear menu
- drawHeader()
- drawAddressBook()
- drawPopUp()
- return
- else
- kernelState = false
- menuState = false
- break --# required to exit properly
- end
- elseif mcY < 2 or mcY > 10 then
- menuState = false
- drawElement(2, 5, 11, 6, nil, black, "") --# clear menu
- drawHeader()
- drawAddressBook()
- --return
- end
- else
- menuState = false
- drawElement(2, 5, 11, 6, nil, black, "") --# clear menu
- drawHeader()
- drawAddressBook()
- --return
- end
- else
- if runState == "DHDhelp" then --# DHD Help Screen
- if mcX > 44 and mcY == 2 and mButton == 1 then
- flashChoice(termX - 6, 2, white, red, " Close ")
- runState = "Dial"
- clearLowerScreen()
- drawCLI()
- return
- end
- elseif runState == "logs" then --# Log Screen
- if mcX > 44 and mcY == 2 and mButton == 1 then
- flashChoice(termX - 6, 2, white, red, " Close ")
- runState = "Dial"
- clearCallHistory()
- lastCall = nil
- clearLowerScreen()
- drawCLI()
- return
- elseif mcX > 44 and mcY == 4 and mButton == 1 then
- flashChoice(termX - 6, 4, white, orange, " Clear ")
- drawElement(termX - 6, 4, 1, 1, orange, silver, " Clear ")
- runState = "clearLogs"
- return
- elseif mcY == termY and mButton == 1 then
- if mcX > 11 and mcX < 14 then --# Home
- logPage = 1
- drawLogScreen()
- elseif mcX > 14 and mcX < 16 then --# PageBack
- logPage = math.max(1, logPage - 1)
- drawLogScreen()
- elseif mcX > 18 and mcX < 33 then --# Page Entry
- flashChoice(math.floor((termX / 2) - 3 - math.floor((#tostring(logPage) + #tostring(logPages)) / 2)), termY, gray, silver, " " .. tostring(logPage) .. " of " .. tostring(logPages) .. " ")
- drawElement(math.floor((termX / 2) - 3 - math.floor((#tostring(logPage) + #tostring(logPages)) / 2)), termY, 1, 1, silver, gray, " " .. tostring(logPage) .. " of " .. tostring(logPages) .. " ")
- runState = "goLogPage"
- drawPopUp()
- return
- elseif mcX > 35 and mcX < 37 then --# PageForward
- logPage = math.min(logPage + 1, logPages)
- drawLogScreen()
- elseif mcX > 37 and mcX < 40 then --# End
- logPage = logPages
- drawLogScreen()
- end
- elseif mcY == 3 and mcX > 30 and mcX < 40 then --# last call
- local callAddress = lastCall:sub(string.find(lastCall, ">") + 2, #lastCall)
- if mButton == 1 and (#callAddress == 7 or #callAddress == 9) then
- runState = "Dial"
- clearCallHistory()
- lastCall = nil
- netSend(callAddress)
- clearLowerScreen()
- drawCLI()
- return
- elseif mButton == 2 then
- runState = "GateEdit"
- addNewAddress(callAddress)
- return
- end
- elseif mcY > 5 and mcY < termY - 2 and mcX > 30 and mcX < 40 then --# call log
- local currentEntry = ((logPage - 1) * 11) + 1 --# Set the first entry (based on page number)
- if callHistory[currentEntry + mcY - 6] then
- local callAddress = callHistory[currentEntry + mcY - 6]:sub(string.find(callHistory[currentEntry + mcY - 6], ">") + 2, #callHistory[currentEntry + mcY - 6])
- if mButton == 1 and (#callAddress == 7 or #callAddress == 9) then
- runState = "Dial"
- clearCallHistory()
- lastCall = nil
- netSend(callAddress)
- clearLowerScreen()
- drawCLI()
- return
- elseif mButton == 2 and (#callAddress == 7 or #callAddress == 9) then
- runState = "GateEdit"
- addNewAddress(callAddress)
- return
- end
- end
- end
- elseif runState == "Dial" then --# Open Menu
- if mcY == 1 and mcX > 1 and mcX < 7 and mButton == 1 then
- drawMenu()
- --return
- end
- end
- --# Command Buttons (change modes, mode operation)
- if mcX > 42 and (runState == "Dial" or runState == "Trim") and secureStatus == "allclear" then
- if mcY == 7 and mButton == 1 and runState == "Dial" then
- if not irisState then
- drawWaitingIrisState()
- netSend("iCLOSE")
- waitingForIris = true
- elseif irisState and secureStatus == "allclear" then
- drawWaitingIrisState(true)
- netSend("iOPEN")
- waitingForIris = true
- end
- elseif mcY == 9 and mButton == 1 and runState == "Dial" then
- if gateStatus == "Connected" or gateStatus == "Dialing" then
- flashChoice(43, 9, orange, black, "END Call ")
- drawElement(43, 9, 1, 1, black, orange, "END Call ")
- netSend("endCall")
- end
- elseif mcY == 11 and mButton == 1 then
- if runState == "Dial" then
- flashChoice(43, 11, red, orange, "LOCKDOWN ")
- drawElement(43, 11, 1, 1, orange, red, "LOCKDOWN ")
- netSend("lockdown")
- secureStatus = "lockdown"
- oldOsPullEvent = os.pullEvent
- os.pullEvent = os.pullEventRaw
- return
- elseif runState == "Trim" and gateChange then
- flashChoice(43, 11, blue, white, "Reload ") --# Undo/Reload
- drawElement(43, 11, 1, 1, gray, sky, "Reload ")
- drawElement(43, 13, 1, 1, nil, green, "Save ")
- ingestData(gateData, "gate")
- gatePage = math.min(gatePage, gatePages)
- drawElement(2, 6, 39, 11, nil, black, "")
- gateChange = false
- drawAddressBook()
- drawNaviUI()
- if displayState == "info" then displayState = "list" end
- displayAddressBook()
- displayMarquee()
- end
- elseif mcY == 13 then
- if runState == "Dial" then
- if mButton == 1 then
- flashChoice(43, 13, blue, white, "AddrBook ")
- drawElement(43, 13, 1, 1, gateChange and lime or white, blue, "AddrBook ")
- runState = "importExport"
- drawPopUp()
- return
- elseif mButton == 2 and gateChange then
- flashChoice(43, 13, blue, white, "AddrBook ")
- drawElement(43, 13, 1, 1, white, blue, "AddrBook ")
- saveData(gateData, "gate")
- end
- elseif runState == "Trim" and mButton == 1 and gateChange then
- flashChoice(43, 13, green, white, "Save ") --# Commit/Save
- drawElement(43, 11, 1, 1, gray, sky, "Reload ")
- drawElement(43, 13, 1, 1, nil, green, "Save ")
- saveData(gateData, "gate")
- end
- elseif mcY == 15 then
- if runState == "Dial" then
- if mButton == 1 then
- flashChoice(43, 15, green, white, "New Gate ")
- runState = "GateEdit"
- addNewAddress()
- return
- elseif mButton == 3 then
- flashChoice(43, 15, green, white, "New Gate ")
- drawElement(43, 15, 1, 1, white, green, "New Gate ")
- drawElement(43, 13, 1, 1, lime, blue, "AddrBook ")
- addNewAddress(nil, true)
- end
- elseif runState == "Trim" and mButton == 1 then
- flashChoice(43, 15, red, white, "Close ") --# Close/Exit Trim
- runState = "Dial"
- drawCLI()
- return
- end
- end
- end
- end
- --# Page Navigation via click
- if mcY == termY and mButton == 1 and secureStatus == "allclear" then
- if runState == "Dial" or runState == "Trim" then
- if mcX > 9 and mcX < 12 and mcY == termY then --# Home
- gatePage = 1
- drawAddressBook()
- drawNaviUI()
- elseif mcX > 12 and mcX < 14 and mcY == termY then --# Back
- if gatePage > 1 then
- gatePage = math.max(1, gatePage - 1)
- drawAddressBook()
- drawNaviUI()
- end
- elseif mcX > 16 and mcX < 25 and mcY == termY then --# Page Numbers (Go To Page dialogue)
- flashChoice(((termX / 2) - 3) - (#pNum / 2) - 2, termY, black, gray, " " .. pNum .. " ")
- drawElement(((termX / 2) - 3) - (#pNum / 2) - 2, termY, #pNum, 1, gray, black, " " .. pNum .. " ")
- runState = runState == "Dial" and "goPage" or "goTrimPage"
- drawPopUp()
- return
- elseif mcX > 27 and mcX < 29 and mcY == termY then --# Forward
- if gatePage < gatePages then
- gatePage = math.min(gatePage + 1, gatePages)
- if gatePage == gatePages and gatePages > 1 then drawElement(2, 6, 39, 11, nil, black, "") end
- drawAddressBook()
- drawNaviUI()
- end
- elseif mcX > 29 and mcX < 32 and mcY == termY then --# End
- gatePage = gatePages
- if gatePages > 1 then drawElement(2, 6, 39, 11, nil, black, "") end
- drawAddressBook()
- drawNaviUI()
- end
- end
- end
- --# Dial a listed address, view it's info, or enter trim mode & delete gates
- if not menuState and (runState == "Dial" or runState == "Trim") and secureStatus == "allclear" then
- if mcX > 1 and mcX < 41 and mcY > 5 and mcY < 17 then
- local magicNumber = ((gatePage - 1) * 23) + gatePage
- local xPos, yPos = 2, 6
- for i = magicNumber, #addressBook do
- if mcX >= xPos and mcX <= xPos + 8 and mcY == yPos then
- if runState == "Dial" then
- if mButton == 1 and gateStatus == "Disconnected" then
- if (#addressBook[i].addr == 9 and addressBook[i].addr == thisGate) or (#addressBook[i].addr == 7 and addressBook[i].addr == thisGate:sub(1, 7)) then
- --# do nothing
- else
- flashDial(addressBook[i].name, xPos, mcY, i)
- dialAddress = addressBook[i].addr
- netSend(dialAddress)
- end
- elseif mButton == 2 then
- flashDial(addressBook[i].name, xPos, mcY, i)
- runState = "GateEdit"
- currentEdit = i
- drawGateLabels()
- return
- elseif mButton == 3 then
- runState = "Trim"
- drawCLI()
- return
- end
- elseif runState == "Trim" and mButton == 1 then
- deleteGate(i)
- if displayState == "info" then displayState = "list" end
- displayAddressBook()
- displayMarquee()
- drawAddressBook()
- drawNaviUI()
- end
- end
- yPos = yPos + 2
- if yPos > 16 then yPos = 6 xPos = xPos + 10 end
- if xPos > 32 then break end
- end
- end
- end
- end
- end
- local function mScroll()
- while true do
- local _, data = os.pullEvent("mouse_scroll")
- if runState == "Dial" or runState == "Trim" then
- if data == -1 and gatePage > 1 then
- gatePage = gatePage - 1
- if menuState then
- drawElement(2, 2, 10, 11, nil, black, "")
- menuState = false
- drawHeader()
- end
- drawAddressBook()
- drawNaviUI()
- elseif data == 1 and gatePage < gatePages then
- gatePage = gatePage + 1
- local doHeader = false
- if menuState then
- drawElement(2, 2, 10, 11, nil, black, "")
- menuState = false
- doHeader = true
- end
- if gatePage == gatePages and gatePages > 1 then
- drawElement(2, 6, 39, 11, nil, black, "")
- doHeader = true
- end
- if doHeader then drawHeader() end
- drawAddressBook()
- drawNaviUI()
- end
- elseif runState == "GateEdit" then
- currentEdit = data == 1 and math.min(currentEdit + 1, #addressBook) or math.max(1, currentEdit - 1)
- if gettingInput then
- term.setCursorBlink(false)
- gettingInput = false
- end
- drawGateData()
- elseif runState == "logs" then
- logPage = data == 1 and math.min(logPage + 1, logPages) or math.max(1, logPage - 1)
- drawLogScreen()
- end
- end
- end
- local function monTouch()
- while true do
- local _, monitor, touchX, touchY = os.pullEvent("monitor_touch")
- if secureStatus == "allclear" then
- local match = false
- for i = 1, #listMonSides do
- if monitor == listMonSides[i] then match = true break end
- end
- if match and displayState == "info" then
- displayState = "list"
- drawCLI(true)
- elseif match and displayState == "list" then
- if touchY < 9 then
- if (listPage - 1) * 8 + touchY <= #addressBook then
- selectedGate = (listPage - 1) * 8 + touchY
- displayState = "info"
- if hardware.marquee > 0 then displayNotes(selectedGate) end
- end
- elseif touchY > 8 then
- if touchX < 10 then
- listPage = math.max(1, listPage - 1)
- displayAddressBook()
- elseif touchX > 9 then
- listPage = math.min(listPage + 1, listPages)
- displayAddressBook()
- end
- end
- end
- end
- local match = false
- for i = 1, #marqueeSides do
- if monitor == marqueeSides[i] then match = true break end
- end
- if match and displayState == "info" and gateStatus == "Disconnected" and secureStatus == "allclear" then
- if #addressBook[selectedGate].addr == 9 and addressBook[selectedGate].addr ~= thisGate then
- dialAddress = addressBook[selectedGate].addr
- netSend(dialAddress)
- elseif #addressBook[selectedGate].addr == 7 and addressBook[selectedGate].addr ~= thisGate:sub(1, 7) then
- dialAddress = addressBook[selectedGate].addr
- netSend(dialAddress)
- end
- elseif match and gateStatus ~= "Disconnected" then
- netSend("endCall")
- end
- end
- end
- local function bioScan() -- "biolock", IDprint, attachSide, learnedName, accessLevel
- while true do
- local fistPrint = { os.pullEvent("biolock") }
- if fistPrint[1] == "biolock" then --# this is here because ^T otherwise causes an error 8 lines down during lockdown
- if runState == "init" then
- if fistPrint[5] >= dhdSettings.bio.auth then
- fistAuth = true
- return fistAuth
- end
- return false
- else
- if fistPrint[5] >= dhdSettings.bio.fAuth then
- if dhdSettings.bio.func == "iris" then
- if not irisState then
- if runState == "Dial" or runState == "goPage" or runState == "importExport" or runState == "exodus" then
- drawWaitingIrisState()
- if gettingInput then redrawInput() end
- end
- netSend("iCLOSE")
- waitingForIris = true
- elseif irisState and secureStatus == "allclear" then
- if runState == "Dial" or runState == "goPage" or runState == "importExport" or runState == "exodus" then
- drawWaitingIrisState(true)
- if gettingInput then redrawInput() end
- end
- netSend("iOPEN")
- waitingForIris = true
- end
- elseif dhdSettings.bio.func == "lock" then
- if secureStatus == "allclear" then
- local states = {
- Dial = "Dial";
- Trim = "Trim";
- GateEdit = "GateEdit";
- DHDhelp = "DHDhelp";
- DHDsettings = "DHDsettings";
- logs = "logs";
- goPage = "Dial",
- importExport = "Dial",
- exodus = "Dial",
- goTrimPage = "Trim",
- newPassword = "DHDsettings",
- clearLogs = "logs",
- goLogPage = "logs",
- }
- runState = states[runState]
- menuState = false
- if gettingInput then
- gettingInput = false
- term.setCursorBlink(false)
- end
- netSend("lockdown")
- secureStatus = "lockdown"
- oldOsPullEvent = os.pullEvent
- os.pullEvent = os.pullEventRaw
- clearLowerScreen()
- drawSecureUI()
- return --# doing this will cycle dhdKernel
- else
- netSend("allclear")
- secureStatus = "allclear"
- drawElement(15, 9, termX - 14, 1, nil, black, "") --# clear !!LOCKDOWN!!
- drawElement(15, 15, termX - 14, 1, nil, nil, "") --# clear password input
- os.pullEvent = oldOsPullEvent
- oldOsPullEvent = nil
- term.setCursorBlink(false)
- gettingInput = false
- waitingForIris = true
- if displayState == "list" then
- displayStatus()
- displayAddressBook()
- else
- displayNotes(selectedGate)
- end
- local states = {
- Dial = function() end;
- Trim = function() end;
- GateEdit = function() drawGateLabels() end,
- logs = function() drawHeader() drawLogScreen() end,
- DHDsettings = function() drawSettingsUI() end,
- DHDhelp = function() drawHelpUI() end,
- }
- states[runState]()
- return --# doing this will cycle dhdKernel
- end
- end
- end
- end
- end
- end
- end
- local function bioAnimation() --# not using drawElement intentionally for performance
- while true do
- for i = 2, 20 do
- term.setCursorPos(i, 4)
- term.setBackgroundColor(blue)
- term.write(" ")
- term.setBackgroundColor(black)
- term.setCursorPos(i - 1, 4)
- term.write(" ")
- sleep(0.04)
- end
- for i = 20, 2, -1 do
- term.setCursorPos(i, 4)
- term.setBackgroundColor(blue)
- term.write(" ")
- term.setBackgroundColor(black)
- term.setCursorPos(i + 1, 4)
- term.write(" ")
- sleep(0.04)
- end
- end
- end
- local function bioLogin()
- if hardware.bio == 0 then return end
- oldOsPullEvent = os.pullEvent
- os.pullEvent = os.pullEventRaw
- fistAuth = false
- clearScreen()
- drawElement(2, 2, 19, 1, yellow, nil, "Waiting for Bioscan")
- if hardware.listMon > 0 then
- for i = 1, hardware.listMon do
- listMon[i].setBackgroundColor(black)
- listMon[i].clear()
- listMon[i].setTextColor(yellow)
- listMon[i].setTextScale(1)
- listMon[i].setCursorPos(1, 2)
- listMon[i].write("Waiting")
- listMon[i].setCursorPos(3, 3)
- listMon[i].write("for")
- listMon[i].setCursorPos(1, 4)
- listMon[i].write("Bioscan")
- end
- end
- while true do
- parallel.waitForAny(bioScan, bioAnimation)
- if fistAuth then
- if oldOsPullEvent then
- os.pullEvent = oldOsPullEvent
- oldOsPullEvent = nil
- end
- return
- end
- end
- end
- do
- local states = {
- Dial = function() end;
- Trim = function() end;
- GateEdit = function() drawGateLabels() end,
- logs = function() drawHeader() drawLogScreen() end,
- DHDsettings = function() drawSettingsUI() end,
- DHDhelp = function() drawHelpUI() end,
- }
- secKernel = function() --# LOCKDOWN handler
- repeat
- local securePass = readInput(termX / 2, 15, yellow, black, 12)
- if securePass == dhdSettings.password then
- netSend("allclear")
- secureStatus = "allclear"
- drawElement(15, 9, termX - 14, 1, nil, nil, "") --# clear !!LOCKDOWN!!
- drawElement(15, 15, termX - 14, 1, nil, nil, "") --# clear password area
- if oldOsPullEvent then os.pullEvent = oldOsPullEvent end
- oldOsPullEvent = nil
- waitingForIris = true
- if displayState == "list" then
- displayStatus()
- displayAddressBook()
- else
- displayNotes(selectedGate)
- end
- states[runState]()
- end
- until secureStatus == "allclear"
- end
- end
- local function dhdKernel()
- repeat
- if kernelState and secureStatus == "lockdown" then
- parallel.waitForAny(secKernel, bioScan, monTouch, netReceive)
- elseif kernelState and secureStatus == "allclear" then
- if runState == "Dial" or runState == "Trim" or runState == "DHDhelp" or runState == "logs" then
- parallel.waitForAny(mClick, mScroll, keyClick, bioScan, monTouch, netReceive)
- elseif runState == "DHDsettings" then
- parallel.waitForAny(editSettings, bioScan, monTouch, netReceive)
- elseif runState == "clearLogs" then
- parallel.waitForAny(clearLogsPopUp, bioScan, monTouch, netReceive)
- elseif runState == "importExport" then
- parallel.waitForAny(importExportPopUp, bioScan, monTouch, netReceive)
- elseif runState == "goPage" or runState == "goTrimPage" then
- parallel.waitForAny(goToPage, bioScan, monTouch, netReceive)
- elseif runState == "goLogPage" then
- parallel.waitForAny(goToLogPage, bioScan, monTouch, netReceive)
- elseif runState == "newPassword" then
- parallel.waitForAny(changeLockdownPassword, bioScan, monTouch, netReceive)
- elseif runState == "GateEdit" then
- parallel.waitForAny(editGate, mScroll, bioScan, monTouch, netReceive)
- elseif runState == "exodus" then
- parallel.waitForAny(saveAndQuitPopUp, bioScan, monTouch, netReceive)
- end
- end
- until not kernelState
- end
- local function missingComponent(id)
- clearScreen()
- if id == "modem" then
- drawElement(2, 2, 1, 1, red, black, "No wireless modem detected!")
- drawElement(2, 4, 1, 1, gray, nil, "ccDHD REQUIRES a wireless modem.")
- end
- term.setCursorPos(1, 8)
- kernelState = false
- return false
- end
- local function addMonitor(attachName)
- peripheral.call(attachName, "setTextScale", 1)
- local monX = peripheral.call(attachName, "getSize")
- if monX == 7 then
- hardware.listMon = hardware.listMon + 1
- listMon[hardware.listMon] = peripheral.wrap(attachName)
- listMonSides[hardware.listMon] = attachName
- elseif monX == 29 then
- hardware.marquee = hardware.marquee + 1
- marquee[hardware.marquee] = peripheral.wrap(attachName)
- marqueeSides[hardware.marquee] = attachName
- end
- end
- local function detectHardware(hwType, firstRunNow)
- if hwType == "bio" then
- hardware.bio = 0
- local tempBio = { peripheral.find("biolock") }
- hardware.bio = #tempBio
- if hardware.bio > 0 then
- drawElement(16, 8, 1, 1, green, gray, "O")
- else
- drawElement(16, 8, 1, 1, red, nil, "0")
- dhdSettings.bio.lock = false --# This accounts for a scanner removed between sessions
- end
- return
- elseif hwType == "modem" then
- hardware.modemSide = "none"
- for _, side in ipairs(rs.getSides()) do
- if peripheral.isPresent(side) and peripheral.getType(side) == "modem" and peripheral.call(side, "isWireless") then
- hardware.modemSide = side
- rednet.open(hardware.modemSide)
- if runState == "init" and not firstRunNow then
- drawElement(16, 6, 1, 1, green, gray, "O") --# Hardware Discovery complete
- drawElement(16, 9, 1, 1, nil, nil, "O") --# WiFi
- end
- break
- end
- end
- return
- elseif hwType == "mon" then
- hardware.listMon = 0
- hardware.marquee = 0
- for _, side in ipairs(rs.getSides()) do
- if peripheral.isPresent(side) then
- if peripheral.getType(side) == "monitor" and peripheral.call(side, "isColor") then
- addMonitor(side)
- elseif peripheral.getType(side) == "modem" and not peripheral.call(side, "isWireless") then
- local mPerps = peripheral.call(side, "getNamesRemote")
- for _, name in ipairs(mPerps) do
- if name:sub(1, 7) == "monitor" and peripheral.call(name, "isColor") then
- addMonitor(name)
- end
- end
- end
- end
- end
- end
- end
- local function waitingAnimation() --# intentionally not using drawElement - less expense
- while true do
- for i = 9, 25 do
- term.setCursorPos(i, 5)
- term.setBackgroundColor(cyan)
- term.write(" ")
- term.setBackgroundColor(black)
- term.setCursorPos(i - 1, 5)
- term.write(" ")
- sleep(0.04)
- end
- for i = 25, 9, -1 do
- term.setCursorPos(i, 5)
- term.setBackgroundColor(cyan)
- term.write(" ")
- term.setBackgroundColor(black)
- term.setCursorPos(i + 1, 5)
- term.write(" ")
- sleep(0.04)
- end
- end
- end
- local function waitingNet()
- while true do
- local gateLiaison = rednet.lookup("ccDHDSetup")
- if gateLiaison then
- dhdSettings.gate = gateLiaison
- netSend("1stRun")
- while true do
- local id, message = rednet.receive()
- if id == dhdSettings.gate and type(message) == "table" then
- if message.program == "ccDHD" then
- thisGate = message.thisGate
- return
- end
- end
- end
- else
- sleep(1)
- end
- end
- end
- local function firstRun()
- drawElement(2, 4, 1, 1, gray, black, "... waiting for gateLiaison ...")
- parallel.waitForAny(waitingNet, waitingAnimation)
- --# Check and, if necessary, set computer label
- local ccLabel = os.getComputerLabel()
- if ccLabel == nil or tostring(ccLabel) == "" or ccLabel == "DHD" then
- os.setComputerLabel(thisGate .. " DHD")
- end
- clearScreen()
- saveData(settingsData, "cfg")
- return true
- end
- local function initMe()
- clearScreen()
- local firstRunNow = false
- if not fs.exists(settingsData) then
- if not fs.exists("/data") then fs.makeDir("/data") end
- firstRunNow = true
- detectHardware("modem", true)
- if hardware.modemSide == "none" then return missingComponent("modem") end
- if not firstRun() then return false end
- end
- drawElement(15, 4, 22, 1, white, blue, "ccDHD Initializing")
- drawElement(15, 5, 22, 10, nil, gray, "")
- drawElement(18, 6, 1, 1, silver, nil, "Hardware Discovery")
- drawElement(18, 7, 1, 1, nil, nil, "Monitors")
- drawElement(18, 8, 1, 1, nil, nil, "Biometric Scanner")
- drawElement(18, 9, 1, 1, nil, nil, "Wireless Modem")
- drawElement(18, 10, 1, 1, nil, nil, "Query gateLiaison")
- drawElement(18, 11, 1, 1, nil, nil, "Await response")
- drawElement(18, 12, 1, 1, nil, nil, "Host pSync")
- drawElement(18, 13, 1, 1, nil, nil, "Ingest gate data")
- drawElement(16, 6, 1, 1, red, nil, "0") --# Hardware Discovery
- drawElement(16, 7, 1, 1, nil, nil, "0") --# Monitors
- drawElement(16, 8, 1, 1, nil, nil, "0") --# Biolocks
- drawElement(16, 9, 1, 1, nil, nil, "0") --# WiFi
- drawElement(16, 10, 1, 1, nil, nil, "0") --# Query gateLiaison
- drawElement(16, 11, 1, 1, nil, nil, "0") --# Await response
- drawElement(16, 12, 1, 1, nil, nil, "0") --# Host pSync
- drawElement(16, 13, 1, 1, nil, nil, "0") --# Ingest gate data
- if not firstRunNow then ingestData(settingsData, "cfg") end
- drawElement(18, 6, 1, 1, white, nil, "Hardware Discovery")
- drawElement(18, 7, 1, 1, nil, nil, "Monitors")
- drawElement(16, 6, 1, 1, orange, nil, "0") --# Hardware Discovery
- drawElement(16, 7, 1, 1, nil, nil, "0") --# Monitors
- detectHardware("mon")
- if hardware.listMon > 0 or hardware.marquee > 0 then
- drawElement(16, 7, 1, 1, green, nil, "O") --# Monitors
- else
- drawElement(16, 7, 1, 1, red, nil, "0")
- end
- if hardware.listMon > 0 then
- for i = 1, hardware.listMon do
- listMon[i].setBackgroundColor(white)
- listMon[i].setTextColor(black)
- listMon[i].clear()
- listMon[i].setTextScale(1)
- listMon[i].setCursorPos(1, 3)
- listMon[i].write("Init...")
- end
- end
- if hardware.marquee > 0 then
- for i = 1, hardware.marquee do
- marquee[i].setBackgroundColor(white)
- marquee[i].setTextColor(black)
- marquee[i].clear()
- marquee[i].setTextScale(2)
- marquee[i].setCursorPos(5, 1)
- marquee[i].write("ccDHD")
- marquee[i].setCursorPos(2, 2)
- marquee[i].write("Initializing")
- end
- end
- drawElement(16, 8, 1, 1, orange, nil, "0") --# Biolocks
- drawElement(18, 8, 1, 1, white, nil, "Biometric Scanner")
- detectHardware("bio")
- drawElement(18, 9, 1, 1, white, nil, "Wireless Modem")
- if firstRunNow then
- drawElement(16, 6, 1, 1, green, nil, "O") --# Hardware Discovery complete
- drawElement(16, 9, 1, 1, nil, nil, "O") --# WiFi
- else
- detectHardware("modem")
- end
- if hardware.modemSide == "none" then shutDown() return missingComponent("modem") end
- drawElement(16, 10, 1, 1, orange, nil, "0") --# Query gateLiaison
- drawElement(18, 10, 1, 1, white, nil, "Query gateLiaison")
- netSend("QRY")
- drawElement(16, 10, 1, 1, green, nil, "O") --# Query gateLiaison
- drawElement(16, 11, 1, 1, orange, nil, "0") --# Await response
- drawElement(18, 11, 1, 1, white, nil, "Await response")
- local missed = 0
- while true do
- local id, message = rednet.receive(1)
- if id == dhdSettings.gate then
- updateStatus(message)
- drawElement(16, 11, 1, 1, green, nil, "O") --# Await response
- break
- end
- missed = missed + 1
- if missed >= 10 then
- shutDown()
- clearScreen()
- drawElement(2, 2, 1, 1, red, nil, "Unable to locate gateLiaison")
- term.setCursorPos(1, 4)
- return false
- end
- end
- drawElement(18, 12, 1, 1, white, nil, "Host pSync")
- if dhdSettings.pSync then
- drawElement(16, 12, 1, 1, orange, nil, "0") --# Host pSync
- rednet.host("pSync", thisGate)
- drawElement(16, 12, 1, 1, green, nil, "O") --# Host pSync
- end
- drawElement(16, 13, 1, 1, orange, nil, "0") --# Ingest gate data
- drawElement(18, 13, 1, 1, white, nil, "Ingest gate data")
- if fs.exists(gateData) then
- ingestData(gateData, "gate")
- else
- if not fs.exists("/data") then fs.makeDir("/data") end
- addressBook[1].name = thisGate
- addressBook[1].addr = thisGate
- saveData(gateData, "gate")
- end
- drawElement(16, 13, 1, 1, green, nil, "O") --# Ingest gate data
- sleep(0.1)
- clearMonitors()
- if dhdSettings.bio.lock and hardware.bio > 0 then --# Bioscanner login
- bioLogin()
- end
- kernelState = true
- runState = "Dial"
- clearScreen()
- drawCLI(true)
- return true
- end
- if not initMe() then return end
- dhdKernel()
- shutDown()
- clearScreen()
- term.setTextColor(white)
- term.setCursorPos(1, 1)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement