hooksignal Synchronous

Intercept Lua listeners on a Roblox event before they receive each firing. You can inspect a listener call, let it through, change its arguments, or suppress it while you investigate event behavior.

Syntax
Luau
hooksignal(
    signal: RBXScriptSignal,
    callback: (info: HookSignalInfo, ...args: any) -> (boolean, ...any)
) -> ()

Parameters

Function parameters
ParameterTypeDescription
signalRBXScriptSignalRBXScriptSignal to intercept.
callback(info: HookSignalInfo, ...args: any) -> (boolean, ...any)Called before each intercepted listener or new Wait result. Return false to suppress delivery, true to pass the original arguments, or true followed by replacement arguments.

Argument fields

HookSignalInfo fields
Luau
HookSignalInfo = {Connection: Connection?, Function: Function?, Index: number?}
FieldTypeDescription
ConnectionConnection?The intercepted RBXScriptConnection. Nil for a Wait call.
FunctionFunction?The listener’s original Lua callback. Nil for a Wait call.
Indexnumber?The listener’s zero-based position at interception time. Nil for a Wait call.
Connection fields
Luau
Connection = {
  Enabled: boolean, ForeignState: boolean, LuaConnection: boolean,
  Function: Function?, Thread: thread?
}

Returns

()

No values. The hook stays active until restoresignal is called.

Usage notes

The first callback argument is HookSignalInfo. For a connected listener, Connection is its connection, Function is its original Lua callback, and Index is its zero-based position. A Wait call receives an empty info table.

Existing Lua listeners are wrapped when the hook is installed. Later Connect, Once, ConnectParallel, and Wait calls are intercepted when their methods are looked up after installation. A method reference saved earlier or a Wait already in progress is unaffected.

The callback may yield; the listener or Wait receives its result after the callback returns. When a Wait callback suppresses delivery, that thread keeps waiting for a later firing, and an error raised by the callback reaches the waiting thread.

Installing another hook on the same signal replaces the previous one; restore the hook when you finish.

Example

Example
Luau
local event = Instance.new("BindableEvent")
local listener = event.Event:Connect(function(message)
    print("Received:", message)
end)

hooksignal(event.Event, function(info, message)
    if info.Function then print("Listener index:", info.Index) end
    if message == "ignore" then return false end
    return true, string.upper(message)
end)

event:Fire("hello")  -- listener receives HELLO
event:Fire("ignore") -- listener is skipped
task.wait()
restoresignal(event.Event)
listener:Disconnect()
event:Destroy()