@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 +4 -1
- package/build/index.d.ts +152 -37
- package/build/mecs.js +109 -45
- package/package.json +3 -3
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<
|
|
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
|
-
|
|
67
|
+
declare type ComponentTypeFromMonomorphClass<T> = T extends MonomorphClass<infer P, any, any> ? PropertyDefinitionClassProperties<P> : never;
|
|
54
68
|
|
|
55
|
-
export declare
|
|
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
|
|
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
|
|
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<
|
|
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<
|
|
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<
|
|
100
|
-
new (data: I,
|
|
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:
|
|
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
|
-
|
|
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<
|
|
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
|
|
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
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
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
|
|
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<
|
|
202
|
-
[K in KCM
|
|
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 {
|
|
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].
|
|
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}.
|
|
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.
|
|
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
|
-
|
|
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].
|
|
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.
|
|
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,
|
|
580
|
-
this.
|
|
581
|
-
this.
|
|
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.
|
|
674
|
+
if (this.poolVersion & 1 === 1) {
|
|
641
675
|
${""}
|
|
642
676
|
return;
|
|
643
677
|
}
|
|
644
|
-
this.
|
|
678
|
+
this.poolVersion++; // becomes odd, meaning deleted
|
|
645
679
|
if (this.pool) {
|
|
646
680
|
this.pool.length--;
|
|
647
|
-
this.pool.freeIndices.push(this.
|
|
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.
|
|
695
|
-
this.arrayOfVersions[length] = instance.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
761
|
-
this.arrayOfVersions[length] = instance.
|
|
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
|
-
|
|
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.
|
|
833
|
-
if (instance.
|
|
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
|
|
910
|
+
const poolVersion = arrayOfData[offset++];
|
|
861
911
|
|
|
862
|
-
if (
|
|
912
|
+
if (poolVersion & 1) {
|
|
863
913
|
if (this.array[i]) {
|
|
864
|
-
this.array[i].
|
|
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].
|
|
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
|
|
950
|
+
const poolVersion = arrayOfData[offset++];
|
|
901
951
|
|
|
902
|
-
if (
|
|
952
|
+
if (poolVersion & 1) {
|
|
903
953
|
if (this.array[i]) {
|
|
904
|
-
this.array[i].
|
|
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].
|
|
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
|
|
990
|
+
const poolVersion = arrayOfData[offset++];
|
|
941
991
|
|
|
942
|
-
if (
|
|
992
|
+
if (poolVersion & 1) {
|
|
943
993
|
if (this.array[i]) {
|
|
944
|
-
this.array[i].
|
|
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].
|
|
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
|
-
|
|
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.
|
|
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.
|
|
1058
|
+
if (reference && !(reference.poolVersion & 1)) {
|
|
997
1059
|
this.reference = reference;
|
|
998
|
-
this.
|
|
1060
|
+
this.poolVersion = reference.poolVersion;
|
|
999
1061
|
} else {
|
|
1000
1062
|
this.reference = null;
|
|
1001
|
-
this.
|
|
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.
|
|
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.
|
|
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.
|
|
40
|
+
"monomorph": "^2.1.0",
|
|
41
41
|
"ts-node": "^10.9.2",
|
|
42
42
|
"tslib": "^2.8.1",
|
|
43
43
|
"typescript": "^5.9.3",
|