-- 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