ecspresso 0.12.7 → 0.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +11 -0
- package/dist/index.js +2 -2
- package/dist/index.js.map +5 -5
- package/dist/plugin.d.ts +89 -22
- package/dist/plugins/audio.d.ts +2 -3
- package/dist/plugins/audio.js +2 -2
- package/dist/plugins/audio.js.map +3 -3
- package/dist/plugins/bounds.d.ts +2 -3
- package/dist/plugins/bounds.js +2 -2
- package/dist/plugins/bounds.js.map +3 -3
- package/dist/plugins/camera.d.ts +1 -2
- package/dist/plugins/camera.js +2 -2
- package/dist/plugins/camera.js.map +3 -3
- package/dist/plugins/collision.d.ts +9 -8
- package/dist/plugins/collision.js +2 -2
- package/dist/plugins/collision.js.map +4 -4
- package/dist/plugins/coroutine.d.ts +2 -3
- package/dist/plugins/coroutine.js +2 -2
- package/dist/plugins/coroutine.js.map +3 -3
- package/dist/plugins/diagnostics.d.ts +1 -3
- package/dist/plugins/diagnostics.js +2 -2
- package/dist/plugins/diagnostics.js.map +3 -3
- package/dist/plugins/input.d.ts +11 -3
- package/dist/plugins/input.js +2 -2
- package/dist/plugins/input.js.map +3 -3
- package/dist/plugins/particles.d.ts +2 -2
- package/dist/plugins/particles.js +2 -2
- package/dist/plugins/particles.js.map +3 -3
- package/dist/plugins/physics2D.d.ts +8 -5
- package/dist/plugins/physics2D.js +2 -2
- package/dist/plugins/physics2D.js.map +4 -4
- package/dist/plugins/renderers/renderer2D.d.ts +36 -9
- package/dist/plugins/renderers/renderer2D.js +2 -2
- package/dist/plugins/renderers/renderer2D.js.map +3 -3
- package/dist/plugins/spatial-index.d.ts +1 -4
- package/dist/plugins/spatial-index.js +2 -2
- package/dist/plugins/spatial-index.js.map +4 -4
- package/dist/plugins/sprite-animation.d.ts +2 -3
- package/dist/plugins/sprite-animation.js +2 -2
- package/dist/plugins/sprite-animation.js.map +3 -3
- package/dist/plugins/state-machine.d.ts +2 -3
- package/dist/plugins/state-machine.js +2 -2
- package/dist/plugins/state-machine.js.map +3 -3
- package/dist/plugins/timers.d.ts +2 -3
- package/dist/plugins/timers.js +2 -2
- package/dist/plugins/timers.js.map +3 -3
- package/dist/plugins/transform.d.ts +3 -3
- package/dist/plugins/transform.js +2 -2
- package/dist/plugins/transform.js.map +3 -3
- package/dist/plugins/tween.d.ts +2 -3
- package/dist/plugins/tween.js +2 -2
- package/dist/plugins/tween.js.map +3 -3
- package/dist/utils/narrowphase.d.ts +60 -19
- package/dist/utils/spatial-hash.d.ts +11 -1
- package/package.json +6 -3
package/dist/index.js.map
CHANGED
|
@@ -8,18 +8,18 @@
|
|
|
8
8
|
"/**\n * Resource factory with declared dependencies and optional disposal callback\n */\nexport interface ResourceFactoryWithDeps<T, Context = unknown, D extends string = string> {\n\tdependsOn?: readonly D[];\n\tfactory: (context: Context) => T | Promise<T>;\n\tonDispose?: (resource: T, context: Context) => void | Promise<void>;\n}\n\n/** @internal */\nexport const RESOURCE_DIRECT: unique symbol = Symbol('resource-direct');\n\n/**\n * Branded wrapper for storing a value as-is, bypassing factory detection.\n * The value is carried on the symbol key to avoid structural conflicts\n * with user resource types that have a `value` property.\n * Create via the `directValue()` helper.\n */\nexport interface ResourceDirectValue<T> {\n\t[RESOURCE_DIRECT]: T;\n}\n\n/**\n * Wrap a value to store it as-is, bypassing factory detection.\n * Use when the resource itself is a function or class that should not be invoked.\n *\n * @example\n * ```ts\n * import { directValue } from 'ecspresso';\n * world.addResource('handler', directValue(myFunction));\n * world.addResource('MyClass', directValue(MyClass));\n * ```\n */\nexport function directValue<T>(value: T): ResourceDirectValue<T> {\n\treturn { [RESOURCE_DIRECT]: value };\n}\n\n/**\n * Type guard for detecting { factory } pattern (with optional dependsOn and onDispose)\n */\nfunction isFactoryWithDeps<T>(resource: unknown): resource is ResourceFactoryWithDeps<T> {\n\treturn (\n\t\ttypeof resource === 'object' &&\n\t\tresource !== null &&\n\t\t'factory' in resource &&\n\t\ttypeof (resource as ResourceFactoryWithDeps<T>).factory === 'function'\n\t);\n}\n\n/**\n * Type guard for detecting { value } wrapper pattern (branded with symbol)\n */\nfunction isDirectValue<T>(resource: unknown): resource is ResourceDirectValue<T> {\n\treturn (\n\t\ttypeof resource === 'object' &&\n\t\tresource !== null &&\n\t\tRESOURCE_DIRECT in resource\n\t);\n}\n\n/**\n * Topological sort with cycle detection\n */\nfunction topologicalSort<K extends string>(\n\tkeys: readonly K[],\n\tgetDeps: (key: K) => readonly string[]\n): K[] {\n\tconst sorted: K[] = [];\n\tconst visited = new Set<K>();\n\tconst visiting = new Set<K>();\n\n\tfunction visit(key: K, path: K[] = []): void {\n\t\tif (visited.has(key)) return;\n\t\tif (visiting.has(key)) {\n\t\t\tthrow new Error(`Circular resource dependency: ${[...path, key].join(' -> ')}`);\n\t\t}\n\n\t\tvisiting.add(key);\n\t\tfor (const dep of getDeps(key)) {\n\t\t\tconst found = keys.find(k => k === dep);\n\t\t\tif (found) {\n\t\t\t\tvisit(found, [...path, key]);\n\t\t\t}\n\t\t}\n\t\tvisiting.delete(key);\n\t\tvisited.add(key);\n\t\tsorted.push(key);\n\t}\n\n\tfor (const key of keys) {\n\t\tvisit(key);\n\t}\n\treturn sorted;\n}\n\n/**\n * When Context is unknown (default), context args are optional.\n * When Context is a specific type (e.g. ECSpresso<...>), context is required.\n */\ntype ContextArgs<Context> = unknown extends Context ? [context?: Context] : [context: Context];\n\nexport default\nclass ResourceManager<\n\tResourceTypes extends Record<string, any> = Record<string, any>,\n\tContext = unknown,\n> {\n\tprivate resources: Map<keyof ResourceTypes, any> = new Map();\n\tprivate resourceFactories: Map<keyof ResourceTypes, (context: Context) => any | Promise<any>> = new Map();\n\tprivate resourceDependencies: Map<keyof ResourceTypes, readonly (keyof ResourceTypes & string)[]> = new Map();\n\tprivate resourceDisposers: Map<keyof ResourceTypes, (resource: any, context: Context) => void | Promise<void>> = new Map();\n\tprivate initializedResourceKeys: Set<keyof ResourceTypes> = new Set();\n\tprivate _changeSubscribers: Map<keyof ResourceTypes, Set<(newValue: any, oldValue: any) => void>> = new Map();\n\n\t/**\n\t * Add a resource to the manager.\n\t *\n\t * Resolution order:\n\t * 1. `{ factory, dependsOn?, onDispose? }` → factory with optional deps/disposal\n\t * 2. `{ value }` → direct value wrapper (use to store functions/classes as-is)\n\t * 3. `typeof === 'function'` → bare factory (no deps)\n\t * 4. Anything else → direct value\n\t *\n\t * @param label The resource key\n\t * @param resource The resource value, a factory function, or a factory with dependencies\n\t * @returns The resource manager instance for chaining\n\t */\n\tadd<K extends keyof ResourceTypes>(\n\t\tlabel: K,\n\t\tresource:\n\t\t\t| ResourceTypes[K]\n\t\t\t| ((context: Context) => ResourceTypes[K] | Promise<ResourceTypes[K]>)\n\t\t\t| ResourceFactoryWithDeps<ResourceTypes[K], Context, keyof ResourceTypes & string>\n\t\t\t| ResourceDirectValue<ResourceTypes[K]>,\n\t) {\n\t\tconst storeValue = (value: unknown) => {\n\t\t\tthis.resources.set(label, value);\n\t\t\tthis.initializedResourceKeys.add(label);\n\t\t\tthis.resourceDependencies.set(label, []);\n\t\t};\n\n\t\tif (isFactoryWithDeps<ResourceTypes[K]>(resource)) {\n\t\t\t// Factory with optional dependencies and/or onDispose\n\t\t\tthis.resourceFactories.set(label, resource.factory as (context: Context) => any | Promise<any>);\n\t\t\t// Type guard narrows to default D=string; the call-site constraint ensures correctness\n\t\t\tthis.resourceDependencies.set(label, (resource.dependsOn ?? []) as readonly (keyof ResourceTypes & string)[]);\n\t\t\tif (resource.onDispose) {\n\t\t\t\tthis.resourceDisposers.set(label, resource.onDispose as (resource: any, context: Context) => void | Promise<void>);\n\t\t\t}\n\t\t} else if (isDirectValue<ResourceTypes[K]>(resource)) {\n\t\t\tstoreValue(resource[RESOURCE_DIRECT]);\n\t\t} else if (typeof resource === 'function') {\n\t\t\t// Bare function → treat as factory (no dependencies)\n\t\t\tthis.resourceFactories.set(label, resource as (context: Context) => any | Promise<any>);\n\t\t\tthis.resourceDependencies.set(label, []);\n\t\t} else {\n\t\t\tstoreValue(resource);\n\t\t}\n\t\treturn this;\n\t}\n\n\t/**\n\t * Try to get a resource from the manager.\n\t * Returns the resource value if it exists, or undefined if not found.\n\t * Like `get`, initializes factory resources on first access.\n\t * @param label The resource key\n\t * @param context Context to pass to factory functions (usually the ECSpresso instance)\n\t * @returns The resource value, or undefined if not found\n\t * @see get — the throwing alternative\n\t */\n\ttryGet<K extends keyof ResourceTypes>(\n\t\tlabel: K,\n\t\t...args: ContextArgs<Context>\n\t): ResourceTypes[K] | undefined {\n\t\tif (!this.has(label)) return undefined;\n\t\treturn this.get(label, ...args);\n\t}\n\n\t/**\n\t * Get a resource from the manager\n\t * @param label The resource key\n\t * @param context Context to pass to factory functions (usually the ECSpresso instance)\n\t * @returns The resource value\n\t * @throws Error if resource not found\n\t * @see tryGet — the non-throwing alternative\n\t */\n\tget<K extends keyof ResourceTypes>(\n\t\tlabel: K,\n\t\t...args: ContextArgs<Context>\n\t): ResourceTypes[K] {\n\t\t// Check if we already have the initialized resource\n\t\tconst resource = this.resources.get(label);\n\t\tif (resource !== undefined) {\n\t\t\treturn resource;\n\t\t}\n\n\t\t// Check if we have a factory for this resource\n\t\tconst factory = this.resourceFactories.get(label);\n\t\tif (factory === undefined) {\n\t\t\tthrow new Error(`Resource ${String(label)} not found`);\n\t\t}\n\n\t\t// Initialize the resource, passing the context\n\t\tconst context = args[0] as Context;\n\t\tconst initializedResource = factory(context);\n\n\t\t// If it's not a Promise, store it immediately\n\t\tif (!(initializedResource instanceof Promise)) {\n\t\t\tthis.resources.set(label, initializedResource);\n\t\t\tthis.initializedResourceKeys.add(label);\n\t\t}\n\n\t\treturn initializedResource;\n\t}\n\n\t/**\n\t * Check if a resource exists\n\t * @param label The resource key\n\t * @returns True if the resource exists\n\t */\n\thas<K extends keyof ResourceTypes>(label: K): boolean {\n\t\treturn this.resources.has(label) || this.resourceFactories.has(label);\n\t}\n\n\t/**\n\t * Remove a resource (without calling onDispose)\n\t * @param label The resource key\n\t * @returns True if the resource was removed\n\t */\n\tremove<K extends keyof ResourceTypes>(label: K): boolean {\n\t\tconst resourceRemoved = this.resources.delete(label);\n\t\tconst factoryRemoved = this.resourceFactories.delete(label);\n\t\tthis.resourceDependencies.delete(label);\n\t\tthis.resourceDisposers.delete(label);\n\t\tthis.initializedResourceKeys.delete(label);\n\t\treturn resourceRemoved || factoryRemoved;\n\t}\n\n\t/**\n\t * Get all resource keys\n\t * @returns Array of resource keys\n\t */\n\tgetKeys(): Array<keyof ResourceTypes> {\n\t\tconst keys = new Set([\n\t\t\t...this.resources.keys(),\n\t\t\t...this.resourceFactories.keys()\n\t\t]);\n\t\treturn Array.from(keys);\n\t}\n\n\t/**\n\t * Check if a resource needs to be initialized\n\t * @param label The resource key\n\t * @returns True if the resource needs initialization\n\t */\n\tneedsInitialization<K extends keyof ResourceTypes>(label: K): boolean {\n\t\treturn this.resourceFactories.has(label) && !this.initializedResourceKeys.has(label);\n\t}\n\n\t/**\n\t * Get all resource keys that need to be initialized\n\t * @returns Array of resource keys that need initialization\n\t */\n\tgetPendingInitializationKeys(): Array<keyof ResourceTypes> {\n\t\treturn Array\n\t\t\t.from(this.resourceFactories.keys())\n\t\t\t.filter(key => !this.initializedResourceKeys.has(key));\n\t}\n\n\t/**\n\t * Initialize a specific resource if it's a factory function\n\t * @param label The resource key\n\t * @param context Context to pass to factory functions\n\t * @returns Promise that resolves when the resource is initialized\n\t */\n\tasync initializeResource<K extends keyof ResourceTypes>(\n\t\tlabel: K,\n\t\t...args: ContextArgs<Context>\n\t): Promise<void> {\n\t\tif (!this.resourceFactories.has(label) || this.initializedResourceKeys.has(label)) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst factory = this.resourceFactories.get(label);\n\t\tif (!factory) return;\n\t\tconst context = args[0] as Context;\n\t\tconst initializedResource = await factory(context);\n\t\tthis.resources.set(label, initializedResource);\n\t\tthis.initializedResourceKeys.add(label);\n\t\tthis.resourceFactories.delete(label);\n\t}\n\n\t/**\n\t * Initialize specific resources or all resources that haven't been initialized yet.\n\t * Resources are initialized in topological order based on their dependencies.\n\t * @param context Context to pass to factory functions (usually the ECSpresso instance)\n\t * @param keys Optional array of resource keys to initialize\n\t * @returns Promise that resolves when the specified resources are initialized\n\t */\n\tasync initializeResources<K extends keyof ResourceTypes>(\n\t\t...args: [...ContextArgs<Context>, ...K[]]\n\t): Promise<void> {\n\t\t// First arg is context (when Context is typed), remaining are keys\n\t\tconst keys = args.slice(1) as K[];\n\n\t\t// Determine which keys to initialize\n\t\tconst keysToInit = keys.length === 0\n\t\t\t? this.getPendingInitializationKeys()\n\t\t\t: keys;\n\n\t\t// If no keys to initialize, we're done\n\t\tif (keysToInit.length === 0) return;\n\n\t\t// Sort keys topologically based on dependencies\n\t\tconst sortedKeys = topologicalSort(\n\t\t\tkeysToInit as readonly (keyof ResourceTypes & string)[],\n\t\t\t(key) => [...(this.resourceDependencies.get(key) ?? [])]\n\t\t);\n\n\t\t// Initialize in order (sequentially to respect dependencies)\n\t\tfor (const key of sortedKeys) {\n\t\t\tawait this.initializeResource(key, ...args.slice(0, 1) as ContextArgs<Context>);\n\t\t}\n\t}\n\n\t/**\n\t * Get the dependencies of a resource\n\t * @param label The resource key\n\t * @returns Array of resource keys that this resource depends on\n\t */\n\tgetDependencies<K extends keyof ResourceTypes>(label: K): readonly (keyof ResourceTypes & string)[] {\n\t\treturn this.resourceDependencies.get(label) ?? [];\n\t}\n\n\t/**\n\t * Dispose a single resource, calling its onDispose callback if it exists\n\t * @param label The resource key to dispose\n\t * @param context Context to pass to the onDispose callback\n\t * @returns True if the resource existed and was disposed, false if it didn't exist\n\t */\n\tasync disposeResource<K extends keyof ResourceTypes>(\n\t\tlabel: K,\n\t\t...args: ContextArgs<Context>\n\t): Promise<boolean> {\n\t\tif (!this.resources.has(label) && !this.resourceFactories.has(label)) {\n\t\t\treturn false;\n\t\t}\n\n\t\t// Only call onDispose if the resource was initialized\n\t\tif (this.initializedResourceKeys.has(label)) {\n\t\t\tconst disposer = this.resourceDisposers.get(label);\n\t\t\tconst resource = this.resources.get(label);\n\t\t\tif (disposer && resource !== undefined) {\n\t\t\t\tconst context = args[0] as Context;\n\t\t\t\tawait disposer(resource, context);\n\t\t\t}\n\t\t}\n\n\t\t// Clean up all tracking\n\t\tthis.resources.delete(label);\n\t\tthis.resourceFactories.delete(label);\n\t\tthis.resourceDependencies.delete(label);\n\t\tthis.resourceDisposers.delete(label);\n\t\tthis.initializedResourceKeys.delete(label);\n\t\tthis._changeSubscribers.delete(label);\n\n\t\treturn true;\n\t}\n\n\t/**\n\t * Subscribe to changes for a specific resource key.\n\t * @param key The resource key to watch\n\t * @param callback Function called with (newValue, oldValue) when the resource changes\n\t * @returns Unsubscribe function\n\t */\n\tonResourceChange<K extends keyof ResourceTypes>(\n\t\tkey: K,\n\t\tcallback: (newValue: ResourceTypes[K], oldValue: ResourceTypes[K]) => void\n\t): () => void {\n\t\tconst existing = this._changeSubscribers.get(key);\n\t\tconst subscribers = existing ?? new Set<(newValue: any, oldValue: any) => void>();\n\t\tif (!existing) {\n\t\t\tthis._changeSubscribers.set(key, subscribers);\n\t\t}\n\t\tconst wrapped = callback as (newValue: any, oldValue: any) => void;\n\t\tsubscribers.add(wrapped);\n\n\t\treturn () => {\n\t\t\tsubscribers.delete(wrapped);\n\t\t\tif (subscribers.size === 0) {\n\t\t\t\tthis._changeSubscribers.delete(key);\n\t\t\t}\n\t\t};\n\t}\n\n\t/**\n\t * Notify subscribers of a resource value change.\n\t * Skips notification if the value is unchanged (via Object.is).\n\t * @param key The resource key that changed\n\t * @param newValue The new resource value\n\t * @param oldValue The previous resource value\n\t */\n\tnotifyChange<K extends keyof ResourceTypes>(\n\t\tkey: K,\n\t\tnewValue: ResourceTypes[K],\n\t\toldValue: ResourceTypes[K]\n\t): void {\n\t\tif (Object.is(newValue, oldValue)) return;\n\t\tconst subscribers = this._changeSubscribers.get(key);\n\t\tif (!subscribers || subscribers.size === 0) return;\n\t\tconst snapshot = [...subscribers];\n\t\tfor (const cb of snapshot) {\n\t\t\tcb(newValue, oldValue);\n\t\t}\n\t}\n\n\t/**\n\t * Dispose all initialized resources in reverse dependency order.\n\t * Resources that depend on others are disposed first.\n\t * @param context Context to pass to onDispose callbacks\n\t */\n\tasync disposeResources(\n\t\t...args: ContextArgs<Context>\n\t): Promise<void> {\n\t\t// Get only initialized resource keys\n\t\tconst initializedKeys = Array.from(this.initializedResourceKeys);\n\n\t\tif (initializedKeys.length === 0) return;\n\n\t\t// Sort in dependency order, then reverse for disposal\n\t\tconst sortedKeys = topologicalSort(\n\t\t\tinitializedKeys as readonly (keyof ResourceTypes & string)[],\n\t\t\t(key) => [...(this.resourceDependencies.get(key) ?? [])]\n\t\t).reverse();\n\n\t\t// Dispose in reverse dependency order\n\t\tfor (const key of sortedKeys) {\n\t\t\tawait this.disposeResource(key, ...args);\n\t\t}\n\t}\n}\n",
|
|
9
9
|
"import type { Entity, FilteredEntity } from \"./types\";\nimport type EntityManager from \"./entity-manager\";\n\n/**\n * Definition for a reactive query with enter/exit callbacks\n */\nexport interface ReactiveQueryDefinition<\n\tComponentTypes extends Record<string, any>,\n\tWithComponents extends keyof ComponentTypes = keyof ComponentTypes,\n\tWithoutComponents extends keyof ComponentTypes = never,\n\tOptionalComponents extends keyof ComponentTypes = never,\n> {\n\t/** Components the entity must have */\n\twith: ReadonlyArray<WithComponents>;\n\t/** Components the entity must not have */\n\twithout?: ReadonlyArray<WithoutComponents>;\n\t/** Components to include in the entity type but not require for matching */\n\toptional?: ReadonlyArray<OptionalComponents>;\n\t/** Components the entity's direct parent must have */\n\tparentHas?: ReadonlyArray<keyof ComponentTypes>;\n\t/** Called when an entity starts matching the query */\n\tonEnter?: (entity: FilteredEntity<ComponentTypes, WithComponents, WithoutComponents, OptionalComponents>) => void;\n\t/** Called when an entity stops matching the query (receives just the ID since entity may be gone) */\n\tonExit?: (entityId: number) => void;\n}\n\ninterface StoredQuery<ComponentTypes extends Record<string, any>> {\n\tdefinition: ReactiveQueryDefinition<ComponentTypes, any, any, any>;\n\tmatchingEntities: Set<number>;\n}\n\n/**\n * Manages reactive queries that trigger callbacks when entities enter/exit query matches\n */\nexport default class ReactiveQueryManager<ComponentTypes extends Record<string, any>, QueryNames extends string = string> {\n\tprivate queries: Map<string, StoredQuery<ComponentTypes>> = new Map();\n\tprivate entityManager: EntityManager<ComponentTypes>;\n\t/** Whether any registered query uses parentHas */\n\tprivate _hasParentHasQueries: boolean = false;\n\n\tconstructor(entityManager: EntityManager<ComponentTypes>) {\n\t\tthis.entityManager = entityManager;\n\t}\n\n\t/**\n\t * Whether any registered reactive query uses parentHas filters\n\t */\n\tget hasParentHasQueries(): boolean {\n\t\treturn this._hasParentHasQueries;\n\t}\n\n\t/**\n\t * Add a reactive query\n\t * @param name Unique name for the query\n\t * @param definition Query definition with callbacks\n\t */\n\taddQuery<\n\t\tWithComponents extends keyof ComponentTypes,\n\t\tWithoutComponents extends keyof ComponentTypes = never,\n\t\tOptionalComponents extends keyof ComponentTypes = never,\n\t>(\n\t\tname: QueryNames,\n\t\tdefinition: ReactiveQueryDefinition<ComponentTypes, WithComponents, WithoutComponents, OptionalComponents>\n\t): void {\n\t\tconst storedQuery: StoredQuery<ComponentTypes> = {\n\t\t\tdefinition,\n\t\t\tmatchingEntities: new Set(),\n\t\t};\n\n\t\tthis.queries.set(name, storedQuery);\n\n\t\t// Update parentHas flag\n\t\tif (definition.parentHas?.length) {\n\t\t\tthis._hasParentHasQueries = true;\n\t\t}\n\n\t\t// Check existing entities for initial matches\n\t\tconst existingMatches = this.entityManager.getEntitiesWithQuery(\n\t\t\tdefinition.with as ReadonlyArray<keyof ComponentTypes>,\n\t\t\t(definition.without ?? []) as ReadonlyArray<keyof ComponentTypes>\n\t\t);\n\n\t\tfor (const entity of existingMatches) {\n\t\t\tif (this.entityMatchesQuery(entity, storedQuery.definition)) {\n\t\t\t\tstoredQuery.matchingEntities.add(entity.id);\n\t\t\t\tstoredQuery.definition.onEnter?.(entity as FilteredEntity<ComponentTypes, any, any, any>);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Remove a reactive query\n\t * @param name Name of the query to remove\n\t * @returns true if the query existed and was removed\n\t */\n\tremoveQuery(name: QueryNames): boolean {\n\t\tconst result = this.queries.delete(name);\n\n\t\t// Recalculate parentHas flag\n\t\tif (result) {\n\t\t\tthis._recalcParentHasFlag();\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t/**\n\t * Check if an entity matches a query definition\n\t */\n\tprivate entityMatchesQuery(\n\t\tentity: Entity<ComponentTypes>,\n\t\tdefinition: ReactiveQueryDefinition<ComponentTypes, any, any, any>\n\t): boolean {\n\t\t// Check required components\n\t\tfor (const comp of definition.with) {\n\t\t\tif (!(comp in entity.components)) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\n\t\t// Check excluded components\n\t\tif (definition.without) {\n\t\t\tfor (const comp of definition.without) {\n\t\t\t\tif (comp in entity.components) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Check parentHas\n\t\tif (definition.parentHas?.length) {\n\t\t\tconst parentId = this.entityManager.getParent(entity.id);\n\t\t\tif (parentId === null) return false;\n\n\t\t\tconst parentEntity = this.entityManager.getEntity(parentId);\n\t\t\tif (!parentEntity) return false;\n\n\t\t\tfor (const comp of definition.parentHas) {\n\t\t\t\tif (!(comp in parentEntity.components)) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn true;\n\t}\n\n\t/**\n\t * Apply enter/exit transitions for a single query against an entity.\n\t * Fires onEnter when entity starts matching, onExit when it stops.\n\t */\n\tprivate _applyQueryTransition(entity: Entity<ComponentTypes>, query: StoredQuery<ComponentTypes>): void {\n\t\tconst wasMatching = query.matchingEntities.has(entity.id);\n\t\tconst nowMatches = this.entityMatchesQuery(entity, query.definition);\n\n\t\tif (!wasMatching && nowMatches) {\n\t\t\tquery.matchingEntities.add(entity.id);\n\t\t\tquery.definition.onEnter?.(entity as FilteredEntity<ComponentTypes, any, any, any>);\n\t\t} else if (wasMatching && !nowMatches) {\n\t\t\tquery.matchingEntities.delete(entity.id);\n\t\t\tquery.definition.onExit?.(entity.id);\n\t\t}\n\t}\n\n\t/**\n\t * Called when a component is added to an entity\n\t * Checks all queries for potential enter/exit events\n\t */\n\tonComponentAdded(entity: Entity<ComponentTypes>, _componentName: keyof ComponentTypes): void {\n\t\tfor (const [, query] of this.queries) {\n\t\t\tthis._applyQueryTransition(entity, query);\n\t\t}\n\n\t\tif (this._hasParentHasQueries) {\n\t\t\tthis._recheckChildren(entity.id);\n\t\t}\n\t}\n\n\t/**\n\t * Called when a component is removed from an entity\n\t * Checks all queries for potential enter/exit events\n\t */\n\tonComponentRemoved(entity: Entity<ComponentTypes>, _componentName: keyof ComponentTypes): void {\n\t\tfor (const [, query] of this.queries) {\n\t\t\tthis._applyQueryTransition(entity, query);\n\t\t}\n\n\t\tif (this._hasParentHasQueries) {\n\t\t\tthis._recheckChildren(entity.id);\n\t\t}\n\t}\n\n\t/**\n\t * Called when an entity is removed\n\t * Triggers onExit for all queries the entity was matching\n\t */\n\tonEntityRemoved(entityId: number): void {\n\t\tfor (const [_name, query] of this.queries) {\n\t\t\tif (query.matchingEntities.has(entityId)) {\n\t\t\t\tquery.matchingEntities.delete(entityId);\n\t\t\t\tquery.definition.onExit?.(entityId);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Recheck an entity against all queries (used after batch component additions)\n\t * Fires enter/exit callbacks as appropriate based on current state vs tracked state\n\t */\n\trecheckEntity(entity: Entity<ComponentTypes>): void {\n\t\tfor (const [, query] of this.queries) {\n\t\t\tthis._applyQueryTransition(entity, query);\n\t\t}\n\t}\n\n\t/**\n\t * Recheck an entity and its children against all queries.\n\t * Used after component mutations to handle both the entity's own queries\n\t * and parentHas queries on its children.\n\t */\n\trecheckEntityAndChildren(entity: Entity<ComponentTypes>): void {\n\t\tthis.recheckEntity(entity);\n\t\tif (this._hasParentHasQueries) {\n\t\t\tthis._recheckChildren(entity.id);\n\t\t}\n\t}\n\n\t/**\n\t * Recheck all children of a parent entity against parentHas queries.\n\t * Called when a component is added/removed from a parent entity.\n\t */\n\tprivate _recheckChildren(parentId: number): void {\n\t\tconst children = this.entityManager.getChildren(parentId);\n\t\tfor (const childId of children) {\n\t\t\tconst childEntity = this.entityManager.getEntity(childId);\n\t\t\tif (childEntity) {\n\t\t\t\tthis.recheckEntity(childEntity);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Recalculate the _hasParentHasQueries flag from all registered queries\n\t */\n\tprivate _recalcParentHasFlag(): void {\n\t\tthis._hasParentHasQueries = false;\n\t\tfor (const [, query] of this.queries) {\n\t\t\tif (query.definition.parentHas?.length) {\n\t\t\t\tthis._hasParentHasQueries = true;\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t}\n}\n",
|
|
10
10
|
"import type ECSpresso from './ecspresso';\nimport type { RemoveEntityOptions } from './types';\nimport type { WorldConfig, EmptyConfig } from './type-utils';\n\n/**\n * CommandBuffer queues structural changes to be executed later.\n * This prevents ordering issues when modifying entities during system execution.\n *\n * Commands are executed in FIFO order when playback() is called.\n *\n * @example\n * ```typescript\n * // In a system\n * ecs.commands.removeEntity(entityId);\n * ecs.commands.spawn({ position: { x: 0, y: 0 } });\n *\n * // Later (automatically at end of update())\n * ecs.commands.playback(ecs);\n * ```\n */\nexport default class CommandBuffer<\n\tCfg extends WorldConfig = EmptyConfig,\n> {\n\tprivate commands: Array<(ecs: ECSpresso<Cfg>) => void> = [];\n\n\t/**\n\t * Queue an entity removal command\n\t * @param entityId The entity ID to remove\n\t * @param options Optional removal options (cascade, etc.)\n\t */\n\tremoveEntity(entityId: number, options?: RemoveEntityOptions): void {\n\t\tthis.commands.push((ecs) => {\n\t\t\tecs.removeEntity(entityId, options);\n\t\t});\n\t}\n\n\t/**\n\t * Queue a component addition command\n\t * @param entityId The entity ID\n\t * @param componentName The name of the component to add\n\t * @param componentValue The component data\n\t */\n\taddComponent<K extends keyof Cfg['components']>(\n\t\tentityId: number,\n\t\tcomponentName: K,\n\t\tcomponentValue: Cfg['components'][K]\n\t): void {\n\t\tthis.commands.push((ecs) => {\n\t\t\tecs.addComponent(entityId, componentName, componentValue);\n\t\t});\n\t}\n\n\t/**\n\t * Queue a component removal command\n\t * @param entityId The entity ID\n\t * @param componentName The name of the component to remove\n\t */\n\tremoveComponent<K extends keyof Cfg['components']>(\n\t\tentityId: number,\n\t\tcomponentName: K\n\t): void {\n\t\tthis.commands.push((ecs) => {\n\t\t\tecs.removeComponent(entityId, componentName);\n\t\t});\n\t}\n\n\t/**\n\t * Queue an entity spawn command\n\t * @param components The initial components for the new entity\n\t * @returns void (entity ID not available until playback)\n\t */\n\tspawn<T extends { [K in keyof Cfg['components']]?: Cfg['components'][K] }>(\n\t\tcomponents: T & Record<Exclude<keyof T, keyof Cfg['components']>, never>\n\t): void {\n\t\tthis.commands.push((ecs) => {\n\t\t\tecs.spawn(components);\n\t\t});\n\t}\n\n\t/**\n\t * Queue a child entity spawn command\n\t * @param parentId The parent entity ID\n\t * @param components The initial components for the new child entity\n\t */\n\tspawnChild<T extends { [K in keyof Cfg['components']]?: Cfg['components'][K] }>(\n\t\tparentId: number,\n\t\tcomponents: T & Record<Exclude<keyof T, keyof Cfg['components']>, never>\n\t): void {\n\t\tthis.commands.push((ecs) => {\n\t\t\tecs.spawnChild(parentId, components);\n\t\t});\n\t}\n\n\t/**\n\t * Queue multiple component additions\n\t * @param entityId The entity ID\n\t * @param components Object with component names as keys and component data as values\n\t */\n\taddComponents<T extends { [K in keyof Cfg['components']]?: Cfg['components'][K] }>(\n\t\tentityId: number,\n\t\tcomponents: T & Record<Exclude<keyof T, keyof Cfg['components']>, never>\n\t): void {\n\t\tthis.commands.push((ecs) => {\n\t\t\tecs.addComponents(entityId, components);\n\t\t});\n\t}\n\n\t/**\n\t * Queue a parent assignment command\n\t * @param childId The child entity ID\n\t * @param parentId The parent entity ID\n\t */\n\tsetParent(childId: number, parentId: number): void {\n\t\tthis.commands.push((ecs) => {\n\t\t\tecs.setParent(childId, parentId);\n\t\t});\n\t}\n\n\t/**\n\t * Queue a component mutation command.\n\t * The mutator runs during playback, receiving the component for in-place mutation.\n\t * Automatically marks the component as changed.\n\t * @param entityId The entity ID\n\t * @param componentName The component to mutate\n\t * @param mutator A function that receives the component value for in-place mutation\n\t */\n\tmutateComponent<K extends keyof Cfg['components']>(\n\t\tentityId: number,\n\t\tcomponentName: K,\n\t\tmutator: (value: Cfg['components'][K]) => void\n\t): void {\n\t\tthis.commands.push((ecs) => {\n\t\t\tecs.mutateComponent(entityId, componentName, mutator);\n\t\t});\n\t}\n\n\t/**\n\t * Queue a markChanged command\n\t * @param entityId The entity ID\n\t * @param componentName The component to mark as changed\n\t */\n\tmarkChanged<K extends keyof Cfg['components']>(entityId: number, componentName: K): void {\n\t\tthis.commands.push((ecs) => {\n\t\t\tecs.markChanged(entityId, componentName);\n\t\t});\n\t}\n\n\t/**\n\t * Queue a parent removal command\n\t * @param childId The child entity ID\n\t */\n\tremoveParent(childId: number): void {\n\t\tthis.commands.push((ecs) => {\n\t\t\tecs.removeParent(childId);\n\t\t});\n\t}\n\n\t/**\n\t * Execute all queued commands in FIFO order.\n\t * Errors from individual commands are caught and logged, but do not stop playback.\n\t * @param ecs The ECSpresso instance to execute commands on\n\t */\n\tplayback(\n\t\tecs: ECSpresso<Cfg>\n\t): void {\n\t\t// Execute all commands, catching errors to prevent one bad command from stopping all playback\n\t\tfor (const command of this.commands) {\n\t\t\ttry {\n\t\t\t\tcommand(ecs);\n\t\t\t} catch (error) {\n\t\t\t\t// Log error but continue with remaining commands\n\t\t\t\t// This matches Unity DOTS behavior where invalid commands are silently skipped\n\t\t\t\tconsole.warn('CommandBuffer: Command failed during playback:', error);\n\t\t\t}\n\t\t}\n\n\t\t// Clear the queue\n\t\tthis.commands.length = 0;\n\t}\n\n\t/**\n\t * Clear all queued commands without executing them\n\t */\n\tclear(): void {\n\t\tthis.commands.length = 0;\n\t}\n\n\t/**\n\t * Get the number of queued commands\n\t * @returns The number of commands waiting to be executed\n\t */\n\tget length(): number {\n\t\treturn this.commands.length;\n\t}\n}\n",
|
|
11
|
-
"import type ECSpresso from './ecspresso';\nimport type { SystemPhase } from './types';\nimport type {\n\tWorldConfig,\n\tEmptyConfig,\n\tMergeConfigs,\n\
|
|
11
|
+
"import type ECSpresso from './ecspresso';\nimport type { SystemPhase } from './types';\nimport type {\n\tWorldConfig,\n\tEmptyConfig,\n\tMergeConfigs,\n\tWithComponents,\n\tWithEvents,\n\tWithResources,\n\tWithAssets,\n\tWithScreens,\n} from './type-utils';\n\n/**\n * Plugin interface for ECSpresso. A plugin is a plain object with an `install`\n * function that configures a world directly, plus phantom properties for\n * compile-time type extraction.\n *\n * @typeParam Cfg - The WorldConfig this plugin provides (components, events, resources, etc.)\n * @typeParam Requires - The WorldConfig this plugin requires from other plugins\n */\nexport interface Plugin<\n\tCfg extends WorldConfig = EmptyConfig,\n\tRequires extends WorldConfig = EmptyConfig,\n\tLabels extends string = never,\n\tGroups extends string = never,\n\tAssetGroupNames extends string = never,\n\tReactiveQueryNames extends string = never,\n> {\n\treadonly id: string;\n\treadonly install: (world: ECSpresso<MergeConfigs<Cfg, Requires>>) => void;\n\t// Phantom type for structural extraction (never set at runtime)\n\treadonly _cfg?: Cfg;\n\treadonly _requires?: Requires;\n\t// Phantom types for positional extraction (never set at runtime)\n\treadonly _labels?: Labels;\n\treadonly _groups?: Groups;\n\treadonly _assetGroupNames?: AssetGroupNames;\n\treadonly _reactiveQueryNames?: ReactiveQueryNames;\n}\n\n/**\n * Common configuration options shared by most plugins.\n * Plugin-specific options interfaces extend this with additional fields.\n */\nexport interface BasePluginOptions<G extends string = string> {\n\t/** System group name for all systems registered by this plugin */\n\tsystemGroup?: G;\n\t/** Priority for the plugin's primary system (default varies per plugin) */\n\tpriority?: number;\n\t/** Execution phase for the plugin's primary system */\n\tphase?: SystemPhase;\n}\n\n/**\n * Fluent builder for defining plugins. Mirrors `ECSpressoBuilder`'s\n * type-accumulator pattern: each `.withXxx<T>()` call threads `T` into the\n * appropriate WorldConfig slot at the type level, with no runtime cost.\n *\n * Terminal call is `.install(fn)` which returns the finalized `Plugin<...>`.\n *\n * @example\n * ```typescript\n * const myPlugin = definePlugin('my-plugin')\n * .withComponentTypes<MyComponents>()\n * .withEventTypes<MyEvents>()\n * .withResourceTypes<MyResources>()\n * .install((world) => {\n * world.addSystem('foo').setProcess(() => {});\n * });\n * ```\n */\nexport class PluginBuilder<\n\tCfg extends WorldConfig = EmptyConfig,\n\tRequires extends WorldConfig = EmptyConfig,\n\tLabels extends string = never,\n\tGroups extends string = never,\n\tAssetGroupNames extends string = never,\n\tReactiveQueryNames extends string = never,\n> {\n\tconstructor(private readonly _id: string) {}\n\n\t/**\n\t * Declare component types this plugin provides.\n\t * Pure type-level operation with no runtime cost.\n\t */\n\twithComponentTypes<T extends Record<string, any>>(): PluginBuilder<\n\t\tWithComponents<Cfg, T>,\n\t\tRequires,\n\t\tLabels,\n\t\tGroups,\n\t\tAssetGroupNames,\n\t\tReactiveQueryNames\n\t> {\n\t\treturn this as unknown as PluginBuilder<\n\t\t\tWithComponents<Cfg, T>,\n\t\t\tRequires,\n\t\t\tLabels,\n\t\t\tGroups,\n\t\t\tAssetGroupNames,\n\t\t\tReactiveQueryNames\n\t\t>;\n\t}\n\n\t/**\n\t * Declare event types this plugin provides.\n\t * Pure type-level operation with no runtime cost.\n\t */\n\twithEventTypes<T extends Record<string, any>>(): PluginBuilder<\n\t\tWithEvents<Cfg, T>,\n\t\tRequires,\n\t\tLabels,\n\t\tGroups,\n\t\tAssetGroupNames,\n\t\tReactiveQueryNames\n\t> {\n\t\treturn this as unknown as PluginBuilder<\n\t\t\tWithEvents<Cfg, T>,\n\t\t\tRequires,\n\t\t\tLabels,\n\t\t\tGroups,\n\t\t\tAssetGroupNames,\n\t\t\tReactiveQueryNames\n\t\t>;\n\t}\n\n\t/**\n\t * Declare resource types this plugin provides.\n\t * Pure type-level operation with no runtime cost.\n\t */\n\twithResourceTypes<T extends Record<string, any>>(): PluginBuilder<\n\t\tWithResources<Cfg, T>,\n\t\tRequires,\n\t\tLabels,\n\t\tGroups,\n\t\tAssetGroupNames,\n\t\tReactiveQueryNames\n\t> {\n\t\treturn this as unknown as PluginBuilder<\n\t\t\tWithResources<Cfg, T>,\n\t\t\tRequires,\n\t\t\tLabels,\n\t\t\tGroups,\n\t\t\tAssetGroupNames,\n\t\t\tReactiveQueryNames\n\t\t>;\n\t}\n\n\t/**\n\t * Declare asset types this plugin provides.\n\t * Pure type-level operation with no runtime cost.\n\t */\n\twithAssetTypes<T extends Record<string, unknown>>(): PluginBuilder<\n\t\tWithAssets<Cfg, T>,\n\t\tRequires,\n\t\tLabels,\n\t\tGroups,\n\t\tAssetGroupNames,\n\t\tReactiveQueryNames\n\t> {\n\t\treturn this as unknown as PluginBuilder<\n\t\t\tWithAssets<Cfg, T>,\n\t\t\tRequires,\n\t\t\tLabels,\n\t\t\tGroups,\n\t\t\tAssetGroupNames,\n\t\t\tReactiveQueryNames\n\t\t>;\n\t}\n\n\t/**\n\t * Declare screen types this plugin provides.\n\t * Pure type-level operation with no runtime cost.\n\t */\n\twithScreenTypes<T extends Record<string, any>>(): PluginBuilder<\n\t\tWithScreens<Cfg, T>,\n\t\tRequires,\n\t\tLabels,\n\t\tGroups,\n\t\tAssetGroupNames,\n\t\tReactiveQueryNames\n\t> {\n\t\treturn this as unknown as PluginBuilder<\n\t\t\tWithScreens<Cfg, T>,\n\t\t\tRequires,\n\t\t\tLabels,\n\t\t\tGroups,\n\t\t\tAssetGroupNames,\n\t\t\tReactiveQueryNames\n\t\t>;\n\t}\n\n\t/**\n\t * Declare system labels this plugin registers.\n\t * Pure type-level operation with no runtime cost.\n\t */\n\twithLabels<L extends string>(): PluginBuilder<\n\t\tCfg,\n\t\tRequires,\n\t\tLabels | L,\n\t\tGroups,\n\t\tAssetGroupNames,\n\t\tReactiveQueryNames\n\t> {\n\t\treturn this as unknown as PluginBuilder<\n\t\t\tCfg,\n\t\t\tRequires,\n\t\t\tLabels | L,\n\t\t\tGroups,\n\t\t\tAssetGroupNames,\n\t\t\tReactiveQueryNames\n\t\t>;\n\t}\n\n\t/**\n\t * Declare system groups this plugin uses.\n\t * Pure type-level operation with no runtime cost.\n\t */\n\twithGroups<G extends string>(): PluginBuilder<\n\t\tCfg,\n\t\tRequires,\n\t\tLabels,\n\t\tGroups | G,\n\t\tAssetGroupNames,\n\t\tReactiveQueryNames\n\t> {\n\t\treturn this as unknown as PluginBuilder<\n\t\t\tCfg,\n\t\t\tRequires,\n\t\t\tLabels,\n\t\t\tGroups | G,\n\t\t\tAssetGroupNames,\n\t\t\tReactiveQueryNames\n\t\t>;\n\t}\n\n\t/**\n\t * Declare asset group names this plugin uses.\n\t * Pure type-level operation with no runtime cost.\n\t */\n\twithAssetGroupNames<N extends string>(): PluginBuilder<\n\t\tCfg,\n\t\tRequires,\n\t\tLabels,\n\t\tGroups,\n\t\tAssetGroupNames | N,\n\t\tReactiveQueryNames\n\t> {\n\t\treturn this as unknown as PluginBuilder<\n\t\t\tCfg,\n\t\t\tRequires,\n\t\t\tLabels,\n\t\t\tGroups,\n\t\t\tAssetGroupNames | N,\n\t\t\tReactiveQueryNames\n\t\t>;\n\t}\n\n\t/**\n\t * Declare reactive query names this plugin registers.\n\t * Pure type-level operation with no runtime cost.\n\t */\n\twithReactiveQueryNames<N extends string>(): PluginBuilder<\n\t\tCfg,\n\t\tRequires,\n\t\tLabels,\n\t\tGroups,\n\t\tAssetGroupNames,\n\t\tReactiveQueryNames | N\n\t> {\n\t\treturn this as unknown as PluginBuilder<\n\t\t\tCfg,\n\t\t\tRequires,\n\t\t\tLabels,\n\t\t\tGroups,\n\t\t\tAssetGroupNames,\n\t\t\tReactiveQueryNames | N\n\t\t>;\n\t}\n\n\t/**\n\t * Declare dependencies this plugin requires from other plugins.\n\t * Accepts a pre-built `WorldConfig` type (typically a named alias like\n\t * `TransformWorldConfig`). The install callback will see these types\n\t * merged into its world parameter.\n\t * Pure type-level operation with no runtime cost.\n\t */\n\trequires<R extends WorldConfig>(): PluginBuilder<\n\t\tCfg,\n\t\tR,\n\t\tLabels,\n\t\tGroups,\n\t\tAssetGroupNames,\n\t\tReactiveQueryNames\n\t> {\n\t\treturn this as unknown as PluginBuilder<\n\t\t\tCfg,\n\t\t\tR,\n\t\t\tLabels,\n\t\t\tGroups,\n\t\t\tAssetGroupNames,\n\t\t\tReactiveQueryNames\n\t\t>;\n\t}\n\n\t/**\n\t * Terminal method. Provide the install function and receive the finalized\n\t * `Plugin<...>` object. The install function receives a world typed as\n\t * `ECSpresso<MergeConfigs<Cfg, Requires>>` — meaning it can use both the\n\t * types this plugin provides and the types it declared via `.requires<>()`.\n\t */\n\tinstall(\n\t\tinstall: (world: ECSpresso<MergeConfigs<Cfg, Requires>>) => void\n\t): Plugin<Cfg, Requires, Labels, Groups, AssetGroupNames, ReactiveQueryNames> {\n\t\treturn {\n\t\t\tid: this._id,\n\t\t\tinstall,\n\t\t} as Plugin<Cfg, Requires, Labels, Groups, AssetGroupNames, ReactiveQueryNames>;\n\t}\n}\n\n/**\n * Entry point for the fluent plugin builder. Pass the plugin id and chain\n * type-accumulator methods, terminating with `.install(fn)`.\n *\n * @example\n * ```typescript\n * const myPlugin = definePlugin('my-plugin')\n * .withComponentTypes<MyComponents>()\n * .withResourceTypes<MyResources>()\n * .install((world) => { ... });\n * ```\n */\nexport function definePlugin(id: string): PluginBuilder {\n\treturn new PluginBuilder(id);\n}\n",
|
|
12
12
|
"import type ECSpresso from \"./ecspresso\";\nimport type { FilteredEntity, QueryDefinition, System, SystemPhase } from \"./types\";\nimport type { WorldConfig, EmptyConfig } from \"./type-utils\";\n\n/**\n * Builder class for creating type-safe ECS Systems with proper query inference.\n * Systems are automatically registered with their ECSpresso instance when\n * finalized (at the start of initialize() or update()).\n */\nexport class SystemBuilder<\n\tCfg extends WorldConfig = EmptyConfig,\n\tQueries extends Record<string, QueryDefinition<Cfg['components']>> = {},\n\tLabel extends string = string,\n\tSysGroups extends string = never,\n\tResourceKeys extends keyof Cfg['resources'] = never,\n> {\n\tprivate queries: Queries = {} as Queries;\n\tprivate processFunction?: InternalProcessFunction<Cfg, Queries>;\n\tprivate detachFunction?: LifecycleFunction<Cfg>;\n\tprivate initializeFunction?: LifecycleFunction<Cfg>;\n\tprivate eventHandlers?: {\n\t\t[EventName in keyof Cfg['events']]?: (ctx: {\n\t\t\tdata: Cfg['events'][EventName];\n\t\t\tecs: ECSpresso<Cfg>;\n\t\t}) => void;\n\t};\n\tprivate _priority = 0;\n\tprivate _phase: SystemPhase = 'update';\n\tprivate _groups: string[] = [];\n\tprivate _inScreens?: ReadonlyArray<keyof Cfg['screens'] & string>;\n\tprivate _excludeScreens?: ReadonlyArray<keyof Cfg['screens'] & string>;\n\tprivate _requiredAssets?: ReadonlyArray<keyof Cfg['assets'] & string>;\n\tprivate _runWhenEmpty = false;\n\tprivate _entityEnterHandlers: Record<string, (ctx: { entity: any; ecs: any }) => void> = {};\n\tprivate _resourceKeys?: string[];\n\n\tconstructor(private _label: string) {}\n\n\tget label() {\n\t\treturn this._label;\n\t}\n\n\t/**\n\t * Create a system object with all configured properties.\n\t * @internal Used by ECSpresso to finalize and register the system\n\t */\n\t_createSystemObject(): System<Cfg, any, any> {\n\t\tconst system: System<Cfg, any, any> = {\n\t\t\tlabel: this._label,\n\t\t\tentityQueries: this.queries,\n\t\t\tpriority: this._priority,\n\t\t\tphase: this._phase,\n\t\t};\n\n\t\tif (this.processFunction) {\n\t\t\tsystem.process = this.processFunction;\n\t\t}\n\n\t\tif (this.detachFunction) {\n\t\t\tsystem.onDetach = this.detachFunction;\n\t\t}\n\n\t\tif (this.initializeFunction) {\n\t\t\tsystem.onInitialize = this.initializeFunction;\n\t\t}\n\n\t\tif (this.eventHandlers) {\n\t\t\tsystem.eventHandlers = this.eventHandlers;\n\t\t}\n\n\t\tif (this._groups.length > 0) {\n\t\t\tsystem.groups = [...this._groups];\n\t\t}\n\n\t\tif (this._inScreens) {\n\t\t\tsystem.inScreens = this._inScreens;\n\t\t}\n\n\t\tif (this._excludeScreens) {\n\t\t\tsystem.excludeScreens = this._excludeScreens;\n\t\t}\n\n\t\tif (this._requiredAssets) {\n\t\t\tsystem.requiredAssets = this._requiredAssets;\n\t\t}\n\n\t\tif (this._runWhenEmpty) {\n\t\t\tsystem.runWhenEmpty = true;\n\t\t}\n\n\t\tif (Object.keys(this._entityEnterHandlers).length > 0) {\n\t\t\tsystem.onEntityEnter = { ...this._entityEnterHandlers };\n\t\t}\n\n\t\treturn system;\n\t}\n\n\t/**\n\t * Set the priority of this system. Systems with higher priority values\n\t * execute before those with lower values. Systems with the same priority\n\t * execute in the order they were registered.\n\t * @param priority The priority value (default: 0)\n\t * @returns This SystemBuilder instance for method chaining\n\t */\n\tsetPriority(priority: number): this {\n\t\tthis._priority = priority;\n\t\treturn this;\n\t}\n\n\t/**\n\t * Set the execution phase for this system.\n\t * Systems are grouped by phase and executed in order:\n\t * preUpdate -> fixedUpdate -> update -> postUpdate -> render\n\t * @param phase The phase to assign this system to (default: 'update')\n\t * @returns This SystemBuilder instance for method chaining\n\t */\n\tinPhase(phase: SystemPhase): this {\n\t\tthis._phase = phase;\n\t\treturn this;\n\t}\n\n\t/**\n\t * Add this system to a group. Systems can belong to multiple groups.\n\t * When any group a system belongs to is disabled, the system will be skipped.\n\t * @param groupName The name of the group to add the system to\n\t * @returns This SystemBuilder instance for method chaining\n\t */\n\tinGroup<G extends string>(groupName: G): SystemBuilder<Cfg, Queries, Label, SysGroups | G, ResourceKeys> {\n\t\tif (!this._groups.includes(groupName)) {\n\t\t\tthis._groups.push(groupName);\n\t\t}\n\t\treturn this as any;\n\t}\n\n\t/**\n\t * Restrict this system to only run in specified screens.\n\t * System will be skipped during update() when the current screen\n\t * is not in this list.\n\t * @param screens Array of screen names where this system should run\n\t * @returns This SystemBuilder instance for method chaining\n\t */\n\tinScreens(screens: ReadonlyArray<keyof Cfg['screens'] & string>): this {\n\t\tthis._inScreens = [...screens];\n\t\treturn this;\n\t}\n\n\t/**\n\t * Exclude this system from running in specified screens.\n\t * System will be skipped during update() when the current screen\n\t * is in this list.\n\t * @param screens Array of screen names where this system should NOT run\n\t * @returns This SystemBuilder instance for method chaining\n\t */\n\texcludeScreens(screens: ReadonlyArray<keyof Cfg['screens'] & string>): this {\n\t\tthis._excludeScreens = [...screens];\n\t\treturn this;\n\t}\n\n\t/**\n\t * Require specific assets to be loaded for this system to run.\n\t * System will be skipped during update() if any required asset\n\t * is not loaded.\n\t * @param assets Array of asset keys that must be loaded\n\t * @returns This SystemBuilder instance for method chaining\n\t */\n\trequiresAssets(assets: ReadonlyArray<keyof Cfg['assets'] & string>): this {\n\t\tthis._requiredAssets = [...assets];\n\t\treturn this;\n\t}\n\n\t/**\n\t * Allow this system to run even when all queries return zero entities.\n\t * By default, systems with queries are skipped when no entities match.\n\t */\n\trunWhenEmpty(): this {\n\t\tthis._runWhenEmpty = true;\n\t\treturn this;\n\t}\n\n\t/**\n\t * Declare resource dependencies for this system. Resources are resolved\n\t * once (on first process call) and the same object is reused every frame.\n\t * The resolved resources are available as ctx.resources in setProcess.\n\t * @param keys Array of resource keys to resolve\n\t * @returns This SystemBuilder instance for method chaining\n\t */\n\twithResources<RK extends keyof Cfg['resources'] & string>(\n\t\tkeys: readonly RK[]\n\t): SystemBuilder<Cfg, Queries, Label, SysGroups, RK> {\n\t\t(this as any)._resourceKeys = [...keys];\n\t\treturn this as any;\n\t}\n\n\t/**\n\t * Add a query definition to the system\n\t */\n\taddQuery<\n\t\tQueryName extends string,\n\t\tWithComponents extends keyof Cfg['components'],\n\t\tWithoutComponents extends keyof Cfg['components'] = never,\n\t\tOptionalComponents extends keyof Cfg['components'] = never,\n\t\tNewQueries extends Queries & Record<QueryName, QueryDefinition<Cfg['components'], WithComponents, WithoutComponents, OptionalComponents>> =\n\t\t\tQueries & Record<QueryName, QueryDefinition<Cfg['components'], WithComponents, WithoutComponents, OptionalComponents>>\n\t>(\n\t\tname: QueryName,\n\t\tdefinition: {\n\t\t\twith: ReadonlyArray<WithComponents>;\n\t\t\twithout?: ReadonlyArray<WithoutComponents>;\n\t\t\tchanged?: ReadonlyArray<WithComponents>;\n\t\t\toptional?: ReadonlyArray<OptionalComponents>;\n\t\t\tparentHas?: ReadonlyArray<keyof Cfg['components']>;\n\t\t}\n\t): SystemBuilder<Cfg, NewQueries, Label, SysGroups, ResourceKeys> {\n\t\t// Cast is needed because TypeScript can't preserve the type information\n\t\t// when modifying an object property\n\t\tconst newBuilder = this as any;\n\t\tnewBuilder.queries = {\n\t\t\t...this.queries,\n\t\t\t[name]: definition,\n\t\t};\n\t\treturn newBuilder;\n\t}\n\n\t/**\n\t * Set the system's process function that runs each update.\n\t * The callback receives a single context object { queries, dt, ecs, resources? }.\n\t * The context is pre-allocated per system and reused every frame.\n\t * @param process Function to process entities matching the system's queries each update\n\t * @returns This SystemBuilder instance for method chaining\n\t */\n\tsetProcess(\n\t\tprocess: ProcessFunction<Cfg, Queries, ResourceKeys>\n\t): this {\n\t\tif (this._resourceKeys?.length) {\n\t\t\tconst keys = this._resourceKeys;\n\t\t\tlet resolved: Record<string, unknown> | undefined;\n\t\t\tthis.processFunction = ((ctx) => {\n\t\t\t\tif (!resolved) {\n\t\t\t\t\tresolved = {};\n\t\t\t\t\tfor (const key of keys) {\n\t\t\t\t\t\tresolved[key] = ctx.ecs.getResource(key as keyof Cfg['resources'] & string);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t(ctx as Record<string, unknown>)['resources'] = resolved;\n\t\t\t\t(process as Function)(ctx);\n\t\t\t}) as InternalProcessFunction<Cfg, Queries>;\n\t\t} else {\n\t\t\t// When ResourceKeys is never, ProcessFunction collapses to InternalProcessFunction.\n\t\t\t// TypeScript can't prove this while ResourceKeys is still generic, so cast through Function.\n\t\t\tthis.processFunction = process as unknown as InternalProcessFunction<Cfg, Queries>;\n\t\t}\n\t\treturn this;\n\t}\n\n\t/**\n\t * Register a callback that fires once per entity the first time it appears\n\t * in a query's results. Fires before process. Automatic cleanup when entity\n\t * leaves the query so re-entry fires the callback again.\n\t * @param queryName Name of a query previously added via addQuery\n\t * @param callback Function called with the entity and ecs instance\n\t * @returns This SystemBuilder instance for method chaining\n\t */\n\tsetOnEntityEnter<QN extends keyof Queries & string>(\n\t\tqueryName: QN,\n\t\tcallback: (ctx: {\n\t\t\tentity: FilteredEntity<\n\t\t\t\tCfg['components'],\n\t\t\t\tQueries[QN] extends QueryDefinition<Cfg['components'], infer W> ? W : never,\n\t\t\t\tQueries[QN] extends QueryDefinition<Cfg['components'], any, infer WO> ? WO : never,\n\t\t\t\tQueries[QN] extends QueryDefinition<Cfg['components'], any, any, infer O> ? O : never\n\t\t\t>;\n\t\t\tecs: ECSpresso<Cfg>;\n\t\t}) => void,\n\t): this {\n\t\tthis._entityEnterHandlers[queryName] = callback;\n\t\treturn this;\n\t}\n\n\t/**\n\t * Set the onDetach lifecycle hook\n\t * Called when the system is removed from the ECS\n\t * @param onDetach Function to run when this system is detached from the ECS\n\t * @returns This SystemBuilder instance for method chaining\n\t */\n\tsetOnDetach(\n\t\tonDetach: LifecycleFunction<Cfg>\n\t): this {\n\t\tthis.detachFunction = onDetach;\n\t\treturn this;\n\t}\n\n\t/**\n\t * Set the onInitialize lifecycle hook\n\t * Called when the system is initialized via ECSpresso.initialize() method\n\t * @param onInitialize Function to run when this system is initialized\n\t * @returns This SystemBuilder instance for method chaining\n\t */\n\tsetOnInitialize(\n\t\tonInitialize: LifecycleFunction<Cfg>\n\t): this {\n\t\tthis.initializeFunction = onInitialize;\n\t\treturn this;\n\t}\n\n\t/**\n\t * Set event handlers for the system\n\t * These handlers will be automatically subscribed when the system is attached\n\t * @param handlers Object mapping event names to handler functions\n\t * @returns This SystemBuilder instance for method chaining\n\t */\n\tsetEventHandlers(\n\t\thandlers: {\n\t\t\t[EventName in keyof Cfg['events']]?: (ctx: {\n\t\t\t\tdata: Cfg['events'][EventName];\n\t\t\t\tecs: ECSpresso<Cfg>;\n\t\t\t}) => void;\n\t\t}\n\t): this {\n\t\tthis.eventHandlers = handlers;\n\t\treturn this;\n\t}\n}\n\n// Helper type definitions\n\ntype QueryResults<\n\tComponentTypes extends Record<string, any>,\n\tQueries extends Record<string, QueryDefinition<ComponentTypes>>,\n> = {\n\t[QueryName in keyof Queries]: QueryName extends string\n\t\t? FilteredEntity<\n\t\t\tComponentTypes,\n\t\t\tQueries[QueryName] extends QueryDefinition<ComponentTypes, infer W> ? W : never,\n\t\t\tQueries[QueryName] extends QueryDefinition<ComponentTypes, any, infer WO> ? WO : never,\n\t\t\tQueries[QueryName] extends QueryDefinition<ComponentTypes, any, any, infer O> ? O : never\n\t\t>[]\n\t\t: never;\n};\n\n/**\n * Context object passed to system process functions.\n * Pre-allocated per system and reused every frame (zero per-frame allocation).\n * When resources are declared via withResources(), the context includes a\n * `resources` field with the resolved values (cached once on first call).\n */\nexport type ProcessContext<\n\tCfg extends WorldConfig,\n\tQueries extends Record<string, QueryDefinition<Cfg['components']>>,\n\tResourceKeys extends keyof Cfg['resources'] = never,\n> = {\n\tqueries: QueryResults<Cfg['components'], Queries>;\n\tdt: number;\n\tecs: ECSpresso<Cfg>;\n} & ([ResourceKeys] extends [never]\n\t? {}\n\t: { resources: { readonly [K in ResourceKeys]: Cfg['resources'][K] } });\n\n/**\n * Function signature for system process methods.\n * Receives a single context object with queries, dt, ecs, and optionally resources.\n */\ntype ProcessFunction<\n\tCfg extends WorldConfig,\n\tQueries extends Record<string, QueryDefinition<Cfg['components']>>,\n\tResourceKeys extends keyof Cfg['resources'] = never,\n> = (ctx: ProcessContext<Cfg, Queries, ResourceKeys>) => void;\n\n/**\n * Internal process function used for storage on System objects.\n * When resources are declared, the SystemBuilder wraps the user's function\n * to resolve and cache resources on the context object.\n */\ntype InternalProcessFunction<\n\tCfg extends WorldConfig,\n\tQueries extends Record<string, QueryDefinition<Cfg['components']>>,\n> = (ctx: ProcessContext<Cfg, Queries, never>) => void;\n\n/**\n * Type for system lifecycle functions\n * These can be asynchronous\n */\ntype LifecycleFunction<Cfg extends WorldConfig> = (\n\tecs: ECSpresso<Cfg>,\n) => void | Promise<void>;\n",
|
|
13
13
|
"/**\n * BFS cycle detection for required component graphs.\n * Shared by ECSpresso and Plugin.\n *\n * @param trigger The component that triggers the requirement\n * @param newRequired The component about to be added as required\n * @param getRequirements Callback returning the existing requirements for a component\n * @throws Error if adding trigger→newRequired would create a cycle\n */\nexport function checkRequiredCycle<K>(\n\ttrigger: K,\n\tnewRequired: K,\n\tgetRequirements: (component: K) => Iterable<{ component: K }> | undefined,\n): void {\n\tconst visited = new Set<K>();\n\tconst stack: K[] = [newRequired];\n\n\twhile (stack.length > 0) {\n\t\tconst current = stack.pop();\n\t\tif (current === undefined) break;\n\t\tif (current === trigger) {\n\t\t\tthrow new Error(\n\t\t\t\t`Circular required component dependency: '${String(trigger)}' -> '${String(newRequired)}' -> ... -> '${String(trigger)}'`\n\t\t\t);\n\t\t}\n\t\tif (visited.has(current)) continue;\n\t\tvisited.add(current);\n\n\t\tconst reqs = getRequirements(current);\n\t\tif (reqs) {\n\t\t\tfor (const r of reqs) {\n\t\t\t\tstack.push(r.component);\n\t\t\t}\n\t\t}\n\t}\n}\n",
|
|
14
14
|
"/**\n * Asset management for ECSpresso ECS framework\n */\n\nimport type EventBus from './event-bus';\nimport type {\n\tAssetStatus,\n\tAssetDefinition,\n\tAssetHandle,\n\tAssetsResource,\n\tAssetEvents,\n\tAssetConfigurator,\n} from './asset-types';\n\ninterface AssetEntry<T> {\n\tdefinition: AssetDefinition<T>;\n\tstatus: AssetStatus;\n\tvalue?: T;\n\terror?: Error;\n\tloadPromise?: Promise<T>;\n}\n\n/**\n * Manages asset loading and access for ECSpresso\n */\nexport default class AssetManager<AssetTypes extends Record<string, unknown> = Record<string, never>, AssetGroupNames extends string = string> {\n\tprivate readonly assets: Map<keyof AssetTypes, AssetEntry<unknown>> = new Map();\n\tprivate readonly groups: Map<string, Set<keyof AssetTypes>> = new Map();\n\tprivate eventBus: EventBus<AssetEvents<keyof AssetTypes & string, AssetGroupNames>> | null = null;\n\n\t/**\n\t * Set the event bus for asset events\n\t * @internal\n\t */\n\tsetEventBus(eventBus: EventBus<AssetEvents<keyof AssetTypes & string, AssetGroupNames>>): void {\n\t\tthis.eventBus = eventBus;\n\t}\n\n\t/**\n\t * Register an asset definition\n\t */\n\tregister<K extends string, T>(\n\t\tkey: K,\n\t\tdefinition: AssetDefinition<T>\n\t): void {\n\t\tthis.assets.set(key, {\n\t\t\tdefinition,\n\t\t\tstatus: 'pending',\n\t\t});\n\n\t\tif (definition.group) {\n\t\t\tconst groupSet = this.groups.get(definition.group) ?? new Set();\n\t\t\tgroupSet.add(key);\n\t\t\tthis.groups.set(definition.group, groupSet);\n\t\t}\n\t}\n\n\t/**\n\t * Load all assets marked as eager\n\t */\n\tasync loadEagerAssets(): Promise<void> {\n\t\tconst eagerAssets: (keyof AssetTypes)[] = [];\n\n\t\tfor (const [key, entry] of this.assets) {\n\t\t\tif (entry.definition.eager && entry.status === 'pending') {\n\t\t\t\teagerAssets.push(key);\n\t\t\t}\n\t\t}\n\n\t\tawait Promise.all(eagerAssets.map(key => this.loadAsset(key)));\n\t}\n\n\t/**\n\t * Load a single asset by key\n\t */\n\tasync loadAsset<K extends keyof AssetTypes>(key: K): Promise<AssetTypes[K]> {\n\t\tconst entry = this.assets.get(key);\n\n\t\tif (!entry) {\n\t\t\tthrow new Error(`Asset '${String(key)}' not found`);\n\t\t}\n\n\t\t// Already loaded\n\t\tif (entry.status === 'loaded' && entry.value !== undefined) {\n\t\t\treturn entry.value as AssetTypes[K];\n\t\t}\n\n\t\t// Already loading - return existing promise\n\t\tif (entry.status === 'loading' && entry.loadPromise) {\n\t\t\treturn entry.loadPromise as Promise<AssetTypes[K]>;\n\t\t}\n\n\t\t// Failed - try again\n\t\tif (entry.status === 'failed') {\n\t\t\tentry.status = 'pending';\n\t\t}\n\n\t\t// Start loading\n\t\tentry.status = 'loading';\n\t\tentry.loadPromise = entry.definition.loader();\n\n\t\ttry {\n\t\t\tconst value = await entry.loadPromise;\n\t\t\tentry.value = value;\n\t\t\tentry.status = 'loaded';\n\t\t\tentry.loadPromise = undefined;\n\n\t\t\tthis.eventBus?.publish('assetLoaded', { key: key as keyof AssetTypes & string });\n\t\t\tthis.checkGroupProgress(entry.definition.group);\n\n\t\t\treturn value as AssetTypes[K];\n\t\t} catch (err) {\n\t\t\tconst error = err instanceof Error ? err : new Error(String(err));\n\t\t\tentry.status = 'failed';\n\t\t\tentry.error = error;\n\t\t\tentry.loadPromise = undefined;\n\n\t\t\tthis.eventBus?.publish('assetFailed', { key: key as keyof AssetTypes & string, error });\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\t/**\n\t * Load all assets in a group\n\t */\n\tasync loadAssetGroup(groupName: AssetGroupNames): Promise<void> {\n\t\tconst groupKeys = this.groups.get(groupName);\n\n\t\tif (!groupKeys || groupKeys.size === 0) {\n\t\t\tthrow new Error(`Asset group '${groupName}' not found or empty`);\n\t\t}\n\n\t\tawait Promise.all(\n\t\t\tArray.from(groupKeys).map(key => this.loadAsset(key))\n\t\t);\n\t}\n\n\t/**\n\t * Get a loaded asset. Throws if not loaded.\n\t */\n\tget<K extends keyof AssetTypes>(key: K): AssetTypes[K] {\n\t\tconst entry = this.assets.get(key);\n\n\t\tif (!entry) {\n\t\t\tthrow new Error(`Asset '${String(key)}' not found`);\n\t\t}\n\n\t\tif (entry.status !== 'loaded' || entry.value === undefined) {\n\t\t\tthrow new Error(`Asset '${String(key)}' is not loaded (status: ${entry.status})`);\n\t\t}\n\n\t\treturn entry.value as AssetTypes[K];\n\t}\n\n\t/**\n\t * Get a loaded asset or undefined\n\t */\n\ttryGet<K extends keyof AssetTypes>(key: K): AssetTypes[K] | undefined {\n\t\tconst entry = this.assets.get(key);\n\n\t\tif (!entry || entry.status !== 'loaded') {\n\t\t\treturn undefined;\n\t\t}\n\n\t\treturn entry.value as AssetTypes[K] | undefined;\n\t}\n\n\t/**\n\t * Get a handle to an asset with status information\n\t */\n\tgetHandle<K extends keyof AssetTypes>(key: K): AssetHandle<AssetTypes[K]> {\n\t\tconst entry = this.assets.get(key);\n\n\t\tif (!entry) {\n\t\t\tthrow new Error(`Asset '${String(key)}' not found`);\n\t\t}\n\n\t\tconst manager = this;\n\t\treturn {\n\t\t\tget status() {\n\t\t\t\treturn entry.status;\n\t\t\t},\n\t\t\tget isLoaded() {\n\t\t\t\treturn entry.status === 'loaded';\n\t\t\t},\n\t\t\tget() {\n\t\t\t\treturn manager.get(key);\n\t\t\t},\n\t\t\ttryGet() {\n\t\t\t\treturn manager.tryGet(key);\n\t\t\t},\n\t\t};\n\t}\n\n\t/**\n\t * Get the status of an asset\n\t */\n\tgetStatus<K extends keyof AssetTypes>(key: K): AssetStatus {\n\t\tconst entry = this.assets.get(key);\n\n\t\tif (!entry) {\n\t\t\tthrow new Error(`Asset '${String(key)}' not found`);\n\t\t}\n\n\t\treturn entry.status;\n\t}\n\n\t/**\n\t * Check if an asset is loaded\n\t */\n\tisLoaded<K extends keyof AssetTypes>(key: K): boolean {\n\t\tconst entry = this.assets.get(key);\n\t\treturn entry?.status === 'loaded';\n\t}\n\n\t/**\n\t * Check if all assets in a group are loaded\n\t */\n\tisGroupLoaded(groupName: AssetGroupNames): boolean {\n\t\tconst groupKeys = this.groups.get(groupName);\n\n\t\tif (!groupKeys || groupKeys.size === 0) {\n\t\t\treturn false;\n\t\t}\n\n\t\tfor (const key of groupKeys) {\n\t\t\tconst entry = this.assets.get(key);\n\t\t\tif (!entry || entry.status !== 'loaded') {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\n\t\treturn true;\n\t}\n\n\t/**\n\t * Get the loading progress of a group (0-1)\n\t */\n\tgetGroupProgress(groupName: AssetGroupNames): number {\n\t\treturn this.getGroupProgressDetails(groupName).progress;\n\t}\n\n\t/**\n\t * Get detailed group progress\n\t */\n\tgetGroupProgressDetails(groupName: AssetGroupNames): { loaded: number; total: number; progress: number } {\n\t\tconst groupKeys = this.groups.get(groupName);\n\n\t\tif (!groupKeys || groupKeys.size === 0) {\n\t\t\treturn { loaded: 0, total: 0, progress: 0 };\n\t\t}\n\n\t\tlet loaded = 0;\n\t\tfor (const key of groupKeys) {\n\t\t\tconst entry = this.assets.get(key);\n\t\t\tif (entry?.status === 'loaded') {\n\t\t\t\tloaded++;\n\t\t\t}\n\t\t}\n\n\t\tconst total = groupKeys.size;\n\t\treturn { loaded, total, progress: loaded / total };\n\t}\n\n\t/**\n\t * Check group progress and emit events\n\t */\n\tprivate checkGroupProgress(groupName: string | undefined): void {\n\t\tif (!groupName || !this.eventBus) return;\n\n\t\tconst group = groupName as AssetGroupNames;\n\t\tconst details = this.getGroupProgressDetails(group);\n\n\t\tthis.eventBus.publish('assetGroupProgress', {\n\t\t\tgroup,\n\t\t\t...details,\n\t\t});\n\n\t\tif (details.loaded === details.total) {\n\t\t\tthis.eventBus.publish('assetGroupLoaded', { group });\n\t\t}\n\t}\n\n\t/**\n\t * Create the $assets resource object\n\t */\n\tcreateResource(): AssetsResource<AssetTypes, AssetGroupNames> {\n\t\tconst manager = this;\n\t\treturn {\n\t\t\tgetStatus<K extends keyof AssetTypes>(key: K): AssetStatus {\n\t\t\t\treturn manager.getStatus(key);\n\t\t\t},\n\t\t\tisLoaded<K extends keyof AssetTypes>(key: K): boolean {\n\t\t\t\treturn manager.isLoaded(key);\n\t\t\t},\n\t\t\tisGroupLoaded(groupName: AssetGroupNames): boolean {\n\t\t\t\treturn manager.isGroupLoaded(groupName);\n\t\t\t},\n\t\t\tgetGroupProgress(groupName: AssetGroupNames): number {\n\t\t\t\treturn manager.getGroupProgress(groupName);\n\t\t\t},\n\t\t\tget<K extends keyof AssetTypes>(key: K): AssetTypes[K] {\n\t\t\t\treturn manager.get(key);\n\t\t\t},\n\t\t\ttryGet<K extends keyof AssetTypes>(key: K): AssetTypes[K] | undefined {\n\t\t\t\treturn manager.tryGet(key);\n\t\t\t},\n\t\t\tgetHandle<K extends keyof AssetTypes>(key: K): AssetHandle<AssetTypes[K]> {\n\t\t\t\treturn manager.getHandle(key);\n\t\t\t},\n\t\t};\n\t}\n\n\t/**\n\t * Get all registered asset keys\n\t */\n\tgetKeys(): Array<keyof AssetTypes> {\n\t\treturn Array.from(this.assets.keys());\n\t}\n\n\t/**\n\t * Get all group names\n\t */\n\tgetGroupNames(): string[] {\n\t\treturn Array.from(this.groups.keys());\n\t}\n\n\t/**\n\t * Get all asset keys in a group\n\t */\n\tgetGroupKeys(groupName: string): Array<keyof AssetTypes> {\n\t\tconst groupKeys = this.groups.get(groupName);\n\t\treturn groupKeys ? Array.from(groupKeys) : [];\n\t}\n}\n\n/**\n * Implementation of AssetConfigurator for builder pattern\n */\nexport class AssetConfiguratorImpl<A extends Record<string, unknown>, G extends string = never> implements AssetConfigurator<A, G> {\n\tprivate readonly manager: AssetManager<A, G>;\n\n\tconstructor(manager: AssetManager<A, G>) {\n\t\tthis.manager = manager;\n\t}\n\n\tadd<K extends string, T>(\n\t\tkey: K,\n\t\tloader: () => Promise<T>\n\t): AssetConfigurator<A & Record<K, T>, G> {\n\t\tthis.manager.register(key, { loader, eager: true });\n\t\treturn this as unknown as AssetConfigurator<A & Record<K, T>, G>;\n\t}\n\n\taddWithConfig<K extends string, T>(\n\t\tkey: K,\n\t\tdefinition: AssetDefinition<T>\n\t): AssetConfigurator<A & Record<K, T>, G> {\n\t\tthis.manager.register(key, definition);\n\t\treturn this as unknown as AssetConfigurator<A & Record<K, T>, G>;\n\t}\n\n\taddGroup<GN extends string, T extends Record<string, () => Promise<unknown>>>(\n\t\tgroupName: GN,\n\t\tassets: T\n\t): AssetConfigurator<A & { [K in keyof T]: Awaited<ReturnType<T[K]>> }, G | GN> {\n\t\tfor (const [key, loader] of Object.entries(assets)) {\n\t\t\tthis.manager.register(key, {\n\t\t\t\tloader: loader as () => Promise<unknown>,\n\t\t\t\teager: false,\n\t\t\t\tgroup: groupName,\n\t\t\t});\n\t\t}\n\t\treturn this as unknown as AssetConfigurator<A & { [K in keyof T]: Awaited<ReturnType<T[K]>> }, G | GN>;\n\t}\n\n\t/**\n\t * Get the underlying manager\n\t * @internal\n\t */\n\tgetManager(): AssetManager<A, G> {\n\t\treturn this.manager;\n\t}\n}\n\n/**\n * Create a new AssetConfigurator for builder pattern usage\n */\nexport function createAssetConfigurator<A extends Record<string, unknown> = Record<string, never>, G extends string = never>(\n\tmanager?: AssetManager<A, G>\n): AssetConfiguratorImpl<A, G> {\n\treturn new AssetConfiguratorImpl(manager ?? new AssetManager<A, G>());\n}\n",
|
|
15
15
|
"/**\n * Screen/State management for ECSpresso ECS framework\n */\n\nimport type EventBus from './event-bus';\nimport type {\n\tScreenDefinition,\n\tScreenResource,\n\tScreenEvents,\n\tScreenConfigurator,\n\tScreenStackEntry,\n\tScreenConfig,\n\tScreenState,\n} from './screen-types';\n\n/** Structural interface covering only the AssetManager methods ScreenManager uses. */\ninterface ScreenManagerAssetDeps {\n\tisLoaded(key: string): boolean;\n\tloadAsset(key: string): Promise<unknown>;\n\tisGroupLoaded(group: string): boolean;\n\tloadAssetGroup(group: string): Promise<void>;\n}\n\n/** Store definitions with W erased to `unknown` so callbacks accept unknown ecs. */\ntype ErasedDefinition = ScreenDefinition<any, any, unknown>;\n\ninterface ScreenEntry {\n\tdefinition: ErasedDefinition;\n}\n\ninterface ActiveScreen<Screens extends Record<string, ScreenDefinition<any, any>>> {\n\tname: keyof Screens;\n\tconfig: Record<string, unknown>;\n\tstate: Record<string, unknown>;\n}\n\n/**\n * Manages screen/state transitions for ECSpresso\n */\nexport default class ScreenManager<Screens extends Record<string, ScreenDefinition<any, any>> = Record<string, never>> {\n\tprivate readonly screens: Map<keyof Screens, ScreenEntry> = new Map();\n\tprivate currentScreen: ActiveScreen<Screens> | null = null;\n\tprivate screenStack: Array<ActiveScreen<Screens>> = [];\n\n\tprivate eventBus: EventBus<ScreenEvents<keyof Screens & string>> | null = null;\n\tprivate assetManager: ScreenManagerAssetDeps | null = null;\n\tprivate ecs: unknown = null;\n\n\t/**\n\t * Set dependencies for screen transitions\n\t * @internal\n\t */\n\tsetDependencies(\n\t\teventBus: EventBus<ScreenEvents<keyof Screens & string>>,\n\t\tassetManager: ScreenManagerAssetDeps | null,\n\t\tecs: unknown\n\t): void {\n\t\tthis.eventBus = eventBus;\n\t\tthis.assetManager = assetManager;\n\t\tthis.ecs = ecs;\n\t}\n\n\tprivate requireEcs(): unknown {\n\t\tif (!this.ecs) throw new Error('ScreenManager: dependencies not set. Call setDependencies() first.');\n\t\treturn this.ecs;\n\t}\n\n\t/**\n\t * Register a screen definition\n\t */\n\tregister<K extends string, Config extends Record<string, unknown>, State extends Record<string, unknown>>(\n\t\tname: K,\n\t\tdefinition: ScreenDefinition<Config, State>\n\t): void {\n\t\tthis.screens.set(name, { definition: definition as ErasedDefinition });\n\t}\n\n\t/**\n\t * Transition to a new screen, clearing the stack\n\t */\n\tasync setScreen<K extends keyof Screens>(\n\t\tname: K,\n\t\tconfig: Screens[K] extends ScreenDefinition<infer C, any> ? C : never\n\t): Promise<void> {\n\t\tconst entry = this.screens.get(name);\n\n\t\tif (!entry) {\n\t\t\tthrow new Error(`Screen '${String(name)}' not found`);\n\t\t}\n\n\t\t// Verify required assets\n\t\tawait this.verifyRequiredAssets(entry.definition.requiredAssets, entry.definition.requiredAssetGroups);\n\n\t\t// Exit all screens in stack (bottom to top order)\n\t\twhile (this.screenStack.length > 0) {\n\t\t\tconst stackScreen = this.screenStack.pop();\n\t\t\tif (stackScreen) {\n\t\t\t\tawait this.exitScreen(stackScreen.name);\n\t\t\t}\n\t\t}\n\n\t\t// Exit current screen\n\t\tif (this.currentScreen) {\n\t\t\tawait this.exitScreen(this.currentScreen.name);\n\t\t}\n\n\t\t// Enter new screen\n\t\tconst state = entry.definition.initialState(config);\n\t\tthis.currentScreen = {\n\t\t\tname,\n\t\t\tconfig: config as Record<string, unknown>,\n\t\t\tstate,\n\t\t};\n\n\t\tawait entry.definition.onEnter?.({ config, ecs: this.requireEcs() });\n\t\tthis.eventBus?.publish('screenEnter', { screen: name as keyof Screens & string, config });\n\t}\n\n\t/**\n\t * Push a screen onto the stack (overlay)\n\t */\n\tasync pushScreen<K extends keyof Screens>(\n\t\tname: K,\n\t\tconfig: Screens[K] extends ScreenDefinition<infer C, any> ? C : never\n\t): Promise<void> {\n\t\tconst entry = this.screens.get(name);\n\n\t\tif (!entry) {\n\t\t\tthrow new Error(`Screen '${String(name)}' not found`);\n\t\t}\n\n\t\t// Verify required assets\n\t\tawait this.verifyRequiredAssets(entry.definition.requiredAssets, entry.definition.requiredAssetGroups);\n\n\t\t// Push current screen to stack\n\t\tif (this.currentScreen) {\n\t\t\tthis.screenStack.push(this.currentScreen);\n\t\t}\n\n\t\t// Enter new screen\n\t\tconst state = entry.definition.initialState(config);\n\t\tthis.currentScreen = {\n\t\t\tname,\n\t\t\tconfig: config as Record<string, unknown>,\n\t\t\tstate,\n\t\t};\n\n\t\tawait entry.definition.onEnter?.({ config, ecs: this.requireEcs() });\n\t\tthis.eventBus?.publish('screenPush', { screen: name as keyof Screens & string, config });\n\t}\n\n\t/**\n\t * Pop the current screen and return to the previous one\n\t */\n\tasync popScreen(): Promise<void> {\n\t\tif (this.screenStack.length === 0) {\n\t\t\tthrow new Error('Cannot pop screen: stack is empty');\n\t\t}\n\n\t\t// Exit current screen\n\t\tif (this.currentScreen) {\n\t\t\tawait this.exitScreen(this.currentScreen.name);\n\t\t\tthis.eventBus?.publish('screenPop', { screen: this.currentScreen.name as keyof Screens & string });\n\t\t}\n\n\t\t// Restore previous screen from stack\n\t\tthis.currentScreen = this.screenStack.pop() ?? null;\n\t}\n\n\t/**\n\t * Exit a screen by name (internal helper)\n\t */\n\tprivate async exitScreen(name: keyof Screens): Promise<void> {\n\t\tconst entry = this.screens.get(name);\n\t\tif (entry?.definition.onExit) {\n\t\t\tawait entry.definition.onExit(this.requireEcs());\n\t\t}\n\t\tthis.eventBus?.publish('screenExit', { screen: name as keyof Screens & string });\n\t}\n\n\t/**\n\t * Verify required assets are loaded before screen transition\n\t */\n\tprivate async verifyRequiredAssets(\n\t\tassets?: ReadonlyArray<string>,\n\t\tgroups?: ReadonlyArray<string>,\n\t): Promise<void> {\n\t\tif (!this.assetManager) return;\n\n\t\tif (assets) {\n\t\t\tfor (const assetKey of assets) {\n\t\t\t\tif (!this.assetManager.isLoaded(assetKey)) {\n\t\t\t\t\tawait this.assetManager.loadAsset(assetKey);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (groups) {\n\t\t\tfor (const groupName of groups) {\n\t\t\t\tif (!this.assetManager.isGroupLoaded(groupName)) {\n\t\t\t\t\tawait this.assetManager.loadAssetGroup(groupName);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Get the current screen name\n\t */\n\tgetCurrentScreen(): keyof Screens | null {\n\t\treturn this.currentScreen?.name ?? null;\n\t}\n\n\t/**\n\t * Get the current screen config (immutable).\n\t * If `screen` is provided, asserts that the current screen matches.\n\t */\n\tgetConfig(screen?: keyof Screens): Readonly<ScreenConfig<Screens[keyof Screens]>> {\n\t\tif (!this.currentScreen) {\n\t\t\tthrow new Error('No current screen');\n\t\t}\n\t\tif (screen !== undefined && this.currentScreen.name !== screen) {\n\t\t\tthrow new Error(`Expected current screen '${String(screen)}', but current is '${String(this.currentScreen.name)}'`);\n\t\t}\n\t\treturn this.currentScreen.config as Readonly<ScreenConfig<Screens[keyof Screens]>>;\n\t}\n\n\t/**\n\t * Get the current screen config or undefined.\n\t * If `screen` is provided, returns undefined when the current screen doesn't match.\n\t */\n\ttryGetConfig(screen?: keyof Screens): Readonly<ScreenConfig<Screens[keyof Screens]>> | undefined {\n\t\tif (!this.currentScreen) return undefined;\n\t\tif (screen !== undefined && this.currentScreen.name !== screen) return undefined;\n\t\treturn this.currentScreen.config as Readonly<ScreenConfig<Screens[keyof Screens]>>;\n\t}\n\n\t/**\n\t * Get the current screen state (mutable).\n\t * If `screen` is provided, asserts that the current screen matches.\n\t */\n\tgetState(screen?: keyof Screens): ScreenState<Screens[keyof Screens]> {\n\t\tif (!this.currentScreen) {\n\t\t\tthrow new Error('No current screen');\n\t\t}\n\t\tif (screen !== undefined && this.currentScreen.name !== screen) {\n\t\t\tthrow new Error(`Expected current screen '${String(screen)}', but current is '${String(this.currentScreen.name)}'`);\n\t\t}\n\t\treturn this.currentScreen.state as ScreenState<Screens[keyof Screens]>;\n\t}\n\n\t/**\n\t * Get the current screen state or undefined.\n\t * If `screen` is provided, returns undefined when the current screen doesn't match.\n\t */\n\ttryGetState(screen?: keyof Screens): ScreenState<Screens[keyof Screens]> | undefined {\n\t\tif (!this.currentScreen) return undefined;\n\t\tif (screen !== undefined && this.currentScreen.name !== screen) return undefined;\n\t\treturn this.currentScreen.state as ScreenState<Screens[keyof Screens]>;\n\t}\n\n\t/**\n\t * Update the current screen state.\n\t * If `screen` is provided, asserts that the current screen matches.\n\t */\n\tupdateState(update: unknown, screen?: keyof Screens): void {\n\t\tif (!this.currentScreen) {\n\t\t\tthrow new Error('No current screen');\n\t\t}\n\t\tif (screen !== undefined && this.currentScreen.name !== screen) {\n\t\t\tthrow new Error(`Expected current screen '${String(screen)}', but current is '${String(this.currentScreen.name)}'`);\n\t\t}\n\n\t\tconst partial = typeof update === 'function'\n\t\t\t? (update as (current: Record<string, unknown>) => Record<string, unknown>)(this.currentScreen.state)\n\t\t\t: update;\n\n\t\tthis.currentScreen.state = {\n\t\t\t...this.currentScreen.state,\n\t\t\t...(partial as Record<string, unknown>),\n\t\t};\n\t}\n\n\t/**\n\t * Get the screen stack depth\n\t */\n\tgetStackDepth(): number {\n\t\treturn this.screenStack.length;\n\t}\n\n\t/**\n\t * Check if current screen is an overlay\n\t */\n\tisOverlay(): boolean {\n\t\treturn this.screenStack.length > 0;\n\t}\n\n\t/**\n\t * Check if a screen is active (current or in stack)\n\t */\n\tisActive(screenName: keyof Screens): boolean {\n\t\tif (this.currentScreen?.name === screenName) {\n\t\t\treturn true;\n\t\t}\n\t\treturn this.screenStack.some(s => s.name === screenName);\n\t}\n\n\t/**\n\t * Check if a screen is the current screen\n\t */\n\tisCurrent(screenName: keyof Screens): boolean {\n\t\treturn this.currentScreen?.name === screenName;\n\t}\n\n\t/**\n\t * Create the $screen resource object\n\t */\n\tcreateResource(): ScreenResource<Screens> {\n\t\tconst manager = this;\n\t\treturn {\n\t\t\tget current(): keyof Screens | null {\n\t\t\t\treturn manager.getCurrentScreen();\n\t\t\t},\n\t\t\tget config(): Readonly<ScreenConfig<Screens[keyof Screens]>> | null {\n\t\t\t\treturn manager.tryGetConfig() ?? null;\n\t\t\t},\n\t\t\tget state(): ScreenState<Screens[keyof Screens]> | null {\n\t\t\t\treturn manager.tryGetState() ?? null;\n\t\t\t},\n\t\t\tset state(value: ScreenState<Screens[keyof Screens]> | null) {\n\t\t\t\tif (manager.currentScreen && value !== null) {\n\t\t\t\t\tmanager.currentScreen.state = value as Record<string, unknown>;\n\t\t\t\t}\n\t\t\t},\n\t\t\tget stack(): ReadonlyArray<ScreenStackEntry<Screens>> {\n\t\t\t\treturn manager.screenStack as unknown as ReadonlyArray<ScreenStackEntry<Screens>>;\n\t\t\t},\n\t\t\tget isOverlay(): boolean {\n\t\t\t\treturn manager.isOverlay();\n\t\t\t},\n\t\t\tget stackDepth(): number {\n\t\t\t\treturn manager.getStackDepth();\n\t\t\t},\n\t\t\tisActive(screenName: keyof Screens): boolean {\n\t\t\t\treturn manager.isActive(screenName);\n\t\t\t},\n\t\t\tisCurrent(screenName: keyof Screens): boolean {\n\t\t\t\treturn manager.isCurrent(screenName);\n\t\t\t},\n\t\t};\n\t}\n\n\t/**\n\t * Get all registered screen names\n\t */\n\tgetScreenNames(): Array<keyof Screens> {\n\t\treturn Array.from(this.screens.keys());\n\t}\n\n\t/**\n\t * Check if a screen is registered\n\t */\n\thasScreen(name: keyof Screens): boolean {\n\t\treturn this.screens.has(name);\n\t}\n}\n\n/**\n * Implementation of ScreenConfigurator for builder pattern\n */\nexport class ScreenConfiguratorImpl<Screens extends Record<string, ScreenDefinition<any, any>>, W = unknown> implements ScreenConfigurator<Screens, W> {\n\tprivate readonly manager: ScreenManager<Screens>;\n\n\tconstructor(manager: ScreenManager<Screens>) {\n\t\tthis.manager = manager;\n\t}\n\n\tadd<K extends string, Config extends Record<string, unknown>, State extends Record<string, unknown>>(\n\t\tname: K,\n\t\tdefinition: ScreenDefinition<Config, State, W>\n\t): ScreenConfigurator<Screens & Record<K, ScreenDefinition<Config, State, W>>, W> {\n\t\tthis.manager.register(name, definition as ScreenDefinition<Config, State>);\n\t\treturn this as unknown as ScreenConfigurator<Screens & Record<K, ScreenDefinition<Config, State, W>>, W>;\n\t}\n\n\t/**\n\t * Get the underlying manager\n\t * @internal\n\t */\n\tgetManager(): ScreenManager<Screens> {\n\t\treturn this.manager;\n\t}\n}\n\n/**\n * Create a new ScreenConfigurator for builder pattern usage\n */\nexport function createScreenConfigurator<Screens extends Record<string, ScreenDefinition<any, any>> = Record<string, never>, W = unknown>(\n\tmanager?: ScreenManager<Screens>\n): ScreenConfiguratorImpl<Screens, W> {\n\treturn new ScreenConfiguratorImpl<Screens, W>(manager ?? new ScreenManager<Screens>());\n}\n",
|
|
16
|
-
"import ECSpresso from \"./ecspresso\";\nimport AssetManager, { AssetConfiguratorImpl, createAssetConfigurator } from \"./asset-manager\";\nimport ScreenManager, { ScreenConfiguratorImpl, createScreenConfigurator } from \"./screen-manager\";\nimport type { ResourceFactoryWithDeps, ResourceDirectValue } from \"./resource-manager\";\nimport { definePlugin, type Plugin } from \"./plugin\";\nimport type { WorldConfig, EmptyConfig, ConfigsAreCompatible, MergeConfigs, TypesAreCompatible, RequirementsSatisfied, WithComponents, WithEvents, WithResources } from \"./type-utils\";\nimport type { AssetConfigurator, AssetsResource } from \"./asset-types\";\nimport type { ScreenDefinition, ScreenConfigurator, ScreenResource } from \"./screen-types\";\n\n/**\n * Helper type: finalize built-in resources ($assets, $screen) in the resource map.\n * Auto-injects $assets/$screen when plugins contribute asset/screen types even without\n * explicit withAssets()/withScreens(). Also narrows the AssetGroupNames on $assets.\n */\ntype FinalizeBuiltinResources<Cfg extends WorldConfig, AG extends string> = {\n\treadonly components: Cfg['components'];\n\treadonly events: Cfg['events'];\n\treadonly resources: Omit<Cfg['resources'], '$assets' | '$screen'>\n\t\t& ([keyof Cfg['assets']] extends [never] ? {} : { $assets: AssetsResource<Cfg['assets'], AG> })\n\t\t& ([keyof Cfg['screens']] extends [never] ? {} : { $screen: ScreenResource<Cfg['screens']> });\n\treadonly assets: Cfg['assets'];\n\treadonly screens: Cfg['screens'];\n};\n\n/**\n\t* Builder class for ECSpresso that provides fluent type-safe plugin installation.\n\t* Handles type checking during build process to ensure type safety.\n*/\nexport class ECSpressoBuilder<\n\tCfg extends WorldConfig = EmptyConfig,\n\tLabels extends string = never,\n\tGroups extends string = never,\n\tAssetGroupNames extends string = never,\n\tReactiveQueryNames extends string = never,\n> {\n\t/** Asset configurator for collecting asset definitions */\n\tprivate assetConfigurator: AssetConfiguratorImpl<Cfg['assets']> | null = null;\n\t/** Screen configurator for collecting screen definitions */\n\tprivate screenConfigurator: ScreenConfiguratorImpl<Cfg['screens']> | null = null;\n\t/** Pending resources to add during build */\n\tprivate pendingResources: Array<{ key: string; value: unknown }> = [];\n\t/** Pending dispose callbacks to register during build */\n\tprivate pendingDisposeCallbacks: Array<{ key: string; callback: (ctx: { value: unknown; entityId: number }) => void }> = [];\n\t/** Pending required component registrations to apply during build */\n\tprivate pendingRequiredComponents: Array<{ trigger: string; required: string; factory: (triggerValue: any) => unknown }> = [];\n\t/** Pending plugins to install during build */\n\tprivate pendingPlugins: Plugin<any, any, any, any, any, any>[] = [];\n\t/** Fixed timestep interval (null means use default 1/60) */\n\tprivate _fixedDt: number | null = null;\n\n\tconstructor() {}\n\n\t/**\n\t\t* Add the first plugin when starting with empty types.\n\t\t* This overload allows any plugin to be added to an empty ECSpresso instance.\n\t\t* Only merges the plugin's Provides (PCfg) into accumulated config, not its Requires (PReq).\n\t*/\n\twithPlugin<\n\t\tPCfg extends WorldConfig,\n\t\tPReq extends WorldConfig = EmptyConfig,\n\t\tBL extends string = never,\n\t\tBG extends string = never,\n\t\tBAG extends string = never,\n\t\tBRQ extends string = never,\n\t>(\n\t\tthis: ECSpressoBuilder<{ readonly components: {}; readonly events: {}; readonly resources: {}; readonly assets: Cfg['assets']; readonly screens: Cfg['screens'] }, Labels, Groups, AssetGroupNames, ReactiveQueryNames>,\n\t\tplugin: Plugin<PCfg, PReq, BL, BG, BAG, BRQ>\n\t): ECSpressoBuilder<{\n\t\treadonly components: PCfg['components'];\n\t\treadonly events: PCfg['events'];\n\t\treadonly resources: PCfg['resources'];\n\t\treadonly assets: Cfg['assets'] & PCfg['assets'];\n\t\treadonly screens: Cfg['screens'] & PCfg['screens'];\n\t}, Labels | BL, Groups | BG, AssetGroupNames | BAG, ReactiveQueryNames | BRQ>;\n\n\t/**\n\t\t* Add a subsequent plugin with type checking.\n\t\t* This overload enforces plugin type compatibility and requirement satisfaction.\n\t\t* Only merges the plugin's Provides (PCfg) into accumulated config, not its Requires (PReq).\n\t*/\n\twithPlugin<\n\t\tPCfg extends WorldConfig,\n\t\tPReq extends WorldConfig = EmptyConfig,\n\t\tBL extends string = never,\n\t\tBG extends string = never,\n\t\tBAG extends string = never,\n\t\tBRQ extends string = never,\n\t>(\n\t\tplugin: ConfigsAreCompatible<Cfg, PCfg> extends true\n\t\t\t? RequirementsSatisfied<Cfg, PReq> extends true\n\t\t\t\t? Plugin<PCfg, PReq, BL, BG, BAG, BRQ>\n\t\t\t\t: never\n\t\t\t: never\n\t): ECSpressoBuilder<MergeConfigs<Cfg, PCfg>, Labels | BL, Groups | BG, AssetGroupNames | BAG, ReactiveQueryNames | BRQ>;\n\n\t/**\n\t\t* Implementation of both overloads.\n\t\t* Since the type compatibility is checked in the method signature,\n\t\t* we can safely assume the plugin is compatible here.\n\t*/\n\twithPlugin<\n\t\tPCfg extends WorldConfig,\n\t\tPReq extends WorldConfig = EmptyConfig,\n\t\tBL extends string = never,\n\t\tBG extends string = never,\n\t\tBAG extends string = never,\n\t\tBRQ extends string = never,\n\t>(\n\t\tplugin: Plugin<PCfg, PReq, BL, BG, BAG, BRQ>\n\t): ECSpressoBuilder<MergeConfigs<Cfg, PCfg>, Labels | BL, Groups | BG, AssetGroupNames | BAG, ReactiveQueryNames | BRQ> {\n\t\t// Defer plugin installation to build time\n\t\tthis.pendingPlugins.push(plugin);\n\n\t\t// Return a builder with the updated type parameters\n\t\treturn this as unknown as ECSpressoBuilder<MergeConfigs<Cfg, PCfg>, Labels | BL, Groups | BG, AssetGroupNames | BAG, ReactiveQueryNames | BRQ>;\n\t}\n\n\t/**\n\t * Add application-specific component types to the builder chain.\n\t * This is a pure type-level operation with no runtime cost.\n\t * Conflicts with existing component types (same key, different type) produce a `never` return.\n\t */\n\twithComponentTypes<T extends Record<string, any>>(): TypesAreCompatible<Cfg['components'], T> extends true\n\t\t? ECSpressoBuilder<WithComponents<Cfg, T>, Labels, Groups, AssetGroupNames, ReactiveQueryNames>\n\t\t: never;\n\twithComponentTypes<T extends Record<string, any>>(): ECSpressoBuilder<WithComponents<Cfg, T>, Labels, Groups, AssetGroupNames, ReactiveQueryNames> {\n\t\treturn this as unknown as ECSpressoBuilder<WithComponents<Cfg, T>, Labels, Groups, AssetGroupNames, ReactiveQueryNames>;\n\t}\n\n\t/**\n\t * Add application-specific event types to the builder chain.\n\t * This is a pure type-level operation with no runtime cost.\n\t * Conflicts with existing event types (same key, different type) produce a `never` return.\n\t */\n\twithEventTypes<T extends Record<string, any>>(): TypesAreCompatible<Cfg['events'], T> extends true\n\t\t? ECSpressoBuilder<WithEvents<Cfg, T>, Labels, Groups, AssetGroupNames, ReactiveQueryNames>\n\t\t: never;\n\twithEventTypes<T extends Record<string, any>>(): ECSpressoBuilder<WithEvents<Cfg, T>, Labels, Groups, AssetGroupNames, ReactiveQueryNames> {\n\t\treturn this as unknown as ECSpressoBuilder<WithEvents<Cfg, T>, Labels, Groups, AssetGroupNames, ReactiveQueryNames>;\n\t}\n\n\t/**\n\t * Add application-specific resource types to the builder chain.\n\t * This is a pure type-level operation with no runtime cost.\n\t * Conflicts with existing resource types (same key, different type) produce a `never` return.\n\t */\n\twithResourceTypes<T extends Record<string, any>>(): TypesAreCompatible<Cfg['resources'], T> extends true\n\t\t? ECSpressoBuilder<WithResources<Cfg, T>, Labels, Groups, AssetGroupNames, ReactiveQueryNames>\n\t\t: never;\n\twithResourceTypes<T extends Record<string, any>>(): ECSpressoBuilder<WithResources<Cfg, T>, Labels, Groups, AssetGroupNames, ReactiveQueryNames> {\n\t\treturn this as unknown as ECSpressoBuilder<WithResources<Cfg, T>, Labels, Groups, AssetGroupNames, ReactiveQueryNames>;\n\t}\n\n\t/**\n\t * Add a resource during ECSpresso construction.\n\t *\n\t * When the key matches a pre-declared resource type (via `withResourceTypes`, `create<C,E,R>()`,\n\t * or plugin resources), the value is validated against that type.\n\t * For new keys, the value type is inferred as before.\n\t *\n\t * @param key The resource key\n\t * @param resource The resource value, factory function, or factory with dependencies/disposal\n\t * @returns This builder with updated resource types\n\t */\n\twithResource<K extends keyof Cfg['resources'] & string>(\n\t\tkey: K,\n\t\tresource: Cfg['resources'][K] | ((context: ECSpresso<Cfg>) => Cfg['resources'][K] | Promise<Cfg['resources'][K]>) | ResourceFactoryWithDeps<Cfg['resources'][K], ECSpresso<Cfg>, keyof Cfg['resources'] & string> | ResourceDirectValue<Cfg['resources'][K]>\n\t): ECSpressoBuilder<Cfg, Labels, Groups, AssetGroupNames, ReactiveQueryNames>;\n\twithResource<K extends string, V>(\n\t\tkey: K & ([K] extends [keyof Cfg['resources']] ? [V] extends [Cfg['resources'][K & keyof Cfg['resources']]] ? string : never : string),\n\t\tresource: V | ((context: ECSpresso<WithResources<Cfg, Record<K, V>>>) => V | Promise<V>) | ResourceFactoryWithDeps<V, ECSpresso<WithResources<Cfg, Record<K, V>>>, keyof (Cfg['resources'] & Record<K, V>) & string> | ResourceDirectValue<V>\n\t): ECSpressoBuilder<WithResources<Cfg, Record<K, V>>, Labels, Groups, AssetGroupNames, ReactiveQueryNames>;\n\twithResource(key: string, resource: unknown): ECSpressoBuilder<any, Labels, Groups, AssetGroupNames, ReactiveQueryNames> {\n\t\tthis.pendingResources.push({ key, value: resource });\n\t\treturn this as unknown as ECSpressoBuilder<any, Labels, Groups, AssetGroupNames, ReactiveQueryNames>;\n\t}\n\n\t/**\n\t * Register a dispose callback for a component type during build.\n\t * Called when a component is removed (explicit removal, entity destruction, or replacement).\n\t * @param componentName The component type to register disposal for\n\t * @param callback Function receiving the component value being disposed\n\t * @returns This builder for method chaining\n\t */\n\twithDispose<K extends keyof Cfg['components'] & string>(\n\t\tcomponentName: K,\n\t\tcallback: (ctx: { value: Cfg['components'][K]; entityId: number }) => void\n\t): this {\n\t\tthis.pendingDisposeCallbacks.push({ key: componentName, callback: callback as (ctx: { value: unknown; entityId: number }) => void });\n\t\treturn this;\n\t}\n\n\t/**\n\t * Register a required component relationship during build.\n\t * When an entity gains `trigger`, the `required` component is auto-added\n\t * (using `factory` for the default value) if not already present.\n\t * @param trigger The component whose presence triggers auto-addition\n\t * @param required The component to auto-add\n\t * @param factory Function that creates the default value for the required component\n\t * @returns This builder for method chaining\n\t */\n\twithRequired<\n\t\tTrigger extends keyof Cfg['components'] & string,\n\t\tRequired extends keyof Cfg['components'] & string,\n\t>(\n\t\ttrigger: Trigger,\n\t\trequired: Required,\n\t\tfactory: (triggerValue: Cfg['components'][Trigger]) => Cfg['components'][Required]\n\t): this {\n\t\tthis.pendingRequiredComponents.push({\n\t\t\ttrigger,\n\t\t\trequired,\n\t\t\tfactory: factory as (triggerValue: any) => unknown,\n\t\t});\n\t\treturn this;\n\t}\n\n\t/**\n\t * Configure assets for this ECSpresso instance\n\t * @param configurator Function that receives an AssetConfigurator and returns it after adding assets\n\t * @returns This builder with updated asset types\n\t */\n\twithAssets<NewA extends Record<string, unknown>, NewG extends string = never>(\n\t\tconfigurator: (assets: AssetConfigurator<{}, never>) => AssetConfigurator<NewA, NewG>\n\t): ECSpressoBuilder<{\n\t\treadonly components: Cfg['components'];\n\t\treadonly events: Cfg['events'];\n\t\treadonly resources: Cfg['resources'] & { $assets: AssetsResource<Cfg['assets'] & NewA, string> };\n\t\treadonly assets: Cfg['assets'] & NewA;\n\t\treadonly screens: Cfg['screens'];\n\t}, Labels, Groups, AssetGroupNames | NewG, ReactiveQueryNames> {\n\t\tconst assetConfig = createAssetConfigurator<{}, never>();\n\t\tconfigurator(assetConfig);\n\t\tthis.assetConfigurator = assetConfig as unknown as AssetConfiguratorImpl<Cfg['assets']>;\n\t\treturn this as unknown as ECSpressoBuilder<{\n\t\t\treadonly components: Cfg['components'];\n\t\t\treadonly events: Cfg['events'];\n\t\t\treadonly resources: Cfg['resources'] & { $assets: AssetsResource<Cfg['assets'] & NewA, string> };\n\t\t\treadonly assets: Cfg['assets'] & NewA;\n\t\t\treadonly screens: Cfg['screens'];\n\t\t}, Labels, Groups, AssetGroupNames | NewG, ReactiveQueryNames>;\n\t}\n\n\t/**\n\t * Configure screens for this ECSpresso instance\n\t * @param configurator Function that receives a ScreenConfigurator and returns it after adding screens\n\t * @returns This builder with updated screen types\n\t */\n\twithScreens<NewS extends Record<string, ScreenDefinition<any, any>>>(\n\t\tconfigurator: (screens: ScreenConfigurator<{}, ECSpresso<{\n\t\t\treadonly components: Cfg['components'];\n\t\t\treadonly events: Cfg['events'];\n\t\t\treadonly resources: Cfg['resources'];\n\t\t\treadonly assets: Cfg['assets'];\n\t\t\treadonly screens: Record<string, ScreenDefinition>;\n\t\t}>>) => ScreenConfigurator<NewS, ECSpresso<{\n\t\t\treadonly components: Cfg['components'];\n\t\t\treadonly events: Cfg['events'];\n\t\t\treadonly resources: Cfg['resources'];\n\t\t\treadonly assets: Cfg['assets'];\n\t\t\treadonly screens: Record<string, ScreenDefinition>;\n\t\t}>>\n\t): ECSpressoBuilder<{\n\t\treadonly components: Cfg['components'];\n\t\treadonly events: Cfg['events'];\n\t\treadonly resources: Cfg['resources'] & { $screen: ScreenResource<Cfg['screens'] & NewS> };\n\t\treadonly assets: Cfg['assets'];\n\t\treadonly screens: Cfg['screens'] & NewS;\n\t}, Labels, Groups, AssetGroupNames, ReactiveQueryNames> {\n\t\tconst screenConfig = createScreenConfigurator<{}, ECSpresso<{\n\t\t\treadonly components: Cfg['components'];\n\t\t\treadonly events: Cfg['events'];\n\t\t\treadonly resources: Cfg['resources'];\n\t\t\treadonly assets: Cfg['assets'];\n\t\t\treadonly screens: Record<string, ScreenDefinition>;\n\t\t}>>();\n\t\tconfigurator(screenConfig);\n\t\tthis.screenConfigurator = screenConfig as unknown as ScreenConfiguratorImpl<Cfg['screens']>;\n\t\treturn this as unknown as ECSpressoBuilder<{\n\t\t\treadonly components: Cfg['components'];\n\t\t\treadonly events: Cfg['events'];\n\t\t\treadonly resources: Cfg['resources'] & { $screen: ScreenResource<Cfg['screens'] & NewS> };\n\t\t\treadonly assets: Cfg['assets'];\n\t\t\treadonly screens: Cfg['screens'] & NewS;\n\t\t}, Labels, Groups, AssetGroupNames, ReactiveQueryNames>;\n\t}\n\n\t/**\n\t * Configure the fixed timestep interval for the fixedUpdate phase.\n\t * @param dt The fixed timestep in seconds (e.g., 1/60 for 60Hz physics)\n\t * @returns This builder for method chaining\n\t */\n\twithFixedTimestep(dt: number): this {\n\t\tthis._fixedDt = dt;\n\t\treturn this;\n\t}\n\n\t/**\n\t * Declare reactive query names that will be registered at runtime.\n\t * This is a pure type-level operation with no runtime cost.\n\t */\n\twithReactiveQueryNames<N extends string>(): ECSpressoBuilder<Cfg, Labels, Groups, AssetGroupNames, ReactiveQueryNames | N> {\n\t\treturn this as unknown as ECSpressoBuilder<Cfg, Labels, Groups, AssetGroupNames, ReactiveQueryNames | N>;\n\t}\n\n\t/**\n\t * Create a plugin factory from the builder's accumulated types.\n\t * Returns a definePlugin equivalent with no manual type parameters.\n\t */\n\tpluginFactory(): <\n\t\tPL extends string = never,\n\t\tPG extends string = never,\n\t\tPAG extends string = never,\n\t\tPRQ extends string = never,\n\t>(config: {\n\t\tid: string;\n\t\tinstall: (world: ECSpresso<Cfg>) => void;\n\t}) => Plugin<Cfg, EmptyConfig, PL, PG, PAG, PRQ> {\n\t\treturn definePlugin as unknown as ReturnType<ECSpressoBuilder<Cfg>['pluginFactory']>;\n\t}\n\n\t/**\n\t\t* Complete the build process and return the built ECSpresso instance\n\t*/\n\tbuild(): ECSpresso<\n\t\tFinalizeBuiltinResources<Cfg, [AssetGroupNames] extends [never] ? string : AssetGroupNames>,\n\t\t[Labels] extends [never] ? string : Labels,\n\t\t[Groups] extends [never] ? string : Groups,\n\t\t[AssetGroupNames] extends [never] ? string : AssetGroupNames,\n\t\t[ReactiveQueryNames] extends [never] ? string : ReactiveQueryNames\n\t> {\n\t\tconst ecspresso = new ECSpresso() as ECSpresso<Cfg>;\n\n\t\t// Install all pending plugins\n\t\tfor (const plugin of this.pendingPlugins) {\n\t\t\tecspresso.installPlugin(plugin);\n\t\t}\n\n\t\t// Apply pending resources\n\t\tfor (const { key, value } of this.pendingResources) {\n\t\t\tecspresso.addResource(key as keyof Cfg['resources'], value as any);\n\t\t}\n\n\t\t// Apply pending dispose callbacks\n\t\tfor (const { key, callback } of this.pendingDisposeCallbacks) {\n\t\t\tecspresso.registerDispose(key as keyof Cfg['components'], callback as (ctx: { value: Cfg['components'][keyof Cfg['components']]; entityId: number }) => void);\n\t\t}\n\n\t\t// Apply pending required component registrations\n\t\tfor (const { trigger, required, factory } of this.pendingRequiredComponents) {\n\t\t\tecspresso.registerRequired(\n\t\t\t\ttrigger as keyof Cfg['components'],\n\t\t\t\trequired as keyof Cfg['components'],\n\t\t\t\tfactory as () => Cfg['components'][keyof Cfg['components']]\n\t\t\t);\n\t\t}\n\n\t\t// Set up asset manager if configured via withAssets(), or auto-create if plugins contributed assets\n\t\tif (this.assetConfigurator) {\n\t\t\tecspresso._setAssetManager(this.assetConfigurator.getManager() as unknown as AssetManager<Cfg['assets']>);\n\t\t} else if (ecspresso._hasPendingPluginAssets()) {\n\t\t\tecspresso._setAssetManager(new AssetManager() as unknown as AssetManager<Cfg['assets']>);\n\t\t}\n\n\t\t// Set up screen manager if configured via withScreens(), or auto-create if plugins contributed screens\n\t\tif (this.screenConfigurator) {\n\t\t\tecspresso._setScreenManager(this.screenConfigurator.getManager() as unknown as ScreenManager<Cfg['screens']>);\n\t\t} else if (ecspresso._hasPendingPluginScreens()) {\n\t\t\tecspresso._setScreenManager(new ScreenManager() as unknown as ScreenManager<Cfg['screens']>);\n\t\t}\n\n\t\t// Set fixed timestep if configured\n\t\tif (this._fixedDt !== null) {\n\t\t\tecspresso._setFixedDt(this._fixedDt);\n\t\t}\n\n\t\treturn ecspresso as unknown as ECSpresso<\n\t\t\tFinalizeBuiltinResources<Cfg, [AssetGroupNames] extends [never] ? string : AssetGroupNames>,\n\t\t\t[Labels] extends [never] ? string : Labels,\n\t\t\t[Groups] extends [never] ? string : Groups,\n\t\t\t[AssetGroupNames] extends [never] ? string : AssetGroupNames,\n\t\t\t[ReactiveQueryNames] extends [never] ? string : ReactiveQueryNames\n\t\t>;\n\t}\n}\n",
|
|
17
|
-
"import EntityManager from \"./entity-manager\";\nimport EventBus from \"./event-bus\";\nimport ResourceManager, { type ResourceFactoryWithDeps, type ResourceDirectValue } from \"./resource-manager\";\nimport AssetManager from \"./asset-manager\";\nimport ScreenManager from \"./screen-manager\";\nimport ReactiveQueryManager, { type ReactiveQueryDefinition } from \"./reactive-query-manager\";\nimport CommandBuffer from \"./command-buffer\";\nimport type { System, SystemPhase, FilteredEntity, Entity, RemoveEntityOptions, HierarchyEntry, HierarchyIteratorOptions } from \"./types\";\nimport { definePlugin, type Plugin } from \"./plugin\";\nimport { SystemBuilder } from \"./system-builder\";\nimport { checkRequiredCycle } from \"./utils/check-required-cycle\";\nimport { version } from \"../package.json\";\nimport type { AssetDefinition, AssetHandle, AssetEvents } from \"./asset-types\";\nimport type { ScreenDefinition, ScreenEvents } from \"./screen-types\";\nimport { ECSpressoBuilder } from \"./ecspresso-builder\";\nimport type { WorldConfig, EmptyConfig } from \"./type-utils\";\n\n/**\n\t* Interface declaration for ECSpresso constructor to ensure type augmentation works properly.\n\t* This merges with the class declaration below.\n*/\nexport default interface ECSpresso<\n\tCfg extends WorldConfig = EmptyConfig,\n\tLabels extends string = string,\n\tGroups extends string = string,\n\tAssetGroupNames extends string = string,\n\tReactiveQueryNames extends string = string,\n> {\n\t/**\n\t\t* Default constructor\n\t*/\n\tnew(): ECSpresso<Cfg, Labels, Groups, AssetGroupNames, ReactiveQueryNames>;\n}\n\nconst PHASE_ORDER: readonly SystemPhase[] = [\n\t'preUpdate', 'fixedUpdate', 'update', 'postUpdate', 'render',\n];\n\n\n/**\n\t* ECSpresso is the central ECS framework class that connects all features.\n\t* It handles creation and management of entities, components, and systems, and provides lifecycle hooks.\n*/\nexport default class ECSpresso<\n\tCfg extends WorldConfig = EmptyConfig,\n\tLabels extends string = string,\n\tGroups extends string = string,\n\tAssetGroupNames extends string = string,\n\tReactiveQueryNames extends string = string,\n> {\n\t// Phantom type property for structural type extraction (no runtime cost).\n\tdeclare readonly _cfg: Cfg;\n\n\t/** Library version*/\n\tpublic static readonly VERSION = version;\n\n\t/** Access/modify stored components and entities*/\n\tprivate _entityManager: EntityManager<Cfg['components']>;\n\t/** Publish/subscribe to events*/\n\tprivate _eventBus: EventBus<Cfg['events']>;\n\t/** Access/modify registered resources*/\n\tprivate _resourceManager: ResourceManager<Cfg['resources'], ECSpresso<Cfg>>;\n\t/** Command buffer for deferred structural changes */\n\tprivate _commandBuffer: CommandBuffer<Cfg>;\n\n\t/** Registered systems that will be updated in order*/\n\tprivate _systems: Array<System<Cfg, any, any>> = [];\n\t/** Systems grouped by execution phase, each sorted by priority */\n\tprivate _phaseSystems: Record<SystemPhase, Array<System<Cfg, any, any>>> = {\n\t\tpreUpdate: [], fixedUpdate: [], update: [], postUpdate: [], render: [],\n\t};\n\t/** Track installed plugins to prevent duplicates*/\n\tprivate _installedPlugins: Set<string> = new Set();\n\t/** Disabled system groups */\n\tprivate _disabledGroups: Set<string> = new Set();\n\t/** Asset manager for loading and accessing assets */\n\tprivate _assetManager: AssetManager<Cfg['assets']> | null = null;\n\t/** Screen manager for state/screen transitions */\n\tprivate _screenManager: ScreenManager<Cfg['screens']> | null = null;\n\t/** Reactive query manager for enter/exit callbacks */\n\tprivate _reactiveQueryManager: ReactiveQueryManager<Cfg['components']>;\n\t/** Post-update hooks to be called after all systems in update() */\n\tprivate _postUpdateHooks: Array<(ctx: { ecs: ECSpresso<Cfg>; dt: number }) => void> = [];\n\t/** Global tick counter, incremented at the end of each update() */\n\tprivate _currentTick: number = 0;\n\t/** Per-system last-seen change sequence for change detection */\n\tprivate _systemLastSeqs: Map<object, number> = new Map();\n\t/** Change threshold used for public getEntitiesWithQuery and between-system resolution */\n\tprivate _changeThreshold: number = 0;\n\t/** Fixed timestep interval in seconds (default: 1/60) */\n\tprivate _fixedDt: number = 1 / 60;\n\t/** Accumulated time for fixed update steps */\n\tprivate _fixedAccumulator: number = 0;\n\t/** Interpolation alpha between fixed steps (accumulator / fixedDt) */\n\tprivate _interpolationAlpha: number = 0;\n\t/** Maximum fixed update steps per frame (spiral-of-death protection) */\n\tprivate _maxFixedSteps: number = 8;\n\t/** Registry of required component relationships: trigger -> [{component, factory}] */\n\tprivate _requiredComponents: Map<keyof Cfg['components'], Array<{ component: keyof Cfg['components']; factory: (triggerValue: unknown) => unknown }>> = new Map();\n\t/** Pending plugin assets awaiting manager creation at build time */\n\tprivate _pendingPluginAssets: Array<[string, AssetDefinition<unknown>]> = [];\n\t/** Pending plugin screens awaiting manager creation at build time */\n\tprivate _pendingPluginScreens: Array<[string, ScreenDefinition<any, any>]> = [];\n\t/** Whether diagnostics timing collection is enabled */\n\tprivate _diagnosticsEnabled: boolean = false;\n\t/** Per-system timing in ms, populated when diagnostics enabled */\n\tprivate _systemTimings: Map<string, number> = new Map();\n\t/** Per-phase timing in ms, populated when diagnostics enabled */\n\tprivate _phaseTimings: Record<SystemPhase, number> = {\n\t\tpreUpdate: 0, fixedUpdate: 0, update: 0, postUpdate: 0, render: 0,\n\t};\n\t/** Per-system per-query seen entity IDs for onEntityEnter tracking */\n\tprivate _entityEnterTracking: Map<object, Map<string, Set<number>>> = new Map();\n\t/** Shared reusable set for per-tick entity enter comparison (avoids allocation) */\n\tprivate _entityEnterFrameSet: Set<number> = new Set();\n\t/** Pre-allocated process context per system (avoids per-frame allocation) */\n\t// eslint-disable-next-line @typescript-eslint/no-explicit-any -- cascades from System<Cfg, any, any>; can't remove without existential types\n\tprivate _systemContexts: WeakMap<object, { queries: Record<string, any>; dt: number; ecs: ECSpresso<Cfg> }> = new WeakMap();\n\t/** Pending system builder finalizers to run before next update/initialize */\n\tprivate _pendingFinalizers: Array<() => void> = [];\n\tprivate _batchingRegistrations = false;\n\n\t/**\n\t\t* Creates a new ECSpresso instance.\n\t*/\n\tconstructor() {\n\t\tthis._entityManager = new EntityManager<Cfg['components']>();\n\t\tthis._eventBus = new EventBus<Cfg['events']>();\n\t\tthis._resourceManager = new ResourceManager<Cfg['resources'], ECSpresso<Cfg>>();\n\t\tthis._reactiveQueryManager = new ReactiveQueryManager<Cfg['components']>(this._entityManager);\n\t\tthis._commandBuffer = new CommandBuffer<Cfg>();\n\n\t\t// Wire up lifecycle hooks for change detection, required components, and reactive queries\n\t\tthis._subscribeLifecycleHooks();\n\t}\n\n\t/**\n\t * Subscribes to EntityManager lifecycle hooks for change detection,\n\t * required component auto-addition, and reactive query tracking.\n\t * @private\n\t */\n\tprivate _subscribeLifecycleHooks(): void {\n\t\t// afterComponentAdded → mark changed + auto-add required components\n\t\tthis._entityManager.onAfterComponentAdded((entityId, componentName) => {\n\t\t\tthis._entityManager.markChanged(entityId, componentName);\n\n\t\t\t// Auto-add required components (recursive via addComponent → this hook)\n\t\t\tconst reqs = this._requiredComponents.get(componentName);\n\t\t\tif (reqs) {\n\t\t\t\tconst entity = this._entityManager.getEntity(entityId);\n\t\t\t\tif (entity) {\n\t\t\t\t\tconst triggerValue = entity.components[componentName];\n\t\t\t\t\tfor (const { component, factory } of reqs) {\n\t\t\t\t\t\tif (this._entityManager._pendingBatchKeys?.has(component)) continue;\n\t\t\t\t\t\tif (!(component in entity.components)) {\n\t\t\t\t\t\t\tthis._entityManager.addComponent(entityId, component, factory(triggerValue) as Cfg['components'][keyof Cfg['components']]);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\t// afterEntityMutated → recheck reactive queries (entity itself + children for parentHas)\n\t\tthis._entityManager.onAfterEntityMutated((entityId) => {\n\t\t\tconst entity = this._entityManager.getEntity(entityId);\n\t\t\tif (entity) {\n\t\t\t\tthis._reactiveQueryManager.recheckEntityAndChildren(entity);\n\t\t\t}\n\t\t});\n\n\t\t// afterComponentRemoved → notify reactive query manager\n\t\tthis._entityManager.onAfterComponentRemoved((entityId, componentName) => {\n\t\t\tconst entity = this._entityManager.getEntity(entityId);\n\t\t\tif (entity) {\n\t\t\t\tthis._reactiveQueryManager.onComponentRemoved(entity, componentName);\n\t\t\t}\n\t\t});\n\n\t\t// beforeEntityRemoved → notify reactive query manager\n\t\tthis._entityManager.onBeforeEntityRemoved((entityId) => {\n\t\t\tthis._reactiveQueryManager.onEntityRemoved(entityId);\n\t\t});\n\n\t\t// afterParentChanged → recheck child entity for parentHas queries\n\t\tthis._entityManager.onAfterParentChanged((childId) => {\n\t\t\tif (this._reactiveQueryManager.hasParentHasQueries) {\n\t\t\t\tconst childEntity = this._entityManager.getEntity(childId);\n\t\t\t\tif (childEntity) {\n\t\t\t\t\tthis._reactiveQueryManager.recheckEntity(childEntity);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t}\n\n\t/**\n\t\t* Creates a new ECSpresso builder for type-safe plugin installation.\n\t\t* Types are inferred from the builder chain — use `.withPlugin()`,\n\t\t* `.withComponentTypes<T>()`, `.withEventTypes<T>()`, and `.withResource()`\n\t\t* to accumulate types without manual aggregate interfaces.\n\t *\n\t\t* @returns A builder instance for fluent method chaining\n\t *\n\t\t* @example\n\t\t* ```typescript\n\t\t* const ecs = ECSpresso.create()\n\t *\t .withPlugin(createRenderer2DPlugin({ ... }))\n\t *\t .withPlugin(createPhysics2DPlugin())\n\t *\t .withComponentTypes<{ player: true; enemy: { type: string } }>()\n\t *\t .withEventTypes<{ gameStart: true }>()\n\t *\t .withResource('score', { value: 0 })\n\t *\t .build();\n\t *\n\t * type ECS = typeof ecs;\n\t\t* ```\n\t*/\n\tstatic create<Cfg2 extends WorldConfig = EmptyConfig>(): ECSpressoBuilder<Cfg2, never, never, never, never> {\n\t\treturn new ECSpressoBuilder<Cfg2, never, never, never, never>();\n\t}\n\n\t/**\n\t\t* Adds a system directly to this ECSpresso instance.\n\t\t* The system is registered when initialize() or update() is next called.\n\t\t* @param label Unique name to identify the system\n\t\t* @returns A SystemBuilder instance for method chaining\n\t*/\n\taddSystem(label: string): SystemBuilder<Cfg> {\n\t\tconst builder = new SystemBuilder<Cfg>(label);\n\t\tthis._pendingFinalizers.push(() => {\n\t\t\tthis._registerSystem(builder._createSystemObject());\n\t\t});\n\t\treturn builder;\n\t}\n\n\t/**\n\t * Finalize and register all pending system builders.\n\t * @private\n\t */\n\tprivate _finalizePendingBuilders(): void {\n\t\tif (this._pendingFinalizers.length === 0) return;\n\t\tthis._batchingRegistrations = true;\n\t\twhile (this._pendingFinalizers.length > 0) {\n\t\t\tconst finalizers = this._pendingFinalizers;\n\t\t\tthis._pendingFinalizers = [];\n\t\t\tfor (const finalize of finalizers) {\n\t\t\t\tfinalize();\n\t\t\t}\n\t\t}\n\t\tthis._batchingRegistrations = false;\n\t\tthis._rebuildPhaseSystems();\n\t}\n\n\t/**\n\t * Update all systems across execution phases.\n\t * Phases run in order: preUpdate -> fixedUpdate -> update -> postUpdate -> render.\n\t * The fixedUpdate phase uses a time accumulator for deterministic fixed-timestep simulation.\n\t * @param deltaTime Time elapsed since the last update (in seconds)\n\t */\n\tupdate(deltaTime: number) {\n\t\tthis._finalizePendingBuilders();\n\t\tconst currentScreen = (this._screenManager?.getCurrentScreen() ?? null) as (keyof Cfg['screens'] & string) | null;\n\t\tconst timing = this._diagnosticsEnabled;\n\n\t\t// 1. preUpdate phase\n\t\tthis._runPhase('preUpdate', deltaTime, currentScreen, timing);\n\n\t\t// 2. fixedUpdate phase — accumulate time and step N times\n\t\tconst fixedT0 = timing ? performance.now() : 0;\n\t\tthis._fixedAccumulator += deltaTime;\n\t\tlet steps = 0;\n\t\twhile (this._fixedAccumulator >= this._fixedDt && steps < this._maxFixedSteps) {\n\t\t\tthis._executePhase(this._phaseSystems.fixedUpdate, this._fixedDt, currentScreen);\n\t\t\tthis._commandBuffer.playback(this);\n\t\t\tthis._fixedAccumulator -= this._fixedDt;\n\t\t\tsteps++;\n\t\t}\n\t\t// Clamp accumulator if we hit the spiral-of-death cap\n\t\tif (this._fixedAccumulator >= this._fixedDt) {\n\t\t\tthis._fixedAccumulator = 0;\n\t\t}\n\t\tif (timing) {\n\t\t\tthis._phaseTimings.fixedUpdate = performance.now() - fixedT0;\n\t\t}\n\t\t// Compute interpolation alpha for render-phase smoothing\n\t\tthis._interpolationAlpha = this._fixedAccumulator / this._fixedDt;\n\n\t\t// 3. update phase\n\t\tthis._runPhase('update', deltaTime, currentScreen, timing);\n\n\t\t// 4. postUpdate phase\n\t\tthis._runPhase('postUpdate', deltaTime, currentScreen, timing);\n\n\t\t// 5. Post-update hooks (between postUpdate and render, preserving existing behavior)\n\t\tfor (const hook of this._postUpdateHooks) {\n\t\t\thook({ ecs: this, dt: deltaTime });\n\t\t}\n\n\t\t// 6. render phase\n\t\tthis._runPhase('render', deltaTime, currentScreen, timing);\n\n\t\t// Set change threshold to current sequence so that public\n\t\t// getEntitiesWithQuery (called between updates) sees command\n\t\t// buffer marks but not stale ones.\n\t\tthis._changeThreshold = this._entityManager.changeSeq;\n\n\t\t// Increment tick counter (frame counter only)\n\t\tthis._currentTick++;\n\t}\n\n\t/**\n\t * Execute all systems in a single phase.\n\t * @private\n\t */\n\tprivate _executePhase(\n\t\tsystems: ReadonlyArray<System<Cfg, any, any>>,\n\t\tdeltaTime: number,\n\t\tcurrentScreen: (keyof Cfg['screens'] & string) | null\n\t): void {\n\t\tfor (const system of systems) {\n\t\t\tif (!system.process && !system.onEntityEnter) continue;\n\n\t\t\t// Group filtering - skip if any of the system's groups is disabled\n\t\t\tif (system.groups?.length) {\n\t\t\t\tlet anyDisabled = false;\n\t\t\t\tfor (const group of system.groups) {\n\t\t\t\t\tif (this._disabledGroups.has(group)) {\n\t\t\t\t\t\tanyDisabled = true;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (anyDisabled) continue;\n\t\t\t}\n\n\t\t\t// Screen filtering - skip if system is restricted to specific screens\n\t\t\tif (system.inScreens?.length) {\n\t\t\t\tif (currentScreen === null || !system.inScreens.includes(currentScreen)) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Screen exclusion - skip if system excludes current screen\n\t\t\tif (system.excludeScreens?.length) {\n\t\t\t\tif (currentScreen !== null && system.excludeScreens.includes(currentScreen)) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Asset requirements - skip if required assets not loaded\n\t\t\tif (system.requiredAssets?.length && this._assetManager) {\n\t\t\t\tlet assetsReady = true;\n\t\t\t\tfor (const assetKey of system.requiredAssets) {\n\t\t\t\t\tif (!this._assetManager.isLoaded(assetKey)) {\n\t\t\t\t\t\tassetsReady = false;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (!assetsReady) continue;\n\t\t\t}\n\n\t\t\t// Set per-system change threshold from its last-seen sequence\n\t\t\tconst systemThreshold = this._systemLastSeqs.get(system) ?? 0;\n\t\t\tthis._changeThreshold = systemThreshold;\n\n\t\t\t// Get or create pre-allocated context for this system\n\t\t\tlet ctx = this._systemContexts.get(system);\n\t\t\tif (!ctx) {\n\t\t\t\tctx = { queries: {}, dt: 0, ecs: this };\n\t\t\t\tthis._systemContexts.set(system, ctx);\n\t\t\t}\n\t\t\tctx.dt = deltaTime;\n\n\t\t\t// Prepare query results for each defined query in the system\n\t\t\tconst queryResults = ctx.queries;\n\t\t\tlet hasResults = false;\n\t\t\tlet hasQueries = false;\n\n\t\t\tif (system.entityQueries) {\n\t\t\t\tfor (const queryName in system.entityQueries) {\n\t\t\t\t\thasQueries = true;\n\n\t\t\t\t\tconst query = system.entityQueries[queryName];\n\n\t\t\t\t\tif (query) {\n\t\t\t\t\t\tconst existing = queryResults[queryName];\n\t\t\t\t\t\tconst output = existing ?? (queryResults[queryName] = []);\n\n\t\t\t\t\t\tthis._entityManager.getEntitiesWithQueryInto(\n\t\t\t\t\t\t\toutput,\n\t\t\t\t\t\t\tquery.with,\n\t\t\t\t\t\t\tquery.without || [],\n\t\t\t\t\t\t\tquery.changed,\n\t\t\t\t\t\t\tquery.changed ? this._changeThreshold : undefined,\n\t\t\t\t\t\t\tquery.parentHas,\n\t\t\t\t\t\t);\n\n\t\t\t\t\t\tif (output.length) {\n\t\t\t\t\t\t\thasResults = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Fire onEntityEnter callbacks before process\n\t\t\tconst enterTracking = this._entityEnterTracking.get(system);\n\t\t\tif (enterTracking && system.onEntityEnter) {\n\t\t\t\tfor (const queryName in system.onEntityEnter) {\n\t\t\t\t\tconst results = queryResults[queryName];\n\t\t\t\t\tconst seenEntities = enterTracking.get(queryName);\n\t\t\t\t\tif (!results || !seenEntities) continue;\n\n\t\t\t\t\tconst callback = system.onEntityEnter[queryName];\n\t\t\t\t\tif (!callback) continue;\n\n\t\t\t\t\t// Build set of current entity IDs for pruning\n\t\t\t\t\tconst frameSet = this._entityEnterFrameSet;\n\t\t\t\t\tframeSet.clear();\n\n\t\t\t\t\tfor (const entity of results) {\n\t\t\t\t\t\tframeSet.add(entity.id);\n\t\t\t\t\t\tif (!seenEntities.has(entity.id)) {\n\t\t\t\t\t\t\tseenEntities.add(entity.id);\n\t\t\t\t\t\t\tcallback({ entity, ecs: this });\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Prune stale entries (entities no longer in query results)\n\t\t\t\t\tfor (const id of seenEntities) {\n\t\t\t\t\t\tif (!frameSet.has(id)) {\n\t\t\t\t\t\t\tseenEntities.delete(id);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Call the system's process function only if there are results or there is no query.\n\t\t\tif (system.process) {\n\t\t\t\tif (this._diagnosticsEnabled) {\n\t\t\t\t\tconst t0 = performance.now();\n\t\t\t\t\tif (hasResults || system.runWhenEmpty) {\n\t\t\t\t\t\tsystem.process(ctx);\n\t\t\t\t\t} else if (!hasQueries) {\n\t\t\t\t\t\tsystem.process(ctx);\n\t\t\t\t\t}\n\t\t\t\t\tthis._systemTimings.set(system.label, performance.now() - t0);\n\t\t\t\t} else if (hasResults || system.runWhenEmpty) {\n\t\t\t\t\tsystem.process(ctx);\n\t\t\t\t} else if (!hasQueries) {\n\t\t\t\t\tsystem.process(ctx);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Record this system's last-seen sequence so it won't re-process these marks\n\t\t\tthis._systemLastSeqs.set(system, this._entityManager.changeSeq);\n\t\t}\n\t}\n\n\t/**\n\t * Execute a non-fixed phase with optional timing, then play back the command buffer.\n\t * @private\n\t */\n\tprivate _runPhase(\n\t\tphase: SystemPhase,\n\t\tdeltaTime: number,\n\t\tcurrentScreen: (keyof Cfg['screens'] & string) | null,\n\t\ttiming: boolean\n\t): void {\n\t\tif (timing) {\n\t\t\tconst t0 = performance.now();\n\t\t\tthis._executePhase(this._phaseSystems[phase], deltaTime, currentScreen);\n\t\t\tthis._phaseTimings[phase] = performance.now() - t0;\n\t\t} else {\n\t\t\tthis._executePhase(this._phaseSystems[phase], deltaTime, currentScreen);\n\t\t}\n\t\tthis._commandBuffer.playback(this);\n\t}\n\n\t/**\n\t * Initialize all resources and systems\n\t * This method:\n\t * 1. Initializes all resources that were added as factory functions\n\t * 2. Sets up asset manager and loads eager assets\n\t * 3. Sets up screen manager\n\t * 4. Calls the onInitialize lifecycle hook on all systems\n\t *\n\t * This is useful for game startup to ensure all resources are ready\n\t * and systems are properly initialized before the game loop begins.\n\t *\n\t * @returns Promise that resolves when everything is initialized\n\t */\n\tasync initialize(): Promise<void> {\n\t\tthis._finalizePendingBuilders();\n\t\tawait this.initializeResources();\n\n\t\t// Set up asset manager if present\n\t\t// Key/value casts are needed because the class generic doesn't constrain ResourceTypes\n\t\t// to contain $assets/$screen — the builder merges them into R at the type level.\n\t\tif (this._assetManager) {\n\t\t\tthis._assetManager.setEventBus(this._eventBus as unknown as EventBus<AssetEvents<keyof Cfg['assets'] & string>>);\n\t\t\tawait this._assetManager.loadEagerAssets();\n\t\t\tthis._resourceManager.add('$assets' as keyof Cfg['resources'], this._assetManager.createResource() as unknown as Cfg['resources'][keyof Cfg['resources']]);\n\t\t}\n\n\t\t// Set up screen manager if present\n\t\tif (this._screenManager) {\n\t\t\tthis._screenManager.setDependencies(\n\t\t\t\tthis._eventBus as unknown as EventBus<ScreenEvents<keyof Cfg['screens'] & string>>,\n\t\t\t\tthis._assetManager,\n\t\t\t\tthis\n\t\t\t);\n\t\t\tthis._resourceManager.add('$screen' as keyof Cfg['resources'], this._screenManager.createResource() as unknown as Cfg['resources'][keyof Cfg['resources']]);\n\t\t}\n\n\t\tfor (const system of this._systems) {\n\t\t\tawait system.onInitialize?.(this);\n\t\t}\n\t}\n\n\t/**\n\t * Initialize specific resources or all resources that were added as factory functions but haven't been initialized yet.\n\t * This is useful when you need to ensure resources are ready before proceeding.\n\t * @param keys Optional array of resource keys to initialize. If not provided, all pending resources will be initialized.\n\t * @returns Promise that resolves when the specified resources are initialized\n\t */\n\tasync initializeResources<K extends keyof Cfg['resources']>(...keys: K[]): Promise<void> {\n\t\tawait this._resourceManager.initializeResources(this, ...keys);\n\t}\n\n\t/**\n\t * Rebuild per-phase system arrays from the flat _systems list.\n\t * Each phase array is sorted by priority (higher first), with\n\t * registration order as tiebreaker.\n\t * @private\n\t */\n\tprivate _rebuildPhaseSystems(): void {\n\t\tfor (const phase of PHASE_ORDER) {\n\t\t\tthis._phaseSystems[phase] = [];\n\t\t}\n\t\tfor (const system of this._systems) {\n\t\t\tconst phase = system.phase ?? 'update';\n\t\t\tthis._phaseSystems[phase].push(system);\n\t\t}\n\t\tfor (const phase of PHASE_ORDER) {\n\t\t\tthis._phaseSystems[phase].sort((a, b) => {\n\t\t\t\tconst priorityA = a.priority ?? 0;\n\t\t\t\tconst priorityB = b.priority ?? 0;\n\t\t\t\treturn priorityB - priorityA; // Higher priority executes first\n\t\t\t});\n\t\t}\n\t}\n\n\t/**\n\t\t* Update the priority of a system\n\t\t* @param label The unique label of the system to update\n\t\t* @param priority The new priority value (higher values execute first)\n\t\t* @returns true if the system was found and updated, false otherwise\n\t*/\n\tupdateSystemPriority(label: Labels, priority: number): boolean {\n\t\tthis._finalizePendingBuilders();\n\t\tconst system = this._systems.find(system => system.label === label);\n\t\tif (!system) return false;\n\n\t\t// Set the new priority\n\t\tsystem.priority = priority;\n\n\t\t// Re-sort the systems array\n\t\tthis._rebuildPhaseSystems();\n\n\t\treturn true;\n\t}\n\n\t/**\n\t * Move a system to a different execution phase at runtime.\n\t * @param label The unique label of the system to move\n\t * @param phase The target phase\n\t * @returns true if the system was found and updated, false otherwise\n\t */\n\tupdateSystemPhase(label: Labels, phase: SystemPhase): boolean {\n\t\tthis._finalizePendingBuilders();\n\t\tconst system = this._systems.find(system => system.label === label);\n\t\tif (!system) return false;\n\n\t\tsystem.phase = phase;\n\t\tthis._rebuildPhaseSystems();\n\n\t\treturn true;\n\t}\n\n\t/**\n\t * The interpolation alpha between fixed update steps.\n\t * Ranges from 0 to <1, representing how far into the next\n\t * fixed step the current frame is. Use in the render phase\n\t * for smooth visual interpolation.\n\t */\n\tget interpolationAlpha(): number {\n\t\treturn this._interpolationAlpha;\n\t}\n\n\t/**\n\t * The configured fixed timestep interval in seconds.\n\t */\n\tget fixedDt(): number {\n\t\treturn this._fixedDt;\n\t}\n\n\t// ==================== System Group Control ====================\n\n\t/**\n\t * Disable a system group. Systems in this group will be skipped during update().\n\t * @param groupName The name of the group to disable\n\t */\n\tdisableSystemGroup(groupName: Groups): void {\n\t\tthis._disabledGroups.add(groupName);\n\t}\n\n\t/**\n\t * Enable a system group. Systems in this group will run during update().\n\t * @param groupName The name of the group to enable\n\t */\n\tenableSystemGroup(groupName: Groups): void {\n\t\tthis._disabledGroups.delete(groupName);\n\t}\n\n\t/**\n\t * Check if a system group is enabled.\n\t * @param groupName The name of the group to check\n\t * @returns true if the group is enabled (or doesn't exist), false if disabled\n\t */\n\tisSystemGroupEnabled(groupName: Groups): boolean {\n\t\treturn !this._disabledGroups.has(groupName);\n\t}\n\n\t/**\n\t * Get all system labels that belong to a specific group.\n\t * @param groupName The name of the group\n\t * @returns Array of system labels in the group\n\t */\n\tgetSystemsInGroup(groupName: Groups): string[] {\n\t\tthis._finalizePendingBuilders();\n\t\treturn this._systems\n\t\t\t.filter(system => system.groups?.includes(groupName))\n\t\t\t.map(system => system.label);\n\t}\n\n\t/**\n\t\t* Remove a system by its label\n\t\t* Calls the system's onDetach method with this ECSpresso instance if defined\n\t\t* @param label The unique label of the system to remove\n\t\t* @returns true if the system was found and removed, false otherwise\n\t*/\n\tremoveSystem(label: Labels): boolean {\n\t\tthis._finalizePendingBuilders();\n\t\tconst index = this._systems.findIndex(system => system.label === label);\n\t\tif (index === -1) return false;\n\n\t\tconst system = this._systems[index];\n\t\t// This should never happen since we just found the system by index\n\t\tif (!system) return false;\n\n\t\t// Call the onDetach lifecycle hook if defined\n\t\tif (system.onDetach) {\n\t\t\tsystem.onDetach(this);\n\t\t}\n\n\t\t// Remove system and clean up per-system tracking\n\t\tthis._systems.splice(index, 1);\n\t\tthis._systemLastSeqs.delete(system);\n\t\tthis._entityEnterTracking.delete(system);\n\n\t\t// Re-sort systems\n\t\tthis._rebuildPhaseSystems();\n\n\t\treturn true;\n\t}\n\n\t/**\n\t\t* Internal method to register a system with this ECSpresso instance\n\t\t* @internal Used by SystemBuilder - replaces direct private property access\n\t*/\n\t_registerSystem(system: System<Cfg, any, any>): void {\n\t\tthis._systems.push(system);\n\t\t// Initialize the system's last-seen sequence to the current change threshold.\n\t\t// Before any update this is 0, so newly added systems see spawn marks.\n\t\t// After updates, the threshold is advanced past consumed marks, so\n\t\t// systems added later don't see stale marks.\n\t\tthis._systemLastSeqs.set(system, this._changeThreshold);\n\t\tif (!this._batchingRegistrations) {\n\t\t\tthis._rebuildPhaseSystems();\n\t\t}\n\n\t\t// Set up entity enter tracking if the system has onEntityEnter handlers\n\t\tif (system.onEntityEnter) {\n\t\t\tconst queryMap = new Map<string, Set<number>>();\n\t\t\tfor (const queryName in system.onEntityEnter) {\n\t\t\t\tqueryMap.set(queryName, new Set());\n\t\t\t}\n\t\t\tthis._entityEnterTracking.set(system, queryMap);\n\t\t}\n\n\t\t// Set up event handlers if they exist\n\t\tif (!system.eventHandlers) return;\n\n\t\tfor (const eventName in system.eventHandlers) {\n\t\t\tconst handler = system.eventHandlers[eventName];\n\t\t\tif (handler) {\n\t\t\t\tthis._eventBus.subscribe(eventName, (data) => {\n\t\t\t\t\thandler({ data, ecs: this });\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t\t* Check if a resource exists\n\t*/\n\thasResource<K extends keyof Cfg['resources']>(key: K): boolean {\n\t\treturn this._resourceManager.has(key);\n\t}\n\n\t/**\n\t * Get a resource by key. Throws if the resource is not found.\n\t * @param key The resource key\n\t * @returns The resource value\n\t * @throws Error if resource not found\n\t * @see tryGetResource — the non-throwing alternative that returns undefined\n\t */\n\tgetResource<K extends keyof Cfg['resources']>(key: K): Cfg['resources'][K] {\n\t\tif (!this._resourceManager.has(key)) {\n\t\t\tthrow new Error(`Resource '${String(key)}' not found. Available resources: [${this.getResourceKeys().map(k => String(k)).join(', ')}]`);\n\t\t}\n\n\t\treturn this._resourceManager.get(key, this);\n\t}\n\n\t/**\n\t * Try to get a resource by key. Returns undefined if the resource is not found.\n\t * Inspired by Bevy's `World::get_resource::<T>()` which returns `Option<&T>`.\n\t *\n\t * Two overloads:\n\t * 1. Known key — full type safety from `ResourceTypes`\n\t * 2. String key with explicit type param — for cross-plugin optional dependencies\n\t *\n\t * @example\n\t * ```typescript\n\t * // Known key (type inferred from ResourceTypes)\n\t * const score = ecs.tryGetResource('score'); // ScoreResource | undefined\n\t *\n\t * // Cross-plugin optional dependency (caller specifies expected type)\n\t * const si = ecs.tryGetResource<SpatialIndex>('spatialIndex') ?? null;\n\t * ```\n\t */\n\ttryGetResource<K extends keyof Cfg['resources']>(key: K): Cfg['resources'][K] | undefined;\n\ttryGetResource<T>(key: unknown extends T ? never : string): T | undefined;\n\ttryGetResource(key: string): unknown {\n\t\tconst k = key as keyof Cfg['resources'];\n\t\tif (!this._resourceManager.has(k)) return undefined;\n\t\treturn this._resourceManager.get(k, this);\n\t}\n\n\t/**\n\t\t* Add a resource to the ECS instance.\n\t\t*\n\t\t* - Plain value → stored directly\n\t\t* - Function → treated as a factory, called with this ECSpresso instance on first access\n\t\t* - `{ factory, dependsOn?, onDispose? }` → factory with dependencies/disposal\n\t\t* - `directValue(val)` → stores the value as-is (use to store functions/classes without invoking them)\n\t*/\n\taddResource<K extends keyof Cfg['resources']>(\n\t\tkey: K,\n\t\tresource:\n\t\t\t| Cfg['resources'][K]\n\t\t\t| ((ecs: ECSpresso<Cfg>) => Cfg['resources'][K] | Promise<Cfg['resources'][K]>)\n\t\t\t| ResourceFactoryWithDeps<Cfg['resources'][K], ECSpresso<Cfg>, keyof Cfg['resources'] & string>\n\t\t\t| ResourceDirectValue<Cfg['resources'][K]>\n\t): this {\n\t\tthis._resourceManager.add(key, resource);\n\t\treturn this;\n\t}\n\n\t/**\n\t\t* Remove a resource from the ECS instance (without calling onDispose)\n\t\t* @param key The resource key to remove\n\t\t* @returns True if the resource was removed, false if it didn't exist\n\t*/\n\tremoveResource<K extends keyof Cfg['resources']>(key: K): boolean {\n\t\treturn this._resourceManager.remove(key);\n\t}\n\n\t/**\n\t * Dispose a single resource, calling its onDispose callback if defined\n\t * @param key The resource key to dispose\n\t * @returns True if the resource existed and was disposed, false if it didn't exist\n\t */\n\tasync disposeResource<K extends keyof Cfg['resources']>(key: K): Promise<boolean> {\n\t\treturn this._resourceManager.disposeResource(key, this);\n\t}\n\n\t/**\n\t * Dispose all initialized resources in reverse dependency order.\n\t * Resources that depend on others are disposed first.\n\t * Calls each resource's onDispose callback if defined.\n\t */\n\tasync disposeResources(): Promise<void> {\n\t\treturn this._resourceManager.disposeResources(this);\n\t}\n\n\t/**\n\t\t* Update an existing resource using an updater function\n\t\t* @param key The resource key to update\n\t\t* @param updater Function that receives the current resource value and returns the new value\n\t\t* @returns This ECSpresso instance for chaining\n\t\t* @throws Error if the resource doesn't exist\n\t*/\n\tupdateResource<K extends keyof Cfg['resources']>(\n\t\tkey: K,\n\t\tupdater: (current: Cfg['resources'][K]) => Cfg['resources'][K]\n\t): this {\n\t\tconst oldValue = this.getResource(key);\n\t\tconst newValue = updater(oldValue);\n\t\tthis._resourceManager.add(key, newValue);\n\t\tthis._resourceManager.notifyChange(key, newValue, oldValue);\n\t\treturn this;\n\t}\n\n\t/**\n\t\t* Set a resource to a plain value.\n\t\t* Unlike updateResource, does not require an updater function.\n\t\t* @param key The resource key to set\n\t\t* @param value The new resource value\n\t\t* @returns This ECSpresso instance for chaining\n\t*/\n\tsetResource<K extends keyof Cfg['resources']>(\n\t\tkey: K,\n\t\tvalue: Cfg['resources'][K]\n\t): this {\n\t\tconst oldValue = this.tryGetResource(key);\n\t\tthis._resourceManager.add(key, value);\n\t\tif (oldValue !== undefined) {\n\t\t\tthis._resourceManager.notifyChange(key, value, oldValue);\n\t\t}\n\t\treturn this;\n\t}\n\n\t/**\n\t\t* Subscribe to changes for a specific resource key.\n\t\t* @param key The resource key to watch\n\t\t* @param callback Function called with (newValue, oldValue) when the resource changes\n\t\t* @returns Unsubscribe function\n\t*/\n\tonResourceChange<K extends keyof Cfg['resources']>(\n\t\tkey: K,\n\t\tcallback: (newValue: Cfg['resources'][K], oldValue: Cfg['resources'][K]) => void\n\t): () => void {\n\t\treturn this._resourceManager.onResourceChange(key, callback);\n\t}\n\n\t/**\n\t\t* Get all resource keys that are currently registered\n\t\t* @returns Array of resource keys\n\t*/\n\tgetResourceKeys(): Array<keyof Cfg['resources']> {\n\t\treturn this._resourceManager.getKeys() as Array<keyof Cfg['resources']>;\n\t}\n\n\t/**\n\t\t* Check if a resource needs initialization (was added as a factory function)\n\t\t* @param key The resource key to check\n\t\t* @returns True if the resource needs initialization\n\t*/\n\tresourceNeedsInitialization<K extends keyof Cfg['resources']>(key: K): boolean {\n\t\treturn this._resourceManager.needsInitialization(key);\n\t}\n\n\t/**\n\t\t* Get an entity by ID.\n\t\t* @param entityId The entity ID\n\t\t* @returns The entity, or undefined if it doesn't exist\n\t*/\n\tgetEntity(entityId: number): Entity<Cfg['components']> | undefined {\n\t\treturn this._entityManager.getEntity(entityId);\n\t}\n\n\t/**\n\t\t* Get a component value from an entity.\n\t\t* @param entityId The entity ID\n\t\t* @param componentName The component to retrieve\n\t\t* @returns The component value, or undefined if the entity doesn't have it\n\t*/\n\tgetComponent<K extends keyof Cfg['components']>(\n\t\tentityId: number,\n\t\tcomponentName: K\n\t): Cfg['components'][K] | undefined {\n\t\treturn this._entityManager.getComponent(entityId, componentName);\n\t}\n\n\t/**\n\t\t* Add or replace a component on an entity.\n\t\t* Triggers component-added callbacks and marks the component as changed.\n\t\t* @param entityId The entity ID\n\t\t* @param componentName The component to add\n\t\t* @param value The component value\n\t*/\n\taddComponent<K extends keyof Cfg['components']>(\n\t\tentityId: number,\n\t\tcomponentName: K,\n\t\tvalue: Cfg['components'][K]\n\t): void {\n\t\tthis._entityManager.addComponent(entityId, componentName, value);\n\t}\n\n\t/**\n\t\t* Add multiple components to an entity at once.\n\t\t* @param entityId The entity ID\n\t\t* @param components Object with component names as keys and component data as values\n\t*/\n\taddComponents<T extends { [K in keyof Cfg['components']]?: Cfg['components'][K] }>(\n\t\tentityId: number,\n\t\tcomponents: T & Record<Exclude<keyof T, keyof Cfg['components']>, never>\n\t): void {\n\t\tthis._entityManager.addComponents(entityId, components);\n\t}\n\n\t/**\n\t\t* Remove a component from an entity.\n\t\t* Triggers component-removed and dispose callbacks.\n\t\t* @param entityId The entity ID\n\t\t* @param componentName The component to remove\n\t*/\n\tremoveComponent<K extends keyof Cfg['components']>(\n\t\tentityId: number,\n\t\tcomponentName: K\n\t): void {\n\t\tthis._entityManager.removeComponent(entityId, componentName);\n\t}\n\n\t/**\n\t\t* Check if an entity has a component\n\t*/\n\thasComponent<K extends keyof Cfg['components']>(\n\t\tentityId: number,\n\t\tcomponentName: K\n\t): boolean {\n\t\tconst component = this._entityManager.getComponent(entityId, componentName);\n\t\treturn component !== undefined;\n\t}\n\n\t/**\n\t\t* Create an entity and add components to it in one call\n\t\t* @param components Object with component names as keys and component data as values\n\t\t* @returns The created entity with all components added\n\t\t*/\n\tspawn<T extends { [K in keyof Cfg['components']]?: Cfg['components'][K] }>(\n\t\tcomponents: T & Record<Exclude<keyof T, keyof Cfg['components']>, never>\n\t): FilteredEntity<Cfg['components'], keyof T & keyof Cfg['components']> {\n\t\tconst entity = this._entityManager.createEntity();\n\t\tthis._entityManager.addComponents(entity.id, components);\n\t\treturn entity as FilteredEntity<Cfg['components'], keyof T & keyof Cfg['components']>;\n\t}\n\n\t/**\n\t\t* Get all entities with specific components\n\t*/\n\tgetEntitiesWithQuery<\n\t\tWithComponents extends keyof Cfg['components'],\n\t\tWithoutComponents extends keyof Cfg['components'] = never\n\t>(\n\t\twithComponents: ReadonlyArray<WithComponents>,\n\t\twithoutComponents: ReadonlyArray<WithoutComponents> = [],\n\t\tchangedComponents?: ReadonlyArray<keyof Cfg['components']>,\n\t\tparentHas?: ReadonlyArray<keyof Cfg['components']>,\n\t): Array<FilteredEntity<Cfg['components'], WithComponents, WithoutComponents>> {\n\t\treturn this._entityManager.getEntitiesWithQuery(\n\t\t\twithComponents,\n\t\t\twithoutComponents,\n\t\t\tchangedComponents,\n\t\t\tchangedComponents ? this._changeThreshold : undefined,\n\t\t\tparentHas,\n\t\t);\n\t}\n\n\t/**\n\t * Get the single entity matching a query. Throws if zero or more than one match.\n\t * @param withComponents Components the entity must have\n\t * @param withoutComponents Components the entity must not have\n\t * @returns The single matching entity\n\t * @throws If zero or more than one entity matches\n\t */\n\tgetSingleton<\n\t\tWithComponents extends keyof Cfg['components'],\n\t\tWithoutComponents extends keyof Cfg['components'] = never\n\t>(\n\t\twithComponents: ReadonlyArray<WithComponents>,\n\t\twithoutComponents: ReadonlyArray<WithoutComponents> = [] as unknown as ReadonlyArray<WithoutComponents>,\n\t): FilteredEntity<Cfg['components'], WithComponents, WithoutComponents> {\n\t\tconst results = this._entityManager.getEntitiesWithQuery(withComponents, withoutComponents);\n\t\tif (results.length === 0) {\n\t\t\tthrow new Error(`getSingleton: no entity matches query with=[${String(withComponents)}] without=[${String(withoutComponents)}]`);\n\t\t}\n\t\tif (results.length > 1) {\n\t\t\tthrow new Error(`getSingleton: expected 1 entity but found ${results.length} matching query with=[${String(withComponents)}] without=[${String(withoutComponents)}]`);\n\t\t}\n\t\tconst result = results[0];\n\t\tif (!result) throw new Error('getSingleton: unexpected empty result');\n\t\treturn result;\n\t}\n\n\t/**\n\t * Get the single entity matching a query, or undefined if none match.\n\t * Throws if more than one entity matches.\n\t * @param withComponents Components the entity must have\n\t * @param withoutComponents Components the entity must not have\n\t * @returns The single matching entity, or undefined if none match\n\t * @throws If more than one entity matches\n\t */\n\ttryGetSingleton<\n\t\tWithComponents extends keyof Cfg['components'],\n\t\tWithoutComponents extends keyof Cfg['components'] = never\n\t>(\n\t\twithComponents: ReadonlyArray<WithComponents>,\n\t\twithoutComponents: ReadonlyArray<WithoutComponents> = [] as unknown as ReadonlyArray<WithoutComponents>,\n\t): FilteredEntity<Cfg['components'], WithComponents, WithoutComponents> | undefined {\n\t\tconst results = this._entityManager.getEntitiesWithQuery(withComponents, withoutComponents);\n\t\tif (results.length === 0) return undefined;\n\t\tif (results.length > 1) {\n\t\t\tthrow new Error(`tryGetSingleton: expected 0 or 1 entity but found ${results.length} matching query with=[${String(withComponents)}] without=[${String(withoutComponents)}]`);\n\t\t}\n\t\treturn results[0];\n\t}\n\n\t/**\n\t * Remove an entity (and optionally its descendants)\n\t * @param entityId Entity ID to remove\n\t * @param options Options for removal (cascade: true by default)\n\t * @returns true if entity was removed\n\t */\n\tremoveEntity(entityId: number, options?: RemoveEntityOptions): boolean {\n\t\treturn this._entityManager.removeEntity(entityId, options);\n\t}\n\n\t// ==================== Hierarchy Methods ====================\n\n\t/**\n\t * Create an entity as a child of another entity with initial components\n\t * @param parentId The parent entity ID\n\t * @param components Initial components to add\n\t * @returns The created child entity\n\t */\n\tspawnChild<T extends { [K in keyof Cfg['components']]?: Cfg['components'][K] }>(\n\t\tparentId: number,\n\t\tcomponents: T & Record<Exclude<keyof T, keyof Cfg['components']>, never>\n\t): FilteredEntity<Cfg['components'], keyof T & keyof Cfg['components']> {\n\t\tconst entity = this._entityManager.spawnChild(parentId, components);\n\t\tthis._emitHierarchyChanged(entity.id, null, parentId);\n\t\treturn entity;\n\t}\n\n\t/**\n\t * Set the parent of an entity\n\t * @param childId The entity ID to set as a child\n\t * @param parentId The entity ID to set as the parent\n\t */\n\tsetParent(childId: number, parentId: number): this {\n\t\tconst oldParent = this._entityManager.getParent(childId);\n\t\tthis._entityManager.setParent(childId, parentId);\n\t\tthis._emitHierarchyChanged(childId, oldParent, parentId);\n\t\treturn this;\n\t}\n\n\t/**\n\t * Remove the parent relationship for an entity (orphan it)\n\t * @param childId The entity ID to orphan\n\t * @returns true if a parent was removed, false if entity had no parent\n\t */\n\tremoveParent(childId: number): boolean {\n\t\tconst oldParent = this._entityManager.getParent(childId);\n\t\tconst result = this._entityManager.removeParent(childId);\n\t\tif (result) {\n\t\t\tthis._emitHierarchyChanged(childId, oldParent, null);\n\t\t}\n\t\treturn result;\n\t}\n\n\t/**\n\t * Get the parent of an entity\n\t * @param entityId The entity ID to get the parent of\n\t * @returns The parent entity ID, or null if no parent\n\t */\n\tgetParent(entityId: number): number | null {\n\t\treturn this._entityManager.getParent(entityId);\n\t}\n\n\t/**\n\t * Get all children of an entity in insertion order\n\t * @param parentId The parent entity ID\n\t * @returns Readonly array of child entity IDs\n\t */\n\tgetChildren(parentId: number): readonly number[] {\n\t\treturn this._entityManager.getChildren(parentId);\n\t}\n\n\t/**\n\t * Get a child at a specific index\n\t * @param parentId The parent entity ID\n\t * @param index The index of the child\n\t * @returns The child entity ID, or null if index is out of bounds\n\t */\n\tgetChildAt(parentId: number, index: number): number | null {\n\t\treturn this._entityManager.getChildAt(parentId, index);\n\t}\n\n\t/**\n\t * Get the index of a child within its parent's children list\n\t * @param parentId The parent entity ID\n\t * @param childId The child entity ID to find\n\t * @returns The index of the child, or -1 if not found\n\t */\n\tgetChildIndex(parentId: number, childId: number): number {\n\t\treturn this._entityManager.getChildIndex(parentId, childId);\n\t}\n\n\t/**\n\t * Get all ancestors of an entity in order [parent, grandparent, ...]\n\t * @param entityId The entity ID to get ancestors of\n\t * @returns Readonly array of ancestor entity IDs\n\t */\n\tgetAncestors(entityId: number): readonly number[] {\n\t\treturn this._entityManager.getAncestors(entityId);\n\t}\n\n\t/**\n\t * Get all descendants of an entity in depth-first order\n\t * @param entityId The entity ID to get descendants of\n\t * @returns Readonly array of descendant entity IDs\n\t */\n\tgetDescendants(entityId: number): readonly number[] {\n\t\treturn this._entityManager.getDescendants(entityId);\n\t}\n\n\t/**\n\t * Get the root ancestor of an entity (topmost parent), or self if no parent\n\t * @param entityId The entity ID to get the root of\n\t * @returns The root entity ID\n\t */\n\tgetRoot(entityId: number): number {\n\t\treturn this._entityManager.getRoot(entityId);\n\t}\n\n\t/**\n\t * Get siblings of an entity (other children of the same parent)\n\t * @param entityId The entity ID to get siblings of\n\t * @returns Readonly array of sibling entity IDs\n\t */\n\tgetSiblings(entityId: number): readonly number[] {\n\t\treturn this._entityManager.getSiblings(entityId);\n\t}\n\n\t/**\n\t * Check if an entity is a descendant of another entity\n\t * @param entityId The potential descendant ID\n\t * @param ancestorId The potential ancestor ID\n\t * @returns true if entityId is a descendant of ancestorId\n\t */\n\tisDescendantOf(entityId: number, ancestorId: number): boolean {\n\t\treturn this._entityManager.isDescendantOf(entityId, ancestorId);\n\t}\n\n\t/**\n\t * Check if an entity is an ancestor of another entity\n\t * @param entityId The potential ancestor ID\n\t * @param descendantId The potential descendant ID\n\t * @returns true if entityId is an ancestor of descendantId\n\t */\n\tisAncestorOf(entityId: number, descendantId: number): boolean {\n\t\treturn this._entityManager.isAncestorOf(entityId, descendantId);\n\t}\n\n\t/**\n\t * Get all root entities (entities that have children but no parent)\n\t * @returns Readonly array of root entity IDs\n\t */\n\tgetRootEntities(): readonly number[] {\n\t\treturn this._entityManager.getRootEntities();\n\t}\n\n\t/**\n\t * Traverse the hierarchy in parent-first (breadth-first) order.\n\t * Parents are guaranteed to be visited before their children.\n\t * @param callback Function called for each entity with (entityId, parentId, depth)\n\t * @param options Optional traversal options (roots to filter to specific subtrees)\n\t */\n\tforEachInHierarchy(\n\t\tcallback: (entityId: number, parentId: number | null, depth: number) => void,\n\t\toptions?: HierarchyIteratorOptions\n\t): void {\n\t\tthis._entityManager.forEachInHierarchy(callback, options);\n\t}\n\n\t/**\n\t * Generator-based hierarchy traversal in parent-first (breadth-first) order.\n\t * Supports early termination via break.\n\t * @param options Optional traversal options (roots to filter to specific subtrees)\n\t * @yields HierarchyEntry for each entity in parent-first order\n\t */\n\thierarchyIterator(options?: HierarchyIteratorOptions): Generator<HierarchyEntry, void, unknown> {\n\t\treturn this._entityManager.hierarchyIterator(options);\n\t}\n\n\t/**\n\t * Emit a hierarchy changed event\n\t * @internal\n\t */\n\tprivate _emitHierarchyChanged(entityId: number, oldParent: number | null, newParent: number | null): void {\n\t\t// Publish the event - if the user has declared hierarchyChanged in their EventTypes, it will be handled\n\t\ttype HierarchyEventBus = EventBus<{ hierarchyChanged: { entityId: number; oldParent: number | null; newParent: number | null } }>;\n\t\t(this._eventBus as unknown as HierarchyEventBus).publish('hierarchyChanged', { entityId, oldParent, newParent });\n\t}\n\n\t/**\n\t\t* Get all installed plugin IDs\n\t*/\n\tget installedPlugins(): string[] {\n\t\treturn Array.from(this._installedPlugins);\n\t}\n\n\t// Getters for the internal managers\n\tget entityManager() {\n\t\treturn this._entityManager;\n\t}\n\n\tget eventBus() {\n\t\tthis._finalizePendingBuilders();\n\t\treturn this._eventBus;\n\t}\n\n\t/**\n\t * Command buffer for queuing deferred structural changes.\n\t * Commands are executed automatically at the end of each update() cycle.\n\t *\n\t * @example\n\t * ```typescript\n\t * // In a system or event handler\n\t * ecs.commands.removeEntity(entityId);\n\t * ecs.commands.spawn({ position: { x: 0, y: 0 } });\n\t * ```\n\t */\n\tget commands() {\n\t\treturn this._commandBuffer;\n\t}\n\n\t/**\n\t * The current tick number, incremented at the end of each update()\n\t */\n\tget currentTick(): number {\n\t\treturn this._currentTick;\n\t}\n\n\t/**\n\t * The current change detection threshold.\n\t * During system execution, this is the system's last-seen sequence.\n\t * Between updates, this is the global sequence after command buffer playback.\n\t * Manual change detection should compare: getChangeSeq(...) > changeThreshold\n\t */\n\tget changeThreshold(): number {\n\t\treturn this._changeThreshold;\n\t}\n\n\t// ==================== Diagnostics ====================\n\n\t/**\n\t * Toggle diagnostics timing collection. When enabled, system and phase\n\t * timings are recorded each frame. When disabled, timing maps are cleared\n\t * and no overhead is incurred.\n\t */\n\tenableDiagnostics(enabled: boolean): void {\n\t\tthis._diagnosticsEnabled = enabled;\n\t\tif (!enabled) {\n\t\t\tthis._systemTimings.clear();\n\t\t\tthis._phaseTimings = {\n\t\t\t\tpreUpdate: 0, fixedUpdate: 0, update: 0, postUpdate: 0, render: 0,\n\t\t\t};\n\t\t}\n\t}\n\n\tget diagnosticsEnabled(): boolean {\n\t\treturn this._diagnosticsEnabled;\n\t}\n\n\tget systemTimings(): ReadonlyMap<string, number> {\n\t\treturn this._systemTimings;\n\t}\n\n\tget phaseTimings(): Readonly<Record<SystemPhase, number>> {\n\t\treturn this._phaseTimings;\n\t}\n\n\tget entityCount(): number {\n\t\treturn this._entityManager.entityCount;\n\t}\n\n\t/**\n\t * Mutate a component in place and automatically mark it as changed.\n\t * Throws if the entity does not exist or does not have the component.\n\t * @param entityId The entity ID\n\t * @param componentName The component to mutate\n\t * @param mutator A function that receives the component value for in-place mutation\n\t * @returns The mutated component value\n\t */\n\tmutateComponent<K extends keyof Cfg['components']>(\n\t\tentityId: number,\n\t\tcomponentName: K,\n\t\tmutator: (value: Cfg['components'][K]) => void\n\t): Cfg['components'][K] {\n\t\tconst component = this._entityManager.getComponent(entityId, componentName);\n\t\tif (component === undefined) {\n\t\t\tthrow new Error(`Entity ${entityId} does not have component \"${String(componentName)}\"`);\n\t\t}\n\t\tmutator(component);\n\t\tthis._entityManager.markChanged(entityId, componentName);\n\t\treturn component;\n\t}\n\n\t/**\n\t * Mark a component as changed on an entity.\n\t * Each call increments a global monotonic sequence; systems with changed\n\t * queries will see the mark exactly once (on their next execution).\n\t * @param entityId The entity ID\n\t * @param componentName The component that was changed\n\t */\n\tmarkChanged<K extends keyof Cfg['components']>(entityId: number, componentName: K): void {\n\t\tthis._entityManager.markChanged(entityId, componentName);\n\t}\n\n\t// ==================== Component Dispose ====================\n\n\t/**\n\t * Register a dispose callback for a component type.\n\t * Called when a component is removed (explicit removal, entity destruction, or replacement).\n\t * Later registrations replace earlier ones for the same component type.\n\t * @param componentName The component type to register disposal for\n\t * @param callback Function receiving the component value being disposed and the entity ID\n\t */\n\tregisterDispose<K extends keyof Cfg['components']>(\n\t\tcomponentName: K,\n\t\tcallback: (ctx: { value: Cfg['components'][K]; entityId: number }) => void\n\t): void {\n\t\tthis._entityManager.registerDispose(componentName, callback);\n\t}\n\n\t// ==================== Required Components ====================\n\n\t/**\n\t * Register a required component relationship.\n\t * When an entity gains `trigger`, the `required` component is auto-added\n\t * (using `factory` for the default value) if not already present.\n\t * Enforced at insertion time (spawn/addComponent) only — removal is unrestricted.\n\t * @param trigger The component whose presence triggers auto-addition\n\t * @param required The component to auto-add\n\t * @param factory Function that creates the default value for the required component\n\t */\n\tregisterRequired<\n\t\tTrigger extends keyof Cfg['components'],\n\t\tRequired extends keyof Cfg['components'],\n\t>(\n\t\ttrigger: Trigger,\n\t\trequired: Required,\n\t\tfactory: (triggerValue: Cfg['components'][Trigger]) => Cfg['components'][Required]\n\t): void {\n\t\tif (String(trigger) === String(required)) {\n\t\t\tthrow new Error(`Cannot require a component to depend on itself: '${String(trigger)}'`);\n\t\t}\n\n\t\tconst existing = this._requiredComponents.get(trigger) ?? [];\n\n\t\tif (existing.some(r => r.component === required)) {\n\t\t\tthrow new Error(\n\t\t\t\t`Required component '${String(required)}' already registered for trigger '${String(trigger)}'`\n\t\t\t);\n\t\t}\n\n\t\tthis._checkRequiredCycle(trigger, required);\n\n\t\texisting.push({ component: required, factory: factory as (triggerValue: unknown) => unknown });\n\t\tthis._requiredComponents.set(trigger, existing);\n\t}\n\n\t/**\n\t * Check for circular dependencies in the required components graph.\n\t * @throws Error if adding trigger→newRequired would create a cycle\n\t */\n\tprivate _checkRequiredCycle(\n\t\ttrigger: keyof Cfg['components'],\n\t\tnewRequired: keyof Cfg['components']\n\t): void {\n\t\tcheckRequiredCycle(\n\t\t\ttrigger,\n\t\t\tnewRequired,\n\t\t\t(component) => this._requiredComponents.get(component),\n\t\t);\n\t}\n\n\t// ==================== Component Lifecycle Hooks ====================\n\n\t/**\n\t * Register a callback when a specific component is added to any entity\n\t * @param componentName The component key\n\t * @param handler Function receiving the new component value and the entity\n\t * @returns Unsubscribe function to remove the callback\n\t */\n\tonComponentAdded<K extends keyof Cfg['components']>(\n\t\tcomponentName: K,\n\t\thandler: (ctx: { value: Cfg['components'][K]; entity: Entity<Cfg['components']> }) => void\n\t): () => void {\n\t\treturn this._entityManager.onComponentAdded(componentName, handler);\n\t}\n\n\t/**\n\t * Register a callback when a specific component is removed from any entity\n\t * @param componentName The component key\n\t * @param handler Function receiving the old component value and the entity\n\t * @returns Unsubscribe function to remove the callback\n\t */\n\tonComponentRemoved<K extends keyof Cfg['components']>(\n\t\tcomponentName: K,\n\t\thandler: (ctx: { value: Cfg['components'][K]; entity: Entity<Cfg['components']> }) => void\n\t): () => void {\n\t\treturn this._entityManager.onComponentRemoved(componentName, handler);\n\t}\n\n\t// ==================== Reactive Queries ====================\n\n\t/**\n\t * Add a reactive query that triggers callbacks when entities enter/exit the query match.\n\t * @param name Unique name for the query\n\t * @param definition Query definition with with/without arrays and onEnter/onExit callbacks\n\t */\n\taddReactiveQuery<\n\t\tWithComponents extends keyof Cfg['components'],\n\t\tWithoutComponents extends keyof Cfg['components'] = never,\n\t\tOptionalComponents extends keyof Cfg['components'] = never,\n\t>(\n\t\tname: ReactiveQueryNames,\n\t\tdefinition: ReactiveQueryDefinition<Cfg['components'], WithComponents, WithoutComponents, OptionalComponents>\n\t): void {\n\t\tthis._reactiveQueryManager.addQuery(name, definition);\n\t}\n\n\t/**\n\t * Remove a reactive query by name.\n\t * @param name Name of the query to remove\n\t * @returns true if the query existed and was removed, false otherwise\n\t */\n\tremoveReactiveQuery(name: ReactiveQueryNames): boolean {\n\t\treturn this._reactiveQueryManager.removeQuery(name);\n\t}\n\n\t// ==================== Event Convenience Methods ====================\n\n\t/**\n\t * Subscribe to an event (convenience wrapper for eventBus.subscribe)\n\t * @param eventType The event type to subscribe to\n\t * @param callback The callback to invoke when the event is published\n\t * @returns An unsubscribe function\n\t */\n\ton<E extends keyof Cfg['events']>(\n\t\teventType: E,\n\t\tcallback: (data: Cfg['events'][E]) => void\n\t): () => void {\n\t\treturn this._eventBus.subscribe(eventType, callback);\n\t}\n\n\t/**\n\t * Unsubscribe from an event by callback reference (convenience wrapper for eventBus.unsubscribe)\n\t * @param eventType The event type to unsubscribe from\n\t * @param callback The callback to remove\n\t * @returns true if the callback was found and removed, false otherwise\n\t */\n\toff<E extends keyof Cfg['events']>(\n\t\teventType: E,\n\t\tcallback: (data: Cfg['events'][E]) => void\n\t): boolean {\n\t\treturn this._eventBus.unsubscribe(eventType, callback);\n\t}\n\n\t/**\n\t * Register a hook that runs after all systems in update()\n\t * @param callback The hook to call after all systems have processed\n\t * @returns An unsubscribe function to remove the hook\n\t */\n\tonPostUpdate(\n\t\tcallback: (ctx: { ecs: ECSpresso<Cfg>; dt: number }) => void\n\t): () => void {\n\t\tthis._postUpdateHooks.push(callback);\n\t\treturn () => {\n\t\t\tconst index = this._postUpdateHooks.indexOf(callback);\n\t\t\tif (index !== -1) {\n\t\t\t\tthis._postUpdateHooks.splice(index, 1);\n\t\t\t}\n\t\t};\n\t}\n\n\t// ==================== Asset Management ====================\n\n\tprivate requireAssetManager(): AssetManager<Cfg['assets']> {\n\t\tif (!this._assetManager) {\n\t\t\tthrow new Error('Asset manager not configured. Use withAssets() in builder.');\n\t\t}\n\t\treturn this._assetManager;\n\t}\n\n\t/**\n\t * Get a loaded asset by key. Throws if not loaded.\n\t */\n\tgetAsset<K extends keyof Cfg['assets']>(key: K): Cfg['assets'][K] {\n\t\treturn this.requireAssetManager().get(key);\n\t}\n\n\t/**\n\t * Get a loaded asset or undefined if not loaded\n\t */\n\ttryGetAsset<K extends keyof Cfg['assets']>(key: K): Cfg['assets'][K] | undefined {\n\t\treturn this._assetManager?.tryGet(key);\n\t}\n\n\t/**\n\t * Get a handle to an asset with status information\n\t */\n\tgetAssetHandle<K extends keyof Cfg['assets']>(key: K): AssetHandle<Cfg['assets'][K]> {\n\t\treturn this.requireAssetManager().getHandle(key);\n\t}\n\n\t/**\n\t * Check if an asset is loaded\n\t */\n\tisAssetLoaded<K extends keyof Cfg['assets']>(key: K): boolean {\n\t\treturn this._assetManager?.isLoaded(key) ?? false;\n\t}\n\n\t/**\n\t * Load a single asset\n\t */\n\tasync loadAsset<K extends keyof Cfg['assets']>(key: K): Promise<Cfg['assets'][K]> {\n\t\treturn this.requireAssetManager().loadAsset(key);\n\t}\n\n\t/**\n\t * Load all assets in a group\n\t */\n\tasync loadAssetGroup(groupName: AssetGroupNames): Promise<void> {\n\t\treturn this.requireAssetManager().loadAssetGroup(groupName);\n\t}\n\n\t/**\n\t * Check if all assets in a group are loaded\n\t */\n\tisAssetGroupLoaded(groupName: AssetGroupNames): boolean {\n\t\treturn this._assetManager?.isGroupLoaded(groupName) ?? false;\n\t}\n\n\t/**\n\t * Get the loading progress of a group (0-1)\n\t */\n\tgetAssetGroupProgress(groupName: AssetGroupNames): number {\n\t\treturn this._assetManager?.getGroupProgress(groupName) ?? 0;\n\t}\n\n\t// ==================== Screen Management ====================\n\n\tprivate requireScreenManager(): ScreenManager<Cfg['screens']> {\n\t\tif (!this._screenManager) {\n\t\t\tthrow new Error('Screen manager not configured. Use withScreens() in builder.');\n\t\t}\n\t\treturn this._screenManager;\n\t}\n\n\t/**\n\t * Transition to a new screen, clearing the stack\n\t */\n\tasync setScreen<K extends keyof Cfg['screens']>(\n\t\tname: K,\n\t\tconfig: Cfg['screens'][K] extends ScreenDefinition<infer C, any> ? C : never\n\t): Promise<void> {\n\t\treturn this.requireScreenManager().setScreen(name, config);\n\t}\n\n\t/**\n\t * Push a screen onto the stack (overlay)\n\t */\n\tasync pushScreen<K extends keyof Cfg['screens']>(\n\t\tname: K,\n\t\tconfig: Cfg['screens'][K] extends ScreenDefinition<infer C, any> ? C : never\n\t): Promise<void> {\n\t\treturn this.requireScreenManager().pushScreen(name, config);\n\t}\n\n\t/**\n\t * Pop the current screen and return to the previous one\n\t */\n\tasync popScreen(): Promise<void> {\n\t\treturn this.requireScreenManager().popScreen();\n\t}\n\n\t/**\n\t * Get the current screen name\n\t */\n\tgetCurrentScreen(): keyof Cfg['screens'] | null {\n\t\treturn this._screenManager?.getCurrentScreen() ?? null;\n\t}\n\n\t/**\n\t * Get the current screen config (immutable), narrowed to a specific screen.\n\t * Throws if the current screen doesn't match.\n\t */\n\tgetScreenConfig<K extends keyof Cfg['screens'] & string>(screen: K): Cfg['screens'][K] extends ScreenDefinition<infer C, any> ? Readonly<C> : never;\n\t/**\n\t * Get the current screen config (immutable).\n\t * Returns a union of all possible config types.\n\t */\n\tgetScreenConfig(): { [K in keyof Cfg['screens']]: Cfg['screens'][K] extends ScreenDefinition<infer C, any> ? Readonly<C> : never }[keyof Cfg['screens']];\n\tgetScreenConfig(screen?: keyof Cfg['screens'] & string) {\n\t\treturn this.requireScreenManager().getConfig(screen);\n\t}\n\n\t/**\n\t * Get the current screen config narrowed to a specific screen, or undefined if not on that screen.\n\t */\n\ttryGetScreenConfig<K extends keyof Cfg['screens'] & string>(screen: K): (Cfg['screens'][K] extends ScreenDefinition<infer C, any> ? Readonly<C> : never) | undefined;\n\t/**\n\t * Get the current screen config or undefined.\n\t * Returns a union of all possible config types, or undefined.\n\t */\n\ttryGetScreenConfig(): { [K in keyof Cfg['screens']]: Cfg['screens'][K] extends ScreenDefinition<infer C, any> ? Readonly<C> : never }[keyof Cfg['screens']] | undefined;\n\ttryGetScreenConfig(screen?: keyof Cfg['screens'] & string) {\n\t\treturn this._screenManager?.tryGetConfig(screen) ?? undefined;\n\t}\n\n\t/**\n\t * Get the current screen state (mutable), narrowed to a specific screen.\n\t * Throws if the current screen doesn't match.\n\t */\n\tgetScreenState<K extends keyof Cfg['screens'] & string>(screen: K): Cfg['screens'][K] extends ScreenDefinition<any, infer S> ? S : never;\n\t/**\n\t * Get the current screen state (mutable).\n\t * Returns a union of all possible state types.\n\t */\n\tgetScreenState(): { [K in keyof Cfg['screens']]: Cfg['screens'][K] extends ScreenDefinition<any, infer S> ? S : never }[keyof Cfg['screens']];\n\tgetScreenState(screen?: keyof Cfg['screens'] & string) {\n\t\treturn this.requireScreenManager().getState(screen);\n\t}\n\n\t/**\n\t * Get the current screen state narrowed to a specific screen, or undefined if not on that screen.\n\t */\n\ttryGetScreenState<K extends keyof Cfg['screens'] & string>(screen: K): (Cfg['screens'][K] extends ScreenDefinition<any, infer S> ? S : never) | undefined;\n\t/**\n\t * Get the current screen state or undefined.\n\t * Returns a union of all possible state types, or undefined.\n\t */\n\ttryGetScreenState(): { [K in keyof Cfg['screens']]: Cfg['screens'][K] extends ScreenDefinition<any, infer S> ? S : never }[keyof Cfg['screens']] | undefined;\n\ttryGetScreenState(screen?: keyof Cfg['screens'] & string) {\n\t\treturn this._screenManager?.tryGetState(screen) ?? undefined;\n\t}\n\n\t/**\n\t * Update the current screen state, narrowed to a specific screen.\n\t * Throws if the current screen doesn't match.\n\t */\n\tupdateScreenState<K extends keyof Cfg['screens'] & string>(\n\t\tscreen: K,\n\t\tupdate: Partial<Cfg['screens'][K] extends ScreenDefinition<any, infer S> ? S : never> |\n\t\t\t((current: Cfg['screens'][K] extends ScreenDefinition<any, infer S> ? S : never) => Partial<Cfg['screens'][K] extends ScreenDefinition<any, infer S> ? S : never>)\n\t): void;\n\t/**\n\t * Update the current screen state.\n\t */\n\tupdateScreenState<K extends keyof Cfg['screens']>(\n\t\tupdate: Partial<Cfg['screens'][K] extends ScreenDefinition<any, infer S> ? S : never> |\n\t\t\t((current: Cfg['screens'][K] extends ScreenDefinition<any, infer S> ? S : never) => Partial<Cfg['screens'][K] extends ScreenDefinition<any, infer S> ? S : never>)\n\t): void;\n\tupdateScreenState(\n\t\tscreenOrUpdate: unknown,\n\t\tmaybeUpdate?: unknown,\n\t): void {\n\t\tif (typeof screenOrUpdate === 'string') {\n\t\t\tthis.requireScreenManager().updateState(maybeUpdate, screenOrUpdate);\n\t\t} else {\n\t\t\tthis.requireScreenManager().updateState(screenOrUpdate);\n\t\t}\n\t}\n\n\t/**\n\t * Check if a screen is the current screen\n\t */\n\tisCurrentScreen(screenName: keyof Cfg['screens']): boolean {\n\t\treturn this._screenManager?.isCurrent(screenName) ?? false;\n\t}\n\n\t/**\n\t * Check if a screen is active (current or in stack)\n\t */\n\tisScreenActive(screenName: keyof Cfg['screens']): boolean {\n\t\treturn this._screenManager?.isActive(screenName) ?? false;\n\t}\n\n\t/**\n\t * Get the screen stack depth\n\t */\n\tgetScreenStackDepth(): number {\n\t\treturn this._screenManager?.getStackDepth() ?? 0;\n\t}\n\n\t// ==================== Internal Methods ====================\n\n\t/**\n\t * Internal method to set the asset manager and drain pending plugin assets\n\t * @internal Used by ECSpressoBuilder\n\t */\n\t_setAssetManager(manager: AssetManager<Cfg['assets']>): void {\n\t\tthis._assetManager = manager;\n\t\tfor (const [key, definition] of this._pendingPluginAssets) {\n\t\t\tthis._assetManager.register(key, definition as any);\n\t\t}\n\t\tthis._pendingPluginAssets = [];\n\t}\n\n\t/**\n\t * Internal method to set the screen manager and drain pending plugin screens\n\t * @internal Used by ECSpressoBuilder\n\t */\n\t_setScreenManager(manager: ScreenManager<Cfg['screens']>): void {\n\t\tthis._screenManager = manager;\n\t\tfor (const [name, definition] of this._pendingPluginScreens) {\n\t\t\tthis._screenManager.register(name, definition as any);\n\t\t}\n\t\tthis._pendingPluginScreens = [];\n\t}\n\n\t/** @internal */\n\t_hasPendingPluginAssets(): boolean {\n\t\treturn this._pendingPluginAssets.length > 0;\n\t}\n\n\t/** @internal */\n\t_hasPendingPluginScreens(): boolean {\n\t\treturn this._pendingPluginScreens.length > 0;\n\t}\n\n\t/**\n\t * Internal method to set the fixed timestep interval\n\t * @internal Used by ECSpressoBuilder\n\t */\n\t_setFixedDt(dt: number): void {\n\t\tthis._fixedDt = dt;\n\t}\n\n\t/**\n\t * Register an asset definition for deferred registration.\n\t * @internal Used by plugins that need to register assets\n\t */\n\t_registerAsset(key: string, definition: AssetDefinition<unknown>): void {\n\t\tthis._pendingPluginAssets.push([key, definition]);\n\t}\n\n\t/**\n\t * Register a screen definition for deferred registration.\n\t * @internal Used by plugins that need to register screens\n\t */\n\t_registerScreen(name: string, definition: ScreenDefinition<any, any>): void {\n\t\tthis._pendingPluginScreens.push([name, definition]);\n\t}\n\n\t/**\n\t * Install a plugin into this ECSpresso instance.\n\t * Deduplicates by plugin ID. Composite plugins call this in their install function.\n\t */\n\tinstallPlugin(plugin: Plugin<any, any, any, any, any, any>): this {\n\t\t// Prevent duplicate installation of the same plugin\n\t\tif (this._installedPlugins.has(plugin.id)) {\n\t\t\treturn this;\n\t\t}\n\n\t\t// Mark this plugin as installed\n\t\tthis._installedPlugins.add(plugin.id);\n\n\t\t// Call the plugin's install function with this world\n\t\tplugin.install(this as any);\n\n\t\treturn this;\n\t}\n\n\t/**\n\t * Create a plugin factory from the built world's types.\n\t * Returns a definePlugin equivalent with no manual type parameters.\n\t */\n\tpluginFactory(): <\n\t\tPL extends string = never,\n\t\tPG extends string = never,\n\t\tPAG extends string = never,\n\t\tPRQ extends string = never,\n\t>(config: {\n\t\tid: string;\n\t\tinstall: (world: ECSpresso<Cfg>) => void;\n\t}) => Plugin<Cfg, EmptyConfig, PL, PG, PAG, PRQ> {\n\t\treturn definePlugin as unknown as ReturnType<\n\t\t\tECSpresso<Cfg>['pluginFactory']\n\t\t>;\n\t}\n\n\t/**\n\t * Call a helper factory with this world instance, inferring the full world type.\n\t * Eliminates the need for a separate `type ECS = typeof ecs` ceremony.\n\t *\n\t * @example\n\t * ```typescript\n\t * const helpers = ecs.getHelpers(createStateMachineHelpers);\n\t * ```\n\t */\n\tgetHelpers<H>(factory: (world: this) => H): H {\n\t\treturn factory(this);\n\t}\n}\n",
|
|
16
|
+
"import ECSpresso from \"./ecspresso\";\nimport AssetManager, { AssetConfiguratorImpl, createAssetConfigurator } from \"./asset-manager\";\nimport ScreenManager, { ScreenConfiguratorImpl, createScreenConfigurator } from \"./screen-manager\";\nimport type { ResourceFactoryWithDeps, ResourceDirectValue } from \"./resource-manager\";\nimport { definePlugin, type Plugin } from \"./plugin\";\nimport type { WorldConfig, EmptyConfig, ConfigsAreCompatible, MergeConfigs, TypesAreCompatible, RequirementsSatisfied, WithComponents, WithEvents, WithResources } from \"./type-utils\";\nimport type { AssetConfigurator, AssetsResource } from \"./asset-types\";\nimport type { ScreenDefinition, ScreenConfigurator, ScreenResource } from \"./screen-types\";\n\n/**\n * Helper type: finalize built-in resources ($assets, $screen) in the resource map.\n * Auto-injects $assets/$screen when plugins contribute asset/screen types even without\n * explicit withAssets()/withScreens(). Also narrows the AssetGroupNames on $assets.\n */\ntype FinalizeBuiltinResources<Cfg extends WorldConfig, AG extends string> = {\n\treadonly components: Cfg['components'];\n\treadonly events: Cfg['events'];\n\treadonly resources: Omit<Cfg['resources'], '$assets' | '$screen'>\n\t\t& ([keyof Cfg['assets']] extends [never] ? {} : { $assets: AssetsResource<Cfg['assets'], AG> })\n\t\t& ([keyof Cfg['screens']] extends [never] ? {} : { $screen: ScreenResource<Cfg['screens']> });\n\treadonly assets: Cfg['assets'];\n\treadonly screens: Cfg['screens'];\n};\n\n/**\n\t* Builder class for ECSpresso that provides fluent type-safe plugin installation.\n\t* Handles type checking during build process to ensure type safety.\n*/\nexport class ECSpressoBuilder<\n\tCfg extends WorldConfig = EmptyConfig,\n\tLabels extends string = never,\n\tGroups extends string = never,\n\tAssetGroupNames extends string = never,\n\tReactiveQueryNames extends string = never,\n> {\n\t/** Asset configurator for collecting asset definitions */\n\tprivate assetConfigurator: AssetConfiguratorImpl<Cfg['assets']> | null = null;\n\t/** Screen configurator for collecting screen definitions */\n\tprivate screenConfigurator: ScreenConfiguratorImpl<Cfg['screens']> | null = null;\n\t/** Pending resources to add during build */\n\tprivate pendingResources: Array<{ key: string; value: unknown }> = [];\n\t/** Pending dispose callbacks to register during build */\n\tprivate pendingDisposeCallbacks: Array<{ key: string; callback: (ctx: { value: unknown; entityId: number }) => void }> = [];\n\t/** Pending required component registrations to apply during build */\n\tprivate pendingRequiredComponents: Array<{ trigger: string; required: string; factory: (triggerValue: any) => unknown }> = [];\n\t/** Pending plugins to install during build */\n\tprivate pendingPlugins: Plugin<any, any, any, any, any, any>[] = [];\n\t/** Fixed timestep interval (null means use default 1/60) */\n\tprivate _fixedDt: number | null = null;\n\n\tconstructor() {}\n\n\t/**\n\t\t* Add the first plugin when starting with empty types.\n\t\t* This overload allows any plugin to be added to an empty ECSpresso instance.\n\t\t* Only merges the plugin's Provides (PCfg) into accumulated config, not its Requires (PReq).\n\t*/\n\twithPlugin<\n\t\tPCfg extends WorldConfig,\n\t\tPReq extends WorldConfig = EmptyConfig,\n\t\tBL extends string = never,\n\t\tBG extends string = never,\n\t\tBAG extends string = never,\n\t\tBRQ extends string = never,\n\t>(\n\t\tthis: ECSpressoBuilder<{ readonly components: {}; readonly events: {}; readonly resources: {}; readonly assets: Cfg['assets']; readonly screens: Cfg['screens'] }, Labels, Groups, AssetGroupNames, ReactiveQueryNames>,\n\t\tplugin: Plugin<PCfg, PReq, BL, BG, BAG, BRQ>\n\t): ECSpressoBuilder<{\n\t\treadonly components: PCfg['components'];\n\t\treadonly events: PCfg['events'];\n\t\treadonly resources: PCfg['resources'];\n\t\treadonly assets: Cfg['assets'] & PCfg['assets'];\n\t\treadonly screens: Cfg['screens'] & PCfg['screens'];\n\t}, Labels | BL, Groups | BG, AssetGroupNames | BAG, ReactiveQueryNames | BRQ>;\n\n\t/**\n\t\t* Add a subsequent plugin with type checking.\n\t\t* This overload enforces plugin type compatibility and requirement satisfaction.\n\t\t* Only merges the plugin's Provides (PCfg) into accumulated config, not its Requires (PReq).\n\t*/\n\twithPlugin<\n\t\tPCfg extends WorldConfig,\n\t\tPReq extends WorldConfig = EmptyConfig,\n\t\tBL extends string = never,\n\t\tBG extends string = never,\n\t\tBAG extends string = never,\n\t\tBRQ extends string = never,\n\t>(\n\t\tplugin: ConfigsAreCompatible<Cfg, PCfg> extends true\n\t\t\t? RequirementsSatisfied<Cfg, PReq> extends true\n\t\t\t\t? Plugin<PCfg, PReq, BL, BG, BAG, BRQ>\n\t\t\t\t: never\n\t\t\t: never\n\t): ECSpressoBuilder<MergeConfigs<Cfg, PCfg>, Labels | BL, Groups | BG, AssetGroupNames | BAG, ReactiveQueryNames | BRQ>;\n\n\t/**\n\t\t* Implementation of both overloads.\n\t\t* Since the type compatibility is checked in the method signature,\n\t\t* we can safely assume the plugin is compatible here.\n\t*/\n\twithPlugin<\n\t\tPCfg extends WorldConfig,\n\t\tPReq extends WorldConfig = EmptyConfig,\n\t\tBL extends string = never,\n\t\tBG extends string = never,\n\t\tBAG extends string = never,\n\t\tBRQ extends string = never,\n\t>(\n\t\tplugin: Plugin<PCfg, PReq, BL, BG, BAG, BRQ>\n\t): ECSpressoBuilder<MergeConfigs<Cfg, PCfg>, Labels | BL, Groups | BG, AssetGroupNames | BAG, ReactiveQueryNames | BRQ> {\n\t\t// Defer plugin installation to build time\n\t\tthis.pendingPlugins.push(plugin);\n\n\t\t// Return a builder with the updated type parameters\n\t\treturn this as unknown as ECSpressoBuilder<MergeConfigs<Cfg, PCfg>, Labels | BL, Groups | BG, AssetGroupNames | BAG, ReactiveQueryNames | BRQ>;\n\t}\n\n\t/**\n\t * Add application-specific component types to the builder chain.\n\t * This is a pure type-level operation with no runtime cost.\n\t * Conflicts with existing component types (same key, different type) produce a `never` return.\n\t */\n\twithComponentTypes<T extends Record<string, any>>(): TypesAreCompatible<Cfg['components'], T> extends true\n\t\t? ECSpressoBuilder<WithComponents<Cfg, T>, Labels, Groups, AssetGroupNames, ReactiveQueryNames>\n\t\t: never;\n\twithComponentTypes<T extends Record<string, any>>(): ECSpressoBuilder<WithComponents<Cfg, T>, Labels, Groups, AssetGroupNames, ReactiveQueryNames> {\n\t\treturn this as unknown as ECSpressoBuilder<WithComponents<Cfg, T>, Labels, Groups, AssetGroupNames, ReactiveQueryNames>;\n\t}\n\n\t/**\n\t * Add application-specific event types to the builder chain.\n\t * This is a pure type-level operation with no runtime cost.\n\t * Conflicts with existing event types (same key, different type) produce a `never` return.\n\t */\n\twithEventTypes<T extends Record<string, any>>(): TypesAreCompatible<Cfg['events'], T> extends true\n\t\t? ECSpressoBuilder<WithEvents<Cfg, T>, Labels, Groups, AssetGroupNames, ReactiveQueryNames>\n\t\t: never;\n\twithEventTypes<T extends Record<string, any>>(): ECSpressoBuilder<WithEvents<Cfg, T>, Labels, Groups, AssetGroupNames, ReactiveQueryNames> {\n\t\treturn this as unknown as ECSpressoBuilder<WithEvents<Cfg, T>, Labels, Groups, AssetGroupNames, ReactiveQueryNames>;\n\t}\n\n\t/**\n\t * Add application-specific resource types to the builder chain.\n\t * This is a pure type-level operation with no runtime cost.\n\t * Conflicts with existing resource types (same key, different type) produce a `never` return.\n\t */\n\twithResourceTypes<T extends Record<string, any>>(): TypesAreCompatible<Cfg['resources'], T> extends true\n\t\t? ECSpressoBuilder<WithResources<Cfg, T>, Labels, Groups, AssetGroupNames, ReactiveQueryNames>\n\t\t: never;\n\twithResourceTypes<T extends Record<string, any>>(): ECSpressoBuilder<WithResources<Cfg, T>, Labels, Groups, AssetGroupNames, ReactiveQueryNames> {\n\t\treturn this as unknown as ECSpressoBuilder<WithResources<Cfg, T>, Labels, Groups, AssetGroupNames, ReactiveQueryNames>;\n\t}\n\n\t/**\n\t * Add a resource during ECSpresso construction.\n\t *\n\t * When the key matches a pre-declared resource type (via `withResourceTypes`, `create<C,E,R>()`,\n\t * or plugin resources), the value is validated against that type.\n\t * For new keys, the value type is inferred as before.\n\t *\n\t * @param key The resource key\n\t * @param resource The resource value, factory function, or factory with dependencies/disposal\n\t * @returns This builder with updated resource types\n\t */\n\twithResource<K extends keyof Cfg['resources'] & string>(\n\t\tkey: K,\n\t\tresource: Cfg['resources'][K] | ((context: ECSpresso<Cfg>) => Cfg['resources'][K] | Promise<Cfg['resources'][K]>) | ResourceFactoryWithDeps<Cfg['resources'][K], ECSpresso<Cfg>, keyof Cfg['resources'] & string> | ResourceDirectValue<Cfg['resources'][K]>\n\t): ECSpressoBuilder<Cfg, Labels, Groups, AssetGroupNames, ReactiveQueryNames>;\n\twithResource<K extends string, V>(\n\t\tkey: K & ([K] extends [keyof Cfg['resources']] ? [V] extends [Cfg['resources'][K & keyof Cfg['resources']]] ? string : never : string),\n\t\tresource: V | ((context: ECSpresso<WithResources<Cfg, Record<K, V>>>) => V | Promise<V>) | ResourceFactoryWithDeps<V, ECSpresso<WithResources<Cfg, Record<K, V>>>, keyof (Cfg['resources'] & Record<K, V>) & string> | ResourceDirectValue<V>\n\t): ECSpressoBuilder<WithResources<Cfg, Record<K, V>>, Labels, Groups, AssetGroupNames, ReactiveQueryNames>;\n\twithResource(key: string, resource: unknown): ECSpressoBuilder<any, Labels, Groups, AssetGroupNames, ReactiveQueryNames> {\n\t\tthis.pendingResources.push({ key, value: resource });\n\t\treturn this as unknown as ECSpressoBuilder<any, Labels, Groups, AssetGroupNames, ReactiveQueryNames>;\n\t}\n\n\t/**\n\t * Register a dispose callback for a component type during build.\n\t * Called when a component is removed (explicit removal, entity destruction, or replacement).\n\t * @param componentName The component type to register disposal for\n\t * @param callback Function receiving the component value being disposed\n\t * @returns This builder for method chaining\n\t */\n\twithDispose<K extends keyof Cfg['components'] & string>(\n\t\tcomponentName: K,\n\t\tcallback: (ctx: { value: Cfg['components'][K]; entityId: number }) => void\n\t): this {\n\t\tthis.pendingDisposeCallbacks.push({ key: componentName, callback: callback as (ctx: { value: unknown; entityId: number }) => void });\n\t\treturn this;\n\t}\n\n\t/**\n\t * Register a required component relationship during build.\n\t * When an entity gains `trigger`, the `required` component is auto-added\n\t * (using `factory` for the default value) if not already present.\n\t * @param trigger The component whose presence triggers auto-addition\n\t * @param required The component to auto-add\n\t * @param factory Function that creates the default value for the required component\n\t * @returns This builder for method chaining\n\t */\n\twithRequired<\n\t\tTrigger extends keyof Cfg['components'] & string,\n\t\tRequired extends keyof Cfg['components'] & string,\n\t>(\n\t\ttrigger: Trigger,\n\t\trequired: Required,\n\t\tfactory: (triggerValue: Cfg['components'][Trigger]) => Cfg['components'][Required]\n\t): this {\n\t\tthis.pendingRequiredComponents.push({\n\t\t\ttrigger,\n\t\t\trequired,\n\t\t\tfactory: factory as (triggerValue: any) => unknown,\n\t\t});\n\t\treturn this;\n\t}\n\n\t/**\n\t * Configure assets for this ECSpresso instance\n\t * @param configurator Function that receives an AssetConfigurator and returns it after adding assets\n\t * @returns This builder with updated asset types\n\t */\n\twithAssets<NewA extends Record<string, unknown>, NewG extends string = never>(\n\t\tconfigurator: (assets: AssetConfigurator<{}, never>) => AssetConfigurator<NewA, NewG>\n\t): ECSpressoBuilder<{\n\t\treadonly components: Cfg['components'];\n\t\treadonly events: Cfg['events'];\n\t\treadonly resources: Cfg['resources'] & { $assets: AssetsResource<Cfg['assets'] & NewA, string> };\n\t\treadonly assets: Cfg['assets'] & NewA;\n\t\treadonly screens: Cfg['screens'];\n\t}, Labels, Groups, AssetGroupNames | NewG, ReactiveQueryNames> {\n\t\tconst assetConfig = createAssetConfigurator<{}, never>();\n\t\tconfigurator(assetConfig);\n\t\tthis.assetConfigurator = assetConfig as unknown as AssetConfiguratorImpl<Cfg['assets']>;\n\t\treturn this as unknown as ECSpressoBuilder<{\n\t\t\treadonly components: Cfg['components'];\n\t\t\treadonly events: Cfg['events'];\n\t\t\treadonly resources: Cfg['resources'] & { $assets: AssetsResource<Cfg['assets'] & NewA, string> };\n\t\t\treadonly assets: Cfg['assets'] & NewA;\n\t\t\treadonly screens: Cfg['screens'];\n\t\t}, Labels, Groups, AssetGroupNames | NewG, ReactiveQueryNames>;\n\t}\n\n\t/**\n\t * Configure screens for this ECSpresso instance\n\t * @param configurator Function that receives a ScreenConfigurator and returns it after adding screens\n\t * @returns This builder with updated screen types\n\t */\n\twithScreens<NewS extends Record<string, ScreenDefinition<any, any>>>(\n\t\tconfigurator: (screens: ScreenConfigurator<{}, ECSpresso<{\n\t\t\treadonly components: Cfg['components'];\n\t\t\treadonly events: Cfg['events'];\n\t\t\treadonly resources: Cfg['resources'];\n\t\t\treadonly assets: Cfg['assets'];\n\t\t\treadonly screens: Record<string, ScreenDefinition>;\n\t\t}>>) => ScreenConfigurator<NewS, ECSpresso<{\n\t\t\treadonly components: Cfg['components'];\n\t\t\treadonly events: Cfg['events'];\n\t\t\treadonly resources: Cfg['resources'];\n\t\t\treadonly assets: Cfg['assets'];\n\t\t\treadonly screens: Record<string, ScreenDefinition>;\n\t\t}>>\n\t): ECSpressoBuilder<{\n\t\treadonly components: Cfg['components'];\n\t\treadonly events: Cfg['events'];\n\t\treadonly resources: Cfg['resources'] & { $screen: ScreenResource<Cfg['screens'] & NewS> };\n\t\treadonly assets: Cfg['assets'];\n\t\treadonly screens: Cfg['screens'] & NewS;\n\t}, Labels, Groups, AssetGroupNames, ReactiveQueryNames> {\n\t\tconst screenConfig = createScreenConfigurator<{}, ECSpresso<{\n\t\t\treadonly components: Cfg['components'];\n\t\t\treadonly events: Cfg['events'];\n\t\t\treadonly resources: Cfg['resources'];\n\t\t\treadonly assets: Cfg['assets'];\n\t\t\treadonly screens: Record<string, ScreenDefinition>;\n\t\t}>>();\n\t\tconfigurator(screenConfig);\n\t\tthis.screenConfigurator = screenConfig as unknown as ScreenConfiguratorImpl<Cfg['screens']>;\n\t\treturn this as unknown as ECSpressoBuilder<{\n\t\t\treadonly components: Cfg['components'];\n\t\t\treadonly events: Cfg['events'];\n\t\t\treadonly resources: Cfg['resources'] & { $screen: ScreenResource<Cfg['screens'] & NewS> };\n\t\t\treadonly assets: Cfg['assets'];\n\t\t\treadonly screens: Cfg['screens'] & NewS;\n\t\t}, Labels, Groups, AssetGroupNames, ReactiveQueryNames>;\n\t}\n\n\t/**\n\t * Configure the fixed timestep interval for the fixedUpdate phase.\n\t * @param dt The fixed timestep in seconds (e.g., 1/60 for 60Hz physics)\n\t * @returns This builder for method chaining\n\t */\n\twithFixedTimestep(dt: number): this {\n\t\tthis._fixedDt = dt;\n\t\treturn this;\n\t}\n\n\t/**\n\t * Declare reactive query names that will be registered at runtime.\n\t * This is a pure type-level operation with no runtime cost.\n\t */\n\twithReactiveQueryNames<N extends string>(): ECSpressoBuilder<Cfg, Labels, Groups, AssetGroupNames, ReactiveQueryNames | N> {\n\t\treturn this as unknown as ECSpressoBuilder<Cfg, Labels, Groups, AssetGroupNames, ReactiveQueryNames | N>;\n\t}\n\n\t/**\n\t * Create a plugin factory from the builder's accumulated types.\n\t * Returns a definePlugin equivalent with no manual type parameters.\n\t */\n\tpluginFactory(): <\n\t\tPL extends string = never,\n\t\tPG extends string = never,\n\t\tPAG extends string = never,\n\t\tPRQ extends string = never,\n\t>(config: {\n\t\tid: string;\n\t\tinstall: (world: ECSpresso<Cfg>) => void;\n\t}) => Plugin<Cfg, EmptyConfig, PL, PG, PAG, PRQ> {\n\t\treturn ((config: { id: string; install: (world: ECSpresso<any>) => void }) =>\n\t\t\tdefinePlugin(config.id).install(config.install)\n\t\t) as unknown as ReturnType<ECSpressoBuilder<Cfg>['pluginFactory']>;\n\t}\n\n\t/**\n\t\t* Complete the build process and return the built ECSpresso instance\n\t*/\n\tbuild(): ECSpresso<\n\t\tFinalizeBuiltinResources<Cfg, [AssetGroupNames] extends [never] ? string : AssetGroupNames>,\n\t\t[Labels] extends [never] ? string : Labels,\n\t\t[Groups] extends [never] ? string : Groups,\n\t\t[AssetGroupNames] extends [never] ? string : AssetGroupNames,\n\t\t[ReactiveQueryNames] extends [never] ? string : ReactiveQueryNames\n\t> {\n\t\tconst ecspresso = new ECSpresso() as ECSpresso<Cfg>;\n\n\t\t// Install all pending plugins\n\t\tfor (const plugin of this.pendingPlugins) {\n\t\t\tecspresso.installPlugin(plugin);\n\t\t}\n\n\t\t// Apply pending resources\n\t\tfor (const { key, value } of this.pendingResources) {\n\t\t\tecspresso.addResource(key as keyof Cfg['resources'], value as any);\n\t\t}\n\n\t\t// Apply pending dispose callbacks\n\t\tfor (const { key, callback } of this.pendingDisposeCallbacks) {\n\t\t\tecspresso.registerDispose(key as keyof Cfg['components'], callback as (ctx: { value: Cfg['components'][keyof Cfg['components']]; entityId: number }) => void);\n\t\t}\n\n\t\t// Apply pending required component registrations\n\t\tfor (const { trigger, required, factory } of this.pendingRequiredComponents) {\n\t\t\tecspresso.registerRequired(\n\t\t\t\ttrigger as keyof Cfg['components'],\n\t\t\t\trequired as keyof Cfg['components'],\n\t\t\t\tfactory as () => Cfg['components'][keyof Cfg['components']]\n\t\t\t);\n\t\t}\n\n\t\t// Set up asset manager if configured via withAssets(), or auto-create if plugins contributed assets\n\t\tif (this.assetConfigurator) {\n\t\t\tecspresso._setAssetManager(this.assetConfigurator.getManager() as unknown as AssetManager<Cfg['assets']>);\n\t\t} else if (ecspresso._hasPendingPluginAssets()) {\n\t\t\tecspresso._setAssetManager(new AssetManager() as unknown as AssetManager<Cfg['assets']>);\n\t\t}\n\n\t\t// Set up screen manager if configured via withScreens(), or auto-create if plugins contributed screens\n\t\tif (this.screenConfigurator) {\n\t\t\tecspresso._setScreenManager(this.screenConfigurator.getManager() as unknown as ScreenManager<Cfg['screens']>);\n\t\t} else if (ecspresso._hasPendingPluginScreens()) {\n\t\t\tecspresso._setScreenManager(new ScreenManager() as unknown as ScreenManager<Cfg['screens']>);\n\t\t}\n\n\t\t// Set fixed timestep if configured\n\t\tif (this._fixedDt !== null) {\n\t\t\tecspresso._setFixedDt(this._fixedDt);\n\t\t}\n\n\t\treturn ecspresso as unknown as ECSpresso<\n\t\t\tFinalizeBuiltinResources<Cfg, [AssetGroupNames] extends [never] ? string : AssetGroupNames>,\n\t\t\t[Labels] extends [never] ? string : Labels,\n\t\t\t[Groups] extends [never] ? string : Groups,\n\t\t\t[AssetGroupNames] extends [never] ? string : AssetGroupNames,\n\t\t\t[ReactiveQueryNames] extends [never] ? string : ReactiveQueryNames\n\t\t>;\n\t}\n}\n",
|
|
17
|
+
"import EntityManager from \"./entity-manager\";\nimport EventBus from \"./event-bus\";\nimport ResourceManager, { type ResourceFactoryWithDeps, type ResourceDirectValue } from \"./resource-manager\";\nimport AssetManager from \"./asset-manager\";\nimport ScreenManager from \"./screen-manager\";\nimport ReactiveQueryManager, { type ReactiveQueryDefinition } from \"./reactive-query-manager\";\nimport CommandBuffer from \"./command-buffer\";\nimport type { System, SystemPhase, FilteredEntity, Entity, RemoveEntityOptions, HierarchyEntry, HierarchyIteratorOptions } from \"./types\";\nimport { definePlugin, type Plugin } from \"./plugin\";\nimport { SystemBuilder } from \"./system-builder\";\nimport { checkRequiredCycle } from \"./utils/check-required-cycle\";\nimport { version } from \"../package.json\";\nimport type { AssetDefinition, AssetHandle, AssetEvents } from \"./asset-types\";\nimport type { ScreenDefinition, ScreenEvents } from \"./screen-types\";\nimport { ECSpressoBuilder } from \"./ecspresso-builder\";\nimport type { WorldConfig, EmptyConfig } from \"./type-utils\";\n\n/**\n\t* Interface declaration for ECSpresso constructor to ensure type augmentation works properly.\n\t* This merges with the class declaration below.\n*/\nexport default interface ECSpresso<\n\tCfg extends WorldConfig = EmptyConfig,\n\tLabels extends string = string,\n\tGroups extends string = string,\n\tAssetGroupNames extends string = string,\n\tReactiveQueryNames extends string = string,\n> {\n\t/**\n\t\t* Default constructor\n\t*/\n\tnew(): ECSpresso<Cfg, Labels, Groups, AssetGroupNames, ReactiveQueryNames>;\n}\n\nconst PHASE_ORDER: readonly SystemPhase[] = [\n\t'preUpdate', 'fixedUpdate', 'update', 'postUpdate', 'render',\n];\n\n\n/**\n\t* ECSpresso is the central ECS framework class that connects all features.\n\t* It handles creation and management of entities, components, and systems, and provides lifecycle hooks.\n*/\nexport default class ECSpresso<\n\tCfg extends WorldConfig = EmptyConfig,\n\tLabels extends string = string,\n\tGroups extends string = string,\n\tAssetGroupNames extends string = string,\n\tReactiveQueryNames extends string = string,\n> {\n\t// Phantom type property for structural type extraction (no runtime cost).\n\tdeclare readonly _cfg: Cfg;\n\n\t/** Library version*/\n\tpublic static readonly VERSION = version;\n\n\t/** Access/modify stored components and entities*/\n\tprivate _entityManager: EntityManager<Cfg['components']>;\n\t/** Publish/subscribe to events*/\n\tprivate _eventBus: EventBus<Cfg['events']>;\n\t/** Access/modify registered resources*/\n\tprivate _resourceManager: ResourceManager<Cfg['resources'], ECSpresso<Cfg>>;\n\t/** Command buffer for deferred structural changes */\n\tprivate _commandBuffer: CommandBuffer<Cfg>;\n\n\t/** Registered systems that will be updated in order*/\n\tprivate _systems: Array<System<Cfg, any, any>> = [];\n\t/** Systems grouped by execution phase, each sorted by priority */\n\tprivate _phaseSystems: Record<SystemPhase, Array<System<Cfg, any, any>>> = {\n\t\tpreUpdate: [], fixedUpdate: [], update: [], postUpdate: [], render: [],\n\t};\n\t/** Track installed plugins to prevent duplicates*/\n\tprivate _installedPlugins: Set<string> = new Set();\n\t/** Disabled system groups */\n\tprivate _disabledGroups: Set<string> = new Set();\n\t/** Asset manager for loading and accessing assets */\n\tprivate _assetManager: AssetManager<Cfg['assets']> | null = null;\n\t/** Screen manager for state/screen transitions */\n\tprivate _screenManager: ScreenManager<Cfg['screens']> | null = null;\n\t/** Reactive query manager for enter/exit callbacks */\n\tprivate _reactiveQueryManager: ReactiveQueryManager<Cfg['components']>;\n\t/** Post-update hooks to be called after all systems in update() */\n\tprivate _postUpdateHooks: Array<(ctx: { ecs: ECSpresso<Cfg>; dt: number }) => void> = [];\n\t/** Global tick counter, incremented at the end of each update() */\n\tprivate _currentTick: number = 0;\n\t/** Per-system last-seen change sequence for change detection */\n\tprivate _systemLastSeqs: Map<object, number> = new Map();\n\t/** Change threshold used for public getEntitiesWithQuery and between-system resolution */\n\tprivate _changeThreshold: number = 0;\n\t/** Fixed timestep interval in seconds (default: 1/60) */\n\tprivate _fixedDt: number = 1 / 60;\n\t/** Accumulated time for fixed update steps */\n\tprivate _fixedAccumulator: number = 0;\n\t/** Interpolation alpha between fixed steps (accumulator / fixedDt) */\n\tprivate _interpolationAlpha: number = 0;\n\t/** Maximum fixed update steps per frame (spiral-of-death protection) */\n\tprivate _maxFixedSteps: number = 8;\n\t/** Registry of required component relationships: trigger -> [{component, factory}] */\n\tprivate _requiredComponents: Map<keyof Cfg['components'], Array<{ component: keyof Cfg['components']; factory: (triggerValue: unknown) => unknown }>> = new Map();\n\t/** Pending plugin assets awaiting manager creation at build time */\n\tprivate _pendingPluginAssets: Array<[string, AssetDefinition<unknown>]> = [];\n\t/** Pending plugin screens awaiting manager creation at build time */\n\tprivate _pendingPluginScreens: Array<[string, ScreenDefinition<any, any>]> = [];\n\t/** Whether diagnostics timing collection is enabled */\n\tprivate _diagnosticsEnabled: boolean = false;\n\t/** Per-system timing in ms, populated when diagnostics enabled */\n\tprivate _systemTimings: Map<string, number> = new Map();\n\t/** Per-phase timing in ms, populated when diagnostics enabled */\n\tprivate _phaseTimings: Record<SystemPhase, number> = {\n\t\tpreUpdate: 0, fixedUpdate: 0, update: 0, postUpdate: 0, render: 0,\n\t};\n\t/** Per-system per-query seen entity IDs for onEntityEnter tracking */\n\tprivate _entityEnterTracking: Map<object, Map<string, Set<number>>> = new Map();\n\t/** Shared reusable set for per-tick entity enter comparison (avoids allocation) */\n\tprivate _entityEnterFrameSet: Set<number> = new Set();\n\t/** Pre-allocated process context per system (avoids per-frame allocation) */\n\t// eslint-disable-next-line @typescript-eslint/no-explicit-any -- cascades from System<Cfg, any, any>; can't remove without existential types\n\tprivate _systemContexts: WeakMap<object, { queries: Record<string, any>; dt: number; ecs: ECSpresso<Cfg> }> = new WeakMap();\n\t/** Pending system builder finalizers to run before next update/initialize */\n\tprivate _pendingFinalizers: Array<() => void> = [];\n\tprivate _batchingRegistrations = false;\n\n\t/**\n\t\t* Creates a new ECSpresso instance.\n\t*/\n\tconstructor() {\n\t\tthis._entityManager = new EntityManager<Cfg['components']>();\n\t\tthis._eventBus = new EventBus<Cfg['events']>();\n\t\tthis._resourceManager = new ResourceManager<Cfg['resources'], ECSpresso<Cfg>>();\n\t\tthis._reactiveQueryManager = new ReactiveQueryManager<Cfg['components']>(this._entityManager);\n\t\tthis._commandBuffer = new CommandBuffer<Cfg>();\n\n\t\t// Wire up lifecycle hooks for change detection, required components, and reactive queries\n\t\tthis._subscribeLifecycleHooks();\n\t}\n\n\t/**\n\t * Subscribes to EntityManager lifecycle hooks for change detection,\n\t * required component auto-addition, and reactive query tracking.\n\t * @private\n\t */\n\tprivate _subscribeLifecycleHooks(): void {\n\t\t// afterComponentAdded → mark changed + auto-add required components\n\t\tthis._entityManager.onAfterComponentAdded((entityId, componentName) => {\n\t\t\tthis._entityManager.markChanged(entityId, componentName);\n\n\t\t\t// Auto-add required components (recursive via addComponent → this hook)\n\t\t\tconst reqs = this._requiredComponents.get(componentName);\n\t\t\tif (reqs) {\n\t\t\t\tconst entity = this._entityManager.getEntity(entityId);\n\t\t\t\tif (entity) {\n\t\t\t\t\tconst triggerValue = entity.components[componentName];\n\t\t\t\t\tfor (const { component, factory } of reqs) {\n\t\t\t\t\t\tif (this._entityManager._pendingBatchKeys?.has(component)) continue;\n\t\t\t\t\t\tif (!(component in entity.components)) {\n\t\t\t\t\t\t\tthis._entityManager.addComponent(entityId, component, factory(triggerValue) as Cfg['components'][keyof Cfg['components']]);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\t// afterEntityMutated → recheck reactive queries (entity itself + children for parentHas)\n\t\tthis._entityManager.onAfterEntityMutated((entityId) => {\n\t\t\tconst entity = this._entityManager.getEntity(entityId);\n\t\t\tif (entity) {\n\t\t\t\tthis._reactiveQueryManager.recheckEntityAndChildren(entity);\n\t\t\t}\n\t\t});\n\n\t\t// afterComponentRemoved → notify reactive query manager\n\t\tthis._entityManager.onAfterComponentRemoved((entityId, componentName) => {\n\t\t\tconst entity = this._entityManager.getEntity(entityId);\n\t\t\tif (entity) {\n\t\t\t\tthis._reactiveQueryManager.onComponentRemoved(entity, componentName);\n\t\t\t}\n\t\t});\n\n\t\t// beforeEntityRemoved → notify reactive query manager\n\t\tthis._entityManager.onBeforeEntityRemoved((entityId) => {\n\t\t\tthis._reactiveQueryManager.onEntityRemoved(entityId);\n\t\t});\n\n\t\t// afterParentChanged → recheck child entity for parentHas queries\n\t\tthis._entityManager.onAfterParentChanged((childId) => {\n\t\t\tif (this._reactiveQueryManager.hasParentHasQueries) {\n\t\t\t\tconst childEntity = this._entityManager.getEntity(childId);\n\t\t\t\tif (childEntity) {\n\t\t\t\t\tthis._reactiveQueryManager.recheckEntity(childEntity);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t}\n\n\t/**\n\t\t* Creates a new ECSpresso builder for type-safe plugin installation.\n\t\t* Types are inferred from the builder chain — use `.withPlugin()`,\n\t\t* `.withComponentTypes<T>()`, `.withEventTypes<T>()`, and `.withResource()`\n\t\t* to accumulate types without manual aggregate interfaces.\n\t *\n\t\t* @returns A builder instance for fluent method chaining\n\t *\n\t\t* @example\n\t\t* ```typescript\n\t\t* const ecs = ECSpresso.create()\n\t *\t .withPlugin(createRenderer2DPlugin({ ... }))\n\t *\t .withPlugin(createPhysics2DPlugin())\n\t *\t .withComponentTypes<{ player: true; enemy: { type: string } }>()\n\t *\t .withEventTypes<{ gameStart: true }>()\n\t *\t .withResource('score', { value: 0 })\n\t *\t .build();\n\t *\n\t * type ECS = typeof ecs;\n\t\t* ```\n\t*/\n\tstatic create<Cfg2 extends WorldConfig = EmptyConfig>(): ECSpressoBuilder<Cfg2, never, never, never, never> {\n\t\treturn new ECSpressoBuilder<Cfg2, never, never, never, never>();\n\t}\n\n\t/**\n\t\t* Adds a system directly to this ECSpresso instance.\n\t\t* The system is registered when initialize() or update() is next called.\n\t\t* @param label Unique name to identify the system\n\t\t* @returns A SystemBuilder instance for method chaining\n\t*/\n\taddSystem(label: string): SystemBuilder<Cfg> {\n\t\tconst builder = new SystemBuilder<Cfg>(label);\n\t\tthis._pendingFinalizers.push(() => {\n\t\t\tthis._registerSystem(builder._createSystemObject());\n\t\t});\n\t\treturn builder;\n\t}\n\n\t/**\n\t * Finalize and register all pending system builders.\n\t * @private\n\t */\n\tprivate _finalizePendingBuilders(): void {\n\t\tif (this._pendingFinalizers.length === 0) return;\n\t\tthis._batchingRegistrations = true;\n\t\twhile (this._pendingFinalizers.length > 0) {\n\t\t\tconst finalizers = this._pendingFinalizers;\n\t\t\tthis._pendingFinalizers = [];\n\t\t\tfor (const finalize of finalizers) {\n\t\t\t\tfinalize();\n\t\t\t}\n\t\t}\n\t\tthis._batchingRegistrations = false;\n\t\tthis._rebuildPhaseSystems();\n\t}\n\n\t/**\n\t * Update all systems across execution phases.\n\t * Phases run in order: preUpdate -> fixedUpdate -> update -> postUpdate -> render.\n\t * The fixedUpdate phase uses a time accumulator for deterministic fixed-timestep simulation.\n\t * @param deltaTime Time elapsed since the last update (in seconds)\n\t */\n\tupdate(deltaTime: number) {\n\t\tthis._finalizePendingBuilders();\n\t\tconst currentScreen = (this._screenManager?.getCurrentScreen() ?? null) as (keyof Cfg['screens'] & string) | null;\n\t\tconst timing = this._diagnosticsEnabled;\n\n\t\t// 1. preUpdate phase\n\t\tthis._runPhase('preUpdate', deltaTime, currentScreen, timing);\n\n\t\t// 2. fixedUpdate phase — accumulate time and step N times\n\t\tconst fixedT0 = timing ? performance.now() : 0;\n\t\tthis._fixedAccumulator += deltaTime;\n\t\tlet steps = 0;\n\t\twhile (this._fixedAccumulator >= this._fixedDt && steps < this._maxFixedSteps) {\n\t\t\tthis._executePhase(this._phaseSystems.fixedUpdate, this._fixedDt, currentScreen);\n\t\t\tthis._commandBuffer.playback(this);\n\t\t\tthis._fixedAccumulator -= this._fixedDt;\n\t\t\tsteps++;\n\t\t}\n\t\t// Clamp accumulator if we hit the spiral-of-death cap\n\t\tif (this._fixedAccumulator >= this._fixedDt) {\n\t\t\tthis._fixedAccumulator = 0;\n\t\t}\n\t\tif (timing) {\n\t\t\tthis._phaseTimings.fixedUpdate = performance.now() - fixedT0;\n\t\t}\n\t\t// Compute interpolation alpha for render-phase smoothing\n\t\tthis._interpolationAlpha = this._fixedAccumulator / this._fixedDt;\n\n\t\t// 3. update phase\n\t\tthis._runPhase('update', deltaTime, currentScreen, timing);\n\n\t\t// 4. postUpdate phase\n\t\tthis._runPhase('postUpdate', deltaTime, currentScreen, timing);\n\n\t\t// 5. Post-update hooks (between postUpdate and render, preserving existing behavior)\n\t\tfor (const hook of this._postUpdateHooks) {\n\t\t\thook({ ecs: this, dt: deltaTime });\n\t\t}\n\n\t\t// 6. render phase\n\t\tthis._runPhase('render', deltaTime, currentScreen, timing);\n\n\t\t// Set change threshold to current sequence so that public\n\t\t// getEntitiesWithQuery (called between updates) sees command\n\t\t// buffer marks but not stale ones.\n\t\tthis._changeThreshold = this._entityManager.changeSeq;\n\n\t\t// Increment tick counter (frame counter only)\n\t\tthis._currentTick++;\n\t}\n\n\t/**\n\t * Execute all systems in a single phase.\n\t * @private\n\t */\n\tprivate _executePhase(\n\t\tsystems: ReadonlyArray<System<Cfg, any, any>>,\n\t\tdeltaTime: number,\n\t\tcurrentScreen: (keyof Cfg['screens'] & string) | null\n\t): void {\n\t\tfor (const system of systems) {\n\t\t\tif (!system.process && !system.onEntityEnter) continue;\n\n\t\t\t// Group filtering - skip if any of the system's groups is disabled\n\t\t\tif (system.groups?.length) {\n\t\t\t\tlet anyDisabled = false;\n\t\t\t\tfor (const group of system.groups) {\n\t\t\t\t\tif (this._disabledGroups.has(group)) {\n\t\t\t\t\t\tanyDisabled = true;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (anyDisabled) continue;\n\t\t\t}\n\n\t\t\t// Screen filtering - skip if system is restricted to specific screens\n\t\t\tif (system.inScreens?.length) {\n\t\t\t\tif (currentScreen === null || !system.inScreens.includes(currentScreen)) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Screen exclusion - skip if system excludes current screen\n\t\t\tif (system.excludeScreens?.length) {\n\t\t\t\tif (currentScreen !== null && system.excludeScreens.includes(currentScreen)) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Asset requirements - skip if required assets not loaded\n\t\t\tif (system.requiredAssets?.length && this._assetManager) {\n\t\t\t\tlet assetsReady = true;\n\t\t\t\tfor (const assetKey of system.requiredAssets) {\n\t\t\t\t\tif (!this._assetManager.isLoaded(assetKey)) {\n\t\t\t\t\t\tassetsReady = false;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (!assetsReady) continue;\n\t\t\t}\n\n\t\t\t// Set per-system change threshold from its last-seen sequence\n\t\t\tconst systemThreshold = this._systemLastSeqs.get(system) ?? 0;\n\t\t\tthis._changeThreshold = systemThreshold;\n\n\t\t\t// Get or create pre-allocated context for this system\n\t\t\tlet ctx = this._systemContexts.get(system);\n\t\t\tif (!ctx) {\n\t\t\t\tctx = { queries: {}, dt: 0, ecs: this };\n\t\t\t\tthis._systemContexts.set(system, ctx);\n\t\t\t}\n\t\t\tctx.dt = deltaTime;\n\n\t\t\t// Prepare query results for each defined query in the system\n\t\t\tconst queryResults = ctx.queries;\n\t\t\tlet hasResults = false;\n\t\t\tlet hasQueries = false;\n\n\t\t\tif (system.entityQueries) {\n\t\t\t\tfor (const queryName in system.entityQueries) {\n\t\t\t\t\thasQueries = true;\n\n\t\t\t\t\tconst query = system.entityQueries[queryName];\n\n\t\t\t\t\tif (query) {\n\t\t\t\t\t\tconst existing = queryResults[queryName];\n\t\t\t\t\t\tconst output = existing ?? (queryResults[queryName] = []);\n\n\t\t\t\t\t\tthis._entityManager.getEntitiesWithQueryInto(\n\t\t\t\t\t\t\toutput,\n\t\t\t\t\t\t\tquery.with,\n\t\t\t\t\t\t\tquery.without || [],\n\t\t\t\t\t\t\tquery.changed,\n\t\t\t\t\t\t\tquery.changed ? this._changeThreshold : undefined,\n\t\t\t\t\t\t\tquery.parentHas,\n\t\t\t\t\t\t);\n\n\t\t\t\t\t\tif (output.length) {\n\t\t\t\t\t\t\thasResults = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Fire onEntityEnter callbacks before process\n\t\t\tconst enterTracking = this._entityEnterTracking.get(system);\n\t\t\tif (enterTracking && system.onEntityEnter) {\n\t\t\t\tfor (const queryName in system.onEntityEnter) {\n\t\t\t\t\tconst results = queryResults[queryName];\n\t\t\t\t\tconst seenEntities = enterTracking.get(queryName);\n\t\t\t\t\tif (!results || !seenEntities) continue;\n\n\t\t\t\t\tconst callback = system.onEntityEnter[queryName];\n\t\t\t\t\tif (!callback) continue;\n\n\t\t\t\t\t// Build set of current entity IDs for pruning\n\t\t\t\t\tconst frameSet = this._entityEnterFrameSet;\n\t\t\t\t\tframeSet.clear();\n\n\t\t\t\t\tfor (const entity of results) {\n\t\t\t\t\t\tframeSet.add(entity.id);\n\t\t\t\t\t\tif (!seenEntities.has(entity.id)) {\n\t\t\t\t\t\t\tseenEntities.add(entity.id);\n\t\t\t\t\t\t\tcallback({ entity, ecs: this });\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Prune stale entries (entities no longer in query results)\n\t\t\t\t\tfor (const id of seenEntities) {\n\t\t\t\t\t\tif (!frameSet.has(id)) {\n\t\t\t\t\t\t\tseenEntities.delete(id);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Call the system's process function only if there are results or there is no query.\n\t\t\tif (system.process) {\n\t\t\t\tif (this._diagnosticsEnabled) {\n\t\t\t\t\tconst t0 = performance.now();\n\t\t\t\t\tif (hasResults || system.runWhenEmpty) {\n\t\t\t\t\t\tsystem.process(ctx);\n\t\t\t\t\t} else if (!hasQueries) {\n\t\t\t\t\t\tsystem.process(ctx);\n\t\t\t\t\t}\n\t\t\t\t\tthis._systemTimings.set(system.label, performance.now() - t0);\n\t\t\t\t} else if (hasResults || system.runWhenEmpty) {\n\t\t\t\t\tsystem.process(ctx);\n\t\t\t\t} else if (!hasQueries) {\n\t\t\t\t\tsystem.process(ctx);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Record this system's last-seen sequence so it won't re-process these marks\n\t\t\tthis._systemLastSeqs.set(system, this._entityManager.changeSeq);\n\t\t}\n\t}\n\n\t/**\n\t * Execute a non-fixed phase with optional timing, then play back the command buffer.\n\t * @private\n\t */\n\tprivate _runPhase(\n\t\tphase: SystemPhase,\n\t\tdeltaTime: number,\n\t\tcurrentScreen: (keyof Cfg['screens'] & string) | null,\n\t\ttiming: boolean\n\t): void {\n\t\tif (timing) {\n\t\t\tconst t0 = performance.now();\n\t\t\tthis._executePhase(this._phaseSystems[phase], deltaTime, currentScreen);\n\t\t\tthis._phaseTimings[phase] = performance.now() - t0;\n\t\t} else {\n\t\t\tthis._executePhase(this._phaseSystems[phase], deltaTime, currentScreen);\n\t\t}\n\t\tthis._commandBuffer.playback(this);\n\t}\n\n\t/**\n\t * Initialize all resources and systems\n\t * This method:\n\t * 1. Initializes all resources that were added as factory functions\n\t * 2. Sets up asset manager and loads eager assets\n\t * 3. Sets up screen manager\n\t * 4. Calls the onInitialize lifecycle hook on all systems\n\t *\n\t * This is useful for game startup to ensure all resources are ready\n\t * and systems are properly initialized before the game loop begins.\n\t *\n\t * @returns Promise that resolves when everything is initialized\n\t */\n\tasync initialize(): Promise<void> {\n\t\tthis._finalizePendingBuilders();\n\t\tawait this.initializeResources();\n\n\t\t// Set up asset manager if present\n\t\t// Key/value casts are needed because the class generic doesn't constrain ResourceTypes\n\t\t// to contain $assets/$screen — the builder merges them into R at the type level.\n\t\tif (this._assetManager) {\n\t\t\tthis._assetManager.setEventBus(this._eventBus as unknown as EventBus<AssetEvents<keyof Cfg['assets'] & string>>);\n\t\t\tawait this._assetManager.loadEagerAssets();\n\t\t\tthis._resourceManager.add('$assets' as keyof Cfg['resources'], this._assetManager.createResource() as unknown as Cfg['resources'][keyof Cfg['resources']]);\n\t\t}\n\n\t\t// Set up screen manager if present\n\t\tif (this._screenManager) {\n\t\t\tthis._screenManager.setDependencies(\n\t\t\t\tthis._eventBus as unknown as EventBus<ScreenEvents<keyof Cfg['screens'] & string>>,\n\t\t\t\tthis._assetManager,\n\t\t\t\tthis\n\t\t\t);\n\t\t\tthis._resourceManager.add('$screen' as keyof Cfg['resources'], this._screenManager.createResource() as unknown as Cfg['resources'][keyof Cfg['resources']]);\n\t\t}\n\n\t\tfor (const system of this._systems) {\n\t\t\tawait system.onInitialize?.(this);\n\t\t}\n\t}\n\n\t/**\n\t * Initialize specific resources or all resources that were added as factory functions but haven't been initialized yet.\n\t * This is useful when you need to ensure resources are ready before proceeding.\n\t * @param keys Optional array of resource keys to initialize. If not provided, all pending resources will be initialized.\n\t * @returns Promise that resolves when the specified resources are initialized\n\t */\n\tasync initializeResources<K extends keyof Cfg['resources']>(...keys: K[]): Promise<void> {\n\t\tawait this._resourceManager.initializeResources(this, ...keys);\n\t}\n\n\t/**\n\t * Rebuild per-phase system arrays from the flat _systems list.\n\t * Each phase array is sorted by priority (higher first), with\n\t * registration order as tiebreaker.\n\t * @private\n\t */\n\tprivate _rebuildPhaseSystems(): void {\n\t\tfor (const phase of PHASE_ORDER) {\n\t\t\tthis._phaseSystems[phase] = [];\n\t\t}\n\t\tfor (const system of this._systems) {\n\t\t\tconst phase = system.phase ?? 'update';\n\t\t\tthis._phaseSystems[phase].push(system);\n\t\t}\n\t\tfor (const phase of PHASE_ORDER) {\n\t\t\tthis._phaseSystems[phase].sort((a, b) => {\n\t\t\t\tconst priorityA = a.priority ?? 0;\n\t\t\t\tconst priorityB = b.priority ?? 0;\n\t\t\t\treturn priorityB - priorityA; // Higher priority executes first\n\t\t\t});\n\t\t}\n\t}\n\n\t/**\n\t\t* Update the priority of a system\n\t\t* @param label The unique label of the system to update\n\t\t* @param priority The new priority value (higher values execute first)\n\t\t* @returns true if the system was found and updated, false otherwise\n\t*/\n\tupdateSystemPriority(label: Labels, priority: number): boolean {\n\t\tthis._finalizePendingBuilders();\n\t\tconst system = this._systems.find(system => system.label === label);\n\t\tif (!system) return false;\n\n\t\t// Set the new priority\n\t\tsystem.priority = priority;\n\n\t\t// Re-sort the systems array\n\t\tthis._rebuildPhaseSystems();\n\n\t\treturn true;\n\t}\n\n\t/**\n\t * Move a system to a different execution phase at runtime.\n\t * @param label The unique label of the system to move\n\t * @param phase The target phase\n\t * @returns true if the system was found and updated, false otherwise\n\t */\n\tupdateSystemPhase(label: Labels, phase: SystemPhase): boolean {\n\t\tthis._finalizePendingBuilders();\n\t\tconst system = this._systems.find(system => system.label === label);\n\t\tif (!system) return false;\n\n\t\tsystem.phase = phase;\n\t\tthis._rebuildPhaseSystems();\n\n\t\treturn true;\n\t}\n\n\t/**\n\t * The interpolation alpha between fixed update steps.\n\t * Ranges from 0 to <1, representing how far into the next\n\t * fixed step the current frame is. Use in the render phase\n\t * for smooth visual interpolation.\n\t */\n\tget interpolationAlpha(): number {\n\t\treturn this._interpolationAlpha;\n\t}\n\n\t/**\n\t * The configured fixed timestep interval in seconds.\n\t */\n\tget fixedDt(): number {\n\t\treturn this._fixedDt;\n\t}\n\n\t// ==================== System Group Control ====================\n\n\t/**\n\t * Disable a system group. Systems in this group will be skipped during update().\n\t * @param groupName The name of the group to disable\n\t */\n\tdisableSystemGroup(groupName: Groups): void {\n\t\tthis._disabledGroups.add(groupName);\n\t}\n\n\t/**\n\t * Enable a system group. Systems in this group will run during update().\n\t * @param groupName The name of the group to enable\n\t */\n\tenableSystemGroup(groupName: Groups): void {\n\t\tthis._disabledGroups.delete(groupName);\n\t}\n\n\t/**\n\t * Check if a system group is enabled.\n\t * @param groupName The name of the group to check\n\t * @returns true if the group is enabled (or doesn't exist), false if disabled\n\t */\n\tisSystemGroupEnabled(groupName: Groups): boolean {\n\t\treturn !this._disabledGroups.has(groupName);\n\t}\n\n\t/**\n\t * Get all system labels that belong to a specific group.\n\t * @param groupName The name of the group\n\t * @returns Array of system labels in the group\n\t */\n\tgetSystemsInGroup(groupName: Groups): string[] {\n\t\tthis._finalizePendingBuilders();\n\t\treturn this._systems\n\t\t\t.filter(system => system.groups?.includes(groupName))\n\t\t\t.map(system => system.label);\n\t}\n\n\t/**\n\t\t* Remove a system by its label\n\t\t* Calls the system's onDetach method with this ECSpresso instance if defined\n\t\t* @param label The unique label of the system to remove\n\t\t* @returns true if the system was found and removed, false otherwise\n\t*/\n\tremoveSystem(label: Labels): boolean {\n\t\tthis._finalizePendingBuilders();\n\t\tconst index = this._systems.findIndex(system => system.label === label);\n\t\tif (index === -1) return false;\n\n\t\tconst system = this._systems[index];\n\t\t// This should never happen since we just found the system by index\n\t\tif (!system) return false;\n\n\t\t// Call the onDetach lifecycle hook if defined\n\t\tif (system.onDetach) {\n\t\t\tsystem.onDetach(this);\n\t\t}\n\n\t\t// Remove system and clean up per-system tracking\n\t\tthis._systems.splice(index, 1);\n\t\tthis._systemLastSeqs.delete(system);\n\t\tthis._entityEnterTracking.delete(system);\n\n\t\t// Re-sort systems\n\t\tthis._rebuildPhaseSystems();\n\n\t\treturn true;\n\t}\n\n\t/**\n\t\t* Internal method to register a system with this ECSpresso instance\n\t\t* @internal Used by SystemBuilder - replaces direct private property access\n\t*/\n\t_registerSystem(system: System<Cfg, any, any>): void {\n\t\tthis._systems.push(system);\n\t\t// Initialize the system's last-seen sequence to the current change threshold.\n\t\t// Before any update this is 0, so newly added systems see spawn marks.\n\t\t// After updates, the threshold is advanced past consumed marks, so\n\t\t// systems added later don't see stale marks.\n\t\tthis._systemLastSeqs.set(system, this._changeThreshold);\n\t\tif (!this._batchingRegistrations) {\n\t\t\tthis._rebuildPhaseSystems();\n\t\t}\n\n\t\t// Set up entity enter tracking if the system has onEntityEnter handlers\n\t\tif (system.onEntityEnter) {\n\t\t\tconst queryMap = new Map<string, Set<number>>();\n\t\t\tfor (const queryName in system.onEntityEnter) {\n\t\t\t\tqueryMap.set(queryName, new Set());\n\t\t\t}\n\t\t\tthis._entityEnterTracking.set(system, queryMap);\n\t\t}\n\n\t\t// Set up event handlers if they exist\n\t\tif (!system.eventHandlers) return;\n\n\t\tfor (const eventName in system.eventHandlers) {\n\t\t\tconst handler = system.eventHandlers[eventName];\n\t\t\tif (handler) {\n\t\t\t\tthis._eventBus.subscribe(eventName, (data) => {\n\t\t\t\t\thandler({ data, ecs: this });\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t\t* Check if a resource exists\n\t*/\n\thasResource<K extends keyof Cfg['resources']>(key: K): boolean {\n\t\treturn this._resourceManager.has(key);\n\t}\n\n\t/**\n\t * Get a resource by key. Throws if the resource is not found.\n\t * @param key The resource key\n\t * @returns The resource value\n\t * @throws Error if resource not found\n\t * @see tryGetResource — the non-throwing alternative that returns undefined\n\t */\n\tgetResource<K extends keyof Cfg['resources']>(key: K): Cfg['resources'][K] {\n\t\tif (!this._resourceManager.has(key)) {\n\t\t\tthrow new Error(`Resource '${String(key)}' not found. Available resources: [${this.getResourceKeys().map(k => String(k)).join(', ')}]`);\n\t\t}\n\n\t\treturn this._resourceManager.get(key, this);\n\t}\n\n\t/**\n\t * Try to get a resource by key. Returns undefined if the resource is not found.\n\t * Inspired by Bevy's `World::get_resource::<T>()` which returns `Option<&T>`.\n\t *\n\t * Two overloads:\n\t * 1. Known key — full type safety from `ResourceTypes`\n\t * 2. String key with explicit type param — for cross-plugin optional dependencies\n\t *\n\t * @example\n\t * ```typescript\n\t * // Known key (type inferred from ResourceTypes)\n\t * const score = ecs.tryGetResource('score'); // ScoreResource | undefined\n\t *\n\t * // Cross-plugin optional dependency (caller specifies expected type)\n\t * const si = ecs.tryGetResource<SpatialIndex>('spatialIndex') ?? null;\n\t * ```\n\t */\n\ttryGetResource<K extends keyof Cfg['resources']>(key: K): Cfg['resources'][K] | undefined;\n\ttryGetResource<T>(key: unknown extends T ? never : string): T | undefined;\n\ttryGetResource(key: string): unknown {\n\t\tconst k = key as keyof Cfg['resources'];\n\t\tif (!this._resourceManager.has(k)) return undefined;\n\t\treturn this._resourceManager.get(k, this);\n\t}\n\n\t/**\n\t\t* Add a resource to the ECS instance.\n\t\t*\n\t\t* - Plain value → stored directly\n\t\t* - Function → treated as a factory, called with this ECSpresso instance on first access\n\t\t* - `{ factory, dependsOn?, onDispose? }` → factory with dependencies/disposal\n\t\t* - `directValue(val)` → stores the value as-is (use to store functions/classes without invoking them)\n\t*/\n\taddResource<K extends keyof Cfg['resources']>(\n\t\tkey: K,\n\t\tresource:\n\t\t\t| Cfg['resources'][K]\n\t\t\t| ((ecs: ECSpresso<Cfg>) => Cfg['resources'][K] | Promise<Cfg['resources'][K]>)\n\t\t\t| ResourceFactoryWithDeps<Cfg['resources'][K], ECSpresso<Cfg>, keyof Cfg['resources'] & string>\n\t\t\t| ResourceDirectValue<Cfg['resources'][K]>\n\t): this {\n\t\tthis._resourceManager.add(key, resource);\n\t\treturn this;\n\t}\n\n\t/**\n\t\t* Remove a resource from the ECS instance (without calling onDispose)\n\t\t* @param key The resource key to remove\n\t\t* @returns True if the resource was removed, false if it didn't exist\n\t*/\n\tremoveResource<K extends keyof Cfg['resources']>(key: K): boolean {\n\t\treturn this._resourceManager.remove(key);\n\t}\n\n\t/**\n\t * Dispose a single resource, calling its onDispose callback if defined\n\t * @param key The resource key to dispose\n\t * @returns True if the resource existed and was disposed, false if it didn't exist\n\t */\n\tasync disposeResource<K extends keyof Cfg['resources']>(key: K): Promise<boolean> {\n\t\treturn this._resourceManager.disposeResource(key, this);\n\t}\n\n\t/**\n\t * Dispose all initialized resources in reverse dependency order.\n\t * Resources that depend on others are disposed first.\n\t * Calls each resource's onDispose callback if defined.\n\t */\n\tasync disposeResources(): Promise<void> {\n\t\treturn this._resourceManager.disposeResources(this);\n\t}\n\n\t/**\n\t\t* Update an existing resource using an updater function\n\t\t* @param key The resource key to update\n\t\t* @param updater Function that receives the current resource value and returns the new value\n\t\t* @returns This ECSpresso instance for chaining\n\t\t* @throws Error if the resource doesn't exist\n\t*/\n\tupdateResource<K extends keyof Cfg['resources']>(\n\t\tkey: K,\n\t\tupdater: (current: Cfg['resources'][K]) => Cfg['resources'][K]\n\t): this {\n\t\tconst oldValue = this.getResource(key);\n\t\tconst newValue = updater(oldValue);\n\t\tthis._resourceManager.add(key, newValue);\n\t\tthis._resourceManager.notifyChange(key, newValue, oldValue);\n\t\treturn this;\n\t}\n\n\t/**\n\t\t* Set a resource to a plain value.\n\t\t* Unlike updateResource, does not require an updater function.\n\t\t* @param key The resource key to set\n\t\t* @param value The new resource value\n\t\t* @returns This ECSpresso instance for chaining\n\t*/\n\tsetResource<K extends keyof Cfg['resources']>(\n\t\tkey: K,\n\t\tvalue: Cfg['resources'][K]\n\t): this {\n\t\tconst oldValue = this.tryGetResource(key);\n\t\tthis._resourceManager.add(key, value);\n\t\tif (oldValue !== undefined) {\n\t\t\tthis._resourceManager.notifyChange(key, value, oldValue);\n\t\t}\n\t\treturn this;\n\t}\n\n\t/**\n\t\t* Subscribe to changes for a specific resource key.\n\t\t* @param key The resource key to watch\n\t\t* @param callback Function called with (newValue, oldValue) when the resource changes\n\t\t* @returns Unsubscribe function\n\t*/\n\tonResourceChange<K extends keyof Cfg['resources']>(\n\t\tkey: K,\n\t\tcallback: (newValue: Cfg['resources'][K], oldValue: Cfg['resources'][K]) => void\n\t): () => void {\n\t\treturn this._resourceManager.onResourceChange(key, callback);\n\t}\n\n\t/**\n\t\t* Get all resource keys that are currently registered\n\t\t* @returns Array of resource keys\n\t*/\n\tgetResourceKeys(): Array<keyof Cfg['resources']> {\n\t\treturn this._resourceManager.getKeys() as Array<keyof Cfg['resources']>;\n\t}\n\n\t/**\n\t\t* Check if a resource needs initialization (was added as a factory function)\n\t\t* @param key The resource key to check\n\t\t* @returns True if the resource needs initialization\n\t*/\n\tresourceNeedsInitialization<K extends keyof Cfg['resources']>(key: K): boolean {\n\t\treturn this._resourceManager.needsInitialization(key);\n\t}\n\n\t/**\n\t\t* Get an entity by ID.\n\t\t* @param entityId The entity ID\n\t\t* @returns The entity, or undefined if it doesn't exist\n\t*/\n\tgetEntity(entityId: number): Entity<Cfg['components']> | undefined {\n\t\treturn this._entityManager.getEntity(entityId);\n\t}\n\n\t/**\n\t\t* Get a component value from an entity.\n\t\t* @param entityId The entity ID\n\t\t* @param componentName The component to retrieve\n\t\t* @returns The component value, or undefined if the entity doesn't have it\n\t*/\n\tgetComponent<K extends keyof Cfg['components']>(\n\t\tentityId: number,\n\t\tcomponentName: K\n\t): Cfg['components'][K] | undefined {\n\t\treturn this._entityManager.getComponent(entityId, componentName);\n\t}\n\n\t/**\n\t\t* Add or replace a component on an entity.\n\t\t* Triggers component-added callbacks and marks the component as changed.\n\t\t* @param entityId The entity ID\n\t\t* @param componentName The component to add\n\t\t* @param value The component value\n\t*/\n\taddComponent<K extends keyof Cfg['components']>(\n\t\tentityId: number,\n\t\tcomponentName: K,\n\t\tvalue: Cfg['components'][K]\n\t): void {\n\t\tthis._entityManager.addComponent(entityId, componentName, value);\n\t}\n\n\t/**\n\t\t* Add multiple components to an entity at once.\n\t\t* @param entityId The entity ID\n\t\t* @param components Object with component names as keys and component data as values\n\t*/\n\taddComponents<T extends { [K in keyof Cfg['components']]?: Cfg['components'][K] }>(\n\t\tentityId: number,\n\t\tcomponents: T & Record<Exclude<keyof T, keyof Cfg['components']>, never>\n\t): void {\n\t\tthis._entityManager.addComponents(entityId, components);\n\t}\n\n\t/**\n\t\t* Remove a component from an entity.\n\t\t* Triggers component-removed and dispose callbacks.\n\t\t* @param entityId The entity ID\n\t\t* @param componentName The component to remove\n\t*/\n\tremoveComponent<K extends keyof Cfg['components']>(\n\t\tentityId: number,\n\t\tcomponentName: K\n\t): void {\n\t\tthis._entityManager.removeComponent(entityId, componentName);\n\t}\n\n\t/**\n\t\t* Check if an entity has a component\n\t*/\n\thasComponent<K extends keyof Cfg['components']>(\n\t\tentityId: number,\n\t\tcomponentName: K\n\t): boolean {\n\t\tconst component = this._entityManager.getComponent(entityId, componentName);\n\t\treturn component !== undefined;\n\t}\n\n\t/**\n\t\t* Create an entity and add components to it in one call\n\t\t* @param components Object with component names as keys and component data as values\n\t\t* @returns The created entity with all components added\n\t\t*/\n\tspawn<T extends { [K in keyof Cfg['components']]?: Cfg['components'][K] }>(\n\t\tcomponents: T & Record<Exclude<keyof T, keyof Cfg['components']>, never>\n\t): FilteredEntity<Cfg['components'], keyof T & keyof Cfg['components']> {\n\t\tconst entity = this._entityManager.createEntity();\n\t\tthis._entityManager.addComponents(entity.id, components);\n\t\treturn entity as FilteredEntity<Cfg['components'], keyof T & keyof Cfg['components']>;\n\t}\n\n\t/**\n\t\t* Get all entities with specific components\n\t*/\n\tgetEntitiesWithQuery<\n\t\tWithComponents extends keyof Cfg['components'],\n\t\tWithoutComponents extends keyof Cfg['components'] = never\n\t>(\n\t\twithComponents: ReadonlyArray<WithComponents>,\n\t\twithoutComponents: ReadonlyArray<WithoutComponents> = [],\n\t\tchangedComponents?: ReadonlyArray<keyof Cfg['components']>,\n\t\tparentHas?: ReadonlyArray<keyof Cfg['components']>,\n\t): Array<FilteredEntity<Cfg['components'], WithComponents, WithoutComponents>> {\n\t\treturn this._entityManager.getEntitiesWithQuery(\n\t\t\twithComponents,\n\t\t\twithoutComponents,\n\t\t\tchangedComponents,\n\t\t\tchangedComponents ? this._changeThreshold : undefined,\n\t\t\tparentHas,\n\t\t);\n\t}\n\n\t/**\n\t * Get the single entity matching a query. Throws if zero or more than one match.\n\t * @param withComponents Components the entity must have\n\t * @param withoutComponents Components the entity must not have\n\t * @returns The single matching entity\n\t * @throws If zero or more than one entity matches\n\t */\n\tgetSingleton<\n\t\tWithComponents extends keyof Cfg['components'],\n\t\tWithoutComponents extends keyof Cfg['components'] = never\n\t>(\n\t\twithComponents: ReadonlyArray<WithComponents>,\n\t\twithoutComponents: ReadonlyArray<WithoutComponents> = [] as unknown as ReadonlyArray<WithoutComponents>,\n\t): FilteredEntity<Cfg['components'], WithComponents, WithoutComponents> {\n\t\tconst results = this._entityManager.getEntitiesWithQuery(withComponents, withoutComponents);\n\t\tif (results.length === 0) {\n\t\t\tthrow new Error(`getSingleton: no entity matches query with=[${String(withComponents)}] without=[${String(withoutComponents)}]`);\n\t\t}\n\t\tif (results.length > 1) {\n\t\t\tthrow new Error(`getSingleton: expected 1 entity but found ${results.length} matching query with=[${String(withComponents)}] without=[${String(withoutComponents)}]`);\n\t\t}\n\t\tconst result = results[0];\n\t\tif (!result) throw new Error('getSingleton: unexpected empty result');\n\t\treturn result;\n\t}\n\n\t/**\n\t * Get the single entity matching a query, or undefined if none match.\n\t * Throws if more than one entity matches.\n\t * @param withComponents Components the entity must have\n\t * @param withoutComponents Components the entity must not have\n\t * @returns The single matching entity, or undefined if none match\n\t * @throws If more than one entity matches\n\t */\n\ttryGetSingleton<\n\t\tWithComponents extends keyof Cfg['components'],\n\t\tWithoutComponents extends keyof Cfg['components'] = never\n\t>(\n\t\twithComponents: ReadonlyArray<WithComponents>,\n\t\twithoutComponents: ReadonlyArray<WithoutComponents> = [] as unknown as ReadonlyArray<WithoutComponents>,\n\t): FilteredEntity<Cfg['components'], WithComponents, WithoutComponents> | undefined {\n\t\tconst results = this._entityManager.getEntitiesWithQuery(withComponents, withoutComponents);\n\t\tif (results.length === 0) return undefined;\n\t\tif (results.length > 1) {\n\t\t\tthrow new Error(`tryGetSingleton: expected 0 or 1 entity but found ${results.length} matching query with=[${String(withComponents)}] without=[${String(withoutComponents)}]`);\n\t\t}\n\t\treturn results[0];\n\t}\n\n\t/**\n\t * Remove an entity (and optionally its descendants)\n\t * @param entityId Entity ID to remove\n\t * @param options Options for removal (cascade: true by default)\n\t * @returns true if entity was removed\n\t */\n\tremoveEntity(entityId: number, options?: RemoveEntityOptions): boolean {\n\t\treturn this._entityManager.removeEntity(entityId, options);\n\t}\n\n\t// ==================== Hierarchy Methods ====================\n\n\t/**\n\t * Create an entity as a child of another entity with initial components\n\t * @param parentId The parent entity ID\n\t * @param components Initial components to add\n\t * @returns The created child entity\n\t */\n\tspawnChild<T extends { [K in keyof Cfg['components']]?: Cfg['components'][K] }>(\n\t\tparentId: number,\n\t\tcomponents: T & Record<Exclude<keyof T, keyof Cfg['components']>, never>\n\t): FilteredEntity<Cfg['components'], keyof T & keyof Cfg['components']> {\n\t\tconst entity = this._entityManager.spawnChild(parentId, components);\n\t\tthis._emitHierarchyChanged(entity.id, null, parentId);\n\t\treturn entity;\n\t}\n\n\t/**\n\t * Set the parent of an entity\n\t * @param childId The entity ID to set as a child\n\t * @param parentId The entity ID to set as the parent\n\t */\n\tsetParent(childId: number, parentId: number): this {\n\t\tconst oldParent = this._entityManager.getParent(childId);\n\t\tthis._entityManager.setParent(childId, parentId);\n\t\tthis._emitHierarchyChanged(childId, oldParent, parentId);\n\t\treturn this;\n\t}\n\n\t/**\n\t * Remove the parent relationship for an entity (orphan it)\n\t * @param childId The entity ID to orphan\n\t * @returns true if a parent was removed, false if entity had no parent\n\t */\n\tremoveParent(childId: number): boolean {\n\t\tconst oldParent = this._entityManager.getParent(childId);\n\t\tconst result = this._entityManager.removeParent(childId);\n\t\tif (result) {\n\t\t\tthis._emitHierarchyChanged(childId, oldParent, null);\n\t\t}\n\t\treturn result;\n\t}\n\n\t/**\n\t * Get the parent of an entity\n\t * @param entityId The entity ID to get the parent of\n\t * @returns The parent entity ID, or null if no parent\n\t */\n\tgetParent(entityId: number): number | null {\n\t\treturn this._entityManager.getParent(entityId);\n\t}\n\n\t/**\n\t * Get all children of an entity in insertion order\n\t * @param parentId The parent entity ID\n\t * @returns Readonly array of child entity IDs\n\t */\n\tgetChildren(parentId: number): readonly number[] {\n\t\treturn this._entityManager.getChildren(parentId);\n\t}\n\n\t/**\n\t * Get a child at a specific index\n\t * @param parentId The parent entity ID\n\t * @param index The index of the child\n\t * @returns The child entity ID, or null if index is out of bounds\n\t */\n\tgetChildAt(parentId: number, index: number): number | null {\n\t\treturn this._entityManager.getChildAt(parentId, index);\n\t}\n\n\t/**\n\t * Get the index of a child within its parent's children list\n\t * @param parentId The parent entity ID\n\t * @param childId The child entity ID to find\n\t * @returns The index of the child, or -1 if not found\n\t */\n\tgetChildIndex(parentId: number, childId: number): number {\n\t\treturn this._entityManager.getChildIndex(parentId, childId);\n\t}\n\n\t/**\n\t * Get all ancestors of an entity in order [parent, grandparent, ...]\n\t * @param entityId The entity ID to get ancestors of\n\t * @returns Readonly array of ancestor entity IDs\n\t */\n\tgetAncestors(entityId: number): readonly number[] {\n\t\treturn this._entityManager.getAncestors(entityId);\n\t}\n\n\t/**\n\t * Get all descendants of an entity in depth-first order\n\t * @param entityId The entity ID to get descendants of\n\t * @returns Readonly array of descendant entity IDs\n\t */\n\tgetDescendants(entityId: number): readonly number[] {\n\t\treturn this._entityManager.getDescendants(entityId);\n\t}\n\n\t/**\n\t * Get the root ancestor of an entity (topmost parent), or self if no parent\n\t * @param entityId The entity ID to get the root of\n\t * @returns The root entity ID\n\t */\n\tgetRoot(entityId: number): number {\n\t\treturn this._entityManager.getRoot(entityId);\n\t}\n\n\t/**\n\t * Get siblings of an entity (other children of the same parent)\n\t * @param entityId The entity ID to get siblings of\n\t * @returns Readonly array of sibling entity IDs\n\t */\n\tgetSiblings(entityId: number): readonly number[] {\n\t\treturn this._entityManager.getSiblings(entityId);\n\t}\n\n\t/**\n\t * Check if an entity is a descendant of another entity\n\t * @param entityId The potential descendant ID\n\t * @param ancestorId The potential ancestor ID\n\t * @returns true if entityId is a descendant of ancestorId\n\t */\n\tisDescendantOf(entityId: number, ancestorId: number): boolean {\n\t\treturn this._entityManager.isDescendantOf(entityId, ancestorId);\n\t}\n\n\t/**\n\t * Check if an entity is an ancestor of another entity\n\t * @param entityId The potential ancestor ID\n\t * @param descendantId The potential descendant ID\n\t * @returns true if entityId is an ancestor of descendantId\n\t */\n\tisAncestorOf(entityId: number, descendantId: number): boolean {\n\t\treturn this._entityManager.isAncestorOf(entityId, descendantId);\n\t}\n\n\t/**\n\t * Get all root entities (entities that have children but no parent)\n\t * @returns Readonly array of root entity IDs\n\t */\n\tgetRootEntities(): readonly number[] {\n\t\treturn this._entityManager.getRootEntities();\n\t}\n\n\t/**\n\t * Traverse the hierarchy in parent-first (breadth-first) order.\n\t * Parents are guaranteed to be visited before their children.\n\t * @param callback Function called for each entity with (entityId, parentId, depth)\n\t * @param options Optional traversal options (roots to filter to specific subtrees)\n\t */\n\tforEachInHierarchy(\n\t\tcallback: (entityId: number, parentId: number | null, depth: number) => void,\n\t\toptions?: HierarchyIteratorOptions\n\t): void {\n\t\tthis._entityManager.forEachInHierarchy(callback, options);\n\t}\n\n\t/**\n\t * Generator-based hierarchy traversal in parent-first (breadth-first) order.\n\t * Supports early termination via break.\n\t * @param options Optional traversal options (roots to filter to specific subtrees)\n\t * @yields HierarchyEntry for each entity in parent-first order\n\t */\n\thierarchyIterator(options?: HierarchyIteratorOptions): Generator<HierarchyEntry, void, unknown> {\n\t\treturn this._entityManager.hierarchyIterator(options);\n\t}\n\n\t/**\n\t * Emit a hierarchy changed event\n\t * @internal\n\t */\n\tprivate _emitHierarchyChanged(entityId: number, oldParent: number | null, newParent: number | null): void {\n\t\t// Publish the event - if the user has declared hierarchyChanged in their EventTypes, it will be handled\n\t\ttype HierarchyEventBus = EventBus<{ hierarchyChanged: { entityId: number; oldParent: number | null; newParent: number | null } }>;\n\t\t(this._eventBus as unknown as HierarchyEventBus).publish('hierarchyChanged', { entityId, oldParent, newParent });\n\t}\n\n\t/**\n\t\t* Get all installed plugin IDs\n\t*/\n\tget installedPlugins(): string[] {\n\t\treturn Array.from(this._installedPlugins);\n\t}\n\n\t// Getters for the internal managers\n\tget entityManager() {\n\t\treturn this._entityManager;\n\t}\n\n\tget eventBus() {\n\t\tthis._finalizePendingBuilders();\n\t\treturn this._eventBus;\n\t}\n\n\t/**\n\t * Command buffer for queuing deferred structural changes.\n\t * Commands are executed automatically at the end of each update() cycle.\n\t *\n\t * @example\n\t * ```typescript\n\t * // In a system or event handler\n\t * ecs.commands.removeEntity(entityId);\n\t * ecs.commands.spawn({ position: { x: 0, y: 0 } });\n\t * ```\n\t */\n\tget commands() {\n\t\treturn this._commandBuffer;\n\t}\n\n\t/**\n\t * The current tick number, incremented at the end of each update()\n\t */\n\tget currentTick(): number {\n\t\treturn this._currentTick;\n\t}\n\n\t/**\n\t * The current change detection threshold.\n\t * During system execution, this is the system's last-seen sequence.\n\t * Between updates, this is the global sequence after command buffer playback.\n\t * Manual change detection should compare: getChangeSeq(...) > changeThreshold\n\t */\n\tget changeThreshold(): number {\n\t\treturn this._changeThreshold;\n\t}\n\n\t// ==================== Diagnostics ====================\n\n\t/**\n\t * Toggle diagnostics timing collection. When enabled, system and phase\n\t * timings are recorded each frame. When disabled, timing maps are cleared\n\t * and no overhead is incurred.\n\t */\n\tenableDiagnostics(enabled: boolean): void {\n\t\tthis._diagnosticsEnabled = enabled;\n\t\tif (!enabled) {\n\t\t\tthis._systemTimings.clear();\n\t\t\tthis._phaseTimings = {\n\t\t\t\tpreUpdate: 0, fixedUpdate: 0, update: 0, postUpdate: 0, render: 0,\n\t\t\t};\n\t\t}\n\t}\n\n\tget diagnosticsEnabled(): boolean {\n\t\treturn this._diagnosticsEnabled;\n\t}\n\n\tget systemTimings(): ReadonlyMap<string, number> {\n\t\treturn this._systemTimings;\n\t}\n\n\tget phaseTimings(): Readonly<Record<SystemPhase, number>> {\n\t\treturn this._phaseTimings;\n\t}\n\n\tget entityCount(): number {\n\t\treturn this._entityManager.entityCount;\n\t}\n\n\t/**\n\t * Mutate a component in place and automatically mark it as changed.\n\t * Throws if the entity does not exist or does not have the component.\n\t * @param entityId The entity ID\n\t * @param componentName The component to mutate\n\t * @param mutator A function that receives the component value for in-place mutation\n\t * @returns The mutated component value\n\t */\n\tmutateComponent<K extends keyof Cfg['components']>(\n\t\tentityId: number,\n\t\tcomponentName: K,\n\t\tmutator: (value: Cfg['components'][K]) => void\n\t): Cfg['components'][K] {\n\t\tconst component = this._entityManager.getComponent(entityId, componentName);\n\t\tif (component === undefined) {\n\t\t\tthrow new Error(`Entity ${entityId} does not have component \"${String(componentName)}\"`);\n\t\t}\n\t\tmutator(component);\n\t\tthis._entityManager.markChanged(entityId, componentName);\n\t\treturn component;\n\t}\n\n\t/**\n\t * Mark a component as changed on an entity.\n\t * Each call increments a global monotonic sequence; systems with changed\n\t * queries will see the mark exactly once (on their next execution).\n\t * @param entityId The entity ID\n\t * @param componentName The component that was changed\n\t */\n\tmarkChanged<K extends keyof Cfg['components']>(entityId: number, componentName: K): void {\n\t\tthis._entityManager.markChanged(entityId, componentName);\n\t}\n\n\t// ==================== Component Dispose ====================\n\n\t/**\n\t * Register a dispose callback for a component type.\n\t * Called when a component is removed (explicit removal, entity destruction, or replacement).\n\t * Later registrations replace earlier ones for the same component type.\n\t * @param componentName The component type to register disposal for\n\t * @param callback Function receiving the component value being disposed and the entity ID\n\t */\n\tregisterDispose<K extends keyof Cfg['components']>(\n\t\tcomponentName: K,\n\t\tcallback: (ctx: { value: Cfg['components'][K]; entityId: number }) => void\n\t): void {\n\t\tthis._entityManager.registerDispose(componentName, callback);\n\t}\n\n\t// ==================== Required Components ====================\n\n\t/**\n\t * Register a required component relationship.\n\t * When an entity gains `trigger`, the `required` component is auto-added\n\t * (using `factory` for the default value) if not already present.\n\t * Enforced at insertion time (spawn/addComponent) only — removal is unrestricted.\n\t * @param trigger The component whose presence triggers auto-addition\n\t * @param required The component to auto-add\n\t * @param factory Function that creates the default value for the required component\n\t */\n\tregisterRequired<\n\t\tTrigger extends keyof Cfg['components'],\n\t\tRequired extends keyof Cfg['components'],\n\t>(\n\t\ttrigger: Trigger,\n\t\trequired: Required,\n\t\tfactory: (triggerValue: Cfg['components'][Trigger]) => Cfg['components'][Required]\n\t): void {\n\t\tif (String(trigger) === String(required)) {\n\t\t\tthrow new Error(`Cannot require a component to depend on itself: '${String(trigger)}'`);\n\t\t}\n\n\t\tconst existing = this._requiredComponents.get(trigger) ?? [];\n\n\t\tif (existing.some(r => r.component === required)) {\n\t\t\tthrow new Error(\n\t\t\t\t`Required component '${String(required)}' already registered for trigger '${String(trigger)}'`\n\t\t\t);\n\t\t}\n\n\t\tthis._checkRequiredCycle(trigger, required);\n\n\t\texisting.push({ component: required, factory: factory as (triggerValue: unknown) => unknown });\n\t\tthis._requiredComponents.set(trigger, existing);\n\t}\n\n\t/**\n\t * Check for circular dependencies in the required components graph.\n\t * @throws Error if adding trigger→newRequired would create a cycle\n\t */\n\tprivate _checkRequiredCycle(\n\t\ttrigger: keyof Cfg['components'],\n\t\tnewRequired: keyof Cfg['components']\n\t): void {\n\t\tcheckRequiredCycle(\n\t\t\ttrigger,\n\t\t\tnewRequired,\n\t\t\t(component) => this._requiredComponents.get(component),\n\t\t);\n\t}\n\n\t// ==================== Component Lifecycle Hooks ====================\n\n\t/**\n\t * Register a callback when a specific component is added to any entity\n\t * @param componentName The component key\n\t * @param handler Function receiving the new component value and the entity\n\t * @returns Unsubscribe function to remove the callback\n\t */\n\tonComponentAdded<K extends keyof Cfg['components']>(\n\t\tcomponentName: K,\n\t\thandler: (ctx: { value: Cfg['components'][K]; entity: Entity<Cfg['components']> }) => void\n\t): () => void {\n\t\treturn this._entityManager.onComponentAdded(componentName, handler);\n\t}\n\n\t/**\n\t * Register a callback when a specific component is removed from any entity\n\t * @param componentName The component key\n\t * @param handler Function receiving the old component value and the entity\n\t * @returns Unsubscribe function to remove the callback\n\t */\n\tonComponentRemoved<K extends keyof Cfg['components']>(\n\t\tcomponentName: K,\n\t\thandler: (ctx: { value: Cfg['components'][K]; entity: Entity<Cfg['components']> }) => void\n\t): () => void {\n\t\treturn this._entityManager.onComponentRemoved(componentName, handler);\n\t}\n\n\t// ==================== Reactive Queries ====================\n\n\t/**\n\t * Add a reactive query that triggers callbacks when entities enter/exit the query match.\n\t * @param name Unique name for the query\n\t * @param definition Query definition with with/without arrays and onEnter/onExit callbacks\n\t */\n\taddReactiveQuery<\n\t\tWithComponents extends keyof Cfg['components'],\n\t\tWithoutComponents extends keyof Cfg['components'] = never,\n\t\tOptionalComponents extends keyof Cfg['components'] = never,\n\t>(\n\t\tname: ReactiveQueryNames,\n\t\tdefinition: ReactiveQueryDefinition<Cfg['components'], WithComponents, WithoutComponents, OptionalComponents>\n\t): void {\n\t\tthis._reactiveQueryManager.addQuery(name, definition);\n\t}\n\n\t/**\n\t * Remove a reactive query by name.\n\t * @param name Name of the query to remove\n\t * @returns true if the query existed and was removed, false otherwise\n\t */\n\tremoveReactiveQuery(name: ReactiveQueryNames): boolean {\n\t\treturn this._reactiveQueryManager.removeQuery(name);\n\t}\n\n\t// ==================== Event Convenience Methods ====================\n\n\t/**\n\t * Subscribe to an event (convenience wrapper for eventBus.subscribe)\n\t * @param eventType The event type to subscribe to\n\t * @param callback The callback to invoke when the event is published\n\t * @returns An unsubscribe function\n\t */\n\ton<E extends keyof Cfg['events']>(\n\t\teventType: E,\n\t\tcallback: (data: Cfg['events'][E]) => void\n\t): () => void {\n\t\treturn this._eventBus.subscribe(eventType, callback);\n\t}\n\n\t/**\n\t * Unsubscribe from an event by callback reference (convenience wrapper for eventBus.unsubscribe)\n\t * @param eventType The event type to unsubscribe from\n\t * @param callback The callback to remove\n\t * @returns true if the callback was found and removed, false otherwise\n\t */\n\toff<E extends keyof Cfg['events']>(\n\t\teventType: E,\n\t\tcallback: (data: Cfg['events'][E]) => void\n\t): boolean {\n\t\treturn this._eventBus.unsubscribe(eventType, callback);\n\t}\n\n\t/**\n\t * Register a hook that runs after all systems in update()\n\t * @param callback The hook to call after all systems have processed\n\t * @returns An unsubscribe function to remove the hook\n\t */\n\tonPostUpdate(\n\t\tcallback: (ctx: { ecs: ECSpresso<Cfg>; dt: number }) => void\n\t): () => void {\n\t\tthis._postUpdateHooks.push(callback);\n\t\treturn () => {\n\t\t\tconst index = this._postUpdateHooks.indexOf(callback);\n\t\t\tif (index !== -1) {\n\t\t\t\tthis._postUpdateHooks.splice(index, 1);\n\t\t\t}\n\t\t};\n\t}\n\n\t// ==================== Asset Management ====================\n\n\tprivate requireAssetManager(): AssetManager<Cfg['assets']> {\n\t\tif (!this._assetManager) {\n\t\t\tthrow new Error('Asset manager not configured. Use withAssets() in builder.');\n\t\t}\n\t\treturn this._assetManager;\n\t}\n\n\t/**\n\t * Get a loaded asset by key. Throws if not loaded.\n\t */\n\tgetAsset<K extends keyof Cfg['assets']>(key: K): Cfg['assets'][K] {\n\t\treturn this.requireAssetManager().get(key);\n\t}\n\n\t/**\n\t * Get a loaded asset or undefined if not loaded\n\t */\n\ttryGetAsset<K extends keyof Cfg['assets']>(key: K): Cfg['assets'][K] | undefined {\n\t\treturn this._assetManager?.tryGet(key);\n\t}\n\n\t/**\n\t * Get a handle to an asset with status information\n\t */\n\tgetAssetHandle<K extends keyof Cfg['assets']>(key: K): AssetHandle<Cfg['assets'][K]> {\n\t\treturn this.requireAssetManager().getHandle(key);\n\t}\n\n\t/**\n\t * Check if an asset is loaded\n\t */\n\tisAssetLoaded<K extends keyof Cfg['assets']>(key: K): boolean {\n\t\treturn this._assetManager?.isLoaded(key) ?? false;\n\t}\n\n\t/**\n\t * Load a single asset\n\t */\n\tasync loadAsset<K extends keyof Cfg['assets']>(key: K): Promise<Cfg['assets'][K]> {\n\t\treturn this.requireAssetManager().loadAsset(key);\n\t}\n\n\t/**\n\t * Load all assets in a group\n\t */\n\tasync loadAssetGroup(groupName: AssetGroupNames): Promise<void> {\n\t\treturn this.requireAssetManager().loadAssetGroup(groupName);\n\t}\n\n\t/**\n\t * Check if all assets in a group are loaded\n\t */\n\tisAssetGroupLoaded(groupName: AssetGroupNames): boolean {\n\t\treturn this._assetManager?.isGroupLoaded(groupName) ?? false;\n\t}\n\n\t/**\n\t * Get the loading progress of a group (0-1)\n\t */\n\tgetAssetGroupProgress(groupName: AssetGroupNames): number {\n\t\treturn this._assetManager?.getGroupProgress(groupName) ?? 0;\n\t}\n\n\t// ==================== Screen Management ====================\n\n\tprivate requireScreenManager(): ScreenManager<Cfg['screens']> {\n\t\tif (!this._screenManager) {\n\t\t\tthrow new Error('Screen manager not configured. Use withScreens() in builder.');\n\t\t}\n\t\treturn this._screenManager;\n\t}\n\n\t/**\n\t * Transition to a new screen, clearing the stack\n\t */\n\tasync setScreen<K extends keyof Cfg['screens']>(\n\t\tname: K,\n\t\tconfig: Cfg['screens'][K] extends ScreenDefinition<infer C, any> ? C : never\n\t): Promise<void> {\n\t\treturn this.requireScreenManager().setScreen(name, config);\n\t}\n\n\t/**\n\t * Push a screen onto the stack (overlay)\n\t */\n\tasync pushScreen<K extends keyof Cfg['screens']>(\n\t\tname: K,\n\t\tconfig: Cfg['screens'][K] extends ScreenDefinition<infer C, any> ? C : never\n\t): Promise<void> {\n\t\treturn this.requireScreenManager().pushScreen(name, config);\n\t}\n\n\t/**\n\t * Pop the current screen and return to the previous one\n\t */\n\tasync popScreen(): Promise<void> {\n\t\treturn this.requireScreenManager().popScreen();\n\t}\n\n\t/**\n\t * Get the current screen name\n\t */\n\tgetCurrentScreen(): keyof Cfg['screens'] | null {\n\t\treturn this._screenManager?.getCurrentScreen() ?? null;\n\t}\n\n\t/**\n\t * Get the current screen config (immutable), narrowed to a specific screen.\n\t * Throws if the current screen doesn't match.\n\t */\n\tgetScreenConfig<K extends keyof Cfg['screens'] & string>(screen: K): Cfg['screens'][K] extends ScreenDefinition<infer C, any> ? Readonly<C> : never;\n\t/**\n\t * Get the current screen config (immutable).\n\t * Returns a union of all possible config types.\n\t */\n\tgetScreenConfig(): { [K in keyof Cfg['screens']]: Cfg['screens'][K] extends ScreenDefinition<infer C, any> ? Readonly<C> : never }[keyof Cfg['screens']];\n\tgetScreenConfig(screen?: keyof Cfg['screens'] & string) {\n\t\treturn this.requireScreenManager().getConfig(screen);\n\t}\n\n\t/**\n\t * Get the current screen config narrowed to a specific screen, or undefined if not on that screen.\n\t */\n\ttryGetScreenConfig<K extends keyof Cfg['screens'] & string>(screen: K): (Cfg['screens'][K] extends ScreenDefinition<infer C, any> ? Readonly<C> : never) | undefined;\n\t/**\n\t * Get the current screen config or undefined.\n\t * Returns a union of all possible config types, or undefined.\n\t */\n\ttryGetScreenConfig(): { [K in keyof Cfg['screens']]: Cfg['screens'][K] extends ScreenDefinition<infer C, any> ? Readonly<C> : never }[keyof Cfg['screens']] | undefined;\n\ttryGetScreenConfig(screen?: keyof Cfg['screens'] & string) {\n\t\treturn this._screenManager?.tryGetConfig(screen) ?? undefined;\n\t}\n\n\t/**\n\t * Get the current screen state (mutable), narrowed to a specific screen.\n\t * Throws if the current screen doesn't match.\n\t */\n\tgetScreenState<K extends keyof Cfg['screens'] & string>(screen: K): Cfg['screens'][K] extends ScreenDefinition<any, infer S> ? S : never;\n\t/**\n\t * Get the current screen state (mutable).\n\t * Returns a union of all possible state types.\n\t */\n\tgetScreenState(): { [K in keyof Cfg['screens']]: Cfg['screens'][K] extends ScreenDefinition<any, infer S> ? S : never }[keyof Cfg['screens']];\n\tgetScreenState(screen?: keyof Cfg['screens'] & string) {\n\t\treturn this.requireScreenManager().getState(screen);\n\t}\n\n\t/**\n\t * Get the current screen state narrowed to a specific screen, or undefined if not on that screen.\n\t */\n\ttryGetScreenState<K extends keyof Cfg['screens'] & string>(screen: K): (Cfg['screens'][K] extends ScreenDefinition<any, infer S> ? S : never) | undefined;\n\t/**\n\t * Get the current screen state or undefined.\n\t * Returns a union of all possible state types, or undefined.\n\t */\n\ttryGetScreenState(): { [K in keyof Cfg['screens']]: Cfg['screens'][K] extends ScreenDefinition<any, infer S> ? S : never }[keyof Cfg['screens']] | undefined;\n\ttryGetScreenState(screen?: keyof Cfg['screens'] & string) {\n\t\treturn this._screenManager?.tryGetState(screen) ?? undefined;\n\t}\n\n\t/**\n\t * Update the current screen state, narrowed to a specific screen.\n\t * Throws if the current screen doesn't match.\n\t */\n\tupdateScreenState<K extends keyof Cfg['screens'] & string>(\n\t\tscreen: K,\n\t\tupdate: Partial<Cfg['screens'][K] extends ScreenDefinition<any, infer S> ? S : never> |\n\t\t\t((current: Cfg['screens'][K] extends ScreenDefinition<any, infer S> ? S : never) => Partial<Cfg['screens'][K] extends ScreenDefinition<any, infer S> ? S : never>)\n\t): void;\n\t/**\n\t * Update the current screen state.\n\t */\n\tupdateScreenState<K extends keyof Cfg['screens']>(\n\t\tupdate: Partial<Cfg['screens'][K] extends ScreenDefinition<any, infer S> ? S : never> |\n\t\t\t((current: Cfg['screens'][K] extends ScreenDefinition<any, infer S> ? S : never) => Partial<Cfg['screens'][K] extends ScreenDefinition<any, infer S> ? S : never>)\n\t): void;\n\tupdateScreenState(\n\t\tscreenOrUpdate: unknown,\n\t\tmaybeUpdate?: unknown,\n\t): void {\n\t\tif (typeof screenOrUpdate === 'string') {\n\t\t\tthis.requireScreenManager().updateState(maybeUpdate, screenOrUpdate);\n\t\t} else {\n\t\t\tthis.requireScreenManager().updateState(screenOrUpdate);\n\t\t}\n\t}\n\n\t/**\n\t * Check if a screen is the current screen\n\t */\n\tisCurrentScreen(screenName: keyof Cfg['screens']): boolean {\n\t\treturn this._screenManager?.isCurrent(screenName) ?? false;\n\t}\n\n\t/**\n\t * Check if a screen is active (current or in stack)\n\t */\n\tisScreenActive(screenName: keyof Cfg['screens']): boolean {\n\t\treturn this._screenManager?.isActive(screenName) ?? false;\n\t}\n\n\t/**\n\t * Get the screen stack depth\n\t */\n\tgetScreenStackDepth(): number {\n\t\treturn this._screenManager?.getStackDepth() ?? 0;\n\t}\n\n\t// ==================== Internal Methods ====================\n\n\t/**\n\t * Internal method to set the asset manager and drain pending plugin assets\n\t * @internal Used by ECSpressoBuilder\n\t */\n\t_setAssetManager(manager: AssetManager<Cfg['assets']>): void {\n\t\tthis._assetManager = manager;\n\t\tfor (const [key, definition] of this._pendingPluginAssets) {\n\t\t\tthis._assetManager.register(key, definition as any);\n\t\t}\n\t\tthis._pendingPluginAssets = [];\n\t}\n\n\t/**\n\t * Internal method to set the screen manager and drain pending plugin screens\n\t * @internal Used by ECSpressoBuilder\n\t */\n\t_setScreenManager(manager: ScreenManager<Cfg['screens']>): void {\n\t\tthis._screenManager = manager;\n\t\tfor (const [name, definition] of this._pendingPluginScreens) {\n\t\t\tthis._screenManager.register(name, definition as any);\n\t\t}\n\t\tthis._pendingPluginScreens = [];\n\t}\n\n\t/** @internal */\n\t_hasPendingPluginAssets(): boolean {\n\t\treturn this._pendingPluginAssets.length > 0;\n\t}\n\n\t/** @internal */\n\t_hasPendingPluginScreens(): boolean {\n\t\treturn this._pendingPluginScreens.length > 0;\n\t}\n\n\t/**\n\t * Internal method to set the fixed timestep interval\n\t * @internal Used by ECSpressoBuilder\n\t */\n\t_setFixedDt(dt: number): void {\n\t\tthis._fixedDt = dt;\n\t}\n\n\t/**\n\t * Register an asset definition for deferred registration.\n\t * @internal Used by plugins that need to register assets\n\t */\n\t_registerAsset(key: string, definition: AssetDefinition<unknown>): void {\n\t\tthis._pendingPluginAssets.push([key, definition]);\n\t}\n\n\t/**\n\t * Register a screen definition for deferred registration.\n\t * @internal Used by plugins that need to register screens\n\t */\n\t_registerScreen(name: string, definition: ScreenDefinition<any, any>): void {\n\t\tthis._pendingPluginScreens.push([name, definition]);\n\t}\n\n\t/**\n\t * Install a plugin into this ECSpresso instance.\n\t * Deduplicates by plugin ID. Composite plugins call this in their install function.\n\t */\n\tinstallPlugin(plugin: Plugin<any, any, any, any, any, any>): this {\n\t\t// Prevent duplicate installation of the same plugin\n\t\tif (this._installedPlugins.has(plugin.id)) {\n\t\t\treturn this;\n\t\t}\n\n\t\t// Mark this plugin as installed\n\t\tthis._installedPlugins.add(plugin.id);\n\n\t\t// Call the plugin's install function with this world\n\t\tplugin.install(this as any);\n\n\t\treturn this;\n\t}\n\n\t/**\n\t * Create a plugin factory from the built world's types.\n\t * Returns a definePlugin equivalent with no manual type parameters.\n\t */\n\tpluginFactory(): <\n\t\tPL extends string = never,\n\t\tPG extends string = never,\n\t\tPAG extends string = never,\n\t\tPRQ extends string = never,\n\t>(config: {\n\t\tid: string;\n\t\tinstall: (world: ECSpresso<Cfg>) => void;\n\t}) => Plugin<Cfg, EmptyConfig, PL, PG, PAG, PRQ> {\n\t\treturn ((config: { id: string; install: (world: ECSpresso<any>) => void }) =>\n\t\t\tdefinePlugin(config.id).install(config.install)\n\t\t) as unknown as ReturnType<\n\t\t\tECSpresso<Cfg>['pluginFactory']\n\t\t>;\n\t}\n\n\t/**\n\t * Call a helper factory with this world instance, inferring the full world type.\n\t * Eliminates the need for a separate `type ECS = typeof ecs` ceremony.\n\t *\n\t * @example\n\t * ```typescript\n\t * const helpers = ecs.getHelpers(createStateMachineHelpers);\n\t * ```\n\t */\n\tgetHelpers<H>(factory: (world: this) => H): H {\n\t\treturn factory(this);\n\t}\n}\n",
|
|
18
18
|
"import ECSpresso from \"./ecspresso\";\nimport type { WorldConfig, EmptyConfig, WorldConfigFrom } from \"./type-utils\";\n\n/**\n * Execution phase for systems. Systems are grouped by phase and executed\n * in this fixed order: preUpdate -> fixedUpdate -> update -> postUpdate -> render.\n * Within each phase, systems are sorted by priority (higher first).\n */\nexport type SystemPhase = 'preUpdate' | 'fixedUpdate' | 'update' | 'postUpdate' | 'render';\n\nexport\ninterface Entity<ComponentTypes> {\n\tid: number;\n\tcomponents: Partial<ComponentTypes>;\n}\n\n/**\n * Options for removing an entity\n */\nexport\ninterface RemoveEntityOptions {\n\t/**\n\t * Whether to also remove all descendants (default: true)\n\t */\n\tcascade?: boolean;\n}\n\n/**\n * Options for hierarchy traversal methods\n */\nexport\ninterface HierarchyIteratorOptions {\n\t/** Specific root entities to start traversal from. If not provided, all root entities are used. */\n\troots?: readonly number[];\n}\n\n/**\n * Entry yielded during hierarchy traversal\n */\nexport\ninterface HierarchyEntry {\n\t/** The entity being visited */\n\tentityId: number;\n\t/** The parent entity ID, or null for root entities */\n\tparentId: number | null;\n\t/** Depth in the hierarchy (0 for roots) */\n\tdepth: number;\n}\n\nexport\ninterface FilteredEntity<\n\tComponentTypes,\n\tWithComponents extends keyof ComponentTypes = never,\n\tWithoutComponents extends keyof ComponentTypes = never,\n\tOptionalComponents extends keyof ComponentTypes = never,\n> {\n\tid: number;\n\tcomponents: Omit<Partial<ComponentTypes>, WithoutComponents | OptionalComponents> & {\n\t\t[K in WithComponents]: ComponentTypes[K]\n\t} & {\n\t\t[K in OptionalComponents]: ComponentTypes[K] | undefined\n\t};\n}\n\nexport\ninterface QueryConfig<\n\tComponentTypes,\n\tWithComponents extends keyof ComponentTypes,\n\tWithoutComponents extends keyof ComponentTypes,\n\tOptionalComponents extends keyof ComponentTypes = WithComponents,\n> {\n\twith: ReadonlyArray<WithComponents>;\n\twithout?: ReadonlyArray<WithoutComponents>;\n\tchanged?: ReadonlyArray<WithComponents>;\n\toptional?: ReadonlyArray<OptionalComponents>;\n\tparentHas?: ReadonlyArray<keyof ComponentTypes>;\n}\n\n/**\n * Utility type to derive the entity type that would result from a query definition.\n * This is useful for creating helper functions that operate on query results.\n *\n * @example\n * ```typescript\n * const queryDef = {\n * with: ['position', 'sprite'],\n * without: ['dead']\n * };\n *\n * type EntityType = QueryResultEntity<Components, typeof queryDef>;\n *\n * function updateSpritePosition(entity: EntityType) {\n * entity.components.sprite.position.set(\n * entity.components.position.x,\n * entity.components.position.y\n * );\n * }\n * ```\n */\nexport type QueryResultEntity<\n\tComponentTypes extends Record<string, any>,\n\tQueryDef extends {\n\t\twith: ReadonlyArray<keyof ComponentTypes>;\n\t\twithout?: ReadonlyArray<keyof ComponentTypes>;\n\t\tchanged?: ReadonlyArray<keyof ComponentTypes>;\n\t\toptional?: ReadonlyArray<keyof ComponentTypes>;\n\t\tparentHas?: ReadonlyArray<keyof ComponentTypes>;\n\t}\n> = FilteredEntity<\n\tComponentTypes,\n\tQueryDef['with'][number],\n\tQueryDef['without'] extends ReadonlyArray<any> ? QueryDef['without'][number] : never,\n\tQueryDef['optional'] extends ReadonlyArray<any> ? QueryDef['optional'][number] : never\n>;\n\n/**\n * Simplified query definition type for creating reusable queries\n */\nexport type QueryDefinition<\n\tComponentTypes extends Record<string, any>,\n\tWithComponents extends keyof ComponentTypes = keyof ComponentTypes,\n\tWithoutComponents extends keyof ComponentTypes = keyof ComponentTypes,\n\tOptionalComponents extends keyof ComponentTypes = keyof ComponentTypes,\n> = {\n\twith: ReadonlyArray<WithComponents>;\n\twithout?: ReadonlyArray<WithoutComponents>;\n\tchanged?: ReadonlyArray<WithComponents>;\n\toptional?: ReadonlyArray<OptionalComponents>;\n\tparentHas?: ReadonlyArray<keyof ComponentTypes>;\n};\n\n/**\n * Helper function to create a query definition with proper type inference.\n * This enables better TypeScript inference when creating reusable queries.\n *\n * @example\n * ```typescript\n * const movingEntitiesQuery = createQueryDefinition({\n * with: ['position', 'velocity'],\n * without: ['dead']\n * });\n *\n * type MovingEntity = QueryResultEntity<Components, typeof movingEntitiesQuery>;\n *\n * function updatePosition(entity: MovingEntity) {\n * entity.components.position.x += entity.components.velocity.x;\n * entity.components.position.y += entity.components.velocity.y;\n * }\n *\n * world.addSystem('movement')\n * .addQuery('entities', movingEntitiesQuery)\n * .setProcess(({ queries }) => {\n * for (const entity of queries.entities) {\n * updatePosition(entity);\n * }\n * });\n * ```\n */\nexport function createQueryDefinition<\n\tComponentTypes extends Record<string, any>,\n\tconst QueryDef extends {\n\t\twith: ReadonlyArray<keyof ComponentTypes>;\n\t\twithout?: ReadonlyArray<keyof ComponentTypes>;\n\t\tchanged?: ReadonlyArray<keyof ComponentTypes>;\n\t\toptional?: ReadonlyArray<keyof ComponentTypes>;\n\t\tparentHas?: ReadonlyArray<keyof ComponentTypes>;\n\t}\n>(queryDef: QueryDef): QueryDef {\n\treturn queryDef;\n}\n\nexport\ninterface System<\n\tCfg extends WorldConfig = EmptyConfig,\n\tWithComponents extends keyof Cfg['components'] = never,\n\tWithoutComponents extends keyof Cfg['components'] = never,\n> {\n\tlabel: string;\n\t/**\n\t * System priority - higher values execute first (default: 0)\n\t * When systems have the same priority, they execute in registration order\n\t */\n\tpriority?: number;\n\t/**\n\t * Execution phase for this system (default: 'update')\n\t * Systems are grouped by phase and executed in order:\n\t * preUpdate -> fixedUpdate -> update -> postUpdate -> render\n\t */\n\tphase?: SystemPhase;\n\t/**\n\t * Groups this system belongs to. If any group is disabled, the system will be skipped.\n\t */\n\tgroups?: string[];\n\t/**\n\t * Screens where this system should run. If specified, system only runs\n\t * when current screen is in this list.\n\t */\n\tinScreens?: ReadonlyArray<keyof Cfg['screens'] & string>;\n\t/**\n\t * Screens where this system should NOT run. If specified, system skips\n\t * when current screen is in this list.\n\t */\n\texcludeScreens?: ReadonlyArray<keyof Cfg['screens'] & string>;\n\t/**\n\t * Assets that must be loaded for this system to run.\n\t * System will be skipped if any required asset is not loaded.\n\t */\n\trequiredAssets?: ReadonlyArray<keyof Cfg['assets'] & string>;\n\t/**\n\t * When true, the system's process function runs even when all queries\n\t * return zero entities. Default is false (system is skipped when all\n\t * queries are empty).\n\t */\n\trunWhenEmpty?: boolean;\n\tentityQueries?: {\n\t\t[queryName: string]: QueryConfig<Cfg['components'], WithComponents, WithoutComponents>;\n\t};\n\t/**\n\t * Process method that runs during each update cycle.\n\t * Receives a single context object with queries, dt, and ecs.\n\t */\n\tprocess?(ctx: {\n\t\tqueries: {\n\t\t\t[queryName: string]: Array<FilteredEntity<Cfg['components'], WithComponents, WithoutComponents>>;\n\t\t};\n\t\tdt: number;\n\t\tecs: ECSpresso<Cfg>;\n\t}): void;\n\n\t/**\n\t * Lifecycle hook called when the system is initialized\n\t * This is called when ECSpresso.initialize() is invoked, after resources are initialized\n\t * Use this for one-time initialization that depends on resources\n\t * @param ecs The ECSpresso instance providing access to all ECS functionality\n\t */\n\tonInitialize?(\n\t\tecs: ECSpresso<Cfg>\n\t): void | Promise<void>;\n\n\t/**\n\t * Lifecycle hook called when the system is detached from the ECS\n\t * @param ecs The ECSpresso instance providing access to all ECS functionality\n\t */\n\tonDetach?(\n\t\tecs: import(\"./ecspresso\").default<Cfg>\n\t): void;\n\n\t/**\n\t * Per-query callbacks that fire once per entity the first time it appears\n\t * in a query's results. Fires before process. Automatic cleanup when\n\t * entity leaves query (component removed, entity destroyed) so re-entry\n\t * fires the callback again.\n\t */\n\tonEntityEnter?: Record<string, (ctx: { entity: FilteredEntity<Cfg['components'], WithComponents, WithoutComponents>; ecs: ECSpresso<Cfg> }) => void>;\n\n\t/**\n\t * Event handlers for specific event types\n\t */\n\teventHandlers?: {\n\t\t[EventName in keyof Cfg['events']]?: (ctx: {\n\t\t\tdata: Cfg['events'][EventName];\n\t\t\tecs: ECSpresso<Cfg>;\n\t\t}) => void;\n\t};\n}\n\n// ==================== Base World ====================\n\n/**\n * Typed world interface for plugin helpers and structural typing.\n *\n * Generic over component types `C`:\n * - `BaseWorld` (no param): defaults to `{}`, meaning component-accessing methods\n * cannot be called (keys resolve to `never`). Use for functions that only need\n * `removeEntity`, `getResource`, etc.\n * - `BaseWorld<MyComponents>`: narrows `getComponent`, `hasComponent`, `markChanged`,\n * `spawn`, and command buffer methods to the declared component map.\n *\n * Structural typing ensures any `ECSpresso<Cfg>` where `Cfg['components']` is a\n * superset of `C` satisfies `BaseWorld<C>`.\n */\ntype _BaseWorldCfg<C extends Record<string, any>> = WorldConfigFrom<C, Record<string, any>, Record<string, any>, Record<string, unknown>, Record<string, any>>;\ntype _EventBus = import(\"./event-bus\").default<Record<string, any>>;\nexport type BaseWorld<C extends Record<string, any> = {}> = Pick<ECSpresso<_BaseWorldCfg<C>>,\n\t| 'getComponent'\n\t| 'hasComponent'\n\t| 'removeEntity'\n\t| 'spawn'\n\t| 'markChanged'\n\t| 'getResource'\n\t| 'hasResource'\n> & {\n\teventBus: Pick<_EventBus, 'publish'>;\n\tcommands: Pick<import(\"./command-buffer\").default<_BaseWorldCfg<C>>, 'spawn' | 'removeEntity' | 'addComponent' | 'removeComponent'>;\n};\n\n// Re-export utility types from type-utils\nexport type { Merge, MergeAll, TypesAreCompatible, ComponentsOf, EventsOf, ResourcesOf, LabelsOf, GroupsOf, AssetGroupNamesOf, ReactiveQueryNamesOf, AssetTypesOf, ScreenStatesOf, ComponentsOfWorld, EventsOfWorld, AssetsOfWorld, ScreenStatesOfWorld, AnyECSpresso, AnyPlugin, EventNameMatching, ChannelOfWorld, WorldConfig, EmptyConfig, WorldConfigFrom, MergeConfigs, ConfigsAreCompatible, ConfigOf, WithComponents, WithEvents, WithResources, WithAssets, WithScreens } from './type-utils';\n",
|
|
19
19
|
"/**\n * Shared 2D vector math utilities for ECSpresso bundles.\n * All functions are pure — they return new vectors, never mutate inputs.\n */\n\n/**\n * A 2D vector with x and y components.\n */\nexport interface Vector2D {\n\tx: number;\n\ty: number;\n}\n\n/**\n * Create a Vector2D from x and y components.\n */\nexport function vec2(x: number, y: number): Vector2D {\n\treturn { x, y };\n}\n\n/**\n * Return a zero vector {x: 0, y: 0}.\n */\nexport function vec2Zero(): Vector2D {\n\treturn { x: 0, y: 0 };\n}\n\n/**\n * Add two vectors component-wise.\n */\nexport function vec2Add(a: Vector2D, b: Vector2D): Vector2D {\n\treturn { x: a.x + b.x, y: a.y + b.y };\n}\n\n/**\n * Subtract b from a component-wise.\n */\nexport function vec2Sub(a: Vector2D, b: Vector2D): Vector2D {\n\treturn { x: a.x - b.x, y: a.y - b.y };\n}\n\n/**\n * Scale a vector by a scalar.\n */\nexport function vec2Scale(v: Vector2D, scalar: number): Vector2D {\n\treturn { x: v.x * scalar, y: v.y * scalar };\n}\n\n/**\n * Negate a vector (flip both components).\n */\nexport function vec2Negate(v: Vector2D): Vector2D {\n\treturn { x: -v.x, y: -v.y };\n}\n\n/**\n * Compute the dot product of two vectors.\n */\nexport function vec2Dot(a: Vector2D, b: Vector2D): number {\n\treturn a.x * b.x + a.y * b.y;\n}\n\n/**\n * Compute the 2D cross product (scalar z-component of the 3D cross product).\n */\nexport function vec2Cross(a: Vector2D, b: Vector2D): number {\n\treturn a.x * b.y - a.y * b.x;\n}\n\n/**\n * Compute the squared length of a vector. Avoids sqrt when only comparing magnitudes.\n */\nexport function vec2LengthSq(v: Vector2D): number {\n\treturn v.x * v.x + v.y * v.y;\n}\n\n/**\n * Compute the length (magnitude) of a vector.\n */\nexport function vec2Length(v: Vector2D): number {\n\treturn Math.sqrt(v.x * v.x + v.y * v.y);\n}\n\n/**\n * Return a unit vector in the same direction. Returns zero vector if input is zero-length.\n */\nexport function vec2Normalize(v: Vector2D): Vector2D {\n\tconst len = Math.sqrt(v.x * v.x + v.y * v.y);\n\tif (len === 0) return { x: 0, y: 0 };\n\treturn { x: v.x / len, y: v.y / len };\n}\n\n/**\n * Compute the squared distance between two points. Avoids sqrt when only comparing.\n */\nexport function vec2DistanceSq(a: Vector2D, b: Vector2D): number {\n\tconst dx = a.x - b.x;\n\tconst dy = a.y - b.y;\n\treturn dx * dx + dy * dy;\n}\n\n/**\n * Compute the distance between two points.\n */\nexport function vec2Distance(a: Vector2D, b: Vector2D): number {\n\tconst dx = a.x - b.x;\n\tconst dy = a.y - b.y;\n\treturn Math.sqrt(dx * dx + dy * dy);\n}\n\n/**\n * Check if two vectors are approximately equal within an epsilon tolerance.\n */\nexport function vec2Equals(a: Vector2D, b: Vector2D, epsilon = 1e-10): boolean {\n\treturn Math.abs(a.x - b.x) <= epsilon && Math.abs(a.y - b.y) <= epsilon;\n}\n",
|
|
20
20
|
"import ECSpresso from './ecspresso';\nimport { SystemBuilder, type ProcessContext } from './system-builder';\nimport { type Plugin, type BasePluginOptions, definePlugin } from './plugin';\n\nexport * from './types';\nexport * from './asset-types';\nexport * from './screen-types';\nexport * from './utils/math';\nexport type { ReactiveQueryDefinition } from './reactive-query-manager';\nexport { default as AssetManager, createAssetConfigurator } from './asset-manager';\nexport { default as ScreenManager, createScreenConfigurator } from './screen-manager';\nexport { SystemBuilder, type ProcessContext };\nexport { type Plugin, type BasePluginOptions, definePlugin };\nexport { directValue, type ResourceDirectValue } from './resource-manager';\nexport default ECSpresso;\n"
|
|
21
21
|
],
|
|
22
|
-
"mappings": "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",
|
|
23
|
-
"debugId": "
|
|
22
|
+
"mappings": "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",
|
|
23
|
+
"debugId": "3212F06B56962B5F64756E2164756E21",
|
|
24
24
|
"names": []
|
|
25
25
|
}
|