From 74dd72f4783e409bdfacd70e657aff040487fd8d Mon Sep 17 00:00:00 2001 From: Moonlit Productions Date: Mon, 29 Dec 2025 01:15:42 -0500 Subject: [PATCH] entirely rework event handling take 2 --- events.lua | 109 +++++++++++++++++++++++++++ handlers.lua | 202 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 311 insertions(+) create mode 100644 events.lua create mode 100644 handlers.lua diff --git a/events.lua b/events.lua new file mode 100644 index 0000000..5d1fe6e --- /dev/null +++ b/events.lua @@ -0,0 +1,109 @@ +--[[ + Event Management System + Centralized event dispatcher with priority-based routing +]] + +local events = {} + +-- Event queue and handler registry +local eventHandlers = {} +local handlerPriorities = {} + +--------------------------------------------- +-- PRIORITY LEVELS (higher = more priority) +--------------------------------------------- +events.PRIORITY = { + PASSWORD_INPUT = 100, -- Highest priority - password entry + ENTITY_READ = 50, -- Entity tracking + MESSAGE = 50, -- Message handling + DISCONNECT_BUTTON = 30, -- Manual disconnect button + ACTIVATION = 20, -- Incoming wormhole + DISCONNECT_CHECK = 10, -- Natural disconnection + TIMEOUT = 5, -- Timeout handlers + DEFAULT = 1 -- Default priority +} + +--------------------------------------------- +-- HANDLER REGISTRATION +--------------------------------------------- + +function events.registerHandler(eventType, callback, priority) + priority = priority or events.PRIORITY.DEFAULT + + if not eventHandlers[eventType] then + eventHandlers[eventType] = {} + handlerPriorities[eventType] = {} + end + + table.insert(eventHandlers[eventType], callback) + table.insert(handlerPriorities[eventType], priority) +end + +function events.clearHandlers(eventType) + if eventType then + eventHandlers[eventType] = {} + handlerPriorities[eventType] = {} + else + eventHandlers = {} + handlerPriorities = {} + end +end + +--------------------------------------------- +-- EVENT DISPATCHER +--------------------------------------------- + +function events.dispatch(eventType, ...) + local handlers = eventHandlers[eventType] + if not handlers or #handlers == 0 then + return nil + end + + -- Sort handlers by priority (highest first) + local sortedHandlers = {} + for i = 1, #handlers do + table.insert(sortedHandlers, { + callback = handlers[i], + priority = handlerPriorities[eventType][i] + }) + end + + table.sort(sortedHandlers, function(a, b) + return a.priority > b.priority + end) + + -- Call handlers in priority order until one handles the event + for _, handler in ipairs(sortedHandlers) do + local result = handler.callback(...) + if result ~= nil then + return result + end + end + + return nil +end + +--------------------------------------------- +-- EVENT POLLING +--------------------------------------------- + +function events.pullEvent(filter) + while true do + local eventData = {os.pullEvent(filter)} + local eventType = eventData[1] + + local result = events.dispatch(eventType, table.unpack(eventData)) + + -- If a handler processed the event and returned something, return it + if result ~= nil then + return result, eventType, eventData + end + end +end + +function events.waitForAny(...) + local functions = {...} + return parallel.waitForAny(table.unpack(functions)) +end + +return events diff --git a/handlers.lua b/handlers.lua new file mode 100644 index 0000000..095cc09 --- /dev/null +++ b/handlers.lua @@ -0,0 +1,202 @@ +--[[ + Event Handlers + All event handling functions for the stargate control system +]] + +local handlers = {} + +-- Module references (set by init) +local config, gate, mon, utils, display, events + +-- State variables +local state = { + incomingAddress = {}, + incomingEntityType = "", + incomingEntityName = "", + lastReceivedMessage = nil, + enteringPassword = false, + remoteHasComputer = false, + destAddress = {}, + destAddressname = "" +} + +function handlers.init(cfg, gateInterface, monitor, utilsModule, displayModule, eventsModule) + config = cfg + gate = gateInterface + mon = monitor + utils = utilsModule + display = displayModule + events = eventsModule +end + +function handlers.getState() + return state +end + +--------------------------------------------- +-- CLICK HANDLER (Priority-based) +--------------------------------------------- + +function handlers.handleMonitorTouch(eventType, side, x, y) + -- This is called by the event dispatcher for monitor_touch events + -- Returns nil to allow lower priority handlers to process if needed + return nil +end + +--------------------------------------------- +-- PASSWORD INPUT HANDLER (Highest Priority) +--------------------------------------------- + +function handlers.handlePasswordInput() + display.showPasswordPrompt() + + local password = "" + state.enteringPassword = true + + -- Register high-priority click handler for password input + local function passwordClickHandler(eventType, side, x, y) + if not state.enteringPassword then + return nil -- No longer active, let other handlers process + end + + -- 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) + return true -- Event consumed + 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) + return true + elseif x >= 13 and x <= 16 then + -- Zero button + password = password .. "0" + display.updatePasswordDisplay(password) + return true + elseif x >= 18 and x <= 21 then + -- OK button - submit password + state.enteringPassword = false + return "submit" + end + end + + return true -- Consume all clicks during password entry + end + + -- Register the password handler with highest priority + events.registerHandler("monitor_touch", passwordClickHandler, events.PRIORITY.PASSWORD_INPUT) + + -- Wait for password submission + while state.enteringPassword do + local result = events.pullEvent("monitor_touch") + if result == "submit" then + break + end + end + + -- Unregister the password handler + events.clearHandlers("monitor_touch") + + -- Send password attempt + utils.sendPasswordAttempt(password) + + return password +end + +--------------------------------------------- +-- DISCONNECT BUTTON HANDLER +--------------------------------------------- + +function handlers.handleDisconnectButton(eventType, side, x, y) + -- Only process if not entering password (password handler has higher priority) + if state.enteringPassword then + return nil + end + + -- Check if clicking disconnect button (bottom-right corner) + if y >= 17 and y <= 19 and x >= 20 and x <= 28 then + gate.disconnectStargate() + redstone.setOutput("top", false) + utils.log("Manual disconnect triggered") + return "disconnect" + end + + return nil -- Not a disconnect button click +end + +--------------------------------------------- +-- ACTIVATION HANDLER +--------------------------------------------- + +function handlers.handleActivation(eventType, side, address) + state.incomingAddress = address + utils.log("Incoming wormhole: " .. gate.addressToString(address)) + return "activation" +end + +--------------------------------------------- +-- ENTITY READ HANDLER +--------------------------------------------- + +function handlers.handleEntityRead(eventType, side, entityType, entityName, ...) + sleep(0.1) + state.incomingEntityType = entityType + state.incomingEntityName = entityName + utils.log("Entity reconstructed: " .. entityName .. " (" .. entityType .. ")") + return "entity" +end + +--------------------------------------------- +-- DISCONNECT CHECK HANDLER +--------------------------------------------- + +function handlers.handleDisconnect(eventType, side, disCode) + redstone.setOutput("top", false) + utils.log("Stargate disconnected (code: " .. tostring(disCode) .. ")") + + if config.autoOpenIrisAfterDisconnect then + utils.openIris() + end + + return "disconnected" +end + +--------------------------------------------- +-- MESSAGE HANDLER +--------------------------------------------- + +function handlers.handleMessage(eventType, side, message) + state.lastReceivedMessage = message + return "message" +end + +--------------------------------------------- +-- SETUP EVENT HANDLERS +--------------------------------------------- + +function handlers.setupConnectionHandlers() + -- Clear any existing handlers + events.clearHandlers() + + -- Register all handlers with their priorities + events.registerHandler("monitor_touch", handlers.handleDisconnectButton, events.PRIORITY.DISCONNECT_BUTTON) + events.registerHandler("stargate_incoming_wormhole", handlers.handleActivation, events.PRIORITY.ACTIVATION) + events.registerHandler("stargate_reconstructing_entity", handlers.handleEntityRead, events.PRIORITY.ENTITY_READ) + events.registerHandler("stargate_disconnected", handlers.handleDisconnect, events.PRIORITY.DISCONNECT_CHECK) + events.registerHandler("stargate_message_received", handlers.handleMessage, events.PRIORITY.MESSAGE) +end + +return handlers