CCCPaste

0ab1a5ff240e6

-- Configuration
local MONITOR_SIDE = "top"
local REDSTONE_SIDE = "back"
local CHATBOX_SIDE = "bottom"
local WHITELIST = {"M_CI_HYPE"}
local CHECK_RADIUS = 3
local SECRET_PASSWORD = "open"
local LOG_FILE = "/disk/main/security_log.txt"
local SERVER_URL = "http://read-whom.gl.at.ply.gg:11738/log"

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

if monitor then
    monitor.setTextScale(1)
end

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

-- State variables
local overrideActive = false
local overrideStartTime = 0
local overrideDuration = 10
local overrideBy = ""
local lastIntruders = {}

-- 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 sendLogToServer(logEntry)
    local success, err = pcall(function()
        local request = http.post(
            SERVER_URL,
            logEntry,
            { ["Content-Type"] = "application/json" }
        )
        
        if request then
            local response = request.readAll()
            request.close()
            print("Log sent to server successfully")
            return true
        else
            print("Failed to connect to log server")
            return false
        end
    end)
    
    if not success then
        print("Error sending log to server: " .. tostring(err))
        return false
    end
    return true
end

function logEvent(username, doorOpened, openedBy)
    local timestamp = os.date("%Y-%m-%d %H:%M:%S")
    local status = doorOpened and "was" or "wasn't"
    local logEntry = textutils.serializeJSON({
        timestamp = timestamp,
        player = username,
        door_opened = doorOpened,
        opened_by = openedBy,
        system = "minecraft_security"
    })
    
    print("Log entry: " .. username .. " - Door " .. status .. " - " .. openedBy)
    
    -- Try to send to remote server first
    local serverSuccess = sendLogToServer(logEntry)
    
    -- Always save locally as backup
    local success, err = pcall(function()
        local logFile = fs.open(LOG_FILE, "a")
        if logFile then
            logFile.writeLine(timestamp .. " - " .. username .. " - Door " .. status .. " - " .. openedBy)
            logFile.close()
            print("Logged locally: " .. LOG_FILE)
            return true
        else
            print("ERROR: Failed to open local log file: " .. LOG_FILE)
            return false
        end
    end)
    
    if not success then
        print("ERROR during local file operation: " .. tostring(err))
    end
end

function getPlayerName(player)
    if type(player) == "string" then
        return player
    elseif type(player) == "table" then
        return player.name or player.username or player.nickname or tostring(player)
    else
        return tostring(player)
    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
                local playerName = getPlayerName(player)
                print("Found player: " .. playerName)
                if playerName == username and isInWhitelist(username) then
                    playerInRange = true
                    break
                end
            end
            
            if playerInRange then
                overrideActive = true
                overrideStartTime = os.clock()
                overrideBy = username
                
                logEvent(username, true, "secret word")
                
                if chatBox then
                    local success, err = pcall(function()
                        chatBox.sendMessageToPlayer(username, "Override activated for " .. overrideDuration .. " seconds")
                    end)
                    
                    if not success then
                        print("Error with sendMessageToPlayer: " .. tostring(err))
                        local success2, err2 = pcall(function()
                            chatBox.sendMessage("Override activated for " .. overrideDuration .. " seconds for " .. username)
                        end)
                    end
                end
                
                print("Override activated by " .. username)
                updateDisplay()
            else
                print("Access denied for " .. username .. " - not in range or not in whitelist")
                if chatBox then
                    local success, err = pcall(function()
                        chatBox.sendMessageToPlayer(username, "Access denied")
                    end)
                    
                    if not success then
                        local success2, err2 = pcall(function()
                            chatBox.sendMessage("Access denied for " .. username)
                        end)
                    end
                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 elapsed = os.clock() - overrideStartTime
        local timeLeft = math.max(0, overrideDuration - elapsed)
        
        if timeLeft > 0 then
            monitor.setCursorPos(1, 2)
            monitor.setTextColor(colors.orange)
            monitor.write("OVERRIDE: " .. string.format("%.1f", timeLeft) .. "s")
            monitor.setCursorPos(1, 3)
            monitor.write("By: " .. overrideBy)
        else
            overrideActive = false
            print("Override expired")
        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
        
        local maxDisplayLines = height - intrudersStartLine - 1
        local displayCount = math.min(#lastIntruders, maxDisplayLines)
        
        for i = 1, displayCount do
            monitor.setCursorPos(1, intrudersStartLine + 1 + i)
            monitor.setTextColor(colors.yellow)
            monitor.write("- " .. lastIntruders[i].name)
        end
        
        if #lastIntruders > maxDisplayLines then
            monitor.setCursorPos(1, height)
            monitor.setTextColor(colors.red)
            monitor.write("+" .. (#lastIntruders - maxDisplayLines) .. " more...")
        end
    end
end

function main()
    print("Starting security system...")
    
    -- Create log file with more verbose error handling
    print("Attempting to create log file: " .. LOG_FILE)
    
    local dir = "/disk/main"
    if not fs.exists(dir) then
        fs.makeDir(dir)
        print("Created directory: " .. dir)
    end
    
    local success, err = pcall(function()
        local logFile = fs.open(LOG_FILE, "w")
        if logFile then
            logFile.writeLine("Security System Log - Started: " .. os.date())
            logFile.close()
            print("Log file created successfully: " .. LOG_FILE)
            return true
        else
            print("ERROR: Could not create log file: " .. LOG_FILE)
            return false
        end
    end)
    
    if not success then
        print("ERROR during file creation: " .. tostring(err))
    end
    
    -- Test remote server connection
    if SERVER_URL ~= "http://your-server-ip:port/log" then
        print("Testing connection to log server...")
        local testSuccess = sendLogToServer(textutils.serializeJSON({
            timestamp = os.date("%Y-%m-%d %H:%M:%S"),
            message = "Connection test from Minecraft security system",
            system = "minecraft_security"
        }))
        
        if testSuccess then
            print("Log server connection successful")
        else
            print("Log server connection failed")
        end
    else
        print("SERVER_URL not configured, remote logging disabled")
    end
    
    -- Initial display update
    updateDisplay()
    
    -- Start listeners
    local parallelFunctions = {}
    
    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 = {}
            
            for _, player in ipairs(players) do
                local playerName = getPlayerName(player)
                
                if playerName then
                    currentPlayers[playerName] = true
                    
                    if isInWhitelist(playerName) then
                        authorized = true
                    else
                        table.insert(intruders, {
                            name = playerName
                        })
                    end
                end
            end
            
            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
            
            lastIntruders = intruders
            previousPlayers = currentPlayers
            
            if overrideActive then
                local elapsed = os.clock() - overrideStartTime
                if elapsed >= overrideDuration then
                    overrideActive = false
                    print("Override expired after " .. elapsed .. " seconds")
                end
            end
            
            local shouldOpen = (authorized and #intruders == 0) or overrideActive
            redstone.setOutput(REDSTONE_SIDE, shouldOpen)
            
            updateDisplay()
            
            os.sleep(0.1)
        end
    end)
    
    print("Starting parallel execution with " .. #parallelFunctions .. " functions")
    parallel.waitForAny(table.unpack(parallelFunctions))
end

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