Advertisement
HydrantHunter

ccDHD Lite 1.5

Jan 16th, 2015
483
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 64.93 KB | None | 0 0
  1. --[[  LanteaCraft  ]]--
  2. --[[  and SGCraft  ]]--
  3. --[[  ccDHD  Lite  ]]--
  4. --[[    by Dog     ]]--
  5. --[[     a k a     ]]--
  6. --[[ HydrantHunter ]]--
  7. --[[  pastebin:    ]]--
  8. --[[     W3AxUYJE  ]]--
  9. local ccDHDliteVer = "1.5.02"
  10. --[[
  11. Tested with/requires:
  12.   - Minecraft 1.7.10
  13.   - LanteaCraft-1.7.10-70 || SGCraft1.95-mc1.7.10
  14.   - ComputerCraft 1.73, 1.74, 1.75
  15.   - An advanced computer
  16.   - A stargate with a CC adapter
  17. ]]--
  18. local termX, termY = term.getSize()
  19. local gate, screen, currentGate, incomingAddress, assignColor, assignRating, drawRatingList, gateStateChange
  20. local kernelState, irisState, lcGate, gateChange, addrRedraw = false, false, false, false, false
  21. local gatePage, gatePages, logPage, logPages, chevronNumber = 1, 1, 1, 1, 0
  22. local callHistory, guiElements = { }, { }
  23. local addressBook = { { name = "NEW GATE", addr = "ADDRESS", rating = "U", iris = "none", note = "short note", loc = { x = 99999, y = 99999, z = 99999, dim = "Overworld", }, }, }
  24. local thisGate, gateStatus, gateTarget, cachedInput = "!!ERROR!!", "Idle", "No Target", ""
  25. local gateData, historyData = "/data/DHDgates", "/data/DHDhistory"
  26.  
  27. --# custom read function courtesy of theoriginalbit (modified by Dog)
  28. local function read( _mask, _history, _limit, _noTerminate, _noMouse, gField )
  29.   if _mask and type(_mask) ~= "string" then
  30.     error("Invalid parameter #1: Expected string, got "..type(_mask), 2)
  31.   end
  32.   if _history and type(_history) ~= "table" then
  33.     error("Invalid parameter #2: Expected table, got "..type(_history), 2)
  34.   end
  35.   if _limit and type(_limit) ~= "number" then
  36.     error("Invalid parameter #3: Expected number, got "..type(_limit), 2)
  37.   end
  38.   if _noTerminate and type(_noTerminate) ~= "boolean" then
  39.     error("Invalid argument #4: Expected boolean, got "..nativeType(_noTerminate), 2)
  40.   end
  41.   if _noMouse and type(_noMouse) ~= "boolean" then
  42.     error("Invalid argument #5: Expected boolean, got "..nativeType(_noMouse), 2)
  43.   end
  44.   if gField and type(gField) ~= "boolean" then
  45.     error("Invalid argument #6: Expected boolean, got "..nativeType(gField), 2)
  46.   end
  47.   term.setCursorBlink(true)
  48.   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 }
  49.   local input = ""
  50.   local pos = 0
  51.   local historyPos = nil
  52.   local pullEvent = _noTerminate and os.pullEventRaw or os.pullEvent
  53.   local sw, sh = term.getSize()
  54.   local sx, sy = term.getCursorPos()
  55.   local function redraw( _special )
  56.     local scroll = (sx + pos >= sw and (sx + pos) - sw or 0)
  57.     local replace = _special or _mask
  58.     local output = replace and (string.rep( replace, math.ceil(#input / #replace) - scroll )):sub(1, #input) or input:sub(scroll + 1)
  59.     term.setCursorPos( sx, sy )
  60.     term.write( output )
  61.     term.setCursorPos( sx + pos - scroll, sy )
  62.   end
  63.   local nativeScroll = term.scroll
  64.   term.scroll = function( _n ) local ok, err = pcall( function() return nativeScroll( _n ) end ) if ok then sy = sy - _n return err end error( err, 2 ) end
  65.   while true do
  66.     local event, code, mX, mY = pullEvent()
  67.     if event == "char" and (not _limit or #input < _limit) then
  68.       local goodData = false
  69.       if gField then
  70.         if symbols[code:upper()] then
  71.           goodData = true
  72.         end
  73.       else
  74.         goodData = true
  75.       end
  76.       if goodData then
  77.         input = input:sub(1, pos) .. code .. input:sub(pos + 1)
  78.         pos = pos + 1
  79.         cachedInput = input
  80.       end
  81.     elseif event == "paste" and (not _limit or #input < _limit) then
  82.       if _limit and #input + #code > _limit then
  83.         code = code:sub(1, _limit - #input)
  84.       end
  85.       if gField then
  86.         local newWord, glyph = { }, ""
  87.         for i = 1, #code do
  88.           glyph = string.upper(code:sub(i, i))
  89.           if symbols[glyph] then
  90.             newWord[i] = glyph
  91.           else
  92.             newWord[i] = "?"
  93.           end
  94.         end
  95.         code = table.concat(newWord)
  96.       end
  97.       input = input:sub(1, pos) .. code .. input:sub(pos + 1)
  98.       pos = pos + #code
  99.       cachedInput = input
  100.     elseif event == "key" then
  101.       if code == keys.enter or code == keys.numPadEnter then
  102.         cachedInput = ""
  103.         break
  104.       elseif code == keys.backspace and pos > 0 then
  105.         redraw(' ')
  106.         input = input:sub(1, math.max(pos - 1, 0))..input:sub(pos + 1)
  107.         pos = math.max(pos - 1, 0)
  108.         cachedInput = input
  109.       elseif code == keys.delete and pos < #input then
  110.         redraw(' ')
  111.         input = input:sub(1, pos)..input:sub(pos + 2)
  112.         cachedInput = input
  113.       elseif code == keys.home then
  114.         pos = 0
  115.       elseif code == keys["end"] then
  116.         pos = #input
  117.       elseif code == keys.left and pos > 0 then
  118.         pos = math.max(pos - 1, 0)
  119.       elseif code == keys.right and pos < #input then
  120.         pos = math.min(pos + 1, #input)
  121.       elseif _history and code == keys.up or code == keys.down then
  122.         redraw(' ')
  123.         if code == keys.up then
  124.           if not historyPos then
  125.             historyPos = #_history
  126.           elseif historyPos > 1 then
  127.             historyPos = historyPos - 1
  128.           end
  129.         else
  130.           if historyPos ~= nil and historyPos < #_history then
  131.             historyPos = math.max(historyPos + 1, #_history)
  132.           elseif historyPos == #_history then
  133.             historyPos = nil
  134.           end
  135.         end
  136.         if historyPos and #_history > 0 then
  137.           input = string.sub(_history[historyPos], 1, _limit) or ""
  138.           pos = #input
  139.           cachedInput = input
  140.         else
  141.           input = ""
  142.           pos = 0
  143.           cachedInput = input
  144.         end
  145.       end
  146.     elseif event == "mouse_click" and ((mX < sx or mX >= sx + _limit) or (mY ~= sy)) and not _noMouse then
  147.       cachedInput = ""
  148.       break
  149.     end
  150.     redraw(_mask)
  151.   end
  152.   term.scroll = nativeScroll
  153.   term.setCursorBlink(false)
  154.   if sy + 1 > sh then
  155.     term.scroll(sy + 1 - sh)
  156.     term.setCursorPos(1, sy)
  157.   else
  158.     term.setCursorPos(1, sy + 1)
  159.   end
  160.   return input
  161. end
  162.  
  163. --# newButton function courtesy of theoriginalbit (modified by Dog)
  164. local function newButton(x, y, w, h, text, bc, tc, action, name, mbtn, callback)
  165.   w = math.max(type(w) == "number" and w or 1, 1)
  166.   h = math.max(type(h) == "number" and h or 1, 1)
  167.   mbtn = (type(mbtn) == "number" and mbtn >= 1 and mbtn <= 3) and mbtn or 1
  168.   action = action or function() end
  169.   callback = type(callback) == "function" and callback or function() end
  170.   name = (type(name) == "string" and #name > 0) and name or "noName"
  171.   local hx = x + math.ceil((w - #text) / 2)
  172.   local hy = y + math.ceil(h / 2) - 1
  173.   local enabled = true
  174.   local dbc, dtc = colors.lightGray, colors.gray
  175.   return {
  176.     getType = function()
  177.       return "button"
  178.     end;
  179.     getName = function()
  180.       return name
  181.     end;
  182.     setDisabledColors = function(bc, tc)
  183.       dbc = bc
  184.       dtc = tc
  185.     end;
  186.     setText = function(t)
  187.       text = t or ""
  188.       hx = x + math.ceil((w - #text) / 2) --# recalculate offset
  189.     end;
  190.     setEnabled = function(e)
  191.       enabled = e == true
  192.     end;
  193.     render = function()
  194.       term.setBackgroundColor(enabled and bc or dbc)
  195.       term.setTextColor(enabled and tc or dtc)
  196.       for i = 0, h - 1 do
  197.         term.setCursorPos(x, y + i)
  198.         write(string.rep(' ', w))
  199.       end
  200.       term.setCursorPos(hx, hy)
  201.       write(text)
  202.     end;
  203.     processEvent = function(event, button, xPos, yPos)
  204.       if enabled and event == "mouse_click" and button == mbtn and
  205.         xPos >= x and xPos <= (x + w - 1) and
  206.         yPos >= y and yPos <= (y + h - 1) then
  207.         local modeSwitch = action()
  208.         --callback(name)
  209.         if modeSwitch then return true else return false end
  210.       end
  211.     end;
  212.   }
  213. end
  214.  
  215. local function saveData(fileName)
  216.   fileName = fileName or gateData
  217.   if fs.exists("/disk") and fileName == ("/disk/data/DHDgates") then
  218.     if not fs.exists("/disk/data") then fs.makeDir("/disk/data") end
  219.   end
  220.   local dhdData = fs.open(fileName, "w")
  221.   dhdData.write(textutils.serialize(addressBook))
  222.   if fileName == gateData then gateChange = false end
  223.   dhdData.close()
  224. end
  225.  
  226. local function ingestData(fileName)
  227.   if fileName == "logs" then
  228.     if fs.exists(historyData) then
  229.       for log_entry in io.lines(historyData) do
  230.         table.insert(callHistory, 1, log_entry)
  231.       end
  232.     end
  233.     logPage, logPages = 1, math.max(1, math.ceil(#callHistory / 11)) --# paginate call logs
  234.   else
  235.     fileName = fileName or gateData
  236.     if fs.exists(fileName) then
  237.       for i = #addressBook, 1, -1 do
  238.         addressBook[i] = nil
  239.       end
  240.       local dhdData = fs.open(fileName, "r")
  241.       addressBook = textutils.unserialize(dhdData.readAll())
  242.       dhdData.close()
  243.       gatePage, gatePages = 1, math.ceil(#addressBook / 21) --# paginate address book
  244.       for i = 1, #addressBook do
  245.         if not addressBook[i].iris then
  246.           addressBook[i].iris = "none"
  247.           saveAB = true
  248.         end
  249.       end
  250.       if saveAB and fileName == gateData then saveData(gateData) end
  251.       if fileName ~= gateData then gateChange = true end
  252.     end
  253.   end
  254. end
  255.  
  256. local function mergeData()                            --# merge two address books into one
  257.   if not fs.exists("/disk/data/DHDgates") then return end
  258.   local dhdData = fs.open("/disk/data/DHDgates", "r")
  259.   local newGates = textutils.unserialize(dhdData.readAll())
  260.   dhdData.close()
  261.   local matchFound = false                            --# use matchFound to indicate if a matching gate was found or not
  262.   for i = 1, #newGates do                             --# start cycling through the 'new' list of gates
  263.     for j = 1, #addressBook do                        --# search the address book for a matching address
  264.       if newGates[i].addr == addressBook[j].addr then --# if the gate is already in the address book...
  265.         matchFound = true                             --# ...set matchFound to true and...
  266.         break                                         --# stop the address book search loop and move on to the next gate in the 'new' list
  267.       end
  268.     end
  269.     if not matchFound then                            --# if a match wasn't found...
  270.       addressBook[#addressBook + 1] = { }             --# initialize a new address book entry
  271.       for k, v in pairs(newGates[i]) do               --# loop through the gate entries...
  272.         addressBook[#addressBook][k] = v              --# ...and add them to the new address book entry
  273.       end
  274.       gateChange = true                               --# indicate that address book data has changed
  275.     else
  276.       matchFound = false                              --# if a match was found, reset the variable for the next iteration of the loop
  277.     end
  278.   end
  279.   gatePages = math.ceil(#addressBook / 24)            --# repaginate gates
  280. end
  281.  
  282. local function recordSessionData()                     --# Human readable log files
  283.   local logAddress = gateTarget or "ERROR"             --# set logAddress
  284.   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
  285.   local callDirection = incomingAddress and "Inbound" or "Outbound" --# set callDirection
  286.   local tTime = textutils.formatTime(os.time(), false) --# format the time
  287.   if #tTime == 7 then tTime = " " .. tTime end         --# move single digit hour times to the right one space
  288.   local callArchive = fs.open(historyData, fs.exists(historyData) and "a" or "w")
  289.   callArchive.writeLine(tostring(os.day()) .. " @ " .. tTime .. " <" .. callDirection .. "> " .. logAddress)
  290.   callArchive.close()
  291. end
  292.  
  293. do
  294.   local colorBurst = {
  295.     B = { colors.blue, "Base/Outpost/Hub" },
  296.     H = { colors.lightBlue, "Home/Camp" },
  297.     V = { colors.brown, "Village" },
  298.     M = { colors.purple, "Misc/Special" },
  299.     S = { colors.green, "Safe/Secured" },
  300.     C = { colors.orange, "Caution" },
  301.     D = { colors.red, "Danger" },
  302.     U = { colors.lightGray, "Unknown/Unclassified" }
  303.   }
  304.  
  305.   assignColor = function(gateNumber)
  306.     return colorBurst[addressBook[gateNumber].rating][1]
  307.   end
  308.  
  309.   assignRating = function(gateNumber)
  310.     return colorBurst[addressBook[gateNumber].rating][2]
  311.   end
  312. end
  313.  
  314. local function clearCallHistory()
  315.   for i = #callHistory, 1, -1 do
  316.     callHistory[i] = nil
  317.   end
  318. end
  319.  
  320. local function clearScreen()
  321.   term.setBackgroundColor(colors.black)
  322.   term.clear()
  323. end
  324.  
  325. local function clearLowerScreen(bgColor)
  326.   --paintutils.drawFilledBox(1, 4, termX, termY, bgColor or colors.black)
  327.   term.setBackgroundColor(bgColor or colors.black)
  328.   local line = string.rep(" ", termX)
  329.   for i = 4, termY do                 --# clear the display area
  330.     term.setCursorPos(1, i)
  331.     term.write(line)
  332.   end
  333. end
  334.  
  335. local function clearDataArea(bgColor)
  336.   --paintutils.drawFilledBox(17, 5, termX, termY, bgColor or colors.black)
  337.   term.setBackgroundColor(bgColor or colors.black)
  338.   local line = string.rep(" ", 33)
  339.   for i = 5, termY - 1 do             --# clear the data area
  340.     term.setCursorPos(17, i)
  341.     term.write(line)
  342.   end
  343. end
  344.  
  345. local function clearABPopUp()
  346.   --paintutils.drawFilledBox(15, 10, 35, 17, colors.black)
  347.   term.setBackgroundColor(colors.black)
  348.   local line = string.rep(" ", 21)
  349.   for i = 10, 17 do
  350.     term.setCursorPos(15, i)
  351.     term.write(line)
  352.   end
  353. end
  354.  
  355. local function clearExodusPopUp()
  356.   --paintutils.drawFilledBox(20, 9, 38, 12, colors.black)
  357.   term.setBackgroundColor(colors.black)
  358.   local line = string.rep(" ", 19)
  359.   for i = 9, 12 do
  360.     term.setCursorPos(20, i)
  361.     term.write(line)
  362.   end
  363. end
  364.  
  365. local function clearPagePopUp(bgColor)
  366.   --paintuitls.drawFilledBox(screen == "main" and 29 or 22, termY - 3, screen == "main" and 37 or 30, termY - 1, bgColor or colors.black)
  367.   term.setBackgroundColor(bgColor or colors.black)
  368.   for i = 1, 3 do
  369.     term.setCursorPos(screen == "main" and 29 or 22, (termY - 4) + i)
  370.     term.write("        ")
  371.   end
  372. end
  373.  
  374. local function redrawInput()
  375.   term.setCursorPos(screen == "gatePage" and 31 or 24, termY - 2)
  376.   term.setBackgroundColor(colors.black)
  377.   term.setTextColor(colors.white)
  378.   term.write(cachedInput)
  379. end
  380.  
  381. local function highlightAddressButton()
  382.   term.setBackgroundColor(colors.blue)
  383.   term.setTextColor(colors.lime)
  384.   term.setCursorPos(2, 13)
  385.   term.write("Addr Book")
  386. end
  387.  
  388. local function drawIrisSwitch(switchPos)
  389.   term.setCursorPos(31, 5)
  390.   if switchPos == "none" then
  391.     term.setBackgroundColor(colors.green)
  392.     term.write(" ")
  393.     term.setBackgroundColor(colors.gray)
  394.     term.write("  ")
  395.     term.setBackgroundColor(colors.red)
  396.     term.write(" ")
  397.   elseif switchPos == "open" then
  398.     term.setBackgroundColor(colors.green)
  399.     term.write("  ")
  400.     term.setBackgroundColor(colors.gray)
  401.     term.write("  ")
  402.   elseif switchPos == "close" then
  403.     term.setBackgroundColor(colors.gray)
  404.     term.write("  ")
  405.     term.setBackgroundColor(colors.red)
  406.     term.write("  ")
  407.   end
  408.   term.setBackgroundColor(colors.black)
  409. end
  410.  
  411. local function drawClearLogsPopUp()
  412.   term.setBackgroundColor(colors.blue)
  413.   term.setTextColor(colors.white)
  414.   term.setCursorPos((termX / 2) - 5, math.floor(termY / 2) - 2)
  415.   term.write(" Clear Logs? ")
  416.   --paintutils.drawFilledBox((termX / 2) - 5, math.floor(termY / 2) - 1, (termX / 2) + 7, math.floor(termY /2 ) + 1, colors.gray)
  417.   term.setBackgroundColor(colors.gray)
  418.   local line = string.rep(" ", 13)
  419.   for i = math.floor(termY / 2) - 1, math.floor(termY / 2) + 1 do
  420.     term.setCursorPos((termX / 2) - 5, i)
  421.     term.write(line)
  422.   end
  423.   term.setBackgroundColor(colors.green)
  424.   term.setCursorPos((termX / 2) - 4, math.floor(termY / 2))
  425.   term.write(" YES ")
  426.   term.setBackgroundColor(colors.red)
  427.   term.setCursorPos((termX / 2) + 2, math.floor(termY / 2))
  428.   term.write(" N O ")
  429. end
  430.  
  431. local function drawExodusPopUp()
  432.   term.setBackgroundColor(colors.blue)
  433.   term.setTextColor(colors.white)
  434.   term.setCursorPos(20, 9)
  435.   term.write("  Save Addr Book?  ")
  436.   --paintutils.drawFilledBox(20, 10, 38, 12, colors.gray)
  437.   term.setBackgroundColor(colors.gray)
  438.   local line = string.rep(" ", 19)
  439.   for i = 10, 12 do
  440.     term.setCursorPos(20, i)
  441.     term.write(line)
  442.   end
  443.   term.setBackgroundColor(colors.green)
  444.   term.setCursorPos(22, 11)
  445.   term.write(" Save ")
  446.   term.setBackgroundColor(colors.orange)
  447.   term.setCursorPos(31, 11)
  448.   term.write(" Quit ")
  449. end
  450.  
  451. local function drawAddressBookManagementPopUp()
  452.   term.setBackgroundColor(colors.blue)
  453.   term.setTextColor(colors.white)
  454.   term.setCursorPos(16, 10)
  455.   term.write(" Address Book Mgt. ")
  456.   --paintutils.drawFilledBox(16, 11, 34, 17, colors.gray)
  457.   term.setBackgroundColor(colors.gray)
  458.   local line = string.rep(" ", 19)
  459.   for i = 11, 17 do
  460.     term.setCursorPos(16, i)
  461.     term.write(line)
  462.   end
  463.   for _, button in pairs(guiElements.addrBookMgt) do
  464.     if button.getName() == "ABSave" then
  465.       button.setEnabled(gateChange)
  466.     elseif button.getName() == "ABMerge" then
  467.       button.setEnabled(fs.exists("/disk/data/DHDgates"))
  468.     elseif button.getName() == "ABImport" then
  469.       button.setEnabled(fs.exists("/disk/data/DHDgates"))
  470.     elseif button.getName() == "ABExport" then
  471.       button.setEnabled(fs.exists("/disk"))
  472.     end
  473.     button.render()
  474.   end
  475. end
  476.  
  477. local function drawPagePopUp()
  478.   term.setBackgroundColor(colors.gray)
  479.   term.setTextColor(colors.white)
  480.   for i = 1, 3 do
  481.     term.setCursorPos(screen == "gatePage" and 29 or 22, termY - 4 + i)
  482.     term.write(i == 1 and " :Page: " or "        ")
  483.   end
  484.   term.setBackgroundColor(colors.black)
  485.   term.setCursorPos(screen == "gatePage" and 30 or 23, termY - 2)
  486.   term.write("      ")
  487. end
  488.  
  489. local function drawHeader()
  490.   term.setTextColor(colors.white)
  491.   local line = string.rep(" ", 48)
  492.   for i = 1, 3 do
  493.     term.setCursorPos(1, i)
  494.     term.setBackgroundColor(colors.blue)
  495.     term.write(line)
  496.     term.setBackgroundColor(colors.red)
  497.     term.write(i == 2 and " X " or "   ")
  498.   end
  499.   term.setBackgroundColor(colors.blue)
  500.   term.setTextColor(colors.lightBlue)
  501.   term.setCursorPos(22, 2)
  502.   term.write(thisGate)
  503. end
  504.  
  505. local function drawFooter()
  506.   term.setBackgroundColor(colors.gray)
  507.   term.setTextColor(colors.lightGray)
  508.   term.setCursorPos(screen == "main" and 13 or 1, termY)
  509.   term.write(string.rep(" ", screen == "main" and termX - 12 or termX))
  510.   local cX = screen == "main" and (math.ceil(termX / 2) - (#tostring(gatePage) + #tostring(gatePages) + 4) / 2) + 7 or (math.ceil(termX / 2) - (#tostring(logPage) + #tostring(logPages) + 4) / 2)
  511.   term.setCursorPos(cX, termY)
  512.   term.write(screen == "main" and (tostring(gatePage) .. " of " .. tostring(gatePages)) or (tostring(logPage) .. " of " .. tostring(logPages)))  
  513.   for _, button in pairs(screen == "main" and guiElements.mainFooter or guiElements.logButtons) do
  514.     button.render()
  515.   end
  516. end
  517.  
  518. local function drawHelpScreen()
  519.   clearLowerScreen(colors.white)
  520.   --paintutils.drawFilledBox(1, 4, 15, termY, colors.gray)
  521.   term.setBackgroundColor(colors.gray)
  522.   local line = string.rep(" ", 15)
  523.   for i = 4, termY do
  524.     term.setCursorPos(1, i)
  525.     term.write(line)
  526.   end
  527.   term.setTextColor(colors.black)
  528.   term.setCursorPos(2, 5)
  529.   term.write("Main Screen")
  530.   term.setCursorPos(2, 10)
  531.   term.write("Addr Book Btn")
  532.   term.setCursorPos(4, 12)
  533.   term.write("(popup)")
  534.   term.setCursorPos(2, 16)
  535.   term.write("Log Screen")
  536.   term.setTextColor(colors.lightGray)
  537.   term.setCursorPos(2, 6)
  538.   term.write("Left click")
  539.   term.setCursorPos(2, 7)
  540.   term.write("Right click")
  541.   term.setCursorPos(2, 8)
  542.   term.write("Middle click")
  543.   term.setCursorPos(2, 11)
  544.   term.write("Right click")
  545.   term.setCursorPos(2, 13)
  546.   term.write("Import/Export")
  547.   term.setCursorPos(2, 14)
  548.   term.write("Merge! Button")
  549.   term.setCursorPos(2, 17)
  550.   term.write("Left click")
  551.   term.setCursorPos(2, 18)
  552.   term.write("Right click")
  553.   term.setBackgroundColor(colors.white)
  554.   term.setTextColor(colors.gray)
  555.   term.setCursorPos(17, 6)
  556.   term.write("an address to dial")
  557.   term.setCursorPos(17, 7)
  558.   term.write("an address to view/edit")
  559.   term.setCursorPos(17, 8)
  560.   term.write("an address to delete")
  561.   term.setCursorPos(17, 11)
  562.   term.write("Save/update the Address Book")
  563.   term.setCursorPos(17, 13)
  564.   term.write("Copy Addr Book FROM/TO floppy disk")
  565.   term.setCursorPos(17, 14)
  566.   term.write("Import only new gates from floppy")
  567.   term.setCursorPos(17, 17)
  568.   term.write("an address to dial")
  569.   term.setCursorPos(17, 18)
  570.   term.write("an address to add to Address Book")
  571. end
  572.  
  573. local function drawLogScreen()
  574.   if logPage == logPages and logPages > 1 then
  575.     clearLowerScreen(colors.white)
  576.   end
  577.   if not callHistory[1] then
  578.     term.setCursorPos(2, 6)
  579.     term.setBackgroundColor(colors.white)
  580.     term.setTextColor(colors.gray)
  581.     term.write("No Logs")
  582.     for _, button in pairs(guiElements.logButtons) do
  583.       button.setEnabled(false)
  584.     end
  585.     return
  586.   end
  587.   term.setBackgroundColor(colors.gray)                              --#
  588.   term.setTextColor(colors.white)                                   --#
  589.   term.setCursorPos(1, 4)                                           --# Header
  590.   term.write(string.rep(" ", termX))                                --#
  591.   term.setCursorPos(1, 5)                                           --#
  592.   term.write(" Day    Time       Vector     Address              ") --#
  593.   for _, button in pairs(guiElements.logButtons) do
  594.     button.setEnabled(true)
  595.   end
  596.   drawFooter()
  597.   term.setBackgroundColor(colors.white)
  598.   local currentEntry = ((logPage - 1) * 11) + 1 --# Set the first entry to show (based on page number)
  599.   local spacer = string.rep(" ", 9)
  600.   for i = currentEntry, currentEntry + 10 do    --# Display logs
  601.     local callDir = callHistory[i]:sub(string.find(callHistory[i], "<") + 1, string.find(callHistory[i], ">") - 1)
  602.     term.setTextColor(callDir == "Inbound" and colors.gray or colors.lightGray)
  603.     term.setCursorPos(2, i - currentEntry + 7)  --# position entry
  604.     term.write(callHistory[i]:sub(1, string.find(callHistory[i], "@") - 2) .. " ") --# write day
  605.     term.setCursorPos(9, i - currentEntry + 7)  --# position entry
  606.     term.write(callHistory[i]:sub(string.find(callHistory[i], "@") + 2, string.find(callHistory[i], "M"))) --# write time
  607.     term.setCursorPos(20, i - currentEntry + 7) --# position entry
  608.     term.write(callDir .. " ")                  --# write direction
  609.     term.setCursorPos(31, i - currentEntry + 7) --# position entry
  610.     local callAddr = callHistory[i]:sub(string.find(callHistory[i], ">") + 2)      --# set address
  611.     term.setTextColor(callDir == "Inbound" and colors.cyan or colors.lightBlue)
  612.     term.write(callAddr .. spacer)              --# write address (and clear space for truncated entries)
  613.     if i >= #callHistory then break end         --# if we've reached the end of the log then stop the loop
  614.   end
  615. end
  616.  
  617. do
  618.   local ratings = {
  619.     [1] = { rating = "B", color = colors.blue, desc = "Base/Outpost/Hub" },
  620.     [2] = { rating = "H", color = colors.lightBlue, desc = "Home/Camp" },
  621.     [3] = { rating = "V", color = colors.brown, desc = "Village" },
  622.     [4] = { rating = "M", color = colors.purple, desc = "Misc/Special" },
  623.     [5] = { rating = "S", color = colors.green, desc = "Safe/Secured" },
  624.     [6] = { rating = "C", color = colors.orange, desc = "Caution" },
  625.     [7] = { rating = "D", color = colors.red, desc = "Danger" },
  626.     [8] = { rating = "U", color = colors.lightGray, desc = "Unk/Unclassified" },
  627.   }
  628.  
  629.   drawRatingList = function(gRating)
  630.     local rColor
  631.     term.setTextColor(colors.white)
  632.     term.setBackgroundColor(colors.blue)
  633.     term.setCursorPos(18, 6)
  634.     term.write("   Classification   ")
  635.     --paintutils.drawFilledBox(18, 7, 37, 16, colors.gray)
  636.     term.setBackgroundColor(colors.gray)
  637.     local line = string.rep(" ", 20)
  638.     for i = 7, 16 do    --# menu body
  639.       term.setCursorPos(18, i)
  640.       term.write(line)
  641.     end
  642.     for i = 1, #ratings do
  643.       if gRating == ratings[i].rating then
  644.         rColor = gRating == "U" and colors.white or ratings[i].color
  645.         term.setBackgroundColor(ratings[i].color)
  646.         term.setCursorPos(37, i + 7)
  647.         term.write(" ") --# current rating color pip
  648.       else
  649.         rColor = colors.lightGray
  650.       end
  651.       term.setBackgroundColor(ratings[i].color)
  652.       term.setCursorPos(18, i + 7)
  653.       term.write(" ")   --# color pip
  654.       term.setBackgroundColor(colors.gray)
  655.       term.setTextColor(rColor)
  656.       term.setCursorPos(20, i + 7)
  657.       term.write(ratings[i].desc)
  658.     end
  659.   end
  660. end
  661.  
  662. local function drawGateData()
  663.   term.setTextColor(colors.yellow)
  664.   term.setCursorPos(11, 5)
  665.   term.write(addressBook[currentGate].name .. string.rep(" ", 9 - #addressBook[currentGate].name))
  666.   term.setCursorPos(13, 13)
  667.   term.write(addressBook[currentGate].loc.dim .. string.rep(" ", 38 - #addressBook[currentGate].loc.dim))
  668.   local gateNum = tostring(currentGate)
  669.   term.setCursorPos(termX - 6, 5)
  670.   term.setTextColor(colors.white)
  671.   term.write(gateNum .. string.rep(" ", 6 - #gateNum))
  672.   term.setCursorPos(8, 9)
  673.   term.write(addressBook[currentGate].note:sub(1, 43) .. string.rep(" ", 43 - #addressBook[currentGate].note:sub(1, 43)))
  674.   term.setTextColor(assignColor(currentGate))
  675.   term.setCursorPos(11, 7)
  676.   term.write(addressBook[currentGate].addr .. "  ")
  677.   local ratingWord = assignRating(currentGate)
  678.   term.setCursorPos(18, 11)
  679.   term.write(ratingWord .. string.rep(" ", 14))
  680.   drawIrisSwitch(addressBook[currentGate].iris)
  681.   term.setCursorPos(25, 7)
  682.   if addressBook[currentGate].addr == thisGate or addressBook[currentGate].addr == thisGate:sub(1, 7) then
  683.     term.setTextColor(colors.gray)
  684.     term.write("< This Gate >")
  685.   else
  686.     term.write("             ")
  687.   end
  688.   term.setTextColor(colors.lightGray)
  689.   term.setCursorPos(5, 15)
  690.   term.write(tostring(addressBook[currentGate].loc.x) .. string.rep(" ", 9 - #tostring(addressBook[currentGate].loc.x)))
  691.   term.setCursorPos(19, 15)
  692.   term.write(tostring(addressBook[currentGate].loc.y) .. string.rep(" ", 9 - #tostring(addressBook[currentGate].loc.y)))
  693.   term.setCursorPos(33, 15)
  694.   term.write(tostring(addressBook[currentGate].loc.z) .. string.rep(" ", 9 - #tostring(addressBook[currentGate].loc.z)))
  695. end
  696.  
  697. local function drawGateLabels()
  698.   clearLowerScreen()
  699.   term.setTextColor(colors.gray)
  700.   term.setCursorPos(2, 5)
  701.   term.write("Name:                  Iris:")
  702.   term.setCursorPos(termX - 8, 5)
  703.   term.write("# ")
  704.   term.setCursorPos(2, 7)
  705.   term.write("Address:")
  706.   term.setCursorPos(2, 9)
  707.   term.write("Note:")
  708.   term.setCursorPos(2, 11)
  709.   term.write("Classification:")
  710.   term.setCursorPos(2, 13)
  711.   term.write("Dimension:")
  712.   term.setCursorPos(2, 15)
  713.   term.write("x:            y:            z:")
  714.   drawGateData()
  715. end
  716.  
  717. local function drawAddressList()
  718.   local xPos, yPos = 17, 5
  719.   local magicNumber = ((gatePage - 1) * 20) + gatePage --# 21 gates/page
  720.   for i = magicNumber, #addressBook do
  721.     if addressBook[i].addr == thisGate or addressBook[i].addr == thisGate:sub(1, 7) then
  722.       term.setBackgroundColor(colors.gray)
  723.       term.setTextColor(colors.lightGray)
  724.     elseif gateTarget ~= "No Target" and ((addressBook[i].addr == gateTarget) or (#gateTarget == 7 and addressBook[i].addr:sub(1, 7) == gateTarget and addressBook[i].addr:sub(8, 9) == thisGate:sub(8, 9)) or (#addressBook[i].addr == 7 and addressBook[i].addr == gateTarget:sub(1, 7) and gateTarget:sub(8, 9) == thisGate:sub(8, 9))) then
  725.       term.setBackgroundColor(assignColor(i))
  726.       term.setTextColor(colors.black)
  727.     else
  728.       term.setBackgroundColor(assignColor(i))
  729.       term.setTextColor(colors.white)
  730.     end
  731.     term.setCursorPos(xPos, yPos)
  732.     term.write(string.rep(" ", math.floor((9 - #addressBook[i].name) / 2)) .. addressBook[i].name .. string.rep(" ", math.ceil((9 - #addressBook[i].name) / 2)))
  733.     yPos = yPos + 2
  734.     if yPos >= termY - 1 then xPos = xPos + 11 yPos = 5 end
  735.     if xPos >= termX - 10 then break end
  736.   end
  737.   addrRedraw = false
  738. end
  739.  
  740. local function drawIrisStatus()
  741.   paintutils.drawLine(10, 9, 11, 9, irisState and colors.lime or colors.orange)
  742. end
  743.  
  744. local function drawDHDStatus()
  745.   local fuelState, fuelPercent
  746.   if lcGate then
  747.     fuelState = gate.hasFuel()
  748.     term.setBackgroundColor(fuelState and colors.white or colors.red)
  749.   else
  750.     fuelPercent = math.floor((gate.energyAvailable() / 203842) * 100)
  751.     term.setBackgroundColor(fuelPercent > 5 and colors.white or colors.red)
  752.   end
  753.   local line = string.rep(" ", 12)
  754.   for i = 4, 7 do
  755.     term.setCursorPos(1, i)
  756.     term.write(line)
  757.   end
  758.   term.setTextColor(colors.blue)
  759.   term.setCursorPos(2, 5)
  760.   term.write(gateStatus)
  761.   if lcGate then
  762.     term.setTextColor(gateStatus == "Dialing" and colors.lightGray or colors.gray)
  763.   else
  764.     term.setTextColor((gateStatus == "Dialing" or gateStatus == "Incoming") and colors.lightGray or colors.gray)
  765.   end
  766.   term.setCursorPos(2, 6)
  767.   if lcGate then
  768.     if fuelState then
  769.       term.write(gateTarget)
  770.     else
  771.       term.write(gateTarget == "No Target" and "No Fuel" or gateTarget)
  772.     end
  773.   else
  774.     if fuelPercent > 5 then
  775.       term.write(gateTarget)
  776.     else
  777.       term.write(gateTarget == "No Target" and "Low Fuel" or gateTarget)
  778.     end
  779.   end
  780.   if addrRedraw then drawAddressList() end
  781.   if screen == "gatePage" then redrawInput() end
  782. end
  783.  
  784. local function drawDHDControls()
  785.   for _, button in pairs(guiElements.mainButtons) do
  786.     button.render()
  787.   end
  788.   if gateChange then highlightAddressButton() end
  789.   drawIrisStatus()
  790. end
  791.  
  792. local function drawLeftPane()
  793.   drawDHDStatus()
  794.   --paintutils.drawFilledBox(1, 8, 12, termY, colors.gray)
  795.   term.setBackgroundColor(colors.gray)
  796.   local line = string.rep(" ", 12)
  797.   for i = 8, termY do
  798.     term.setCursorPos(1, i)
  799.     term.write(line)
  800.   end
  801.   drawDHDControls()
  802. end
  803.  
  804. local function drawMainScreen()
  805.   drawLeftPane()
  806.   drawFooter()
  807.   drawAddressList()
  808. end
  809.  
  810. local function flashDial(gName, gX, gY, gateNum)
  811.   local gColor = assignColor(gateNum)
  812.   local gLabel = string.rep(" ", math.floor((9 - #gName) / 2)) .. gName .. string.rep(" ", math.ceil((9 - #gName) / 2))
  813.   term.setBackgroundColor(colors.black)
  814.   term.setTextColor(gColor)
  815.   term.setCursorPos(gX, gY)
  816.   term.write(gLabel)
  817.   sleep(0.1)
  818.   term.setBackgroundColor(gColor)
  819.   term.setTextColor(colors.white)
  820.   term.setCursorPos(gX, gY)
  821.   term.write(gLabel)
  822.   addrRedraw = true
  823. end
  824.  
  825. local function flashChoice(fX, fY, txtCol, bgCol, fText)
  826.   term.setBackgroundColor(bgCol)
  827.   term.setTextColor(txtCol)
  828.   term.setCursorPos(fX, fY)
  829.   term.write(fText)
  830.   sleep(0.1)
  831.   term.setBackgroundColor(txtCol)
  832.   term.setTextColor(bgCol)
  833.   term.setCursorPos(fX, fY)
  834.   term.write(fText)
  835. end
  836.  
  837. local function addNewAddress(newEntry, fast)
  838.   if #addressBook < 23976 then
  839.     local newAddress = { name = newEntry or "NEW GATE", addr = newEntry or "ADDRESS", rating = "U", iris = "none", note = "short note", loc = { x = 99999, y = 99999, z = 99999, dim = "Overworld", }, }
  840.     addressBook[#addressBook + 1] = newAddress
  841.     gatePages = math.ceil(#addressBook / 21)
  842.     gateChange = true
  843.     if fast then
  844.       drawAddressList()
  845.       drawFooter()
  846.       highlightAddressButton()
  847.     else
  848.       screen = "gate"
  849.       currentGate = #addressBook
  850.       drawGateLabels()
  851.     end
  852.   end
  853. end
  854.  
  855. local function hangUp()
  856.   local onHook, _ = pcall(gate.disconnect)
  857.   if onHook then
  858.     gateTarget = "No Target"
  859.     incomingAddress = nil
  860.   end
  861. end
  862.  
  863. local function dialOut(addr)
  864.   local ok, _ = pcall(gate.dial, addr)
  865.   if ok then
  866.     gateTarget = addr
  867.     gateStatus = "Dialing"
  868.     drawDHDStatus()
  869.   end
  870. end
  871.  
  872. local function toggleIris()
  873.   if lcGate then
  874.     irisState = not irisState
  875.   else
  876.     term.setBackgroundColor(colors.lightBlue)
  877.     term.setCursorPos(2, 9)
  878.     if irisState then
  879.       term.setTextColor(colors.orange)
  880.       pcall(gate.openIris)
  881.     else
  882.       term.setTextColor(colors.green)
  883.       pcall(gate.closeIris)
  884.     end
  885.     term.write("I r i s")
  886.   end
  887. end
  888.  
  889. local function irisStateChange() --# SGCraft
  890.   while true do
  891.     local irisEvent, _, newState, oldState = os.pullEvent("sgIrisStateChange")
  892.     if newState == "Closed" or newState == "Open" or newState == "Offline" then
  893.       term.setBackgroundColor(colors.lightBlue)
  894.       term.setCursorPos(2, 9)
  895.       term.setTextColor(colors.white)
  896.       term.write("I r i s")
  897.       if newState == "Closed" then
  898.         irisState = true
  899.       else
  900.         irisState = false
  901.       end
  902.       drawIrisStatus()
  903.       if screen == "gatePage" then redrawInput() end
  904.     end
  905.   end
  906. end
  907.  
  908. do
  909.   local states = {
  910.     Idle = "Idle",
  911.     Dialling = "Dialing",
  912.     Opening = "Dialing",
  913.     Connected = "Connected",
  914.     Closing = "Closing",
  915.     Offline = "Idle",
  916.   }
  917.  
  918.   gateStateChange = function() --# SGCraft
  919.     while true do
  920.       local sgEvent, _, new_State, old_State = os.pullEvent("sgStargateStateChange")
  921.       gateStatus = states[new_State]
  922.       if gateStatus == "Closing" or gateStatus == "Idle" then
  923.         gateTarget = "No Target"
  924.         incomingAddress = nil
  925.         chevronNumber = 0
  926.       end
  927.       if gateStatus == "Connected" then
  928.         recordSessionData()
  929.       end
  930.       if (gateStatus == "Idle" or gateStatus == "Connected") and (screen == "main" or screen == "gatePage" or screen == "manage" or screen == "exodus") then
  931.         drawAddressList()
  932.       end
  933.       if gateStatus ~= "Dialing" and (screen == "main" or screen == "gatePage" or screen == "manage" or screen == "exodus") then
  934.         drawDHDStatus()
  935.       end
  936.     end
  937.   end
  938. end
  939.  
  940. local function chevronEncoder() --# SGCraft
  941.   local fuelPercent = math.floor((gate.energyAvailable() / 203842) * 100)
  942.   local sgEvent, _, chevron
  943.   while true do
  944.     sgEvent, _, chevronNumber, chevron = os.pullEvent("sgChevronEngaged")
  945.     if screen == "main" or screen == "gatePage" or screen == "manage" or screen == "exodus" then
  946.       term.setCursorPos(2, 6)
  947.       term.setBackgroundColor(fuelPercent > 5 and colors.white or colors.red)
  948.       term.setTextColor(colors.gray)
  949.       term.write(gateTarget:sub(1, chevronNumber))
  950.       if incomingAddress then
  951.         term.setTextColor(colors.lightGray)
  952.         term.write(gateTarget:sub(chevronNumber + 1, #gateTarget))
  953.       end
  954.       if screen == "gatePage" then redrawInput() end
  955.     end
  956.   end
  957. end
  958.  
  959. local function gateIdle() --# LanteaCraft
  960.   while true do
  961.     os.pullEvent("sgIdle")
  962.     gateStatus = "Idle"
  963.     gateTarget = "No Target"
  964.     incomingAddress = nil
  965.     chevronNumber = 0
  966.     if screen == "main" or screen == "gatePage" or screen == "manage" or screen == "exodus" then
  967.       drawDHDStatus()
  968.     end
  969.   end
  970. end
  971.  
  972. local function gateConnect() --# LanteaCraft
  973.   while true do
  974.     os.pullEvent("sgWormholeOpening")
  975.     gateStatus = "Connected"
  976.     gateTarget = incomingAddress or gateTarget
  977.     recordSessionData()
  978.     if screen == "main" or screen == "gatePage" or screen == "manage" or screen == "exodus" then
  979.       if incomingAddress then drawAddressList() end
  980.       if screen == "gatePage" then drawPagePopUp() end
  981.       drawDHDStatus()
  982.     end
  983.   end
  984. end
  985.  
  986. local function gateDisconnect() --# LanteaCraft
  987.   while true do
  988.     os.pullEvent("sgWormholeClosing")
  989.     gateStatus = "Closing"
  990.     gateTarget = "No Target"
  991.     incomingAddress = nil
  992.     chevronNumber = 0
  993.     if screen == "main" or screen == "gatePage" or screen == "manage" or screen == "exodus" then
  994.       drawAddressList()
  995.       if screen == "gatePage" then drawPagePopUp() end
  996.       drawDHDStatus()
  997.     end
  998.   end
  999. end
  1000.  
  1001. local function incomingCall() --# LanteaCraft & SGCraft
  1002.   local sgEvent, _
  1003.   while true do
  1004.     if lcGate then
  1005.       local _, incomingChevron = os.pullEvent("sgIncoming")
  1006.       incomingAddress = incomingAddress and incomingAddress .. incomingChevron or incomingChevron
  1007.     else
  1008.       sgEvent, _, incomingAddress = os.pullEvent("sgDialIn")
  1009.     end
  1010.     gateStatus = "Incoming"
  1011.     gateTarget = incomingAddress
  1012.     for i = 1, #addressBook do
  1013.       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
  1014.         if addressBook[i].iris == "open" then
  1015.           pcall(gate.openIris)
  1016.         elseif addressBook[i].iris == "close" then
  1017.           pcall(gate.closeIris)
  1018.         end
  1019.         break
  1020.       end
  1021.     end
  1022.     if screen == "main" or screen == "gatePage" or screen == "manage" or screen == "exodus" then
  1023.       if not lcGate then addrRedraw = true end
  1024.       drawDHDStatus()
  1025.     end
  1026.   end
  1027. end
  1028.  
  1029. local function outgoingCall() --# LanteaCraft
  1030.   local _
  1031.   while true do
  1032.     _, chevronNumber = os.pullEvent("sgChevronEncode")
  1033.     if chevronNumber == #gateTarget and (screen == "main" or screen == "gatePage" or screen == "manage" or screen == "exodus") then
  1034.       drawDHDStatus()
  1035.     else
  1036.       if screen == "main" or screen == "gatePage" or screen == "manage" or screen == "exodus" then
  1037.         term.setCursorPos(2, 6)
  1038.         local fuelState = gate.hasFuel()
  1039.         term.setBackgroundColor(fuelState and colors.white or colors.red)
  1040.         term.setTextColor(colors.gray)
  1041.         term.write(gateTarget:sub(1, chevronNumber))
  1042.         if screen == "gatePage" then redrawInput() end
  1043.       end
  1044.     end
  1045.   end
  1046. end
  1047.  
  1048. local function inputExodusMouse()
  1049.   while true do
  1050.     local _, button, x, y = os.pullEvent("mouse_click")
  1051.     if y > 8 and y < 13 and x > 19 and x < 39 then
  1052.       if y == 11 and x > 21 and x < 28 and button == 1 then
  1053.         flashChoice(22, 11, colors.green, colors.white, " Save ")
  1054.         saveData(gateData)
  1055.         kernelState = false
  1056.         return
  1057.       elseif y == 11 and x > 30 and x < 37 and button == 1 then
  1058.         flashChoice(31, 11, colors.orange, colors.white, " Quit ")
  1059.         kernelState = false
  1060.         return
  1061.       end
  1062.     else
  1063.       screen = "main"
  1064.       clearExodusPopUp()
  1065.       drawAddressList()
  1066.       return
  1067.     end
  1068.   end
  1069. end
  1070.  
  1071. local function inputHelpMouse()
  1072.   while true do
  1073.     local _, button, x, y = os.pullEvent("mouse_click")
  1074.     if x > termX - 3 and y < 4 and button == 1 then
  1075.       screen = "main"
  1076.       clearLowerScreen()
  1077.       drawMainScreen()
  1078.       return
  1079.     end
  1080.   end
  1081. end
  1082.  
  1083. local function inputHelpKey()
  1084.   while true do
  1085.     local _, data = os.pullEvent("key")
  1086.     if data == keys.f1 then
  1087.       screen = "main"
  1088.       clearLowerScreen()
  1089.       drawMainScreen()
  1090.       return
  1091.     end
  1092.   end
  1093. end
  1094.  
  1095. local function inputLogChangePageKey()
  1096.   term.setBackgroundColor(colors.black)
  1097.   term.setTextColor(colors.white)
  1098.   term.setCursorPos(24, termY - 2)
  1099.   local newPage = tonumber(read(nil, nil, 4))
  1100.   logPage = newPage or logPage
  1101.   logPage = math.floor(math.max(1, math.min(logPage, logPages)))
  1102.   screen = "logs"
  1103.   clearPagePopUp(colors.white)
  1104.   drawLogScreen()
  1105. end
  1106.  
  1107. local function inputLogScreenMouse()
  1108.   while true do
  1109.     local event, button, x, y = os.pullEvent("mouse_click")
  1110.     if x > termX - 3 and y < 4 and button == 1 then
  1111.       clearCallHistory()
  1112.       screen = "main"
  1113.       clearLowerScreen()
  1114.       drawMainScreen()
  1115.       return
  1116.     elseif x > 20 and x < 31 and y == termY and callHistory[1] then
  1117.       flashChoice((math.ceil(termX / 2) - (#tostring(logPage) + #tostring(logPages) + 4) / 2), termY, colors.gray, colors.lightGray, tostring(logPage) .. " of " .. tostring(logPages))
  1118.       screen = "logPage"
  1119.       drawPagePopUp()
  1120.       return
  1121.     elseif y > 6 and y < termY - 1 and x > 30 and x < 40 then
  1122.       local currentEntry = ((logPage - 1) * 11) + 1 --# Set the first entry to show (based on page number)
  1123.       if callHistory[currentEntry + y - 7] then
  1124.         local targetAddress = callHistory[currentEntry + y - 7]:sub(string.find(callHistory[currentEntry + y - 7], ">") + 2, #callHistory[currentEntry + y - 7])
  1125.         if button == 1 and (#targetAddress == 7 or #targetAddress == 9) then
  1126.           clearCallHistory()
  1127.           screen = "main"
  1128.           dialOut(targetAddress)
  1129.           clearLowerScreen()
  1130.           drawMainScreen()
  1131.         elseif button == 2 and (#targetAddress == 7 or #targetAddress == 9) then
  1132.           clearCallHistory()
  1133.           addNewAddress(targetAddress)
  1134.         end
  1135.         return
  1136.       end
  1137.     else
  1138.       local modeSwitch = false
  1139.       for _, click in pairs(guiElements.logButtons) do
  1140.         modeSwitch = click.processEvent(event, button, x, y)
  1141.         if modeSwitch then return end
  1142.       end
  1143.     end
  1144.   end
  1145. end
  1146.  
  1147. local function inputLogScreenScroll()
  1148.   while true do
  1149.     local _, data = os.pullEvent("mouse_scroll")
  1150.     logPage = data == 1 and math.min(logPage + 1, logPages) or math.max(1, logPage - 1)
  1151.     drawLogScreen()
  1152.   end
  1153. end
  1154.  
  1155. local function inputLogScreenKey()
  1156.   while true do
  1157.     local _, data = os.pullEvent("key") --# pageUp, pageDn, Home, End
  1158.     if data == keys.pageUp then
  1159.       logPage = math.min(logPages, logPage + 1)
  1160.     elseif data == keys.pageDown then
  1161.       logPage = math.max(1, logPage - 1)
  1162.     elseif data == keys.home then
  1163.       logPage = 1
  1164.     elseif data == keys["end"] then
  1165.       logPage = logPages
  1166.     end
  1167.     drawLogScreen()
  1168.   end
  1169. end
  1170.  
  1171. local function inputClearLogsMouse()
  1172.   while true do
  1173.     local _, button, x, y = os.pullEvent("mouse_click")
  1174.     if y == math.floor(termY / 2) then
  1175.       if x > (termX / 2) - 5 and x < (termX / 2) and button == 1 then     --# yes
  1176.         flashChoice((termX / 2) - 4, math.floor(termY / 2), colors.green, colors.white, " YES ")
  1177.         screen = "logs"
  1178.         local clearLog = fs.open(historyData, "w")
  1179.         clearLog.close()
  1180.         clearCallHistory()
  1181.         logPage, logPages = 1, 1
  1182.         clearLowerScreen(colors.white)
  1183.         drawLogScreen()
  1184.         return
  1185.       elseif x > (termX / 2) and x < (termX / 2) + 6 and button == 1 then --# no
  1186.         flashChoice((termX / 2) + 2, math.floor(termY / 2), colors.red, colors.white, " N O ")
  1187.         screen = "logs"
  1188.         clearLowerScreen(colors.white)
  1189.         drawLogScreen()
  1190.         return
  1191.       end
  1192.     end
  1193.   end
  1194. end
  1195.  
  1196. local function inputManageAddressBookMouse()
  1197.   while true do
  1198.     local event, button, x, y = os.pullEvent("mouse_click")
  1199.     local modeSwitch = false
  1200.     for _, click in pairs(guiElements.addrBookMgt) do      --# process buttons
  1201.       modeSwitch = click.processEvent(event, button, x, y) --# carry out action for clicked button
  1202.       if modeSwitch then return end
  1203.     end
  1204.   end
  1205. end
  1206.  
  1207. local function inputGateRatingMouse()
  1208.   local selected = false
  1209.   local gRatings = { "B", "H", "V", "M", "S", "C", "D", "U" }
  1210.   while true do
  1211.     local _, button, x, y = os.pullEvent("mouse_click")
  1212.     if x > 17 and x < 38 and y > 5 and y < 17 and button == 1 then
  1213.       for i = 1, 8 do
  1214.         if y == i + 7 then
  1215.           if addressBook[currentGate].rating ~= gRatings[i] then
  1216.             addressBook[currentGate].rating = gRatings[i]
  1217.             gateChange = true
  1218.           end
  1219.           selected = true
  1220.           break
  1221.         end
  1222.       end
  1223.       if selected then break end
  1224.     else
  1225.       break
  1226.     end
  1227.   end
  1228.   --paintutils.drawFilledBox(18, 6, 37, 17, colors.black)
  1229.   term.setBackgroundColor(colors.black)
  1230.   local line = string.rep(" ", 20)
  1231.   for i = 6, 17 do --# clear menu body
  1232.     term.setCursorPos(18, i)
  1233.     term.write(line)
  1234.   end
  1235.   term.setTextColor(colors.gray)
  1236.   term.setCursorPos(30, 15)
  1237.   term.write("z:")
  1238.   drawGateData()
  1239.   screen = "gate"
  1240. end
  1241.  
  1242. local function inputViewGateMouse()
  1243.   while true do
  1244.     local _, button, x, y = os.pullEvent("mouse_click")
  1245.     if x > termX - 3 and y < 4 and button == 1 then
  1246.       screen = "main"
  1247.       currentGate = nil
  1248.       clearLowerScreen()
  1249.       drawMainScreen()
  1250.       return
  1251.     elseif y == 5 and button == 1 then  --# Name, gate order
  1252.       if x > 10 and x < 20 then         --# Name
  1253.         term.setTextColor(colors.gray)
  1254.         term.setCursorPos(11, 5)
  1255.         term.write(addressBook[currentGate].name)
  1256.         term.setTextColor(colors.white)
  1257.         term.setCursorPos(11, 5)
  1258.         local newName = read(nil, nil, 9)
  1259.         if newName ~= "" then
  1260.           addressBook[currentGate].name = newName
  1261.           gateChange = true
  1262.         end
  1263.         term.setCursorPos(11, 5)
  1264.         term.write(string.rep(" ", 9))
  1265.         term.setTextColor(colors.yellow)
  1266.         term.setCursorPos(11, 5)
  1267.         term.write(addressBook[currentGate].name)
  1268.       elseif x > 30 and x < 35 then --# iris blacklist/whitelist
  1269.         if addressBook[currentGate].iris == "none" then
  1270.           addressBook[currentGate].iris = "open"
  1271.         elseif addressBook[currentGate].iris == "open" then
  1272.           addressBook[currentGate].iris = "close"
  1273.         elseif addressBook[currentGate].iris == "close" then
  1274.           addressBook[currentGate].iris = "none"
  1275.         end
  1276.         drawIrisSwitch(addressBook[currentGate].iris)
  1277.       elseif x > termX - 7 and x < termX - 6 + #tostring(currentGate) then --# change entry #
  1278.         term.setCursorPos(termX - 6, 5)
  1279.         term.write(string.rep(" ", 6))
  1280.         term.setTextColor(colors.gray)
  1281.         term.setCursorPos(termX - 6, 5)
  1282.         term.write(tostring(currentGate))
  1283.         term.setTextColor(colors.white)
  1284.         term.setCursorPos(termX - 6, 5)
  1285.         local newPos = tonumber(read(nil, nil, 3))
  1286.         if newPos then
  1287.           local tempGate = { } --# = addressBook[currentGate]
  1288.           for k, v in pairs(addressBook[currentGate]) do
  1289.             tempGate[k] = v
  1290.           end
  1291.           table.remove(addressBook, currentGate)
  1292.           table.insert(addressBook, newPos, tempGate)
  1293.           currentGate = newPos
  1294.         end
  1295.         term.setCursorPos(termX - 6, 5)
  1296.         term.write(string.rep(" ", 6))
  1297.         drawGateData()
  1298.       end
  1299.     elseif y == 7 and x > 10 and x < 20 and button == 1 then  --# Address
  1300.       term.setTextColor(colors.gray)
  1301.       term.setCursorPos(11, 7)
  1302.       term.write(addressBook[currentGate].addr)
  1303.       term.setTextColor(colors.white)
  1304.       term.setCursorPos(11, 7)
  1305.       local newAddress = string.upper(read(nil, nil, 9, nil, nil, true))
  1306.       local nameChange = false
  1307.       if newAddress and (#newAddress == 7 or #newAddress == 9) then
  1308.         addressBook[currentGate].addr = newAddress
  1309.         local gNames = { "NEW GATE", "New Gate", "Name" }
  1310.         for _, tName in ipairs(gNames) do
  1311.           if addressBook[currentGate].name == tName then
  1312.             addressBook[currentGate].name = newAddress
  1313.             nameChange = true
  1314.             break
  1315.           end
  1316.         end
  1317.         gateChange = true
  1318.       end
  1319.       if nameChange then
  1320.         term.setCursorPos(11, 5)
  1321.         term.write(string.rep(" ", 9))
  1322.         term.setTextColor(colors.yellow)
  1323.         term.setCursorPos(11, 5)
  1324.         term.write(addressBook[currentGate].name)
  1325.       end
  1326.       term.setCursorPos(11, 7)
  1327.       term.write(string.rep(" ", 9))
  1328.       term.setTextColor(assignColor(currentGate))
  1329.       term.setCursorPos(11, 7)
  1330.       term.write(addressBook[currentGate].addr)
  1331.     elseif y == 9 and x > 7 and x < 8 + #addressBook[currentGate].note:sub(1, 43) and button == 1 then --# Note
  1332.       term.setTextColor(colors.gray)
  1333.       term.setCursorPos(8, 9)
  1334.       term.write(addressBook[currentGate].note:sub(1, 43))
  1335.       term.setTextColor(colors.white)
  1336.       term.setCursorPos(8, 9)
  1337.       local newNote = read(nil, nil, 43)
  1338.       if newNote ~= "" then
  1339.         addressBook[currentGate].note = newNote
  1340.         gateChange = true
  1341.       end
  1342.       term.setCursorPos(8, 9)
  1343.       term.write(string.rep(" ", 43))
  1344.       term.setCursorPos(8, 9)
  1345.       term.write(addressBook[currentGate].note:sub(1, 43))
  1346.     elseif y == 11 and x > 17 and x < 18 + #assignRating(currentGate) and button == 1 then --# Classification
  1347.       screen = "rating"
  1348.       drawRatingList(addressBook[currentGate].rating)
  1349.       return
  1350.     elseif y == 13 and x > 12 and x < 13 + #addressBook[currentGate].loc.dim and button == 1 then --# Dimension
  1351.       term.setTextColor(colors.gray)
  1352.       term.setCursorPos(13, 13)
  1353.       term.write(addressBook[currentGate].loc.dim)
  1354.       term.setTextColor(colors.white)
  1355.       term.setCursorPos(13, 13)
  1356.       local newDim = read(nil, nil, 19)
  1357.       if newDim ~= "" then
  1358.         addressBook[currentGate].loc.dim = newDim
  1359.         gateChange = true
  1360.       end
  1361.       term.setCursorPos(13, 13)
  1362.       term.write(string.rep(" ", 25))
  1363.       term.setTextColor(colors.yellow)
  1364.       term.setCursorPos(13, 13)
  1365.       term.write(addressBook[currentGate].loc.dim)
  1366.     elseif y == 15 and button == 1 then                       --# x, y, z coords
  1367.       if x > 4 and x < 5 + #tostring(addressBook[currentGate].loc.x) then
  1368.         term.setTextColor(colors.gray)
  1369.         term.setCursorPos(5, 15)
  1370.         term.write(tostring(addressBook[currentGate].loc.x))
  1371.         term.setTextColor(colors.white)
  1372.         term.setCursorPos(5, 15)
  1373.         local newX = tonumber(read(nil, nil, 9))
  1374.         if newX then
  1375.           addressBook[currentGate].loc.x = newX
  1376.           gateChange = true
  1377.         end
  1378.         term.setCursorPos(5, 15)
  1379.         term.write(string.rep(" ", 9))
  1380.         term.setTextColor(colors.lightGray)
  1381.         term.setCursorPos(5, 15)
  1382.         term.write(tostring(addressBook[currentGate].loc.x))
  1383.       elseif x > 18 and x < 19 + #tostring(addressBook[currentGate].loc.y) then
  1384.         term.setTextColor(colors.gray)
  1385.         term.setCursorPos(19, 15)
  1386.         term.write(tostring(addressBook[currentGate].loc.y))
  1387.         term.setTextColor(colors.white)
  1388.         term.setCursorPos(19, 15)
  1389.         local newY = tonumber(read(nil, nil, 9))
  1390.         if newY then
  1391.           addressBook[currentGate].loc.y = newY
  1392.           gateChange = true
  1393.         end
  1394.         term.setCursorPos(19, 15)
  1395.         term.write(string.rep(" ", 9))
  1396.         term.setTextColor(colors.lightGray)
  1397.         term.setCursorPos(19, 15)
  1398.         term.write(tostring(addressBook[currentGate].loc.y))
  1399.       elseif x > 32 and x < 33 + #tostring(addressBook[currentGate].loc.z) then
  1400.         term.setTextColor(colors.gray)
  1401.         term.setCursorPos(33, 15)
  1402.         term.write(tostring(addressBook[currentGate].loc.z))
  1403.         term.setTextColor(colors.white)
  1404.         term.setCursorPos(33, 15)
  1405.         local newZ = tonumber(read(nil, nil, 9))
  1406.         if newZ then
  1407.           addressBook[currentGate].loc.z = newZ
  1408.           gateChange = true
  1409.         end
  1410.         term.setCursorPos(33, 15)
  1411.         term.write(string.rep(" ", 9))
  1412.         term.setTextColor(colors.lightGray)
  1413.         term.setCursorPos(33, 15)
  1414.         term.write(tostring(addressBook[currentGate].loc.z))
  1415.       end
  1416.     end
  1417.   end
  1418. end
  1419.  
  1420. local function inputViewGateScroll()
  1421.   while true do
  1422.     local _, data = os.pullEvent("mouse_scroll")
  1423.     currentGate = data == 1 and math.min(#addressBook, currentGate + 1) or math.max(1, currentGate - 1)
  1424.     term.setCursorBlink(false)
  1425.     drawGateData()
  1426.   end
  1427. end
  1428.  
  1429. local function changePage()
  1430.   if gatePage == gatePages and gatePages > 1 then clearDataArea() end
  1431.   drawAddressList()
  1432.   drawFooter()
  1433. end
  1434.  
  1435. local function inputMainChangePageKey()
  1436.   term.setBackgroundColor(colors.black)
  1437.   term.setTextColor(colors.white)
  1438.   term.setCursorPos(31, termY - 2)
  1439.   local newPage = tonumber(read(nil, nil, 4))
  1440.   gatePage = newPage or gatePage
  1441.   gatePage = math.floor(math.max(1, math.min(gatePage, gatePages)))
  1442.   screen = "main"
  1443.   clearPagePopUp()
  1444.   if gatePage == gatePages and gatePages > 1 then clearDataArea() end
  1445.   drawAddressList()
  1446.   drawFooter()
  1447. end
  1448.  
  1449. local function inputMainScreenMouse()
  1450.   while true do
  1451.     local event, button, x, y = os.pullEvent("mouse_click")
  1452.     local xPos, yPos = 17, 5
  1453.     local magicNumber = ((gatePage - 1) * 20) + gatePage
  1454.     if x > termX - 3 and y < 4 and button == 1 then --# 'X' (quit)
  1455.       if gateChange then
  1456.         screen = "exodus"
  1457.         drawExodusPopUp()
  1458.         return
  1459.       end
  1460.       kernelState = false
  1461.       return
  1462.     elseif x > 27 and x < 38 and y == termY then
  1463.       flashChoice((math.ceil(termX / 2) - (#tostring(gatePage) + #tostring(gatePages) + 4) / 2) + 7, termY, colors.gray, colors.lightGray, tostring(gatePage) .. " of " .. tostring(gatePages))
  1464.       screen = "gatePage"
  1465.       drawPagePopUp()
  1466.       return
  1467.     end
  1468.     for i = magicNumber, #addressBook do
  1469.       if x >= xPos and x <= xPos + 8 and y == yPos then
  1470.         if button == 1 then              --# dial address
  1471.           if (#addressBook[i].addr == 9 and addressBook[i].addr == thisGate) or (#addressBook[i].addr == 7 and addressBook[i].addr == thisGate:sub(1, 7)) then
  1472.             return                       --# thisGate - don't dial
  1473.           else
  1474.             flashDial(addressBook[i].name, xPos, yPos, i)
  1475.             dialOut(addressBook[i].addr) --# dial out
  1476.             return
  1477.           end
  1478.         elseif button == 2 then          --# view/edit address
  1479.           flashDial(addressBook[i].name, xPos, yPos, i)
  1480.           screen = "gate"
  1481.           currentGate = i
  1482.           drawGateLabels()
  1483.           return
  1484.         elseif button == 3 and #addressBook > 1 then --# delete address
  1485.           flashDial(addressBook[i].name, xPos, yPos, i)
  1486.           table.remove(addressBook, i)
  1487.           gatePages = math.ceil(#addressBook / 21)
  1488.           gatePage = math.min(gatePage, gatePages)
  1489.           if gatePage == gatePages then clearDataArea() end
  1490.           drawAddressList()
  1491.           drawFooter()
  1492.           highlightAddressButton()
  1493.           gateChange = true
  1494.           return
  1495.         end
  1496.       else
  1497.         yPos = yPos + 2
  1498.         if yPos >= termY - 1 then xPos = xPos + 11 yPos = 5 end
  1499.         if xPos >= termX - 5 then break end
  1500.       end
  1501.     end
  1502.     local modeSwitch = false
  1503.     for _, click in pairs(guiElements.mainButtons) do      --# process buttons
  1504.       modeSwitch = click.processEvent(event, button, x, y) --# carry out action for clicked button
  1505.       if modeSwitch then return end
  1506.     end
  1507.     for _, click in pairs(guiElements.mainFooter) do
  1508.       click.processEvent(event, button, x, y)
  1509.     end
  1510.   end
  1511. end
  1512.  
  1513. local function inputMainScreenScroll()
  1514.   while true do
  1515.     local _, data = os.pullEvent("mouse_scroll")
  1516.     gatePage = data == 1 and math.min(gatePage + 1, gatePages) or math.max(1, gatePage - 1)
  1517.     changePage()
  1518.   end
  1519. end
  1520.  
  1521. local function inputMainScreenKey()
  1522.   while true do
  1523.     local _, data = os.pullEvent("key") --# pageUp, pageDn, Home, End, F1
  1524.     if data == keys.pageUp then
  1525.       gatePage = math.min(gatePages, gatePage + 1)
  1526.       changePage()
  1527.     elseif data == keys.pageDown then
  1528.       gatePage = math.max(1, gatePage - 1)
  1529.       changePage()
  1530.     elseif data == keys.home then
  1531.       gatePage = 1
  1532.       changePage()
  1533.     elseif data == keys["end"] then
  1534.       gatePage = gatePages
  1535.       changePage()
  1536.     elseif data == keys.f1 then
  1537.       screen = "help"
  1538.       drawHelpScreen()
  1539.     end
  1540.   end
  1541. end
  1542.  
  1543. local function dhdKernel()
  1544.   while kernelState do
  1545.     if lcGate then
  1546.       if screen == "main" then
  1547.         parallel.waitForAny(inputMainScreenMouse, inputMainScreenScroll, inputMainScreenKey, incomingCall, outgoingCall, gateIdle, gateConnect, gateDisconnect)
  1548.       elseif screen == "gate" then
  1549.         parallel.waitForAny(inputViewGateMouse, inputViewGateScroll, incomingCall, outgoingCall, gateIdle, gateConnect, gateDisconnect)
  1550.       elseif screen == "gatePage" then
  1551.         parallel.waitForAny(inputMainChangePageKey, incomingCall, outgoingCall, gateIdle, gateConnect, gateDisconnect)
  1552.       elseif screen == "rating" then
  1553.         parallel.waitForAny(inputGateRatingMouse, incomingCall, outgoingCall, gateIdle, gateConnect, gateDisconnect)
  1554.       elseif screen == "manage" then
  1555.         parallel.waitForAny(inputManageAddressBookMouse, incomingCall, outgoingCall, gateIdle, gateConnect, gateDisconnect)
  1556.       elseif screen == "logs" then
  1557.         parallel.waitForAny(inputLogScreenMouse, inputLogScreenScroll, inputLogScreenKey, incomingCall, outgoingCall, gateIdle, gateConnect, gateDisconnect)
  1558.       elseif screen == "logPage" then
  1559.         parallel.waitForAny(inputLogChangePageKey, incomingCall, outgoingCall, gateIdle, gateConnect, gateDisconnect)
  1560.       elseif screen == "clearLogs" then
  1561.         parallel.waitForAny(inputClearLogsMouse, incomingCall, outgoingCall, gateIdle, gateConnect, gateDisconnect)
  1562.       elseif screen == "help" then
  1563.         parallel.waitForAny(inputHelpMouse, inputHelpKey, incomingCall, outgoingCall, gateIdle, gateConnect, gateDisconnect)
  1564.       elseif screen == "exodus" then
  1565.         parallel.waitForAny(inputExodusMouse, incomingCall, outgoingCall, gateIdle, gateConnect, gateDisconnect)
  1566.       end
  1567.     else
  1568.       if screen == "main" then
  1569.         parallel.waitForAny(inputMainScreenMouse, inputMainScreenScroll, inputMainScreenKey, incomingCall, chevronEncoder, gateStateChange, irisStateChange)
  1570.       elseif screen == "gate" then
  1571.         parallel.waitForAny(inputViewGateMouse, inputViewGateScroll, incomingCall, chevronEncoder, gateStateChange, irisStateChange)
  1572.       elseif screen == "gatePage" then
  1573.         parallel.waitForAny(inputMainChangePageKey, incomingCall, chevronEncoder, gateStateChange, irisStateChange)
  1574.       elseif screen == "rating" then
  1575.         parallel.waitForAny(inputGateRatingMouse, incomingCall, chevronEncoder, gateStateChange, irisStateChange)
  1576.       elseif screen == "manage" then
  1577.         parallel.waitForAny(inputManageAddressBookMouse, incomingCall, chevronEncoder, gateStateChange, irisStateChange)
  1578.       elseif screen == "logs" then
  1579.         parallel.waitForAny(inputLogScreenMouse, inputLogScreenScroll, inputLogScreenKey, incomingCall, chevronEncoder, gateStateChange, irisStateChange)
  1580.       elseif screen == "logPage" then
  1581.         parallel.waitForAny(inputLogChangePageKey, incomingCall, chevronEncoder, gateStateChange, irisStateChange)
  1582.       elseif screen == "clearLogs" then
  1583.         parallel.waitForAny(inputClearLogsMouse, incomingCall, chevronEncoder, gateStateChange, irisStateChange)
  1584.       elseif screen == "help" then
  1585.         parallel.waitForAny(inputHelpMouse, inputHelpKey, incomingCall, chevronEncoder, gateStateChange, irisStateChange)
  1586.       elseif screen == "exodus" then
  1587.         parallel.waitForAny(inputExodusMouse, incomingCall, chevronEncoder, gateStateChange, irisStateChange)
  1588.       end
  1589.     end
  1590.   end
  1591. end
  1592.  
  1593. local function errorMessage(which)
  1594.   clearScreen()
  1595.   term.setCursorPos(2, 2)
  1596.   if which == "color" then
  1597.     term.write("This program requires an advanced computer")
  1598.   elseif which == "gate" then
  1599.     term.setTextColor(colors.red)
  1600.     term.write("Unable to locate a stargate")
  1601.     term.setTextColor(colors.white)
  1602.   end
  1603.   term.setCursorPos(1, 5)
  1604. end
  1605.  
  1606. local function initGate()
  1607.   gate = peripheral.find("stargate")
  1608.   if type(gate) == "table" then
  1609.     lcGate = pcall(gate.getAddress)
  1610.     if lcGate then
  1611.       irisState = false
  1612.       thisGate = gate.getAddress()
  1613.       if gate.isDialing() then
  1614.         gateStatus = "Dialing"
  1615.         gateTarget = "........."
  1616.       elseif gate.isConnected() then
  1617.         gateStatus = "Connected"
  1618.         gateTarget = "........."
  1619.       else
  1620.         gateStatus = "Idle"
  1621.       end
  1622.     else
  1623.       local gateState, callDirection
  1624.       gateState, chevronNumber, callDirection = gate.stargateState()
  1625.       if gateState == "Offline" then return false end
  1626.       thisGate = gate.localAddress()
  1627.       local irisStatus = gate.irisState()
  1628.       local irisStates = {
  1629.         Offline = "Open",
  1630.         Open = "Open",
  1631.         Opening = "Closed",
  1632.         Closed = "Closed",
  1633.         Closing = "Open",
  1634.       }
  1635.       for iState, iNewStatus in pairs(irisStates) do
  1636.         if irisStatus == iState then
  1637.           if iNewStatus == "Open" then
  1638.             irisState = false
  1639.           else
  1640.             irisState = true
  1641.           end
  1642.           break
  1643.         end
  1644.       end
  1645.       local states = {
  1646.         Idle = "Idle",
  1647.         Dialling = "Dialing",
  1648.         Opening = "Dialing",
  1649.         Connected = "Connected",
  1650.         Closing = "Closing",
  1651.       }
  1652.       gateStatus = states[gateState]
  1653.       if gateStatus == "Dialing" or gateStatus == "Connected" then
  1654.         gateTarget = gate.remoteAddress()
  1655.         if callDirection == "Incoming" then incomingAddress = gateTarget end
  1656.         if callDirection == "Incoming" and gateStatus == "Dialing" then gateStatus = "Incoming" end
  1657.       end
  1658.     end
  1659.     return true
  1660.   else
  1661.     return false
  1662.   end
  1663. end
  1664.  
  1665. local function initMe()
  1666.   if not term.isColor() then errorMessage("color") return false end
  1667.   if not initGate() then errorMessage("gate") return false end
  1668.   if not fs.exists(gateData) then
  1669.     if not fs.exists("/data") then fs.makeDir("/data") end
  1670.     addressBook[1].name = thisGate
  1671.     addressBook[1].addr = thisGate
  1672.     saveData(gateData)
  1673.   end
  1674.   ingestData(gateData)
  1675.   screen = "main"
  1676.   kernelState = true
  1677.   guiElements = {
  1678.     mainButtons = {
  1679.       newButton(1, 9, 11, 1, "I r i s  ", colors.lightBlue, colors.white, function() toggleIris() drawIrisStatus() end, "Iris", 1);
  1680.       newButton(1, 11, 11, 1, "END Call ", colors.orange, colors.black, function() if gateStatus == "Dialing" or gateStatus == "Connected" or gateStatus == "Incoming" then flashChoice(1, 11, colors.orange, colors.black, " END Call  ") hangUp() drawDHDStatus() end end, "EndCall", 1);
  1681.       newButton(1, 13, 11, 1, "Addr Book", colors.blue, colors.white, function() flashChoice(1, 13, colors.blue, gateChange and colors.lime or colors.white, " Addr Book ") screen = "manage" drawAddressBookManagementPopUp() return true end, "AddrBook", 1);
  1682.       newButton(1, 13, 11, 1, "Addr Book", colors.blue, colors.white, function() if gateChange then flashChoice(1, 13, colors.blue, colors.white, " Addr Book ") saveData(gateData) end end, "SaveAB", 2);
  1683.       newButton(1, 15, 11, 1, "New Gate ", colors.green, colors.white, function() flashChoice(1, 15, colors.green, colors.white, " New Gate  ") addNewAddress() end, "NewGate", 1);
  1684.       newButton(1, 15, 11, 1, "New Gate ", colors.green, colors.white, function() flashChoice(1, 15, colors.green, colors.white, " New Gate  ") addNewAddress(nil, true) end, "NewGateFast", 3);
  1685.       newButton(1, 17, 11, 1, "Logs     ", colors.yellow, colors.gray, function() flashChoice(1, 17, colors.yellow, colors.gray, " Logs      ") screen = "logs" ingestData("logs") clearLowerScreen(colors.white) drawLogScreen() return true end, "Logs", 1);
  1686.       newButton(1, termY, 11, 1, "[F1] Help", colors.gray, colors.lightGray, function() screen = "help" drawHelpScreen() return true end, "Help", 1);
  1687.     },
  1688.     mainFooter = {
  1689.       newButton(22, termY, 2, 1, "<<", colors.gray, colors.lightGray, function() gatePage = 1 changePage() end, "firstPage", 1);
  1690.       newButton(25, termY, 1, 1, "<", colors.gray, colors.lightGray, function() gatePage = math.max(1, gatePage - 1) changePage() end, "pageMinus", 1);
  1691.       newButton(40, termY, 1, 1, ">", colors.gray, colors.lightGray, function() gatePage = math.min(gatePages, gatePage + 1) changePage() end, "pagePlus", 1);
  1692.       newButton(42, termY, 2, 1, ">>", colors.gray, colors.lightGray, function() gatePage = gatePages changePage() end, "lastPage", 1);
  1693.     },
  1694.     logButtons = {
  1695.       newButton(termX - 7, 5, 7, 1, "CLEAR", colors.lightGray, colors.black, function() flashChoice(termX - 7, 5, colors.lightGray, colors.black, " CLEAR ") screen = "clearLogs" drawClearLogsPopUp() return true end, "logPageClear", 1);
  1696.       newButton(14, termY, 2, 1, "<<", colors.gray, colors.lightGray, function() logPage = 1 drawLogScreen() end, "logPageHome", 1);
  1697.       newButton(17, termY, 1, 1, "<", colors.gray, colors.lightGray, function() logPage = math.max(1, logPage - 1) drawLogScreen() end, "logPageMinus", 1);
  1698.       newButton(34, termY, 1, 1, ">", colors.gray, colors.lightGray, function() logPage = math.min(logPages, logPage + 1) clearLowerScreen(colors.white) drawLogScreen() end, "logPagePlus", 1);
  1699.       newButton(36, termY, 2, 1, ">>", colors.gray, colors.lightGray, function() logPage = logPages clearLowerScreen(colors.white) drawLogScreen() end, "logPageEnd", 1);
  1700.     },
  1701.     addrBookMgt = {
  1702.       newButton(17, 12, 8, 1, "Import", colors.yellow, colors.black, function() flashChoice(17, 12, colors.yellow, colors.black, " Import ") ingestData("/disk/data/DHDgates") clearDataArea() drawAddressList() highlightAddressButton() drawAddressBookManagementPopUp() end, "ABImport", 1);
  1703.       newButton(26, 12, 8, 1, "Export", colors.orange, colors.black, function() flashChoice(26, 12, colors.orange, colors.black, " Export ") saveData("/disk/data/DHDgates") drawAddressBookManagementPopUp() end, "ABExport", 1);
  1704.       newButton(17, 14, 8, 1, "Merge!", colors.purple, colors.white, function() flashChoice(17, 14, colors.purple, colors.white, " Merge! ") mergeData() if gatePage == gatePages then drawAddressList() end if gateChange then highlightAddressButton() end drawAddressBookManagementPopUp() end, "ABMerge", 1);
  1705.       newButton(26, 14, 8, 1, "Save", colors.green, colors.white, function() flashChoice(26, 14, colors.green, colors.white, "  Save  ") saveData(gateData) drawDHDControls() drawAddressBookManagementPopUp() end, "ABSave", 1);
  1706.       newButton(22, 16, 7, 1, "Close", colors.red, colors.white, function() flashChoice(22, 16, colors.red, colors.white, " Close ") screen = "main" clearABPopUp() drawAddressList() return true end, "ABClose", 1);
  1707.     },
  1708.   }
  1709.   return true
  1710. end
  1711.  
  1712. if not initMe() then return end
  1713. clearScreen()
  1714. drawHeader()
  1715. drawMainScreen()
  1716. dhdKernel()
  1717. clearScreen()
  1718. term.setTextColor(colors.white)
  1719. term.setCursorPos(1, 1)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement