@perplexdotgg/mecs 0.4.2 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -142,6 +142,9 @@ const queries = {
142
142
  without: ['localTransform'],
143
143
 
144
144
  // listeners can added now, or later (see the Queries docs below)
145
+ // note that in this context, the entity type doesn't have Entity methods that you've added
146
+ // if you need those, either ts-ignore when calling them here, or add listeners later in your system code using:
147
+ // Entity.queries().yourQueryKey.afterEntityAdded.addListener((entity) => { /* your code here will get the right entity type */ }))
145
148
  afterEntityAdded: (entity) => {
146
149
  // this is called when an entity newly matches this query
147
150
  },
@@ -154,7 +157,7 @@ const queries = {
154
157
  with: ['localTransform', 'globalTransform'],
155
158
  without: [],
156
159
  },
157
- } as const satisfies QueryMap<Entity, typeof components>;
160
+ } as const satisfies QueryMap<typeof components>;
158
161
 
159
162
  // additional Entity class options, see "Entity Class Options" below
160
163
  const extraOptions = {};
package/build/index.d.ts CHANGED
@@ -4,10 +4,18 @@ import { MonomorphInstance } from 'monomorph';
4
4
  import { NumberArray } from 'monomorph';
5
5
  import { PartialRecursive } from 'monomorph';
6
6
  import { PoolClass } from 'monomorph';
7
+ import { PropertyDefinitionClassProperties } from 'monomorph';
8
+ import { PropertyDefinitionReference } from 'monomorph';
9
+ import { PropertyDefinitionReferenceList } from 'monomorph';
10
+ import { ReferenceListClass } from 'monomorph';
7
11
  import { WithPool } from 'monomorph';
8
12
 
13
+ declare type BivariantCallback<T> = {
14
+ bivarianceHack(arg: T): void;
15
+ }["bivarianceHack"];
16
+
9
17
  export declare type ComponentConfig<ComponentType, ComponentInputType extends any = InputType<ComponentType> extends never ? ComponentType : InputType<ComponentType>> = {
10
- monomorphClass?: ComponentType extends MonomorphClass<any, any, any> ? ComponentType : ComponentType extends MonomorphInstance<infer P, infer I> ? MonomorphClass<P, I, ComponentType> : never;
18
+ monomorphClass?: ComponentType extends LazyWrapper<infer MC extends MonomorphClass<any, any, any>> ? LazyWrapper<MC> : ComponentType extends MonomorphClass<any, any, any> ? ComponentType : ComponentType extends MonomorphInstance<infer P, infer I> ? MonomorphClass<P, I, ComponentType> : never;
11
19
  afterComponentAdded?: (componentInstance: ComponentType extends abstract new (...args: any) => any ? InstanceType<ComponentType> : ComponentType, entity: any, componentKey: string) => void;
12
20
  afterComponentAddedCode?: string | ComponentConfigFunction<ComponentType, ComponentInputType>;
13
21
  beforeComponentRemoved?: (componentInstance: ComponentType extends abstract new (...args: any) => any ? InstanceType<ComponentType> : ComponentType, entity: any, componentKey: string) => void;
@@ -40,26 +48,36 @@ export declare type ComponentConfigFunction<ComponentType, ComponentInputType> =
40
48
 
41
49
  export declare type ComponentInput<X> = X extends MonomorphClass<infer P, infer I, infer M> ? M extends MonomorphInstance<infer iP, infer iI> ? InputType<M> : never : X extends ComponentConfig<infer CT, infer I> ? I : X;
42
50
 
51
+ declare type ComponentInputResolved<CC, CM extends ComponentMap> = ResolveEntityInputListItems<ComponentInput<ExtractMonomorphClass<CC>>, CM>;
52
+
43
53
  export declare type ComponentMap = Record<string, ComponentConfig<any, any> | MonomorphClass<any, any, any> | LazyWrapper<MonomorphClass<any, any, any>> | ComponentConfig<MonomorphClass<any, any, any>, any> | ComponentConfig<LazyWrapper<MonomorphClass<any, any, any>>, any>>;
44
54
 
45
- declare type ComponentMapClassProperties<CM> = {
46
- [K in keyof CM as LowercaseFirstLetter<K>]?: ExtractMonomorphClass<CM[K]> extends MonomorphClass<infer P, infer I, infer M> ? M : ExtractMonomorphClass<CM[K]>;
55
+ declare type ComponentMapClassProperties<CM extends ComponentMap> = {
56
+ [K in keyof CM as LowercaseFirstLetter<K>]?: ExtractMonomorphClass<CM[K]> extends MonomorphClass<infer P, infer I, infer M> ? ResolveEntityRefs<M, CM> : ExtractMonomorphClass<CM[K]>;
47
57
  };
48
58
 
49
59
  export declare type ComponentMapInput<CM extends ComponentMap> = Partial<{
50
- [K in keyof CM as LowercaseFirstLetter<K>]: ComponentInput<ExtractMonomorphClass<CM[K]>>;
60
+ [K in keyof CM as LowercaseFirstLetter<K>]: ResolveEntityInput<ComponentInput<ExtractMonomorphClass<CM[K]>>, CM>;
61
+ }>;
62
+
63
+ declare type ComponentMapInputListItems<CM extends ComponentMap> = Partial<{
64
+ [K in keyof CM as LowercaseFirstLetter<K>]: ResolveEntityInputListItems<ComponentInput<ExtractMonomorphClass<CM[K]>>, CM>;
51
65
  }>;
52
66
 
53
- export declare function createEntityClass<C>(options?: EntityCodeGenerationOptions): <CM extends ComponentMap, QM extends QueryMap<C, CM>, I extends ComponentMapInput<CM> = ComponentMapInput<CM>>(componentMap: CM, queries?: QM) => EntityClassWithStatics<C, CM, QM, I>;
67
+ declare type ComponentTypeFromMonomorphClass<T> = T extends MonomorphClass<infer P, any, any> ? PropertyDefinitionClassProperties<P> : never;
54
68
 
55
- export declare type CreateEntityFunction<C, CM extends ComponentMap, I extends ComponentMapInput<CM>> = (data?: I, updateQueryMemberships?: boolean, pool?: EntityPoolClass<C>) => EntityInstanceWithPool<CM, I, C>;
69
+ export declare function createEntityClass<C>(options?: EntityCodeGenerationOptions): <CM extends ComponentMap, QM extends QueryMap<CM>, I extends ComponentMapInput<CM> = ComponentMapInput<CM>>(componentMap: CM, queries?: QM) => EntityClassWithStatics<C, CM, QM, I>;
56
70
 
57
- declare type ElementOfArray<T> = T extends (infer E)[] ? E : never;
71
+ export declare function createEntityClass(options?: EntityCodeGenerationOptions): <CM extends ComponentMap, QM extends QueryMap<CM>, I extends ComponentMapInput<CM> = ComponentMapInput<CM>>(componentMap: CM, queries?: QM) => EntityClassWithStatics<EntityInstance<CM, I>, CM, QM, I>;
72
+
73
+ export declare type CreateEntityFunction<C, CM extends ComponentMap, I extends ComponentMapInput<CM>> = <T extends EntityConstructor<any, any, I, CM>>(this: T, data?: I, updateQueryMemberships?: boolean, pool?: EntityPoolClass<InstanceType<T>>) => EntityInstanceWithPool<CM, I, InstanceType<T>>;
74
+
75
+ declare type ElementOfReadonlyArray<T> = T extends ReadonlyArray<infer E> ? E : never;
58
76
 
59
77
  declare interface EntityBaseProperties<CM extends ComponentMap, I extends any = ComponentMapInput<CM>> {
60
78
  componentMap: CM;
61
79
  __typescriptOnlyInputType: I;
62
- addComponent: <CCK extends LowercaseFirstLetter<keyof CM>, CC extends CM[OriginalComponentKey<CCK, CM>] = CM[OriginalComponentKey<CCK, CM>]>(...a: (undefined extends ComponentInput<ExtractMonomorphClass<CC>> ? [key: CCK, data?: ComponentInput<ExtractMonomorphClass<CC>>, updateQueryMemberships?: boolean] : [key: CCK, data: ComponentInput<ExtractMonomorphClass<CC>>, updateQueryMemberships?: boolean])) => void;
80
+ addComponent: <CCK extends LowercaseFirstLetter<keyof CM>, CC extends CM[OriginalComponentKey<CCK, CM>] = CM[OriginalComponentKey<CCK, CM>]>(...a: (undefined extends NoInfer<ComponentInputResolved<CC, CM>> ? [key: CCK, data?: NoInfer<ComponentInputResolved<CC, CM>>, updateQueryMemberships?: boolean] : [key: CCK, data: NoInfer<ComponentInputResolved<CC, CM>>, updateQueryMemberships?: boolean])) => void;
63
81
  removeComponent: <CCK extends LowercaseFirstLetter<keyof CM>>(key: CCK, updateQueryMemberships?: boolean) => void;
64
82
  hasComponent: <CCK extends LowercaseFirstLetter<keyof CM>>(key: CCK) => boolean;
65
83
  clone(): this;
@@ -68,9 +86,9 @@ declare interface EntityBaseProperties<CM extends ComponentMap, I extends any =
68
86
  isDestroyed(): boolean;
69
87
  }
70
88
 
71
- export declare type EntityClass<CM extends ComponentMap, I extends ComponentMapInput<CM> = ComponentMapInput<CM>, QM extends QueryMap<any, CM> = QueryMap<any, CM>, E extends EntityInstance<CM, I> = EntityInstance<CM, I>> = EntityConstructor<QM, E, I, CM>;
89
+ export declare type EntityClass<CM extends ComponentMap, I extends ComponentMapInput<CM> = ComponentMapInput<CM>, QM extends QueryMap<CM> = QueryMap<CM>, E extends EntityInstance<CM, I> = EntityInstance<CM, I>> = EntityConstructor<QM, E, I, CM>;
72
90
 
73
- export declare type EntityClassWithStatics<C, CM extends ComponentMap, QM extends QueryMap<C, CM>, I extends ComponentMapInput<CM> = ComponentMapInput<CM>> = EntityClass<CM, I, QM> & {
91
+ export declare type EntityClassWithStatics<C, CM extends ComponentMap, QM extends QueryMap<CM>, I extends ComponentMapInput<CM> = ComponentMapInput<CM>> = EntityClass<CM, I, QM> & {
74
92
  create: CreateEntityFunction<C, CM, I>;
75
93
  Pool: NoInfer<EntityPoolClass<C>>;
76
94
  };
@@ -96,11 +114,13 @@ declare type EntityCodeGenerationOptions = {
96
114
  skipSafetyChecks?: boolean;
97
115
  };
98
116
 
99
- export declare interface EntityConstructor<QM extends QueryMap<any, CM>, E extends EntityInstance<CM, I>, I extends any, CM extends ComponentMap> {
100
- new (data: I, index?: number, pool?: EntityPoolClass<E>, updateQueryMemberships?: boolean): E;
117
+ export declare interface EntityConstructor<QM extends QueryMap<CM>, E extends EntityInstance<CM, I>, I extends any, CM extends ComponentMap> {
118
+ new (data: I, poolIndex?: number, pool?: EntityPoolClass<E>, updateQueryMemberships?: boolean): E;
101
119
  componentMap: CM;
120
+ __lazyReferenceTarget?: E;
102
121
  __typescriptOnlyInputType: I;
103
- pool: EntityPoolClass<E>;
122
+ pool: PoolCallable<E>;
123
+ queries: QueriesCallable<E, QM, CM>;
104
124
  componentsWithEntities: {
105
125
  [K in keyof CM as ExtractMonomorphClass<CM[K]> extends MonomorphClass<infer P, infer I, infer M> ? LowercaseFirstLetter<K> : never]: {
106
126
  [Symbol.iterator](): IterableIterator<[WithPool<InstanceType<ExtractMonomorphClass<CM[K]>>>, E]>;
@@ -109,24 +129,17 @@ export declare interface EntityConstructor<QM extends QueryMap<any, CM>, E exten
109
129
  components: {
110
130
  [K in keyof CM as ExtractMonomorphClass<CM[K]> extends MonomorphClass<infer P, infer I, infer M> ? LowercaseFirstLetter<K> : never]: PoolClass<ExtractMonomorphClass<CM[K]>>;
111
131
  };
112
- queries: {
113
- [K in keyof QM]: {
114
- afterEntityAdded: {
115
- addListener(listener: (entity: E) => void): void;
116
- removeListener(listener: (entity: E) => void): void;
117
- };
118
- beforeEntityRemoved: {
119
- addListener(listener: (entity: E) => void): void;
120
- removeListener(listener: (entity: E) => void): void;
121
- };
122
- [Symbol.iterator](): IterableIterator<WithComponent<E, ElementOfArray<QM[K]['with']> extends LowercaseFirstLetter<keyof E["componentMap"]> ? ElementOfArray<QM[K]['with']> : never>>;
123
- };
124
- };
125
132
  }
126
133
 
134
+ declare type EntityConstructorLike = abstract new (...args: any[]) => any;
135
+
136
+ declare type EntityFor<CM extends ComponentMap> = EntityInstance<CM, any>;
137
+
127
138
  export declare type EntityInput<X extends ComponentMap | EntityClass<any, any, any, any> | EntityInstanceWithPool<any, any, any> | EntityInstance<any, any>> = Writeable<X extends ComponentMap ? ComponentMapInput<X> : X extends EntityConstructor<infer QM, infer E, infer I, infer CM> ? I : X extends EntityInstanceWithPool<infer CM, infer I, infer E> ? I : X extends EntityInstance<infer CM, infer I> ? I : never>;
128
139
 
129
- export declare type EntityInstance<CM extends ComponentMap, I extends any = ComponentMapInput<CM>> = ComponentMapClassProperties<CM> & EntityBaseProperties<CM, I>;
140
+ declare type EntityInputListItems<E> = E extends ComponentMap ? ComponentMapInputListItems<E> : E extends EntityConstructor<any, any, any, infer CM> ? ComponentMapInputListItems<CM> : E extends EntityInstance<infer CM, any> ? ComponentMapInputListItems<CM> : E extends EntityInstanceWithPool<infer CM, any, any> ? ComponentMapInputListItems<CM> : EntityInput<NoInfer<E>>;
141
+
142
+ export declare type EntityInstance<CM extends ComponentMap, I extends any = ComponentMapInput<CM>> = ComponentMapClassProperties<NoInfer<CM>> & EntityBaseProperties<CM, I>;
130
143
 
131
144
  export declare type EntityInstanceWithPool<CM extends ComponentMap, I extends ComponentMapInput<CM>, E> = NoInfer<E & {
132
145
  pool: EntityPoolClass<E> | null;
@@ -159,6 +172,65 @@ export declare interface EntityPoolClass<M> {
159
172
  fromArrayOnlyReferences(array: NumberArray, references?: any, startOffset?: number, classConstructor?: new (...args: any[]) => M): number;
160
173
  }
161
174
 
175
+ declare type EntityPoolInput = {
176
+ array: unknown[];
177
+ freeIndices: number[];
178
+ maxLength: number;
179
+ length: number;
180
+ [Symbol.iterator](): IterableIterator<any>;
181
+ create?(data?: any): any;
182
+ };
183
+
184
+ declare type EntityQueries<E, QM extends QueryMap<CM>, CM extends ComponentMap> = E extends {
185
+ componentMap: any;
186
+ } ? ({
187
+ [K in keyof QM]: {
188
+ afterEntityAdded: {
189
+ addListener(listener: BivariantCallback<WithComponent<E, ElementOfReadonlyArray<QM[K]['with']> extends LowercaseFirstLetter<keyof E["componentMap"]> ? ElementOfReadonlyArray<QM[K]['with']> : never>>): void;
190
+ removeListener(listener: BivariantCallback<E>): void;
191
+ };
192
+ beforeEntityRemoved: {
193
+ addListener(listener: BivariantCallback<WithComponent<E, ElementOfReadonlyArray<QM[K]['with']> extends LowercaseFirstLetter<keyof E["componentMap"]> ? ElementOfReadonlyArray<QM[K]['with']> : never>>): void;
194
+ removeListener(listener: BivariantCallback<E>): void;
195
+ };
196
+ [Symbol.iterator](): IterableIterator<WithComponent<E, ElementOfReadonlyArray<QM[K]['with']> extends LowercaseFirstLetter<keyof E["componentMap"]> ? ElementOfReadonlyArray<QM[K]['with']> : never>>;
197
+ };
198
+ } & {
199
+ [key: string]: any;
200
+ }) : never;
201
+
202
+ declare const EntityRefBrand: unique symbol;
203
+
204
+ export declare function EntityReference(fn: () => any): PropertyDefinitionReference<EntitySelfRef | null, true>;
205
+
206
+ export declare function EntityReference<E>(fn: () => any): PropertyDefinitionReference<LazyEntityReferenceTarget<E> | null, true>;
207
+
208
+ export declare function EntityReference<C extends EntityConstructorLike>(fn: () => C): PropertyDefinitionReference<LazyEntityReferenceTarget<C> | null, true>;
209
+
210
+ export declare function EntityReferenceList(fn: () => any): PropertyDefinitionReferenceList<EntitySelfRef, EntitySelfRefListInput>;
211
+
212
+ export declare function EntityReferenceList<E>(fn: () => any): PropertyDefinitionReferenceList<LazyEntityReferenceTarget<E>, EntitySelfRefListInput>;
213
+
214
+ export declare function EntityReferenceList<C extends EntityConstructorLike>(fn: () => C): PropertyDefinitionReferenceList<LazyEntityReferenceTarget<C>, EntitySelfRefListInput>;
215
+
216
+ export declare type EntityReferenceListInput<E> = EntityReferenceListInputBase<EntityInputListItems<NoInfer<E>>>;
217
+
218
+ declare type EntityReferenceListInputBase<TItems = unknown> = {
219
+ pool: EntityPoolInput;
220
+ items?: TItems[];
221
+ maxLength?: number;
222
+ };
223
+
224
+ declare const EntityRefListBrand: unique symbol;
225
+
226
+ declare type EntitySelfRef = {
227
+ [EntityRefBrand]?: true;
228
+ };
229
+
230
+ declare type EntitySelfRefListInput = {
231
+ [EntityRefListBrand]?: true;
232
+ };
233
+
162
234
  export declare type ExtractMonomorphClass<CC> = CC extends {
163
235
  monomorphClass?: infer MC extends MonomorphClass<any, any, any>;
164
236
  } ? MC : CC extends ({
@@ -169,9 +241,20 @@ export declare type ExtractMonomorphClass<CC> = CC extends {
169
241
  fnInArray: [() => infer MC extends MonomorphClass<any, any, any>];
170
242
  } ? MC : CC;
171
243
 
172
- export declare function getEntityClassCode<C, CM extends ComponentMap>(componentMap: CM, queries?: QueryMap<C, CM>, options?: EntityCodeGenerationOptions): string;
244
+ export declare function getEntityClassCode<C, CM extends ComponentMap>(componentMap: CM, queries?: QueryMap<CM>, options?: EntityCodeGenerationOptions): string;
245
+
246
+ export declare function LazyComponent<CT = undefined, MC extends MonomorphClass<any, any, any> = MonomorphClass<any, any, any>>(componentFn: () => MC): LazyComponentWrapper<MC, CT>;
247
+
248
+ declare type LazyComponentResolvedType<MC extends MonomorphClass<any, any, any>, CT> = CT extends undefined ? ComponentTypeFromMonomorphClass<MC> : CT;
249
+
250
+ declare type LazyComponentWrapper<MC extends MonomorphClass<any, any, any>, CT> = {
251
+ fnInArray: [() => MC];
252
+ componentType: Writeable<LazyComponentResolvedType<MC, CT>>;
253
+ };
173
254
 
174
- export declare function LazyComponent<F extends () => T, T>(componentFn: F): LazyWrapper<ReturnType<F>>;
255
+ export declare type LazyEntityReferenceTarget<T> = {
256
+ __lazyReferenceTarget?: NoInfer<T>;
257
+ };
175
258
 
176
259
  export declare type LazyMonomorphComponentConfig<MC extends MonomorphClass<any, any, any>> = ComponentConfig<LazyWrapper<MC>, InputType<InstanceType<MC>>>;
177
260
 
@@ -185,21 +268,53 @@ export declare type MonomorphComponentConfig<MC extends MonomorphClass<any, any,
185
268
 
186
269
  declare type OriginalComponentKey<CCK extends LowercaseFirstLetter<keyof CM>, CM extends ComponentMap> = CCK extends keyof CM ? CCK : UppercaseFirstLetter<CCK>;
187
270
 
188
- export declare type QueryConfig<C, CM extends ComponentMap> = {
189
- with?: LowercaseFirstLetter<keyof CM>[];
190
- without?: LowercaseFirstLetter<keyof CM>[];
191
- afterEntityAdded?: (entity: C) => void;
192
- beforeEntityRemoved?: (entity: C) => void;
271
+ declare type PoolCallable<E> = EntityPoolClass<E> & {
272
+ <Self extends abstract new (...args: any) => any>(this: Self): EntityPoolClass<InstanceType<Self>>;
273
+ };
274
+
275
+ declare type QueriesCallable<E, QM extends QueryMap<CM>, CM extends ComponentMap> = EntityQueries<E, QM, CM> & {
276
+ <Self extends abstract new (...args: any) => any>(this: Self): EntityQueries<InstanceType<Self>, QM, CM>;
193
277
  };
194
278
 
195
- export declare type QueryMap<C, CM extends ComponentMap> = Record<string, QueryConfig<C, CM>>;
279
+ export declare type QueryConfig<CM extends ComponentMap> = {
280
+ with?: ReadonlyArray<LowercaseFirstLetter<keyof CM>>;
281
+ without?: ReadonlyArray<LowercaseFirstLetter<keyof CM>>;
282
+ afterEntityAdded?: (entity: EntityInstance<CM>) => void;
283
+ beforeEntityRemoved?: (entity: EntityInstance<CM>) => void;
284
+ };
285
+
286
+ export declare type QueryMap<CM extends ComponentMap> = Record<string, QueryConfig<CM>>;
287
+
288
+ declare type ResolveEntityInput<T, CM extends ComponentMap> = T extends object ? {
289
+ [K in keyof T]: ResolveEntityInputValue<T[K], CM>;
290
+ } : ResolveEntityInputValue<T, CM>;
291
+
292
+ declare type ResolveEntityInputListItems<T, CM extends ComponentMap> = T extends object ? {
293
+ [K in keyof T]: ResolveEntityInputValueListItems<T[K], CM>;
294
+ } : ResolveEntityInputValueListItems<T, CM>;
295
+
296
+ declare type ResolveEntityInputValue<T, CM extends ComponentMap> = T extends any ? (UnwrapLazyEntityReferenceTarget<T> extends EntitySelfRef ? EntityFor<CM> : UnwrapLazyEntityReferenceTarget<T> extends EntitySelfRefListInput ? EntityReferenceListInput<EntityFor<CM>> : UnwrapEntityTarget<T> extends ReferenceListClass<infer M> ? EntityReferenceListInput<UnwrapEntityTarget<M>> : UnwrapEntityTarget<T>) : never;
297
+
298
+ declare type ResolveEntityInputValueListItems<T, CM extends ComponentMap> = T extends any ? (UnwrapLazyEntityReferenceTarget<T> extends EntitySelfRef ? EntityFor<CM> : UnwrapLazyEntityReferenceTarget<T> extends EntitySelfRefListInput ? EntityReferenceListInputBase : T extends EntityReferenceListInputBase<any> ? EntityReferenceListInputBase : UnwrapEntityTarget<T> extends ReferenceListClass<any> ? EntityReferenceListInputBase : UnwrapEntityTarget<T>) : never;
299
+
300
+ declare type ResolveEntityRefs<T, CM extends ComponentMap> = T extends object ? {
301
+ [K in keyof T]: ResolveEntityRefValue<T[K], CM>;
302
+ } : ResolveEntityRefValue<T, CM>;
303
+
304
+ declare type ResolveEntityRefValue<T, CM extends ComponentMap> = [
305
+ T
306
+ ] extends [any] ? (UnwrapLazyEntityReferenceTarget<T> extends EntitySelfRef ? EntityFor<CM> : T extends ReferenceListClass<infer M> ? (UnwrapLazyEntityReferenceTarget<M> extends EntitySelfRef ? ReferenceListClass<EntityFor<CM>> : ReferenceListClass<UnwrapEntityTarget<M>>) : UnwrapEntityTarget<T>) : never;
307
+
308
+ declare type UnwrapEntityTarget<T> = UnwrapLazyEntityReferenceTarget<T> extends EntityConstructor<any, infer E, any, any> ? E : UnwrapLazyEntityReferenceTarget<T> extends EntityConstructor<any, any, any, any> ? InstanceType<UnwrapLazyEntityReferenceTarget<T>> : UnwrapLazyEntityReferenceTarget<T>;
309
+
310
+ declare type UnwrapLazyEntityReferenceTarget<T> = T extends LazyEntityReferenceTarget<infer U> ? U : T;
196
311
 
197
312
  declare type UppercaseFirstLetter<S> = S extends `${infer FirstLetter}${infer Rest}` ? `${Uppercase<FirstLetter>}${Rest}` : S;
198
313
 
199
314
  export declare type WithComponent<C extends {
200
315
  componentMap: any;
201
- }, KCM extends LowercaseFirstLetter<keyof C['componentMap']>> = Writeable<Omit<C, KCM> & {
202
- [K in KCM as LowercaseFirstLetter<K>]-?: Exclude<C[K extends keyof C ? K : never], undefined | null>;
316
+ }, KCM extends LowercaseFirstLetter<keyof C['componentMap']>> = Writeable<C & {
317
+ [K in KCM]-?: NonNullable<C[K extends keyof C ? K : never]>;
203
318
  }>;
204
319
 
205
320
  declare type Writeable<T> = {
package/build/mecs.js CHANGED
@@ -1,5 +1,43 @@
1
+ // @__NO_SIDE_EFFECTS__
2
+ function LazyReferenceType(fn, readOnly) {
3
+ return {
4
+ monomorph: {
5
+ serializedSize: 2,
6
+ fnInArray: [fn],
7
+ theClass: null
8
+ },
9
+ propertyType: 4,
10
+ optional: true,
11
+ defaultValue: null,
12
+ readOnly
13
+ };
14
+ }
15
+ // @__NO_SIDE_EFFECTS__
16
+ function LazyReferenceListType(fn, readOnly) {
17
+ return {
18
+ monomorph: {
19
+ serializedSize: 2,
20
+ // @ts-ignore
21
+ fnInArray: [fn],
22
+ theClass: null
23
+ },
24
+ propertyType: 7,
25
+ optional: true,
26
+ defaultValue: void 0,
27
+ readOnly
28
+ };
29
+ }
1
30
  function LazyComponent(componentFn) {
2
- return { fnInArray: [componentFn] };
31
+ return {
32
+ fnInArray: [componentFn],
33
+ componentType: void 0
34
+ };
35
+ }
36
+ function EntityReference(fn) {
37
+ return /* @__PURE__ */ LazyReferenceType(fn ?? (() => null));
38
+ }
39
+ function EntityReferenceList(fn) {
40
+ return /* @__PURE__ */ LazyReferenceListType(fn ?? (() => null));
3
41
  }
4
42
  function lowercaseFirstLetter(str) {
5
43
  return str.charAt(0).toLowerCase() + str.slice(1);
@@ -182,7 +220,7 @@ function getEntityClassCode(componentMap, queries, options) {
182
220
  return {
183
221
  next() {
184
222
  ${""}
185
- while (index < (${componentKey}Pool.length + ${componentKey}Pool.freeIndices.length) && (!${componentKey}PoolArray[index] || (${componentKey}PoolArray[index].version & 1) === 1)) {
223
+ while (index < (${componentKey}Pool.length + ${componentKey}Pool.freeIndices.length) && (!${componentKey}PoolArray[index] || (${componentKey}PoolArray[index].poolVersion & 1) === 1)) {
186
224
  index++;
187
225
  }
188
226
 
@@ -208,7 +246,7 @@ function getEntityClassCode(componentMap, queries, options) {
208
246
  (data, entity, componentKey, updateQueryMemberships) => {
209
247
  entity.componentFlags |= ${componentFlagValue}n;
210
248
  entity.${componentKey} = ${resolvedMonomorphClass}.create(${processedDataCode}, ${componentKey}Pool);
211
- ${componentKey}ComponentToEntity[entity.${componentKey}.index] = entity;
249
+ ${componentKey}ComponentToEntity[entity.${componentKey}.poolIndex] = entity;
212
250
 
213
251
  ${afterComponentAddedCode}
214
252
 
@@ -225,7 +263,7 @@ function getEntityClassCode(componentMap, queries, options) {
225
263
 
226
264
  ${beforeComponentRemovedCode}
227
265
 
228
- ${componentKey}ComponentToEntity[instance.index] = null;
266
+ ${componentKey}ComponentToEntity[instance.poolIndex] = null;
229
267
  instance.destroy();
230
268
 
231
269
  ${""}
@@ -323,12 +361,8 @@ function getEntityClassCode(componentMap, queries, options) {
323
361
  }
324
362
  }
325
363
  queryListenerCode += `
326
- const queryEntityAddedListeners${queryIndex} = [
327
- ${queryConfig.afterEntityAdded ? "queryMap." + queryName + ".afterEntityAdded" : ""}
328
- ];
329
- const queryEntityRemovedListeners${queryIndex} = [
330
- ${queryConfig.beforeEntityRemoved ? "queryMap." + queryName + ".beforeEntityRemoved" : ""}
331
- ];
364
+ const queryEntityAddedListeners${queryIndex} = [];
365
+ const queryEntityRemovedListeners${queryIndex} = [];
332
366
 
333
367
  function afterEntityAdded${queryIndex} (entity) {
334
368
  for (const listener of queryEntityAddedListeners${queryIndex}) {
@@ -499,7 +533,7 @@ function getEntityClassCode(componentMap, queries, options) {
499
533
  return {
500
534
  next() {
501
535
  ${""}
502
- while (index < (pool.length + pool.freeIndices.length) && (!array[index] || (array[index].version & 1) === 1)) {
536
+ while (index < (pool.length + pool.freeIndices.length) && (!array[index] || (array[index].poolVersion & 1) === 1)) {
503
537
  index++;
504
538
  }
505
539
 
@@ -544,7 +578,7 @@ function getEntityClassCode(componentMap, queries, options) {
544
578
  poolItem = poolArray[arrayOfIndices[index]];
545
579
 
546
580
  ${""}
547
- while (index < arrayOfIndices.length && (((poolItem.version & 1) === 1) || poolItem.version !== arrayOfVersions[index])) {
581
+ while (index < arrayOfIndices.length && (((poolItem.poolVersion & 1) === 1) || poolItem.poolVersion !== arrayOfVersions[index])) {
548
582
  if (fixDestroyed) {
549
583
  if (index < arrayOfIndices.length - 1) {
550
584
  arrayOfIndices[index] = arrayOfIndices[arrayOfIndices.length - 1];
@@ -576,9 +610,9 @@ function getEntityClassCode(componentMap, queries, options) {
576
610
  }
577
611
 
578
612
  const theClass = class {
579
- constructor(data, index = 0, updateQueryMemberships = true, pool = this.constructor.pool) {
580
- this.index = index;
581
- this.version = 0; ${""}
613
+ constructor(data, poolIndex = 0, updateQueryMemberships = true, pool = this.constructor.pool) {
614
+ this.poolIndex = poolIndex;
615
+ this.poolVersion = 0; ${""}
582
616
  this.pool = pool;
583
617
  this.queryIndices = new Array(${queryIndex}).fill(-1);
584
618
  this.componentFlags = 0n; ${""}
@@ -637,14 +671,14 @@ function getEntityClassCode(componentMap, queries, options) {
637
671
 
638
672
  destroy(updateQueryMemberships = true) {
639
673
  ${destroyCode}
640
- if (this.version & 1 === 1) {
674
+ if (this.poolVersion & 1 === 1) {
641
675
  ${""}
642
676
  return;
643
677
  }
644
- this.version++; // becomes odd, meaning deleted
678
+ this.poolVersion++; // becomes odd, meaning deleted
645
679
  if (this.pool) {
646
680
  this.pool.length--;
647
- this.pool.freeIndices.push(this.index);
681
+ this.pool.freeIndices.push(this.poolIndex);
648
682
  }
649
683
  }
650
684
 
@@ -691,8 +725,8 @@ function getEntityClassCode(componentMap, queries, options) {
691
725
  throw new Error("Could not add instance to reference list, instance does not belong to the same pool as the reference list");
692
726
  }
693
727
  const length = this.length;
694
- this.arrayOfIndices[length] = instance.index;
695
- this.arrayOfVersions[length] = instance.version;
728
+ this.arrayOfIndices[length] = instance.poolIndex;
729
+ this.arrayOfVersions[length] = instance.poolVersion;
696
730
  return length;
697
731
  }
698
732
 
@@ -703,7 +737,7 @@ function getEntityClassCode(componentMap, queries, options) {
703
737
  let poolItem = this.pool.array[this.arrayOfIndices[index]];
704
738
 
705
739
  if (fixDestroyed) {
706
- while (index < this.arrayOfIndices.length && ((poolItem.version & 1) === 1 || poolItem.version !== this.arrayOfVersions[index])) {
740
+ while (index < this.arrayOfIndices.length && ((poolItem.poolVersion & 1) === 1 || poolItem.poolVersion !== this.arrayOfVersions[index])) {
707
741
  if (index < this.arrayOfIndices.length - 1) {
708
742
  this.arrayOfIndices[index] = this.arrayOfIndices[this.arrayOfIndices.length - 1];
709
743
  this.arrayOfVersions[index] = this.arrayOfVersions[this.arrayOfVersions.length - 1];
@@ -717,7 +751,7 @@ function getEntityClassCode(componentMap, queries, options) {
717
751
  return null;
718
752
  }
719
753
  }
720
- } else if ((poolItem.version & 1) === 1 || poolItem.version !== this.arrayOfVersions[index]) {
754
+ } else if ((poolItem.poolVersion & 1) === 1 || poolItem.poolVersion !== this.arrayOfVersions[index]) {
721
755
  return null;
722
756
  }
723
757
 
@@ -726,7 +760,7 @@ function getEntityClassCode(componentMap, queries, options) {
726
760
 
727
761
  remove(instance) {
728
762
  for (let i = 0; i < this.arrayOfIndices.length; i++) {
729
- if (this.arrayOfIndices[i] === instance.index && this.arrayOfVersions[i] === instance.version) {
763
+ if (this.arrayOfIndices[i] === instance.poolIndex && this.arrayOfVersions[i] === instance.poolVersion) {
730
764
  if (i < this.arrayOfIndices.length - 1) {
731
765
  this.arrayOfIndices[i] = this.arrayOfIndices[this.arrayOfIndices.length - 1];
732
766
  this.arrayOfVersions[i] = this.arrayOfVersions[this.arrayOfVersions.length - 1];
@@ -757,8 +791,8 @@ function getEntityClassCode(componentMap, queries, options) {
757
791
  create(data) {
758
792
  const instance = this.classConstructor.create(data, this.pool);
759
793
  const length = this.length;
760
- this.arrayOfIndices[length] = instance.index;
761
- this.arrayOfVersions[length] = instance.version;
794
+ this.arrayOfIndices[length] = instance.poolIndex;
795
+ this.arrayOfVersions[length] = instance.poolVersion;
762
796
  return instance;
763
797
  }
764
798
 
@@ -784,7 +818,23 @@ function getEntityClassCode(componentMap, queries, options) {
784
818
  if (!this.dynamicPoolInstance) {
785
819
  this.dynamicPoolInstance = new this.Pool();
786
820
  }
787
- return this.dynamicPoolInstance;
821
+ if (!this.dynamicPoolCallable) {
822
+ const poolInstance = this.dynamicPoolInstance;
823
+ const callable = new Proxy(function () { return poolInstance; }, {
824
+ get(_target, prop) {
825
+ if (prop in poolInstance) {
826
+ return poolInstance[prop];
827
+ }
828
+ return undefined;
829
+ },
830
+ set(_target, prop, value) {
831
+ poolInstance[prop] = value;
832
+ return true;
833
+ },
834
+ });
835
+ this.dynamicPoolCallable = callable;
836
+ }
837
+ return this.dynamicPoolCallable;
788
838
  }
789
839
 
790
840
  static get Pool() {
@@ -829,8 +879,8 @@ function getEntityClassCode(componentMap, queries, options) {
829
879
  array[offset++] = -1;
830
880
  continue;
831
881
  }
832
- array[offset++] = instance.version;
833
- if (instance.version & 1) {${""}
882
+ array[offset++] = instance.poolVersion;
883
+ if (instance.poolVersion & 1) {${""}
834
884
  continue;
835
885
  }
836
886
  offset = instance.toArray(array, offset, skipPoolReferences);
@@ -857,11 +907,11 @@ function getEntityClassCode(componentMap, queries, options) {
857
907
 
858
908
 
859
909
  for (let i = 0; i < usedLength; i++) {
860
- const version = arrayOfData[offset++];
910
+ const poolVersion = arrayOfData[offset++];
861
911
 
862
- if (version & 1) {
912
+ if (poolVersion & 1) {
863
913
  if (this.array[i]) {
864
- this.array[i].version = version;
914
+ this.array[i].poolVersion = poolVersion;
865
915
  }
866
916
  continue;
867
917
  }
@@ -872,7 +922,7 @@ function getEntityClassCode(componentMap, queries, options) {
872
922
  this.array[i] = new classConstructor(undefined, i, this);
873
923
  }
874
924
 
875
- this.array[i].version = version;
925
+ this.array[i].poolVersion = poolVersion;
876
926
 
877
927
  offset = this.array[i].fromArray(arrayOfData, references, offset);
878
928
  }
@@ -897,11 +947,11 @@ function getEntityClassCode(componentMap, queries, options) {
897
947
  }
898
948
 
899
949
  for (let i = 0; i < usedLength; i++) {
900
- const version = arrayOfData[offset++];
950
+ const poolVersion = arrayOfData[offset++];
901
951
 
902
- if (version & 1) {
952
+ if (poolVersion & 1) {
903
953
  if (this.array[i]) {
904
- this.array[i].version = version;
954
+ this.array[i].poolVersion = poolVersion;
905
955
  }
906
956
  continue;
907
957
  }
@@ -912,7 +962,7 @@ function getEntityClassCode(componentMap, queries, options) {
912
962
  this.array[i] = new classConstructor(undefined, i, this);
913
963
  }
914
964
 
915
- this.array[i].version = version;
965
+ this.array[i].poolVersion = poolVersion;
916
966
 
917
967
  offset = this.array[i].fromArrayNoReferences(arrayOfData, offset);
918
968
  }
@@ -937,11 +987,11 @@ function getEntityClassCode(componentMap, queries, options) {
937
987
  }
938
988
 
939
989
  for (let i = 0; i < usedLength; i++) {
940
- const version = arrayOfData[offset++];
990
+ const poolVersion = arrayOfData[offset++];
941
991
 
942
- if (version & 1) {
992
+ if (poolVersion & 1) {
943
993
  if (this.array[i]) {
944
- this.array[i].version = version;
994
+ this.array[i].poolVersion = poolVersion;
945
995
  }
946
996
  continue;
947
997
  }
@@ -952,7 +1002,7 @@ function getEntityClassCode(componentMap, queries, options) {
952
1002
  this.array[i] = new classConstructor(undefined, i, this);
953
1003
  }
954
1004
 
955
- this.array[i].version = version;
1005
+ this.array[i].poolVersion = poolVersion;
956
1006
 
957
1007
  offset = this.array[i].fromArrayOnlyReferences(arrayOfData, references, offset);
958
1008
  }
@@ -967,7 +1017,19 @@ function getEntityClassCode(componentMap, queries, options) {
967
1017
 
968
1018
  }
969
1019
 
970
- theClass.queries = queries;
1020
+ const queriesCallable = new Proxy(function () { return queriesCallable; }, {
1021
+ get(_target, prop) {
1022
+ if (prop in queries) {
1023
+ return queries[prop];
1024
+ }
1025
+ return undefined;
1026
+ },
1027
+ set(_target, prop, value) {
1028
+ queries[prop] = value;
1029
+ return true;
1030
+ },
1031
+ });
1032
+ theClass.queries = queriesCallable;
971
1033
  theClass.componentToEntity = componentToEntity;
972
1034
  theClass.componentIndices = componentIndices;
973
1035
  theClass.components = componentPools;
@@ -980,7 +1042,7 @@ function getEntityClassCode(componentMap, queries, options) {
980
1042
  const index = pool.freeIndices.pop();
981
1043
  pool.length++;
982
1044
  const instance = pool.array[index];
983
- instance.version++; ${""}
1045
+ instance.poolVersion++; ${""}
984
1046
  instance.reset(data, updateQueryMemberships, pool);
985
1047
  return instance;
986
1048
  } else {
@@ -993,12 +1055,12 @@ function getEntityClassCode(componentMap, queries, options) {
993
1055
 
994
1056
  theClass.Reference = class {
995
1057
  constructor(reference) {
996
- if (reference && !(reference.version & 1)) {
1058
+ if (reference && !(reference.poolVersion & 1)) {
997
1059
  this.reference = reference;
998
- this.version = reference.version;
1060
+ this.poolVersion = reference.poolVersion;
999
1061
  } else {
1000
1062
  this.reference = null;
1001
- this.version = -1;
1063
+ this.poolVersion = -1;
1002
1064
  }
1003
1065
  }
1004
1066
  }
@@ -1014,6 +1076,8 @@ function createEntityClass(options) {
1014
1076
  return (componentMap, queries) => new Function("componentMap", "queryMap", getEntityClassCode(componentMap, queries, options))(componentMap, queries);
1015
1077
  }
1016
1078
  export {
1079
+ EntityReference,
1080
+ EntityReferenceList,
1017
1081
  LazyComponent,
1018
1082
  createEntityClass,
1019
1083
  getEntityClassCode
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@perplexdotgg/mecs",
3
- "version": "0.4.2",
3
+ "version": "0.5.0",
4
4
  "description": "MECS - Monomorph ECS - A high-performance Entity Component System for TypeScript and JavaScript projects, designed for games and simulations.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -28,7 +28,7 @@
28
28
  "bench": "vitest bench"
29
29
  },
30
30
  "peerDependencies": {
31
- "monomorph": "^1.5.6"
31
+ "monomorph": "^2.1.0"
32
32
  },
33
33
  "peerDependenciesMeta": {
34
34
  "monomorph": {
@@ -37,7 +37,7 @@
37
37
  },
38
38
  "devDependencies": {
39
39
  "@types/node": "^25.0.1",
40
- "monomorph": "^1.5.6",
40
+ "monomorph": "^2.1.0",
41
41
  "ts-node": "^10.9.2",
42
42
  "tslib": "^2.8.1",
43
43
  "typescript": "^5.9.3",