CCCPaste

9f0644d1c3b44

-- Configuration
local MONITOR_SIDE = "top"
local REDSTONE_SIDE = "back"
local CHATBOX_SIDE = "bottom"
local WHITELIST = {"M_CI_HYPE"} -- Fixed nickname
local CHECK_RADIUS = 20
local SECRET_PASSWORD = "open"
local LOG_FILE = "security_log.txt"

-- Peripheral initialization
local playerDetector = peripheral.find("playerDetector")
local monitor = peripheral.find("monitor")
local chatBox = peripheral.find("chatBox")

if monitor then
    monitor.setTextScale(0.5)
end

-- Colors
local colors = {
    green = 32768,
    yellow = 16,
    white = 1,
    red = 16384,
    orange = 4
}

-- State variables
local currentPage = 1
local lastIntruders = {}
local lastTouchTime = 0
local touchCooldown = 0.5
local overrideActive = false
local overrideEndTime = 0
local overrideDuration = 10
local overrideBy = ""

-- Tracking for logging
local playersInZone = {}

function isInWhitelist(username)
    for _, whitelistedName in ipairs(WHITELIST) do
        if whitelistedName == username then
            return true
        end
    end
    return false
end

function logEvent(username, doorOpened, openedBy)
    local timestamp = os.date("%H:%M:%S")
    local status = doorOpened and "was" or "wasn't"
    local logEntry = "Player detected: " .. username .. ", time: " .. timestamp .. 
                    ". Door " .. status .. " opened. Opened by: " .. openedBy
    
    print("Attempting to log: " .. logEntry)
    
    -- Save to file
    local logFile = fs.open(LOG_FILE, "a")
    if logFile then
        logFile.writeLine(logEntry)
        logFile.close()
        print("Successfully logged to file")
    else
        print("ERROR: Failed to open log file for writing")
    end
end

function handleMonitorTouch()
    while true do
        local event, side, x, y = os.pullEvent("monitor_touch")
        local currentTime = os.clock()
        
        if currentTime - lastTouchTime > touchCooldown then
            lastTouchTime = currentTime
            
            if #lastIntruders > 0 then
                currentPage = currentPage + 1
                if currentPage > #lastIntruders then
                    currentPage = 1
                end
                updateDisplay()
            end
        end
    end
end

function handleChat()
    while true do
        local event, username, message, uuid = os.pullEvent("chat")
        print("Chat received from " .. username .. ": " .. message)
        
        if message:lower() == SECRET_PASSWORD then
            local players = playerDetector.getPlayersInRange(CHECK_RADIUS)
            local playerInRange = false
            
            print("Checking players in range for " .. username)
            for _, player in ipairs(players) do
                if player and player.name then -- Added nil check
                    print("Found player: " .. player.name)
                    if player.name == username and isInWhitelist(username) then
                        playerInRange = true
                        break
                    end
                end
            end
            
            if playerInRange then
                overrideActive = true
                overrideEndTime = os.time() + overrideDuration
                overrideBy = username
                
                logEvent(username, true, "secret word")
                
                if chatBox then
                    chatBox.sendMessageToPlayer(username, "Override activated for " .. overrideDuration .. " seconds")
                end
                
                print("Override activated by " .. username)
                updateDisplay()
            else
                print("Access denied for " .. username .. " - not in range or not in whitelist")
                if chatBox then
                    chatBox.sendMessageToPlayer(username, "Access denied")
                end
            end
        end
    end
end

function updateDisplay()
    if not monitor then 
        print("No monitor found")
        return 
    end
    
    monitor.clear()
    local width, height = monitor.getSize()
    
    monitor.setCursorPos(1, 1)
    monitor.setTextColor(colors.white)
    monitor.write("Access Control System")
    
    if overrideActive then
        local timeLeft = overrideEndTime - os.time()
        if timeLeft > 0 then
            monitor.setCursorPos(1, 2)
            monitor.setTextColor(colors.orange)
            monitor.write("OVERRIDE: " .. timeLeft .. "s")
            monitor.setCursorPos(1, 3)
            monitor.write("By: " .. overrideBy)
        else
            overrideActive = false
        end
    end
    
    local doorStatusLine = overrideActive and 4 or 2
    monitor.setCursorPos(1, doorStatusLine)
    
    if #lastIntruders == 0 or overrideActive then
        monitor.setTextColor(colors.green)
        monitor.write("ACCESS GRANTED")
    else
        monitor.setTextColor(colors.red)
        monitor.write("ACCESS DENIED")
    end
    
    local intrudersStartLine = doorStatusLine + 2
    
    if #lastIntruders == 0 then
        monitor.setCursorPos(1, intrudersStartLine)
        monitor.setTextColor(colors.green)
        monitor.write("Area secure")
        monitor.setCursorPos(1, intrudersStartLine + 1)
        monitor.write("No intruders detected")
    else
        monitor.setCursorPos(1, intrudersStartLine)
        if overrideActive then
            monitor.setTextColor(colors.orange)
            monitor.write("Warning: " .. #lastIntruders .. " strangers")
        else
            monitor.setTextColor(colors.yellow)
            monitor.write("Warning: " .. #lastIntruders .. " strangers")
        end
        
        monitor.setCursorPos(1, intrudersStartLine + 1)
        monitor.setTextColor(colors.white)
        monitor.write("Viewing: " .. currentPage .. "/" .. #lastIntruders)
        
        local intruder = lastIntruders[currentPage]
        if intruder then
            monitor.setCursorPos(1, intrudersStartLine + 3)
            monitor.setTextColor(colors.yellow)
            monitor.write("Name: " .. intruder.name)
            monitor.setCursorPos(1, intrudersStartLine + 4)
            monitor.write("Max HP: " .. intruder.maxHealth)
        end
        
        if monitor.isColor() then
            monitor.setCursorPos(1, height)
            monitor.setTextColor(colors.white)
            monitor.write("Touch screen to cycle")
        end
    end
end

function main()
    print("Starting security system...")
    
    -- Create log file with more verbose error handling
    local logFile = fs.open(LOG_FILE, "a")
    if logFile then
        logFile.writeLine("Security System Log - Started: " .. os.date())
        logFile.close()
        print("Log file created/accessed successfully")
    else
        print("ERROR: Could not create or access log file")
    end
    
    -- Initial display update
    updateDisplay()
    
    -- Start listeners
    local parallelFunctions = {}
    
    if monitor and monitor.isColor() then
        table.insert(parallelFunctions, function()
            print("Starting touch listener")
            handleMonitorTouch()
        end)
    end
    
    if chatBox then
        table.insert(parallelFunctions, function()
            print("Starting chat listener")
            handleChat()
        end)
    end
    
    -- Main detection loop
    table.insert(parallelFunctions, function()
        print("Starting main detection loop")
        local previousPlayers = {}
        
        while true do
            local players = playerDetector.getPlayersInRange(CHECK_RADIUS) or {}
            local authorized = false
            local intruders = {}
            local currentPlayers = {}
            
            print("Players in range: " .. #players)
            
            -- Track current players for logging
            for _, player in ipairs(players) do
                if player and player.name then  -- Added nil check
                    print("Processing player: " .. player.name)
                    currentPlayers[player.name] = true
                    
                    if isInWhitelist(player.name) then
                        authorized = true
                        print("Authorized player detected: " .. player.name)
                    else
                        print("Intruder detected: " .. player.name)
                        table.insert(intruders, {
                            name = player.name,
                            maxHealth = math.floor(player.maxHealth or 20)
                        })
                    end
                else
                    print("WARNING: Found player with nil name")
                end
            end
            
            -- Log player entries (only when they first enter)
            for playerName, _ in pairs(currentPlayers) do
                if not previousPlayers[playerName] then
                    print("New player entered zone: " .. playerName)
                    local doorOpened = (authorized and #intruders == 0) or overrideActive
                    local openedBy = overrideActive and "secret word" or "auto"
                    logEvent(playerName, doorOpened, openedBy)
                end
            end
            
            -- Reset page if intruder list changed
            if #intruders ~= #lastIntruders then
                currentPage = 1
            end
            
            lastIntruders = intruders
            previousPlayers = currentPlayers
            
            -- Check if override has expired
            if overrideActive and os.time() > overrideEndTime then
                overrideActive = false
                print("Override expired")
            end
            
            -- Control door
            local shouldOpen = (authorized and #intruders == 0) or overrideActive
            redstone.setOutput(REDSTONE_SIDE, shouldOpen)
            
            -- Update display
            updateDisplay()
            
            os.sleep(0.5)
        end
    end)
    
    -- Run all functions in parallel
    print("Starting parallel execution with " .. #parallelFunctions .. " functions")
    parallel.waitForAny(table.unpack(parallelFunctions))
end

-- Error handling
print("Initializing security system...")
local ok, err = pcall(main)
if not ok then
    print("System error: " .. err)
    if monitor then
        monitor.clear()
        monitor.setCursorPos(1, 1)
        monitor.setTextColor(colors.red)
        monitor.write("SYSTEM ERROR")
        monitor.setCursorPos(1, 2)
        monitor.write(tostring(err))
    end
end