Allow to disconnect signals

This commit is contained in:
Ukendio 2025-04-25 22:07:22 +02:00
parent cb238ab29e
commit 5b31a1af22

View file

@ -93,14 +93,16 @@ local function monitors_new(world, description)
end end
local function observers_add(world: jecs.World & { [string]: any }): PatchedWorld local function observers_add(world: jecs.World & { [string]: any }): PatchedWorld
type Signal = { [jecs.Entity]: { (...any) -> () } }
local signals = { local signals = {
added = {}, added = {} :: Signal,
emplaced = {}, emplaced = {} :: Signal,
removed = {} removed = {} :: Signal
} }
world.added = function(_, component, fn) world.added = function(_, component, fn)
local listeners = signals.added[component] local listeners = signals.added[component]
local max = #listeners + 1
local component_index = world.component_index :: jecs.ComponentIndex local component_index = world.component_index :: jecs.ComponentIndex
assert(component_index[component] == nil, "You cannot use hooks on components you intend to use this signal with") assert(component_index[component] == nil, "You cannot use hooks on components you intend to use this signal with")
if not listeners then if not listeners then
@ -115,14 +117,22 @@ local function observers_add(world: jecs.World & { [string]: any }): PatchedWorl
world:set(component, jecs.OnAdd, on_add) world:set(component, jecs.OnAdd, on_add)
end end
table.insert(listeners, fn) table.insert(listeners, fn)
listeners[max] = fn
return function()
local n = #listeners
listeners[max] = listeners[n]
listeners[n] = nil
end
end end
world.changed = function(_, component, fn) world.changed = function(_, component, fn)
local listeners = signals.emplaced[component] local listeners = signals.emplaced[component]
local max = 0
local component_index = world.component_index :: jecs.ComponentIndex local component_index = world.component_index :: jecs.ComponentIndex
assert(component_index[component] == nil, "You cannot use hooks on components you intend to use this signal with") assert(component_index[component] == nil, "You cannot use hooks on components you intend to use this signal with")
if not listeners then if not listeners then
listeners = {} listeners = {}
max = 1
signals.emplaced[component] = listeners signals.emplaced[component] = listeners
local function on_change(entity: number, id: number, value: any) local function on_change(entity: number, id: number, value: any)
for _, listener in listeners :: any do for _, listener in listeners :: any do
@ -130,12 +140,20 @@ local function observers_add(world: jecs.World & { [string]: any }): PatchedWorl
end end
end end
world:set(component, jecs.OnChange, on_change) world:set(component, jecs.OnChange, on_change)
else
max = #listeners + 1
end
listeners[max] = fn
return function()
local n = #listeners
listeners[max] = listeners[n]
listeners[n] = nil
end end
table.insert(listeners, fn)
end end
world.removed = function(_, component, fn) world.removed = function(_, component, fn)
local listeners = signals.removed[component] local listeners = signals.removed[component]
local max = #listeners
local component_index = world.component_index :: jecs.ComponentIndex local component_index = world.component_index :: jecs.ComponentIndex
assert(component_index[component] == nil, "You cannot use hooks on components you intend to use this signal with") assert(component_index[component] == nil, "You cannot use hooks on components you intend to use this signal with")
if not listeners then if not listeners then
@ -148,7 +166,12 @@ local function observers_add(world: jecs.World & { [string]: any }): PatchedWorl
end end
world:set(component, jecs.OnRemove, on_remove) world:set(component, jecs.OnRemove, on_remove)
end end
table.insert(listeners, fn) listeners[max] = fn
return function()
local n = #listeners
listeners[max] = listeners[n]
listeners[n] = nil
end
end end
world.signals = signals world.signals = signals