ecspresso 0.16.2 → 0.17.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.
@@ -95,11 +95,7 @@ export default class CommandBuffer<Cfg extends WorldConfig = EmptyConfig> {
95
95
  * @param mutator A function that receives the component value for in-place mutation
96
96
  */
97
97
  mutateComponent<K extends keyof Cfg['components']>(entityId: number, componentName: K, mutator: (value: Cfg['components'][K]) => void): void;
98
- /**
99
- * Queue a markChanged command
100
- * @param entityId The entity ID
101
- * @param componentName The component to mark as changed
102
- */
98
+ /** Queue a markChanged command for playback. */
103
99
  markChanged<K extends keyof Cfg['components']>(entityId: number, componentName: K): void;
104
100
  /**
105
101
  * Queue a parent removal command
@@ -39,6 +39,8 @@ export declare class ECSpressoBuilder<Cfg extends WorldConfig = EmptyConfig, Lab
39
39
  private pendingPlugins;
40
40
  /** Fixed timestep interval (null means use default 1/60) */
41
41
  private _fixedDt;
42
+ /** True when `.disableChangeTracking()` was called; flips the runtime into "track nothing" at build. */
43
+ private _disableChangeTracking;
42
44
  constructor();
43
45
  /**
44
46
  * Add the first plugin when starting with empty types.
@@ -51,13 +53,7 @@ export declare class ECSpressoBuilder<Cfg extends WorldConfig = EmptyConfig, Lab
51
53
  readonly resources: {};
52
54
  readonly assets: Cfg['assets'];
53
55
  readonly screens: Cfg['screens'];
54
- }, Labels, Groups, AssetGroupNames, ReactiveQueryNames>, plugin: Plugin<PCfg, PReq, BL, BG, BAG, BRQ>): ECSpressoBuilder<{
55
- readonly components: PCfg['components'];
56
- readonly events: PCfg['events'];
57
- readonly resources: PCfg['resources'];
58
- readonly assets: Cfg['assets'] & PCfg['assets'];
59
- readonly screens: Cfg['screens'] & PCfg['screens'];
60
- }, Labels | BL, Groups | BG, AssetGroupNames | BAG, ReactiveQueryNames | BRQ>;
56
+ }, Labels, Groups, AssetGroupNames, ReactiveQueryNames>, plugin: Plugin<PCfg, PReq, BL, BG, BAG, BRQ>): ECSpressoBuilder<MergeConfigs<Cfg, PCfg>, Labels | BL, Groups | BG, AssetGroupNames | BAG, ReactiveQueryNames | BRQ>;
61
57
  /**
62
58
  * Add a subsequent plugin with type checking.
63
59
  * This overload enforces plugin type compatibility and requirement satisfaction.
@@ -82,6 +78,18 @@ export declare class ECSpressoBuilder<Cfg extends WorldConfig = EmptyConfig, Lab
82
78
  * Conflicts with existing resource types (same key, different type) produce a `never` return.
83
79
  */
84
80
  withResourceTypes<T extends Record<string, any>>(): TypesAreCompatible<Cfg['resources'], T> extends true ? ECSpressoBuilder<WithResources<Cfg, T>, Labels, Groups, AssetGroupNames, ReactiveQueryNames> : never;
81
+ /**
82
+ * Opt out of change tracking entirely. After this call every `markChanged`
83
+ * (and `commands.markChanged`) is a runtime no-op, and `changed:` filters
84
+ * yield nothing. Useful for worlds with no reactive consumers (e.g. the
85
+ * physics bench) to skip the per-mark sequence stamp and array allocation.
86
+ *
87
+ * By default, change tracking is auto-derived: any system that declares a
88
+ * `changed:` filter auto-subscribes those components, and all other marks
89
+ * become no-ops. If no system declares `changed:`, every mark is recorded
90
+ * (track-all default). Call this to force the no-op-everything mode.
91
+ */
92
+ disableChangeTracking(): this;
85
93
  /**
86
94
  * Add a resource during ECSpresso construction.
87
95
  *
@@ -635,11 +635,10 @@ export default class ECSpresso<Cfg extends WorldConfig = EmptyConfig, Labels ext
635
635
  */
636
636
  mutateComponent<K extends keyof Cfg['components']>(entityId: number, componentName: K, mutator: (value: Cfg['components'][K]) => void): Cfg['components'][K];
637
637
  /**
638
- * Mark a component as changed on an entity.
639
- * Each call increments a global monotonic sequence; systems with changed
640
- * queries will see the mark exactly once (on their next execution).
641
- * @param entityId The entity ID
642
- * @param componentName The component that was changed
638
+ * Mark a component as changed on an entity. Recorded iff the component is
639
+ * subscribed (auto-subscribed by any system's `changed:` filter, or implicit
640
+ * track-all when no subscription exists). Each recorded call increments a
641
+ * monotonic sequence; `changed:` queries see the mark once on their next run.
643
642
  */
644
643
  markChanged<K extends keyof Cfg['components']>(entityId: number, componentName: K): void;
645
644
  /**
@@ -23,9 +23,23 @@ export default class EntityManager<ComponentTypes> {
23
23
  private disposeCallbacks;
24
24
  /**
25
25
  * Per-entity per-component change sequence tracking.
26
- * Maps entityId -> (componentName -> sequence number when last changed)
26
+ * Flat storage: changeSeqs[entityId][componentIdx] = seq number when last changed.
27
+ * Component names are mapped to dense indices via componentNameToIdx.
28
+ * Uint32Array zero-init means "never changed" (seq numbers start at 1).
27
29
  */
28
30
  private changeSeqs;
31
+ private componentNameToIdx;
32
+ private _idxCache0Name;
33
+ private _idxCache0Idx;
34
+ private _idxCache1Name;
35
+ private _idxCache1Idx;
36
+ /**
37
+ * Subscription bitmap for change tracking. `null` means track all (the
38
+ * default); a Uint8Array means explicit-only, with 1 at indices that opted
39
+ * in via `subscribeChanged`. Indices outside the array's bounds are
40
+ * treated as 0 (not tracked).
41
+ */
42
+ private _subscribedComponentIdx;
29
43
  /**
30
44
  * Monotonic sequence counter for change detection.
31
45
  * Each markChanged call increments this and stamps the new value.
@@ -85,12 +99,16 @@ export default class EntityManager<ComponentTypes> {
85
99
  }>(entityId: number, components: T & Record<Exclude<keyof T, keyof ComponentTypes>, never>): this;
86
100
  removeComponent<ComponentName extends keyof ComponentTypes>(entityId: number, componentName: ComponentName): this;
87
101
  getComponent<ComponentName extends keyof ComponentTypes>(entityId: number, componentName: ComponentName): ComponentTypes[ComponentName] | undefined;
88
- getEntitiesWithQuery<WithComponents extends keyof ComponentTypes = never, WithoutComponents extends keyof ComponentTypes = never>(required?: ReadonlyArray<WithComponents>, excluded?: ReadonlyArray<WithoutComponents>, changed?: ReadonlyArray<keyof ComponentTypes>, changeThreshold?: number, parentHas?: ReadonlyArray<keyof ComponentTypes>): Array<FilteredEntity<ComponentTypes, WithComponents extends never ? never : WithComponents, WithoutComponents extends never ? never : WithoutComponents>>;
102
+ getEntitiesWithQuery<WithComponents extends keyof ComponentTypes = never, WithoutComponents extends keyof ComponentTypes = never>(required?: ReadonlyArray<WithComponents>, excluded?: ReadonlyArray<WithoutComponents>, changed?: ReadonlyArray<keyof ComponentTypes>, changeThreshold?: number, parentHas?: ReadonlyArray<keyof ComponentTypes>, changedIdx?: ReadonlyArray<number>): Array<FilteredEntity<ComponentTypes, WithComponents extends never ? never : WithComponents, WithoutComponents extends never ? never : WithoutComponents>>;
89
103
  /**
90
104
  * Fill an existing array with entities matching the query, clearing it first.
91
105
  * Returns the same array reference for convenience.
106
+ *
107
+ * `changedIdx`, when supplied, skips the per-call name→idx resolution loop.
108
+ * The framework pre-resolves it once at system registration; ad-hoc callers
109
+ * may omit it and pay the per-call lookup cost.
92
110
  */
93
- getEntitiesWithQueryInto<WithComponents extends keyof ComponentTypes = never, WithoutComponents extends keyof ComponentTypes = never>(output: Array<FilteredEntity<ComponentTypes, WithComponents extends never ? never : WithComponents, WithoutComponents extends never ? never : WithoutComponents>>, required?: ReadonlyArray<WithComponents>, excluded?: ReadonlyArray<WithoutComponents>, changed?: ReadonlyArray<keyof ComponentTypes>, changeThreshold?: number, parentHas?: ReadonlyArray<keyof ComponentTypes>): Array<FilteredEntity<ComponentTypes, WithComponents extends never ? never : WithComponents, WithoutComponents extends never ? never : WithoutComponents>>;
111
+ getEntitiesWithQueryInto<WithComponents extends keyof ComponentTypes = never, WithoutComponents extends keyof ComponentTypes = never>(output: Array<FilteredEntity<ComponentTypes, WithComponents extends never ? never : WithComponents, WithoutComponents extends never ? never : WithoutComponents>>, required?: ReadonlyArray<WithComponents>, excluded?: ReadonlyArray<WithoutComponents>, changed?: ReadonlyArray<keyof ComponentTypes>, changeThreshold?: number, parentHas?: ReadonlyArray<keyof ComponentTypes>, changedIdx?: ReadonlyArray<number>): Array<FilteredEntity<ComponentTypes, WithComponents extends never ? never : WithComponents, WithoutComponents extends never ? never : WithoutComponents>>;
94
112
  /** Test-only accessor for the internal query cache. @internal */
95
113
  get _queryCacheForTesting(): QueryCache<ComponentTypes>;
96
114
  removeEntity(entityId: number, options?: RemoveEntityOptions): boolean;
@@ -135,6 +153,32 @@ export default class EntityManager<ComponentTypes> {
135
153
  * @param componentName The component that changed
136
154
  */
137
155
  markChanged<K extends keyof ComponentTypes>(entityId: number, componentName: K): void;
156
+ /**
157
+ * Fast-path companion to markChanged that skips the component-name lookup.
158
+ * Use after resolving names to indices once via getOrAssignComponentIdx.
159
+ */
160
+ markChangedByIdx(entityId: number, componentIdx: number): void;
161
+ getOrAssignComponentIdx<K extends keyof ComponentTypes>(componentName: K): number;
162
+ /**
163
+ * @internal Subscribe a component to change tracking. First call transitions
164
+ * from default track-all (null bitmap) to explicit-only mode; subsequent calls
165
+ * extend the subscription set. Called by ECSpresso._registerSystem for each
166
+ * component named in a query's `changed:` filter.
167
+ */
168
+ subscribeChanged<K extends keyof ComponentTypes>(componentName: K): void;
169
+ /**
170
+ * @internal Opt out of change tracking entirely. Installs an empty bitmap,
171
+ * making every markChanged call a no-op until subscribeChanged is called.
172
+ * Used by `.disableChangeTracking()` on the builder for worlds with no
173
+ * reactive consumers.
174
+ */
175
+ disableChangeTracking(): void;
176
+ /**
177
+ * @internal True if at least one of `idxs` is currently subscribed for
178
+ * change tracking (or the bitmap is null = track-all). Used by the
179
+ * auto-mark walk to skip entity iteration when every mark would be a no-op.
180
+ */
181
+ hasAnySubscribed(idxs: ReadonlyArray<number>): boolean;
138
182
  /**
139
183
  * Get the sequence number at which a component was last changed on an entity
140
184
  * @param entityId The entity ID
@@ -22,7 +22,8 @@ export default class EventBus<EventTypes> {
22
22
  * Zero-allocation hot path: uses index-based iteration with a snapshot length
23
23
  * so handlers added mid-publish are not called in the same publish cycle.
24
24
  */
25
- publish<E extends keyof EventTypes>(...[eventType, data]: EventTypes[E] extends void | undefined ? [eventType: E, data?: EventTypes[E]] : [eventType: E, data: EventTypes[E]]): void;
25
+ publish<E extends keyof EventTypes>(eventType: EventTypes[E] extends void | undefined ? E : never): void;
26
+ publish<E extends keyof EventTypes>(eventType: E, data: EventTypes[E]): void;
26
27
  clear(): void;
27
28
  clearEvent<E extends keyof EventTypes>(eventType: E): void;
28
29
  }
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- var $j=((j)=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(j,{get:(D,$)=>(typeof require<"u"?require:D)[$]}):j)(function(j){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+j+'" is not supported')});class H{parentMap=new Map;childrenMap=new Map;_bfsQueue=[];setParent(j,D){if(j===D)throw Error(`Cannot set entity ${j} as its own parent`);if(this.wouldCreateCycle(j,D))throw Error("Cannot set parent: would create circular reference");let $=this.parentMap.get(j);if($!==void 0){let J=this.childrenMap.get($);if(J){let X=J.indexOf(j);if(X!==-1)J.splice(X,1)}}this.parentMap.set(j,D);let G=this.childrenMap.get(D);if(G)G.push(j);else this.childrenMap.set(D,[j]);return this}removeParent(j){let D=this.parentMap.get(j);if(D===void 0)return!1;let $=this.childrenMap.get(D);if($){let G=$.indexOf(j);if(G!==-1)$.splice(G,1)}return this.parentMap.delete(j),!0}getParent(j){return this.parentMap.get(j)??null}getChildren(j){let D=this.childrenMap.get(j);return D?[...D]:[]}getChildAt(j,D){if(D<0)return null;let $=this.childrenMap.get(j);if(!$||D>=$.length)return null;return $[D]??null}getChildIndex(j,D){let $=this.childrenMap.get(j);if(!$)return-1;return $.indexOf(D)}removeEntity(j){let D=this.parentMap.get(j)??null;if(D!==null){let J=this.childrenMap.get(D);if(J){let X=J.indexOf(j);if(X!==-1)J.splice(X,1)}}this.parentMap.delete(j);let $=this.childrenMap.get(j)??[],G=[...$];for(let J of $)this.parentMap.delete(J);return this.childrenMap.delete(j),{oldParent:D,orphanedChildren:G}}getAncestors(j){let D=[],$=this.parentMap.get(j);while($!==void 0)D.push($),$=this.parentMap.get($);return D}getDescendants(j){let D=[],$=this.childrenMap.get(j);if(!$)return D;let G=$.slice().reverse();while(G.length>0){let J=G.pop();D.push(J);let X=this.childrenMap.get(J);if(X)for(let Z=X.length-1;Z>=0;Z--)G.push(X[Z])}return D}getRoot(j){let D=j,$=this.parentMap.get(D);while($!==void 0)D=$,$=this.parentMap.get(D);return D}getSiblings(j){let D=this.parentMap.get(j);if(D===void 0)return[];let $=this.childrenMap.get(D);if(!$)return[];return $.filter((G)=>G!==j)}isDescendantOf(j,D){if(j===D)return!1;let $=this.parentMap.get(j);while($!==void 0){if($===D)return!0;$=this.parentMap.get($)}return!1}isAncestorOf(j,D){return this.isDescendantOf(D,j)}get hasHierarchy(){return this.childrenMap.size>0}getRootEntities(){let j=[];for(let D of this.childrenMap.keys())if(!this.parentMap.has(D))j.push(D);return j}wouldCreateCycle(j,D){let $=D;while($!==void 0){if($===j)return!0;$=this.parentMap.get($)}return!1}forEachInHierarchy(j,D){let $=D?.roots??this.getRootEntities(),G=this._bfsQueue;G.length=0;for(let J of $)G.push(J,-1,0);for(let J=0;J<G.length;J+=3){let X=G[J],Z=G[J+1],W=G[J+2];j(X,Z===-1?null:Z,W);let A=this.childrenMap.get(X);if(A){let L=W+1;for(let O of A)G.push(O,X,L)}}}*hierarchyIterator(j){let D=j?.roots??this.getRootEntities(),$=[];for(let G of D)$.push({entityId:G,parentId:null,depth:0});for(let G of $){yield G;let J=this.childrenMap.get(G.entityId);if(J)for(let X of J)$.push({entityId:X,parentId:G.entityId,depth:G.depth+1})}}}function R(j,D,$,G,J){let X=j.components;for(let Z of D)if(!(Z in X))return!1;if($){for(let Z of $)if(Z in X)return!1}if(G&&G.length>0){let Z=J.getParent(j.id);if(Z===null)return!1;let W=J.getEntity(Z);if(!W)return!1;let A=W.components;for(let L of G)if(!(L in A))return!1}return!0}function a(j,D,$){let G=j.length===0?"":[...j].map(String).sort().join(","),J=D.length===0?"":[...D].map(String).sort().join(","),X=$.length===0?"":[...$].map(String).sort().join(",");return`${G}|${J}|${X}`}class S{host;caches=new Map;byComp=new Map;byParentComp=new Map;constructor(j){this.host=j}getOrCreate(j,D,$){let G=a(j,D,$),J=this.caches.get(G);if(J)return J.members;let X={with:[...j],without:[...D],parentHas:[...$],members:new Map};this.caches.set(G,X);for(let Z of X.with)v(this.byComp,Z,X);for(let Z of X.without)v(this.byComp,Z,X);for(let Z of X.parentHas)v(this.byParentComp,Z,X);return this.populate(X),X.members}get cacheCount(){return this.caches.size}populate(j){let D=this.host,$=j.with;if($.length===0){for(let Z of D.allEntities())if(this.matches(Z,j))j.members.set(Z.id,Z);return}let G=$[0];if(G===void 0)return;let J=D.componentIndex(G)?.size??0;for(let Z=1;Z<$.length;Z++){let W=$[Z];if(W===void 0)continue;let A=D.componentIndex(W)?.size??0;if(A<J)G=W,J=A}let X=D.componentIndex(G);if(!X||X.size===0)return;for(let Z of X){let W=D.getEntity(Z);if(!W)continue;if(this.matches(W,j))j.members.set(Z,W)}}matches(j,D){return R(j,D.with,D.without,D.parentHas,this.host)}reeval(j,D){let $=this.host.getEntity(j);if(!$){D.members.delete(j);return}if(this.matches($,D))D.members.set(j,$);else D.members.delete(j)}onComponentChanged(j,D){let $=this.byComp.get(D);if($)for(let J of $)this.reeval(j,J);let G=this.byParentComp.get(D);if(G&&G.length>0){let J=this.host.getChildren(j);if(J.length>0)for(let X of G)for(let Z of J)this.reeval(Z,X)}}onParentChanged(j){for(let D of this.caches.values())if(D.parentHas.length>0)this.reeval(j,D)}onEntityRemoved(j){let D=!1;for(let G of this.caches.values())if(G.members.delete(j),G.parentHas.length>0)D=!0;if(!D)return;let $=this.host.getChildren(j);if($.length===0)return;for(let G of this.caches.values()){if(G.parentHas.length===0)continue;for(let J of $)G.members.delete(J)}}}function v(j,D,$){let G=j.get(D);if(G)G.push($);else j.set(D,[$])}function m(j,D,$){if(!j)return!1;for(let G of D)if((j.get(G)??-1)>$)return!0;return!1}class N{callbacks=[];_iterDepth=0;_pendingRemovals=[];add(j){this.callbacks.push(j)}remove(j){if(this._iterDepth>0){this._pendingRemovals.push(j);return}let D=this.callbacks.indexOf(j);if(D!==-1)this.callbacks.splice(D,1)}invoke(j){this._iterDepth++;let D=this.callbacks.length;for(let $=0;$<D;$++){let G=this.callbacks[$];if(G)G(j)}if(this._iterDepth--,this._iterDepth===0&&this._pendingRemovals.length>0){for(let $ of this._pendingRemovals){let G=this.callbacks.indexOf($);if(G!==-1)this.callbacks.splice(G,1)}this._pendingRemovals.length=0}}}class T{nextId=1;entities=new Map;componentIndices=new Map;addedCallbacks=new Map;removedCallbacks=new Map;hierarchyManager=new H;disposeCallbacks=new Map;changeSeqs=new Map;_changeSeq=0;_afterComponentAddedHooks=[];_afterEntityMutatedHooks=[];_afterComponentRemovedHooks=[];_beforeEntityRemovedHooks=[];_afterParentChangedHooks=[];_queryCache=new S({getEntity:(j)=>this.entities.get(j),getParent:(j)=>this.hierarchyManager.getParent(j),getChildren:(j)=>this.hierarchyManager.getChildren(j),allEntities:()=>this.entities.values(),componentIndex:(j)=>this.componentIndices.get(j)});_batchingDepth=0;_batchedEntityIds=new Set;_pendingBatchKeys=null;get entityCount(){return this.entities.size}createEntity(){let j=this.nextId++,D={id:j,components:{}};return this.entities.set(j,D),D}registerDispose(j,D){this.disposeCallbacks.set(j,D)}getDisposeCallbacks(){return this.disposeCallbacks}invokeDispose(j,D,$){let G=this.disposeCallbacks.get(j);if(!G)return;try{G({value:D,entityId:$})}catch(J){console.warn(`Component dispose callback for '${String(j)}' threw:`,J)}}addComponent(j,D,$){let G=this.entities.get(j);if(!G)throw Error(`Cannot add component '${String(D)}': Entity with ID ${j} does not exist`);let J=G.components[D];if(J!==void 0)this.invokeDispose(D,J,G.id);if(G.components[D]=$,!this.componentIndices.has(D))this.componentIndices.set(D,new Set);this.componentIndices.get(D)?.add(G.id);let X=this.addedCallbacks.get(D);if(X)X.invoke({value:$,entity:G});this._queryCache.onComponentChanged(G.id,D),this._batchingDepth++;for(let Z of this._afterComponentAddedHooks)Z(G.id,D);if(this._batchedEntityIds.add(G.id),this._batchingDepth--,this._batchingDepth===0){for(let Z of this._batchedEntityIds)for(let W of this._afterEntityMutatedHooks)W(Z);this._batchedEntityIds.clear()}return this}addComponents(j,D){let $=this.entities.get(j);if(!$)throw Error(`Cannot add components: Entity with ID ${j} does not exist`);let G=this._pendingBatchKeys;this._pendingBatchKeys=new Set(Object.keys(D)),this._batchingDepth++;for(let J in D)this.addComponent($.id,J,D[J]);if(this._batchingDepth--,this._pendingBatchKeys=G,this._batchingDepth===0){for(let J of this._batchedEntityIds)for(let X of this._afterEntityMutatedHooks)X(J);this._batchedEntityIds.clear()}return this}removeComponent(j,D){let $=this.entities.get(j);if(!$)throw Error(`Cannot remove component '${String(D)}': Entity with ID ${j} does not exist`);let G=$.components[D];if(G!==void 0)this.invokeDispose(D,G,$.id);delete $.components[D];let J=this.removedCallbacks.get(D);if(J&&G!==void 0)J.invoke({value:G,entity:$});if(this.componentIndices.get(D)?.delete($.id),G!==void 0){this._queryCache.onComponentChanged($.id,D);for(let X of this._afterComponentRemovedHooks)X($.id,D)}return this}getComponent(j,D){return this.entities.get(j)?.components[D]}getEntitiesWithQuery(j=[],D=[],$,G,J){return this.getEntitiesWithQueryInto([],j,D,$,G,J)}getEntitiesWithQueryInto(j,D=[],$=[],G,J,X){j.length=0;let Z=G!==void 0&&G.length>0&&J!==void 0,W=X!==void 0&&X.length>0;if(D.length===0&&$.length===0&&!W){if(!Z){for(let L of this.entities.values())j.push(L);return j}for(let L of this.entities.values()){if(!m(this.changeSeqs.get(L.id),G,J))continue;j.push(L)}return j}let A=this._queryCache.getOrCreate(D,$,X??[]);if(A.size===0)return j;if(Z){for(let L of A.values()){if(!m(this.changeSeqs.get(L.id),G,J))continue;j.push(L)}return j}for(let L of A.values())j.push(L);return j}get _queryCacheForTesting(){return this._queryCache}removeEntity(j,D){let $=this.entities.get(j);if(!$)return!1;if(D?.cascade??!0){let J=this.hierarchyManager.getDescendants($.id);for(let X=J.length-1;X>=0;X--){let Z=J[X];if(Z===void 0)continue;this._queryCache.onEntityRemoved(Z);for(let W of this._beforeEntityRemovedHooks)W(Z)}this._queryCache.onEntityRemoved($.id);for(let X of this._beforeEntityRemovedHooks)X($.id);for(let X=J.length-1;X>=0;X--){let Z=J[X];if(Z===void 0)continue;this.removeEntityInternal(Z)}}else{this._queryCache.onEntityRemoved($.id);for(let J of this._beforeEntityRemovedHooks)J($.id)}return this.removeEntityInternal($.id)}removeEntityInternal(j){let D=this.entities.get(j);if(!D)return!1;this.hierarchyManager.removeEntity(j);for(let $ of Object.keys(D.components)){let G=D.components[$];if(G!==void 0){this.invokeDispose($,G,D.id);let J=this.removedCallbacks.get($);if(J)J.invoke({value:G,entity:D})}this.componentIndices.get($)?.delete(D.id)}return this.changeSeqs.delete(D.id),this.entities.delete(D.id)}getEntity(j){return this.entities.get(j)}onComponentAdded(j,D){let $=D,G=this.addedCallbacks.get(j);if(!G)G=new N,this.addedCallbacks.set(j,G);return G.add($),()=>{this.addedCallbacks.get(j)?.remove($)}}onComponentRemoved(j,D){let $=D,G=this.removedCallbacks.get(j);if(!G)G=new N,this.removedCallbacks.set(j,G);return G.add($),()=>{this.removedCallbacks.get(j)?.remove($)}}onAfterComponentAdded(j){return this._afterComponentAddedHooks.push(j),()=>{let D=this._afterComponentAddedHooks.indexOf(j);if(D!==-1)this._afterComponentAddedHooks.splice(D,1)}}onAfterEntityMutated(j){return this._afterEntityMutatedHooks.push(j),()=>{let D=this._afterEntityMutatedHooks.indexOf(j);if(D!==-1)this._afterEntityMutatedHooks.splice(D,1)}}onAfterComponentRemoved(j){return this._afterComponentRemovedHooks.push(j),()=>{let D=this._afterComponentRemovedHooks.indexOf(j);if(D!==-1)this._afterComponentRemovedHooks.splice(D,1)}}onBeforeEntityRemoved(j){return this._beforeEntityRemovedHooks.push(j),()=>{let D=this._beforeEntityRemovedHooks.indexOf(j);if(D!==-1)this._beforeEntityRemovedHooks.splice(D,1)}}onAfterParentChanged(j){return this._afterParentChangedHooks.push(j),()=>{let D=this._afterParentChangedHooks.indexOf(j);if(D!==-1)this._afterParentChangedHooks.splice(D,1)}}get changeSeq(){return this._changeSeq}markChanged(j,D){let $=++this._changeSeq,G=this.changeSeqs.get(j);if(!G)G=new Map,this.changeSeqs.set(j,G);G.set(D,$)}getChangeSeq(j,D){return this.changeSeqs.get(j)?.get(D)??-1}spawnChild(j,D){let $=this.createEntity();return this.addComponents($.id,D),this.setParent($.id,j),$}setParent(j,D){this.hierarchyManager.setParent(j,D),this._queryCache.onParentChanged(j);for(let $ of this._afterParentChangedHooks)$(j);return this}removeParent(j){let D=this.hierarchyManager.removeParent(j);if(D){this._queryCache.onParentChanged(j);for(let $ of this._afterParentChangedHooks)$(j)}return D}getParent(j){return this.hierarchyManager.getParent(j)}getChildren(j){return this.hierarchyManager.getChildren(j)}getChildAt(j,D){return this.hierarchyManager.getChildAt(j,D)}getChildIndex(j,D){return this.hierarchyManager.getChildIndex(j,D)}getAncestors(j){return this.hierarchyManager.getAncestors(j)}getDescendants(j){return this.hierarchyManager.getDescendants(j)}getRoot(j){return this.hierarchyManager.getRoot(j)}getSiblings(j){return this.hierarchyManager.getSiblings(j)}isDescendantOf(j,D){return this.hierarchyManager.isDescendantOf(j,D)}isAncestorOf(j,D){return this.hierarchyManager.isAncestorOf(j,D)}get hasHierarchy(){return this.hierarchyManager.hasHierarchy}getRootEntities(){return this.hierarchyManager.getRootEntities()}forEachInHierarchy(j,D){this.hierarchyManager.forEachInHierarchy(j,D)}hierarchyIterator(j){return this.hierarchyManager.hierarchyIterator(j)}}class x{handlers=new Map;subscribe(j,D){return this.addHandler(j,D,!1)}once(j,D){return this.addHandler(j,D,!0)}unsubscribe(j,D){let $=this.handlers.get(j);if(!$)return!1;let G=$.findIndex((J)=>J.callback===D);if(G===-1)return!1;return $.splice(G,1),!0}addHandler(j,D,$){let G=this.handlers.get(j);if(!G)G=[],this.handlers.set(j,G);let J={callback:D,once:$};return G.push(J),()=>{let X=this.handlers.get(j);if(X){let Z=X.indexOf(J);if(Z!==-1)X.splice(Z,1)}}}publish(...[j,D]){let $=this.handlers.get(j);if(!$||$.length===0)return;let G=!1,J=$.length;for(let X=0;X<J&&X<$.length;X++){let Z=$[X];if(!Z)continue;if(Z.callback(D),Z.once)G=!0}if(G){for(let X=$.length-1;X>=0;X--)if($[X]?.once)$.splice(X,1)}}clear(){this.handlers.clear()}clearEvent(j){this.handlers.delete(j)}}var p=Symbol("resource-direct");function n(j){return{[p]:j}}function b(j){if(typeof j==="object"&&j!==null&&!Array.isArray(j))return{...j};return{$value:j}}function t(j,D){if(typeof j==="object"&&j!==null&&!Array.isArray(j)){let $=j;for(let G in D)if(!Object.is($[G],D[G]))return!0;return!1}return!Object.is(j,D.$value)}function e(j){return typeof j==="object"&&j!==null&&"factory"in j&&typeof j.factory==="function"}function jj(j){return typeof j==="object"&&j!==null&&p in j}function l(j,D){let $=[],G=new Set,J=new Set;function X(Z,W=[]){if(G.has(Z))return;if(J.has(Z))throw Error(`Circular resource dependency: ${[...W,Z].join(" -> ")}`);J.add(Z);for(let A of D(Z)){let L=j.find((O)=>O===A);if(L)X(L,[...W,Z])}J.delete(Z),G.add(Z),$.push(Z)}for(let Z of j)X(Z);return $}class w{resources=new Map;resourceFactories=new Map;resourceDependencies=new Map;resourceDisposers=new Map;initializedResourceKeys=new Set;_changeSubscribers=new Map;_observedSnapshots=new Map;add(j,D){let $=(G)=>{this.resources.set(j,G),this.initializedResourceKeys.add(j),this.resourceDependencies.set(j,[])};if(e(D)){if(this.resourceFactories.set(j,D.factory),this.resourceDependencies.set(j,D.dependsOn??[]),D.onDispose)this.resourceDisposers.set(j,D.onDispose)}else if(jj(D))$(D[p]);else if(typeof D==="function")this.resourceFactories.set(j,D),this.resourceDependencies.set(j,[]);else $(D);return this}tryGet(j,...D){if(!this.has(j))return;return this.get(j,...D)}get(j,...D){let $=this.resources.get(j);if($!==void 0)return $;let G=this.resourceFactories.get(j);if(G===void 0)throw Error(`Resource ${String(j)} not found`);let J=D[0],X=G(J);if(!(X instanceof Promise))this.resources.set(j,X),this.initializedResourceKeys.add(j);return X}has(j){return this.resources.has(j)||this.resourceFactories.has(j)}remove(j){let D=this.resources.delete(j),$=this.resourceFactories.delete(j);return this.resourceDependencies.delete(j),this.resourceDisposers.delete(j),this.initializedResourceKeys.delete(j),D||$}getKeys(){let j=new Set([...this.resources.keys(),...this.resourceFactories.keys()]);return Array.from(j)}needsInitialization(j){return this.resourceFactories.has(j)&&!this.initializedResourceKeys.has(j)}getPendingInitializationKeys(){return Array.from(this.resourceFactories.keys()).filter((j)=>!this.initializedResourceKeys.has(j))}async initializeResource(j,...D){if(!this.resourceFactories.has(j)||this.initializedResourceKeys.has(j))return;let $=this.resourceFactories.get(j);if(!$)return;let G=D[0],J=await $(G);this.resources.set(j,J),this.initializedResourceKeys.add(j),this.resourceFactories.delete(j)}async initializeResources(...j){let D=j.slice(1),$=D.length===0?this.getPendingInitializationKeys():D;if($.length===0)return;let G=l($,(J)=>[...this.resourceDependencies.get(J)??[]]);for(let J of G)await this.initializeResource(J,...j.slice(0,1))}getDependencies(j){return this.resourceDependencies.get(j)??[]}async disposeResource(j,...D){if(!this.resources.has(j)&&!this.resourceFactories.has(j))return!1;if(this.initializedResourceKeys.has(j)){let $=this.resourceDisposers.get(j),G=this.resources.get(j);if($&&G!==void 0){let J=D[0];await $(G,J)}}return this.resources.delete(j),this.resourceFactories.delete(j),this.resourceDependencies.delete(j),this.resourceDisposers.delete(j),this.initializedResourceKeys.delete(j),this._changeSubscribers.delete(j),!0}onResourceChange(j,D){let $=this._changeSubscribers.get(j),G=$??new Set;if(!$){this._changeSubscribers.set(j,G);let X=this.resources.get(j);this._observedSnapshots.set(j,b(X))}let J=D;return G.add(J),()=>{if(G.delete(J),G.size===0)this._changeSubscribers.delete(j),this._observedSnapshots.delete(j)}}notifyChange(j,D,$){if(Object.is(D,$))return;let G=this._changeSubscribers.get(j);if(!G||G.size===0)return;if(this._observedSnapshots.has(j))this._observedSnapshots.set(j,b(D));let J=[...G];for(let X of J)X(D,$)}isObserved(j){return this._observedSnapshots.has(j)}flushObserved(){if(this._observedSnapshots.size===0)return;for(let[j,D]of this._observedSnapshots){let $=this.resources.get(j);if(!t($,D))continue;let G="$value"in D?D.$value:D,J=b($),X=this._changeSubscribers.get(j);for(let Z of X)Z($,G);this._observedSnapshots.set(j,J)}}async disposeResources(...j){let D=Array.from(this.initializedResourceKeys);if(D.length===0)return;let $=l(D,(G)=>[...this.resourceDependencies.get(G)??[]]).reverse();for(let G of $)await this.disposeResource(G,...j)}}class q{queries=new Map;entityManager;_hasParentHasQueries=!1;constructor(j){this.entityManager=j}get hasParentHasQueries(){return this._hasParentHasQueries}addQuery(j,D){let $={definition:D,matchingEntities:new Set};if(this.queries.set(j,$),D.parentHas?.length)this._hasParentHasQueries=!0;let G=this.entityManager.getEntitiesWithQuery(D.with,D.without??[]);for(let J of G)if(this.entityMatchesQuery(J,$.definition))$.matchingEntities.add(J.id),$.definition.onEnter?.(J)}removeQuery(j){let D=this.queries.delete(j);if(D)this._recalcParentHasFlag();return D}entityMatchesQuery(j,D){return R(j,D.with,D.without,D.parentHas,this.entityManager)}_applyQueryTransition(j,D){let $=D.matchingEntities.has(j.id),G=this.entityMatchesQuery(j,D.definition);if(!$&&G)D.matchingEntities.add(j.id),D.definition.onEnter?.(j);else if($&&!G)D.matchingEntities.delete(j.id),D.definition.onExit?.(j.id)}onComponentAdded(j,D){for(let[,$]of this.queries)this._applyQueryTransition(j,$);if(this._hasParentHasQueries)this._recheckChildren(j.id)}onComponentRemoved(j,D){for(let[,$]of this.queries)this._applyQueryTransition(j,$);if(this._hasParentHasQueries)this._recheckChildren(j.id)}onEntityRemoved(j){for(let[D,$]of this.queries)if($.matchingEntities.has(j))$.matchingEntities.delete(j),$.definition.onExit?.(j)}recheckEntity(j){for(let[,D]of this.queries)this._applyQueryTransition(j,D)}recheckEntityAndChildren(j){if(this.recheckEntity(j),this._hasParentHasQueries)this._recheckChildren(j.id)}_recheckChildren(j){let D=this.entityManager.getChildren(j);for(let $ of D){let G=this.entityManager.getEntity($);if(G)this.recheckEntity(G)}}_recalcParentHasFlag(){this._hasParentHasQueries=!1;for(let[,j]of this.queries)if(j.definition.parentHas?.length){this._hasParentHasQueries=!0;return}}}class C{parent;commands=[];constructor(j){this.parent=j}removeEntity(j,D){this.commands.push(($)=>{$.removeEntity(j,D)})}addComponent(j,D,$){this.commands.push((G)=>{G.addComponent(j,D,$)})}removeComponent(j,D){this.commands.push(($)=>{$.removeComponent(j,D)})}spawn(j,D){let $=this._resolveScope(D);this.commands.push((G)=>{G.spawn(j,$)})}spawnChild(j,D,$){let G=this._resolveScope($);this.commands.push((J)=>{J.spawnChild(j,D,G)})}_resolveScope(j){if(j?.scope!==void 0)return j;let D=this.parent?._getActiveScopeHint();if(!D)return j;return{scope:D}}addComponents(j,D){this.commands.push(($)=>{$.addComponents(j,D)})}setParent(j,D){this.commands.push(($)=>{$.setParent(j,D)})}mutateComponent(j,D,$){this.commands.push((G)=>{G.mutateComponent(j,D,$)})}markChanged(j,D){this.commands.push(($)=>{$.markChanged(j,D)})}removeParent(j){this.commands.push((D)=>{D.removeParent(j)})}playback(j){for(let D of this.commands)try{D(j)}catch($){console.warn("CommandBuffer: Command failed during playback:",$)}this.commands.length=0}clear(){this.commands.length=0}get length(){return this.commands.length}}class s{_id;constructor(j){this._id=j}_systemDefaults;setSystemDefaults(j){return this._systemDefaults=j,this}withComponentTypes(){return this}withEventTypes(){return this}withResourceTypes(){return this}withAssetTypes(){return this}withScreenTypes(){return this}withLabels(){return this}withGroups(){return this}withAssetGroupNames(){return this}withReactiveQueryNames(){return this}requires(){return this}install(j){return{id:this._id,install:j,...this._systemDefaults?{systemDefaults:this._systemDefaults}:{}}}}function E(j){return new s(j)}var i="__each";class g{_label;queries={};singletons={};processFunction;detachFunction;initializeFunction;eventHandlers;_priority=0;_phase="update";_groups=[];_inScreens;_excludeScreens;_requiredAssets;_runWhenEmpty=!1;_entityEnterHandlers={};_resourceKeys;constructor(j,D){this._label=j;if(D){if(D.phase!==void 0)this._phase=D.phase;if(D.priority!==void 0)this._priority=D.priority;if(D.inScreens!==void 0)this._inScreens=D.inScreens;if(D.excludeScreens!==void 0)this._excludeScreens=D.excludeScreens}}get label(){return this._label}_createSystemObject(){let j={label:this._label,entityQueries:this.queries,priority:this._priority,phase:this._phase};if(Object.keys(this.singletons).length>0)j.entitySingletons=this.singletons;if(this.processFunction)j.process=this.processFunction;if(this.detachFunction)j.onDetach=this.detachFunction;if(this.initializeFunction)j.onInitialize=this.initializeFunction;if(this.eventHandlers)j.eventHandlers=this.eventHandlers;if(this._groups.length>0)j.groups=[...this._groups];if(this._inScreens)j.inScreens=this._inScreens;if(this._excludeScreens)j.excludeScreens=this._excludeScreens;if(this._requiredAssets)j.requiredAssets=this._requiredAssets;if(this._runWhenEmpty)j.runWhenEmpty=!0;if(Object.keys(this._entityEnterHandlers).length>0)j.onEntityEnter={...this._entityEnterHandlers};return j}setPriority(j){return this._priority=j,this}inPhase(j){return this._phase=j,this}inGroup(j){if(!this._groups.includes(j))this._groups.push(j);return this}inScreens(j){return this._inScreens=[...j],this}excludeScreens(j){return this._excludeScreens=[...j],this}requiresAssets(j){return this._requiredAssets=[...j],this}runWhenEmpty(){return this._runWhenEmpty=!0,this}withResources(j){return this._resourceKeys=[...j],this}addQuery(j,D){let $=this;return $.queries={...this.queries,[j]:D},$}addSingleton(j,D){let $=this;return $.singletons={...this.singletons,[j]:D},$}setProcess(j){return this.processFunction=this._wrapWithResources(j),this}_wrapWithResources(j){if(!this._resourceKeys?.length)return j;let D=this._resourceKeys,$={},G=!1;return(J)=>{for(let X of D)if(!G||J.ecs.isResourceObserved(X))$[X]=J.ecs.getResource(X);G=!0,J.resources=$,j(J)}}setProcessEach(j,D){let $=this;if(Object.keys($.queries).length>0||Object.keys($.singletons).length>0||$.processFunction!==void 0)throw Error("setProcessEach requires a SystemBuilder with no prior queries, singletons, or process function. Use addQuery + setProcess for multi-query systems.");$.queries.__each=j;let G={entity:void 0,dt:0,ecs:void 0,resources:void 0},J=j.mutates&&j.mutates.length>0?j.mutates:void 0,X=(Z)=>{let W=Z,A=W.queries.__each;if(!A)return;G.dt=W.dt,G.ecs=W.ecs,G.resources=W.resources;for(let L=0;L<A.length;L++){let O=A[L];if(!O)continue;G.entity=O;let _=D(G);if(J===void 0||_===!1)continue;for(let Y=0;Y<J.length;Y++){let F=J[Y];if(F!==void 0)W.ecs.markChanged(O.id,F)}}};return $.processFunction=$._wrapWithResources(X),this}setOnEntityEnter(j,D){return this._entityEnterHandlers[j]=D,this}setOnDetach(j){return this.detachFunction=j,this}setOnInitialize(j){return this.initializeFunction=j,this}setEventHandlers(j){return this.eventHandlers=j,this}}function c(j,D,$){let G=new Set,J=[D];while(J.length>0){let X=J.pop();if(X===void 0)break;if(X===j)throw Error(`Circular required component dependency: '${String(j)}' -> '${String(D)}' -> ... -> '${String(j)}'`);if(G.has(X))continue;G.add(X);let Z=$(X);if(Z)for(let W of Z)J.push(W.component)}}var d="0.16.2";class z{assets=new Map;groups=new Map;eventBus=null;setEventBus(j){this.eventBus=j}register(j,D){if(this.assets.set(j,{definition:D,status:"pending"}),D.group){let $=this.groups.get(D.group)??new Set;$.add(j),this.groups.set(D.group,$)}}async loadEagerAssets(){let j=[];for(let[D,$]of this.assets)if($.definition.eager&&$.status==="pending")j.push(D);await Promise.all(j.map((D)=>this.loadAsset(D)))}async loadAsset(j){let D=this.assets.get(j);if(!D)throw Error(`Asset '${String(j)}' not found`);if(D.status==="loaded"&&D.value!==void 0)return D.value;if(D.status==="loading"&&D.loadPromise)return D.loadPromise;if(D.status==="failed")D.status="pending";D.status="loading",D.loadPromise=D.definition.loader();try{let $=await D.loadPromise;return D.value=$,D.status="loaded",D.loadPromise=void 0,this.eventBus?.publish("assetLoaded",{key:j}),this.checkGroupProgress(D.definition.group),$}catch($){let G=$ instanceof Error?$:Error(String($));throw D.status="failed",D.error=G,D.loadPromise=void 0,this.eventBus?.publish("assetFailed",{key:j,error:G}),G}}async loadAssetGroup(j){let D=this.groups.get(j);if(!D||D.size===0)throw Error(`Asset group '${j}' not found or empty`);await Promise.all(Array.from(D).map(($)=>this.loadAsset($)))}get(j){let D=this.assets.get(j);if(!D)throw Error(`Asset '${String(j)}' not found`);if(D.status!=="loaded"||D.value===void 0)throw Error(`Asset '${String(j)}' is not loaded (status: ${D.status})`);return D.value}tryGet(j){let D=this.assets.get(j);if(!D||D.status!=="loaded")return;return D.value}getHandle(j){let D=this.assets.get(j);if(!D)throw Error(`Asset '${String(j)}' not found`);let $=this;return{get status(){return D.status},get isLoaded(){return D.status==="loaded"},get(){return $.get(j)},tryGet(){return $.tryGet(j)}}}getStatus(j){let D=this.assets.get(j);if(!D)throw Error(`Asset '${String(j)}' not found`);return D.status}isLoaded(j){return this.assets.get(j)?.status==="loaded"}isGroupLoaded(j){let D=this.groups.get(j);if(!D||D.size===0)return!1;for(let $ of D){let G=this.assets.get($);if(!G||G.status!=="loaded")return!1}return!0}getGroupProgress(j){return this.getGroupProgressDetails(j).progress}getGroupProgressDetails(j){let D=this.groups.get(j);if(!D||D.size===0)return{loaded:0,total:0,progress:0};let $=0;for(let J of D)if(this.assets.get(J)?.status==="loaded")$++;let G=D.size;return{loaded:$,total:G,progress:$/G}}checkGroupProgress(j){if(!j||!this.eventBus)return;let D=j,$=this.getGroupProgressDetails(D);if(this.eventBus.publish("assetGroupProgress",{group:D,...$}),$.loaded===$.total)this.eventBus.publish("assetGroupLoaded",{group:D})}createResource(){let j=this;return{getStatus(D){return j.getStatus(D)},isLoaded(D){return j.isLoaded(D)},isGroupLoaded(D){return j.isGroupLoaded(D)},getGroupProgress(D){return j.getGroupProgress(D)},get(D){return j.get(D)},tryGet(D){return j.tryGet(D)},getHandle(D){return j.getHandle(D)}}}getKeys(){return Array.from(this.assets.keys())}getGroupNames(){return Array.from(this.groups.keys())}getGroupKeys(j){let D=this.groups.get(j);return D?Array.from(D):[]}}class y{manager;constructor(j){this.manager=j}add(j,D){return this.manager.register(j,{loader:D,eager:!0}),this}addWithConfig(j,D){return this.manager.register(j,D),this}addGroup(j,D){for(let[$,G]of Object.entries(D))this.manager.register($,{loader:G,eager:!1,group:j});return this}getManager(){return this.manager}}function k(j){return new y(j??new z)}class P{screens=new Map;currentScreen=null;screenStack=[];eventBus=null;assetManager=null;ecs=null;setDependencies(j,D,$){this.eventBus=j,this.assetManager=D,this.ecs=$}requireEcs(){if(!this.ecs)throw Error("ScreenManager: dependencies not set. Call setDependencies() first.");return this.ecs}register(j,D){this.screens.set(j,{definition:D})}async setScreen(j,D){let $=this.screens.get(j);if(!$)throw Error(`Screen '${String(j)}' not found`);await this.verifyRequiredAssets($.definition.requiredAssets,$.definition.requiredAssetGroups);while(this.screenStack.length>0){let J=this.screenStack.pop();if(J)await this.exitScreen(J.name)}if(this.currentScreen)await this.exitScreen(this.currentScreen.name);let G=$.definition.initialState(D);this.currentScreen={name:j,config:D,state:G},await $.definition.onEnter?.({config:D,ecs:this.requireEcs()}),this.eventBus?.publish("screenEnter",{screen:j,config:D})}async pushScreen(j,D){let $=this.screens.get(j);if(!$)throw Error(`Screen '${String(j)}' not found`);if(await this.verifyRequiredAssets($.definition.requiredAssets,$.definition.requiredAssetGroups),this.currentScreen)this.screenStack.push(this.currentScreen);let G=$.definition.initialState(D);this.currentScreen={name:j,config:D,state:G},await $.definition.onEnter?.({config:D,ecs:this.requireEcs()}),this.eventBus?.publish("screenPush",{screen:j,config:D})}async popScreen(){if(this.screenStack.length===0)throw Error("Cannot pop screen: stack is empty");if(this.currentScreen)await this.exitScreen(this.currentScreen.name),this.eventBus?.publish("screenPop",{screen:this.currentScreen.name});this.currentScreen=this.screenStack.pop()??null}async exitScreen(j){let D=this.screens.get(j);if(D?.definition.onExit)await D.definition.onExit(this.requireEcs());this.eventBus?.publish("screenExit",{screen:j})}async verifyRequiredAssets(j,D){if(!this.assetManager)return;if(j){for(let $ of j)if(!this.assetManager.isLoaded($))await this.assetManager.loadAsset($)}if(D){for(let $ of D)if(!this.assetManager.isGroupLoaded($))await this.assetManager.loadAssetGroup($)}}getCurrentScreen(){return this.currentScreen?.name??null}getConfig(j){if(!this.currentScreen)throw Error("No current screen");if(j!==void 0&&this.currentScreen.name!==j)throw Error(`Expected current screen '${String(j)}', but current is '${String(this.currentScreen.name)}'`);return this.currentScreen.config}tryGetConfig(j){if(!this.currentScreen)return;if(j!==void 0&&this.currentScreen.name!==j)return;return this.currentScreen.config}getState(j){if(!this.currentScreen)throw Error("No current screen");if(j!==void 0&&this.currentScreen.name!==j)throw Error(`Expected current screen '${String(j)}', but current is '${String(this.currentScreen.name)}'`);return this.currentScreen.state}tryGetState(j){if(!this.currentScreen)return;if(j!==void 0&&this.currentScreen.name!==j)return;return this.currentScreen.state}updateState(j,D){if(!this.currentScreen)throw Error("No current screen");if(D!==void 0&&this.currentScreen.name!==D)throw Error(`Expected current screen '${String(D)}', but current is '${String(this.currentScreen.name)}'`);let $=typeof j==="function"?j(this.currentScreen.state):j;this.currentScreen.state={...this.currentScreen.state,...$}}getStackDepth(){return this.screenStack.length}isOverlay(){return this.screenStack.length>0}isActive(j){if(this.currentScreen?.name===j)return!0;return this.screenStack.some((D)=>D.name===j)}isCurrent(j){return this.currentScreen?.name===j}createResource(){let j=this;return{get current(){return j.getCurrentScreen()},get config(){return j.tryGetConfig()??null},get state(){return j.tryGetState()??null},set state(D){if(j.currentScreen&&D!==null)j.currentScreen.state=D},get stack(){return j.screenStack},get isOverlay(){return j.isOverlay()},get stackDepth(){return j.getStackDepth()},isActive(D){return j.isActive(D)},isCurrent(D){return j.isCurrent(D)}}}getScreenNames(){return Array.from(this.screens.keys())}hasScreen(j){return this.screens.has(j)}}class o{manager;constructor(j){this.manager=j}add(j,D){return this.manager.register(j,D),this}getManager(){return this.manager}}function I(j){return new o(j??new P)}class h{assetConfigurator=null;screenConfigurator=null;pendingResources=[];pendingDisposeCallbacks=[];pendingRequiredComponents=[];pendingPlugins=[];_fixedDt=null;constructor(){}withPlugin(j){return this.pendingPlugins.push(j),this}withComponentTypes(){return this}withEventTypes(){return this}withResourceTypes(){return this}withResource(j,D){return this.pendingResources.push({key:j,value:D}),this}withDispose(j,D){return this.pendingDisposeCallbacks.push({key:j,callback:D}),this}withRequired(j,D,$){return this.pendingRequiredComponents.push({trigger:j,required:D,factory:$}),this}withAssets(j){let D=k();return j(D),this.assetConfigurator=D,this}withScreens(j){let D=I();return j(D),this.screenConfigurator=D,this}withFixedTimestep(j){return this._fixedDt=j,this}withReactiveQueryNames(){return this}pluginFactory(){return(j)=>E(j.id).install(j.install)}build(){let j=new V;for(let D of this.pendingPlugins)j._installPluginUnchecked(D);for(let{key:D,value:$}of this.pendingResources)j.addResource(D,$);for(let{key:D,callback:$}of this.pendingDisposeCallbacks)j.registerDispose(D,$);for(let{trigger:D,required:$,factory:G}of this.pendingRequiredComponents)j.registerRequired(D,$,G);if(this.assetConfigurator)j._setAssetManager(this.assetConfigurator.getManager());else if(j._hasPendingPluginAssets())j._setAssetManager(new z);if(this.screenConfigurator)j._setScreenManager(this.screenConfigurator.getManager());else if(j._hasPendingPluginScreens())j._setScreenManager(new P);if(this._fixedDt!==null)j._setFixedDt(this._fixedDt);return j}}var r=["preUpdate","fixedUpdate","update","postUpdate","render"];class V{static VERSION=d;_entityManager;_eventBus;_resourceManager;_commandBuffer;_systems=[];_phaseSystems={preUpdate:[],fixedUpdate:[],update:[],postUpdate:[],render:[]};_installedPlugins=new Set;_pluginCleanups=new Map;_currentSystemDefaults;_screenScopedEntities=new Map;_entityScreenScope=new Map;_activeScopeHint=null;_disabledGroups=new Set;_assetManager=null;_screenManager=null;_reactiveQueryManager;_postUpdateHooks=[];_currentTick=0;_systemLastSeqs=new Map;_changeThreshold=0;_fixedDt=0.016666666666666666;_fixedAccumulator=0;_interpolationAlpha=0;_maxFixedSteps=8;_requiredComponents=new Map;_pendingPluginAssets=[];_pendingPluginScreens=[];_diagnosticsEnabled=!1;_systemTimings=new Map;_phaseTimings={preUpdate:0,fixedUpdate:0,update:0,postUpdate:0,render:0};_entityEnterTracking=new Map;_entityEnterFrameSet=new Set;_systemContexts=new WeakMap;_singletonScratch=[];_pendingFinalizers=[];_batchingRegistrations=!1;_initializeFired=!1;_systemsInitialized=new WeakSet;constructor(){this._entityManager=new T,this._eventBus=new x,this._resourceManager=new w,this._reactiveQueryManager=new q(this._entityManager),this._commandBuffer=new C(this),this._subscribeLifecycleHooks()}_subscribeLifecycleHooks(){this._entityManager.onAfterComponentAdded((j,D)=>{this._entityManager.markChanged(j,D);let $=this._requiredComponents.get(D);if($){let G=this._entityManager.getEntity(j);if(G){let J=G.components[D];for(let{component:X,factory:Z}of $){if(this._entityManager._pendingBatchKeys?.has(X))continue;if(!(X in G.components))this._entityManager.addComponent(j,X,Z(J))}}}}),this._entityManager.onAfterEntityMutated((j)=>{let D=this._entityManager.getEntity(j);if(D)this._reactiveQueryManager.recheckEntityAndChildren(D)}),this._entityManager.onAfterComponentRemoved((j,D)=>{let $=this._entityManager.getEntity(j);if($)this._reactiveQueryManager.onComponentRemoved($,D)}),this._entityManager.onBeforeEntityRemoved((j)=>{this._reactiveQueryManager.onEntityRemoved(j);let D=this._entityScreenScope.get(j);if(D!==void 0)this._entityScreenScope.delete(j),this._screenScopedEntities.get(D)?.delete(j)}),this._entityManager.onAfterParentChanged((j)=>{if(this._reactiveQueryManager.hasParentHasQueries){let D=this._entityManager.getEntity(j);if(D)this._reactiveQueryManager.recheckEntity(D)}})}static create(){return new h}addSystem(j){let D=new g(j,this._currentSystemDefaults);return this._pendingFinalizers.push(()=>{this._registerSystem(D._createSystemObject())}),D}_finalizePendingBuilders(){if(this._pendingFinalizers.length===0)return;this._batchingRegistrations=!0;while(this._pendingFinalizers.length>0){let j=this._pendingFinalizers;this._pendingFinalizers=[];for(let D of j)D()}this._batchingRegistrations=!1,this._rebuildPhaseSystems()}update(j){this._finalizePendingBuilders();let D=this._screenManager?.getCurrentScreen()??null,$=this._diagnosticsEnabled;this._runPhase("preUpdate",j,D,$);let G=$?performance.now():0;this._fixedAccumulator+=j;let J=0;while(this._fixedAccumulator>=this._fixedDt&&J<this._maxFixedSteps)this._executePhase(this._phaseSystems.fixedUpdate,this._fixedDt,D),this._commandBuffer.playback(this),this._fixedAccumulator-=this._fixedDt,J++;if(this._fixedAccumulator>=this._fixedDt)this._fixedAccumulator=0;if($)this._phaseTimings.fixedUpdate=performance.now()-G;this._interpolationAlpha=this._fixedAccumulator/this._fixedDt,this._runPhase("update",j,D,$),this._runPhase("postUpdate",j,D,$);for(let X of this._postUpdateHooks)X({ecs:this,dt:j});this._runPhase("render",j,D,$),this._resourceManager.flushObserved(),this._changeThreshold=this._entityManager.changeSeq,this._currentTick++}_executePhase(j,D,$){for(let G of j){if(!G.process&&!G.onEntityEnter)continue;if(G.groups?.length){let _=!1;for(let Y of G.groups)if(this._disabledGroups.has(Y)){_=!0;break}if(_)continue}if(G.inScreens?.length){if($===null||!G.inScreens.includes($))continue}if(G.excludeScreens?.length){if($!==null&&G.excludeScreens.includes($))continue}if(G.requiredAssets?.length&&this._assetManager){let _=!0;for(let Y of G.requiredAssets)if(!this._assetManager.isLoaded(Y)){_=!1;break}if(!_)continue}let J=this._systemLastSeqs.get(G)??0;this._changeThreshold=J;let X=this._systemContexts.get(G);if(!X)X={queries:{},dt:0,ecs:this},this._systemContexts.set(G,X);X.dt=D;let Z=X.queries,W=!1,A=!1;if(G.entityQueries)for(let _ in G.entityQueries){A=!0;let Y=G.entityQueries[_];if(Y){let Q=Z[_]??(Z[_]=[]);if(this._entityManager.getEntitiesWithQueryInto(Q,Y.with,Y.without||[],Y.changed,Y.changed?this._changeThreshold:void 0,Y.parentHas),Q.length)W=!0}}if(G.entitySingletons){let _=this._singletonScratch;for(let Y in G.entitySingletons){A=!0;let F=G.entitySingletons[Y];if(F){if(this._entityManager.getEntitiesWithQueryInto(_,F.with,F.without||[],F.changed,F.changed?this._changeThreshold:void 0,F.parentHas),Z[Y]=_[0],_.length)W=!0}}}let L=this._entityEnterTracking.get(G);if(L&&G.onEntityEnter)for(let _ in G.onEntityEnter){let Y=Z[_],F=L.get(_);if(!Y||!F)continue;let Q=G.onEntityEnter[_];if(!Q)continue;let K=this._entityEnterFrameSet;K.clear();for(let B of Y)if(K.add(B.id),!F.has(B.id))F.add(B.id),Q({entity:B,ecs:this});for(let B of F)if(!K.has(B))F.delete(B)}if(G.process){if(W||G.runWhenEmpty||!A){let Y=this._activeScopeHint;this._activeScopeHint=G.inScreens?.length&&$!==null?$:null;let F=this._diagnosticsEnabled?performance.now():0;try{G.process(X)}finally{if(this._activeScopeHint=Y,this._diagnosticsEnabled)this._systemTimings.set(G.label,performance.now()-F)}}}let O=G._autoMarkPairs;if(O){let _=this._entityManager;for(let Y=0;Y<O.length;Y++){let F=O[Y];if(!F)continue;let Q=F.mutates,K=Q.length;if(F.kind==="list"){let B=Z[F.queryName];if(!B)continue;for(let U=0;U<B.length;U++){let M=B[U];if(!M)continue;for(let f=0;f<K;f++){let u=Q[f];if(u!==void 0)_.markChanged(M.id,u)}}}else{let B=Z[F.queryName];if(!B)continue;for(let U=0;U<K;U++){let M=Q[U];if(M!==void 0)_.markChanged(B.id,M)}}}}this._systemLastSeqs.set(G,this._entityManager.changeSeq)}}_runPhase(j,D,$,G){if(G){let J=performance.now();this._executePhase(this._phaseSystems[j],D,$),this._phaseTimings[j]=performance.now()-J}else this._executePhase(this._phaseSystems[j],D,$);this._commandBuffer.playback(this)}async initialize(){if(this._finalizePendingBuilders(),await this.initializeResources(),this._assetManager)this._assetManager.setEventBus(this._eventBus),await this._assetManager.loadEagerAssets(),this._resourceManager.add("$assets",this._assetManager.createResource());if(this._screenManager){let j=this._eventBus;this._screenManager.setDependencies(j,this._assetManager,this),this._resourceManager.add("$screen",this._screenManager.createResource()),j.subscribe("screenExit",({screen:D})=>{let $=this._screenScopedEntities.get(D);if(!$||$.size===0)return;this._screenScopedEntities.delete(D);for(let G of Array.from($))this._entityScreenScope.delete(G),this.removeEntity(G)})}for(let j of this._systems){if(this._systemsInitialized.has(j))continue;this._systemsInitialized.add(j),await j.onInitialize?.(this)}this._initializeFired=!0}async initializeResources(...j){await this._resourceManager.initializeResources(this,...j)}_rebuildPhaseSystems(){for(let j of r)this._phaseSystems[j]=[];for(let j of this._systems){let D=j.phase??"update";this._phaseSystems[D].push(j)}for(let j of r)this._phaseSystems[j].sort((D,$)=>{let G=D.priority??0;return($.priority??0)-G})}updateSystemPriority(j,D){this._finalizePendingBuilders();let $=this._systems.find((G)=>G.label===j);if(!$)return!1;return $.priority=D,this._rebuildPhaseSystems(),!0}updateSystemPhase(j,D){this._finalizePendingBuilders();let $=this._systems.find((G)=>G.label===j);if(!$)return!1;return $.phase=D,this._rebuildPhaseSystems(),!0}get interpolationAlpha(){return this._interpolationAlpha}get fixedDt(){return this._fixedDt}disableSystemGroup(j){this._disabledGroups.add(j)}enableSystemGroup(j){this._disabledGroups.delete(j)}isSystemGroupEnabled(j){return!this._disabledGroups.has(j)}getSystemsInGroup(j){return this._finalizePendingBuilders(),this._systems.filter((D)=>D.groups?.includes(j)).map((D)=>D.label)}removeSystem(j){this._finalizePendingBuilders();let D=this._systems.findIndex((G)=>G.label===j);if(D===-1)return!1;let $=this._systems[D];if(!$)return!1;if($.onDetach)$.onDetach(this);return this._systems.splice(D,1),this._systemLastSeqs.delete($),this._entityEnterTracking.delete($),this._systemsInitialized.delete($),this._rebuildPhaseSystems(),!0}_registerSystem(j){if(this._systems.push(j),this._systemLastSeqs.set(j,this._changeThreshold),!this._batchingRegistrations)this._rebuildPhaseSystems();let D=[];if(j.entityQueries)for(let $ in j.entityQueries){if($===i)continue;let J=j.entityQueries[$]?.mutates;if(J&&J.length>0)D.push({queryName:$,mutates:J,kind:"list"})}if(j.entitySingletons)for(let $ in j.entitySingletons){let J=j.entitySingletons[$]?.mutates;if(J&&J.length>0)D.push({queryName:$,mutates:J,kind:"singleton"})}if(j._autoMarkPairs=D.length>0?D:null,j.onEntityEnter){let $=new Map;for(let G in j.onEntityEnter)$.set(G,new Set);this._entityEnterTracking.set(j,$)}if(j.eventHandlers)for(let $ in j.eventHandlers){let G=j.eventHandlers[$];if(G)this._eventBus.subscribe($,(J)=>{G({data:J,ecs:this})})}if(this._initializeFired&&!this._systemsInitialized.has(j)){this._systemsInitialized.add(j);let $=j.onInitialize?.(this);if($ instanceof Promise)$.catch((G)=>{console.error(`onInitialize for system "${j.label}" rejected:`,G)})}}hasResource(j){return this._resourceManager.has(j)}getResource(j){if(!this._resourceManager.has(j))throw Error(`Resource '${String(j)}' not found. Available resources: [${this.getResourceKeys().map((D)=>String(D)).join(", ")}]`);return this._resourceManager.get(j,this)}tryGetResource(j){let D=j;if(!this._resourceManager.has(D))return;return this._resourceManager.get(D,this)}addResource(j,D){return this._resourceManager.add(j,D),this}removeResource(j){return this._resourceManager.remove(j)}async disposeResource(j){return this._resourceManager.disposeResource(j,this)}async disposeResources(){return this._resourceManager.disposeResources(this)}updateResource(j,D){let $=this.getResource(j),G=D($);return this._resourceManager.add(j,G),this._resourceManager.notifyChange(j,G,$),this}setResource(j,D){let $=this.tryGetResource(j);if(this._resourceManager.add(j,D),$!==void 0)this._resourceManager.notifyChange(j,D,$);return this}onResourceChange(j,D){return this._resourceManager.onResourceChange(j,D)}isResourceObserved(j){return this._resourceManager.isObserved(j)}getResourceKeys(){return this._resourceManager.getKeys()}resourceNeedsInitialization(j){return this._resourceManager.needsInitialization(j)}getEntity(j){return this._entityManager.getEntity(j)}getComponent(j,D){return this._entityManager.getComponent(j,D)}addComponent(j,D,$){this._entityManager.addComponent(j,D,$)}addComponents(j,D){this._entityManager.addComponents(j,D)}removeComponent(j,D){this._entityManager.removeComponent(j,D)}hasComponent(j,D){return this._entityManager.getComponent(j,D)!==void 0}spawn(j,D){let $=this._entityManager.createEntity();return this._entityManager.addComponents($.id,j),this._applyScreenScope($.id,D),$}_getActiveScopeHint(){return this._activeScopeHint}_applyScreenScope(j,D){let $=D?.scope!==void 0?D.scope:this._activeScopeHint;if($===null)return;let G=this._screenScopedEntities.get($)??new Set;G.add(j),this._screenScopedEntities.set($,G),this._entityScreenScope.set(j,$)}getEntitiesWithQuery(j,D=[],$,G){return this._entityManager.getEntitiesWithQuery(j,D,$,$?this._changeThreshold:void 0,G)}getSingleton(j,D=[]){let $=this._entityManager.getEntitiesWithQuery(j,D);if($.length===0)throw Error(`getSingleton: no entity matches query with=[${String(j)}] without=[${String(D)}]`);if($.length>1)throw Error(`getSingleton: expected 1 entity but found ${$.length} matching query with=[${String(j)}] without=[${String(D)}]`);let G=$[0];if(!G)throw Error("getSingleton: unexpected empty result");return G}tryGetSingleton(j,D=[]){let $=this._entityManager.getEntitiesWithQuery(j,D);if($.length===0)return;if($.length>1)throw Error(`tryGetSingleton: expected 0 or 1 entity but found ${$.length} matching query with=[${String(j)}] without=[${String(D)}]`);return $[0]}removeEntity(j,D){return this._entityManager.removeEntity(j,D)}spawnChild(j,D,$){let G=this._entityManager.spawnChild(j,D);return this._emitHierarchyChanged(G.id,null,j),this._applyScreenScope(G.id,$),G}setParent(j,D){let $=this._entityManager.getParent(j);return this._entityManager.setParent(j,D),this._emitHierarchyChanged(j,$,D),this}removeParent(j){let D=this._entityManager.getParent(j),$=this._entityManager.removeParent(j);if($)this._emitHierarchyChanged(j,D,null);return $}getParent(j){return this._entityManager.getParent(j)}getChildren(j){return this._entityManager.getChildren(j)}getChildAt(j,D){return this._entityManager.getChildAt(j,D)}getChildIndex(j,D){return this._entityManager.getChildIndex(j,D)}getAncestors(j){return this._entityManager.getAncestors(j)}getDescendants(j){return this._entityManager.getDescendants(j)}getRoot(j){return this._entityManager.getRoot(j)}getSiblings(j){return this._entityManager.getSiblings(j)}isDescendantOf(j,D){return this._entityManager.isDescendantOf(j,D)}isAncestorOf(j,D){return this._entityManager.isAncestorOf(j,D)}getRootEntities(){return this._entityManager.getRootEntities()}forEachInHierarchy(j,D){this._entityManager.forEachInHierarchy(j,D)}hierarchyIterator(j){return this._entityManager.hierarchyIterator(j)}_emitHierarchyChanged(j,D,$){this._eventBus.publish("hierarchyChanged",{entityId:j,oldParent:D,newParent:$})}get installedPlugins(){return Array.from(this._installedPlugins)}get entityManager(){return this._entityManager}get eventBus(){return this._finalizePendingBuilders(),this._eventBus}get commands(){return this._commandBuffer}get currentTick(){return this._currentTick}get changeThreshold(){return this._changeThreshold}enableDiagnostics(j){if(this._diagnosticsEnabled=j,!j)this._systemTimings.clear(),this._phaseTimings={preUpdate:0,fixedUpdate:0,update:0,postUpdate:0,render:0}}get diagnosticsEnabled(){return this._diagnosticsEnabled}get systemTimings(){return this._systemTimings}get phaseTimings(){return this._phaseTimings}get entityCount(){return this._entityManager.entityCount}mutateComponent(j,D,$){let G=this._entityManager.getComponent(j,D);if(G===void 0)throw Error(`Entity ${j} does not have component "${String(D)}"`);return $(G),this._entityManager.markChanged(j,D),G}markChanged(j,D){this._entityManager.markChanged(j,D)}registerDispose(j,D){this._entityManager.registerDispose(j,D)}registerRequired(j,D,$){if(String(j)===String(D))throw Error(`Cannot require a component to depend on itself: '${String(j)}'`);let G=this._requiredComponents.get(j)??[];if(G.some((J)=>J.component===D))throw Error(`Required component '${String(D)}' already registered for trigger '${String(j)}'`);this._checkRequiredCycle(j,D),G.push({component:D,factory:$}),this._requiredComponents.set(j,G)}_checkRequiredCycle(j,D){c(j,D,($)=>this._requiredComponents.get($))}onComponentAdded(j,D){return this._entityManager.onComponentAdded(j,D)}onComponentRemoved(j,D){return this._entityManager.onComponentRemoved(j,D)}addReactiveQuery(j,D){this._reactiveQueryManager.addQuery(j,D)}removeReactiveQuery(j){return this._reactiveQueryManager.removeQuery(j)}on(j,D){return this._eventBus.subscribe(j,D)}off(j,D){return this._eventBus.unsubscribe(j,D)}onPostUpdate(j){return this._postUpdateHooks.push(j),()=>{let D=this._postUpdateHooks.indexOf(j);if(D!==-1)this._postUpdateHooks.splice(D,1)}}requireAssetManager(){if(!this._assetManager)throw Error("Asset manager not configured. Use withAssets() in builder.");return this._assetManager}getAsset(j){return this.requireAssetManager().get(j)}tryGetAsset(j){return this._assetManager?.tryGet(j)}getAssetHandle(j){return this.requireAssetManager().getHandle(j)}isAssetLoaded(j){return this._assetManager?.isLoaded(j)??!1}async loadAsset(j){return this.requireAssetManager().loadAsset(j)}async loadAssetGroup(j){return this.requireAssetManager().loadAssetGroup(j)}isAssetGroupLoaded(j){return this._assetManager?.isGroupLoaded(j)??!1}getAssetGroupProgress(j){return this._assetManager?.getGroupProgress(j)??0}requireScreenManager(){if(!this._screenManager)throw Error("Screen manager not configured. Use withScreens() in builder.");return this._screenManager}async setScreen(j,D){return this.requireScreenManager().setScreen(j,D)}async pushScreen(j,D){return this.requireScreenManager().pushScreen(j,D)}async popScreen(){return this.requireScreenManager().popScreen()}getCurrentScreen(){return this._screenManager?.getCurrentScreen()??null}getScreenConfig(j){return this.requireScreenManager().getConfig(j)}tryGetScreenConfig(j){return this._screenManager?.tryGetConfig(j)??void 0}getScreenState(j){return this.requireScreenManager().getState(j)}tryGetScreenState(j){return this._screenManager?.tryGetState(j)??void 0}updateScreenState(j,D){if(typeof j==="string")this.requireScreenManager().updateState(D,j);else this.requireScreenManager().updateState(j)}isCurrentScreen(j){return this._screenManager?.isCurrent(j)??!1}isScreenActive(j){return this._screenManager?.isActive(j)??!1}getScreenStackDepth(){return this._screenManager?.getStackDepth()??0}onScreenEnter(j,D){let $=this._eventBus,G=(Z)=>{if(Z.screen!==j)return;D({config:Z.config,ecs:this})},J=$.subscribe("screenEnter",G),X=$.subscribe("screenPush",G);return()=>{J(),X()}}onScreenExit(j,D){return this._eventBus.subscribe("screenExit",(G)=>{if(G.screen!==j)return;D({ecs:this})})}_setAssetManager(j){this._assetManager=j;for(let[D,$]of this._pendingPluginAssets)this._assetManager.register(D,$);this._pendingPluginAssets=[]}_setScreenManager(j){this._screenManager=j;for(let[D,$]of this._pendingPluginScreens)this._screenManager.register(D,$);this._pendingPluginScreens=[]}_hasPendingPluginAssets(){return this._pendingPluginAssets.length>0}_hasPendingPluginScreens(){return this._pendingPluginScreens.length>0}_setFixedDt(j){this._fixedDt=j}_registerAsset(j,D){this._pendingPluginAssets.push([j,D])}_registerScreen(j,D){this._pendingPluginScreens.push([j,D])}installPlugin(j){return this._installPluginUnchecked(j)}_installPluginUnchecked(j){if(this._installedPlugins.has(j.id))return this;this._installedPlugins.add(j.id);let D=[];this._pluginCleanups.set(j.id,D);let $=(J)=>{D.push(J)},G=this._currentSystemDefaults;this._currentSystemDefaults=j.systemDefaults;try{j.install(this,$)}finally{this._currentSystemDefaults=G}return this}uninstallPlugin(j){if(!this._installedPlugins.has(j))return!1;let D=this._pluginCleanups.get(j);if(this._pluginCleanups.delete(j),this._installedPlugins.delete(j),D)for(let $=D.length-1;$>=0;$--){let G=D[$];if(!G)continue;try{G()}catch(J){console.warn(`Plugin '${j}' cleanup threw:`,J)}}return!0}dispose(){let j=Array.from(this._installedPlugins);for(let D=j.length-1;D>=0;D--){let $=j[D];if($!==void 0)this.uninstallPlugin($)}}pluginFactory(){return(j)=>E(j.id).install(j.install)}getHelpers(j){return j(this)}}function uj(j){return j}function lj(j,D){return{x:j,y:D}}function sj(){return{x:0,y:0}}function ij(j,D){return{x:j.x+D.x,y:j.y+D.y}}function cj(j,D){return{x:j.x-D.x,y:j.y-D.y}}function dj(j,D){return{x:j.x*D,y:j.y*D}}function yj(j){return{x:-j.x,y:-j.y}}function oj(j,D){return j.x*D.x+j.y*D.y}function rj(j,D){return j.x*D.y-j.y*D.x}function aj(j){return j.x*j.x+j.y*j.y}function nj(j){return Math.sqrt(j.x*j.x+j.y*j.y)}function tj(j){let D=Math.sqrt(j.x*j.x+j.y*j.y);if(D===0)return{x:0,y:0};return{x:j.x/D,y:j.y/D}}function ej(j,D){let $=j.x-D.x,G=j.y-D.y;return $*$+G*G}function j3(j,D){let $=j.x-D.x,G=j.y-D.y;return Math.sqrt($*$+G*G)}function D3(j,D,$=0.0000000001){return Math.abs(j.x-D.x)<=$&&Math.abs(j.y-D.y)<=$}function $3(j,D,$){return{x:j,y:D,z:$}}function G3(){return{x:0,y:0,z:0}}function J3(j,D){return{x:j.x+D.x,y:j.y+D.y,z:j.z+D.z}}function X3(j,D){return{x:j.x-D.x,y:j.y-D.y,z:j.z-D.z}}function Z3(j,D){return{x:j.x*D,y:j.y*D,z:j.z*D}}function W3(j){return{x:-j.x,y:-j.y,z:-j.z}}function Y3(j,D){return j.x*D.x+j.y*D.y+j.z*D.z}function F3(j,D){return{x:j.y*D.z-j.z*D.y,y:j.z*D.x-j.x*D.z,z:j.x*D.y-j.y*D.x}}function L3(j){return j.x*j.x+j.y*j.y+j.z*j.z}function _3(j){return Math.sqrt(j.x*j.x+j.y*j.y+j.z*j.z)}function A3(j){let D=Math.sqrt(j.x*j.x+j.y*j.y+j.z*j.z);if(D===0)return{x:0,y:0,z:0};return{x:j.x/D,y:j.y/D,z:j.z/D}}function B3(j,D){let $=j.x-D.x,G=j.y-D.y,J=j.z-D.z;return $*$+G*G+J*J}function O3(j,D){let $=j.x-D.x,G=j.y-D.y,J=j.z-D.z;return Math.sqrt($*$+G*G+J*J)}function Q3(j,D,$=0.0000000001){return Math.abs(j.x-D.x)<=$&&Math.abs(j.y-D.y)<=$&&Math.abs(j.z-D.z)<=$}var w3=V;export{G3 as vec3Zero,X3 as vec3Sub,Z3 as vec3Scale,A3 as vec3Normalize,W3 as vec3Negate,L3 as vec3LengthSq,_3 as vec3Length,Q3 as vec3Equals,Y3 as vec3Dot,B3 as vec3DistanceSq,O3 as vec3Distance,F3 as vec3Cross,J3 as vec3Add,$3 as vec3,sj as vec2Zero,cj as vec2Sub,dj as vec2Scale,tj as vec2Normalize,yj as vec2Negate,aj as vec2LengthSq,nj as vec2Length,D3 as vec2Equals,oj as vec2Dot,ej as vec2DistanceSq,j3 as vec2Distance,rj as vec2Cross,ij as vec2Add,lj as vec2,n as directValue,E as definePlugin,w3 as default,I as createScreenConfigurator,uj as createQueryDefinition,k as createAssetConfigurator,g as SystemBuilder,P as ScreenManager,z as AssetManager};
1
+ var $j=((j)=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(j,{get:(D,$)=>(typeof require<"u"?require:D)[$]}):j)(function(j){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+j+'" is not supported')});class H{parentMap=new Map;childrenMap=new Map;_bfsQueue=[];setParent(j,D){if(j===D)throw Error(`Cannot set entity ${j} as its own parent`);if(this.wouldCreateCycle(j,D))throw Error("Cannot set parent: would create circular reference");let $=this.parentMap.get(j);if($!==void 0){let J=this.childrenMap.get($);if(J){let X=J.indexOf(j);if(X!==-1)J.splice(X,1)}}this.parentMap.set(j,D);let G=this.childrenMap.get(D);if(G)G.push(j);else this.childrenMap.set(D,[j]);return this}removeParent(j){let D=this.parentMap.get(j);if(D===void 0)return!1;let $=this.childrenMap.get(D);if($){let G=$.indexOf(j);if(G!==-1)$.splice(G,1)}return this.parentMap.delete(j),!0}getParent(j){return this.parentMap.get(j)??null}getChildren(j){let D=this.childrenMap.get(j);return D?[...D]:[]}getChildAt(j,D){if(D<0)return null;let $=this.childrenMap.get(j);if(!$||D>=$.length)return null;return $[D]??null}getChildIndex(j,D){let $=this.childrenMap.get(j);if(!$)return-1;return $.indexOf(D)}removeEntity(j){let D=this.parentMap.get(j)??null;if(D!==null){let J=this.childrenMap.get(D);if(J){let X=J.indexOf(j);if(X!==-1)J.splice(X,1)}}this.parentMap.delete(j);let $=this.childrenMap.get(j)??[],G=[...$];for(let J of $)this.parentMap.delete(J);return this.childrenMap.delete(j),{oldParent:D,orphanedChildren:G}}getAncestors(j){let D=[],$=this.parentMap.get(j);while($!==void 0)D.push($),$=this.parentMap.get($);return D}getDescendants(j){let D=[],$=this.childrenMap.get(j);if(!$)return D;let G=$.slice().reverse();while(G.length>0){let J=G.pop();D.push(J);let X=this.childrenMap.get(J);if(X)for(let Z=X.length-1;Z>=0;Z--)G.push(X[Z])}return D}getRoot(j){let D=j,$=this.parentMap.get(D);while($!==void 0)D=$,$=this.parentMap.get(D);return D}getSiblings(j){let D=this.parentMap.get(j);if(D===void 0)return[];let $=this.childrenMap.get(D);if(!$)return[];return $.filter((G)=>G!==j)}isDescendantOf(j,D){if(j===D)return!1;let $=this.parentMap.get(j);while($!==void 0){if($===D)return!0;$=this.parentMap.get($)}return!1}isAncestorOf(j,D){return this.isDescendantOf(D,j)}get hasHierarchy(){return this.childrenMap.size>0}getRootEntities(){let j=[];for(let D of this.childrenMap.keys())if(!this.parentMap.has(D))j.push(D);return j}wouldCreateCycle(j,D){let $=D;while($!==void 0){if($===j)return!0;$=this.parentMap.get($)}return!1}forEachInHierarchy(j,D){let $=D?.roots??this.getRootEntities(),G=this._bfsQueue;G.length=0;for(let J of $)G.push(J,-1,0);for(let J=0;J<G.length;J+=3){let X=G[J],Z=G[J+1],Y=G[J+2];j(X,Z===-1?null:Z,Y);let F=this.childrenMap.get(X);if(F){let B=Y+1;for(let A of F)G.push(A,X,B)}}}*hierarchyIterator(j){let D=j?.roots??this.getRootEntities(),$=[];for(let G of D)$.push({entityId:G,parentId:null,depth:0});for(let G of $){yield G;let J=this.childrenMap.get(G.entityId);if(J)for(let X of J)$.push({entityId:X,parentId:G.entityId,depth:G.depth+1})}}}function R(j,D,$,G,J){let X=j.components;for(let Z of D)if(!(Z in X))return!1;if($){for(let Z of $)if(Z in X)return!1}if(G&&G.length>0){let Z=J.getParent(j.id);if(Z===null)return!1;let Y=J.getEntity(Z);if(!Y)return!1;let F=Y.components;for(let B of G)if(!(B in F))return!1}return!0}function a(j,D,$){let G=j.length===0?"":[...j].map(String).sort().join(","),J=D.length===0?"":[...D].map(String).sort().join(","),X=$.length===0?"":[...$].map(String).sort().join(",");return`${G}|${J}|${X}`}class S{host;caches=new Map;byComp=new Map;byParentComp=new Map;constructor(j){this.host=j}getOrCreate(j,D,$){let G=a(j,D,$),J=this.caches.get(G);if(J)return J.members;let X={with:[...j],without:[...D],parentHas:[...$],members:new Map};this.caches.set(G,X);for(let Z of X.with)v(this.byComp,Z,X);for(let Z of X.without)v(this.byComp,Z,X);for(let Z of X.parentHas)v(this.byParentComp,Z,X);return this.populate(X),X.members}get cacheCount(){return this.caches.size}populate(j){let D=this.host,$=j.with;if($.length===0){for(let Z of D.allEntities())if(this.matches(Z,j))j.members.set(Z.id,Z);return}let G=$[0];if(G===void 0)return;let J=D.componentIndex(G)?.size??0;for(let Z=1;Z<$.length;Z++){let Y=$[Z];if(Y===void 0)continue;let F=D.componentIndex(Y)?.size??0;if(F<J)G=Y,J=F}let X=D.componentIndex(G);if(!X||X.size===0)return;for(let Z of X){let Y=D.getEntity(Z);if(!Y)continue;if(this.matches(Y,j))j.members.set(Z,Y)}}matches(j,D){return R(j,D.with,D.without,D.parentHas,this.host)}reeval(j,D){let $=this.host.getEntity(j);if(!$){D.members.delete(j);return}if(this.matches($,D))D.members.set(j,$);else D.members.delete(j)}onComponentChanged(j,D){let $=this.byComp.get(D);if($)for(let J of $)this.reeval(j,J);let G=this.byParentComp.get(D);if(G&&G.length>0){let J=this.host.getChildren(j);if(J.length>0)for(let X of G)for(let Z of J)this.reeval(Z,X)}}onParentChanged(j){for(let D of this.caches.values())if(D.parentHas.length>0)this.reeval(j,D)}onEntityRemoved(j){let D=!1;for(let G of this.caches.values())if(G.members.delete(j),G.parentHas.length>0)D=!0;if(!D)return;let $=this.host.getChildren(j);if($.length===0)return;for(let G of this.caches.values()){if(G.parentHas.length===0)continue;for(let J of $)G.members.delete(J)}}}function v(j,D,$){let G=j.get(D);if(G)G.push($);else j.set(D,[$])}function l(j,D,$){if(!j||!D)return!1;for(let G=0;G<D.length;G++){let J=D[G];if(J===void 0||J>=j.length)continue;let X=j[J];if(X!==void 0&&X>$)return!0}return!1}class N{callbacks=[];_iterDepth=0;_pendingRemovals=[];add(j){this.callbacks.push(j)}remove(j){if(this._iterDepth>0){this._pendingRemovals.push(j);return}let D=this.callbacks.indexOf(j);if(D!==-1)this.callbacks.splice(D,1)}invoke(j){this._iterDepth++;let D=this.callbacks.length;for(let $=0;$<D;$++){let G=this.callbacks[$];if(G)G(j)}if(this._iterDepth--,this._iterDepth===0&&this._pendingRemovals.length>0){for(let $ of this._pendingRemovals){let G=this.callbacks.indexOf($);if(G!==-1)this.callbacks.splice(G,1)}this._pendingRemovals.length=0}}}class T{nextId=1;entities=new Map;componentIndices=new Map;addedCallbacks=new Map;removedCallbacks=new Map;hierarchyManager=new H;disposeCallbacks=new Map;changeSeqs=[];componentNameToIdx=new Map;_idxCache0Name;_idxCache0Idx=-1;_idxCache1Name;_idxCache1Idx=-1;_subscribedComponentIdx=null;_changeSeq=0;_afterComponentAddedHooks=[];_afterEntityMutatedHooks=[];_afterComponentRemovedHooks=[];_beforeEntityRemovedHooks=[];_afterParentChangedHooks=[];_queryCache=new S({getEntity:(j)=>this.entities.get(j),getParent:(j)=>this.hierarchyManager.getParent(j),getChildren:(j)=>this.hierarchyManager.getChildren(j),allEntities:()=>this.entities.values(),componentIndex:(j)=>this.componentIndices.get(j)});_batchingDepth=0;_batchedEntityIds=new Set;_pendingBatchKeys=null;get entityCount(){return this.entities.size}createEntity(){let j=this.nextId++,D={id:j,components:{}};return this.entities.set(j,D),D}registerDispose(j,D){this.disposeCallbacks.set(j,D)}getDisposeCallbacks(){return this.disposeCallbacks}invokeDispose(j,D,$){let G=this.disposeCallbacks.get(j);if(!G)return;try{G({value:D,entityId:$})}catch(J){console.warn(`Component dispose callback for '${String(j)}' threw:`,J)}}addComponent(j,D,$){let G=this.entities.get(j);if(!G)throw Error(`Cannot add component '${String(D)}': Entity with ID ${j} does not exist`);let J=G.components[D];if(J!==void 0)this.invokeDispose(D,J,G.id);if(G.components[D]=$,!this.componentIndices.has(D))this.componentIndices.set(D,new Set);this.componentIndices.get(D)?.add(G.id);let X=this.addedCallbacks.get(D);if(X)X.invoke({value:$,entity:G});this._queryCache.onComponentChanged(G.id,D),this._batchingDepth++;for(let Z of this._afterComponentAddedHooks)Z(G.id,D);if(this._batchedEntityIds.add(G.id),this._batchingDepth--,this._batchingDepth===0){for(let Z of this._batchedEntityIds)for(let Y of this._afterEntityMutatedHooks)Y(Z);this._batchedEntityIds.clear()}return this}addComponents(j,D){let $=this.entities.get(j);if(!$)throw Error(`Cannot add components: Entity with ID ${j} does not exist`);let G=this._pendingBatchKeys;this._pendingBatchKeys=new Set(Object.keys(D)),this._batchingDepth++;for(let J in D)this.addComponent($.id,J,D[J]);if(this._batchingDepth--,this._pendingBatchKeys=G,this._batchingDepth===0){for(let J of this._batchedEntityIds)for(let X of this._afterEntityMutatedHooks)X(J);this._batchedEntityIds.clear()}return this}removeComponent(j,D){let $=this.entities.get(j);if(!$)throw Error(`Cannot remove component '${String(D)}': Entity with ID ${j} does not exist`);let G=$.components[D];if(G!==void 0)this.invokeDispose(D,G,$.id);delete $.components[D];let J=this.removedCallbacks.get(D);if(J&&G!==void 0)J.invoke({value:G,entity:$});if(this.componentIndices.get(D)?.delete($.id),G!==void 0){this._queryCache.onComponentChanged($.id,D);for(let X of this._afterComponentRemovedHooks)X($.id,D)}return this}getComponent(j,D){return this.entities.get(j)?.components[D]}getEntitiesWithQuery(j=[],D=[],$,G,J,X){return this.getEntitiesWithQueryInto([],j,D,$,G,J,X)}getEntitiesWithQueryInto(j,D=[],$=[],G,J,X,Z){j.length=0;let Y=G!==void 0&&G.length>0&&J!==void 0,F=Z;if(Y&&F===void 0){let W=[];for(let _ of G){let L=this.componentNameToIdx.get(_);if(L!==void 0)W.push(L)}F=W}if(Y&&F.length===0)return j;let B=X!==void 0&&X.length>0;if(D.length===0&&$.length===0&&!B){if(!Y){for(let W of this.entities.values())j.push(W);return j}for(let W of this.entities.values()){if(!l(this.changeSeqs[W.id],F,J??0))continue;j.push(W)}return j}let A=this._queryCache.getOrCreate(D,$,X??[]);if(A.size===0)return j;if(Y){for(let W of A.values()){if(!l(this.changeSeqs[W.id],F,J??0))continue;j.push(W)}return j}for(let W of A.values())j.push(W);return j}get _queryCacheForTesting(){return this._queryCache}removeEntity(j,D){let $=this.entities.get(j);if(!$)return!1;if(D?.cascade??!0){let J=this.hierarchyManager.getDescendants($.id);for(let X=J.length-1;X>=0;X--){let Z=J[X];if(Z===void 0)continue;this._queryCache.onEntityRemoved(Z);for(let Y of this._beforeEntityRemovedHooks)Y(Z)}this._queryCache.onEntityRemoved($.id);for(let X of this._beforeEntityRemovedHooks)X($.id);for(let X=J.length-1;X>=0;X--){let Z=J[X];if(Z===void 0)continue;this.removeEntityInternal(Z)}}else{this._queryCache.onEntityRemoved($.id);for(let J of this._beforeEntityRemovedHooks)J($.id)}return this.removeEntityInternal($.id)}removeEntityInternal(j){let D=this.entities.get(j);if(!D)return!1;this.hierarchyManager.removeEntity(j);for(let $ of Object.keys(D.components)){let G=D.components[$];if(G!==void 0){this.invokeDispose($,G,D.id);let J=this.removedCallbacks.get($);if(J)J.invoke({value:G,entity:D})}this.componentIndices.get($)?.delete(D.id)}return this.changeSeqs[D.id]=void 0,this.entities.delete(D.id)}getEntity(j){return this.entities.get(j)}onComponentAdded(j,D){let $=D,G=this.addedCallbacks.get(j);if(!G)G=new N,this.addedCallbacks.set(j,G);return G.add($),()=>{this.addedCallbacks.get(j)?.remove($)}}onComponentRemoved(j,D){let $=D,G=this.removedCallbacks.get(j);if(!G)G=new N,this.removedCallbacks.set(j,G);return G.add($),()=>{this.removedCallbacks.get(j)?.remove($)}}onAfterComponentAdded(j){return this._afterComponentAddedHooks.push(j),()=>{let D=this._afterComponentAddedHooks.indexOf(j);if(D!==-1)this._afterComponentAddedHooks.splice(D,1)}}onAfterEntityMutated(j){return this._afterEntityMutatedHooks.push(j),()=>{let D=this._afterEntityMutatedHooks.indexOf(j);if(D!==-1)this._afterEntityMutatedHooks.splice(D,1)}}onAfterComponentRemoved(j){return this._afterComponentRemovedHooks.push(j),()=>{let D=this._afterComponentRemovedHooks.indexOf(j);if(D!==-1)this._afterComponentRemovedHooks.splice(D,1)}}onBeforeEntityRemoved(j){return this._beforeEntityRemovedHooks.push(j),()=>{let D=this._beforeEntityRemovedHooks.indexOf(j);if(D!==-1)this._beforeEntityRemovedHooks.splice(D,1)}}onAfterParentChanged(j){return this._afterParentChangedHooks.push(j),()=>{let D=this._afterParentChangedHooks.indexOf(j);if(D!==-1)this._afterParentChangedHooks.splice(D,1)}}get changeSeq(){return this._changeSeq}markChanged(j,D){this.markChangedByIdx(j,this.getOrAssignComponentIdx(D))}markChangedByIdx(j,D){let $=this._subscribedComponentIdx;if($!==null&&(D>=$.length||$[D]===0))return;let G=++this._changeSeq,J=this.changeSeqs[j];if(J===void 0)J=new Uint32Array(Math.max(D+1,8)),this.changeSeqs[j]=J;else if(D>=J.length){let X=new Uint32Array(Math.max(D+1,J.length*2));X.set(J),J=X,this.changeSeqs[j]=J}J[D]=G}getOrAssignComponentIdx(j){if(j===this._idxCache0Name)return this._idxCache0Idx;if(j===this._idxCache1Name){let $=this._idxCache1Idx;return this._idxCache1Name=this._idxCache0Name,this._idxCache1Idx=this._idxCache0Idx,this._idxCache0Name=j,this._idxCache0Idx=$,$}let D=this.componentNameToIdx.get(j);if(D===void 0)D=this.componentNameToIdx.size,this.componentNameToIdx.set(j,D);return this._idxCache1Name=this._idxCache0Name,this._idxCache1Idx=this._idxCache0Idx,this._idxCache0Name=j,this._idxCache0Idx=D,D}subscribeChanged(j){let D=this.getOrAssignComponentIdx(j),$=this._subscribedComponentIdx;if($===null)$=new Uint8Array(Math.max(D+1,8)),this._subscribedComponentIdx=$;else if(D>=$.length){let G=new Uint8Array(Math.max(D+1,$.length*2));G.set($),$=G,this._subscribedComponentIdx=$}$[D]=1}disableChangeTracking(){this._subscribedComponentIdx=new Uint8Array(0)}hasAnySubscribed(j){let D=this._subscribedComponentIdx;if(D===null)return!0;for(let $=0;$<j.length;$++){let G=j[$];if(G!==void 0&&G<D.length&&D[G]!==0)return!0}return!1}getChangeSeq(j,D){let $=this.componentNameToIdx.get(D);if($===void 0)return-1;let G=this.changeSeqs[j];if(!G||$>=G.length)return-1;let J=G[$]??0;return J===0?-1:J}spawnChild(j,D){let $=this.createEntity();return this.addComponents($.id,D),this.setParent($.id,j),$}setParent(j,D){this.hierarchyManager.setParent(j,D),this._queryCache.onParentChanged(j);for(let $ of this._afterParentChangedHooks)$(j);return this}removeParent(j){let D=this.hierarchyManager.removeParent(j);if(D){this._queryCache.onParentChanged(j);for(let $ of this._afterParentChangedHooks)$(j)}return D}getParent(j){return this.hierarchyManager.getParent(j)}getChildren(j){return this.hierarchyManager.getChildren(j)}getChildAt(j,D){return this.hierarchyManager.getChildAt(j,D)}getChildIndex(j,D){return this.hierarchyManager.getChildIndex(j,D)}getAncestors(j){return this.hierarchyManager.getAncestors(j)}getDescendants(j){return this.hierarchyManager.getDescendants(j)}getRoot(j){return this.hierarchyManager.getRoot(j)}getSiblings(j){return this.hierarchyManager.getSiblings(j)}isDescendantOf(j,D){return this.hierarchyManager.isDescendantOf(j,D)}isAncestorOf(j,D){return this.hierarchyManager.isAncestorOf(j,D)}get hasHierarchy(){return this.hierarchyManager.hasHierarchy}getRootEntities(){return this.hierarchyManager.getRootEntities()}forEachInHierarchy(j,D){this.hierarchyManager.forEachInHierarchy(j,D)}hierarchyIterator(j){return this.hierarchyManager.hierarchyIterator(j)}}class w{handlers=new Map;subscribe(j,D){return this.addHandler(j,D,!1)}once(j,D){return this.addHandler(j,D,!0)}unsubscribe(j,D){let $=this.handlers.get(j);if(!$)return!1;let G=$.findIndex((J)=>J.callback===D);if(G===-1)return!1;return $.splice(G,1),!0}addHandler(j,D,$){let G=this.handlers.get(j);if(!G)G=[],this.handlers.set(j,G);let J={callback:D,once:$};return G.push(J),()=>{let X=this.handlers.get(j);if(X){let Z=X.indexOf(J);if(Z!==-1)X.splice(Z,1)}}}publish(j,D){let $=this.handlers.get(j);if(!$||$.length===0)return;let G=!1,J=$.length;for(let X=0;X<J&&X<$.length;X++){let Z=$[X];if(!Z)continue;if(Z.callback(D),Z.once)G=!0}if(G){for(let X=$.length-1;X>=0;X--)if($[X]?.once)$.splice(X,1)}}clear(){this.handlers.clear()}clearEvent(j){this.handlers.delete(j)}}var k=Symbol("resource-direct");function n(j){return{[k]:j}}function b(j){if(typeof j==="object"&&j!==null&&!Array.isArray(j))return{...j};return{$value:j}}function t(j,D){if(typeof j==="object"&&j!==null&&!Array.isArray(j)){let $=j;for(let G in D)if(!Object.is($[G],D[G]))return!0;return!1}return!Object.is(j,D.$value)}function e(j){return typeof j==="object"&&j!==null&&"factory"in j&&typeof j.factory==="function"}function jj(j){return typeof j==="object"&&j!==null&&k in j}function m(j,D){let $=[],G=new Set,J=new Set;function X(Z,Y=[]){if(G.has(Z))return;if(J.has(Z))throw Error(`Circular resource dependency: ${[...Y,Z].join(" -> ")}`);J.add(Z);for(let F of D(Z)){let B=j.find((A)=>A===F);if(B)X(B,[...Y,Z])}J.delete(Z),G.add(Z),$.push(Z)}for(let Z of j)X(Z);return $}class C{resources=new Map;resourceFactories=new Map;resourceDependencies=new Map;resourceDisposers=new Map;initializedResourceKeys=new Set;_changeSubscribers=new Map;_observedSnapshots=new Map;add(j,D){let $=(G)=>{this.resources.set(j,G),this.initializedResourceKeys.add(j),this.resourceDependencies.set(j,[])};if(e(D)){if(this.resourceFactories.set(j,D.factory),this.resourceDependencies.set(j,D.dependsOn??[]),D.onDispose)this.resourceDisposers.set(j,D.onDispose)}else if(jj(D))$(D[k]);else if(typeof D==="function")this.resourceFactories.set(j,D),this.resourceDependencies.set(j,[]);else $(D);return this}tryGet(j,...D){if(!this.has(j))return;return this.get(j,...D)}get(j,...D){let $=this.resources.get(j);if($!==void 0)return $;let G=this.resourceFactories.get(j);if(G===void 0)throw Error(`Resource ${String(j)} not found`);let J=D[0],X=G(J);if(!(X instanceof Promise))this.resources.set(j,X),this.initializedResourceKeys.add(j);return X}has(j){return this.resources.has(j)||this.resourceFactories.has(j)}remove(j){let D=this.resources.delete(j),$=this.resourceFactories.delete(j);return this.resourceDependencies.delete(j),this.resourceDisposers.delete(j),this.initializedResourceKeys.delete(j),D||$}getKeys(){let j=new Set([...this.resources.keys(),...this.resourceFactories.keys()]);return Array.from(j)}needsInitialization(j){return this.resourceFactories.has(j)&&!this.initializedResourceKeys.has(j)}getPendingInitializationKeys(){return Array.from(this.resourceFactories.keys()).filter((j)=>!this.initializedResourceKeys.has(j))}async initializeResource(j,...D){if(!this.resourceFactories.has(j)||this.initializedResourceKeys.has(j))return;let $=this.resourceFactories.get(j);if(!$)return;let G=D[0],J=await $(G);this.resources.set(j,J),this.initializedResourceKeys.add(j),this.resourceFactories.delete(j)}async initializeResources(...j){let D=j.slice(1),$=D.length===0?this.getPendingInitializationKeys():D;if($.length===0)return;let G=m($,(J)=>[...this.resourceDependencies.get(J)??[]]);for(let J of G)await this.initializeResource(J,...j.slice(0,1))}getDependencies(j){return this.resourceDependencies.get(j)??[]}async disposeResource(j,...D){if(!this.resources.has(j)&&!this.resourceFactories.has(j))return!1;if(this.initializedResourceKeys.has(j)){let $=this.resourceDisposers.get(j),G=this.resources.get(j);if($&&G!==void 0){let J=D[0];await $(G,J)}}return this.resources.delete(j),this.resourceFactories.delete(j),this.resourceDependencies.delete(j),this.resourceDisposers.delete(j),this.initializedResourceKeys.delete(j),this._changeSubscribers.delete(j),!0}onResourceChange(j,D){let $=this._changeSubscribers.get(j),G=$??new Set;if(!$){this._changeSubscribers.set(j,G);let X=this.resources.get(j);this._observedSnapshots.set(j,b(X))}let J=D;return G.add(J),()=>{if(G.delete(J),G.size===0)this._changeSubscribers.delete(j),this._observedSnapshots.delete(j)}}notifyChange(j,D,$){if(Object.is(D,$))return;let G=this._changeSubscribers.get(j);if(!G||G.size===0)return;if(this._observedSnapshots.has(j))this._observedSnapshots.set(j,b(D));let J=[...G];for(let X of J)X(D,$)}isObserved(j){return this._observedSnapshots.has(j)}flushObserved(){if(this._observedSnapshots.size===0)return;for(let[j,D]of this._observedSnapshots){let $=this.resources.get(j);if(!t($,D))continue;let G="$value"in D?D.$value:D,J=b($),X=this._changeSubscribers.get(j);for(let Z of X)Z($,G);this._observedSnapshots.set(j,J)}}async disposeResources(...j){let D=Array.from(this.initializedResourceKeys);if(D.length===0)return;let $=m(D,(G)=>[...this.resourceDependencies.get(G)??[]]).reverse();for(let G of $)await this.disposeResource(G,...j)}}class q{queries=new Map;entityManager;_hasParentHasQueries=!1;constructor(j){this.entityManager=j}get hasParentHasQueries(){return this._hasParentHasQueries}addQuery(j,D){let $={definition:D,matchingEntities:new Set};if(this.queries.set(j,$),D.parentHas?.length)this._hasParentHasQueries=!0;let G=this.entityManager.getEntitiesWithQuery(D.with,D.without??[]);for(let J of G)if(this.entityMatchesQuery(J,$.definition))$.matchingEntities.add(J.id),$.definition.onEnter?.(J)}removeQuery(j){let D=this.queries.delete(j);if(D)this._recalcParentHasFlag();return D}entityMatchesQuery(j,D){return R(j,D.with,D.without,D.parentHas,this.entityManager)}_applyQueryTransition(j,D){let $=D.matchingEntities.has(j.id),G=this.entityMatchesQuery(j,D.definition);if(!$&&G)D.matchingEntities.add(j.id),D.definition.onEnter?.(j);else if($&&!G)D.matchingEntities.delete(j.id),D.definition.onExit?.(j.id)}onComponentAdded(j,D){for(let[,$]of this.queries)this._applyQueryTransition(j,$);if(this._hasParentHasQueries)this._recheckChildren(j.id)}onComponentRemoved(j,D){for(let[,$]of this.queries)this._applyQueryTransition(j,$);if(this._hasParentHasQueries)this._recheckChildren(j.id)}onEntityRemoved(j){for(let[D,$]of this.queries)if($.matchingEntities.has(j))$.matchingEntities.delete(j),$.definition.onExit?.(j)}recheckEntity(j){for(let[,D]of this.queries)this._applyQueryTransition(j,D)}recheckEntityAndChildren(j){if(this.recheckEntity(j),this._hasParentHasQueries)this._recheckChildren(j.id)}_recheckChildren(j){let D=this.entityManager.getChildren(j);for(let $ of D){let G=this.entityManager.getEntity($);if(G)this.recheckEntity(G)}}_recalcParentHasFlag(){this._hasParentHasQueries=!1;for(let[,j]of this.queries)if(j.definition.parentHas?.length){this._hasParentHasQueries=!0;return}}}class g{parent;commands=[];constructor(j){this.parent=j}removeEntity(j,D){this.commands.push(($)=>{$.removeEntity(j,D)})}addComponent(j,D,$){this.commands.push((G)=>{G.addComponent(j,D,$)})}removeComponent(j,D){this.commands.push(($)=>{$.removeComponent(j,D)})}spawn(j,D){let $=this._resolveScope(D);this.commands.push((G)=>{G.spawn(j,$)})}spawnChild(j,D,$){let G=this._resolveScope($);this.commands.push((J)=>{J.spawnChild(j,D,G)})}_resolveScope(j){if(j?.scope!==void 0)return j;let D=this.parent?._getActiveScopeHint();if(!D)return j;return{scope:D}}addComponents(j,D){this.commands.push(($)=>{$.addComponents(j,D)})}setParent(j,D){this.commands.push(($)=>{$.setParent(j,D)})}mutateComponent(j,D,$){this.commands.push((G)=>{G.mutateComponent(j,D,$)})}markChanged(j,D){this.commands.push(($)=>{$.markChanged(j,D)})}removeParent(j){this.commands.push((D)=>{D.removeParent(j)})}playback(j){for(let D of this.commands)try{D(j)}catch($){console.warn("CommandBuffer: Command failed during playback:",$)}this.commands.length=0}clear(){this.commands.length=0}get length(){return this.commands.length}}class s{_id;constructor(j){this._id=j}_systemDefaults;setSystemDefaults(j){return this._systemDefaults=j,this}withComponentTypes(){return this}withEventTypes(){return this}withResourceTypes(){return this}withAssetTypes(){return this}withScreenTypes(){return this}withLabels(){return this}withGroups(){return this}withAssetGroupNames(){return this}withReactiveQueryNames(){return this}requires(){return this}install(j){return{id:this._id,install:j,...this._systemDefaults?{systemDefaults:this._systemDefaults}:{}}}}function E(j){return new s(j)}var c="__each";class x{_label;queries={};singletons={};processFunction;detachFunction;initializeFunction;eventHandlers;_priority=0;_phase="update";_groups=[];_inScreens;_excludeScreens;_requiredAssets;_runWhenEmpty=!1;_entityEnterHandlers={};_resourceKeys;constructor(j,D){this._label=j;if(D){if(D.phase!==void 0)this._phase=D.phase;if(D.priority!==void 0)this._priority=D.priority;if(D.inScreens!==void 0)this._inScreens=D.inScreens;if(D.excludeScreens!==void 0)this._excludeScreens=D.excludeScreens}}get label(){return this._label}_createSystemObject(){let j={label:this._label,entityQueries:this.queries,priority:this._priority,phase:this._phase};if(Object.keys(this.singletons).length>0)j.entitySingletons=this.singletons;if(this.processFunction)j.process=this.processFunction;if(this.detachFunction)j.onDetach=this.detachFunction;if(this.initializeFunction)j.onInitialize=this.initializeFunction;if(this.eventHandlers)j.eventHandlers=this.eventHandlers;if(this._groups.length>0)j.groups=[...this._groups];if(this._inScreens)j.inScreens=this._inScreens;if(this._excludeScreens)j.excludeScreens=this._excludeScreens;if(this._requiredAssets)j.requiredAssets=this._requiredAssets;if(this._runWhenEmpty)j.runWhenEmpty=!0;if(Object.keys(this._entityEnterHandlers).length>0)j.onEntityEnter={...this._entityEnterHandlers};return j}setPriority(j){return this._priority=j,this}inPhase(j){return this._phase=j,this}inGroup(j){if(!this._groups.includes(j))this._groups.push(j);return this}inScreens(j){return this._inScreens=[...j],this}excludeScreens(j){return this._excludeScreens=[...j],this}requiresAssets(j){return this._requiredAssets=[...j],this}runWhenEmpty(){return this._runWhenEmpty=!0,this}withResources(j){return this._resourceKeys=[...j],this}addQuery(j,D){let $=this;return $.queries={...this.queries,[j]:D},$}addSingleton(j,D){let $=this;return $.singletons={...this.singletons,[j]:D},$}setProcess(j){return this.processFunction=this._wrapWithResources(j),this}_wrapWithResources(j){if(!this._resourceKeys?.length)return j;let D=this._resourceKeys,$={},G=!1;return(J)=>{for(let X of D)if(!G||J.ecs.isResourceObserved(X))$[X]=J.ecs.getResource(X);G=!0,J.resources=$,j(J)}}setProcessEach(j,D){let $=this;if(Object.keys($.queries).length>0||Object.keys($.singletons).length>0||$.processFunction!==void 0)throw Error("setProcessEach requires a SystemBuilder with no prior queries, singletons, or process function. Use addQuery + setProcess for multi-query systems.");$.queries.__each=j;let G={entity:void 0,dt:0,ecs:void 0,resources:void 0},J=(X)=>{let Z=X,Y=Z.queries.__each;if(!Y)return;let F=j._mutatesIdx;G.dt=Z.dt,G.ecs=Z.ecs,G.resources=Z.resources;let B=Z.ecs.entityManager;for(let A=0;A<Y.length;A++){let W=Y[A];if(!W)continue;G.entity=W;let _=D(G);if(F===void 0||_===!1)continue;for(let L=0;L<F.length;L++){let U=F[L];if(U!==void 0)B.markChangedByIdx(W.id,U)}}};return $.processFunction=$._wrapWithResources(J),this}setOnEntityEnter(j,D){return this._entityEnterHandlers[j]=D,this}setOnDetach(j){return this.detachFunction=j,this}setOnInitialize(j){return this.initializeFunction=j,this}setEventHandlers(j){return this.eventHandlers=j,this}}function i(j,D,$){let G=new Set,J=[D];while(J.length>0){let X=J.pop();if(X===void 0)break;if(X===j)throw Error(`Circular required component dependency: '${String(j)}' -> '${String(D)}' -> ... -> '${String(j)}'`);if(G.has(X))continue;G.add(X);let Z=$(X);if(Z)for(let Y of Z)J.push(Y.component)}}var y="0.17.0";class z{assets=new Map;groups=new Map;eventBus=null;setEventBus(j){this.eventBus=j}register(j,D){if(this.assets.set(j,{definition:D,status:"pending"}),D.group){let $=this.groups.get(D.group)??new Set;$.add(j),this.groups.set(D.group,$)}}async loadEagerAssets(){let j=[];for(let[D,$]of this.assets)if($.definition.eager&&$.status==="pending")j.push(D);await Promise.all(j.map((D)=>this.loadAsset(D)))}async loadAsset(j){let D=this.assets.get(j);if(!D)throw Error(`Asset '${String(j)}' not found`);if(D.status==="loaded"&&D.value!==void 0)return D.value;if(D.status==="loading"&&D.loadPromise)return D.loadPromise;if(D.status==="failed")D.status="pending";D.status="loading",D.loadPromise=D.definition.loader();try{let $=await D.loadPromise;return D.value=$,D.status="loaded",D.loadPromise=void 0,this.eventBus?.publish("assetLoaded",{key:j}),this.checkGroupProgress(D.definition.group),$}catch($){let G=$ instanceof Error?$:Error(String($));throw D.status="failed",D.error=G,D.loadPromise=void 0,this.eventBus?.publish("assetFailed",{key:j,error:G}),G}}async loadAssetGroup(j){let D=this.groups.get(j);if(!D||D.size===0)throw Error(`Asset group '${j}' not found or empty`);await Promise.all(Array.from(D).map(($)=>this.loadAsset($)))}get(j){let D=this.assets.get(j);if(!D)throw Error(`Asset '${String(j)}' not found`);if(D.status!=="loaded"||D.value===void 0)throw Error(`Asset '${String(j)}' is not loaded (status: ${D.status})`);return D.value}tryGet(j){let D=this.assets.get(j);if(!D||D.status!=="loaded")return;return D.value}getHandle(j){let D=this.assets.get(j);if(!D)throw Error(`Asset '${String(j)}' not found`);let $=this;return{get status(){return D.status},get isLoaded(){return D.status==="loaded"},get(){return $.get(j)},tryGet(){return $.tryGet(j)}}}getStatus(j){let D=this.assets.get(j);if(!D)throw Error(`Asset '${String(j)}' not found`);return D.status}isLoaded(j){return this.assets.get(j)?.status==="loaded"}isGroupLoaded(j){let D=this.groups.get(j);if(!D||D.size===0)return!1;for(let $ of D){let G=this.assets.get($);if(!G||G.status!=="loaded")return!1}return!0}getGroupProgress(j){return this.getGroupProgressDetails(j).progress}getGroupProgressDetails(j){let D=this.groups.get(j);if(!D||D.size===0)return{loaded:0,total:0,progress:0};let $=0;for(let J of D)if(this.assets.get(J)?.status==="loaded")$++;let G=D.size;return{loaded:$,total:G,progress:$/G}}checkGroupProgress(j){if(!j||!this.eventBus)return;let D=j,$=this.getGroupProgressDetails(D);if(this.eventBus.publish("assetGroupProgress",{group:D,...$}),$.loaded===$.total)this.eventBus.publish("assetGroupLoaded",{group:D})}createResource(){let j=this;return{getStatus(D){return j.getStatus(D)},isLoaded(D){return j.isLoaded(D)},isGroupLoaded(D){return j.isGroupLoaded(D)},getGroupProgress(D){return j.getGroupProgress(D)},get(D){return j.get(D)},tryGet(D){return j.tryGet(D)},getHandle(D){return j.getHandle(D)}}}getKeys(){return Array.from(this.assets.keys())}getGroupNames(){return Array.from(this.groups.keys())}getGroupKeys(j){let D=this.groups.get(j);return D?Array.from(D):[]}}class d{manager;constructor(j){this.manager=j}add(j,D){return this.manager.register(j,{loader:D,eager:!0}),this}addWithConfig(j,D){return this.manager.register(j,D),this}addGroup(j,D){for(let[$,G]of Object.entries(D))this.manager.register($,{loader:G,eager:!1,group:j});return this}getManager(){return this.manager}}function p(j){return new d(j??new z)}class P{screens=new Map;currentScreen=null;screenStack=[];eventBus=null;assetManager=null;ecs=null;setDependencies(j,D,$){this.eventBus=j,this.assetManager=D,this.ecs=$}requireEcs(){if(!this.ecs)throw Error("ScreenManager: dependencies not set. Call setDependencies() first.");return this.ecs}register(j,D){this.screens.set(j,{definition:D})}async setScreen(j,D){let $=this.screens.get(j);if(!$)throw Error(`Screen '${String(j)}' not found`);await this.verifyRequiredAssets($.definition.requiredAssets,$.definition.requiredAssetGroups);while(this.screenStack.length>0){let J=this.screenStack.pop();if(J)await this.exitScreen(J.name)}if(this.currentScreen)await this.exitScreen(this.currentScreen.name);let G=$.definition.initialState(D);this.currentScreen={name:j,config:D,state:G},await $.definition.onEnter?.({config:D,ecs:this.requireEcs()}),this.eventBus?.publish("screenEnter",{screen:j,config:D})}async pushScreen(j,D){let $=this.screens.get(j);if(!$)throw Error(`Screen '${String(j)}' not found`);if(await this.verifyRequiredAssets($.definition.requiredAssets,$.definition.requiredAssetGroups),this.currentScreen)this.screenStack.push(this.currentScreen);let G=$.definition.initialState(D);this.currentScreen={name:j,config:D,state:G},await $.definition.onEnter?.({config:D,ecs:this.requireEcs()}),this.eventBus?.publish("screenPush",{screen:j,config:D})}async popScreen(){if(this.screenStack.length===0)throw Error("Cannot pop screen: stack is empty");if(this.currentScreen)await this.exitScreen(this.currentScreen.name),this.eventBus?.publish("screenPop",{screen:this.currentScreen.name});this.currentScreen=this.screenStack.pop()??null}async exitScreen(j){let D=this.screens.get(j);if(D?.definition.onExit)await D.definition.onExit(this.requireEcs());this.eventBus?.publish("screenExit",{screen:j})}async verifyRequiredAssets(j,D){if(!this.assetManager)return;if(j){for(let $ of j)if(!this.assetManager.isLoaded($))await this.assetManager.loadAsset($)}if(D){for(let $ of D)if(!this.assetManager.isGroupLoaded($))await this.assetManager.loadAssetGroup($)}}getCurrentScreen(){return this.currentScreen?.name??null}getConfig(j){if(!this.currentScreen)throw Error("No current screen");if(j!==void 0&&this.currentScreen.name!==j)throw Error(`Expected current screen '${String(j)}', but current is '${String(this.currentScreen.name)}'`);return this.currentScreen.config}tryGetConfig(j){if(!this.currentScreen)return;if(j!==void 0&&this.currentScreen.name!==j)return;return this.currentScreen.config}getState(j){if(!this.currentScreen)throw Error("No current screen");if(j!==void 0&&this.currentScreen.name!==j)throw Error(`Expected current screen '${String(j)}', but current is '${String(this.currentScreen.name)}'`);return this.currentScreen.state}tryGetState(j){if(!this.currentScreen)return;if(j!==void 0&&this.currentScreen.name!==j)return;return this.currentScreen.state}updateState(j,D){if(!this.currentScreen)throw Error("No current screen");if(D!==void 0&&this.currentScreen.name!==D)throw Error(`Expected current screen '${String(D)}', but current is '${String(this.currentScreen.name)}'`);let $=typeof j==="function"?j(this.currentScreen.state):j;this.currentScreen.state={...this.currentScreen.state,...$}}getStackDepth(){return this.screenStack.length}isOverlay(){return this.screenStack.length>0}isActive(j){if(this.currentScreen?.name===j)return!0;return this.screenStack.some((D)=>D.name===j)}isCurrent(j){return this.currentScreen?.name===j}createResource(){let j=this;return{get current(){return j.getCurrentScreen()},get config(){return j.tryGetConfig()??null},get state(){return j.tryGetState()??null},set state(D){if(j.currentScreen&&D!==null)j.currentScreen.state=D},get stack(){return j.screenStack},get isOverlay(){return j.isOverlay()},get stackDepth(){return j.getStackDepth()},isActive(D){return j.isActive(D)},isCurrent(D){return j.isCurrent(D)}}}getScreenNames(){return Array.from(this.screens.keys())}hasScreen(j){return this.screens.has(j)}}class o{manager;constructor(j){this.manager=j}add(j,D){return this.manager.register(j,D),this}getManager(){return this.manager}}function h(j){return new o(j??new P)}class I{assetConfigurator=null;screenConfigurator=null;pendingResources=[];pendingDisposeCallbacks=[];pendingRequiredComponents=[];pendingPlugins=[];_fixedDt=null;_disableChangeTracking=!1;constructor(){}withPlugin(j){return this.pendingPlugins.push(j),this}withComponentTypes(){return this}withEventTypes(){return this}withResourceTypes(){return this}disableChangeTracking(){return this._disableChangeTracking=!0,this}withResource(j,D){return this.pendingResources.push({key:j,value:D}),this}withDispose(j,D){return this.pendingDisposeCallbacks.push({key:j,callback:D}),this}withRequired(j,D,$){return this.pendingRequiredComponents.push({trigger:j,required:D,factory:$}),this}withAssets(j){let D=p();return j(D),this.assetConfigurator=D,this}withScreens(j){let D=h();return j(D),this.screenConfigurator=D,this}withFixedTimestep(j){return this._fixedDt=j,this}withReactiveQueryNames(){return this}pluginFactory(){return(j)=>E(j.id).install(j.install)}build(){let j=new V;if(this._disableChangeTracking)j.entityManager.disableChangeTracking();for(let D of this.pendingPlugins)j._installPluginUnchecked(D);for(let{key:D,value:$}of this.pendingResources)j.addResource(D,$);for(let{key:D,callback:$}of this.pendingDisposeCallbacks)j.registerDispose(D,$);for(let{trigger:D,required:$,factory:G}of this.pendingRequiredComponents)j.registerRequired(D,$,G);if(this.assetConfigurator)j._setAssetManager(this.assetConfigurator.getManager());else if(j._hasPendingPluginAssets())j._setAssetManager(new z);if(this.screenConfigurator)j._setScreenManager(this.screenConfigurator.getManager());else if(j._hasPendingPluginScreens())j._setScreenManager(new P);if(this._fixedDt!==null)j._setFixedDt(this._fixedDt);return j}}var r=["preUpdate","fixedUpdate","update","postUpdate","render"];class V{static VERSION=y;_entityManager;_eventBus;_resourceManager;_commandBuffer;_systems=[];_phaseSystems={preUpdate:[],fixedUpdate:[],update:[],postUpdate:[],render:[]};_installedPlugins=new Set;_pluginCleanups=new Map;_currentSystemDefaults;_screenScopedEntities=new Map;_entityScreenScope=new Map;_activeScopeHint=null;_disabledGroups=new Set;_assetManager=null;_screenManager=null;_reactiveQueryManager;_postUpdateHooks=[];_currentTick=0;_systemLastSeqs=new Map;_changeThreshold=0;_fixedDt=0.016666666666666666;_fixedAccumulator=0;_interpolationAlpha=0;_maxFixedSteps=8;_requiredComponents=new Map;_pendingPluginAssets=[];_pendingPluginScreens=[];_diagnosticsEnabled=!1;_systemTimings=new Map;_phaseTimings={preUpdate:0,fixedUpdate:0,update:0,postUpdate:0,render:0};_entityEnterTracking=new Map;_entityEnterFrameSet=new Set;_systemContexts=new WeakMap;_singletonScratch=[];_pendingFinalizers=[];_batchingRegistrations=!1;_initializeFired=!1;_systemsInitialized=new WeakSet;constructor(){this._entityManager=new T,this._eventBus=new w,this._resourceManager=new C,this._reactiveQueryManager=new q(this._entityManager),this._commandBuffer=new g(this),this._subscribeLifecycleHooks()}_subscribeLifecycleHooks(){this._entityManager.onAfterComponentAdded((j,D)=>{this._entityManager.markChanged(j,D);let $=this._requiredComponents.get(D);if($){let G=this._entityManager.getEntity(j);if(G){let J=G.components[D];for(let{component:X,factory:Z}of $){if(this._entityManager._pendingBatchKeys?.has(X))continue;if(!(X in G.components))this._entityManager.addComponent(j,X,Z(J))}}}}),this._entityManager.onAfterEntityMutated((j)=>{let D=this._entityManager.getEntity(j);if(D)this._reactiveQueryManager.recheckEntityAndChildren(D)}),this._entityManager.onAfterComponentRemoved((j,D)=>{let $=this._entityManager.getEntity(j);if($)this._reactiveQueryManager.onComponentRemoved($,D)}),this._entityManager.onBeforeEntityRemoved((j)=>{this._reactiveQueryManager.onEntityRemoved(j);let D=this._entityScreenScope.get(j);if(D!==void 0)this._entityScreenScope.delete(j),this._screenScopedEntities.get(D)?.delete(j)}),this._entityManager.onAfterParentChanged((j)=>{if(this._reactiveQueryManager.hasParentHasQueries){let D=this._entityManager.getEntity(j);if(D)this._reactiveQueryManager.recheckEntity(D)}})}static create(){return new I}addSystem(j){let D=new x(j,this._currentSystemDefaults);return this._pendingFinalizers.push(()=>{this._registerSystem(D._createSystemObject())}),D}_finalizePendingBuilders(){if(this._pendingFinalizers.length===0)return;this._batchingRegistrations=!0;while(this._pendingFinalizers.length>0){let j=this._pendingFinalizers;this._pendingFinalizers=[];for(let D of j)D()}this._batchingRegistrations=!1,this._rebuildPhaseSystems()}update(j){this._finalizePendingBuilders();let D=this._screenManager?.getCurrentScreen()??null,$=this._diagnosticsEnabled;this._runPhase("preUpdate",j,D,$);let G=$?performance.now():0;this._fixedAccumulator+=j;let J=0;while(this._fixedAccumulator>=this._fixedDt&&J<this._maxFixedSteps)this._executePhase(this._phaseSystems.fixedUpdate,this._fixedDt,D),this._commandBuffer.playback(this),this._fixedAccumulator-=this._fixedDt,J++;if(this._fixedAccumulator>=this._fixedDt)this._fixedAccumulator=0;if($)this._phaseTimings.fixedUpdate=performance.now()-G;this._interpolationAlpha=this._fixedAccumulator/this._fixedDt,this._runPhase("update",j,D,$),this._runPhase("postUpdate",j,D,$);for(let X of this._postUpdateHooks)X({ecs:this,dt:j});this._runPhase("render",j,D,$),this._resourceManager.flushObserved(),this._changeThreshold=this._entityManager.changeSeq,this._currentTick++}_executePhase(j,D,$){for(let G of j){if(!G.process&&!G.onEntityEnter)continue;if(G.groups?.length){let W=!1;for(let _ of G.groups)if(this._disabledGroups.has(_)){W=!0;break}if(W)continue}if(G.inScreens?.length){if($===null||!G.inScreens.includes($))continue}if(G.excludeScreens?.length){if($!==null&&G.excludeScreens.includes($))continue}if(G.requiredAssets?.length&&this._assetManager){let W=!0;for(let _ of G.requiredAssets)if(!this._assetManager.isLoaded(_)){W=!1;break}if(!W)continue}let J=this._systemLastSeqs.get(G)??0;this._changeThreshold=J;let X=this._systemContexts.get(G);if(!X)X={queries:{},dt:0,ecs:this},this._systemContexts.set(G,X);X.dt=D;let Z=X.queries,Y=!1,F=!1;if(G.entityQueries)for(let W in G.entityQueries){F=!0;let _=G.entityQueries[W];if(_){let U=Z[W]??(Z[W]=[]);if(this._entityManager.getEntitiesWithQueryInto(U,_.with,_.without||[],_.changed,_.changed?this._changeThreshold:void 0,_.parentHas,_._changedIdx),U.length)Y=!0}}if(G.entitySingletons){let W=this._singletonScratch;for(let _ in G.entitySingletons){F=!0;let L=G.entitySingletons[_];if(L){if(this._entityManager.getEntitiesWithQueryInto(W,L.with,L.without||[],L.changed,L.changed?this._changeThreshold:void 0,L.parentHas,L._changedIdx),Z[_]=W[0],W.length)Y=!0}}}let B=this._entityEnterTracking.get(G);if(B&&G.onEntityEnter)for(let W in G.onEntityEnter){let _=Z[W],L=B.get(W);if(!_||!L)continue;let U=G.onEntityEnter[W];if(!U)continue;let Q=this._entityEnterFrameSet;Q.clear();for(let O of _)if(Q.add(O.id),!L.has(O.id))L.add(O.id),U({entity:O,ecs:this});for(let O of L)if(!Q.has(O))L.delete(O)}if(G.process){if(Y||G.runWhenEmpty||!F){let _=this._activeScopeHint;this._activeScopeHint=G.inScreens?.length&&$!==null?$:null;let L=this._diagnosticsEnabled?performance.now():0;try{G.process(X)}finally{if(this._activeScopeHint=_,this._diagnosticsEnabled)this._systemTimings.set(G.label,performance.now()-L)}}}let A=G._autoMarkPairs;if(A){let W=this._entityManager;for(let _=0;_<A.length;_++){let L=A[_];if(!L)continue;let U=L.mutatesIdx,Q=U.length;if(!W.hasAnySubscribed(U))continue;if(L.kind==="list"){let O=Z[L.queryName];if(!O)continue;for(let K=0;K<O.length;K++){let M=O[K];if(!M)continue;for(let f=0;f<Q;f++){let u=U[f];if(u!==void 0)W.markChangedByIdx(M.id,u)}}}else{let O=Z[L.queryName];if(!O)continue;for(let K=0;K<Q;K++){let M=U[K];if(M!==void 0)W.markChangedByIdx(O.id,M)}}}}this._systemLastSeqs.set(G,this._entityManager.changeSeq)}}_runPhase(j,D,$,G){if(G){let J=performance.now();this._executePhase(this._phaseSystems[j],D,$),this._phaseTimings[j]=performance.now()-J}else this._executePhase(this._phaseSystems[j],D,$);this._commandBuffer.playback(this)}async initialize(){if(this._finalizePendingBuilders(),await this.initializeResources(),this._assetManager)this._assetManager.setEventBus(this._eventBus),await this._assetManager.loadEagerAssets(),this._resourceManager.add("$assets",this._assetManager.createResource());if(this._screenManager){let j=this._eventBus;this._screenManager.setDependencies(j,this._assetManager,this),this._resourceManager.add("$screen",this._screenManager.createResource()),j.subscribe("screenExit",({screen:D})=>{let $=this._screenScopedEntities.get(D);if(!$||$.size===0)return;this._screenScopedEntities.delete(D);for(let G of Array.from($))this._entityScreenScope.delete(G),this.removeEntity(G)})}for(let j of this._systems){if(this._systemsInitialized.has(j))continue;this._systemsInitialized.add(j),await j.onInitialize?.(this)}this._initializeFired=!0}async initializeResources(...j){await this._resourceManager.initializeResources(this,...j)}_rebuildPhaseSystems(){for(let j of r)this._phaseSystems[j]=[];for(let j of this._systems){let D=j.phase??"update";this._phaseSystems[D].push(j)}for(let j of r)this._phaseSystems[j].sort((D,$)=>{let G=D.priority??0;return($.priority??0)-G})}updateSystemPriority(j,D){this._finalizePendingBuilders();let $=this._systems.find((G)=>G.label===j);if(!$)return!1;return $.priority=D,this._rebuildPhaseSystems(),!0}updateSystemPhase(j,D){this._finalizePendingBuilders();let $=this._systems.find((G)=>G.label===j);if(!$)return!1;return $.phase=D,this._rebuildPhaseSystems(),!0}get interpolationAlpha(){return this._interpolationAlpha}get fixedDt(){return this._fixedDt}disableSystemGroup(j){this._disabledGroups.add(j)}enableSystemGroup(j){this._disabledGroups.delete(j)}isSystemGroupEnabled(j){return!this._disabledGroups.has(j)}getSystemsInGroup(j){return this._finalizePendingBuilders(),this._systems.filter((D)=>D.groups?.includes(j)).map((D)=>D.label)}removeSystem(j){this._finalizePendingBuilders();let D=this._systems.findIndex((G)=>G.label===j);if(D===-1)return!1;let $=this._systems[D];if(!$)return!1;if($.onDetach)$.onDetach(this);return this._systems.splice(D,1),this._systemLastSeqs.delete($),this._entityEnterTracking.delete($),this._systemsInitialized.delete($),this._rebuildPhaseSystems(),!0}_registerSystem(j){if(this._systems.push(j),this._systemLastSeqs.set(j,this._changeThreshold),!this._batchingRegistrations)this._rebuildPhaseSystems();let D=[],$=this._entityManager,G=(J,X,Z)=>{let Y=X.changed;if(Y&&Y.length>0){let B=[];for(let A=0;A<Y.length;A++){let W=Y[A];if(W===void 0)continue;$.subscribeChanged(W),B.push($.getOrAssignComponentIdx(W))}X._changedIdx=B}let F=X.mutates;if(F&&F.length>0){let B=[];for(let A=0;A<F.length;A++){let W=F[A];if(W!==void 0)B.push($.getOrAssignComponentIdx(W))}if(X._mutatesIdx=B,J!==c)D.push({queryName:J,mutatesIdx:B,kind:Z})}};if(j.entityQueries)for(let J in j.entityQueries){let X=j.entityQueries[J];if(X)G(J,X,"list")}if(j.entitySingletons)for(let J in j.entitySingletons){let X=j.entitySingletons[J];if(X)G(J,X,"singleton")}if(j._autoMarkPairs=D.length>0?D:null,j.onEntityEnter){let J=new Map;for(let X in j.onEntityEnter)J.set(X,new Set);this._entityEnterTracking.set(j,J)}if(j.eventHandlers)for(let J in j.eventHandlers){let X=j.eventHandlers[J];if(X)this._eventBus.subscribe(J,(Z)=>{X({data:Z,ecs:this})})}if(this._initializeFired&&!this._systemsInitialized.has(j)){this._systemsInitialized.add(j);let J=j.onInitialize?.(this);if(J instanceof Promise)J.catch((X)=>{console.error(`onInitialize for system "${j.label}" rejected:`,X)})}}hasResource(j){return this._resourceManager.has(j)}getResource(j){if(!this._resourceManager.has(j))throw Error(`Resource '${String(j)}' not found. Available resources: [${this.getResourceKeys().map((D)=>String(D)).join(", ")}]`);return this._resourceManager.get(j,this)}tryGetResource(j){let D=j;if(!this._resourceManager.has(D))return;return this._resourceManager.get(D,this)}addResource(j,D){return this._resourceManager.add(j,D),this}removeResource(j){return this._resourceManager.remove(j)}async disposeResource(j){return this._resourceManager.disposeResource(j,this)}async disposeResources(){return this._resourceManager.disposeResources(this)}updateResource(j,D){let $=this.getResource(j),G=D($);return this._resourceManager.add(j,G),this._resourceManager.notifyChange(j,G,$),this}setResource(j,D){let $=this.tryGetResource(j);if(this._resourceManager.add(j,D),$!==void 0)this._resourceManager.notifyChange(j,D,$);return this}onResourceChange(j,D){return this._resourceManager.onResourceChange(j,D)}isResourceObserved(j){return this._resourceManager.isObserved(j)}getResourceKeys(){return this._resourceManager.getKeys()}resourceNeedsInitialization(j){return this._resourceManager.needsInitialization(j)}getEntity(j){return this._entityManager.getEntity(j)}getComponent(j,D){return this._entityManager.getComponent(j,D)}addComponent(j,D,$){this._entityManager.addComponent(j,D,$)}addComponents(j,D){this._entityManager.addComponents(j,D)}removeComponent(j,D){this._entityManager.removeComponent(j,D)}hasComponent(j,D){return this._entityManager.getComponent(j,D)!==void 0}spawn(j,D){let $=this._entityManager.createEntity();return this._entityManager.addComponents($.id,j),this._applyScreenScope($.id,D),$}_getActiveScopeHint(){return this._activeScopeHint}_applyScreenScope(j,D){let $=D?.scope!==void 0?D.scope:this._activeScopeHint;if($===null)return;let G=this._screenScopedEntities.get($)??new Set;G.add(j),this._screenScopedEntities.set($,G),this._entityScreenScope.set(j,$)}getEntitiesWithQuery(j,D=[],$,G){return this._entityManager.getEntitiesWithQuery(j,D,$,$?this._changeThreshold:void 0,G)}getSingleton(j,D=[]){let $=this._entityManager.getEntitiesWithQuery(j,D);if($.length===0)throw Error(`getSingleton: no entity matches query with=[${String(j)}] without=[${String(D)}]`);if($.length>1)throw Error(`getSingleton: expected 1 entity but found ${$.length} matching query with=[${String(j)}] without=[${String(D)}]`);let G=$[0];if(!G)throw Error("getSingleton: unexpected empty result");return G}tryGetSingleton(j,D=[]){let $=this._entityManager.getEntitiesWithQuery(j,D);if($.length===0)return;if($.length>1)throw Error(`tryGetSingleton: expected 0 or 1 entity but found ${$.length} matching query with=[${String(j)}] without=[${String(D)}]`);return $[0]}removeEntity(j,D){return this._entityManager.removeEntity(j,D)}spawnChild(j,D,$){let G=this._entityManager.spawnChild(j,D);return this._emitHierarchyChanged(G.id,null,j),this._applyScreenScope(G.id,$),G}setParent(j,D){let $=this._entityManager.getParent(j);return this._entityManager.setParent(j,D),this._emitHierarchyChanged(j,$,D),this}removeParent(j){let D=this._entityManager.getParent(j),$=this._entityManager.removeParent(j);if($)this._emitHierarchyChanged(j,D,null);return $}getParent(j){return this._entityManager.getParent(j)}getChildren(j){return this._entityManager.getChildren(j)}getChildAt(j,D){return this._entityManager.getChildAt(j,D)}getChildIndex(j,D){return this._entityManager.getChildIndex(j,D)}getAncestors(j){return this._entityManager.getAncestors(j)}getDescendants(j){return this._entityManager.getDescendants(j)}getRoot(j){return this._entityManager.getRoot(j)}getSiblings(j){return this._entityManager.getSiblings(j)}isDescendantOf(j,D){return this._entityManager.isDescendantOf(j,D)}isAncestorOf(j,D){return this._entityManager.isAncestorOf(j,D)}getRootEntities(){return this._entityManager.getRootEntities()}forEachInHierarchy(j,D){this._entityManager.forEachInHierarchy(j,D)}hierarchyIterator(j){return this._entityManager.hierarchyIterator(j)}_emitHierarchyChanged(j,D,$){this._eventBus.publish("hierarchyChanged",{entityId:j,oldParent:D,newParent:$})}get installedPlugins(){return Array.from(this._installedPlugins)}get entityManager(){return this._entityManager}get eventBus(){return this._finalizePendingBuilders(),this._eventBus}get commands(){return this._commandBuffer}get currentTick(){return this._currentTick}get changeThreshold(){return this._changeThreshold}enableDiagnostics(j){if(this._diagnosticsEnabled=j,!j)this._systemTimings.clear(),this._phaseTimings={preUpdate:0,fixedUpdate:0,update:0,postUpdate:0,render:0}}get diagnosticsEnabled(){return this._diagnosticsEnabled}get systemTimings(){return this._systemTimings}get phaseTimings(){return this._phaseTimings}get entityCount(){return this._entityManager.entityCount}mutateComponent(j,D,$){let G=this._entityManager.getComponent(j,D);if(G===void 0)throw Error(`Entity ${j} does not have component "${String(D)}"`);return $(G),this._entityManager.markChanged(j,D),G}markChanged(j,D){this._entityManager.markChanged(j,D)}registerDispose(j,D){this._entityManager.registerDispose(j,D)}registerRequired(j,D,$){if(String(j)===String(D))throw Error(`Cannot require a component to depend on itself: '${String(j)}'`);let G=this._requiredComponents.get(j)??[];if(G.some((J)=>J.component===D))throw Error(`Required component '${String(D)}' already registered for trigger '${String(j)}'`);this._checkRequiredCycle(j,D),G.push({component:D,factory:$}),this._requiredComponents.set(j,G)}_checkRequiredCycle(j,D){i(j,D,($)=>this._requiredComponents.get($))}onComponentAdded(j,D){return this._entityManager.onComponentAdded(j,D)}onComponentRemoved(j,D){return this._entityManager.onComponentRemoved(j,D)}addReactiveQuery(j,D){this._reactiveQueryManager.addQuery(j,D)}removeReactiveQuery(j){return this._reactiveQueryManager.removeQuery(j)}on(j,D){return this._eventBus.subscribe(j,D)}off(j,D){return this._eventBus.unsubscribe(j,D)}onPostUpdate(j){return this._postUpdateHooks.push(j),()=>{let D=this._postUpdateHooks.indexOf(j);if(D!==-1)this._postUpdateHooks.splice(D,1)}}requireAssetManager(){if(!this._assetManager)throw Error("Asset manager not configured. Use withAssets() in builder.");return this._assetManager}getAsset(j){return this.requireAssetManager().get(j)}tryGetAsset(j){return this._assetManager?.tryGet(j)}getAssetHandle(j){return this.requireAssetManager().getHandle(j)}isAssetLoaded(j){return this._assetManager?.isLoaded(j)??!1}async loadAsset(j){return this.requireAssetManager().loadAsset(j)}async loadAssetGroup(j){return this.requireAssetManager().loadAssetGroup(j)}isAssetGroupLoaded(j){return this._assetManager?.isGroupLoaded(j)??!1}getAssetGroupProgress(j){return this._assetManager?.getGroupProgress(j)??0}requireScreenManager(){if(!this._screenManager)throw Error("Screen manager not configured. Use withScreens() in builder.");return this._screenManager}async setScreen(j,D){return this.requireScreenManager().setScreen(j,D)}async pushScreen(j,D){return this.requireScreenManager().pushScreen(j,D)}async popScreen(){return this.requireScreenManager().popScreen()}getCurrentScreen(){return this._screenManager?.getCurrentScreen()??null}getScreenConfig(j){return this.requireScreenManager().getConfig(j)}tryGetScreenConfig(j){return this._screenManager?.tryGetConfig(j)??void 0}getScreenState(j){return this.requireScreenManager().getState(j)}tryGetScreenState(j){return this._screenManager?.tryGetState(j)??void 0}updateScreenState(j,D){if(typeof j==="string")this.requireScreenManager().updateState(D,j);else this.requireScreenManager().updateState(j)}isCurrentScreen(j){return this._screenManager?.isCurrent(j)??!1}isScreenActive(j){return this._screenManager?.isActive(j)??!1}getScreenStackDepth(){return this._screenManager?.getStackDepth()??0}onScreenEnter(j,D){let $=this._eventBus,G=(Z)=>{if(Z.screen!==j)return;D({config:Z.config,ecs:this})},J=$.subscribe("screenEnter",G),X=$.subscribe("screenPush",G);return()=>{J(),X()}}onScreenExit(j,D){return this._eventBus.subscribe("screenExit",(G)=>{if(G.screen!==j)return;D({ecs:this})})}_setAssetManager(j){this._assetManager=j;for(let[D,$]of this._pendingPluginAssets)this._assetManager.register(D,$);this._pendingPluginAssets=[]}_setScreenManager(j){this._screenManager=j;for(let[D,$]of this._pendingPluginScreens)this._screenManager.register(D,$);this._pendingPluginScreens=[]}_hasPendingPluginAssets(){return this._pendingPluginAssets.length>0}_hasPendingPluginScreens(){return this._pendingPluginScreens.length>0}_setFixedDt(j){this._fixedDt=j}_registerAsset(j,D){this._pendingPluginAssets.push([j,D])}_registerScreen(j,D){this._pendingPluginScreens.push([j,D])}installPlugin(j){return this._installPluginUnchecked(j)}_installPluginUnchecked(j){if(this._installedPlugins.has(j.id))return this;this._installedPlugins.add(j.id);let D=[];this._pluginCleanups.set(j.id,D);let $=(J)=>{D.push(J)},G=this._currentSystemDefaults;this._currentSystemDefaults=j.systemDefaults;try{j.install(this,$)}finally{this._currentSystemDefaults=G}return this}uninstallPlugin(j){if(!this._installedPlugins.has(j))return!1;let D=this._pluginCleanups.get(j);if(this._pluginCleanups.delete(j),this._installedPlugins.delete(j),D)for(let $=D.length-1;$>=0;$--){let G=D[$];if(!G)continue;try{G()}catch(J){console.warn(`Plugin '${j}' cleanup threw:`,J)}}return!0}dispose(){let j=Array.from(this._installedPlugins);for(let D=j.length-1;D>=0;D--){let $=j[D];if($!==void 0)this.uninstallPlugin($)}}pluginFactory(){return(j)=>E(j.id).install(j.install)}getHelpers(j){return j(this)}}function uj(j){return j}function mj(j,D){return{x:j,y:D}}function sj(){return{x:0,y:0}}function cj(j,D){return{x:j.x+D.x,y:j.y+D.y}}function ij(j,D){return{x:j.x-D.x,y:j.y-D.y}}function yj(j,D){return{x:j.x*D,y:j.y*D}}function dj(j){return{x:-j.x,y:-j.y}}function oj(j,D){return j.x*D.x+j.y*D.y}function rj(j,D){return j.x*D.y-j.y*D.x}function aj(j){return j.x*j.x+j.y*j.y}function nj(j){return Math.sqrt(j.x*j.x+j.y*j.y)}function tj(j){let D=Math.sqrt(j.x*j.x+j.y*j.y);if(D===0)return{x:0,y:0};return{x:j.x/D,y:j.y/D}}function ej(j,D){let $=j.x-D.x,G=j.y-D.y;return $*$+G*G}function j3(j,D){let $=j.x-D.x,G=j.y-D.y;return Math.sqrt($*$+G*G)}function D3(j,D,$=0.0000000001){return Math.abs(j.x-D.x)<=$&&Math.abs(j.y-D.y)<=$}function $3(j,D,$){return{x:j,y:D,z:$}}function G3(){return{x:0,y:0,z:0}}function J3(j,D){return{x:j.x+D.x,y:j.y+D.y,z:j.z+D.z}}function X3(j,D){return{x:j.x-D.x,y:j.y-D.y,z:j.z-D.z}}function Z3(j,D){return{x:j.x*D,y:j.y*D,z:j.z*D}}function W3(j){return{x:-j.x,y:-j.y,z:-j.z}}function Y3(j,D){return j.x*D.x+j.y*D.y+j.z*D.z}function L3(j,D){return{x:j.y*D.z-j.z*D.y,y:j.z*D.x-j.x*D.z,z:j.x*D.y-j.y*D.x}}function F3(j){return j.x*j.x+j.y*j.y+j.z*j.z}function _3(j){return Math.sqrt(j.x*j.x+j.y*j.y+j.z*j.z)}function A3(j){let D=Math.sqrt(j.x*j.x+j.y*j.y+j.z*j.z);if(D===0)return{x:0,y:0,z:0};return{x:j.x/D,y:j.y/D,z:j.z/D}}function B3(j,D){let $=j.x-D.x,G=j.y-D.y,J=j.z-D.z;return $*$+G*G+J*J}function O3(j,D){let $=j.x-D.x,G=j.y-D.y,J=j.z-D.z;return Math.sqrt($*$+G*G+J*J)}function U3(j,D,$=0.0000000001){return Math.abs(j.x-D.x)<=$&&Math.abs(j.y-D.y)<=$&&Math.abs(j.z-D.z)<=$}var C3=V;export{G3 as vec3Zero,X3 as vec3Sub,Z3 as vec3Scale,A3 as vec3Normalize,W3 as vec3Negate,F3 as vec3LengthSq,_3 as vec3Length,U3 as vec3Equals,Y3 as vec3Dot,B3 as vec3DistanceSq,O3 as vec3Distance,L3 as vec3Cross,J3 as vec3Add,$3 as vec3,sj as vec2Zero,ij as vec2Sub,yj as vec2Scale,tj as vec2Normalize,dj as vec2Negate,aj as vec2LengthSq,nj as vec2Length,D3 as vec2Equals,oj as vec2Dot,ej as vec2DistanceSq,j3 as vec2Distance,rj as vec2Cross,cj as vec2Add,mj as vec2,n as directValue,E as definePlugin,C3 as default,h as createScreenConfigurator,uj as createQueryDefinition,p as createAssetConfigurator,x as SystemBuilder,P as ScreenManager,z as AssetManager};
2
2
 
3
- //# debugId=14B467299BEDA26D64756E2164756E21
3
+ //# debugId=C848B384A7EB6D2064756E2164756E21
4
4
  //# sourceMappingURL=index.js.map