-- licensed under MIT -- @author jackdotink -- https://github.com/red-blox/Util/blob/main/libs/Signal/Signal.luau -- adapted to work in pure luau type node = { next: node?, callback: (T...) -> (), } export type signal = { root: node?, connect: (self: signal, Callback: (T...) -> ()) -> () -> (), wait: (self: signal) -> T..., once: (self: signal, Callback: (T...) -> ()) -> () -> (), fire: (self: signal, T...) -> (), disconnect_all: (self: signal) -> (), } local Signal = {} Signal.__index = Signal -- Extracted this function from Connect as it results in the closure -- made in Connect using less memory because this function can be static local function disconnect(self: signal, Node: node) if self.root == Node then self.root = Node.next else local Current = self.root while Current do if Current.next == Node then Current.next = Node.next break end Current = Current.next end end end function Signal.connect(self: signal, Callback: (T...) -> ()): () -> () local node = { next = self.root, callback = Callback, } self.root = node return function() disconnect(self, node) end end function Signal.wait(self: signal): T... local Thread = coroutine.running() local Disconnect Disconnect = self:connect(function(...) Disconnect() coroutine.resume(Thread, ...) end) return coroutine.yield() end function Signal.once(self: signal, Callback: (T...) -> ()): () -> () local Disconnect Disconnect = self:connect(function(...) Disconnect() Callback(...) end) return Disconnect end function Signal.fire(self: signal, ...: T...) local Current = self.root while Current do Current.callback(...) Current = Current.next end end function Signal.disconnect_all(self: signal) self.root = nil end return function(): signal return setmetatable({ root = nil, }, Signal) :: any end