Builtin Library
README.md
signal
Event primitive. A producer holds a Signal; consumers attach handlers
with :Connect and the producer invokes them with :Fire(...).
local Signal = require("@builtin::modules.signal")
local hit = Signal.new()
local conn = hit:Connect(function(dmg) print("hit for", dmg) end)
hit:Fire(10) -- runs every handler with (10)
conn:Disconnect() -- detach this handler
API
Signal.new() -> Signalsignal:Connect(fn) -> Connection— attach a handler; runs on each:Firein attachment order.signal:Once(fn) -> Connection— fire at most once, then self-disconnect.signal:Wait() -> ...— yield the calling coroutine until the next:Fire, returning its arguments. Call from inside a coroutine (e.g. atask.spawnbody).signal:Fire(...)— invoke every handler with the arguments. A handler that raises is caught and logged; the rest still run.signal:DisconnectAll()— detach every handler.connection:Disconnect()— detach one handler (idempotent).connection.Connected— boolean, false once disconnected.
Handlers run synchronously and must not yield. The connection list is snapshotted before a fire, so a handler may disconnect itself or others mid-fire without skipping a handler.
Auto-cleanup
A connection made while a script component is on the call stack is tagged with that component instance and its entity, and it ends with whichever goes first:
- Removing the component from its entity (
component.remove), or hot-reloading it, disconnects every connection the instance made. - Destroying the entity disconnects every connection it sourced, after the
entity's
onDestroyedfires, so a component's handler on its own entity'sonDestroyedstill runs after the component'sonDestroy(driven by the entity-destroy dispatch inentity_signals.module).
A component never has to track and tear down its own connections.