diff --git a/addons/observers.luau b/addons/observers.luau index 9656781..fdf256e 100755 --- a/addons/observers.luau +++ b/addons/observers.luau @@ -1,9 +1,10 @@ +--!strict local jecs = require("@jecs") export type PatchedWorld = jecs.World & { - added: (PatchedWorld, jecs.Id, (e: jecs.Entity, id: jecs.Id, value: T) -> ()) -> () -> (), + added: (PatchedWorld, jecs.Id, (e: jecs.Entity, id: jecs.Id, value: T?) -> ()) -> () -> (), removed: (PatchedWorld, jecs.Id, (e: jecs.Entity, id: jecs.Id) -> ()) -> () -> (), - changed: (PatchedWorld, jecs.Id, (e: jecs.Entity, id: jecs.Id, value: T) -> ()) -> () -> (), + changed: (PatchedWorld, jecs.Id, (e: jecs.Entity, id: jecs.Id, value: T) -> ()) -> () -> (), observer: ( PatchedWorld, jecs.Query, @@ -16,28 +17,41 @@ export type PatchedWorld = jecs.World & { ) -> () } -local function observers_new(world, query, callback) - local terms = query.filter_with :: { jecs.Id } - if not terms then - local ids = query.ids - query.filter_with = ids - terms = ids +local function observers_new( + world: PatchedWorld, + query: any, + callback: ((jecs.Entity, jecs.Id, value: a?) -> ())? +) + query = query:cached() + + local archetypes = {} + local terms = query.ids + local first = terms[1] + + local observers_on_create = world.observable[jecs.ArchetypeCreate][first] + observers_on_create[#observers_on_create].callback = function(archetype) + archetypes[archetype.id] = true + end + local observers_on_delete = world.observable[jecs.ArchetypeDelete][first] + observers_on_delete[#observers_on_delete].callback = function(archetype) + archetypes[archetype.id] = nil end local entity_index = world.entity_index :: any local i = 0 local entities = {} - local function emplaced(entity, id, value) - local r = jecs.entity_index_try_get_fast( - entity_index, entity :: any) - if not r then - return - end + local function emplaced( + entity: jecs.Entity, + id: jecs.Id, + value: a? + ) + local r = jecs.entity_index_try_get_fast( + entity_index, entity :: any) :: jecs.Record local archetype = r.archetype - if jecs.query_match(query, archetype) then + if archetypes[archetype.id] then i += 1 entities[i] = entity if callback ~= nil then @@ -110,27 +124,36 @@ local function join(world, component) end local function monitors_new(world, query, callback) - local terms = query.filter_with :: { jecs.Id } - if not terms then - local ids = query.ids - query.filter_with = ids - terms = ids + query = query:cached() + + local archetypes = {} + local terms = query.ids + local first = terms[1] + + local observers_on_create = world.observable[jecs.ArchetypeCreate][first] + observers_on_create[#observers_on_create].callback = function(archetype) + archetypes[archetype.id] = true + end + local observers_on_delete = world.observable[jecs.ArchetypeDelete][first] + observers_on_delete[#observers_on_delete].callback = function(archetype) + archetypes[archetype.id] = nil end local entity_index = world.entity_index :: any local i = 0 local entities = {} - local function emplaced(entity, id, value) - local r = jecs.entity_index_try_get_fast( - entity_index, entity :: any) - if not r then - return - end + local function emplaced( + entity: jecs.Entity, + id: jecs.Id, + value: a? + ) + local r = jecs.entity_index_try_get_fast( + entity_index, entity :: any) :: jecs.Record local archetype = r.archetype - if jecs.query_match(query, archetype) then + if archetypes[archetype.id] then i += 1 entities[i] = entity if callback ~= nil then