Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- --[[ LanteaCraft ]]--
- --[[ Gate Liaison ]]--
- --[[ by HydrantHunter ]]--
- --[[ aka Dog ]]--
- --[[ with help from ]]--
- --[[ AfterLifeLochie ]]--
- --[[ pastebin xSHHqL0h ]]--
- --[[ GPL v3 ]]--
- local gVer = "1.1.12"
- --[[
- Tested with/requires:
- - Minecraft 1.6.4
- - LanteaCraft (snapshot 82+ & RC1_15-RC1_22)
- - ComputerCraft ver. 1.57+ for MC 1.6.4
- - HTTP API enabled (for pastebin installer - not required for gateLiaison)
- - 1 Computer (standard or advanced), 3 optional Monitors (standard or advanced) - probably best not to mix, though
- - or 1 Wireless Turtle (standard or advanced), no monitors
- - ccDHD running on an Advanced Computer with 4 optional Advanced Monitors
- - ccDHD also supports GopherATL's BioLock ver. 2.1.3 Fistprint scanner (updated for 1.6.4 by gamax92)
- ]]--
- -- AUTOMATIC/STATIC CONFIGURATION (Part 1)
- local modem, modemSide
- local gate, thisGate
- local fuelGuage, shieldStatus
- local pData
- local gateStatus = "QRY"
- local dialAddress = "none"
- local currentState = "ZZ"
- local pollTimer, timePoller = 0,0
- local longName = ""
- local mon = "none"
- local gateSettings = { shield = "front",
- DHD = 99999,
- chan = { send = 1787, recv = 1776 },
- net = "C",
- pollTime = 2,
- last = "/data/lastCall",
- }
- -- Color Definitions
- local white = colors.white
- local lgray = 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 lblue = colors.lightBlue
- local cyan = colors.cyan
- local lime = colors.lime
- local green = colors.green
- if not term.isColor() then
- lgray = colors.white
- gray = colors.black
- brown = colors.white
- yellow = colors.white
- orange = colors.white
- red = colors.white
- magenta = colors.white
- purple = colors.white
- blue = colors.black
- lblue = colors.white
- cyan = colors.white
- lime = colors.white
- green = colors.white
- end
- -- END AUTOMATIC/STATIC CONFIGURATION (Part 1)
- local function ingestData()
- local gateConfig = fs.open("/data/gateSettings","r") or error("ingestData(): Unable to open /data/gateSettings for reading", 2)
- local gateCfg = gateConfig.readAll()
- gateSettings = textutils.unserialize(gateCfg)
- gateConfig.close()
- end
- local function saveData()
- if not fs.exists("/data") then fs.makeDir("/data") end
- local gateConfig = fs.open("/data/gateSettings","w") or error("saveData(): Unable to open /data/gateSettings for writing", 2)
- gateConfig.write(textutils.serialize(gateSettings))
- gateConfig.close()
- end
- local function displayMarquee() -- Display the local address when there is no other information to display
- if mon == "none" then return end
- mon.setBackgroundColor(black)
- mon.clear()
- mon.setTextScale(2)
- mon.setCursorPos(1,1)
- mon.setTextColor(cyan)
- mon.write("Stargate")
- mon.setTextColor(yellow)
- if #thisGate > 7 then
- mon.setCursorPos(4,2)
- else
- mon.setCursorPos(2,2)
- end
- mon.write(longName)
- end
- local function displayStatus(select)
- if mon == "none" then return end
- if select == "con" then -- Connection status - dialAddress or incoming
- mon.clear()
- mon.setTextScale(2)
- mon.setCursorPos(1,1)
- if dialAddress ~= "none" then -- dialAddress
- mon.setTextColor(lblue)
- mon.write("Connected to")
- mon.setTextColor(yellow)
- if #dialAddress > 7 then
- mon.setCursorPos(4,2)
- mon.write(dialAddress)
- else -- incoming
- mon.setCursorPos(1,2)
- local dA = { }
- for i = 1,#dialAddress do
- dA[i] = dialAddress:sub(i,i)
- mon.write(" " .. dA[i])
- end
- end
- else
- mon.setTextColor(yellow)
- mon.write(" Incoming")
- mon.setCursorPos(4,2)
- mon.write("Connection")
- end
- elseif select == "dial" then -- Dial status - dialAddress or incoming
- mon.clear()
- mon.setTextScale(2)
- mon.setCursorPos(1,1)
- if dialAddress ~= "none" then
- mon.setTextColor(lblue)
- mon.write("Dialing")
- mon.setTextColor(yellow)
- if #dialAddress > 7 then
- mon.setCursorPos(4,2)
- mon.write(dialAddress) -- dialAddress (8+ symbols)
- else -- or longName (7 symbols)
- mon.setCursorPos(1,2)
- local dA = { }
- for i = 1,#dialAddress do
- dA[i] = dialAddress:sub(i,i)
- mon.write(" " .. dA[i])
- end
- end
- else -- incoming
- mon.setTextColor(yellow)
- mon.write(" Incoming")
- mon.setCursorPos(4,2)
- mon.write("Connection")
- end
- elseif select == "" or select == nil then -- Non-specified status - incoming or marquee
- if gate.isDialing() == true and dialAddress == "" then -- incoming
- mon.clear()
- mon.setTextScale(2)
- mon.setTextColor(yellow)
- mon.setCursorPos(1,1)
- mon.write(" Incoming")
- mon.setCursorPos(4,2)
- mon.write("Connection")
- else
- displayMarquee() -- marquee
- end
- end
- end
- local function drawElement(x,y,w,h,txtColor,bgdColor,text)
- local deText = tostring(text)
- term.setCursorPos(x,y)
- term.setBackgroundColor(bgdColor)
- if w > #deText or h > 1 then -- We're 'drawing' something more than text
- for i = 1,h,1 do --
- term.write(string.rep(" ",w)) -- Draw the 'element' (box/rectangle/line-seg)
- term.setCursorPos(x,y+i) --
- end
- end
- if deText ~= "" and deText ~= "nil" then
- term.setTextColor(txtColor)
- if w < #deText then w = #deText end -- Ensure minimum length
- local xW = (x + math.floor(w/2)) - math.floor(#deText/2) -- Center the text horizontally
- local xH = y + math.floor(h/2) -- Center the text vertically
- term.setCursorPos(xW,xH)
- term.write(deText)
- end
- end
- local function drawTermScreen()
- term.setBackgroundColor(black)
- term.clear()
- local stColor,sbColor
- if mon == "none" then
- sbColor = lblue
- stColor = black
- else
- sbColor = blue
- stColor = white
- end
- if fuelGuage == false then
- sbColor = red
- stColor = white
- end
- if not term.isColor() then
- sbColor = white
- stColor = black
- end
- local glHeaderTxt = " Gate Liaison" .. string.rep(" ",12) .. "ver. " .. gVer .. " "
- drawElement(2,2,1,1,stColor,sbColor,glHeaderTxt) -- Header
- drawElement(2,10,37,1,stColor,sbColor,"") -- lowline
- local me = os.getComputerLabel()
- drawElement(3,10,1,1,stColor,sbColor,me)
- local cID = "cc # " .. tostring(os.getComputerID())
- drawElement(38-(#cID),10,1,1,stColor,sbColor,cID)
- drawElement(2,3,12,7,black,lgray,"") -- Information background
- local readouts = { " Gate:", " State:", " Target:", " Iris:", " Fuel:", " Status:", " Network:" }
- for i = 1,7,1 do
- drawElement(2,i+2,1,1,black,lgray,readouts[i])
- end
- if #thisGate == 7 then
- drawElement(2,7,1,1,black,lgray," Shield:")
- end
- drawElement(17,3,1,1,yellow,black,thisGate)
- local sTxtColor = blue
- if gateStatus == "Disconnected" then
- sTxtColor = green
- elseif gateStatus == "Connected" then
- sTxtColor = orange
- elseif gateStatus == "Dialing" then
- sTxtColor = lblue
- end
- if gateStatus == "Dialing" and dialAddress == "none" then
- drawElement(17,4,1,1,sTxtColor,black,"Incoming Connection")
- elseif gateStatus == "lockdown" then
- drawElement(17,4,1,1,red,black,"!! LOCKDOWN !!")
- else
- drawElement(17,4,1,1,sTxtColor,black,gateStatus)
- end
- drawElement(17,5,1,1,brown,black,dialAddress)
- term.setCursorPos(17,6)
- if shieldStatus == true then
- term.setTextColor(green)
- if #thisGate == 7 then
- term.write("ON ")
- elseif #thisGate > 7 then
- term.write("CLOSED")
- end
- elseif shieldStatus == false then
- term.setTextColor(orange)
- if #thisGate == 7 then
- term.write("OFF ")
- elseif #thisGate > 7 then
- term.write("OPEN ")
- end
- else
- term.setTextColor(magenta)
- term.write("ERROR ")
- end
- term.setCursorPos(17,7)
- if fuelGuage == true then
- term.setTextColor(green)
- term.write("YES ")
- elseif fuelGuage == false then
- term.setTextColor(red)
- term.write("NO ")
- else
- term.setTextColor(magenta)
- term.write("ERROR")
- end
- drawElement(17,8,1,1,lblue,black,pData)
- term.setCursorPos(17,9)
- if gateSettings.net == "R" then
- term.setTextColor(red)
- term.write("redNet ")
- term.setTextColor(gray)
- term.write("ccDHD ")
- term.setTextColor(red)
- term.write(tostring(gateSettings.DHD))
- elseif gateSettings.net == "C" then
- term.setTextColor(green)
- term.write("ccNet ")
- term.setTextColor(gray)
- term.write("s:")
- term.setTextColor(green)
- term.write(tostring(gateSettings.chan.send))
- term.setTextColor(gray)
- term.write(" r:")
- term.setTextColor(green)
- term.write(tostring(gateSettings.chan.recv))
- end
- end
- local function netSend(dataPack)
- if gateSettings.net == "R" then
- if gateSettings.DHD ~= 99999 then
- rednet.send(gateSettings.DHD,dataPack)
- end
- elseif gateSettings.net == "C" then
- if gateSettings.chan.recv ~= 2 then
- modem.transmit(gateSettings.chan.send,gateSettings.chan.recv,dataPack)
- end
- end
- end
- local function updateStatus(special)
- currentState = pData
- fuelGuage = gate.hasFuel()
- if gateSettings.shield == "iris" then
- shieldStatus, _ = { pcall(gate.isIrisClosed) }
- else
- shieldStatus = rs.getOutput(gateSettings.shield)
- end
- if gateStatus == "allclear" then
- shieldState = false
- if gate.isConnected() then
- gateStatus = "Connected"
- else
- gateStatus = "Disconnected"
- dialAddress = "none"
- end
- if fuelGuage then
- pData = "YY1"
- else
- pData = "YY0"
- end
- elseif gateStatus == "lockdown" then
- if fuelGuage then
- pData = "XX1"
- else
- pData = "XX0"
- end
- dialAddress = "none"
- else
- if shieldStatus then
- pData = "1"
- else
- pData = "0"
- end
- if gate.isDialing() then
- pData = pData .. "2"
- gateStatus = "Dialing"
- if mon ~= "none" then
- displayStatus("dial")
- end
- else
- if gate.isConnected() then
- pData = pData .. "1"
- gateStatus = "Connected"
- if mon ~= "none" then
- displayStatus("con")
- end
- else
- gateStatus = "Disconnected"
- dialAddress = "none"
- pData = pData .. "0"
- end
- end
- if fuelGuage then
- pData = pData .. "1"
- else
- pData = pData .. "0"
- end
- end
- if gateStatus ~= "Dialing" and gateStatus ~= "Connected" and gateStatus ~= "lockdown" then displayMarquee() end
- if currentState ~= pData or tostring(special) == "QRY" then
- netSend(pData)
- drawTermScreen()
- end
- end
- local function recordSessionData() -- Human readable log files (last gate & history)
- if not fs.exists("/data") then fs.makeDir("/data") end
- local dateStamp = textutils.formatTime(os.time(),false) .. " / Day " .. os.day()
- local lastCall = fs.open(gateSettings.last,"w")
- lastCall.writeLine(dateStamp)
- lastCall.writeLine(dialAddress)
- lastCall.close()
- end
- local function shieldControl(state)
- if state == "ON" then
- if gateSettings.shield == "iris" then
- pcall(gate.irisClose)
- else
- rs.setOutput(gateSettings.shield,true)
- end
- return
- elseif state == "OFF" then
- if gateSettings.shield == "iris" then
- pcall(gate.irisOpen)
- else
- rs.setOutput(gateSettings.shield,false)
- end
- return
- end
- end
- local function lockDown()
- gateStatus = "lockdown"
- shieldControl("ON")
- local onHook, _ = pcall(gate.disconnect)
- if onHook then
- dialAddress = "none"
- end
- updateStatus()
- if mon ~= "none" then
- mon.clear()
- mon.setCursorPos(1,1)
- mon.setTextColor(red)
- mon.write("!! LOCKDOWN !!")
- end
- end
- local function dialOut(targetAddress)
- dialAddress = tostring(targetAddress)
- local dialGate, _ = pcall(gate.dial,dialAddress)
- if dialGate then
- gateStatus = "Dialing"
- recordSessionData()
- updateStatus()
- end
- return dialGate
- end
- local function endCall()
- local hangUp, _ = pcall(gate.disconnect)
- if hangUp then
- gateStatus = "Disconnected"
- dialAddress = "none"
- end
- end
- local function doCommand(thisCommand)
- if thisCommand == "lockdown" then
- lockDown()
- return
- elseif thisCommand == "allclear" then
- displayMarquee()
- shieldControl("OFF")
- gateStatus = "allclear"
- dialAddress = "none"
- updateStatus()
- return
- end
- if thisCommand == "QRY" then
- updateStatus("QRY")
- return
- end
- if gateStatus ~= "lockdown" then
- if thisCommand == "1stRun" then -- When ccDHD signifies its first run...
- while true do
- local myBoss = { os.pullEvent("modem_message") } -- ...it then sends it's cc# and waits for the gate's address & cc #
- if myBoss[3] == gateSettings.chan.recv and myBoss[4] == gateSettings.chan.send then
- gateSettings.DHD = myBoss[5]
- saveData()
- break
- end
- end
- local me = os.getComputerID()
- local tempSettings = { addr = thisGate, gate = me }
- sleep(0.1)
- netSend(tempSettings)
- return
- elseif thisCommand == "redNet" then -- change to redNet
- if gateSettings.net == "C" then modem.close(gateSettings.chan.recv) end
- modem = nil
- gateSettings.net = "R"
- rednet.open(modemSide)
- saveData()
- drawTermScreen()
- return
- elseif thisCommand == "ccNet" then -- change to ccNet
- if gateSettings.net == "R" then rednet.close(modemSide) end
- gateSettings.net = "C"
- modem = peripheral.wrap(modemSide)
- modem.open(gateSettings.chan.recv)
- saveData()
- drawTermScreen()
- return
- elseif thisCommand == "CS" then -- change ccNet Receive Channel
- local newCR = { os.pullEvent("modem_message") }
- modem.close(gateSettings.chan.recv)
- gateSettings.chan.recv = newCR[5]
- modem.open(gateSettings.chan.recv)
- saveData()
- drawTermScreen()
- return
- elseif thisCommand == "CR" then -- change ccNet Send Channel
- local newCS = { os.pullEvent("modem_message") }
- gateSettings.chan.send = newCS[5]
- saveData()
- drawTermScreen()
- return
- elseif thisCommand == "endCall" then
- endCall()
- updateStatus()
- return
- elseif thisCommand == "sON" then
- shieldControl("ON")
- updateStatus()
- return
- elseif thisCommand == "sOFF" then
- shieldControl("OFF")
- updateStatus()
- return
- elseif thisCommand == "restart" or thisCommand == "reset" then
- os.reboot()
- else
- if dialOut(thisCommand) then
- gateStatus = "Dialing"
- updateStatus()
- return
- else
- gateStatus = "Disconnected"
- dialAddress = "none"
- updateStatus()
- return
- end
- end
- end
- end
- local function netReceive()
- while true do
- if gateSettings.net == "R" then
- local eventNet = { rednet.receive() }
- if tonumber(eventNet[1]) == gateSettings.DHD then
- if eventNet[2] ~= nil and eventNet[2] ~= "" then
- doCommand(eventNet[2])
- end
- end
- return
- elseif gateSettings.net == "C" then
- local eventNet = { os.pullEvent("modem_message") }
- if eventNet[3] == gateSettings.chan.recv and eventNet[4] == gateSettings.chan.send then
- if eventNet[5] ~= nil and eventNet[5] ~= "" then
- doCommand(eventNet[5])
- end
- end
- return
- end
- end
- end
- local function dataPoller()
- while true do
- local timerEvent = { os.pullEvent("timer") }
- if timerEvent[2] == pollTimer then
- timePoller = 0
- updateStatus()
- break
- end
- end
- end
- local function gateKernel()
- if timePoller == 0 then
- pollTimer = os.startTimer(gateSettings.pollTime)
- timerPoller = 1
- end
- parallel.waitForAny(netReceive,dataPoller)
- end
- local function firstRun()
- -- Set computer label
- local ccLabel = os.getComputerLabel()
- if ccLabel == nil or tostring(ccLabel) == "" or ccLabel == "Gate" then
- os.setComputerLabel(thisGate .. " gate")
- end
- term.clear()
- -- Select shield/redstone output side
- --if #thisGate == 7 then -- implement when iris control is introduced?
- drawElement(2,2,45,1,lblue,black,"Please select the shield/redstone output side")
- drawElement(2,4,22,1,gray,black,"(select an unused side")
- drawElement(2,5,21,1,gray,black,"if not using redstone")
- drawElement(2,6,7,1,gray,black,"output)")
- if term.isColor() then
- -- Draw side list
- local tPos = { }
- local tSide = { }
- if #thisGate == 7 then
- tPos = { 5,7,9,11,13,15 }
- tSide = { "top","bottom","front","back","left","right" }
- elseif #thisGate > 7 then
- tPos = { 5,7,9,11,13,15 }
- tSide = { "top","bottom","front","back","left","right" }
- --tPos = { 5,7,9,11,13,15,17 }
- --tSide = { "top","bottom","front","back","left","right","iris" }
- end
- if #thisGate == 7 then
- drawElement(26,4,8,13,white,gray,"") -- Draw blank menu (snapshot 82+)
- elseif #thisGate > 7 then
- drawElement(26,4,8,13,white,gray,"") -- Draw blank menu (RC1)
- end
- for j,k in ipairs(tSide) do --
- local tSides = string.upper(k):sub(1,1) .. k:sub(2) -- Draw side labels in menu
- drawElement(27,tPos[j],#tSides,1,white,gray,tSides) --
- end
- while true do
- local newSide = { os.pullEvent("mouse_click") } --
- if newSide[3] > 26 and newSide[3] < 34 then --
- for j,k in ipairs(tSide) do -- Select shield (redstone output) side
- if newSide[4] == tPos[j] then -- or internal iris
- gateSettings.shield = k --
- return false --
- end
- end
- end
- end
- else
- -- Select redstone output side
- term.clear()
- drawElement(2,2,45,1,white,black,"Please select the shield/redstone output side")
- -- Draw side list
- term.setTextColor(white)
- local theseSides = { "top", "bottom", "left", "right", "front", "back" }
- for l,m in ipairs(theseSides) do
- local sSides = tostring(l) .. " = " .. string.upper(m):sub(1,1) .. m:sub(2)
- drawElement(2,l+4,#sSides,1,white,black,sSides) -- Side selection list for standard computers and turtles
- end
- term.setCursorPos(2,12)
- while true do
- local getSide = tonumber(read())
- if getSide ~= nil then
- if getSide > 0 and getSide < 7 then
- for n,o in ipairs(theseSides) do
- if getSide == n then
- gateSettings.shield = o
- end
- end
- break
- end
- end
- end
- end
- --end
- end
- -- AUTOMATIC/STATIC CONFIGURATION (Part 2)
- local function initGate()
- for k,v in ipairs(rs.getSides()) do
- -- Stargate
- if peripheral.getType(v) == "stargate" then
- if not gate then
- gate = peripheral.wrap(tostring(v))
- break
- end
- elseif peripheral.getType(v) == "modem" then
- if peripheral.call(tostring(v),"isWireless") == false then
- local mPerps = peripheral.call(tostring(v),"getNamesRemote")
- for _,mPerp in ipairs(mPerps) do
- if tostring(mPerp):sub(1,8) == "stargate" then
- if not gate then
- gate = peripheral.wrap(mPerp)
- break
- end
- end
- end
- end
- end
- end
- if not gate then
- term.setBackgroundColor(black)
- term.setTextColor(red)
- term.clear()
- term.setCursorPos(1,1)
- term.write("No Stargate detected!")
- term.setCursorPos(1,3)
- return
- end
- thisGate = gate.getAddress()
- fuelGuage = gate.hasFuel()
- if #thisGate > 7 then
- longName = thisGate
- else
- local tG = { }
- longName = ""
- for i = 1,#thisGate,1 do
- tG[i] = thisGate:sub(i,i)
- if i < #thisGate then
- longName = longName .. tG[i] .. " "
- else
- longName = longName .. tG[i]
- end
- end
- end
- end
- local function initMe()
- initGate()
- if not gate then return end
- -- Check for first time install
- if not fs.exists("/data/gateSettings") then
- firstRun()
- term.setBackgroundColor(black)
- term.clear()
- saveData()
- end
- ingestData()
- modemSide = "none"
- for k,v in ipairs(rs.getSides()) do
- -- Modem
- if peripheral.getType(v) == "modem" then
- if peripheral.call(tostring(v),"isWireless") == true then
- -- redNet
- if gateSettings.net == "R" then
- modemSide = v
- rednet.open(v)
- -- ccNet
- elseif gateSettings.net == "C" then
- modemSide = v
- modem = peripheral.wrap(v)
- modem.open(gateSettings.chan.recv)
- end
- -- Monitor
- elseif peripheral.call(tostring(v),"isWireless") == false then
- local mPerps = peripheral.call(tostring(v),"getNamesRemote")
- for _,mPerp in ipairs(mPerps) do
- if tostring(mPerp):sub(1,7) == "monitor" then
- mon = peripheral.wrap(mPerp)
- end
- end
- end
- end
- end
- if modemSide == "none" then
- term.clear()
- term.setCursorPos(2,2)
- term.setTextColor(red)
- term.write("gateLiaison requires a wireless modem")
- term.setCursorPos(1,4)
- return
- end
- if gateSettings.shield == "iris" then
- shieldStatus, _ = pcall(gate.isIrisClosed)
- else
- shieldStatus = rs.getOutput(gateSettings.shield)
- end
- if mon ~= "none" then
- displayMarquee()
- end
- updateStatus()
- end
- -- END AUTOMATIC/STATIC CONFIGURATION (Part 2)
- initMe()
- if not gate then return end
- if modemSide == "none" then return end
- while true do
- gateKernel()
- end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement