divided everything
This commit is contained in:
42
addresses.lua
Normal file
42
addresses.lua
Normal file
@ -0,0 +1,42 @@
|
||||
--[[
|
||||
Address Book
|
||||
Contains all known stargate addresses organized by category
|
||||
]]
|
||||
|
||||
local addresses = {}
|
||||
|
||||
---------------------------------------------
|
||||
-- MAIN GATES
|
||||
---------------------------------------------
|
||||
-- Common 7-chevron addresses for main destinations
|
||||
|
||||
addresses.MainGates = {
|
||||
{ "OVERWORLD", { 27, 25, 4, 35, 10, 28, 0 } },
|
||||
{ "Nether", { 27, 23, 4, 34, 12, 28, 0 } },
|
||||
{ "End", { 13, 24, 2, 19, 3, 30, 0 } },
|
||||
{ "Abydos", { 26, 6, 14, 31, 11, 29, 0 } },
|
||||
{ "Chulak", { 8, 1, 22, 14, 36, 19, 0 } }
|
||||
}
|
||||
|
||||
---------------------------------------------
|
||||
-- PLAYER GATES
|
||||
---------------------------------------------
|
||||
-- Typically 9-chevron addresses for player bases
|
||||
|
||||
addresses.playerGates = {
|
||||
{ "Glaive", { 33, 6, 10, 24, 1, 30, 3, 17, 0 } },
|
||||
{ "Moon", { 32, 33, 8, 7, 25, 21, 14, 35, 0 } },
|
||||
{ "Caldoric", { 18, 2, 24, 16, 8, 19, 4, 29, 0 } },
|
||||
{ "Trading Hall", { 16, 19, 6, 18, 35, 27, 9, 8, 0 } }
|
||||
}
|
||||
|
||||
---------------------------------------------
|
||||
-- HAZARD GATES
|
||||
---------------------------------------------
|
||||
-- Dangerous destinations
|
||||
|
||||
addresses.hazardGates = {
|
||||
-- Add hazardous gate addresses here
|
||||
}
|
||||
|
||||
return addresses
|
||||
55
config.lua
Normal file
55
config.lua
Normal file
@ -0,0 +1,55 @@
|
||||
--[[
|
||||
Configuration File
|
||||
All user-configurable settings for the Stargate Control System
|
||||
]]
|
||||
|
||||
local config = {}
|
||||
|
||||
---------------------------------------------
|
||||
-- GATE BEHAVIOR
|
||||
---------------------------------------------
|
||||
|
||||
-- Gate dialing speed (seconds between chevrons for non-Milky Way gates)
|
||||
config.gatespeed = 0.5
|
||||
|
||||
-- Manual dial for Milky Way gates (rotating ring animation)
|
||||
config.manualDial = true
|
||||
|
||||
-- Access control
|
||||
config.canAccessHazardGates = true
|
||||
|
||||
---------------------------------------------
|
||||
-- IRIS CONFIGURATION
|
||||
---------------------------------------------
|
||||
|
||||
config.irisEnabled = true
|
||||
config.autoCloseIrisOnIncoming = true
|
||||
config.irisCloseDelay = 0.1 -- seconds before closing iris on incoming
|
||||
config.autoOpenIrisAfterDisconnect = true
|
||||
|
||||
---------------------------------------------
|
||||
-- SECURITY
|
||||
---------------------------------------------
|
||||
|
||||
-- Whitelist (if not empty, only these addresses can enter)
|
||||
-- Format: {"Name", {address_table}}
|
||||
config.whitelist = {
|
||||
{ "Glaive", { 33, 6, 10, 24, 1, 30, 3, 17, 0 } },
|
||||
{ "Moon", { 32, 33, 8, 7, 25, 21, 14, 35, 0 } },
|
||||
{ "Caldoric", { 18, 2, 24, 16, 8, 19, 4, 29, 0 } },
|
||||
{ "Trading Hall", { 16, 19, 6, 18, 35, 27, 9, 8, 0 } }
|
||||
}
|
||||
|
||||
-- Blacklist (these addresses are always blocked)
|
||||
config.blacklist = {
|
||||
-- {"DangerGate", {1,2,3,4,5,6,0}},
|
||||
}
|
||||
|
||||
---------------------------------------------
|
||||
-- LOGGING
|
||||
---------------------------------------------
|
||||
|
||||
config.enableLogging = true
|
||||
config.logFile = "stargate.log"
|
||||
|
||||
return config
|
||||
222
display.lua
Normal file
222
display.lua
Normal file
@ -0,0 +1,222 @@
|
||||
--[[
|
||||
Display Functions
|
||||
Handles all monitor/screen drawing operations
|
||||
]]
|
||||
|
||||
local display = {}
|
||||
|
||||
-- Will be set by startup.lua
|
||||
local mon
|
||||
local config
|
||||
local addresses
|
||||
local utils
|
||||
|
||||
-- State variables
|
||||
local buttonXY = {}
|
||||
local computerAddresses = {}
|
||||
local computerNames = {}
|
||||
local x, y = 0, 0
|
||||
|
||||
function display.init(monitor, cfg, addr, utilsModule)
|
||||
mon = monitor
|
||||
config = cfg
|
||||
addresses = addr
|
||||
utils = utilsModule
|
||||
end
|
||||
|
||||
function display.getButtonData()
|
||||
return buttonXY, computerAddresses, computerNames
|
||||
end
|
||||
|
||||
function display.clearButtonData()
|
||||
buttonXY = {}
|
||||
computerAddresses = {}
|
||||
computerNames = {}
|
||||
end
|
||||
|
||||
---------------------------------------------
|
||||
-- DRAWING FUNCTIONS
|
||||
---------------------------------------------
|
||||
|
||||
function display.drawIrisStatus()
|
||||
mon.setCursorPos(1, 19)
|
||||
mon.setBackgroundColor(colors.black)
|
||||
local irisState = utils.getIrisState()
|
||||
if irisState == "OPEN" then
|
||||
mon.setTextColor(colors.green)
|
||||
elseif irisState == "CLOSED" then
|
||||
mon.setTextColor(colors.red)
|
||||
else
|
||||
mon.setTextColor(colors.gray)
|
||||
end
|
||||
mon.write("IRIS: " .. irisState .. " ")
|
||||
mon.setTextColor(colors.white)
|
||||
if irisState == "MOVING" then
|
||||
sleep(0.1)
|
||||
display.drawIrisStatus()
|
||||
end
|
||||
end
|
||||
|
||||
function display.screenWrite(list, fcount, fy)
|
||||
for i = 1, #list do
|
||||
local x1, x2 = 0, 0
|
||||
|
||||
if fcount == 0 then
|
||||
x = 2
|
||||
fcount = 1
|
||||
elseif fcount == 1 then
|
||||
x = 11
|
||||
fcount = 2
|
||||
else
|
||||
x = 20
|
||||
fcount = 0
|
||||
fy = fy + 2
|
||||
end
|
||||
|
||||
mon.setCursorPos(x, fy)
|
||||
mon.write(list[i][1])
|
||||
|
||||
x1 = x
|
||||
x2 = x + 7
|
||||
|
||||
table.insert(buttonXY, { x1, x2, fy })
|
||||
table.insert(computerNames, list[i][1])
|
||||
table.insert(computerAddresses, list[i][2])
|
||||
end
|
||||
|
||||
local oldterm = term.redirect(mon)
|
||||
paintutils.drawFilledBox(23, 17, 28, 19, colors.red)
|
||||
mon.setCursorPos(24, 18)
|
||||
mon.write("Back")
|
||||
term.redirect(oldterm)
|
||||
|
||||
return fcount, fy
|
||||
end
|
||||
|
||||
function display.selectionTabs()
|
||||
mon.setBackgroundColor(colors.black)
|
||||
mon.clear()
|
||||
local oldterm = term.redirect(mon)
|
||||
|
||||
if #addresses.MainGates ~= 0 then
|
||||
paintutils.drawFilledBox(2, 2, 13, 6, colors.purple)
|
||||
mon.setCursorPos(4, 4)
|
||||
mon.setBackgroundColor(colors.purple)
|
||||
mon.write("Main Gates")
|
||||
end
|
||||
|
||||
if #addresses.playerGates ~= 0 then
|
||||
paintutils.drawFilledBox(16, 2, 27, 6, colors.green)
|
||||
mon.setCursorPos(18, 4)
|
||||
mon.setBackgroundColor(colors.green)
|
||||
mon.write("Player")
|
||||
mon.setCursorPos(18, 5)
|
||||
mon.write("Base gates")
|
||||
end
|
||||
|
||||
if (#addresses.hazardGates ~= 0) and (config.canAccessHazardGates == true) then
|
||||
paintutils.drawFilledBox(2, 8, 13, 12, colors.red)
|
||||
mon.setCursorPos(4, 9)
|
||||
mon.setBackgroundColor(colors.red)
|
||||
mon.write("Hazard")
|
||||
mon.setCursorPos(4, 11)
|
||||
mon.write("gates")
|
||||
end
|
||||
|
||||
paintutils.drawFilledBox(23, 17, 28, 19, colors.red)
|
||||
mon.setCursorPos(24, 18)
|
||||
mon.write("Back")
|
||||
|
||||
display.drawIrisStatus()
|
||||
term.redirect(oldterm)
|
||||
end
|
||||
|
||||
function display.showIncoming(addressString, allowed, reason)
|
||||
mon.setBackgroundColor(colors.black)
|
||||
mon.clear()
|
||||
|
||||
if allowed then
|
||||
mon.setBackgroundColor(colors.green)
|
||||
mon.setTextScale(1)
|
||||
mon.setCursorPos(1, 2)
|
||||
mon.write("INCOMING - AUTHORIZED")
|
||||
else
|
||||
mon.setBackgroundColor(colors.red)
|
||||
mon.setTextScale(1)
|
||||
mon.setCursorPos(1, 2)
|
||||
mon.write("INCOMING - UNAUTHORIZED")
|
||||
mon.setCursorPos(1, 4)
|
||||
mon.write(reason)
|
||||
end
|
||||
|
||||
mon.setCursorPos(1, 6)
|
||||
mon.setBackgroundColor(colors.black)
|
||||
mon.write("Address:\n" .. addressString)
|
||||
end
|
||||
|
||||
function display.showEntity(entityType, entityName, allowed)
|
||||
mon.setTextScale(1)
|
||||
mon.setCursorPos(1, 10)
|
||||
mon.write("Type: " .. entityType)
|
||||
mon.setCursorPos(1, 12)
|
||||
mon.write("Name: " .. entityName)
|
||||
|
||||
if not allowed then
|
||||
mon.setCursorPos(1, 14)
|
||||
mon.setTextColor(colors.red)
|
||||
mon.write("IRIS IMPACT!")
|
||||
mon.setTextColor(colors.white)
|
||||
end
|
||||
end
|
||||
|
||||
function display.showDialing(chevron, symbol, gateType)
|
||||
mon.setBackgroundColor(colors.black)
|
||||
mon.clear()
|
||||
mon.setBackgroundColor(colors.red)
|
||||
mon.setTextScale(2)
|
||||
mon.setCursorPos(2, 3)
|
||||
mon.write("DIALING GATE")
|
||||
mon.setCursorPos(4, 5)
|
||||
mon.write("CHEVERON")
|
||||
mon.setCursorPos(7, 7)
|
||||
mon.setBackgroundColor(colors.black)
|
||||
mon.write(chevron)
|
||||
mon.setBackgroundColor(colors.red)
|
||||
|
||||
if symbol ~= 0 then
|
||||
mon.setCursorPos(4, 9)
|
||||
mon.write("ENGAGED")
|
||||
else
|
||||
mon.setCursorPos(5, 9)
|
||||
mon.setBackgroundColor(colors.green)
|
||||
mon.write("LOCKED")
|
||||
end
|
||||
end
|
||||
|
||||
function display.showConnected(destName, destAddr)
|
||||
mon.setBackgroundColor(colors.green)
|
||||
mon.clear()
|
||||
mon.setTextScale(1)
|
||||
mon.setCursorPos(6, 5)
|
||||
mon.write(destName)
|
||||
|
||||
mon.setCursorPos(3, 10)
|
||||
for i = 1, #destAddr do
|
||||
mon.write(destAddr[i])
|
||||
mon.write(" ")
|
||||
end
|
||||
|
||||
display.drawIrisStatus()
|
||||
end
|
||||
|
||||
function display.showMainMenu()
|
||||
mon.setTextScale(1)
|
||||
mon.setBackgroundColor(colors.black)
|
||||
mon.clear()
|
||||
mon.setCursorPos(9, 1)
|
||||
mon.setBackgroundColor(colors.red)
|
||||
mon.write("press to start")
|
||||
display.drawIrisStatus()
|
||||
end
|
||||
|
||||
return display
|
||||
427
startup.lua
427
startup.lua
@ -0,0 +1,427 @@
|
||||
--[[
|
||||
Stargate Control System - Main Entry Point
|
||||
For Stargate Journey Mod - AllTheMods 9
|
||||
|
||||
Comprehensive control program featuring:
|
||||
- Full dialing system with touch screen interface
|
||||
- Automatic iris control with security features
|
||||
- Incoming/outgoing wormhole management
|
||||
- Address book with categories
|
||||
- Entity tracking and logging
|
||||
- Whitelist/blacklist security
|
||||
]]
|
||||
|
||||
---------------------------------------------
|
||||
-- LOAD MODULES
|
||||
---------------------------------------------
|
||||
|
||||
local config = require("config")
|
||||
local addresses = require("addresses")
|
||||
local utils = require("utils")
|
||||
local display = require("display")
|
||||
|
||||
---------------------------------------------
|
||||
-- INITIALIZATION
|
||||
---------------------------------------------
|
||||
|
||||
-- Find and initialize peripherals
|
||||
local mon = peripheral.find("monitor")
|
||||
local gate = peripheral.find("advanced_crystal_interface")
|
||||
or peripheral.find("crystal_interface")
|
||||
or peripheral.find("basic_interface")
|
||||
|
||||
if gate == nil then
|
||||
error("Stargate interface not found! Please connect an interface.")
|
||||
end
|
||||
|
||||
if mon == nil then
|
||||
error("Monitor not found! Please connect a monitor.")
|
||||
end
|
||||
|
||||
-- Check iris availability
|
||||
if gate.getIris() == nil then
|
||||
print("Config has Iris enabled, but there is no iris! Disabling Iris")
|
||||
config.irisEnabled = false
|
||||
end
|
||||
|
||||
-- Initialize modules
|
||||
utils.init(config, gate)
|
||||
display.init(mon, config, addresses, utils)
|
||||
|
||||
-- Ensure gate starts disconnected
|
||||
gate.disconnectStargate()
|
||||
|
||||
-- Ensure iris starts open
|
||||
if config.irisEnabled then
|
||||
gate.openIris()
|
||||
end
|
||||
|
||||
---------------------------------------------
|
||||
-- GLOBAL STATE
|
||||
---------------------------------------------
|
||||
|
||||
local dialing = false
|
||||
local totalstate = nil
|
||||
local disconnect = false
|
||||
local incomingAddress = {}
|
||||
local incomingEntityType = ""
|
||||
local incomingEntityName = ""
|
||||
local destAddress = {}
|
||||
local destAddressname = ""
|
||||
local selx, sely = 0, 0
|
||||
local y = 0
|
||||
|
||||
---------------------------------------------
|
||||
-- EVENT HANDLERS
|
||||
---------------------------------------------
|
||||
|
||||
local function GetClick()
|
||||
mon.setTextScale(1)
|
||||
local event, _, xPos, yPos = os.pullEvent("monitor_touch")
|
||||
return xPos, yPos
|
||||
end
|
||||
|
||||
local function GetActivation()
|
||||
_, _, incomingAddress = os.pullEvent("stargate_incoming_wormhole")
|
||||
utils.log("Incoming wormhole: " .. gate.addressToString(incomingAddress))
|
||||
return 1
|
||||
end
|
||||
|
||||
local function ParaDisconnect()
|
||||
local dx, dy = 0, 0
|
||||
_, _, dx, dy = os.pullEvent("monitor_touch")
|
||||
|
||||
if (dx ~= 0) and (dy ~= 0) then
|
||||
gate.disconnectStargate()
|
||||
redstone.setOutput("top", false)
|
||||
utils.log("Manual disconnect triggered")
|
||||
end
|
||||
return 1
|
||||
end
|
||||
|
||||
local function EntityRead()
|
||||
sleep(0.1)
|
||||
_, _, incomingEntityType, incomingEntityName, _ = os.pullEvent("stargate_reconstructing_entity")
|
||||
utils.log("Entity reconstructed: " .. incomingEntityName .. " (" .. incomingEntityType .. ")")
|
||||
return 1
|
||||
end
|
||||
|
||||
local function DisconnectCheck()
|
||||
local _, _, disCode = os.pullEvent("stargate_disconnected")
|
||||
redstone.setOutput("top", false)
|
||||
utils.log("Stargate disconnected (code: " .. tostring(disCode) .. ")")
|
||||
|
||||
if config.autoOpenIrisAfterDisconnect then
|
||||
utils.openIris()
|
||||
end
|
||||
|
||||
return 2
|
||||
end
|
||||
|
||||
local function Paratimeout()
|
||||
sleep(300)
|
||||
return 2
|
||||
end
|
||||
|
||||
---------------------------------------------
|
||||
-- INCOMING WORMHOLE HANDLER
|
||||
---------------------------------------------
|
||||
|
||||
local function handleIncomingWormhole()
|
||||
mon.setBackgroundColor(colors.black)
|
||||
mon.clear()
|
||||
mon.setBackgroundColor(colors.red)
|
||||
mon.setTextScale(1)
|
||||
mon.setCursorPos(9, 4)
|
||||
mon.write("INCOMING")
|
||||
|
||||
incomingAddress = utils.addressToTable(incomingAddress)
|
||||
|
||||
-- Check security
|
||||
local allowed, reason = utils.isAddressAllowed(incomingAddress)
|
||||
local addressString = gate.addressToString(incomingAddress) or "Unknown"
|
||||
|
||||
utils.log("Incoming wormhole from: " .. addressString .. " " .. reason)
|
||||
|
||||
-- Show incoming connection status
|
||||
display.showIncoming(addressString, allowed, reason)
|
||||
|
||||
-- Handle iris
|
||||
if config.autoCloseIrisOnIncoming then
|
||||
sleep(config.irisCloseDelay)
|
||||
if allowed then
|
||||
utils.openIris()
|
||||
else
|
||||
utils.closeIris()
|
||||
end
|
||||
end
|
||||
|
||||
-- Monitor for entities
|
||||
disconnect = false
|
||||
while (disconnect == false) do
|
||||
-- parallel.waitForAny runs multiple functions at the same time and returns which one finished first
|
||||
-- Here we're watching for 3 things simultaneously:
|
||||
-- 1 = EntityRead (someone/something came through the gate)
|
||||
-- 2 = DisconnectCheck (gate disconnected on its own)
|
||||
-- ParaDisconnect (user clicked screen to manually disconnect)
|
||||
-- Whichever happens first, that function returns and we handle it
|
||||
local incomingcheck = parallel.waitForAny(EntityRead, DisconnectCheck, ParaDisconnect)
|
||||
if (incomingcheck == 1) then
|
||||
display.showEntity(incomingEntityType, incomingEntityName, allowed)
|
||||
incomingEntityType = ""
|
||||
incomingEntityName = ""
|
||||
else
|
||||
disconnect = true
|
||||
end
|
||||
end
|
||||
disconnect = false
|
||||
end
|
||||
|
||||
---------------------------------------------
|
||||
-- DIALING FUNCTIONS
|
||||
---------------------------------------------
|
||||
|
||||
local function dialGate(address)
|
||||
utils.log("Dialing: " .. gate.addressToString(address))
|
||||
|
||||
local gateType = gate.getStargateType()
|
||||
|
||||
-- Manual Milky Way dialing with ring rotation
|
||||
if gateType == "sgjourney:milky_way_stargate" and config.manualDial == true then
|
||||
local addressLength = #address
|
||||
|
||||
if addressLength == 8 then
|
||||
gate.setChevronConfiguration({ 1, 2, 3, 4, 6, 7, 8, 5 })
|
||||
elseif addressLength == 9 then
|
||||
gate.setChevronConfiguration({ 1, 2, 3, 4, 5, 6, 7, 8 })
|
||||
end
|
||||
|
||||
local start = gate.getChevronsEngaged() + 1
|
||||
|
||||
for chevron = start, addressLength, 1 do
|
||||
local symbol = address[chevron]
|
||||
|
||||
if chevron % 2 == 0 then
|
||||
gate.rotateClockwise(symbol)
|
||||
else
|
||||
gate.rotateAntiClockwise(symbol)
|
||||
end
|
||||
|
||||
while (not gate.isCurrentSymbol(symbol)) do
|
||||
sleep(0)
|
||||
end
|
||||
|
||||
gate.openChevron()
|
||||
sleep(1)
|
||||
gate.closeChevron()
|
||||
sleep(0.5)
|
||||
|
||||
display.showDialing(chevron, symbol, gateType)
|
||||
end
|
||||
else
|
||||
-- Automatic dialing for other gate types
|
||||
if gateType ~= "sgjourney:universe_stargate" then
|
||||
local addressLength = #address
|
||||
if addressLength == 8 then
|
||||
gate.setChevronConfiguration({ 1, 2, 3, 4, 6, 7, 8, 5 })
|
||||
elseif addressLength == 9 then
|
||||
gate.setChevronConfiguration({ 1, 2, 3, 4, 5, 6, 7, 8 })
|
||||
end
|
||||
end
|
||||
|
||||
local start = gate.getChevronsEngaged() + 1
|
||||
|
||||
for chevron = start, #address, 1 do
|
||||
local symbol = address[chevron]
|
||||
|
||||
gate.engageSymbol(symbol)
|
||||
sleep(config.gatespeed)
|
||||
|
||||
display.showDialing(chevron, symbol, gateType)
|
||||
|
||||
if (symbol) ~= 0 then
|
||||
if (gateType == "sgjourney:universe_stargate") or (gateType == "sgjourney:pegasus_stargate") then
|
||||
os.pullEvent("stargate_chevron_engaged")
|
||||
end
|
||||
else
|
||||
if gateType == "sgjourney:universe_stargate" then
|
||||
os.pullEvent("stargate_chevron_engaged")
|
||||
redstone.setOutput("top", true)
|
||||
elseif (gateType == "sgjourney:pegasus_stargate") then
|
||||
os.pullEvent("stargate_chevron_engaged")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function selectGateFromList()
|
||||
local selecting = true
|
||||
while dialing == false and selecting == true do
|
||||
selx, sely = GetClick()
|
||||
local buttonXY, computerAddresses, computerNames = display.getButtonData()
|
||||
|
||||
for i = 1, #buttonXY do
|
||||
if (sely == buttonXY[i][3]) and ((selx >= buttonXY[i][1]) and (selx <= buttonXY[i][2])) then
|
||||
dialGate(computerAddresses[i])
|
||||
destAddressname = computerNames[i]
|
||||
destAddress = computerAddresses[i]
|
||||
dialing = true
|
||||
sely = 0
|
||||
selx = 0
|
||||
elseif sely >= 17 and selx >= 23 then
|
||||
selecting = false
|
||||
sely = 0
|
||||
selx = 0
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
display.clearButtonData()
|
||||
return dialing
|
||||
end
|
||||
|
||||
local function selectCategory()
|
||||
local state = true
|
||||
|
||||
while state == true do
|
||||
display.selectionTabs()
|
||||
|
||||
local tabx, taby = GetClick()
|
||||
y = 2
|
||||
local count = 0
|
||||
|
||||
if (taby >= 2) and (taby <= 6) and ((tabx >= 2) and (tabx <= 13)) then
|
||||
if #addresses.MainGates ~= 0 then
|
||||
mon.setBackgroundColor(colors.black)
|
||||
mon.clear()
|
||||
mon.setBackgroundColor(colors.purple)
|
||||
count, y = display.screenWrite(addresses.MainGates, count, y)
|
||||
|
||||
local returnstate = selectGateFromList()
|
||||
if returnstate == true then
|
||||
state = false
|
||||
end
|
||||
|
||||
display.clearButtonData()
|
||||
else
|
||||
mon.setCursorPos(9, 7)
|
||||
mon.write("no gates available")
|
||||
sleep(5)
|
||||
end
|
||||
|
||||
elseif (taby >= 2) and (taby <= 6) and ((tabx >= 16) and (tabx <= 27)) then
|
||||
if #addresses.playerGates ~= 0 then
|
||||
mon.setBackgroundColor(colors.black)
|
||||
mon.clear()
|
||||
mon.setBackgroundColor(colors.green)
|
||||
count, y = display.screenWrite(addresses.playerGates, count, y)
|
||||
|
||||
local returnstate = selectGateFromList()
|
||||
if returnstate == true then
|
||||
state = false
|
||||
end
|
||||
|
||||
display.clearButtonData()
|
||||
else
|
||||
mon.setCursorPos(9, 7)
|
||||
mon.write("no gates available")
|
||||
sleep(5)
|
||||
end
|
||||
|
||||
elseif (((taby >= 8) and (taby <= 12)) and ((tabx >= 2) and (tabx <= 13))) and (config.canAccessHazardGates == true) then
|
||||
if (#addresses.hazardGates ~= 0) and (config.canAccessHazardGates == true) then
|
||||
mon.setBackgroundColor(colors.black)
|
||||
mon.clear()
|
||||
mon.setBackgroundColor(colors.red)
|
||||
count, y = display.screenWrite(addresses.hazardGates, count, y)
|
||||
|
||||
local returnstate = selectGateFromList()
|
||||
if returnstate == true then
|
||||
state = false
|
||||
end
|
||||
|
||||
display.clearButtonData()
|
||||
else
|
||||
mon.setCursorPos(9, 7)
|
||||
mon.write("no gates available")
|
||||
sleep(5)
|
||||
end
|
||||
|
||||
elseif (taby >= 17) and (tabx >= 23) then
|
||||
state = false
|
||||
totalstate = false
|
||||
end
|
||||
end
|
||||
return 1
|
||||
end
|
||||
|
||||
local function handleOutgoingDial()
|
||||
totalstate = true
|
||||
local PDO = 0
|
||||
|
||||
-- parallel.waitForAny runs functions simultaneously and returns which finished first
|
||||
-- Here we're waiting for either:
|
||||
-- 1 = selectCategory (user selected a gate to dial)
|
||||
-- 2 = Paratimeout (5 minutes passed with no selection)
|
||||
-- This prevents the gate from staying on the selection screen forever
|
||||
PDO = parallel.waitForAny(selectCategory, Paratimeout)
|
||||
|
||||
if (PDO == 1) and totalstate == true then
|
||||
sleep(1)
|
||||
|
||||
os.pullEvent("stargate_outgoing_wormhole")
|
||||
|
||||
display.showConnected(destAddressname, destAddress)
|
||||
|
||||
if (gate.isStargateConnected() == true) then
|
||||
-- parallel.waitForAny runs functions at the same time, returns which finished first
|
||||
-- While the wormhole is open, we wait for:
|
||||
-- DisconnectCheck = gate disconnects naturally (timeout or remote disconnect)
|
||||
-- ParaDisconnect = user manually clicks screen to disconnect
|
||||
-- Paratimeout = safety timeout (5 minutes)
|
||||
-- Whichever happens first ends the connection
|
||||
PDO = parallel.waitForAny(DisconnectCheck, ParaDisconnect, Paratimeout)
|
||||
dialing = false
|
||||
end
|
||||
end
|
||||
|
||||
display.clearButtonData()
|
||||
destAddress = {}
|
||||
destAddressname = ""
|
||||
end
|
||||
|
||||
---------------------------------------------
|
||||
-- MAIN MENU
|
||||
---------------------------------------------
|
||||
|
||||
local function mainMenu()
|
||||
while true do
|
||||
display.showMainMenu()
|
||||
|
||||
-- parallel.waitForAny runs multiple functions simultaneously, returns which completes first
|
||||
-- The main menu waits for any of these events:
|
||||
-- 1 = GetClick (user touched the monitor anywhere - assumes they want to dial out)
|
||||
-- 2 = GetActivation (incoming wormhole detected with address)
|
||||
-- Note: We don't wait for CheveronActivation here because it fires at the same time
|
||||
-- as the incoming wormhole event, causing a race condition where we might miss the address
|
||||
local answer = parallel.waitForAny(GetClick, GetActivation)
|
||||
|
||||
if (answer == 1) then
|
||||
handleOutgoingDial()
|
||||
else
|
||||
handleIncomingWormhole()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
---------------------------------------------
|
||||
-- STARTUP
|
||||
---------------------------------------------
|
||||
|
||||
utils.log("=== Stargate Control System Starting ===")
|
||||
utils.log("Gate Type: " .. gate.getStargateType())
|
||||
utils.log("Iris Available: " .. tostring(config.irisEnabled))
|
||||
|
||||
-- Start the main menu
|
||||
mainMenu()
|
||||
|
||||
826
startup_old.lua
Normal file
826
startup_old.lua
Normal file
@ -0,0 +1,826 @@
|
||||
-- Gate dialing speed (seconds between chevrons for non-Milky Way gates)
|
||||
local gatespeed = 0.5
|
||||
local manualDial = true
|
||||
local canAccessHazardGates = true
|
||||
|
||||
local irisEnabled = true
|
||||
local autoCloseIrisOnIncoming = true
|
||||
local irisCloseDelay = 0.1 -- seconds before closing iris on incoming
|
||||
local autoOpenIrisAfterDisconnect = true
|
||||
|
||||
local whitelist = {
|
||||
{ "Glaive", { 33, 6, 10, 24, 1, 30, 3, 17, 0 } },
|
||||
{ "Moon", { 32, 33, 8, 7, 25, 21, 14, 35, 0 } },
|
||||
{ "Caldoric", { 18, 2, 24, 16, 8, 19, 4, 29, 0 } },
|
||||
{ "Trading Hall", { 16, 19, 6, 18, 35, 27, 9, 8, 0 } }
|
||||
}
|
||||
|
||||
local blacklist = {
|
||||
-- {"DangerGate", {1,2,3,4,5,6,0}},
|
||||
}
|
||||
|
||||
local enableLogging = true
|
||||
local logFile = "stargate.log"
|
||||
|
||||
---------------------------------------------
|
||||
-- ADDRESS BOOK
|
||||
---------------------------------------------
|
||||
|
||||
-- Main Gates (7-chevron addresses for common destinations)
|
||||
local MainGates = {
|
||||
{ "OVERWORLD", { 27, 25, 4, 35, 10, 28, 0 } },
|
||||
{ "Nether", { 27, 23, 4, 34, 12, 28, 0 } },
|
||||
{ "End", { 13, 24, 2, 19, 3, 30, 0 } },
|
||||
{ "Abydos", { 26, 6, 14, 31, 11, 29, 0 } },
|
||||
{ "Chulak", { 8, 1, 22, 14, 36, 19, 0 } }
|
||||
}
|
||||
|
||||
-- Player Gates (typically 9-chevron addresses)
|
||||
local playerGates = {
|
||||
{ "Glaive", { 33, 6, 10, 24, 1, 30, 3, 17, 0 } },
|
||||
{ "Moon", { 32, 33, 8, 7, 25, 21, 14, 35, 0 } },
|
||||
{ "Caldoric", { 18, 2, 24, 16, 8, 19, 4, 29, 0 } },
|
||||
{ "Trading Hall", { 16, 19, 6, 18, 35, 27, 9, 8, 0 } }
|
||||
}
|
||||
|
||||
-- Hazard Gates (dangerous destinations)
|
||||
local hazardGates = {
|
||||
-- Add hazardous gate addresses here
|
||||
}
|
||||
|
||||
---------------------------------------------
|
||||
-- INITIALIZATION
|
||||
---------------------------------------------
|
||||
|
||||
-- Find and initialize peripherals
|
||||
local mon = peripheral.find("monitor")
|
||||
local gate = peripheral.find("advanced_crystal_interface")
|
||||
|
||||
if gate == nil then
|
||||
error("Stargate interface not found! Please connect an interface.")
|
||||
end
|
||||
|
||||
if mon == nil then
|
||||
error("Monitor not found! Please connect a monitor.")
|
||||
end
|
||||
|
||||
-- Ensure gate starts disconnected
|
||||
gate.disconnectStargate()
|
||||
|
||||
-- Ensure iris starts open (unless there's a threat)
|
||||
if irisEnabled then
|
||||
gate.openIris()
|
||||
end
|
||||
|
||||
---------------------------------------------
|
||||
-- GLOBAL VARIABLES
|
||||
---------------------------------------------
|
||||
|
||||
-- Outgoing connection state
|
||||
local destAddress = {}
|
||||
local buttonXY = {}
|
||||
local computerAddresses = {}
|
||||
local computerNames = {}
|
||||
local destAddressname = ""
|
||||
local x, y = 0, 0
|
||||
local selx, sely = 0, 0
|
||||
local dialing = false
|
||||
local totalstate = nil
|
||||
|
||||
-- Incoming connection state
|
||||
local incomingAddress = {}
|
||||
local incomingEntityType = ""
|
||||
local incomingEntityName = ""
|
||||
|
||||
-- Menu state
|
||||
local disconnect = false
|
||||
|
||||
---------------------------------------------
|
||||
-- UTILITY FUNCTIONS
|
||||
---------------------------------------------
|
||||
|
||||
local function deepcopy(orig)
|
||||
local orig_type = type(orig)
|
||||
local copy
|
||||
if orig_type == 'table' then
|
||||
copy = {}
|
||||
for orig_key, orig_value in next, orig, nil do
|
||||
copy[deepcopy(orig_key)] = deepcopy(orig_value)
|
||||
end
|
||||
setmetatable(copy, deepcopy(getmetatable(orig)))
|
||||
else -- number, string, boolean, etc
|
||||
copy = orig
|
||||
end
|
||||
return copy
|
||||
end
|
||||
|
||||
|
||||
local function log(message)
|
||||
if enableLogging then
|
||||
local timestamp = os.date("%Y-%m-%d %H:%M:%S")
|
||||
local logEntry = "[" .. timestamp .. "]\n" .. message
|
||||
-- local logEntry = message
|
||||
|
||||
-- Write to console
|
||||
print(logEntry)
|
||||
|
||||
-- Write to file
|
||||
local file = fs.open(logFile, "a")
|
||||
if file then
|
||||
file.writeLine(logEntry)
|
||||
file.close()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function addressToTable(address)
|
||||
if type(address) == "table" then
|
||||
return address
|
||||
end
|
||||
return {}
|
||||
end
|
||||
|
||||
local function compareAddresses(addr1, addr2)
|
||||
addr1 = gate.addressToString(addr1)
|
||||
addr2 = gate.addressToString(addr2)
|
||||
return addr1 == addr2
|
||||
end
|
||||
|
||||
local function isAddressInList(address, list)
|
||||
for _, entry in ipairs(list) do
|
||||
local listAddr = entry[2]
|
||||
tmp = deepcopy(listAddr)
|
||||
table.remove(tmp)
|
||||
if compareAddresses(address, tmp) then
|
||||
return true, entry[1]
|
||||
end
|
||||
end
|
||||
return false, nil
|
||||
end
|
||||
|
||||
local function isAddressAllowed(address)
|
||||
-- Check blacklist first
|
||||
local isBlacklisted, blackName = isAddressInList(address, blacklist)
|
||||
if isBlacklisted then
|
||||
return false, "Blacklisted: " .. blackName
|
||||
end
|
||||
|
||||
-- If whitelist is not empty, check whitelist
|
||||
if #whitelist > 0 then
|
||||
local isWhitelisted, whiteName = isAddressInList(address, whitelist)
|
||||
if isWhitelisted then
|
||||
return true, "Whitelisted: " .. whiteName
|
||||
else
|
||||
return false, "Not on whitelist"
|
||||
end
|
||||
end
|
||||
|
||||
-- If no whitelist, allow all non-blacklisted
|
||||
return true, "Allowed"
|
||||
end
|
||||
|
||||
---------------------------------------------
|
||||
-- IRIS CONTROL FUNCTIONS
|
||||
---------------------------------------------
|
||||
|
||||
local function closeIris()
|
||||
if irisEnabled then
|
||||
gate.closeIris()
|
||||
log("Iris closed")
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
local function openIris()
|
||||
if irisEnabled then
|
||||
gate.openIris()
|
||||
log("Iris opened")
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
local function getIrisState()
|
||||
if irisEnabled then
|
||||
if gate.getIrisProgressPercentage() == 0 then
|
||||
return "OPEN"
|
||||
else
|
||||
if gate.getIrisProgressPercentage() == 100 then
|
||||
return "CLOSED"
|
||||
else
|
||||
return "MOVING"
|
||||
end
|
||||
end
|
||||
end
|
||||
return "NO IRIS"
|
||||
end
|
||||
|
||||
---------------------------------------------
|
||||
-- DISPLAY FUNCTIONS
|
||||
---------------------------------------------
|
||||
|
||||
local function screenWrite(list, fcount, fy)
|
||||
local internaladdress = {}
|
||||
|
||||
for i = 1, #list do
|
||||
local x1, x2 = 0, 0
|
||||
|
||||
if fcount == 0 then
|
||||
x = 2
|
||||
fcount = 1
|
||||
elseif fcount == 1 then
|
||||
x = 11
|
||||
fcount = 2
|
||||
else
|
||||
x = 20
|
||||
fcount = 0
|
||||
fy = fy + 2
|
||||
end
|
||||
|
||||
mon.setCursorPos(x, fy)
|
||||
mon.write(list[i][1])
|
||||
|
||||
x1 = x
|
||||
x2 = x + 7
|
||||
|
||||
table.insert(buttonXY, { x1, x2, fy })
|
||||
table.insert(computerNames, list[i][1])
|
||||
|
||||
-- list[i][2] is now the address table directly
|
||||
table.insert(computerAddresses, list[i][2])
|
||||
internaladdress = {}
|
||||
end
|
||||
|
||||
local oldterm = term.redirect(mon)
|
||||
paintutils.drawFilledBox(23, 17, 28, 19, colors.red)
|
||||
mon.setCursorPos(24, 18)
|
||||
mon.write("Back")
|
||||
term.redirect(oldterm)
|
||||
|
||||
return fcount, fy
|
||||
end
|
||||
|
||||
local function drawIrisStatus()
|
||||
mon.setCursorPos(1, 19)
|
||||
mon.setBackgroundColor(colors.black)
|
||||
local irisState = getIrisState()
|
||||
if irisState == "OPEN" then
|
||||
mon.setTextColor(colors.green)
|
||||
elseif irisState == "CLOSED" then
|
||||
mon.setTextColor(colors.red)
|
||||
else
|
||||
mon.setTextColor(colors.gray)
|
||||
end
|
||||
mon.write("IRIS: " .. irisState .. " ")
|
||||
mon.setTextColor(colors.white)
|
||||
if irisState == "MOVING" then
|
||||
sleep(0.1)
|
||||
drawIrisStatus()
|
||||
end
|
||||
end
|
||||
|
||||
local function SelectDial()
|
||||
local x1, x2 = 0, 0
|
||||
local count = 0
|
||||
y = 2
|
||||
|
||||
mon.setBackgroundColor(colors.black)
|
||||
mon.clear()
|
||||
|
||||
if #MainGates ~= 0 then
|
||||
mon.setBackgroundColor(colors.purple)
|
||||
count, y = screenWrite(MainGates, count, y)
|
||||
end
|
||||
|
||||
if #playerGates ~= 0 then
|
||||
mon.setBackgroundColor(colors.green)
|
||||
count, y = screenWrite(playerGates, count, y)
|
||||
end
|
||||
|
||||
if (#hazardGates ~= 0) and (canAccessHazardGates == true) then
|
||||
mon.setBackgroundColor(colors.red)
|
||||
count, y = screenWrite(hazardGates, count, y)
|
||||
end
|
||||
|
||||
drawIrisStatus()
|
||||
return 1
|
||||
end
|
||||
|
||||
local function selectionTabs()
|
||||
mon.setBackgroundColor(colors.black)
|
||||
mon.clear()
|
||||
local oldterm = term.redirect(mon)
|
||||
|
||||
if #MainGates ~= 0 then
|
||||
paintutils.drawFilledBox(2, 2, 13, 6, colors.purple)
|
||||
mon.setCursorPos(4, 4)
|
||||
mon.setBackgroundColor(colors.purple)
|
||||
mon.write("Main Gates")
|
||||
end
|
||||
|
||||
if #playerGates ~= 0 then
|
||||
paintutils.drawFilledBox(16, 2, 27, 6, colors.green)
|
||||
mon.setCursorPos(18, 4)
|
||||
mon.setBackgroundColor(colors.green)
|
||||
mon.write("Player")
|
||||
mon.setCursorPos(18, 5)
|
||||
mon.write("Base gates")
|
||||
end
|
||||
|
||||
if (#hazardGates ~= 0) and (canAccessHazardGates == true) then
|
||||
paintutils.drawFilledBox(2, 8, 13, 12, colors.red)
|
||||
mon.setCursorPos(4, 9)
|
||||
mon.setBackgroundColor(colors.red)
|
||||
mon.write("Hazard")
|
||||
mon.setCursorPos(4, 11)
|
||||
mon.write("gates")
|
||||
end
|
||||
|
||||
paintutils.drawFilledBox(23, 17, 28, 19, colors.red)
|
||||
mon.setCursorPos(24, 18)
|
||||
mon.write("Back")
|
||||
|
||||
drawIrisStatus()
|
||||
term.redirect(oldterm)
|
||||
end
|
||||
|
||||
---------------------------------------------
|
||||
-- EVENT HANDLING FUNCTIONS
|
||||
---------------------------------------------
|
||||
|
||||
local function GetClick()
|
||||
mon.setTextScale(1)
|
||||
local event, _, xPos, yPos = os.pullEvent("monitor_touch")
|
||||
return xPos, yPos
|
||||
end
|
||||
|
||||
local function GetActivation()
|
||||
_, _, incomingAddress = os.pullEvent("stargate_incoming_wormhole")
|
||||
return 1
|
||||
end
|
||||
|
||||
local function CheveronActivation()
|
||||
local event, _, _, _, incomingBool = os.pullEvent("stargate_chevron_engaged")
|
||||
if incomingBool == true then
|
||||
log("External dial detected")
|
||||
else
|
||||
log("Internal dial detected")
|
||||
end
|
||||
return 1
|
||||
end
|
||||
|
||||
local function ParaDisconnect()
|
||||
local dx, dy = 0, 0
|
||||
_, _, dx, dy = os.pullEvent("monitor_touch")
|
||||
|
||||
if (dx ~= 0) and (dy ~= 0) then
|
||||
gate.disconnectStargate()
|
||||
redstone.setOutput("top", false)
|
||||
log("Manual disconnect triggered")
|
||||
end
|
||||
return 1
|
||||
end
|
||||
|
||||
local function EntityRead()
|
||||
sleep(0.1)
|
||||
_, _, incomingEntityType, incomingEntityName, _ = os.pullEvent("stargate_reconstructing_entity")
|
||||
log("Entity reconstructed: " .. incomingEntityName .. " (" .. incomingEntityType .. ")")
|
||||
return 1
|
||||
end
|
||||
|
||||
local function DisconnectCheck()
|
||||
local _, _, disCode = os.pullEvent("stargate_disconnected")
|
||||
redstone.setOutput("top", false)
|
||||
log("Stargate disconnected (code: " .. tostring(disCode) .. ")")
|
||||
|
||||
-- Auto-open iris after disconnect
|
||||
if autoOpenIrisAfterDisconnect then
|
||||
openIris()
|
||||
end
|
||||
|
||||
return 2
|
||||
end
|
||||
|
||||
---------------------------------------------
|
||||
-- INCOMING WORMHOLE HANDLER
|
||||
---------------------------------------------
|
||||
|
||||
local function PRIMARYwormholeIncoming()
|
||||
mon.setBackgroundColor(colors.black)
|
||||
mon.clear()
|
||||
mon.setBackgroundColor(colors.red)
|
||||
mon.setTextScale(1)
|
||||
mon.setCursorPos(9, 4)
|
||||
mon.write("INCOMING")
|
||||
|
||||
-- Convert address to table if needed
|
||||
incomingAddress = addressToTable(incomingAddress)
|
||||
|
||||
-- Check security
|
||||
local allowed, reason = isAddressAllowed(incomingAddress)
|
||||
|
||||
-- Try to get address string
|
||||
local addressString = gate.addressToString(incomingAddress) or "Unknown"
|
||||
|
||||
log("Incoming wormhole from: " .. addressString .. " " .. reason)
|
||||
|
||||
mon.setBackgroundColor(colors.black)
|
||||
mon.clear()
|
||||
|
||||
if allowed then
|
||||
mon.setBackgroundColor(colors.green)
|
||||
mon.setTextScale(1)
|
||||
mon.setCursorPos(1, 2)
|
||||
mon.write("INCOMING - AUTHORIZED")
|
||||
|
||||
-- Open iris for authorized connections
|
||||
if autoCloseIrisOnIncoming then
|
||||
sleep(irisCloseDelay)
|
||||
openIris()
|
||||
end
|
||||
else
|
||||
mon.setBackgroundColor(colors.red)
|
||||
mon.setTextScale(1)
|
||||
mon.setCursorPos(1, 2)
|
||||
mon.write("INCOMING - UNAUTHORIZED")
|
||||
mon.setCursorPos(1, 4)
|
||||
mon.write(reason)
|
||||
|
||||
-- Close iris for unauthorized connections
|
||||
if autoCloseIrisOnIncoming then
|
||||
sleep(irisCloseDelay)
|
||||
closeIris()
|
||||
end
|
||||
end
|
||||
|
||||
mon.setCursorPos(1, 6)
|
||||
mon.setBackgroundColor(colors.black)
|
||||
mon.write("Address:")
|
||||
mon.setCursorPos(1, 7)
|
||||
mon.write(addressString)
|
||||
|
||||
-- Monitor for incoming entities
|
||||
disconnect = false
|
||||
while (disconnect == false) do
|
||||
-- parallel.waitForAny runs multiple functions at the same time and returns which one finished first
|
||||
-- Here we're watching for 3 things simultaneously:
|
||||
-- 1 = EntityRead (someone/something came through the gate)
|
||||
-- 2 = DisconnectCheck (gate disconnected on its own)
|
||||
-- ParaDisconnect (user clicked screen to manually disconnect)
|
||||
-- Whichever happens first, that function returns and we handle it
|
||||
local incomingcheck = parallel.waitForAny(EntityRead, DisconnectCheck, ParaDisconnect)
|
||||
if (incomingcheck == 1) then
|
||||
mon.setTextScale(1)
|
||||
mon.setCursorPos(1, 10)
|
||||
mon.write("Type: " .. incomingEntityType)
|
||||
mon.setCursorPos(1, 12)
|
||||
mon.write("Name: " .. incomingEntityName)
|
||||
|
||||
-- Check if entity should be blocked
|
||||
if not allowed then
|
||||
mon.setCursorPos(1, 14)
|
||||
mon.setTextColor(colors.red)
|
||||
mon.write("IRIS IMPACT!")
|
||||
mon.setTextColor(colors.white)
|
||||
end
|
||||
|
||||
incomingEntityType = ""
|
||||
incomingEntityName = ""
|
||||
else
|
||||
disconnect = true
|
||||
end
|
||||
end
|
||||
disconnect = false
|
||||
end
|
||||
|
||||
---------------------------------------------
|
||||
-- DIALING FUNCTIONS
|
||||
---------------------------------------------
|
||||
|
||||
local function Dial(address)
|
||||
log("Dialing: " .. gate.addressToString(address))
|
||||
|
||||
local gateType = gate.getStargateType()
|
||||
|
||||
-- Manual Milky Way dialing with ring rotation
|
||||
if gateType == "sgjourney:milky_way_stargate" and manualDial == true then
|
||||
mon.setBackgroundColor(colors.black)
|
||||
mon.clear()
|
||||
mon.setBackgroundColor(colors.red)
|
||||
mon.setTextScale(2)
|
||||
mon.setCursorPos(2, 3)
|
||||
mon.write("DIALING GATE")
|
||||
|
||||
local addressLength = #address
|
||||
|
||||
if addressLength == 8 then
|
||||
gate.setChevronConfiguration({ 1, 2, 3, 4, 6, 7, 8, 5 })
|
||||
elseif addressLength == 9 then
|
||||
gate.setChevronConfiguration({ 1, 2, 3, 4, 5, 6, 7, 8 })
|
||||
end
|
||||
|
||||
local start = gate.getChevronsEngaged() + 1
|
||||
|
||||
for chevron = start, addressLength, 1 do
|
||||
local symbol = address[chevron]
|
||||
|
||||
if chevron % 2 == 0 then
|
||||
gate.rotateClockwise(symbol)
|
||||
else
|
||||
gate.rotateAntiClockwise(symbol)
|
||||
end
|
||||
|
||||
while (not gate.isCurrentSymbol(symbol)) do
|
||||
sleep(0)
|
||||
end
|
||||
|
||||
gate.openChevron()
|
||||
sleep(1)
|
||||
gate.closeChevron()
|
||||
sleep(0.5)
|
||||
|
||||
mon.setBackgroundColor(colors.black)
|
||||
mon.clear()
|
||||
mon.setBackgroundColor(colors.red)
|
||||
mon.setTextScale(2)
|
||||
mon.setCursorPos(2, 3)
|
||||
mon.write("DIALING GATE")
|
||||
mon.setCursorPos(4, 5)
|
||||
mon.write("CHEVERON")
|
||||
mon.setCursorPos(7, 7)
|
||||
mon.setBackgroundColor(colors.black)
|
||||
mon.write(chevron)
|
||||
mon.setBackgroundColor(colors.red)
|
||||
|
||||
if symbol ~= 0 then
|
||||
mon.setCursorPos(4, 9)
|
||||
mon.write("ENGAGED")
|
||||
else
|
||||
mon.setCursorPos(5, 9)
|
||||
mon.setBackgroundColor(colors.green)
|
||||
mon.write("LOCKED")
|
||||
end
|
||||
end
|
||||
else
|
||||
-- Automatic dialing for other gate types
|
||||
mon.setBackgroundColor(colors.black)
|
||||
mon.clear()
|
||||
mon.setBackgroundColor(colors.red)
|
||||
mon.setTextScale(2)
|
||||
mon.setCursorPos(2, 3)
|
||||
mon.write("DIALING GATE")
|
||||
|
||||
if gateType ~= "sgjourney:universe_stargate" then
|
||||
local addressLength = #address
|
||||
if addressLength == 8 then
|
||||
gate.setChevronConfiguration({ 1, 2, 3, 4, 6, 7, 8, 5 })
|
||||
elseif addressLength == 9 then
|
||||
gate.setChevronConfiguration({ 1, 2, 3, 4, 5, 6, 7, 8 })
|
||||
end
|
||||
end
|
||||
|
||||
local start = gate.getChevronsEngaged() + 1
|
||||
|
||||
for chevron = start, #address, 1 do
|
||||
local symbol = address[chevron]
|
||||
|
||||
gate.engageSymbol(symbol)
|
||||
sleep(gatespeed)
|
||||
|
||||
mon.setBackgroundColor(colors.black)
|
||||
mon.clear()
|
||||
mon.setBackgroundColor(colors.red)
|
||||
mon.setTextScale(2)
|
||||
mon.setCursorPos(2, 3)
|
||||
mon.write("DIALING GATE")
|
||||
mon.setCursorPos(4, 5)
|
||||
mon.write("CHEVERON")
|
||||
mon.setCursorPos(7, 7)
|
||||
mon.setBackgroundColor(colors.black)
|
||||
mon.write(chevron)
|
||||
mon.setBackgroundColor(colors.red)
|
||||
|
||||
if (symbol) ~= 0 then
|
||||
mon.setCursorPos(4, 9)
|
||||
mon.write("ENGAGED")
|
||||
|
||||
if (gateType == "sgjourney:universe_stargate") or (gateType == "sgjourney:pegasus_stargate") then
|
||||
os.pullEvent("stargate_chevron_engaged")
|
||||
end
|
||||
else
|
||||
if gateType == "sgjourney:universe_stargate" then
|
||||
os.pullEvent("stargate_chevron_engaged")
|
||||
redstone.setOutput("top", true)
|
||||
elseif (gateType == "sgjourney:pegasus_stargate") then
|
||||
os.pullEvent("stargate_chevron_engaged")
|
||||
end
|
||||
|
||||
mon.setCursorPos(5, 9)
|
||||
mon.setBackgroundColor(colors.green)
|
||||
mon.write("LOCKED")
|
||||
end
|
||||
end
|
||||
|
||||
address = nil
|
||||
end
|
||||
end
|
||||
|
||||
local function ParaDial()
|
||||
local selecting = true
|
||||
while dialing == false and selecting == true do
|
||||
selx, sely = GetClick()
|
||||
for i = 1, #buttonXY do
|
||||
if (sely == buttonXY[i][3]) and ((selx >= buttonXY[i][1]) and (selx <= buttonXY[i][2])) then
|
||||
Dial(computerAddresses[i])
|
||||
destAddressname = computerNames[i]
|
||||
destAddress = computerAddresses[i]
|
||||
dialing = true
|
||||
sely = 0
|
||||
selx = 0
|
||||
elseif sely >= 17 and selx >= 23 then
|
||||
selecting = false
|
||||
sely = 0
|
||||
selx = 0
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
buttonXY = {}
|
||||
computerAddresses = {}
|
||||
computerNames = {}
|
||||
|
||||
return dialing
|
||||
end
|
||||
|
||||
local function tabSelector()
|
||||
local state = true
|
||||
|
||||
while state == true do
|
||||
mon.setBackgroundColor(colors.black)
|
||||
mon.clear()
|
||||
|
||||
selectionTabs()
|
||||
|
||||
local tabx, taby = GetClick()
|
||||
|
||||
y = 2
|
||||
local count = 0
|
||||
|
||||
if (taby >= 2) and (taby <= 6) and ((tabx >= 2) and (tabx <= 13)) then
|
||||
if #MainGates ~= 0 then
|
||||
mon.setBackgroundColor(colors.black)
|
||||
mon.clear()
|
||||
|
||||
mon.setBackgroundColor(colors.purple)
|
||||
count, y = screenWrite(MainGates, count, y)
|
||||
|
||||
local returnstate = ParaDial()
|
||||
|
||||
if returnstate == true then
|
||||
state = false
|
||||
end
|
||||
|
||||
computerAddresses = {}
|
||||
computerNames = {}
|
||||
else
|
||||
mon.setCursorPos(9, 7)
|
||||
mon.write("no gates available")
|
||||
sleep(5)
|
||||
end
|
||||
elseif (taby >= 2) and (taby <= 6) and ((tabx >= 16) and (tabx <= 27)) then
|
||||
if #playerGates ~= 0 then
|
||||
mon.setBackgroundColor(colors.black)
|
||||
mon.clear()
|
||||
|
||||
mon.setBackgroundColor(colors.green)
|
||||
count, y = screenWrite(playerGates, count, y)
|
||||
|
||||
local returnstate = ParaDial()
|
||||
|
||||
if returnstate == true then
|
||||
state = false
|
||||
end
|
||||
|
||||
computerAddresses = {}
|
||||
computerNames = {}
|
||||
else
|
||||
mon.setCursorPos(9, 7)
|
||||
mon.write("no gates available")
|
||||
sleep(5)
|
||||
end
|
||||
elseif (((taby >= 8) and (taby <= 12)) and ((tabx >= 2) and (tabx <= 13))) and (canAccessHazardGates == true) then
|
||||
if (#hazardGates ~= 0) and (canAccessHazardGates == true) then
|
||||
mon.setBackgroundColor(colors.black)
|
||||
mon.clear()
|
||||
|
||||
mon.setBackgroundColor(colors.red)
|
||||
count, y = screenWrite(hazardGates, count, y)
|
||||
|
||||
local returnstate = ParaDial()
|
||||
|
||||
if returnstate == true then
|
||||
state = false
|
||||
end
|
||||
|
||||
computerAddresses = {}
|
||||
computerNames = {}
|
||||
else
|
||||
mon.setCursorPos(9, 7)
|
||||
mon.write("no gates available")
|
||||
sleep(5)
|
||||
end
|
||||
elseif (taby >= 17) and (tabx >= 23) then
|
||||
state = false
|
||||
totalstate = false
|
||||
end
|
||||
end
|
||||
return 1
|
||||
end
|
||||
|
||||
local function Paratimeout()
|
||||
sleep(300)
|
||||
return 2
|
||||
end
|
||||
|
||||
local function DialText()
|
||||
mon.setBackgroundColor(colors.green)
|
||||
mon.clear()
|
||||
mon.setTextScale(1)
|
||||
mon.setCursorPos(6, 5)
|
||||
mon.write(destAddressname)
|
||||
|
||||
mon.setCursorPos(3, 10)
|
||||
for i = 1, #destAddress do
|
||||
mon.write(destAddress[i])
|
||||
mon.write(" ")
|
||||
end
|
||||
|
||||
drawIrisStatus()
|
||||
|
||||
destAddress = {}
|
||||
destAddressname = ""
|
||||
end
|
||||
|
||||
local function PRIMARYDialingOut()
|
||||
totalstate = true
|
||||
local PDO = 0
|
||||
PDO = parallel.waitForAny(tabSelector, Paratimeout)
|
||||
|
||||
if (PDO == 1) and totalstate == true then
|
||||
sleep(1)
|
||||
|
||||
os.pullEvent("stargate_outgoing_wormhole")
|
||||
|
||||
DialText()
|
||||
|
||||
if (gate.isStargateConnected() == true) then
|
||||
PDO = parallel.waitForAny(DisconnectCheck, ParaDisconnect, Paratimeout)
|
||||
dialing = false
|
||||
end
|
||||
end
|
||||
|
||||
computerAddresses = {}
|
||||
computerNames = {}
|
||||
end
|
||||
|
||||
---------------------------------------------
|
||||
-- MAIN MENU
|
||||
---------------------------------------------
|
||||
|
||||
function Menu()
|
||||
while true do
|
||||
mon.setTextScale(1)
|
||||
mon.setBackgroundColor(colors.black)
|
||||
mon.clear()
|
||||
mon.setCursorPos(9, 1)
|
||||
mon.setBackgroundColor(colors.red)
|
||||
mon.write("press to start")
|
||||
|
||||
drawIrisStatus()
|
||||
local answer = parallel.waitForAny(GetClick, GetActivation)
|
||||
|
||||
if (answer == 1) then
|
||||
PRIMARYDialingOut()
|
||||
else
|
||||
PRIMARYwormholeIncoming()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
---------------------------------------------
|
||||
-- STARTUP
|
||||
---------------------------------------------
|
||||
|
||||
if gate.getIris() == nil then
|
||||
log("Config has Iris enabled, but there is no iris! Disabling Iris")
|
||||
irisEnabled = false
|
||||
end
|
||||
|
||||
-- log("=== Stargate Control System Starting ===")
|
||||
-- log("Gate Type: " .. gate.getStargateType())
|
||||
-- log("Iris Available: " .. tostring(irisEnabled))
|
||||
-- log("Configuration: Manual Dial=" .. tostring(manualDial) .. ", Auto Iris=" .. tostring(autoCloseIrisOnIncoming))
|
||||
|
||||
-- Start the main menu
|
||||
Menu()
|
||||
13
test.lua
13
test.lua
@ -1,13 +0,0 @@
|
||||
shell.run("clear")
|
||||
local interface = peripheral.find("basic_interface") or peripheral.find("crystal_interface") or peripheral.find("advanced_crystal_interface")
|
||||
interface.openIris()
|
||||
while true do
|
||||
local _, _, address = os.pullEvent("stargate_incoming_wormhole")
|
||||
interface.closeIris()
|
||||
print("Incoming connection from " .. interface.addressToString(address))
|
||||
local _, _, _, name, _ = os.pullEvent(stargate_reconstructing_entity)
|
||||
print(name .. " got squished")
|
||||
interface.disconnectStargate()
|
||||
interface.openIris()
|
||||
end
|
||||
|
||||
139
utils.lua
Normal file
139
utils.lua
Normal file
@ -0,0 +1,139 @@
|
||||
--[[
|
||||
Utility Functions
|
||||
Helper functions for logging, address handling, and iris control
|
||||
]]
|
||||
|
||||
local utils = {}
|
||||
|
||||
-- Import config (set by startup.lua)
|
||||
local config
|
||||
local gate
|
||||
|
||||
function utils.init(cfg, gateInterface)
|
||||
config = cfg
|
||||
gate = gateInterface
|
||||
end
|
||||
|
||||
---------------------------------------------
|
||||
-- LOGGING
|
||||
---------------------------------------------
|
||||
|
||||
function utils.log(message)
|
||||
if config.enableLogging then
|
||||
local timestamp = os.date("%Y-%m-%d %H:%M:%S")
|
||||
local logEntry = "[" .. timestamp .. "] " .. message
|
||||
|
||||
-- Write to console
|
||||
print(logEntry)
|
||||
|
||||
-- Write to file
|
||||
local file = fs.open(config.logFile, "a")
|
||||
if file then
|
||||
file.writeLine(logEntry)
|
||||
file.close()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
---------------------------------------------
|
||||
-- ADDRESS UTILITIES
|
||||
---------------------------------------------
|
||||
|
||||
function utils.addressToTable(address)
|
||||
if type(address) == "table" then
|
||||
return address
|
||||
end
|
||||
return {}
|
||||
end
|
||||
|
||||
function utils.compareAddresses(addr1, addr2)
|
||||
addr1 = gate.addressToString(addr1)
|
||||
addr2 = gate.addressToString(addr2)
|
||||
return addr1 == addr2
|
||||
end
|
||||
|
||||
function utils.deepcopy(orig)
|
||||
local orig_type = type(orig)
|
||||
local copy
|
||||
if orig_type == 'table' then
|
||||
copy = {}
|
||||
for orig_key, orig_value in next, orig, nil do
|
||||
copy[utils.deepcopy(orig_key)] = utils.deepcopy(orig_value)
|
||||
end
|
||||
setmetatable(copy, utils.deepcopy(getmetatable(orig)))
|
||||
else
|
||||
copy = orig
|
||||
end
|
||||
return copy
|
||||
end
|
||||
|
||||
function utils.isAddressInList(address, list)
|
||||
for _, entry in ipairs(list) do
|
||||
local listAddr = entry[2]
|
||||
local tmp = utils.deepcopy(listAddr)
|
||||
table.remove(tmp) -- Remove point of origin
|
||||
if utils.compareAddresses(address, tmp) then
|
||||
return true, entry[1]
|
||||
end
|
||||
end
|
||||
return false, nil
|
||||
end
|
||||
|
||||
function utils.isAddressAllowed(address)
|
||||
-- Check blacklist first
|
||||
local isBlacklisted, blackName = utils.isAddressInList(address, config.blacklist)
|
||||
if isBlacklisted then
|
||||
return false, "Blacklisted: " .. blackName
|
||||
end
|
||||
|
||||
-- If whitelist is not empty, check whitelist
|
||||
if #config.whitelist > 0 then
|
||||
local isWhitelisted, whiteName = utils.isAddressInList(address, config.whitelist)
|
||||
if isWhitelisted then
|
||||
return true, "Whitelisted: " .. whiteName
|
||||
else
|
||||
return false, "Not on whitelist"
|
||||
end
|
||||
end
|
||||
|
||||
-- If no whitelist, allow all non-blacklisted
|
||||
return true, "Allowed"
|
||||
end
|
||||
|
||||
---------------------------------------------
|
||||
-- IRIS CONTROL
|
||||
---------------------------------------------
|
||||
|
||||
function utils.closeIris()
|
||||
if config.irisEnabled then
|
||||
gate.closeIris()
|
||||
utils.log("Iris closed")
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
function utils.openIris()
|
||||
if config.irisEnabled then
|
||||
gate.openIris()
|
||||
utils.log("Iris opened")
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
function utils.getIrisState()
|
||||
if config.irisEnabled then
|
||||
local progress = gate.getIrisProgressPercentage()
|
||||
if progress == 0 then
|
||||
return "OPEN"
|
||||
elseif progress == 100 then
|
||||
return "CLOSED"
|
||||
else
|
||||
return "MOVING"
|
||||
end
|
||||
end
|
||||
return "NO IRIS"
|
||||
end
|
||||
|
||||
return utils
|
||||
Reference in New Issue
Block a user