11local jecs = require ("@jecs" )
2- local testkit = require ("@testkit" )
2+
3+ type Observer <T ...> = {
4+ callback : (jecs .Entity ) -> (),
5+ query : jecs .Query <T ...>,
6+ }
7+
8+ export type PatchedWorld = jecs .World & {
9+ added : (PatchedWorld , jecs .Id , (e : jecs .Entity , id : jecs .Id , value : any ) -> ()) -> (),
10+ removed : (PatchedWorld , jecs .Id , (e : jecs .Entity , id : jecs .Id ) -> ()) -> (),
11+ changed : (PatchedWorld , jecs .Id , (e : jecs .Entity , id : jecs .Id ) -> ()) -> (),
12+ observer : (PatchedWorld , Observer <any >) -> (),
13+ monitor : (PatchedWorld , Observer <any >) -> (),
14+ }
315
416local function observers_new (world , description )
517 local query = description .query
618 local callback = description .callback
7- local terms = query .filter_with
19+ local terms = query .filter_with :: { jecs . Id }
820 if not terms then
921 local ids = query .ids
1022 query .filter_with = ids
1123 terms = ids
1224 end
1325
14- local entity_index = world .entity_index
15- local function emplaced (entity )
26+ local entity_index = world .entity_index :: any
27+ local function emplaced (entity : jecs . Entity )
1628 local r = jecs .entity_index_try_get_fast (
17- entity_index , entity )
29+ entity_index , entity :: any )
1830
1931 if not r then
2032 return
@@ -33,74 +45,60 @@ local function observers_new(world, description)
3345 end
3446end
3547
36- local function world_track (world , ... )
37- local entity_index = world .entity_index
38- local terms = { ... }
39- local q_shim = { filter_with = terms }
40-
41- local n = 0
42- local dense_array = {}
43- local sparse_array = {}
48+ local function monitors_new (world , description )
49+ local query = description .query
50+ local callback = description .callback
51+ local terms = query .filter_with :: { jecs .Id }
52+ if not terms then
53+ local ids = query .ids
54+ query .filter_with = ids
55+ terms = ids
56+ end
4457
45- local function emplaced (entity )
58+ local entity_index = world .entity_index :: any
59+ local function emplaced (entity : jecs .Entity )
4660 local r = jecs .entity_index_try_get_fast (
47- entity_index , entity )
61+ entity_index , entity :: any )
4862
4963 if not r then
5064 return
5165 end
5266
5367 local archetype = r .archetype
5468
55- if jecs .query_match (q_shim :: any , archetype ) then
56- n += 1
57- dense_array [n ] = entity
58- sparse_array [entity ] = n
69+ if jecs .query_match (query , archetype ) then
70+ callback (entity , jecs .OnAdd )
5971 end
6072 end
6173
62- local function removed (entity )
63- local i = sparse_array [entity ]
64- if i ~= n then
65- dense_array [i ] = dense_array [n ]
74+ local function removed (entity : jecs .Entity , component : jecs .Id )
75+ local r = jecs .entity_index_try_get_fast (
76+ entity_index , entity :: any )
77+
78+ if not r then
79+ return
6680 end
6781
68- dense_array [n ] = nil
82+ local archetype = r .archetype
83+
84+ if jecs .query_match (query , archetype ) then
85+ callback (entity , jecs .OnRemove )
86+ end
6987 end
7088
7189 for _ , term in terms do
7290 world :added (term , emplaced )
73- world :changed (term , emplaced )
91+ world :removed (term , removed )
7492 end
75-
76- local function iter ()
77- local i = n
78- return function ()
79- local row = i
80- if row == 0 then
81- return nil
82- end
83- i -= 1
84- return dense_array [row ] :: any
85- end
86- end
87-
88- local it = {
89- __iter = iter ,
90- without = function (self , ... )
91- q_shim .filter_without = { ... }
92- return self
93- end
94- }
95- return setmetatable (it , it )
9693end
9794
98- local function observers_add (world )
95+ local function observers_add (world : jecs . World & { [ string ]: any }): PatchedWorld
9996 local signals = {
10097 added = {},
10198 emplaced = {},
10299 removed = {}
103100 }
101+
104102 world .added = function (_ , component , fn )
105103 local listeners = signals .added [component ]
106104 if not listeners then
@@ -109,7 +107,7 @@ local function observers_add(world)
109107 local idr = jecs .id_record_ensure (world , component )
110108 idr .hooks .on_add = function (entity )
111109 for _ , listener in listeners do
112- listener (entity )
110+ listener (entity , component )
113111 end
114112 end
115113 end
@@ -124,7 +122,7 @@ local function observers_add(world)
124122 local idr = jecs .id_record_ensure (world , component )
125123 idr .hooks .on_change = function (entity , value )
126124 for _ , listener in listeners do
127- listener (entity , value )
125+ listener (entity , component , value )
128126 end
129127 end
130128 end
@@ -139,7 +137,7 @@ local function observers_add(world)
139137 local idr = jecs .id_record_ensure (world , component )
140138 idr .hooks .on_remove = function (entity )
141139 for _ , listener in listeners do
142- listener (entity )
140+ listener (entity , component )
143141 end
144142 end
145143 end
@@ -148,10 +146,24 @@ local function observers_add(world)
148146
149147 world .signals = signals
150148
151- world .track = world_track
152-
153149 world .observer = observers_new
150+
151+ world .monitor = monitors_new
152+
154153 return world
155154end
156155
157- return observers_add
156+ local world = jecs .world ()
157+
158+ observers_add (world ):observer ({
159+ callback = function () end ,
160+ query = world :query (1 :: any )
161+ })
162+
163+ observers_add (world ):added (1 :: any , function ()
164+
165+ end )
166+
167+ return {
168+ add = observers_add
169+ }
0 commit comments