added Iris Password system

This commit is contained in:
2025-12-29 00:27:25 -05:00
parent dce10bb02e
commit f493405b48
4 changed files with 332 additions and 73 deletions

View File

@ -27,6 +27,19 @@ config.autoCloseIrisOnIncoming = true
config.irisCloseDelay = 0.1 -- seconds before closing iris on incoming
config.autoOpenIrisAfterDisconnect = true
-- Iris password (set to nil to disable remote password unlock)
config.irisPassword = "1234"
---------------------------------------------
-- MESSAGING
---------------------------------------------
-- Program version (sent to remote gates when connection established)
config.programVersion = "1.0"
-- Enable computer-to-computer messaging through stargate
config.enableMessaging = true
---------------------------------------------
-- SECURITY
---------------------------------------------

View File

@ -219,4 +219,74 @@ function display.showMainMenu()
display.drawIrisStatus()
end
---------------------------------------------
-- PASSWORD PROMPT
---------------------------------------------
function display.showPasswordPrompt()
mon.setBackgroundColor(colors.black)
mon.clear()
mon.setTextScale(1)
mon.setBackgroundColor(colors.blue)
mon.setCursorPos(7, 2)
mon.write("IRIS PASSWORD")
mon.setBackgroundColor(colors.black)
mon.setCursorPos(7, 5)
mon.write("Enter Code:")
-- Draw number pad (3x4 grid)
local oldterm = term.redirect(mon)
-- Numbers 1-9
local row = 7
for i = 1, 9 do
local col = 8 + ((i - 1) % 3) * 5
if (i - 1) % 3 == 0 and i > 1 then
row = row + 3
end
paintutils.drawFilledBox(col, row, col + 3, row + 2, colors.green)
mon.setCursorPos(col + 1, row + 1)
mon.write(tostring(i))
end
-- Bottom row: Clear (0), Zero, Enter
paintutils.drawFilledBox(8, 16, 11, 18, colors.red)
mon.setCursorPos(9, 17)
mon.write("CLR")
paintutils.drawFilledBox(13, 16, 16, 18, colors.green)
mon.setCursorPos(14, 17)
mon.write("0")
paintutils.drawFilledBox(18, 16, 21, 18, colors.blue)
mon.setCursorPos(18, 17)
mon.write("OK")
term.redirect(oldterm)
display.drawIrisStatus()
end
function display.updatePasswordDisplay(password)
mon.setBackgroundColor(colors.black)
mon.setCursorPos(7, 6)
mon.write(string.rep("*", #password) .. " ")
end
function display.showPasswordResult(success)
mon.setBackgroundColor(colors.black)
mon.setCursorPos(7, 10)
if success then
mon.setTextColor(colors.green)
mon.write("ACCESS GRANTED")
mon.setTextColor(colors.white)
else
mon.setTextColor(colors.red)
mon.write("ACCESS DENIED")
mon.setTextColor(colors.white)
end
sleep(2)
end
return display

View File

@ -1,7 +1,7 @@
--[[
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
@ -95,7 +95,7 @@ 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)
@ -115,11 +115,11 @@ 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
@ -128,36 +128,116 @@ local function Paratimeout()
return 2
end
local function GetMessage()
local _, _, message = os.pullEvent("stargate_message_received")
return message
end
local function HandlePasswordEntry()
-- Display password prompt
display.showPasswordPrompt()
local password = ""
local entering = true
while entering do
local x, y = GetClick()
-- Check number buttons (1-9)
if y >= 7 and y <= 15 then
local row = math.floor((y - 7) / 3)
local col = math.floor((x - 8) / 5)
if col >= 0 and col <= 2 and row >= 0 and row <= 2 then
local num = row * 3 + col + 1
if num >= 1 and num <= 9 then
password = password .. tostring(num)
display.updatePasswordDisplay(password)
end
end
end
-- Check bottom row buttons
if y >= 16 and y <= 18 then
if x >= 8 and x <= 11 then
-- Clear button
password = ""
display.updatePasswordDisplay(password)
elseif x >= 13 and x <= 16 then
-- Zero button
password = password .. "0"
display.updatePasswordDisplay(password)
elseif x >= 18 and x <= 21 then
-- OK button - submit password
entering = false
end
end
end
-- Send password attempt
utils.sendPasswordAttempt(password)
return password
end
local function HandleIncomingPasswordRequest(password)
-- Check if password matches
if config.irisPassword and password == config.irisPassword then
utils.log("Correct password received, opening iris")
utils.openIris()
utils.sendPasswordResponse(true)
return true
else
utils.log("Incorrect password received: " .. password)
utils.sendPasswordResponse(false)
return false
end
end
local function MonitorRemoteIris()
-- Continuously monitor remote iris state while connected
local lastIrisState = nil
while gate.isStargateConnected() do
sleep(2) -- Check every 2 seconds
sleep(0.5) -- Check every half second
if transceiver then
local remoteIrisState = transceiver.checkConnectedShielding()
if remoteIrisState and remoteIrisState > 0 then
-- Remote iris closed or closing
if remoteIrisState == 100 then
utils.log("ALERT: Remote iris fully closed during connection!")
-- Only update display if state changed
if remoteIrisState ~= lastIrisState then
if remoteIrisState and remoteIrisState > 0 then
-- Remote iris closed or closing
if remoteIrisState == 100 then
utils.log("ALERT: Remote iris fully closed during connection!")
else
utils.log("ALERT: Remote iris moving: " .. remoteIrisState .. "%")
end
mon.setBackgroundColor(colors.red)
mon.clear()
mon.setTextScale(1)
mon.setCursorPos(6, 5)
mon.write("REMOTE IRIS")
mon.setCursorPos(8, 7)
if remoteIrisState == 100 then
mon.write("CLOSED!")
else
mon.write(remoteIrisState .. "% CLOSED")
end
mon.setCursorPos(3, 10)
mon.write("Connection unsafe")
display.drawIrisStatus()
else
utils.log("ALERT: Remote iris closing: " .. remoteIrisState .. "%")
-- Remote iris is open (0 or nil)
if lastIrisState and lastIrisState > 0 then
-- Iris just opened
utils.log("Remote iris opened - connection safe")
end
display.showConnected(destAddressname, destAddress)
end
mon.setBackgroundColor(colors.red)
mon.clear()
mon.setTextScale(1)
mon.setCursorPos(6, 5)
mon.write("REMOTE IRIS")
mon.setCursorPos(8, 7)
if remoteIrisState == 100 then
mon.write("CLOSED!")
else
mon.write(remoteIrisState .. "% CLOSED")
end
mon.setCursorPos(3, 10)
mon.write("Connection unsafe")
display.drawIrisStatus()
lastIrisState = remoteIrisState
end
end
end
@ -175,18 +255,22 @@ local function handleIncomingWormhole()
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)
-- Send version message to remote gate
sleep(0.5) -- Brief delay to ensure connection is stable
utils.sendVersionMessage()
-- Handle iris
if config.autoCloseIrisOnIncoming then
sleep(config.irisCloseDelay)
@ -196,21 +280,32 @@ local function handleIncomingWormhole()
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:
-- Here we're watching for 4 things simultaneously:
-- 1 = EntityRead (someone/something came through the gate)
-- 2 = DisconnectCheck (gate disconnected on its own)
-- 3 = GetMessage (received a message from remote gate)
-- 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
local result = parallel.waitForAny(EntityRead, DisconnectCheck, GetMessage, ParaDisconnect)
if (result == 1) then
display.showEntity(incomingEntityType, incomingEntityName, allowed)
incomingEntityType = ""
incomingEntityName = ""
elseif (result == 3) then
-- Received a message
local message = GetMessage()
utils.log("Received message: " .. message)
-- Check if it's a password attempt
if message:sub(1, 14) == "IRIS_PASSWORD:" then
local password = message:sub(15)
HandleIncomingPasswordRequest(password)
end
else
disconnect = true
end
@ -223,42 +318,42 @@ end
---------------------------------------------
local function dialGate(address)
tmp = deepCopy(address)
tmp = utils.deepCopy(address)
table.remove(tmp)
utils.log("Dialing: " .. gate.addressToString(tmp))
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
@ -271,17 +366,17 @@ local function dialGate(address)
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")
@ -303,7 +398,7 @@ local function selectGateFromList()
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])
@ -319,78 +414,75 @@ local function selectGateFromList()
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
@ -403,18 +495,65 @@ local function handleOutgoingDial()
totalstate = true
local PDO = 0
PDO = parallel.waitForAny(selectCategory, Paratimeout)
if (PDO == 1) and totalstate == true then
sleep(1)
os.pullEvent("stargate_outgoing_wormhole")
-- Wait briefly for version message from remote gate
local remoteHasComputer = false
local function WaitForVersion()
sleep(1) -- Wait up to 1 second for version message
return nil
end
local result = parallel.waitForAny(GetMessage, WaitForVersion)
if result == 1 then
local message = GetMessage()
if message:sub(1, 6) == "SGCS_V" then
remoteHasComputer = true
local version = message:sub(7)
utils.log("Remote gate has control system version " .. version)
end
end
-- Check if remote iris is closed using transceiver
local remoteIrisState = nil
if transceiver then
remoteIrisState = transceiver.checkConnectedShielding()
end
-- If remote has computer + iris closed, offer password entry
if remoteHasComputer and remoteIrisState and remoteIrisState > 0 then
utils.log("Remote iris closed but computer detected - showing password prompt")
local password = HandlePasswordEntry()
-- Wait for response
local function WaitForResponse()
sleep(3) -- Wait up to 3 seconds for response
return nil
end
result = parallel.waitForAny(GetMessage, WaitForResponse)
if result == 1 then
local response = GetMessage()
if response == "IRIS_OPEN" then
display.showPasswordResult(true)
utils.log("Password accepted - iris opened")
elseif response == "IRIS_DENIED" then
display.showPasswordResult(false)
utils.log("Password rejected")
end
end
-- Re-check iris state after password attempt
if transceiver then
remoteIrisState = transceiver.checkConnectedShielding()
end
end
if remoteIrisState and remoteIrisState > 0 then
-- Remote iris is closed (partially or fully)
if remoteIrisState == 100 then
@ -422,7 +561,7 @@ local function handleOutgoingDial()
else
utils.log("WARNING: Remote iris is " .. remoteIrisState .. "% closed!")
end
mon.setBackgroundColor(colors.red)
mon.clear()
mon.setTextScale(1)
@ -441,7 +580,7 @@ local function handleOutgoingDial()
-- Remote iris is open or no iris present
display.showConnected(destAddressname, destAddress)
end
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:
@ -454,7 +593,7 @@ local function handleOutgoingDial()
dialing = false
end
end
display.clearButtonData()
destAddress = {}
destAddressname = ""
@ -468,7 +607,7 @@ local function mainMenu()
while true do
display.showMainMenu()
local answer = parallel.waitForAny(GetClick, GetActivation)
if (answer == 1) then
handleOutgoingDial()
else

View File

@ -136,4 +136,41 @@ function utils.getIrisState()
return "NO IRIS"
end
---------------------------------------------
-- MESSAGING
---------------------------------------------
function utils.sendVersionMessage()
if config.enableMessaging then
local message = "SGCS_V" .. config.programVersion
gate.sendStargateMessage(message)
utils.log("Sent version message: " .. message)
return true
end
return false
end
function utils.sendPasswordResponse(success)
if config.enableMessaging then
if success then
gate.sendStargateMessage("IRIS_OPEN")
utils.log("Sent iris open confirmation")
else
gate.sendStargateMessage("IRIS_DENIED")
utils.log("Sent iris access denied")
end
return true
end
return false
end
function utils.sendPasswordAttempt(password)
if config.enableMessaging then
gate.sendStargateMessage("IRIS_PASSWORD:" .. password)
utils.log("Sent password attempt")
return true
end
return false
end
return utils