ecspresso 0.9.0 → 0.10.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/dist/index.js.map CHANGED
@@ -3,20 +3,20 @@
3
3
  "sources": ["../src/hierarchy-manager.ts", "../src/entity-manager.ts", "../src/event-bus.ts", "../src/resource-manager.ts", "../src/asset-manager.ts", "../src/screen-manager.ts", "../src/reactive-query-manager.ts", "../src/command-buffer.ts", "../src/system-builder.ts", "../src/ecspresso.ts", "../src/bundle.ts", "../src/types.ts", "../src/index.ts"],
4
4
  "sourcesContent": [
5
5
  "import type { HierarchyEntry, HierarchyIteratorOptions } from \"./types\";\n\n/**\n * Manages parent-child relationships between entities.\n * Handles hierarchy storage, validation, and traversal operations.\n */\nexport default class HierarchyManager {\n\t/** childId -> parentId */\n\tprivate parentMap: Map<number, number> = new Map();\n\t/** parentId -> ordered childIds */\n\tprivate childrenMap: Map<number, number[]> = new Map();\n\n\t/**\n\t * Set the parent of an entity.\n\t * @param childId The entity to set as a child\n\t * @param parentId The entity to set as the parent\n\t * @throws Error if this would create a circular reference or self-parenting\n\t */\n\tsetParent(childId: number, parentId: number): this {\n\t\tif (childId === parentId) {\n\t\t\tthrow new Error(`Cannot set entity ${childId} as its own parent`);\n\t\t}\n\n\t\t// Check for circular reference by walking up from the prospective parent\n\t\tif (this.wouldCreateCycle(childId, parentId)) {\n\t\t\tthrow new Error('Cannot set parent: would create circular reference');\n\t\t}\n\n\t\t// Remove from old parent's children list if exists\n\t\tconst oldParent = this.parentMap.get(childId);\n\t\tif (oldParent !== undefined) {\n\t\t\tconst oldChildren = this.childrenMap.get(oldParent);\n\t\t\tif (oldChildren) {\n\t\t\t\tconst idx = oldChildren.indexOf(childId);\n\t\t\t\tif (idx !== -1) {\n\t\t\t\t\toldChildren.splice(idx, 1);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Set new parent\n\t\tthis.parentMap.set(childId, parentId);\n\n\t\t// Add to new parent's children list\n\t\tconst children = this.childrenMap.get(parentId);\n\t\tif (children) {\n\t\t\tchildren.push(childId);\n\t\t} else {\n\t\t\tthis.childrenMap.set(parentId, [childId]);\n\t\t}\n\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 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 parentId = this.parentMap.get(childId);\n\t\tif (parentId === undefined) {\n\t\t\treturn false;\n\t\t}\n\n\t\t// Remove from parent's children list\n\t\tconst children = this.childrenMap.get(parentId);\n\t\tif (children) {\n\t\t\tconst idx = children.indexOf(childId);\n\t\t\tif (idx !== -1) {\n\t\t\t\tchildren.splice(idx, 1);\n\t\t\t}\n\t\t}\n\n\t\tthis.parentMap.delete(childId);\n\t\treturn true;\n\t}\n\n\t/**\n\t * Get the parent of an entity.\n\t * @param entityId The entity 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.parentMap.get(entityId) ?? null;\n\t}\n\n\t/**\n\t * Get all children of an entity in insertion order.\n\t * @param parentId The parent entity\n\t * @returns Readonly array of child entity IDs\n\t */\n\tgetChildren(parentId: number): readonly number[] {\n\t\tconst children = this.childrenMap.get(parentId);\n\t\treturn children ? [...children] : [];\n\t}\n\n\t/**\n\t * Get a child at a specific index.\n\t * @param parentId The parent entity\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\tif (index < 0) return null;\n\t\tconst children = this.childrenMap.get(parentId);\n\t\tif (!children || index >= children.length) return null;\n\t\treturn children[index] ?? null;\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\n\t * @param childId The child entity 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\tconst children = this.childrenMap.get(parentId);\n\t\tif (!children) return -1;\n\t\treturn children.indexOf(childId);\n\t}\n\n\t/**\n\t * Remove an entity from the hierarchy (called when entity is destroyed).\n\t * Orphans any children and removes from parent's children list.\n\t * @param entityId The entity being removed\n\t * @returns Information about the removal (oldParent and orphanedChildren)\n\t */\n\tremoveEntity(entityId: number): { oldParent: number | null; orphanedChildren: number[] } {\n\t\tconst oldParent = this.parentMap.get(entityId) ?? null;\n\n\t\t// Remove from parent's children list\n\t\tif (oldParent !== null) {\n\t\t\tconst parentChildren = this.childrenMap.get(oldParent);\n\t\t\tif (parentChildren) {\n\t\t\t\tconst idx = parentChildren.indexOf(entityId);\n\t\t\t\tif (idx !== -1) {\n\t\t\t\t\tparentChildren.splice(idx, 1);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tthis.parentMap.delete(entityId);\n\n\t\t// Orphan all children\n\t\tconst children = this.childrenMap.get(entityId) ?? [];\n\t\tconst orphanedChildren = [...children];\n\t\tfor (const childId of children) {\n\t\t\tthis.parentMap.delete(childId);\n\t\t}\n\t\tthis.childrenMap.delete(entityId);\n\n\t\treturn { oldParent, orphanedChildren };\n\t}\n\n\t/**\n\t * Get all ancestors of an entity in order [parent, grandparent, ...].\n\t * @param entityId The entity to get ancestors of\n\t * @returns Readonly array of ancestor entity IDs\n\t */\n\tgetAncestors(entityId: number): readonly number[] {\n\t\tconst ancestors: number[] = [];\n\t\tlet current = this.parentMap.get(entityId);\n\t\twhile (current !== undefined) {\n\t\t\tancestors.push(current);\n\t\t\tcurrent = this.parentMap.get(current);\n\t\t}\n\t\treturn ancestors;\n\t}\n\n\t/**\n\t * Get all descendants of an entity in depth-first order.\n\t * @param entityId The entity to get descendants of\n\t * @returns Readonly array of descendant entity IDs\n\t */\n\tgetDescendants(entityId: number): readonly number[] {\n\t\tconst descendants: number[] = [];\n\t\tconst stack = [...(this.childrenMap.get(entityId) ?? [])];\n\n\t\twhile (stack.length > 0) {\n\t\t\tconst current = stack.shift();\n\t\t\tif (current === undefined) continue;\n\t\t\tdescendants.push(current);\n\t\t\tconst children = this.childrenMap.get(current);\n\t\t\tif (children) {\n\t\t\t\t// Insert children at the beginning for depth-first traversal\n\t\t\t\tstack.unshift(...children);\n\t\t\t}\n\t\t}\n\n\t\treturn descendants;\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 to get the root of\n\t * @returns The root entity ID\n\t */\n\tgetRoot(entityId: number): number {\n\t\tlet current = entityId;\n\t\tlet parent = this.parentMap.get(current);\n\t\twhile (parent !== undefined) {\n\t\t\tcurrent = parent;\n\t\t\tparent = this.parentMap.get(current);\n\t\t}\n\t\treturn current;\n\t}\n\n\t/**\n\t * Get siblings of an entity (other children of the same parent).\n\t * @param entityId The entity to get siblings of\n\t * @returns Readonly array of sibling entity IDs\n\t */\n\tgetSiblings(entityId: number): readonly number[] {\n\t\tconst parentId = this.parentMap.get(entityId);\n\t\tif (parentId === undefined) return [];\n\n\t\tconst children = this.childrenMap.get(parentId);\n\t\tif (!children) return [];\n\n\t\treturn children.filter(id => id !== 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\n\t * @param ancestorId The potential ancestor\n\t * @returns true if entityId is a descendant of ancestorId\n\t */\n\tisDescendantOf(entityId: number, ancestorId: number): boolean {\n\t\tif (entityId === ancestorId) return false;\n\n\t\tlet current = this.parentMap.get(entityId);\n\t\twhile (current !== undefined) {\n\t\t\tif (current === ancestorId) return true;\n\t\t\tcurrent = this.parentMap.get(current);\n\t\t}\n\t\treturn false;\n\t}\n\n\t/**\n\t * Check if an entity is an ancestor of another entity.\n\t * @param entityId The potential ancestor\n\t * @param descendantId The potential descendant\n\t * @returns true if entityId is an ancestor of descendantId\n\t */\n\tisAncestorOf(entityId: number, descendantId: number): boolean {\n\t\treturn this.isDescendantOf(descendantId, entityId);\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\tconst roots: number[] = [];\n\t\tfor (const parentId of this.childrenMap.keys()) {\n\t\t\tif (!this.parentMap.has(parentId)) {\n\t\t\t\troots.push(parentId);\n\t\t\t}\n\t\t}\n\t\treturn roots;\n\t}\n\n\t/**\n\t * Check if setting a parent would create a cycle.\n\t * A cycle would occur if the prospective parent is a descendant of the child.\n\t */\n\tprivate wouldCreateCycle(childId: number, parentId: number): boolean {\n\t\tlet current: number | undefined = parentId;\n\t\twhile (current !== undefined) {\n\t\t\tif (current === childId) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\tcurrent = this.parentMap.get(current);\n\t\t}\n\t\treturn false;\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\tconst roots = options?.roots ?? this.getRootEntities();\n\t\tconst queue: Array<{ entityId: number; parentId: number | null; depth: number }> = [];\n\n\t\t// Initialize queue with root entities\n\t\tfor (const id of roots) {\n\t\t\tqueue.push({ entityId: id, parentId: null, depth: 0 });\n\t\t}\n\n\t\twhile (queue.length > 0) {\n\t\t\tconst current = queue.shift();\n\t\t\tif (!current) break;\n\n\t\t\tcallback(current.entityId, current.parentId, current.depth);\n\n\t\t\tconst children = this.childrenMap.get(current.entityId);\n\t\t\tif (children) {\n\t\t\t\tfor (const childId of children) {\n\t\t\t\t\tqueue.push({\n\t\t\t\t\t\tentityId: childId,\n\t\t\t\t\t\tparentId: current.entityId,\n\t\t\t\t\t\tdepth: current.depth + 1\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t}\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\t*hierarchyIterator(options?: HierarchyIteratorOptions): Generator<HierarchyEntry, void, unknown> {\n\t\tconst roots = options?.roots ?? this.getRootEntities();\n\t\tconst queue: HierarchyEntry[] = [];\n\n\t\t// Initialize queue with root entities\n\t\tfor (const id of roots) {\n\t\t\tqueue.push({ entityId: id, parentId: null, depth: 0 });\n\t\t}\n\n\t\twhile (queue.length > 0) {\n\t\t\tconst current = queue.shift();\n\t\t\tif (!current) break;\n\n\t\t\tyield current;\n\n\t\t\tconst children = this.childrenMap.get(current.entityId);\n\t\t\tif (children) {\n\t\t\t\tfor (const childId of children) {\n\t\t\t\t\tqueue.push({\n\t\t\t\t\t\tentityId: childId,\n\t\t\t\t\t\tparentId: current.entityId,\n\t\t\t\t\t\tdepth: current.depth + 1\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n",
6
- "import type { Entity, FilteredEntity, RemoveEntityOptions, HierarchyEntry, HierarchyIteratorOptions } from \"./types\";\nimport HierarchyManager from \"./hierarchy-manager\";\n\nexport default\nclass EntityManager<ComponentTypes> {\n\tprivate nextId: number = 1;\n\tprivate entities: Map<number, Entity<ComponentTypes>> = new Map();\n\tprivate componentIndices: Map<keyof ComponentTypes, Set<number>> = new Map();\n\t/**\n\t * Callbacks registered for component additions\n\t */\n\tprivate addedCallbacks: Map<keyof ComponentTypes, Set<(value: any, entity: Entity<ComponentTypes>) => void>> = new Map();\n\t/**\n\t * Callbacks registered for component removals\n\t */\n\tprivate removedCallbacks: Map<keyof ComponentTypes, Set<(oldValue: any, entity: Entity<ComponentTypes>) => void>> = new Map();\n\t/**\n\t * Hierarchy manager for parent-child relationships\n\t */\n\tprivate hierarchyManager: HierarchyManager = new HierarchyManager();\n\t/**\n\t * Per-entity per-component change sequence tracking.\n\t * Maps entityId -> (componentName -> sequence number when last changed)\n\t */\n\tprivate changeSeqs: Map<number, Map<keyof ComponentTypes, number>> = new Map();\n\t/**\n\t * Monotonic sequence counter for change detection.\n\t * Each markChanged call increments this and stamps the new value.\n\t */\n\tprivate _changeSeq: number = 0;\n\n\tcreateEntity(): Entity<ComponentTypes> {\n\t\tconst id = this.nextId++;\n\t\tconst entity: Entity<ComponentTypes> = { id, components: {} };\n\t\tthis.entities.set(id, entity);\n\t\treturn entity;\n\t}\n\n\t// TODO: Component object pooling if(/when) garbage collection is an issue...?\n\taddComponent<ComponentName extends keyof ComponentTypes>(\n\t\tentityOrId: number | Entity<ComponentTypes>,\n\t\tcomponentName: ComponentName,\n\t\tdata: ComponentTypes[ComponentName]\n\t) {\n\t\tconst entity = typeof entityOrId === 'number' ?\n\t\t\tthis.entities.get(entityOrId) :\n\t\t\tentityOrId;\n\n\t\tif (!entity) {\n\t\t\tconst id = typeof entityOrId === 'number' ? entityOrId : entityOrId.id;\n\t\t\tthrow new Error(`Cannot add component '${String(componentName)}': Entity with ID ${id} does not exist`);\n\t\t}\n\n\t\tentity.components[componentName] = data;\n\n\t\t// Update component index\n\t\tif (!this.componentIndices.has(componentName)) {\n\t\t\tthis.componentIndices.set(componentName, new Set());\n\t\t}\n\t\tthis.componentIndices.get(componentName)?.add(entity.id);\n\t\t// Trigger added callbacks (iterate over copy to allow mid-iteration unsubscribe)\n\t\tconst callbacks = this.addedCallbacks.get(componentName);\n\t\tif (callbacks) {\n\t\t\tfor (const cb of [...callbacks]) {\n\t\t\t\tcb(data, entity);\n\t\t\t}\n\t\t}\n\t\treturn this;\n\t}\n\n\t/**\n\t * Add multiple components to an entity at once\n\t * @param entityOrId Entity or entity ID to add components to\n\t * @param components Object with component names as keys and component data as values\n\t */\n\taddComponents<\n\t\tT extends { [K in keyof ComponentTypes]?: ComponentTypes[K] }\n\t>(\n\t\tentityOrId: number | Entity<ComponentTypes>,\n\t\tcomponents: T & Record<Exclude<keyof T, keyof ComponentTypes>, never>\n\t) {\n\t\tconst entity = typeof entityOrId === 'number' ?\n\t\t\tthis.entities.get(entityOrId) :\n\t\t\tentityOrId;\n\n\t\tif (!entity) {\n\t\t\tconst id = typeof entityOrId === 'number' ? entityOrId : entityOrId.id;\n\t\t\tthrow new Error(`Cannot add components: Entity with ID ${id} does not exist`);\n\t\t}\n\n\t\tfor (const componentName in components) {\n\t\t\tthis.addComponent(\n\t\t\t\tentity,\n\t\t\t\tcomponentName as keyof ComponentTypes,\n\t\t\t\tcomponents[componentName as keyof T] as ComponentTypes[keyof ComponentTypes]\n\t\t\t);\n\t\t}\n\n\t\treturn this;\n\t}\n\n\tremoveComponent<ComponentName extends keyof ComponentTypes>(\n\t\tentityOrId: number | Entity<ComponentTypes>,\n\t\tcomponentName: ComponentName\n\t) {\n\t\tconst entity = typeof entityOrId === 'number' ?\n\t\t\tthis.entities.get(entityOrId) :\n\t\t\tentityOrId;\n\n\t\tif (!entity) {\n\t\t\tconst id = typeof entityOrId === 'number' ? entityOrId : entityOrId.id;\n\t\t\tthrow new Error(`Cannot remove component '${String(componentName)}': Entity with ID ${id} does not exist`);\n\t\t}\n\t\t// Get old value for callbacks\n\t\tconst oldValue = entity.components[componentName] as ComponentTypes[ComponentName] | undefined;\n\n\t\tdelete entity.components[componentName];\n\n\t\t// Trigger removed callbacks (iterate over copy to allow mid-iteration unsubscribe)\n\t\tconst removeCbs = this.removedCallbacks.get(componentName);\n\t\tif (removeCbs && oldValue !== undefined) {\n\t\t\tfor (const cb of [...removeCbs]) {\n\t\t\t\tcb(oldValue, entity);\n\t\t\t}\n\t\t}\n\n\t\t// Update component index\n\t\tthis.componentIndices.get(componentName)?.delete(entity.id);\n\n\t\treturn this;\n\t}\n\n\tgetComponent<ComponentName extends keyof ComponentTypes>(entityId: number, componentName: ComponentName): ComponentTypes[ComponentName] | null {\n\t\tconst entity = this.entities.get(entityId);\n\n\t\tif (!entity) throw new Error(`Cannot get component '${String(componentName)}': Entity with ID ${entityId} does not exist`);\n\n\t\treturn entity.components[componentName] || null;\n\t}\n\n\tgetEntitiesWithQuery<\n\t\tWithComponents extends keyof ComponentTypes = never,\n\t\tWithoutComponents extends keyof ComponentTypes = never\n\t>(\n\t\trequired: ReadonlyArray<WithComponents> = [],\n\t\texcluded: ReadonlyArray<WithoutComponents> = [],\n\t\tchanged?: ReadonlyArray<keyof ComponentTypes>,\n\t\tchangeThreshold?: number,\n\t): Array<FilteredEntity<ComponentTypes, WithComponents extends never ? never : WithComponents, WithoutComponents extends never ? never : WithoutComponents>> {\n\t\tconst hasChangedFilter = changed !== undefined && changed.length > 0 && changeThreshold !== undefined;\n\n\t\t// Use the smallest component set as base for better performance\n\t\tif (required.length === 0) {\n\t\t\tif (excluded.length === 0 && !hasChangedFilter) {\n\t\t\t\treturn Array.from(this.entities.values()) as any;\n\t\t\t}\n\n\t\t\treturn Array\n\t\t\t\t.from(this.entities.values())\n\t\t\t\t.filter((entity) => {\n\t\t\t\t\tif (excluded.length > 0 && !excluded.every(comp => !(comp in entity.components))) {\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t\tif (hasChangedFilter) {\n\t\t\t\t\t\tconst entitySeqs = this.changeSeqs.get(entity.id);\n\t\t\t\t\t\tif (!entitySeqs) return false;\n\t\t\t\t\t\treturn changed.some(comp => (entitySeqs.get(comp) ?? -1) > changeThreshold!);\n\t\t\t\t\t}\n\t\t\t\t\treturn true;\n\t\t\t\t}) as any;\n\t\t}\n\n\t\t// Find the component with the smallest entity set to start with\n\t\tconst smallestComponent = required.reduce((smallest, comp) => {\n\t\t\tconst currentSize = this.componentIndices.get(comp)?.size ?? 0;\n\t\t\tconst smallestSize = this.componentIndices.get(smallest!)?.size ?? Infinity;\n\t\t\treturn currentSize < smallestSize ? comp : smallest;\n\t\t}, required[0])!;\n\n\t\t// Start with the entities from the smallest component set\n\t\tconst candidateSet = this.componentIndices.get(smallestComponent);\n\t\tif (!candidateSet || candidateSet.size === 0) {\n\t\t\treturn [] as any;\n\t\t}\n\n\t\t// Return full entity objects, not just IDs\n\t\tconst result: Array<FilteredEntity<ComponentTypes, WithComponents extends never ? never : WithComponents, WithoutComponents extends never ? never : WithoutComponents>> = [];\n\t\tconst hasExclusions = excluded.length > 0;\n\n\t\tfor (const id of candidateSet) {\n\t\t\tconst entity = this.entities.get(id);\n\t\t\tif (\n\t\t\t\tentity &&\n\t\t\t\trequired.every(comp => comp in entity.components) &&\n\t\t\t\t(!hasExclusions || excluded.every(comp => !(comp in entity.components)))\n\t\t\t) {\n\t\t\t\tif (hasChangedFilter) {\n\t\t\t\t\tconst entitySeqs = this.changeSeqs.get(id);\n\t\t\t\t\tif (!entitySeqs || !changed.some(comp => (entitySeqs.get(comp) ?? -1) > changeThreshold!)) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tresult.push(entity as any);\n\t\t\t}\n\t\t}\n\n\t\treturn result;\n\t}\n\n\tremoveEntity(entityOrId: number | Entity<ComponentTypes>, options?: RemoveEntityOptions): boolean {\n\t\tconst entity = typeof entityOrId === 'number' ?\n\t\t\tthis.entities.get(entityOrId) :\n\t\t\tentityOrId;\n\n\t\tif (!entity) return false;\n\n\t\tconst cascade = options?.cascade ?? true;\n\n\t\tif (cascade) {\n\t\t\t// Get all descendants first (depth-first order)\n\t\t\tconst descendants = this.hierarchyManager.getDescendants(entity.id);\n\t\t\t// Remove descendants in reverse order (children before parents) for proper cleanup\n\t\t\tfor (const descendantId of [...descendants].reverse()) {\n\t\t\t\tthis.removeEntityInternal(descendantId);\n\t\t\t}\n\t\t}\n\n\t\treturn this.removeEntityInternal(entity.id);\n\t}\n\n\t/**\n\t * Internal method to remove a single entity without cascade logic\n\t */\n\tprivate removeEntityInternal(entityId: number): boolean {\n\t\tconst entity = this.entities.get(entityId);\n\t\tif (!entity) return false;\n\n\t\t// Clean up hierarchy\n\t\tthis.hierarchyManager.removeEntity(entityId);\n\n\t\t// Trigger removal callbacks for each component before removing the entity\n\t\tfor (const componentName of Object.keys(entity.components) as Array<keyof ComponentTypes>) {\n\t\t\tconst oldValue = entity.components[componentName];\n\n\t\t\t// Trigger removed callbacks if the component exists (iterate over copy to allow mid-iteration unsubscribe)\n\t\t\tif (oldValue !== undefined) {\n\t\t\t\tconst removeCbs = this.removedCallbacks.get(componentName);\n\t\t\t\tif (removeCbs) {\n\t\t\t\t\tfor (const cb of [...removeCbs]) {\n\t\t\t\t\t\tcb(oldValue, entity);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Remove entity from component indices\n\t\t\tthis.componentIndices.get(componentName)?.delete(entity.id);\n\t\t}\n\n\t\t// Clean up change sequences\n\t\tthis.changeSeqs.delete(entity.id);\n\n\t\t// Remove the entity itself\n\t\treturn this.entities.delete(entity.id);\n\t}\n\n\tgetEntity(entityId: number): Entity<ComponentTypes> | undefined {\n\t\treturn this.entities.get(entityId);\n\t}\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<ComponentName extends keyof ComponentTypes>(\n\t\tcomponentName: ComponentName,\n\t\thandler: (value: ComponentTypes[ComponentName], entity: Entity<ComponentTypes>) => void\n\t): () => void {\n\t\tif (!this.addedCallbacks.has(componentName)) {\n\t\t\tthis.addedCallbacks.set(componentName, new Set());\n\t\t}\n\t\tthis.addedCallbacks.get(componentName)!.add(handler as any);\n\t\treturn () => {\n\t\t\tthis.addedCallbacks.get(componentName)?.delete(handler as any);\n\t\t};\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<ComponentName extends keyof ComponentTypes>(\n\t\tcomponentName: ComponentName,\n\t\thandler: (oldValue: ComponentTypes[ComponentName], entity: Entity<ComponentTypes>) => void\n\t): () => void {\n\t\tif (!this.removedCallbacks.has(componentName)) {\n\t\t\tthis.removedCallbacks.set(componentName, new Set());\n\t\t}\n\t\tthis.removedCallbacks.get(componentName)!.add(handler as any);\n\t\treturn () => {\n\t\t\tthis.removedCallbacks.get(componentName)?.delete(handler as any);\n\t\t};\n\t}\n\n\t// ==================== Change Detection Methods ====================\n\n\t/**\n\t * The current monotonic change sequence value.\n\t * Each markChanged call increments this before stamping.\n\t */\n\tget changeSeq(): number {\n\t\treturn this._changeSeq;\n\t}\n\n\t/**\n\t * Mark a component as changed on an entity, stamping the next sequence number.\n\t * @param entityId The entity ID\n\t * @param componentName The component that changed\n\t */\n\tmarkChanged<K extends keyof ComponentTypes>(entityId: number, componentName: K): void {\n\t\tconst seq = ++this._changeSeq;\n\t\tlet entitySeqs = this.changeSeqs.get(entityId);\n\t\tif (!entitySeqs) {\n\t\t\tentitySeqs = new Map();\n\t\t\tthis.changeSeqs.set(entityId, entitySeqs);\n\t\t}\n\t\tentitySeqs.set(componentName, seq);\n\t}\n\n\t/**\n\t * Get the sequence number at which a component was last changed on an entity\n\t * @param entityId The entity ID\n\t * @param componentName The component to check\n\t * @returns The sequence number when last changed, or -1 if never changed\n\t */\n\tgetChangeSeq<K extends keyof ComponentTypes>(entityId: number, componentName: K): number {\n\t\treturn this.changeSeqs.get(entityId)?.get(componentName) ?? -1;\n\t}\n\n\t/**\n\t * Clear all change sequences for an entity\n\t * @param entityId The entity ID\n\t */\n\tclearChangeSeqs(entityId: number): void {\n\t\tthis.changeSeqs.delete(entityId);\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 ComponentTypes]?: ComponentTypes[K] }>(\n\t\tparentId: number,\n\t\tcomponents: T & Record<Exclude<keyof T, keyof ComponentTypes>, never>\n\t): FilteredEntity<ComponentTypes, keyof T & keyof ComponentTypes, never> {\n\t\tconst entity = this.createEntity();\n\t\tthis.addComponents(entity, components);\n\t\tthis.setParent(entity.id, parentId);\n\t\treturn entity as FilteredEntity<ComponentTypes, keyof T & keyof ComponentTypes, never>;\n\t}\n\n\t/**\n\t * Set the parent of an entity\n\t * @param childId The entity to set as a child\n\t * @param parentId The entity to set as the parent\n\t */\n\tsetParent(childId: number, parentId: number): this {\n\t\tthis.hierarchyManager.setParent(childId, 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 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\treturn this.hierarchyManager.removeParent(childId);\n\t}\n\n\t/**\n\t * Get the parent of an entity\n\t * @param entityId The entity 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.hierarchyManager.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\n\t * @returns Readonly array of child entity IDs\n\t */\n\tgetChildren(parentId: number): readonly number[] {\n\t\treturn this.hierarchyManager.getChildren(parentId);\n\t}\n\n\t/**\n\t * Get a child at a specific index\n\t * @param parentId The parent entity\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.hierarchyManager.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\n\t * @param childId The child entity 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.hierarchyManager.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 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.hierarchyManager.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 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.hierarchyManager.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 to get the root of\n\t * @returns The root entity ID\n\t */\n\tgetRoot(entityId: number): number {\n\t\treturn this.hierarchyManager.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 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.hierarchyManager.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\n\t * @param ancestorId The potential ancestor\n\t * @returns true if entityId is a descendant of ancestorId\n\t */\n\tisDescendantOf(entityId: number, ancestorId: number): boolean {\n\t\treturn this.hierarchyManager.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\n\t * @param descendantId The potential descendant\n\t * @returns true if entityId is an ancestor of descendantId\n\t */\n\tisAncestorOf(entityId: number, descendantId: number): boolean {\n\t\treturn this.hierarchyManager.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.hierarchyManager.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.hierarchyManager.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.hierarchyManager.hierarchyIterator(options);\n\t}\n}\n",
6
+ "import type { Entity, FilteredEntity, RemoveEntityOptions, HierarchyEntry, HierarchyIteratorOptions } from \"./types\";\nimport HierarchyManager from \"./hierarchy-manager\";\n\nexport default\nclass EntityManager<ComponentTypes> {\n\tprivate nextId: number = 1;\n\tprivate entities: Map<number, Entity<ComponentTypes>> = new Map();\n\tprivate componentIndices: Map<keyof ComponentTypes, Set<number>> = new Map();\n\t/**\n\t * Callbacks registered for component additions\n\t */\n\tprivate addedCallbacks: Map<keyof ComponentTypes, Set<(value: any, entity: Entity<ComponentTypes>) => void>> = new Map();\n\t/**\n\t * Callbacks registered for component removals\n\t */\n\tprivate removedCallbacks: Map<keyof ComponentTypes, Set<(oldValue: any, entity: Entity<ComponentTypes>) => void>> = new Map();\n\t/**\n\t * Hierarchy manager for parent-child relationships\n\t */\n\tprivate hierarchyManager: HierarchyManager = new HierarchyManager();\n\t/**\n\t * Per-entity per-component change sequence tracking.\n\t * Maps entityId -> (componentName -> sequence number when last changed)\n\t */\n\tprivate changeSeqs: Map<number, Map<keyof ComponentTypes, number>> = new Map();\n\t/**\n\t * Monotonic sequence counter for change detection.\n\t * Each markChanged call increments this and stamps the new value.\n\t */\n\tprivate _changeSeq: number = 0;\n\n\tcreateEntity(): Entity<ComponentTypes> {\n\t\tconst id = this.nextId++;\n\t\tconst entity: Entity<ComponentTypes> = { id, components: {} };\n\t\tthis.entities.set(id, entity);\n\t\treturn entity;\n\t}\n\n\t// TODO: Component object pooling if(/when) garbage collection is an issue...?\n\taddComponent<ComponentName extends keyof ComponentTypes>(\n\t\tentityOrId: number | Entity<ComponentTypes>,\n\t\tcomponentName: ComponentName,\n\t\tdata: ComponentTypes[ComponentName]\n\t) {\n\t\tconst entity = typeof entityOrId === 'number' ?\n\t\t\tthis.entities.get(entityOrId) :\n\t\t\tentityOrId;\n\n\t\tif (!entity) {\n\t\t\tconst id = typeof entityOrId === 'number' ? entityOrId : entityOrId.id;\n\t\t\tthrow new Error(`Cannot add component '${String(componentName)}': Entity with ID ${id} does not exist`);\n\t\t}\n\n\t\tentity.components[componentName] = data;\n\n\t\t// Update component index\n\t\tif (!this.componentIndices.has(componentName)) {\n\t\t\tthis.componentIndices.set(componentName, new Set());\n\t\t}\n\t\tthis.componentIndices.get(componentName)?.add(entity.id);\n\t\t// Trigger added callbacks (iterate over copy to allow mid-iteration unsubscribe)\n\t\tconst callbacks = this.addedCallbacks.get(componentName);\n\t\tif (callbacks) {\n\t\t\tfor (const cb of [...callbacks]) {\n\t\t\t\tcb(data, entity);\n\t\t\t}\n\t\t}\n\t\treturn this;\n\t}\n\n\t/**\n\t * Add multiple components to an entity at once\n\t * @param entityOrId Entity or entity ID to add components to\n\t * @param components Object with component names as keys and component data as values\n\t */\n\taddComponents<\n\t\tT extends { [K in keyof ComponentTypes]?: ComponentTypes[K] }\n\t>(\n\t\tentityOrId: number | Entity<ComponentTypes>,\n\t\tcomponents: T & Record<Exclude<keyof T, keyof ComponentTypes>, never>\n\t) {\n\t\tconst entity = typeof entityOrId === 'number' ?\n\t\t\tthis.entities.get(entityOrId) :\n\t\t\tentityOrId;\n\n\t\tif (!entity) {\n\t\t\tconst id = typeof entityOrId === 'number' ? entityOrId : entityOrId.id;\n\t\t\tthrow new Error(`Cannot add components: Entity with ID ${id} does not exist`);\n\t\t}\n\n\t\tfor (const componentName in components) {\n\t\t\tthis.addComponent(\n\t\t\t\tentity,\n\t\t\t\tcomponentName as keyof ComponentTypes,\n\t\t\t\tcomponents[componentName as keyof T] as ComponentTypes[keyof ComponentTypes]\n\t\t\t);\n\t\t}\n\n\t\treturn this;\n\t}\n\n\tremoveComponent<ComponentName extends keyof ComponentTypes>(\n\t\tentityOrId: number | Entity<ComponentTypes>,\n\t\tcomponentName: ComponentName\n\t) {\n\t\tconst entity = typeof entityOrId === 'number' ?\n\t\t\tthis.entities.get(entityOrId) :\n\t\t\tentityOrId;\n\n\t\tif (!entity) {\n\t\t\tconst id = typeof entityOrId === 'number' ? entityOrId : entityOrId.id;\n\t\t\tthrow new Error(`Cannot remove component '${String(componentName)}': Entity with ID ${id} does not exist`);\n\t\t}\n\t\t// Get old value for callbacks\n\t\tconst oldValue = entity.components[componentName] as ComponentTypes[ComponentName] | undefined;\n\n\t\tdelete entity.components[componentName];\n\n\t\t// Trigger removed callbacks (iterate over copy to allow mid-iteration unsubscribe)\n\t\tconst removeCbs = this.removedCallbacks.get(componentName);\n\t\tif (removeCbs && oldValue !== undefined) {\n\t\t\tfor (const cb of [...removeCbs]) {\n\t\t\t\tcb(oldValue, entity);\n\t\t\t}\n\t\t}\n\n\t\t// Update component index\n\t\tthis.componentIndices.get(componentName)?.delete(entity.id);\n\n\t\treturn this;\n\t}\n\n\tgetComponent<ComponentName extends keyof ComponentTypes>(entityId: number, componentName: ComponentName): ComponentTypes[ComponentName] | null {\n\t\tconst entity = this.entities.get(entityId);\n\n\t\tif (!entity) throw new Error(`Cannot get component '${String(componentName)}': Entity with ID ${entityId} does not exist`);\n\n\t\treturn entity.components[componentName] || null;\n\t}\n\n\tgetEntitiesWithQuery<\n\t\tWithComponents extends keyof ComponentTypes = never,\n\t\tWithoutComponents extends keyof ComponentTypes = never\n\t>(\n\t\trequired: ReadonlyArray<WithComponents> = [],\n\t\texcluded: ReadonlyArray<WithoutComponents> = [],\n\t\tchanged?: ReadonlyArray<keyof ComponentTypes>,\n\t\tchangeThreshold?: number,\n\t\tparentHas?: ReadonlyArray<keyof ComponentTypes>,\n\t): Array<FilteredEntity<ComponentTypes, WithComponents extends never ? never : WithComponents, WithoutComponents extends never ? never : WithoutComponents>> {\n\t\tconst hasChangedFilter = changed !== undefined && changed.length > 0 && changeThreshold !== undefined;\n\t\tconst hasParentHasFilter = parentHas !== undefined && parentHas.length > 0;\n\n\t\t// Use the smallest component set as base for better performance\n\t\tif (required.length === 0) {\n\t\t\tif (excluded.length === 0 && !hasChangedFilter && !hasParentHasFilter) {\n\t\t\t\treturn Array.from(this.entities.values()) as any;\n\t\t\t}\n\n\t\t\treturn Array\n\t\t\t\t.from(this.entities.values())\n\t\t\t\t.filter((entity) => {\n\t\t\t\t\tif (excluded.length > 0 && !excluded.every(comp => !(comp in entity.components))) {\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t\tif (hasChangedFilter) {\n\t\t\t\t\t\tconst entitySeqs = this.changeSeqs.get(entity.id);\n\t\t\t\t\t\tif (!entitySeqs) return false;\n\t\t\t\t\t\tif (!changed.some(comp => (entitySeqs.get(comp) ?? -1) > changeThreshold!)) return false;\n\t\t\t\t\t}\n\t\t\t\t\tif (hasParentHasFilter && !this.parentHasComponents(entity.id, parentHas)) {\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t\treturn true;\n\t\t\t\t}) as any;\n\t\t}\n\n\t\t// Find the component with the smallest entity set to start with\n\t\tconst smallestComponent = required.reduce((smallest, comp) => {\n\t\t\tconst currentSize = this.componentIndices.get(comp)?.size ?? 0;\n\t\t\tconst smallestSize = this.componentIndices.get(smallest!)?.size ?? Infinity;\n\t\t\treturn currentSize < smallestSize ? comp : smallest;\n\t\t}, required[0])!;\n\n\t\t// Start with the entities from the smallest component set\n\t\tconst candidateSet = this.componentIndices.get(smallestComponent);\n\t\tif (!candidateSet || candidateSet.size === 0) {\n\t\t\treturn [] as any;\n\t\t}\n\n\t\t// Return full entity objects, not just IDs\n\t\tconst result: Array<FilteredEntity<ComponentTypes, WithComponents extends never ? never : WithComponents, WithoutComponents extends never ? never : WithoutComponents>> = [];\n\t\tconst hasExclusions = excluded.length > 0;\n\n\t\tfor (const id of candidateSet) {\n\t\t\tconst entity = this.entities.get(id);\n\t\t\tif (\n\t\t\t\tentity &&\n\t\t\t\trequired.every(comp => comp in entity.components) &&\n\t\t\t\t(!hasExclusions || excluded.every(comp => !(comp in entity.components)))\n\t\t\t) {\n\t\t\t\tif (hasChangedFilter) {\n\t\t\t\t\tconst entitySeqs = this.changeSeqs.get(id);\n\t\t\t\t\tif (!entitySeqs || !changed.some(comp => (entitySeqs.get(comp) ?? -1) > changeThreshold!)) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (hasParentHasFilter && !this.parentHasComponents(id, parentHas)) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tresult.push(entity as any);\n\t\t\t}\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t/**\n\t * Check if an entity's direct parent has all specified components\n\t */\n\tprivate parentHasComponents(entityId: number, components: ReadonlyArray<keyof ComponentTypes>): boolean {\n\t\tconst parentId = this.hierarchyManager.getParent(entityId);\n\t\tif (parentId === null) return false;\n\n\t\tconst parentEntity = this.entities.get(parentId);\n\t\tif (!parentEntity) return false;\n\n\t\tfor (const comp of components) {\n\t\t\tif (!(comp in parentEntity.components)) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\t\treturn true;\n\t}\n\n\tremoveEntity(entityOrId: number | Entity<ComponentTypes>, options?: RemoveEntityOptions): boolean {\n\t\tconst entity = typeof entityOrId === 'number' ?\n\t\t\tthis.entities.get(entityOrId) :\n\t\t\tentityOrId;\n\n\t\tif (!entity) return false;\n\n\t\tconst cascade = options?.cascade ?? true;\n\n\t\tif (cascade) {\n\t\t\t// Get all descendants first (depth-first order)\n\t\t\tconst descendants = this.hierarchyManager.getDescendants(entity.id);\n\t\t\t// Remove descendants in reverse order (children before parents) for proper cleanup\n\t\t\tfor (const descendantId of [...descendants].reverse()) {\n\t\t\t\tthis.removeEntityInternal(descendantId);\n\t\t\t}\n\t\t}\n\n\t\treturn this.removeEntityInternal(entity.id);\n\t}\n\n\t/**\n\t * Internal method to remove a single entity without cascade logic\n\t */\n\tprivate removeEntityInternal(entityId: number): boolean {\n\t\tconst entity = this.entities.get(entityId);\n\t\tif (!entity) return false;\n\n\t\t// Clean up hierarchy\n\t\tthis.hierarchyManager.removeEntity(entityId);\n\n\t\t// Trigger removal callbacks for each component before removing the entity\n\t\tfor (const componentName of Object.keys(entity.components) as Array<keyof ComponentTypes>) {\n\t\t\tconst oldValue = entity.components[componentName];\n\n\t\t\t// Trigger removed callbacks if the component exists (iterate over copy to allow mid-iteration unsubscribe)\n\t\t\tif (oldValue !== undefined) {\n\t\t\t\tconst removeCbs = this.removedCallbacks.get(componentName);\n\t\t\t\tif (removeCbs) {\n\t\t\t\t\tfor (const cb of [...removeCbs]) {\n\t\t\t\t\t\tcb(oldValue, entity);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Remove entity from component indices\n\t\t\tthis.componentIndices.get(componentName)?.delete(entity.id);\n\t\t}\n\n\t\t// Clean up change sequences\n\t\tthis.changeSeqs.delete(entity.id);\n\n\t\t// Remove the entity itself\n\t\treturn this.entities.delete(entity.id);\n\t}\n\n\tgetEntity(entityId: number): Entity<ComponentTypes> | undefined {\n\t\treturn this.entities.get(entityId);\n\t}\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<ComponentName extends keyof ComponentTypes>(\n\t\tcomponentName: ComponentName,\n\t\thandler: (value: ComponentTypes[ComponentName], entity: Entity<ComponentTypes>) => void\n\t): () => void {\n\t\tif (!this.addedCallbacks.has(componentName)) {\n\t\t\tthis.addedCallbacks.set(componentName, new Set());\n\t\t}\n\t\tthis.addedCallbacks.get(componentName)!.add(handler as any);\n\t\treturn () => {\n\t\t\tthis.addedCallbacks.get(componentName)?.delete(handler as any);\n\t\t};\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<ComponentName extends keyof ComponentTypes>(\n\t\tcomponentName: ComponentName,\n\t\thandler: (oldValue: ComponentTypes[ComponentName], entity: Entity<ComponentTypes>) => void\n\t): () => void {\n\t\tif (!this.removedCallbacks.has(componentName)) {\n\t\t\tthis.removedCallbacks.set(componentName, new Set());\n\t\t}\n\t\tthis.removedCallbacks.get(componentName)!.add(handler as any);\n\t\treturn () => {\n\t\t\tthis.removedCallbacks.get(componentName)?.delete(handler as any);\n\t\t};\n\t}\n\n\t// ==================== Change Detection Methods ====================\n\n\t/**\n\t * The current monotonic change sequence value.\n\t * Each markChanged call increments this before stamping.\n\t */\n\tget changeSeq(): number {\n\t\treturn this._changeSeq;\n\t}\n\n\t/**\n\t * Mark a component as changed on an entity, stamping the next sequence number.\n\t * @param entityId The entity ID\n\t * @param componentName The component that changed\n\t */\n\tmarkChanged<K extends keyof ComponentTypes>(entityId: number, componentName: K): void {\n\t\tconst seq = ++this._changeSeq;\n\t\tlet entitySeqs = this.changeSeqs.get(entityId);\n\t\tif (!entitySeqs) {\n\t\t\tentitySeqs = new Map();\n\t\t\tthis.changeSeqs.set(entityId, entitySeqs);\n\t\t}\n\t\tentitySeqs.set(componentName, seq);\n\t}\n\n\t/**\n\t * Get the sequence number at which a component was last changed on an entity\n\t * @param entityId The entity ID\n\t * @param componentName The component to check\n\t * @returns The sequence number when last changed, or -1 if never changed\n\t */\n\tgetChangeSeq<K extends keyof ComponentTypes>(entityId: number, componentName: K): number {\n\t\treturn this.changeSeqs.get(entityId)?.get(componentName) ?? -1;\n\t}\n\n\t/**\n\t * Clear all change sequences for an entity\n\t * @param entityId The entity ID\n\t */\n\tclearChangeSeqs(entityId: number): void {\n\t\tthis.changeSeqs.delete(entityId);\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 ComponentTypes]?: ComponentTypes[K] }>(\n\t\tparentId: number,\n\t\tcomponents: T & Record<Exclude<keyof T, keyof ComponentTypes>, never>\n\t): FilteredEntity<ComponentTypes, keyof T & keyof ComponentTypes, never> {\n\t\tconst entity = this.createEntity();\n\t\tthis.addComponents(entity, components);\n\t\tthis.setParent(entity.id, parentId);\n\t\treturn entity as FilteredEntity<ComponentTypes, keyof T & keyof ComponentTypes, never>;\n\t}\n\n\t/**\n\t * Set the parent of an entity\n\t * @param childId The entity to set as a child\n\t * @param parentId The entity to set as the parent\n\t */\n\tsetParent(childId: number, parentId: number): this {\n\t\tthis.hierarchyManager.setParent(childId, 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 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\treturn this.hierarchyManager.removeParent(childId);\n\t}\n\n\t/**\n\t * Get the parent of an entity\n\t * @param entityId The entity 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.hierarchyManager.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\n\t * @returns Readonly array of child entity IDs\n\t */\n\tgetChildren(parentId: number): readonly number[] {\n\t\treturn this.hierarchyManager.getChildren(parentId);\n\t}\n\n\t/**\n\t * Get a child at a specific index\n\t * @param parentId The parent entity\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.hierarchyManager.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\n\t * @param childId The child entity 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.hierarchyManager.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 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.hierarchyManager.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 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.hierarchyManager.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 to get the root of\n\t * @returns The root entity ID\n\t */\n\tgetRoot(entityId: number): number {\n\t\treturn this.hierarchyManager.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 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.hierarchyManager.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\n\t * @param ancestorId The potential ancestor\n\t * @returns true if entityId is a descendant of ancestorId\n\t */\n\tisDescendantOf(entityId: number, ancestorId: number): boolean {\n\t\treturn this.hierarchyManager.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\n\t * @param descendantId The potential descendant\n\t * @returns true if entityId is an ancestor of descendantId\n\t */\n\tisAncestorOf(entityId: number, descendantId: number): boolean {\n\t\treturn this.hierarchyManager.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.hierarchyManager.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.hierarchyManager.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.hierarchyManager.hierarchyIterator(options);\n\t}\n}\n",
7
7
  "import type { EventHandler } from \"./types\";\n\nexport default\nclass EventBus<EventTypes> {\n\tprivate handlers: Map<string, Array<EventHandler<any>>> = new Map();\n\n\t/**\n\t * Subscribe to an event\n\t */\n\tsubscribe<E extends keyof EventTypes>(\n\t\teventType: E,\n\t\tcallback: (data: EventTypes[E]) => void\n\t): () => void {\n\t\treturn this.addHandler(eventType, callback, false);\n\t}\n\n\t/**\n\t * Subscribe to an event once\n\t */\n\tonce<E extends keyof EventTypes>(\n\t\teventType: E,\n\t\tcallback: (data: EventTypes[E]) => void\n\t): () => void {\n\t\treturn this.addHandler(eventType, callback, true);\n\t}\n\n\t/**\n\t * Unsubscribe a specific callback from an event by reference\n\t * @returns true if the callback was found and removed, false otherwise\n\t */\n\tunsubscribe<E extends keyof EventTypes>(\n\t\teventType: E,\n\t\tcallback: (data: EventTypes[E]) => void\n\t): boolean {\n\t\tconst handlers = this.handlers.get(eventType as string);\n\t\tif (!handlers) return false;\n\n\t\tconst index = handlers.findIndex(h => h.callback === callback);\n\t\tif (index === -1) return false;\n\n\t\thandlers.splice(index, 1);\n\t\treturn true;\n\t}\n\n\t/**\n\t * Internal method to add an event handler\n\t */\n\tprivate addHandler<E extends keyof EventTypes>(\n\t\teventType: E,\n\t\tcallback: (data: EventTypes[E]) => void,\n\t\tonce: boolean\n\t): () => void {\n\t\tif (!this.handlers.has(eventType as string)) {\n\t\t\tthis.handlers.set(eventType as string, []);\n\t\t}\n\n\t\tconst handler: EventHandler<any> = {\n\t\t\tcallback,\n\t\t\tonce\n\t\t};\n\n\t\tthis.handlers.get(eventType as string)!.push(handler);\n\n\t\t// Return unsubscribe function\n\t\treturn () => {\n\t\t\tconst handlers = this.handlers.get(eventType as string);\n\t\t\tif (handlers) {\n\t\t\t\tconst index = handlers.indexOf(handler);\n\t\t\t\tif (index !== -1) {\n\t\t\t\t\thandlers.splice(index, 1);\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t}\n\n\tpublish<E extends keyof EventTypes>(\n\t\teventType: E,\n\t\tdata?: EventTypes[E]\n\t): void {\n\t\tconst handlers = this.handlers.get(eventType as string);\n\t\tif (!handlers) return;\n\n\t\t// Create a copy of handlers to avoid issues with handlers that modify the array\n\t\tconst handlersToCall = [...handlers];\n\n\t\t// Call all handlers and collect handlers to remove\n\t\tconst handlersToRemove: EventHandler<any>[] = [];\n\n\t\tfor (const handler of handlersToCall) {\n\t\t\thandler.callback(data as EventTypes[E]);\n\t\t\tif (handler.once) {\n\t\t\t\thandlersToRemove.push(handler);\n\t\t\t}\n\t\t}\n\n\t\tif (handlersToRemove.length > 0) {\n\t\t\tfor (const handler of handlersToRemove) {\n\t\t\t\tconst index = handlers.indexOf(handler);\n\t\t\t\tif (index !== -1) {\n\t\t\t\t\thandlers.splice(index, 1);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tclear(): void {\n\t\tthis.handlers.clear();\n\t}\n\n\tclearEvent<E extends keyof EventTypes>(eventType: E): void {\n\t\tthis.handlers.delete(eventType as string);\n\t}\n}\n",
8
8
  "/**\n * Resource factory with declared dependencies and optional disposal callback\n */\ninterface ResourceFactoryWithDeps<T> {\n\tdependsOn?: readonly string[];\n\tfactory: (context?: any) => T | Promise<T>;\n\tonDispose?: (resource: T, context?: any) => void | Promise<void>;\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 * Topological sort with cycle detection\n */\nfunction topologicalSort(\n\tkeys: readonly string[],\n\tgetDeps: (key: string) => readonly string[]\n): string[] {\n\tconst sorted: string[] = [];\n\tconst visited = new Set<string>();\n\tconst visiting = new Set<string>();\n\n\tfunction visit(key: string, path: string[] = []): 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\tif (keys.includes(dep)) {\n\t\t\t\tvisit(dep, [...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\nexport default\nclass ResourceManager<ResourceTypes extends Record<string, any> = Record<string, any>> {\n\tprivate resources: Map<string, any> = new Map();\n\tprivate resourceFactories: Map<string, (context?: any) => any | Promise<any>> = new Map();\n\tprivate resourceDependencies: Map<string, readonly string[]> = new Map();\n\tprivate resourceDisposers: Map<string, (resource: any, context?: any) => void | Promise<void>> = new Map();\n\tprivate initializedResourceKeys: Set<string> = new Set();\n\n\t/**\n\t * Add a resource to the manager\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?: any) => ResourceTypes[K] | Promise<ResourceTypes[K]>)\n\t\t\t| ResourceFactoryWithDeps<ResourceTypes[K]>,\n\t) {\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 as string, resource.factory);\n\t\t\tthis.resourceDependencies.set(label as string, resource.dependsOn ?? []);\n\t\t\tif (resource.onDispose) {\n\t\t\t\tthis.resourceDisposers.set(label as string, resource.onDispose);\n\t\t\t}\n\t\t} else if (this._isFactoryFunction(resource)) {\n\t\t\t// Factory function (no dependencies)\n\t\t\tthis.resourceFactories.set(label as string, resource as (context?: any) => any | Promise<any>);\n\t\t\tthis.resourceDependencies.set(label as string, []);\n\t\t} else {\n\t\t\t// Direct resource value\n\t\t\tthis.resources.set(label as string, resource);\n\t\t\tthis.initializedResourceKeys.add(label as string);\n\t\t\tthis.resourceDependencies.set(label as string, []);\n\t\t}\n\t\treturn this;\n\t}\n\n\t/**\n\t * Improved detection of factory functions vs direct values/classes\n\t * @private\n\t */\n\tprivate _isFactoryFunction(value: any): boolean {\n\t\tif (typeof value !== 'function') {\n\t\t\treturn false;\n\t\t}\n\n\t\t// Get the function as string for analysis\n\t\tconst funcStr = value.toString();\n\n\t\t// Check for explicit class syntax\n\t\tif (funcStr.startsWith('class ')) {\n\t\t\treturn false;\n\t\t}\n\n\t\t// Check for native functions/constructors\n\t\tif (funcStr.includes('[native code]')) {\n\t\t\treturn false;\n\t\t}\n\n\t\t// Check if it's a constructor function (has prototype properties beyond constructor)\n\t\t// This is a more nuanced check than just checking for prototype existence\n\t\tif (value.prototype) {\n\t\t\tconst prototypeKeys = Object.getOwnPropertyNames(value.prototype);\n\t\t\t// Constructor functions typically have additional prototype properties\n\t\t\t// Regular functions only have 'constructor'\n\t\t\tif (prototypeKeys.length > 1 || (prototypeKeys.length === 1 && prototypeKeys[0] !== 'constructor')) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\n\t\t// Additional heuristics for constructor functions\n\t\t// Constructor functions typically start with capital letter\n\t\tif (value.name && value.name[0] === value.name[0].toUpperCase() && value.name.length > 1) {\n\t\t\t// But this alone isn't enough - many factory functions also start with capitals\n\t\t\t// Only treat as constructor if it also has other constructor-like characteristics\n\t\t\tif (funcStr.includes('this.') || funcStr.includes('new ')) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\n\t\t// If it passes all checks, treat as factory function\n\t\treturn true;\n\t}\n\n\t/**\n\t * Get a resource from the manager\n\t * @param label The resource key\n\t * @param context Optional 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 */\n\tget<K extends keyof ResourceTypes>(\n\t\tlabel: K,\n\t\tcontext?: any\n\t): ResourceTypes[K] {\n\t\t// Check if we already have the initialized resource\n\t\tconst resource = this.resources.get(label as string);\n\t\tif (resource !== undefined) {\n\t\t\treturn resource as any;\n\t\t}\n\n\t\t// Check if we have a factory for this resource\n\t\tconst factory = this.resourceFactories.get(label as string);\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 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 as string, initializedResource);\n\t\t\tthis.initializedResourceKeys.add(label as string);\n\t\t}\n\n\t\treturn initializedResource as any;\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 as string) || this.resourceFactories.has(label as string);\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 as string);\n\t\tconst factoryRemoved = this.resourceFactories.delete(label as string);\n\t\tthis.resourceDependencies.delete(label as string);\n\t\tthis.resourceDisposers.delete(label as string);\n\t\tthis.initializedResourceKeys.delete(label as string);\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<string> {\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 as string) && !this.initializedResourceKeys.has(label as string);\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<string> {\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 Optional 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\tcontext?: any\n\t): Promise<void> {\n\t\tif (!this.resourceFactories.has(label as string) || this.initializedResourceKeys.has(label as string)) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst factory = this.resourceFactories.get(label as string)!;\n\t\tconst initializedResource = await factory(context);\n\t\tthis.resources.set(label as string, initializedResource);\n\t\tthis.initializedResourceKeys.add(label as string);\n\t\tthis.resourceFactories.delete(label as string);\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 Optional 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\tcontext?: any,\n\t\t...keys: K[]\n\t): Promise<void> {\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.map(k => k as string);\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,\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, 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 string[] {\n\t\treturn this.resourceDependencies.get(label as string) ?? [];\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 Optional 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\tcontext?: any\n\t): Promise<boolean> {\n\t\tconst key = label as string;\n\n\t\tif (!this.resources.has(key) && !this.resourceFactories.has(key)) {\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(key)) {\n\t\t\tconst disposer = this.resourceDisposers.get(key);\n\t\t\tconst resource = this.resources.get(key);\n\t\t\tif (disposer && resource !== undefined) {\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(key);\n\t\tthis.resourceFactories.delete(key);\n\t\tthis.resourceDependencies.delete(key);\n\t\tthis.resourceDisposers.delete(key);\n\t\tthis.initializedResourceKeys.delete(key);\n\n\t\treturn true;\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 Optional context to pass to onDispose callbacks\n\t */\n\tasync disposeResources(context?: any): 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,\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 as keyof ResourceTypes, context);\n\t\t}\n\t}\n}\n",
9
9
  "/**\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>> {\n\tprivate readonly assets: Map<string, AssetEntry<unknown>> = new Map();\n\tprivate readonly groups: Map<string, Set<string>> = new Map();\n\tprivate eventBus: EventBus<AssetEvents> | null = null;\n\n\t/**\n\t * Set the event bus for asset events\n\t * @internal\n\t */\n\tsetEventBus(eventBus: EventBus<AssetEvents>): 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: string[] = [];\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 keyStr = key as string;\n\t\tconst entry = this.assets.get(keyStr);\n\n\t\tif (!entry) {\n\t\t\tthrow new Error(`Asset '${keyStr}' 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: keyStr });\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: keyStr, 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: string): 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 as keyof AssetTypes))\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 keyStr = key as string;\n\t\tconst entry = this.assets.get(keyStr);\n\n\t\tif (!entry) {\n\t\t\tthrow new Error(`Asset '${keyStr}' not found`);\n\t\t}\n\n\t\tif (entry.status !== 'loaded' || entry.value === undefined) {\n\t\t\tthrow new Error(`Asset '${keyStr}' 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\tgetOrUndefined<K extends keyof AssetTypes>(key: K): AssetTypes[K] | undefined {\n\t\tconst keyStr = key as string;\n\t\tconst entry = this.assets.get(keyStr);\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 keyStr = key as string;\n\t\tconst entry = this.assets.get(keyStr);\n\n\t\tif (!entry) {\n\t\t\tthrow new Error(`Asset '${keyStr}' 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\tgetOrUndefined() {\n\t\t\t\treturn manager.getOrUndefined(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 keyStr = key as string;\n\t\tconst entry = this.assets.get(keyStr);\n\n\t\tif (!entry) {\n\t\t\tthrow new Error(`Asset '${keyStr}' 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 keyStr = key as string;\n\t\tconst entry = this.assets.get(keyStr);\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: string): 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: string): number {\n\t\tconst groupKeys = this.groups.get(groupName);\n\n\t\tif (!groupKeys || groupKeys.size === 0) {\n\t\t\treturn 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\treturn loaded / groupKeys.size;\n\t}\n\n\t/**\n\t * Get detailed group progress\n\t */\n\tgetGroupProgressDetails(groupName: string): { 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 details = this.getGroupProgressDetails(groupName);\n\n\t\tthis.eventBus.publish('assetGroupProgress', {\n\t\t\tgroup: groupName,\n\t\t\t...details,\n\t\t});\n\n\t\tif (details.loaded === details.total) {\n\t\t\tthis.eventBus.publish('assetGroupLoaded', { group: groupName });\n\t\t}\n\t}\n\n\t/**\n\t * Create the $assets resource object\n\t */\n\tcreateResource(): AssetsResource<AssetTypes> {\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: string): boolean {\n\t\t\t\treturn manager.isGroupLoaded(groupName);\n\t\t\t},\n\t\t\tgetGroupProgress(groupName: string): 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\tgetOrUndefined<K extends keyof AssetTypes>(key: K): AssetTypes[K] | undefined {\n\t\t\t\treturn manager.getOrUndefined(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()) as Array<keyof AssetTypes>;\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) as Array<keyof AssetTypes> : [];\n\t}\n}\n\n/**\n * Implementation of AssetConfigurator for builder pattern\n */\nexport class AssetConfiguratorImpl<A extends Record<string, unknown>> implements AssetConfigurator<A> {\n\tprivate readonly manager: AssetManager<A>;\n\n\tconstructor(manager: AssetManager<A>) {\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>> {\n\t\tthis.manager.register(key, { loader, eager: true });\n\t\treturn this as unknown as AssetConfigurator<A & Record<K, T>>;\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>> {\n\t\tthis.manager.register(key, definition);\n\t\treturn this as unknown as AssetConfigurator<A & Record<K, T>>;\n\t}\n\n\taddGroup<G extends string, T extends Record<string, () => Promise<unknown>>>(\n\t\tgroupName: G,\n\t\tassets: T\n\t): AssetConfigurator<A & { [K in keyof T]: Awaited<ReturnType<T[K]>> }> {\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]>> }>;\n\t}\n\n\t/**\n\t * Get the underlying manager\n\t * @internal\n\t */\n\tgetManager(): AssetManager<A> {\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>>(\n\tmanager?: AssetManager<A>\n): AssetConfiguratorImpl<A> {\n\treturn new AssetConfiguratorImpl(manager ?? new AssetManager<A>());\n}\n",
10
10
  "/**\n * Screen/State management for ECSpresso ECS framework\n */\n\nimport type EventBus from './event-bus';\nimport type AssetManager from './asset-manager';\nimport type ECSpresso from './ecspresso';\nimport type {\n\tScreenDefinition,\n\tScreenResource,\n\tScreenEvents,\n\tScreenConfigurator,\n\tScreenStackEntry,\n} from './screen-types';\n\ninterface ScreenEntry<Config extends Record<string, unknown>, State extends Record<string, unknown>> {\n\tdefinition: ScreenDefinition<Config, State>;\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<string, ScreenEntry<any, any>> = new Map();\n\tprivate currentScreen: ActiveScreen<Screens> | null = null;\n\tprivate screenStack: Array<ActiveScreen<Screens>> = [];\n\n\tprivate eventBus: EventBus<ScreenEvents> | null = null;\n\tprivate assetManager: AssetManager<any> | null = null;\n\tprivate ecs: ECSpresso<any, any, any, any, any> | null = null;\n\n\t/**\n\t * Set dependencies for screen transitions\n\t * @internal\n\t */\n\tsetDependencies(\n\t\teventBus: EventBus<ScreenEvents>,\n\t\tassetManager: AssetManager<any> | null,\n\t\tecs: ECSpresso<any, any, any, any, any>\n\t): void {\n\t\tthis.eventBus = eventBus;\n\t\tthis.assetManager = assetManager;\n\t\tthis.ecs = 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 });\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 nameStr = name as string;\n\t\tconst entry = this.screens.get(nameStr);\n\n\t\tif (!entry) {\n\t\t\tthrow new Error(`Screen '${nameStr}' not found`);\n\t\t}\n\n\t\t// Verify required assets\n\t\tawait this.verifyRequiredAssets(entry.definition);\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 as string);\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 as string);\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, this.ecs!);\n\t\tthis.eventBus?.publish('screenEnter', { screen: nameStr, 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 nameStr = name as string;\n\t\tconst entry = this.screens.get(nameStr);\n\n\t\tif (!entry) {\n\t\t\tthrow new Error(`Screen '${nameStr}' not found`);\n\t\t}\n\n\t\t// Verify required assets\n\t\tawait this.verifyRequiredAssets(entry.definition);\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, this.ecs!);\n\t\tthis.eventBus?.publish('screenPush', { screen: nameStr, 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\tconst nameStr = this.currentScreen.name as string;\n\t\t\tawait this.exitScreen(nameStr);\n\t\t\tthis.eventBus?.publish('screenPop', { screen: nameStr });\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: string): Promise<void> {\n\t\tconst entry = this.screens.get(name);\n\t\tif (entry?.definition.onExit) {\n\t\t\tawait entry.definition.onExit(this.ecs!);\n\t\t}\n\t\tthis.eventBus?.publish('screenExit', { screen: name });\n\t}\n\n\t/**\n\t * Verify required assets are loaded before screen transition\n\t */\n\tprivate async verifyRequiredAssets(definition: ScreenDefinition<any, any>): Promise<void> {\n\t\tif (!this.assetManager) return;\n\n\t\t// Check individual required assets\n\t\tif (definition.requiredAssets) {\n\t\t\tfor (const assetKey of definition.requiredAssets) {\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\t// Check required asset groups\n\t\tif (definition.requiredAssetGroups) {\n\t\t\tfor (const groupName of definition.requiredAssetGroups) {\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 */\n\tgetConfig<K extends keyof Screens>(): Screens[K] extends ScreenDefinition<infer C, any> ? Readonly<C> : never {\n\t\tif (!this.currentScreen) {\n\t\t\tthrow new Error('No current screen');\n\t\t}\n\t\treturn this.currentScreen.config as any;\n\t}\n\n\t/**\n\t * Get the current screen config or null\n\t */\n\tgetConfigOrNull<K extends keyof Screens>(): (Screens[K] extends ScreenDefinition<infer C, any> ? Readonly<C> : never) | null {\n\t\treturn (this.currentScreen?.config ?? null) as any;\n\t}\n\n\t/**\n\t * Get the current screen state (mutable)\n\t */\n\tgetState<K extends keyof Screens>(): Screens[K] extends ScreenDefinition<any, infer S> ? S : never {\n\t\tif (!this.currentScreen) {\n\t\t\tthrow new Error('No current screen');\n\t\t}\n\t\treturn this.currentScreen.state as any;\n\t}\n\n\t/**\n\t * Get the current screen state or null\n\t */\n\tgetStateOrNull<K extends keyof Screens>(): (Screens[K] extends ScreenDefinition<any, infer S> ? S : never) | null {\n\t\treturn (this.currentScreen?.state ?? null) as any;\n\t}\n\n\t/**\n\t * Update the current screen state\n\t */\n\tupdateState<K extends keyof Screens>(\n\t\tupdate: Partial<Screens[K] extends ScreenDefinition<any, infer S> ? S : never> |\n\t\t\t((current: Screens[K] extends ScreenDefinition<any, infer S> ? S : never) => Partial<Screens[K] extends ScreenDefinition<any, infer S> ? S : never>)\n\t): void {\n\t\tif (!this.currentScreen) {\n\t\t\tthrow new Error('No current screen');\n\t\t}\n\n\t\tconst partial = typeof update === 'function'\n\t\t\t? (update as (current: any) => any)(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,\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(): any {\n\t\t\t\treturn manager.getConfigOrNull();\n\t\t\t},\n\t\t\tget state(): any {\n\t\t\t\treturn manager.getStateOrNull();\n\t\t\t},\n\t\t\tset state(value: any) {\n\t\t\t\tif (manager.currentScreen) {\n\t\t\t\t\tmanager.currentScreen.state = value;\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()) as Array<keyof Screens>;\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 as string);\n\t}\n}\n\n/**\n * Implementation of ScreenConfigurator for builder pattern\n */\nexport class ScreenConfiguratorImpl<Screens extends Record<string, ScreenDefinition<any, any>>> implements ScreenConfigurator<Screens> {\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>\n\t): ScreenConfigurator<Screens & Record<K, ScreenDefinition<Config, State>>> {\n\t\tthis.manager.register(name, definition);\n\t\treturn this as unknown as ScreenConfigurator<Screens & Record<K, ScreenDefinition<Config, State>>>;\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>>(\n\tmanager?: ScreenManager<Screens>\n): ScreenConfiguratorImpl<Screens> {\n\treturn new ScreenConfiguratorImpl(manager ?? new ScreenManager<Screens>());\n}\n",
11
- "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> {\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/** Called when an entity starts matching the query */\n\tonEnter?: (entity: FilteredEntity<ComponentTypes, WithComponents, WithoutComponents>) => 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>;\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>> {\n\tprivate queries: Map<string, StoredQuery<ComponentTypes>> = new Map();\n\tprivate entityManager: EntityManager<ComponentTypes>;\n\n\tconstructor(entityManager: EntityManager<ComponentTypes>) {\n\t\tthis.entityManager = entityManager;\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>(\n\t\tname: string,\n\t\tdefinition: ReactiveQueryDefinition<ComponentTypes, WithComponents, WithoutComponents>\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// 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\tstoredQuery.matchingEntities.add(entity.id);\n\t\t\tdefinition.onEnter?.(entity as FilteredEntity<ComponentTypes, WithComponents, WithoutComponents>);\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: string): boolean {\n\t\treturn this.queries.delete(name);\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>\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\treturn true;\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 [_name, query] of this.queries) {\n\t\t\tconst wasMatching = query.matchingEntities.has(entity.id);\n\t\t\tconst nowMatches = this.entityMatchesQuery(entity, query.definition);\n\n\t\t\tif (!wasMatching && nowMatches) {\n\t\t\t\t// Entity started matching - trigger onEnter\n\t\t\t\tquery.matchingEntities.add(entity.id);\n\t\t\t\tquery.definition.onEnter?.(entity as FilteredEntity<ComponentTypes, any, any>);\n\t\t\t} else if (wasMatching && !nowMatches) {\n\t\t\t\t// Entity stopped matching (added excluded component) - trigger onExit\n\t\t\t\tquery.matchingEntities.delete(entity.id);\n\t\t\t\tquery.definition.onExit?.(entity.id);\n\t\t\t}\n\t\t\t// If component was replaced (wasMatching && nowMatches), do nothing\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 [_name, query] of this.queries) {\n\t\t\tconst wasMatching = query.matchingEntities.has(entity.id);\n\t\t\tconst nowMatches = this.entityMatchesQuery(entity, query.definition);\n\n\t\t\tif (wasMatching && !nowMatches) {\n\t\t\t\t// Entity stopped matching - trigger onExit\n\t\t\t\tquery.matchingEntities.delete(entity.id);\n\t\t\t\tquery.definition.onExit?.(entity.id);\n\t\t\t} else if (!wasMatching && nowMatches) {\n\t\t\t\t// Entity started matching (removed excluded component) - trigger onEnter\n\t\t\t\tquery.matchingEntities.add(entity.id);\n\t\t\t\tquery.definition.onEnter?.(entity as FilteredEntity<ComponentTypes, any, any>);\n\t\t\t}\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 [_name, query] of this.queries) {\n\t\t\tconst wasMatching = query.matchingEntities.has(entity.id);\n\t\t\tconst nowMatches = this.entityMatchesQuery(entity, query.definition);\n\n\t\t\tif (!wasMatching && nowMatches) {\n\t\t\t\t// Entity started matching - trigger onEnter\n\t\t\t\tquery.matchingEntities.add(entity.id);\n\t\t\t\tquery.definition.onEnter?.(entity as FilteredEntity<ComponentTypes, any, any>);\n\t\t\t} else if (wasMatching && !nowMatches) {\n\t\t\t\t// Entity stopped matching - trigger onExit\n\t\t\t\tquery.matchingEntities.delete(entity.id);\n\t\t\t\tquery.definition.onExit?.(entity.id);\n\t\t\t}\n\t\t}\n\t}\n}\n",
11
+ "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>> {\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: string,\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: string): 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 * 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 [_name, query] of this.queries) {\n\t\t\tconst wasMatching = query.matchingEntities.has(entity.id);\n\t\t\tconst nowMatches = this.entityMatchesQuery(entity, query.definition);\n\n\t\t\tif (!wasMatching && nowMatches) {\n\t\t\t\t// Entity started matching - trigger onEnter\n\t\t\t\tquery.matchingEntities.add(entity.id);\n\t\t\t\tquery.definition.onEnter?.(entity as FilteredEntity<ComponentTypes, any, any, any>);\n\t\t\t} else if (wasMatching && !nowMatches) {\n\t\t\t\t// Entity stopped matching (added excluded component) - trigger onExit\n\t\t\t\tquery.matchingEntities.delete(entity.id);\n\t\t\t\tquery.definition.onExit?.(entity.id);\n\t\t\t}\n\t\t\t// If component was replaced (wasMatching && nowMatches), do nothing\n\t\t}\n\n\t\t// If any query uses parentHas, recheck children of this entity\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 [_name, query] of this.queries) {\n\t\t\tconst wasMatching = query.matchingEntities.has(entity.id);\n\t\t\tconst nowMatches = this.entityMatchesQuery(entity, query.definition);\n\n\t\t\tif (wasMatching && !nowMatches) {\n\t\t\t\t// Entity stopped matching - trigger onExit\n\t\t\t\tquery.matchingEntities.delete(entity.id);\n\t\t\t\tquery.definition.onExit?.(entity.id);\n\t\t\t} else if (!wasMatching && nowMatches) {\n\t\t\t\t// Entity started matching (removed excluded component) - trigger onEnter\n\t\t\t\tquery.matchingEntities.add(entity.id);\n\t\t\t\tquery.definition.onEnter?.(entity as FilteredEntity<ComponentTypes, any, any, any>);\n\t\t\t}\n\t\t}\n\n\t\t// If any query uses parentHas, recheck children of this entity\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 [_name, query] of this.queries) {\n\t\t\tconst wasMatching = query.matchingEntities.has(entity.id);\n\t\t\tconst nowMatches = this.entityMatchesQuery(entity, query.definition);\n\n\t\t\tif (!wasMatching && nowMatches) {\n\t\t\t\t// Entity started matching - trigger onEnter\n\t\t\t\tquery.matchingEntities.add(entity.id);\n\t\t\t\tquery.definition.onEnter?.(entity as FilteredEntity<ComponentTypes, any, any, any>);\n\t\t\t} else if (wasMatching && !nowMatches) {\n\t\t\t\t// Entity stopped matching - trigger onExit\n\t\t\t\tquery.matchingEntities.delete(entity.id);\n\t\t\t\tquery.definition.onExit?.(entity.id);\n\t\t\t}\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",
12
12
  "import type ECSpresso from './ecspresso';\nimport type { RemoveEntityOptions } from './types';\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\tComponentTypes extends Record<string, any> = {},\n\tEventTypes extends Record<string, any> = {},\n\tResourceTypes extends Record<string, any> = {}\n> {\n\tprivate commands: Array<(ecs: ECSpresso<ComponentTypes, EventTypes, ResourceTypes, any, any>) => void> = [];\n\n\t/**\n\t * Queue an entity removal command\n\t * @param entityId The ID of the entity 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 ID of the entity\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 ComponentTypes>(\n\t\tentityId: number,\n\t\tcomponentName: K,\n\t\tcomponentValue: ComponentTypes[K]\n\t): void {\n\t\tthis.commands.push((ecs) => {\n\t\t\tecs.entityManager.addComponent(entityId, componentName, componentValue);\n\t\t});\n\t}\n\n\t/**\n\t * Queue a component removal command\n\t * @param entityId The ID of the entity\n\t * @param componentName The name of the component to remove\n\t */\n\tremoveComponent<K extends keyof ComponentTypes>(\n\t\tentityId: number,\n\t\tcomponentName: K\n\t): void {\n\t\tthis.commands.push((ecs) => {\n\t\t\tecs.entityManager.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 ComponentTypes]?: ComponentTypes[K] }>(\n\t\tcomponents: T & Record<Exclude<keyof T, keyof ComponentTypes>, 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 ID of the parent entity\n\t * @param components The initial components for the new child entity\n\t */\n\tspawnChild<T extends { [K in keyof ComponentTypes]?: ComponentTypes[K] }>(\n\t\tparentId: number,\n\t\tcomponents: T & Record<Exclude<keyof T, keyof ComponentTypes>, 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 ID of the entity\n\t * @param components Object with component names as keys and component data as values\n\t */\n\taddComponents<T extends { [K in keyof ComponentTypes]?: ComponentTypes[K] }>(\n\t\tentityId: number,\n\t\tcomponents: T & Record<Exclude<keyof T, keyof ComponentTypes>, never>\n\t): void {\n\t\tthis.commands.push((ecs) => {\n\t\t\tecs.entityManager.addComponents(entityId, components);\n\t\t});\n\t}\n\n\t/**\n\t * Queue a parent assignment command\n\t * @param childId The ID of the child entity\n\t * @param parentId The ID of the parent entity\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 markChanged command\n\t * @param entityId The ID of the entity\n\t * @param componentName The component to mark as changed\n\t */\n\tmarkChanged<K extends keyof ComponentTypes>(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 ID of the child entity\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<AssetTypes extends Record<string, any> = {}, ScreenStates extends Record<string, any> = {}>(\n\t\tecs: ECSpresso<ComponentTypes, EventTypes, ResourceTypes, AssetTypes, ScreenStates>\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 = [];\n\t}\n\n\t/**\n\t * Clear all queued commands without executing them\n\t */\n\tclear(): void {\n\t\tthis.commands = [];\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",
13
- "import Bundle from \"./bundle\";\nimport ECSpresso from \"./ecspresso\";\nimport type { FilteredEntity, System, SystemPhase } from \"./types\";\n\n/**\n * Builder class for creating type-safe ECS Systems with proper query inference\n */\nexport class SystemBuilder<\n\tComponentTypes extends Record<string, any> = Record<string, any>,\n\tEventTypes extends Record<string, any> = Record<string, any>,\n\tResourceTypes extends Record<string, any> = Record<string, any>,\n\tQueries extends Record<string, QueryDefinition<ComponentTypes>> = {},\n> {\n\tprivate queries: Queries = {} as Queries;\n\tprivate processFunction?: ProcessFunction<ComponentTypes, EventTypes, ResourceTypes, Queries>;\n\tprivate detachFunction?: LifecycleFunction<ComponentTypes, EventTypes, ResourceTypes>;\n\tprivate initializeFunction?: LifecycleFunction<ComponentTypes, EventTypes, ResourceTypes>;\n\tprivate eventHandlers?: {\n\t\t[EventName in keyof EventTypes]?: {\n\t\t\thandler(\n\t\t\t\tdata: EventTypes[EventName],\n\t\t\t\tecs: ECSpresso<\n\t\t\t\t\tComponentTypes,\n\t\t\t\t\tEventTypes,\n\t\t\t\t\tResourceTypes\n\t\t\t\t>,\n\t\t\t): void;\n\t\t};\n\t};\n\tprivate _priority = 0; // Default priority is 0\n\tprivate _phase: SystemPhase = 'update'; // Default phase is 'update'\n\tprivate _isRegistered = false; // Track if system has been auto-registered\n\tprivate _groups: string[] = [];\n\tprivate _inScreens?: string[];\n\tprivate _excludeScreens?: string[];\n\tprivate _requiredAssets?: string[];\n\n\tconstructor(\n\t\tprivate _label: string,\n\t\tprivate _ecspresso: ECSpresso<ComponentTypes, EventTypes, ResourceTypes> | null = null,\n\t\tprivate _bundle: Bundle<ComponentTypes, EventTypes, ResourceTypes> | null = null,\n\t) {}\n\n\tget label() {\n\t\treturn this._label;\n\t}\n\n\t/**\n\t * Returns the associated bundle if one was provided in the constructor\n\t */\n\tget bundle() {\n\t\treturn this._bundle;\n\t}\n\n\t/**\n\t * Returns the associated ECSpresso instance if one was provided in the constructor\n\t */\n\tget ecspresso() {\n\t\treturn this._ecspresso;\n\t}\n\n\t/**\n\t * Auto-register this system with its ECSpresso instance if not already registered\n\t * @private\n\t */\n\tprivate _autoRegister(): void {\n\t\tif (this._isRegistered || !this._ecspresso) return;\n\t\t\n\t\tconst system = this._buildSystemObject();\n\t\tregisterSystemWithEcspresso(system, this._ecspresso);\n\t\tthis._isRegistered = true;\n\t}\n\n\t/**\n\t * Create the system object without registering it\n\t * @private\n\t */\n\tprivate _buildSystemObject(): System<ComponentTypes, any, any, EventTypes, ResourceTypes> {\n\t\treturn this._createSystemObject();\n\t}\n\n\t/**\n\t * Create a system object with all configured properties\n\t * @private\n\t */\n\tprivate _createSystemObject(): System<ComponentTypes, any, any, EventTypes, ResourceTypes> {\n\t\tconst system: System<ComponentTypes, any, any, EventTypes, ResourceTypes> = {\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\treturn system;\n\t}\n\n\t// TODO: Should this be a setter?\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(groupName: string): this {\n\t\tif (!this._groups.includes(groupName)) {\n\t\t\tthis._groups.push(groupName);\n\t\t}\n\t\treturn this;\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<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<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<string>): this {\n\t\tthis._requiredAssets = [...assets];\n\t\treturn this;\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 ComponentTypes,\n\t\tWithoutComponents extends keyof ComponentTypes = never,\n\t\tNewQueries extends Queries & Record<QueryName, QueryDefinition<ComponentTypes, WithComponents, WithoutComponents>> =\n\t\t\tQueries & Record<QueryName, QueryDefinition<ComponentTypes, WithComponents, WithoutComponents>>\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}\n\t): this extends SystemBuilderWithEcspresso<ComponentTypes, EventTypes, ResourceTypes, Queries>\n\t\t? SystemBuilderWithEcspresso<ComponentTypes, EventTypes, ResourceTypes, NewQueries>\n\t\t: this extends SystemBuilderWithBundle<ComponentTypes, EventTypes, ResourceTypes, Queries>\n\t\t\t? SystemBuilderWithBundle<ComponentTypes, EventTypes, ResourceTypes, NewQueries>\n\t\t\t: SystemBuilder<ComponentTypes, EventTypes, ResourceTypes, NewQueries> {\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 * @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<ComponentTypes, EventTypes, ResourceTypes, Queries>\n\t): this {\n\t\tthis.processFunction = process;\n\t\treturn this;\n\t}\n\n\t/**\n\t * Register this system with its ECSpresso instance and return the ECSpresso for chaining\n\t * This enables seamless method chaining: .registerAndContinue().addSystem(...)\n\t * @returns ECSpresso instance if attached to one, otherwise throws an error\n\t */\n\tregisterAndContinue(): ECSpresso<ComponentTypes, EventTypes, ResourceTypes> {\n\t\tif (!this._ecspresso) {\n\t\t\tthrow new Error(`Cannot register system '${this._label}': SystemBuilder is not attached to an ECSpresso instance. Use Bundle.addSystem() or ECSpresso.addSystem() instead.`);\n\t\t}\n\t\t\n\t\tthis._autoRegister();\n\t\treturn this._ecspresso;\n\t}\n\n\t/**\n\t * Complete this system and return the parent container for seamless chaining\n\t * - For ECSpresso-attached builders: registers the system and returns ECSpresso\n\t * - For Bundle-attached builders: returns the Bundle\n\t * This method is typed via the specialized interfaces (SystemBuilderWithEcspresso, SystemBuilderWithBundle)\n\t */\n\tand(): ECSpresso<ComponentTypes, EventTypes, ResourceTypes> | Bundle<ComponentTypes, EventTypes, ResourceTypes> {\n\t\tif (this._ecspresso) {\n\t\t\tthis._autoRegister();\n\t\t\treturn this._ecspresso;\n\t\t}\n\n\t\tif (this._bundle) {\n\t\t\treturn this._bundle;\n\t\t}\n\n\t\tthrow new Error(`Cannot use and() on system '${this._label}': not attached to ECSpresso or Bundle.`);\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<ComponentTypes, EventTypes, ResourceTypes>\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<ComponentTypes, EventTypes, ResourceTypes>\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 EventTypes]?: {\n\t\t\t\thandler(\n\t\t\t\t\tdata: EventTypes[EventName],\n\t\t\t\t\tecs: ECSpresso<ComponentTypes, EventTypes, ResourceTypes>\n\t\t\t\t): void;\n\t\t\t};\n\t\t}\n\t): this {\n\t\tthis.eventHandlers = handlers;\n\t\treturn this;\n\t}\n\n\t/**\n\t * Build the final system object\n\t */\n\tbuild(ecspresso?: ECSpresso<ComponentTypes, EventTypes, ResourceTypes>) {\n\t\tconst system = this._createSystemObject();\n\n\t\tif (this._ecspresso) {\n\t\t\tregisterSystemWithEcspresso(system, this._ecspresso);\n\t\t}\n\n\t\tif(ecspresso) {\n\t\t\tregisterSystemWithEcspresso(system, ecspresso);\n\t\t}\n\n\t\treturn this;\n\t}\n}\n\n/**\n * Helper function to register a system with an ECSpresso instance\n * This handles attaching the system and setting up event handlers\n * @internal Used by SystemBuilder and Bundle\n */\nexport function registerSystemWithEcspresso<\n\tComponentTypes extends Record<string, any>,\n\tEventTypes extends Record<string, any>,\n\tResourceTypes extends Record<string, any>\n>(\n\tsystem: System<ComponentTypes, any, any, EventTypes, ResourceTypes>,\n\tecspresso: ECSpresso<ComponentTypes, EventTypes, ResourceTypes>\n) {\n\t// Use the new internal registration method instead of direct property access\n\tecspresso._registerSystem(system);\n}\n\n// Helper type definitions\ntype QueryDefinition<\n\tComponentTypes,\n\tWithComponents extends keyof ComponentTypes = any,\n\tWithoutComponents extends keyof ComponentTypes = any,\n> = {\n\twith: ReadonlyArray<WithComponents>;\n\twithout?: ReadonlyArray<WithoutComponents>;\n\tchanged?: ReadonlyArray<WithComponents>;\n};\n\ntype QueryResults<\n\tComponentTypes,\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, any> ? W : never,\n\t\t\tQueries[QueryName] extends QueryDefinition<ComponentTypes, any, infer WO> ? WO : never\n\t\t>[]\n\t\t: never;\n};\n\n/**\n * Function signature for system process methods\n * @param queries Results of entity queries defined by the system\n * @param deltaTime Time elapsed since last update in seconds\n * @param ecs The ECSpresso instance providing access to all ECS functionality\n */\ntype ProcessFunction<\n\tComponentTypes extends Record<string, any>,\n\tEventTypes extends Record<string, any>,\n\tResourceTypes extends Record<string, any>,\n\tQueries extends Record<string, QueryDefinition<ComponentTypes>>,\n> = (\n\tqueries: QueryResults<ComponentTypes, Queries>,\n\tdeltaTime: number,\n\tecs: ECSpresso<\n\t\tComponentTypes,\n\t\tEventTypes,\n\t\tResourceTypes\n\t>\n) => void;\n\n/**\n * Type for system initialization functions\n * These can be asynchronous\n */\ntype LifecycleFunction<\n\tComponentTypes extends Record<string, any>,\n\tEventTypes extends Record<string, any>,\n\tResourceTypes extends Record<string, any>,\n> = (\n\tecs: ECSpresso<\n\t\tComponentTypes,\n\t\tEventTypes,\n\t\tResourceTypes\n\t>,\n) => void | Promise<void>;\n\n/**\n * Create a SystemBuilder attached to an ECSpresso instance\n * Helper function used by ECSpresso.addSystem\n */\nexport function createEcspressoSystemBuilder<\n\tComponentTypes extends Record<string, any>,\n\tEventTypes extends Record<string, any>,\n\tResourceTypes extends Record<string, any>\n>(\n\tlabel: string,\n\tecspresso: ECSpresso<ComponentTypes, EventTypes, ResourceTypes>\n): SystemBuilderWithEcspresso<ComponentTypes, EventTypes, ResourceTypes> {\n\treturn new SystemBuilder<ComponentTypes, EventTypes, ResourceTypes>(\n\t\tlabel,\n\t\tecspresso\n\t) as SystemBuilderWithEcspresso<ComponentTypes, EventTypes, ResourceTypes>;\n}\n\n/**\n * Create a SystemBuilder attached to a Bundle\n * Helper function used by Bundle.addSystem\n */\nexport function createBundleSystemBuilder<\n\tComponentTypes extends Record<string, any>,\n\tEventTypes extends Record<string, any>,\n\tResourceTypes extends Record<string, any>\n>(\n\tlabel: string,\n\tbundle: Bundle<ComponentTypes, EventTypes, ResourceTypes>\n): SystemBuilderWithBundle<ComponentTypes, EventTypes, ResourceTypes> {\n\treturn new SystemBuilder<ComponentTypes, EventTypes, ResourceTypes>(\n\t\tlabel,\n\t\tnull,\n\t\tbundle\n\t) as SystemBuilderWithBundle<ComponentTypes, EventTypes, ResourceTypes>;\n}\n\n// Type interfaces for specialized SystemBuilders\n\n/**\n * SystemBuilder with a guaranteed non-null reference to an ECSpresso instance\n */\nexport interface SystemBuilderWithEcspresso<\n\tComponentTypes extends Record<string, any>,\n\tEventTypes extends Record<string, any>,\n\tResourceTypes extends Record<string, any>,\n\tQueries extends Record<string, QueryDefinition<ComponentTypes>> = {}\n> extends SystemBuilder<ComponentTypes, EventTypes, ResourceTypes, Queries> {\n\treadonly ecspresso: ECSpresso<ComponentTypes, EventTypes, ResourceTypes>;\n\t\n\t/**\n\t * Complete this system and return ECSpresso for seamless chaining\n\t * Automatically registers the system when called\n\t */\n\tand(): ECSpresso<ComponentTypes, EventTypes, ResourceTypes>;\n}\n\n/**\n * SystemBuilder with a guaranteed non-null reference to a Bundle\n */\nexport interface SystemBuilderWithBundle<\n\tComponentTypes extends Record<string, any>,\n\tEventTypes extends Record<string, any>,\n\tResourceTypes extends Record<string, any>,\n\tQueries extends Record<string, QueryDefinition<ComponentTypes>> = {}\n> extends SystemBuilder<ComponentTypes, EventTypes, ResourceTypes, Queries> {\n\treadonly bundle: Bundle<ComponentTypes, EventTypes, ResourceTypes>;\n\n\t/**\n\t * Complete this system and return the Bundle for chaining\n\t * Enables fluent API: bundle.addSystem(...).and().addSystem(...)\n\t */\n\tand(): Bundle<ComponentTypes, EventTypes, ResourceTypes>;\n}\n",
14
- "import EntityManager from \"./entity-manager\";\nimport EventBus from \"./event-bus\";\nimport ResourceManager from \"./resource-manager\";\nimport AssetManager, { AssetConfiguratorImpl, createAssetConfigurator } from \"./asset-manager\";\nimport ScreenManager, { ScreenConfiguratorImpl, createScreenConfigurator } 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 type Bundle from \"./bundle\";\nimport { createEcspressoSystemBuilder } from \"./system-builder\";\nimport { version } from \"../package.json\";\nimport type { BundlesAreCompatible } from \"./type-utils\";\nimport type { AssetHandle, AssetConfigurator } from \"./asset-types\";\nimport type { ScreenDefinition, ScreenConfigurator } from \"./screen-types\";\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\tComponentTypes extends Record<string, any> = {},\n\tEventTypes extends Record<string, any> = {},\n\tResourceTypes extends Record<string, any> = {},\n\tAssetTypes extends Record<string, unknown> = {},\n\tScreenStates extends Record<string, ScreenDefinition<any, any>> = {},\n> {\n\t/**\n\t\t* Default constructor\n\t*/\n\tnew(): ECSpresso<ComponentTypes, EventTypes, ResourceTypes, AssetTypes, ScreenStates>;\n}\n\nconst PHASE_ORDER: readonly SystemPhase[] = [\n\t'preUpdate', 'fixedUpdate', 'update', 'postUpdate', 'render',\n];\n\nconst EmptyQueryResults = {};\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\tComponentTypes extends Record<string, any> = {},\n\tEventTypes extends Record<string, any> = {},\n\tResourceTypes extends Record<string, any> = {},\n\tAssetTypes extends Record<string, unknown> = {},\n\tScreenStates extends Record<string, ScreenDefinition<any, any>> = {},\n> {\n\t/** Library version*/\n\tpublic static readonly VERSION = version;\n\n\t/** Access/modify stored components and entities*/\n\tprivate _entityManager: EntityManager<ComponentTypes>;\n\t/** Publish/subscribe to events*/\n\tprivate _eventBus: EventBus<EventTypes>;\n\t/** Access/modify registered resources*/\n\tprivate _resourceManager: ResourceManager<ResourceTypes>;\n\t/** Command buffer for deferred structural changes */\n\tprivate _commandBuffer: CommandBuffer<ComponentTypes, EventTypes, ResourceTypes>;\n\n\t/** Registered systems that will be updated in order*/\n\tprivate _systems: Array<System<ComponentTypes, any, any, EventTypes, ResourceTypes, AssetTypes, ScreenStates>> = [];\n\t/** Systems grouped by execution phase, each sorted by priority */\n\tprivate _phaseSystems: Record<SystemPhase, Array<System<ComponentTypes, any, any, EventTypes, ResourceTypes, AssetTypes, ScreenStates>>> = {\n\t\tpreUpdate: [], fixedUpdate: [], update: [], postUpdate: [], render: [],\n\t};\n\t/** Track installed bundles to prevent duplicates*/\n\tprivate _installedBundles: 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<AssetTypes> | null = null;\n\t/** Screen manager for state/screen transitions */\n\tprivate _screenManager: ScreenManager<ScreenStates> | null = null;\n\t/** Reactive query manager for enter/exit callbacks */\n\tprivate _reactiveQueryManager: ReactiveQueryManager<ComponentTypes>;\n\t/** Post-update hooks to be called after all systems in update() */\n\tprivate _postUpdateHooks: Array<(ecs: ECSpresso<ComponentTypes, EventTypes, ResourceTypes>, deltaTime: 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\n\t/**\n\t\t* Creates a new ECSpresso instance.\n\t*/\n\tconstructor() {\n\t\tthis._entityManager = new EntityManager<ComponentTypes>();\n\t\tthis._eventBus = new EventBus<EventTypes>();\n\t\tthis._resourceManager = new ResourceManager<ResourceTypes>();\n\t\tthis._reactiveQueryManager = new ReactiveQueryManager<ComponentTypes>(this._entityManager);\n\t\tthis._commandBuffer = new CommandBuffer<ComponentTypes, EventTypes, ResourceTypes>();\n\n\t\t// Wire up component lifecycle hooks for reactive queries\n\t\tthis._setupReactiveQueryHooks();\n\t}\n\n\t/**\n\t * Sets up component lifecycle hooks for reactive query tracking\n\t * @private\n\t */\n\tprivate _setupReactiveQueryHooks(): void {\n\t\t// Batching mechanism: during addComponents, we defer reactive query checks\n\t\t// until all components are added to avoid intermediate state triggers\n\t\tlet batchingDepth = 0;\n\t\tconst pendingChecks = new Set<number>();\n\n\t\tconst flushPendingChecks = () => {\n\t\t\tfor (const entityId of pendingChecks) {\n\t\t\t\tconst entity = this._entityManager.getEntity(entityId);\n\t\t\t\tif (entity) {\n\t\t\t\t\t// Do a full recheck of the entity against all queries\n\t\t\t\t\tthis._reactiveQueryManager.recheckEntity(entity);\n\t\t\t\t}\n\t\t\t}\n\t\t\tpendingChecks.clear();\n\t\t};\n\n\t\t// Track added components for reactive queries\n\t\tconst originalAddComponent = this._entityManager.addComponent.bind(this._entityManager);\n\t\tthis._entityManager.addComponent = <K extends keyof ComponentTypes>(\n\t\t\tentityOrId: number | Entity<ComponentTypes>,\n\t\t\tcomponentName: K,\n\t\t\tdata: ComponentTypes[K]\n\t\t) => {\n\t\t\tconst result = originalAddComponent(entityOrId, componentName, data);\n\t\t\tconst entityId = typeof entityOrId === 'number' ? entityOrId : entityOrId.id;\n\n\t\t\t// Auto-mark component as changed (always, regardless of batching)\n\t\t\tthis._entityManager.markChanged(entityId, componentName);\n\n\t\t\tif (batchingDepth > 0) {\n\t\t\t\t// During batching, just track that this entity needs checking\n\t\t\t\tpendingChecks.add(entityId);\n\t\t\t} else {\n\t\t\t\t// Not batching, check immediately\n\t\t\t\tconst entity = this._entityManager.getEntity(entityId);\n\t\t\t\tif (entity) {\n\t\t\t\t\tthis._reactiveQueryManager.onComponentAdded(entity, componentName);\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn result;\n\t\t};\n\n\t\t// Wrap addComponents to enable batching\n\t\tconst originalAddComponents = this._entityManager.addComponents.bind(this._entityManager);\n\t\tthis._entityManager.addComponents = <T extends { [K in keyof ComponentTypes]?: ComponentTypes[K] }>(\n\t\t\tentityOrId: number | Entity<ComponentTypes>,\n\t\t\tcomponents: T & Record<Exclude<keyof T, keyof ComponentTypes>, never>\n\t\t) => {\n\t\t\tbatchingDepth++;\n\t\t\tconst result = originalAddComponents(entityOrId, components);\n\t\t\tbatchingDepth--;\n\t\t\tif (batchingDepth === 0) {\n\t\t\t\tflushPendingChecks();\n\t\t\t}\n\t\t\treturn result;\n\t\t};\n\n\t\t// Track removed components for reactive queries\n\t\tconst originalRemoveComponent = this._entityManager.removeComponent.bind(this._entityManager);\n\t\tthis._entityManager.removeComponent = <K extends keyof ComponentTypes>(\n\t\t\tentityOrId: number | Entity<ComponentTypes>,\n\t\t\tcomponentName: K\n\t\t) => {\n\t\t\tconst entityId = typeof entityOrId === 'number' ? entityOrId : entityOrId.id;\n\t\t\tconst entity = this._entityManager.getEntity(entityId);\n\t\t\tconst result = originalRemoveComponent(entityOrId, componentName);\n\t\t\tif (entity) {\n\t\t\t\tthis._reactiveQueryManager.onComponentRemoved(entity, componentName);\n\t\t\t}\n\t\t\treturn result;\n\t\t};\n\n\t\t// Track entity removal for reactive queries\n\t\tconst originalRemoveEntity = this._entityManager.removeEntity.bind(this._entityManager);\n\t\tthis._entityManager.removeEntity = (entityOrId, options?) => {\n\t\t\tconst entityId = typeof entityOrId === 'number' ? entityOrId : entityOrId.id;\n\t\t\t// Notify reactive query manager about all entities being removed (including descendants)\n\t\t\tconst entity = this._entityManager.getEntity(entityId);\n\t\t\tif (entity) {\n\t\t\t\tconst cascade = options?.cascade ?? true;\n\t\t\t\tif (cascade) {\n\t\t\t\t\tconst descendants = this._entityManager.getDescendants(entityId);\n\t\t\t\t\tfor (const descId of descendants) {\n\t\t\t\t\t\tthis._reactiveQueryManager.onEntityRemoved(descId);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tthis._reactiveQueryManager.onEntityRemoved(entityId);\n\t\t\t}\n\t\t\treturn originalRemoveEntity(entityOrId, options);\n\t\t};\n\t}\n\n\t/**\n\t\t* Creates a new ECSpresso builder for type-safe bundle installation.\n\t\t* This is the preferred way to create an ECSpresso instance with bundles.\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<BaseComponents, BaseEvents, BaseResources>()\n\t *\t .withBundle(bundle1)\n\t *\t .withBundle(bundle2)\n\t *\t .build();\n\t\t* ```\n\t*/\n\tstatic create<\n\t\tC extends Record<string, any> = {},\n\t\tE extends Record<string, any> = {},\n\t\tR extends Record<string, any> = {},\n\t\tA extends Record<string, unknown> = {},\n\t\tS extends Record<string, ScreenDefinition<any, any>> = {},\n\t>(): ECSpressoBuilder<C, E, R, A, S> {\n\t\treturn new ECSpressoBuilder<C, E, R, A, S>();\n\t}\n\n\t/**\n\t\t* Adds a system directly to this ECSpresso instance\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) {\n\t\treturn createEcspressoSystemBuilder<\n\t\t\tComponentTypes,\n\t\t\tEventTypes,\n\t\t\tResourceTypes\n\t\t>(label, this);\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\tconst currentScreen = (this._screenManager?.getCurrentScreen() ?? null) as string | null;\n\n\t\t// 1. preUpdate phase\n\t\tthis._executePhase(this._phaseSystems.preUpdate, deltaTime, currentScreen);\n\t\tthis._commandBuffer.playback(this);\n\n\t\t// 2. fixedUpdate phase — accumulate time and step N times\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\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._executePhase(this._phaseSystems.update, deltaTime, currentScreen);\n\t\tthis._commandBuffer.playback(this);\n\n\t\t// 4. postUpdate phase\n\t\tthis._executePhase(this._phaseSystems.postUpdate, deltaTime, currentScreen);\n\t\tthis._commandBuffer.playback(this);\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(this as unknown as ECSpresso<ComponentTypes, EventTypes, ResourceTypes>, deltaTime);\n\t\t}\n\n\t\t// 6. render phase\n\t\tthis._executePhase(this._phaseSystems.render, deltaTime, currentScreen);\n\t\tthis._commandBuffer.playback(this);\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<ComponentTypes, any, any, EventTypes, ResourceTypes, AssetTypes, ScreenStates>>,\n\t\tdeltaTime: number,\n\t\tcurrentScreen: string | null\n\t): void {\n\t\tfor (const system of systems) {\n\t\t\tif (!system.process) 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 as string)) {\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 as string)) {\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 as keyof AssetTypes)) {\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// Prepare query results for each defined query in the system\n\t\t\tconst queryResults: Record<string, any> = {};\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\tqueryResults[queryName] = this._entityManager.getEntitiesWithQuery(\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);\n\n\t\t\t\t\t\tif(queryResults[queryName].length) {\n\t\t\t\t\t\t\thasResults = true; // At least one query has results\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 (hasResults) {\n\t\t\t\tsystem.process(queryResults, deltaTime, this);\n\t\t\t} else if(!hasQueries) {\n\t\t\t\tsystem.process(EmptyQueryResults, deltaTime, this);\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 * 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 * @param resourceKeys Optional array of specific resource keys to initialize\n\t * @returns Promise that resolves when everything is initialized\n\t */\n\tasync initialize(): Promise<void> {\n\t\tawait this.initializeResources();\n\n\t\t// Set up asset manager if present\n\t\tif (this._assetManager) {\n\t\t\tthis._assetManager.setEventBus(this._eventBus as unknown as EventBus<any>);\n\t\t\tawait this._assetManager.loadEagerAssets();\n\t\t\tthis._resourceManager.add('$assets' as keyof ResourceTypes, this._assetManager.createResource() as unknown as ResourceTypes[keyof ResourceTypes]);\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<any>,\n\t\t\t\tthis._assetManager,\n\t\t\t\tthis as unknown as ECSpresso<any, any, any, any, any>\n\t\t\t);\n\t\t\tthis._resourceManager.add('$screen' as keyof ResourceTypes, this._screenManager.createResource() as unknown as ResourceTypes[keyof ResourceTypes]);\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 ResourceTypes>(...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: string, priority: number): boolean {\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: string, phase: SystemPhase): boolean {\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: string): 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: string): 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: string): 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: string): string[] {\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: string): boolean {\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 sequence tracking\n\t\tthis._systems.splice(index, 1);\n\t\tthis._systemLastSeqs.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<ComponentTypes, any, any, EventTypes, ResourceTypes, AssetTypes, ScreenStates>): 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\tthis._rebuildPhaseSystems();\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]?.handler;\n\t\t\tif (handler) {\n\t\t\t\tthis._eventBus.subscribe(eventName, (data) => {\n\t\t\t\t\thandler(data, 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 ResourceTypes>(key: K): boolean {\n\t\treturn this._resourceManager.has(key);\n\t}\n\n\t/**\n\t\t* Get a resource if it exists, or undefined if not\n\t*/\n\tgetResource<K extends keyof ResourceTypes>(key: K): ResourceTypes[K] {\n\t\tconst resource = this._resourceManager.get(key, this);\n\n\t\tif (!resource) throw new Error(`Resource '${String(key)}' not found. Available resources: [${this.getResourceKeys().map(k => String(k)).join(', ')}]`);\n\n\t\treturn resource;\n\t}\n\n\t/**\n\t\t* Add a resource to the ECS instance\n\t*/\n\taddResource<K extends keyof ResourceTypes>(\n\t\tkey: K,\n\t\tresource:\n\t\t\t| ResourceTypes[K]\n\t\t\t| ((ecs: ECSpresso<ComponentTypes, EventTypes, ResourceTypes>) => ResourceTypes[K] | Promise<ResourceTypes[K]>)\n\t\t\t| {\n\t\t\t\tdependsOn?: readonly string[];\n\t\t\t\tfactory: (ecs: ECSpresso<ComponentTypes, EventTypes, ResourceTypes>) => ResourceTypes[K] | Promise<ResourceTypes[K]>;\n\t\t\t\tonDispose?: (resource: ResourceTypes[K], ecs?: ECSpresso<ComponentTypes, EventTypes, ResourceTypes>) => void | Promise<void>;\n\t\t\t}\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 ResourceTypes>(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 ResourceTypes>(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 ResourceTypes>(\n\t\tkey: K,\n\t\tupdater: (current: ResourceTypes[K]) => ResourceTypes[K]\n\t): this {\n\t\tconst currentResource = this.getResource(key);\n\t\tconst updatedResource = updater(currentResource);\n\t\tthis._resourceManager.add(key, updatedResource);\n\t\treturn this;\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 ResourceTypes> {\n\t\treturn this._resourceManager.getKeys() as Array<keyof ResourceTypes>;\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 ResourceTypes>(key: K): boolean {\n\t\treturn this._resourceManager.needsInitialization(key);\n\t}\n\n\t/**\n\t\t* Check if an entity has a component\n\t*/\n\thasComponent<K extends keyof ComponentTypes>(\n\t\tentityId: number,\n\t\tcomponentName: K\n\t): boolean {\n\t\tconst component = this._entityManager.getComponent(entityId, componentName);\n\t\treturn component !== null;\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 ComponentTypes]?: ComponentTypes[K] }>(\n\t\tcomponents: T & Record<Exclude<keyof T, keyof ComponentTypes>, never>\n\t): FilteredEntity<ComponentTypes, keyof T & keyof ComponentTypes, never> {\n\t\tconst entity = this._entityManager.createEntity();\n\t\tthis._entityManager.addComponents(entity, components);\n\t\treturn entity as FilteredEntity<ComponentTypes, keyof T & keyof ComponentTypes, never>;\n\t}\n\n\t/**\n\t\t* Get all entities with specific components\n\t*/\n\tgetEntitiesWithQuery<\n\t\tWithComponents extends keyof ComponentTypes,\n\t\tWithoutComponents extends keyof ComponentTypes = never\n\t>(\n\t\twithComponents: ReadonlyArray<WithComponents>,\n\t\twithoutComponents: ReadonlyArray<WithoutComponents> = [],\n\t\tchangedComponents?: ReadonlyArray<keyof ComponentTypes>,\n\t): Array<FilteredEntity<ComponentTypes, 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);\n\t}\n\n\t/**\n\t * Remove an entity (and optionally its descendants)\n\t * @param entityOrId Entity or 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(entityOrId: number | Entity<ComponentTypes>, options?: RemoveEntityOptions): boolean {\n\t\treturn this._entityManager.removeEntity(entityOrId, 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 ComponentTypes]?: ComponentTypes[K] }>(\n\t\tparentId: number,\n\t\tcomponents: T & Record<Exclude<keyof T, keyof ComponentTypes>, never>\n\t): FilteredEntity<ComponentTypes, keyof T & keyof ComponentTypes, never> {\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 to set as a child\n\t * @param parentId The entity 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 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 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\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\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\n\t * @param childId The child entity 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 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 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 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 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\n\t * @param ancestorId The potential ancestor\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\n\t * @param descendantId The potential descendant\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 bundle IDs\n\t*/\n\tget installedBundles(): string[] {\n\t\treturn Array.from(this._installedBundles);\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\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/**\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 ComponentTypes>(entityId: number, componentName: K): void {\n\t\tthis._entityManager.markChanged(entityId, componentName);\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 ComponentTypes>(\n\t\tcomponentName: K,\n\t\thandler: (value: ComponentTypes[K], entity: Entity<ComponentTypes>) => 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 ComponentTypes>(\n\t\tcomponentName: K,\n\t\thandler: (oldValue: ComponentTypes[K], entity: Entity<ComponentTypes>) => 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 ComponentTypes,\n\t\tWithoutComponents extends keyof ComponentTypes = never\n\t>(\n\t\tname: string,\n\t\tdefinition: ReactiveQueryDefinition<ComponentTypes, WithComponents, WithoutComponents>\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: string): 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 EventTypes>(\n\t\teventType: E,\n\t\tcallback: (data: EventTypes[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 EventTypes>(\n\t\teventType: E,\n\t\tcallback: (data: EventTypes[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: (ecs: ECSpresso<ComponentTypes, EventTypes, ResourceTypes>, deltaTime: 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\t/**\n\t * Get a loaded asset by key. Throws if not loaded.\n\t */\n\tgetAsset<K extends keyof AssetTypes>(key: K): AssetTypes[K] {\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.get(key);\n\t}\n\n\t/**\n\t * Get a loaded asset or undefined if not loaded\n\t */\n\tgetAssetOrUndefined<K extends keyof AssetTypes>(key: K): AssetTypes[K] | undefined {\n\t\treturn this._assetManager?.getOrUndefined(key);\n\t}\n\n\t/**\n\t * Get a handle to an asset with status information\n\t */\n\tgetAssetHandle<K extends keyof AssetTypes>(key: K): AssetHandle<AssetTypes[K]> {\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.getHandle(key);\n\t}\n\n\t/**\n\t * Check if an asset is loaded\n\t */\n\tisAssetLoaded<K extends keyof AssetTypes>(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 AssetTypes>(key: K): Promise<AssetTypes[K]> {\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.loadAsset(key);\n\t}\n\n\t/**\n\t * Load all assets in a group\n\t */\n\tasync loadAssetGroup(groupName: string): Promise<void> {\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.loadAssetGroup(groupName);\n\t}\n\n\t/**\n\t * Check if all assets in a group are loaded\n\t */\n\tisAssetGroupLoaded(groupName: string): 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: string): number {\n\t\treturn this._assetManager?.getGroupProgress(groupName) ?? 0;\n\t}\n\n\t// ==================== Screen Management ====================\n\n\t/**\n\t * Transition to a new screen, clearing the stack\n\t */\n\tasync setScreen<K extends keyof ScreenStates>(\n\t\tname: K,\n\t\tconfig: ScreenStates[K] extends ScreenDefinition<infer C, any> ? C : never\n\t): Promise<void> {\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.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 ScreenStates>(\n\t\tname: K,\n\t\tconfig: ScreenStates[K] extends ScreenDefinition<infer C, any> ? C : never\n\t): Promise<void> {\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.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\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.popScreen();\n\t}\n\n\t/**\n\t * Get the current screen name\n\t */\n\tgetCurrentScreen(): keyof ScreenStates | null {\n\t\treturn this._screenManager?.getCurrentScreen() ?? null;\n\t}\n\n\t/**\n\t * Get the current screen config (immutable)\n\t */\n\tgetScreenConfig<K extends keyof ScreenStates>(): ScreenStates[K] extends ScreenDefinition<infer C, any> ? Readonly<C> : never {\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.getConfig();\n\t}\n\n\t/**\n\t * Get the current screen config or null\n\t */\n\tgetScreenConfigOrNull<K extends keyof ScreenStates>(): (ScreenStates[K] extends ScreenDefinition<infer C, any> ? Readonly<C> : never) | null {\n\t\treturn this._screenManager?.getConfigOrNull() ?? null;\n\t}\n\n\t/**\n\t * Get the current screen state (mutable)\n\t */\n\tgetScreenState<K extends keyof ScreenStates>(): ScreenStates[K] extends ScreenDefinition<any, infer S> ? S : never {\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.getState();\n\t}\n\n\t/**\n\t * Get the current screen state or null\n\t */\n\tgetScreenStateOrNull<K extends keyof ScreenStates>(): (ScreenStates[K] extends ScreenDefinition<any, infer S> ? S : never) | null {\n\t\treturn this._screenManager?.getStateOrNull() ?? null;\n\t}\n\n\t/**\n\t * Update the current screen state\n\t */\n\tupdateScreenState<K extends keyof ScreenStates>(\n\t\tupdate: Partial<ScreenStates[K] extends ScreenDefinition<any, infer S> ? S : never> |\n\t\t\t((current: ScreenStates[K] extends ScreenDefinition<any, infer S> ? S : never) => Partial<ScreenStates[K] extends ScreenDefinition<any, infer S> ? S : never>)\n\t): void {\n\t\tif (!this._screenManager) {\n\t\t\tthrow new Error('Screen manager not configured. Use withScreens() in builder.');\n\t\t}\n\t\tthis._screenManager.updateState(update as any);\n\t}\n\n\t/**\n\t * Check if a screen is the current screen\n\t */\n\tisCurrentScreen(screenName: keyof ScreenStates): 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 ScreenStates): 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\n\t * @internal Used by ECSpressoBuilder\n\t */\n\t_setAssetManager(manager: AssetManager<AssetTypes>): void {\n\t\tthis._assetManager = manager;\n\t}\n\n\t/**\n\t * Internal method to set the screen manager\n\t * @internal Used by ECSpressoBuilder\n\t */\n\t_setScreenManager(manager: ScreenManager<ScreenStates>): void {\n\t\tthis._screenManager = manager;\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\t* Internal method to install a bundle into this ECSpresso instance.\n\t\t* Called by the ECSpressoBuilder during the build process.\n\t\t* The type safety is guaranteed by the builder's type system.\n\t*/\n\t_installBundle<\n\t\tC extends Record<string, any>,\n\t\tE extends Record<string, any>,\n\t\tR extends Record<string, any>,\n\t\tA extends Record<string, unknown> = {},\n\t\tS extends Record<string, ScreenDefinition<any, any>> = {},\n\t>(bundle: Bundle<C, E, R, A, S>): this {\n\t\t// Prevent duplicate installation of the same bundle\n\t\tif (this._installedBundles.has(bundle.id)) {\n\t\t\treturn this;\n\t\t}\n\n\t\t// Mark this bundle as installed\n\t\tthis._installedBundles.add(bundle.id);\n\n\t\t// Register systems from the bundle\n\t\t// The type compatibility is ensured by the builder's withBundle method\n\t\t// We need this cast due to TypeScript's limitations with generics\n\t\ttype BundleEcspresso = ECSpresso<C, E, R>;\n\t\tbundle.registerSystemsWithEcspresso(this as unknown as BundleEcspresso);\n\n\t\t// Register resources from the bundle\n\t\tconst resources = bundle.getResources();\n\t\tfor (const [key, value] of resources.entries()) {\n\t\t\t// Instead of casting, use the add method's flexibility\n\t\t\tthis._resourceManager.add(key as string, value);\n\t\t}\n\n\t\t// Register assets from the bundle if asset manager exists\n\t\tif (this._assetManager) {\n\t\t\tconst assets = bundle.getAssets();\n\t\t\tfor (const [key, definition] of assets.entries()) {\n\t\t\t\tthis._assetManager.register(key, definition as any);\n\t\t\t}\n\t\t}\n\n\t\t// Register screens from the bundle if screen manager exists\n\t\tif (this._screenManager) {\n\t\t\tconst screens = bundle.getScreens();\n\t\t\tfor (const [name, definition] of screens.entries()) {\n\t\t\t\tthis._screenManager.register(name, definition as any);\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t}\n}\n\n/**\n * Resource factory with optional dependencies and disposal callback\n */\ntype ResourceFactoryWithDeps<T> = {\n\tdependsOn?: readonly string[];\n\tfactory: (context?: any) => T | Promise<T>;\n\tonDispose?: (resource: T, context?: any) => void | Promise<void>;\n};\n\n/**\n\t* Builder class for ECSpresso that provides fluent type-safe bundle installation.\n\t* Handles type checking during build process to ensure type safety.\n*/\nexport class ECSpressoBuilder<\n\tC extends Record<string, any> = {},\n\tE extends Record<string, any> = {},\n\tR extends Record<string, any> = {},\n\tA extends Record<string, unknown> = {},\n\tS extends Record<string, ScreenDefinition<any, any>> = {},\n> {\n\t/** The ECSpresso instance being built*/\n\tprivate ecspresso: ECSpresso<C, E, R, A, S>;\n\t/** Asset configurator for collecting asset definitions */\n\tprivate assetConfigurator: AssetConfiguratorImpl<A> | null = null;\n\t/** Screen configurator for collecting screen definitions */\n\tprivate screenConfigurator: ScreenConfiguratorImpl<S> | null = null;\n\t/** Pending resources to add during build */\n\tprivate pendingResources: Array<{ key: string; value: unknown }> = [];\n\t/** Fixed timestep interval (null means use default 1/60) */\n\tprivate _fixedDt: number | null = null;\n\n\tconstructor() {\n\t\tthis.ecspresso = new ECSpresso<C, E, R, A, S>();\n\t}\n\n\t/**\n\t\t* Add the first bundle when starting with empty types.\n\t\t* This overload allows any bundle to be added to an empty ECSpresso instance.\n\t*/\n\twithBundle<\n\t\tBC extends Record<string, any>,\n\t\tBE extends Record<string, any>,\n\t\tBR extends Record<string, any>\n\t>(\n\t\tthis: ECSpressoBuilder<{}, {}, {}, A, S>,\n\t\tbundle: Bundle<BC, BE, BR>\n\t): ECSpressoBuilder<BC, BE, BR, A, S>;\n\n\t/**\n\t\t* Add a subsequent bundle with type checking.\n\t\t* This overload enforces bundle type compatibility.\n\t*/\n\twithBundle<\n\t\tBC extends Record<string, any>,\n\t\tBE extends Record<string, any>,\n\t\tBR extends Record<string, any>\n\t>(\n\t\tbundle: BundlesAreCompatible<C, BC, E, BE, R, BR> extends true\n\t\t\t? Bundle<BC, BE, BR>\n\t\t\t: never\n\t): ECSpressoBuilder<C & BC, E & BE, R & BR, A, S>;\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 bundle is compatible here.\n\t*/\n\twithBundle<\n\t\tBC extends Record<string, any>,\n\t\tBE extends Record<string, any>,\n\t\tBR extends Record<string, any>\n\t>(\n\t\tbundle: Bundle<BC, BE, BR>\n\t): ECSpressoBuilder<C & BC, E & BE, R & BR, A, S> {\n\t\t// Install the bundle\n\t\t// Type compatibility is guaranteed by method overloads\n\t\tthis.ecspresso._installBundle(bundle);\n\n\t\t// Return a builder with the updated type parameters\n\t\treturn this as unknown as ECSpressoBuilder<C & BC, E & BE, R & BR, A, S>;\n\t}\n\n\t/**\n\t * Add a resource during ECSpresso construction\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\t * @example\n\t * ```typescript\n\t * ECSpresso.create<Components, Events, Resources>()\n\t * .withResource('config', { debug: true })\n\t * .withResource('counter', () => 42)\n\t * .withResource('derived', {\n\t * dependsOn: ['base'],\n\t * factory: (ecs) => ecs.getResource('base') * 2,\n\t * onDispose: (value) => console.log('Disposed:', value)\n\t * })\n\t * .build();\n\t * ```\n\t */\n\twithResource<K extends string, V>(\n\t\tkey: K,\n\t\tresource: V | ((context?: any) => V | Promise<V>) | ResourceFactoryWithDeps<V>\n\t): ECSpressoBuilder<C, E, R & Record<K, V>, A, S> {\n\t\tthis.pendingResources.push({ key, value: resource });\n\t\treturn this as unknown as ECSpressoBuilder<C, E, R & Record<K, V>, A, S>;\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\t * @example\n\t * ```typescript\n\t * ECSpresso.create<Components, Events, Resources>()\n\t * .withAssets(assets => assets\n\t * .add('playerSprite', () => loadTexture('player.png'))\n\t * .addGroup('level1', {\n\t * background: () => loadTexture('level1-bg.png'),\n\t * music: () => loadAudio('level1.mp3'),\n\t * })\n\t * )\n\t * .build();\n\t * ```\n\t */\n\twithAssets<NewA extends Record<string, unknown>>(\n\t\tconfigurator: (assets: AssetConfigurator<{}>) => AssetConfigurator<NewA>\n\t): ECSpressoBuilder<C, E, R, A & NewA, S> {\n\t\tconst assetConfig = createAssetConfigurator<{}>();\n\t\tconfigurator(assetConfig);\n\t\tthis.assetConfigurator = assetConfig as unknown as AssetConfiguratorImpl<A>;\n\t\treturn this as unknown as ECSpressoBuilder<C, E, R, A & NewA, S>;\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\t * @example\n\t * ```typescript\n\t * ECSpresso.create<Components, Events, Resources>()\n\t * .withScreens(screens => screens\n\t * .add('loading', {\n\t * initialState: () => ({ progress: 0 }),\n\t * })\n\t * .add('gameplay', {\n\t * initialState: ({ level }) => ({ score: 0, level }),\n\t * requiredAssetGroups: ['level1'],\n\t * })\n\t * )\n\t * .build();\n\t * ```\n\t */\n\twithScreens<NewS extends Record<string, ScreenDefinition<any, any>>>(\n\t\tconfigurator: (screens: ScreenConfigurator<{}>) => ScreenConfigurator<NewS>\n\t): ECSpressoBuilder<C, E, R, A, S & NewS> {\n\t\tconst screenConfig = createScreenConfigurator<{}>();\n\t\tconfigurator(screenConfig);\n\t\tthis.screenConfigurator = screenConfig as unknown as ScreenConfiguratorImpl<S>;\n\t\treturn this as unknown as ECSpressoBuilder<C, E, R, A, S & NewS>;\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\t* Complete the build process and return the built ECSpresso instance\n\t*/\n\tbuild(): ECSpresso<C, E, R, A, S> {\n\t\t// Apply pending resources\n\t\tfor (const { key, value } of this.pendingResources) {\n\t\t\tthis.ecspresso.addResource(key as keyof R, value as any);\n\t\t}\n\n\t\t// Set up asset manager if configured\n\t\tif (this.assetConfigurator) {\n\t\t\tthis.ecspresso._setAssetManager(this.assetConfigurator.getManager() as unknown as AssetManager<A>);\n\t\t}\n\n\t\t// Set up screen manager if configured\n\t\tif (this.screenConfigurator) {\n\t\t\tthis.ecspresso._setScreenManager(this.screenConfigurator.getManager() as unknown as ScreenManager<S>);\n\t\t}\n\n\t\t// Set fixed timestep if configured\n\t\tif (this._fixedDt !== null) {\n\t\t\tthis.ecspresso._setFixedDt(this._fixedDt);\n\t\t}\n\n\t\treturn this.ecspresso;\n\t}\n}\n",
13
+ "import Bundle from \"./bundle\";\nimport ECSpresso from \"./ecspresso\";\nimport type { FilteredEntity, System, SystemPhase } from \"./types\";\n\n/**\n * Builder class for creating type-safe ECS Systems with proper query inference\n */\nexport class SystemBuilder<\n\tComponentTypes extends Record<string, any> = Record<string, any>,\n\tEventTypes extends Record<string, any> = Record<string, any>,\n\tResourceTypes extends Record<string, any> = Record<string, any>,\n\tQueries extends Record<string, QueryDefinition<ComponentTypes>> = {},\n> {\n\tprivate queries: Queries = {} as Queries;\n\tprivate processFunction?: ProcessFunction<ComponentTypes, EventTypes, ResourceTypes, Queries>;\n\tprivate detachFunction?: LifecycleFunction<ComponentTypes, EventTypes, ResourceTypes>;\n\tprivate initializeFunction?: LifecycleFunction<ComponentTypes, EventTypes, ResourceTypes>;\n\tprivate eventHandlers?: {\n\t\t[EventName in keyof EventTypes]?: {\n\t\t\thandler(\n\t\t\t\tdata: EventTypes[EventName],\n\t\t\t\tecs: ECSpresso<\n\t\t\t\t\tComponentTypes,\n\t\t\t\t\tEventTypes,\n\t\t\t\t\tResourceTypes\n\t\t\t\t>,\n\t\t\t): void;\n\t\t};\n\t};\n\tprivate _priority = 0; // Default priority is 0\n\tprivate _phase: SystemPhase = 'update'; // Default phase is 'update'\n\tprivate _isRegistered = false; // Track if system has been auto-registered\n\tprivate _groups: string[] = [];\n\tprivate _inScreens?: string[];\n\tprivate _excludeScreens?: string[];\n\tprivate _requiredAssets?: string[];\n\n\tconstructor(\n\t\tprivate _label: string,\n\t\tprivate _ecspresso: ECSpresso<ComponentTypes, EventTypes, ResourceTypes> | null = null,\n\t\tprivate _bundle: Bundle<ComponentTypes, EventTypes, ResourceTypes> | null = null,\n\t) {}\n\n\tget label() {\n\t\treturn this._label;\n\t}\n\n\t/**\n\t * Returns the associated bundle if one was provided in the constructor\n\t */\n\tget bundle() {\n\t\treturn this._bundle;\n\t}\n\n\t/**\n\t * Returns the associated ECSpresso instance if one was provided in the constructor\n\t */\n\tget ecspresso() {\n\t\treturn this._ecspresso;\n\t}\n\n\t/**\n\t * Auto-register this system with its ECSpresso instance if not already registered\n\t * @private\n\t */\n\tprivate _autoRegister(): void {\n\t\tif (this._isRegistered || !this._ecspresso) return;\n\t\t\n\t\tconst system = this._buildSystemObject();\n\t\tregisterSystemWithEcspresso(system, this._ecspresso);\n\t\tthis._isRegistered = true;\n\t}\n\n\t/**\n\t * Create the system object without registering it\n\t * @private\n\t */\n\tprivate _buildSystemObject(): System<ComponentTypes, any, any, EventTypes, ResourceTypes> {\n\t\treturn this._createSystemObject();\n\t}\n\n\t/**\n\t * Create a system object with all configured properties\n\t * @private\n\t */\n\tprivate _createSystemObject(): System<ComponentTypes, any, any, EventTypes, ResourceTypes> {\n\t\tconst system: System<ComponentTypes, any, any, EventTypes, ResourceTypes> = {\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\treturn system;\n\t}\n\n\t// TODO: Should this be a setter?\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(groupName: string): this {\n\t\tif (!this._groups.includes(groupName)) {\n\t\t\tthis._groups.push(groupName);\n\t\t}\n\t\treturn this;\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<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<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<string>): this {\n\t\tthis._requiredAssets = [...assets];\n\t\treturn this;\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 ComponentTypes,\n\t\tWithoutComponents extends keyof ComponentTypes = never,\n\t\tOptionalComponents extends keyof ComponentTypes = never,\n\t\tNewQueries extends Queries & Record<QueryName, QueryDefinition<ComponentTypes, WithComponents, WithoutComponents, OptionalComponents>> =\n\t\t\tQueries & Record<QueryName, QueryDefinition<ComponentTypes, 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 ComponentTypes>;\n\t\t}\n\t): this extends SystemBuilderWithEcspresso<ComponentTypes, EventTypes, ResourceTypes, Queries>\n\t\t? SystemBuilderWithEcspresso<ComponentTypes, EventTypes, ResourceTypes, NewQueries>\n\t\t: this extends SystemBuilderWithBundle<ComponentTypes, EventTypes, ResourceTypes, Queries>\n\t\t\t? SystemBuilderWithBundle<ComponentTypes, EventTypes, ResourceTypes, NewQueries>\n\t\t\t: SystemBuilder<ComponentTypes, EventTypes, ResourceTypes, NewQueries> {\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 * @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<ComponentTypes, EventTypes, ResourceTypes, Queries>\n\t): this {\n\t\tthis.processFunction = process;\n\t\treturn this;\n\t}\n\n\t/**\n\t * Register this system with its ECSpresso instance and return the ECSpresso for chaining\n\t * This enables seamless method chaining: .registerAndContinue().addSystem(...)\n\t * @returns ECSpresso instance if attached to one, otherwise throws an error\n\t */\n\tregisterAndContinue(): ECSpresso<ComponentTypes, EventTypes, ResourceTypes> {\n\t\tif (!this._ecspresso) {\n\t\t\tthrow new Error(`Cannot register system '${this._label}': SystemBuilder is not attached to an ECSpresso instance. Use Bundle.addSystem() or ECSpresso.addSystem() instead.`);\n\t\t}\n\t\t\n\t\tthis._autoRegister();\n\t\treturn this._ecspresso;\n\t}\n\n\t/**\n\t * Complete this system and return the parent container for seamless chaining\n\t * - For ECSpresso-attached builders: registers the system and returns ECSpresso\n\t * - For Bundle-attached builders: returns the Bundle\n\t * This method is typed via the specialized interfaces (SystemBuilderWithEcspresso, SystemBuilderWithBundle)\n\t */\n\tand(): ECSpresso<ComponentTypes, EventTypes, ResourceTypes> | Bundle<ComponentTypes, EventTypes, ResourceTypes> {\n\t\tif (this._ecspresso) {\n\t\t\tthis._autoRegister();\n\t\t\treturn this._ecspresso;\n\t\t}\n\n\t\tif (this._bundle) {\n\t\t\treturn this._bundle;\n\t\t}\n\n\t\tthrow new Error(`Cannot use and() on system '${this._label}': not attached to ECSpresso or Bundle.`);\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<ComponentTypes, EventTypes, ResourceTypes>\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<ComponentTypes, EventTypes, ResourceTypes>\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 EventTypes]?: {\n\t\t\t\thandler(\n\t\t\t\t\tdata: EventTypes[EventName],\n\t\t\t\t\tecs: ECSpresso<ComponentTypes, EventTypes, ResourceTypes>\n\t\t\t\t): void;\n\t\t\t};\n\t\t}\n\t): this {\n\t\tthis.eventHandlers = handlers;\n\t\treturn this;\n\t}\n\n\t/**\n\t * Build the final system object\n\t */\n\tbuild(ecspresso?: ECSpresso<ComponentTypes, EventTypes, ResourceTypes>) {\n\t\tconst system = this._createSystemObject();\n\n\t\tif (this._ecspresso) {\n\t\t\tregisterSystemWithEcspresso(system, this._ecspresso);\n\t\t}\n\n\t\tif(ecspresso) {\n\t\t\tregisterSystemWithEcspresso(system, ecspresso);\n\t\t}\n\n\t\treturn this;\n\t}\n}\n\n/**\n * Helper function to register a system with an ECSpresso instance\n * This handles attaching the system and setting up event handlers\n * @internal Used by SystemBuilder and Bundle\n */\nexport function registerSystemWithEcspresso<\n\tComponentTypes extends Record<string, any>,\n\tEventTypes extends Record<string, any>,\n\tResourceTypes extends Record<string, any>\n>(\n\tsystem: System<ComponentTypes, any, any, EventTypes, ResourceTypes>,\n\tecspresso: ECSpresso<ComponentTypes, EventTypes, ResourceTypes>\n) {\n\t// Use the new internal registration method instead of direct property access\n\tecspresso._registerSystem(system);\n}\n\n// Helper type definitions\ntype QueryDefinition<\n\tComponentTypes,\n\tWithComponents extends keyof ComponentTypes = any,\n\tWithoutComponents extends keyof ComponentTypes = any,\n\tOptionalComponents extends keyof ComponentTypes = any,\n> = {\n\twith: ReadonlyArray<WithComponents>;\n\twithout?: ReadonlyArray<WithoutComponents>;\n\tchanged?: ReadonlyArray<WithComponents>;\n\toptional?: ReadonlyArray<OptionalComponents>;\n\tparentHas?: ReadonlyArray<keyof ComponentTypes>;\n};\n\ntype QueryResults<\n\tComponentTypes,\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, any, any> ? W : never,\n\t\t\tQueries[QueryName] extends QueryDefinition<ComponentTypes, any, infer WO, any> ? 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 * Function signature for system process methods\n * @param queries Results of entity queries defined by the system\n * @param deltaTime Time elapsed since last update in seconds\n * @param ecs The ECSpresso instance providing access to all ECS functionality\n */\ntype ProcessFunction<\n\tComponentTypes extends Record<string, any>,\n\tEventTypes extends Record<string, any>,\n\tResourceTypes extends Record<string, any>,\n\tQueries extends Record<string, QueryDefinition<ComponentTypes>>,\n> = (\n\tqueries: QueryResults<ComponentTypes, Queries>,\n\tdeltaTime: number,\n\tecs: ECSpresso<\n\t\tComponentTypes,\n\t\tEventTypes,\n\t\tResourceTypes\n\t>\n) => void;\n\n/**\n * Type for system initialization functions\n * These can be asynchronous\n */\ntype LifecycleFunction<\n\tComponentTypes extends Record<string, any>,\n\tEventTypes extends Record<string, any>,\n\tResourceTypes extends Record<string, any>,\n> = (\n\tecs: ECSpresso<\n\t\tComponentTypes,\n\t\tEventTypes,\n\t\tResourceTypes\n\t>,\n) => void | Promise<void>;\n\n/**\n * Create a SystemBuilder attached to an ECSpresso instance\n * Helper function used by ECSpresso.addSystem\n */\nexport function createEcspressoSystemBuilder<\n\tComponentTypes extends Record<string, any>,\n\tEventTypes extends Record<string, any>,\n\tResourceTypes extends Record<string, any>\n>(\n\tlabel: string,\n\tecspresso: ECSpresso<ComponentTypes, EventTypes, ResourceTypes>\n): SystemBuilderWithEcspresso<ComponentTypes, EventTypes, ResourceTypes> {\n\treturn new SystemBuilder<ComponentTypes, EventTypes, ResourceTypes>(\n\t\tlabel,\n\t\tecspresso\n\t) as SystemBuilderWithEcspresso<ComponentTypes, EventTypes, ResourceTypes>;\n}\n\n/**\n * Create a SystemBuilder attached to a Bundle\n * Helper function used by Bundle.addSystem\n */\nexport function createBundleSystemBuilder<\n\tComponentTypes extends Record<string, any>,\n\tEventTypes extends Record<string, any>,\n\tResourceTypes extends Record<string, any>\n>(\n\tlabel: string,\n\tbundle: Bundle<ComponentTypes, EventTypes, ResourceTypes>\n): SystemBuilderWithBundle<ComponentTypes, EventTypes, ResourceTypes> {\n\treturn new SystemBuilder<ComponentTypes, EventTypes, ResourceTypes>(\n\t\tlabel,\n\t\tnull,\n\t\tbundle\n\t) as SystemBuilderWithBundle<ComponentTypes, EventTypes, ResourceTypes>;\n}\n\n// Type interfaces for specialized SystemBuilders\n\n/**\n * SystemBuilder with a guaranteed non-null reference to an ECSpresso instance\n */\nexport interface SystemBuilderWithEcspresso<\n\tComponentTypes extends Record<string, any>,\n\tEventTypes extends Record<string, any>,\n\tResourceTypes extends Record<string, any>,\n\tQueries extends Record<string, QueryDefinition<ComponentTypes>> = {}\n> extends SystemBuilder<ComponentTypes, EventTypes, ResourceTypes, Queries> {\n\treadonly ecspresso: ECSpresso<ComponentTypes, EventTypes, ResourceTypes>;\n\t\n\t/**\n\t * Complete this system and return ECSpresso for seamless chaining\n\t * Automatically registers the system when called\n\t */\n\tand(): ECSpresso<ComponentTypes, EventTypes, ResourceTypes>;\n}\n\n/**\n * SystemBuilder with a guaranteed non-null reference to a Bundle\n */\nexport interface SystemBuilderWithBundle<\n\tComponentTypes extends Record<string, any>,\n\tEventTypes extends Record<string, any>,\n\tResourceTypes extends Record<string, any>,\n\tQueries extends Record<string, QueryDefinition<ComponentTypes>> = {}\n> extends SystemBuilder<ComponentTypes, EventTypes, ResourceTypes, Queries> {\n\treadonly bundle: Bundle<ComponentTypes, EventTypes, ResourceTypes>;\n\n\t/**\n\t * Complete this system and return the Bundle for chaining\n\t * Enables fluent API: bundle.addSystem(...).and().addSystem(...)\n\t */\n\tand(): Bundle<ComponentTypes, EventTypes, ResourceTypes>;\n}\n",
14
+ "import EntityManager from \"./entity-manager\";\nimport EventBus from \"./event-bus\";\nimport ResourceManager from \"./resource-manager\";\nimport AssetManager, { AssetConfiguratorImpl, createAssetConfigurator } from \"./asset-manager\";\nimport ScreenManager, { ScreenConfiguratorImpl, createScreenConfigurator } 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 type Bundle from \"./bundle\";\nimport { createEcspressoSystemBuilder } from \"./system-builder\";\nimport { version } from \"../package.json\";\nimport type { BundlesAreCompatible } from \"./type-utils\";\nimport type { AssetHandle, AssetConfigurator } from \"./asset-types\";\nimport type { ScreenDefinition, ScreenConfigurator } from \"./screen-types\";\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\tComponentTypes extends Record<string, any> = {},\n\tEventTypes extends Record<string, any> = {},\n\tResourceTypes extends Record<string, any> = {},\n\tAssetTypes extends Record<string, unknown> = {},\n\tScreenStates extends Record<string, ScreenDefinition<any, any>> = {},\n> {\n\t/**\n\t\t* Default constructor\n\t*/\n\tnew(): ECSpresso<ComponentTypes, EventTypes, ResourceTypes, AssetTypes, ScreenStates>;\n}\n\nconst PHASE_ORDER: readonly SystemPhase[] = [\n\t'preUpdate', 'fixedUpdate', 'update', 'postUpdate', 'render',\n];\n\nconst EmptyQueryResults = {};\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\tComponentTypes extends Record<string, any> = {},\n\tEventTypes extends Record<string, any> = {},\n\tResourceTypes extends Record<string, any> = {},\n\tAssetTypes extends Record<string, unknown> = {},\n\tScreenStates extends Record<string, ScreenDefinition<any, any>> = {},\n> {\n\t/** Library version*/\n\tpublic static readonly VERSION = version;\n\n\t/** Access/modify stored components and entities*/\n\tprivate _entityManager: EntityManager<ComponentTypes>;\n\t/** Publish/subscribe to events*/\n\tprivate _eventBus: EventBus<EventTypes>;\n\t/** Access/modify registered resources*/\n\tprivate _resourceManager: ResourceManager<ResourceTypes>;\n\t/** Command buffer for deferred structural changes */\n\tprivate _commandBuffer: CommandBuffer<ComponentTypes, EventTypes, ResourceTypes>;\n\n\t/** Registered systems that will be updated in order*/\n\tprivate _systems: Array<System<ComponentTypes, any, any, EventTypes, ResourceTypes, AssetTypes, ScreenStates>> = [];\n\t/** Systems grouped by execution phase, each sorted by priority */\n\tprivate _phaseSystems: Record<SystemPhase, Array<System<ComponentTypes, any, any, EventTypes, ResourceTypes, AssetTypes, ScreenStates>>> = {\n\t\tpreUpdate: [], fixedUpdate: [], update: [], postUpdate: [], render: [],\n\t};\n\t/** Track installed bundles to prevent duplicates*/\n\tprivate _installedBundles: 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<AssetTypes> | null = null;\n\t/** Screen manager for state/screen transitions */\n\tprivate _screenManager: ScreenManager<ScreenStates> | null = null;\n\t/** Reactive query manager for enter/exit callbacks */\n\tprivate _reactiveQueryManager: ReactiveQueryManager<ComponentTypes>;\n\t/** Post-update hooks to be called after all systems in update() */\n\tprivate _postUpdateHooks: Array<(ecs: ECSpresso<ComponentTypes, EventTypes, ResourceTypes>, deltaTime: 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\n\t/**\n\t\t* Creates a new ECSpresso instance.\n\t*/\n\tconstructor() {\n\t\tthis._entityManager = new EntityManager<ComponentTypes>();\n\t\tthis._eventBus = new EventBus<EventTypes>();\n\t\tthis._resourceManager = new ResourceManager<ResourceTypes>();\n\t\tthis._reactiveQueryManager = new ReactiveQueryManager<ComponentTypes>(this._entityManager);\n\t\tthis._commandBuffer = new CommandBuffer<ComponentTypes, EventTypes, ResourceTypes>();\n\n\t\t// Wire up component lifecycle hooks for reactive queries\n\t\tthis._setupReactiveQueryHooks();\n\t}\n\n\t/**\n\t * Sets up component lifecycle hooks for reactive query tracking\n\t * @private\n\t */\n\tprivate _setupReactiveQueryHooks(): void {\n\t\t// Batching mechanism: during addComponents, we defer reactive query checks\n\t\t// until all components are added to avoid intermediate state triggers\n\t\tlet batchingDepth = 0;\n\t\tconst pendingChecks = new Set<number>();\n\n\t\tconst flushPendingChecks = () => {\n\t\t\tfor (const entityId of pendingChecks) {\n\t\t\t\tconst entity = this._entityManager.getEntity(entityId);\n\t\t\t\tif (entity) {\n\t\t\t\t\t// Do a full recheck of the entity against all queries\n\t\t\t\t\tthis._reactiveQueryManager.recheckEntity(entity);\n\t\t\t\t}\n\t\t\t}\n\t\t\tpendingChecks.clear();\n\t\t};\n\n\t\t// Track added components for reactive queries\n\t\tconst originalAddComponent = this._entityManager.addComponent.bind(this._entityManager);\n\t\tthis._entityManager.addComponent = <K extends keyof ComponentTypes>(\n\t\t\tentityOrId: number | Entity<ComponentTypes>,\n\t\t\tcomponentName: K,\n\t\t\tdata: ComponentTypes[K]\n\t\t) => {\n\t\t\tconst result = originalAddComponent(entityOrId, componentName, data);\n\t\t\tconst entityId = typeof entityOrId === 'number' ? entityOrId : entityOrId.id;\n\n\t\t\t// Auto-mark component as changed (always, regardless of batching)\n\t\t\tthis._entityManager.markChanged(entityId, componentName);\n\n\t\t\tif (batchingDepth > 0) {\n\t\t\t\t// During batching, just track that this entity needs checking\n\t\t\t\tpendingChecks.add(entityId);\n\t\t\t} else {\n\t\t\t\t// Not batching, check immediately\n\t\t\t\tconst entity = this._entityManager.getEntity(entityId);\n\t\t\t\tif (entity) {\n\t\t\t\t\tthis._reactiveQueryManager.onComponentAdded(entity, componentName);\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn result;\n\t\t};\n\n\t\t// Wrap addComponents to enable batching\n\t\tconst originalAddComponents = this._entityManager.addComponents.bind(this._entityManager);\n\t\tthis._entityManager.addComponents = <T extends { [K in keyof ComponentTypes]?: ComponentTypes[K] }>(\n\t\t\tentityOrId: number | Entity<ComponentTypes>,\n\t\t\tcomponents: T & Record<Exclude<keyof T, keyof ComponentTypes>, never>\n\t\t) => {\n\t\t\tbatchingDepth++;\n\t\t\tconst result = originalAddComponents(entityOrId, components);\n\t\t\tbatchingDepth--;\n\t\t\tif (batchingDepth === 0) {\n\t\t\t\tflushPendingChecks();\n\t\t\t}\n\t\t\treturn result;\n\t\t};\n\n\t\t// Track removed components for reactive queries\n\t\tconst originalRemoveComponent = this._entityManager.removeComponent.bind(this._entityManager);\n\t\tthis._entityManager.removeComponent = <K extends keyof ComponentTypes>(\n\t\t\tentityOrId: number | Entity<ComponentTypes>,\n\t\t\tcomponentName: K\n\t\t) => {\n\t\t\tconst entityId = typeof entityOrId === 'number' ? entityOrId : entityOrId.id;\n\t\t\tconst entity = this._entityManager.getEntity(entityId);\n\t\t\tconst result = originalRemoveComponent(entityOrId, componentName);\n\t\t\tif (entity) {\n\t\t\t\tthis._reactiveQueryManager.onComponentRemoved(entity, componentName);\n\t\t\t}\n\t\t\treturn result;\n\t\t};\n\n\t\t// Track hierarchy changes for parentHas reactive queries\n\t\tconst originalSetParent = this._entityManager.setParent.bind(this._entityManager);\n\t\tthis._entityManager.setParent = (childId: number, parentId: number) => {\n\t\t\tconst result = originalSetParent(childId, parentId);\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\treturn result;\n\t\t};\n\n\t\tconst originalRemoveParent = this._entityManager.removeParent.bind(this._entityManager);\n\t\tthis._entityManager.removeParent = (childId: number) => {\n\t\t\tconst result = originalRemoveParent(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\treturn result;\n\t\t};\n\n\t\t// Track entity removal for reactive queries\n\t\tconst originalRemoveEntity = this._entityManager.removeEntity.bind(this._entityManager);\n\t\tthis._entityManager.removeEntity = (entityOrId, options?) => {\n\t\t\tconst entityId = typeof entityOrId === 'number' ? entityOrId : entityOrId.id;\n\t\t\t// Notify reactive query manager about all entities being removed (including descendants)\n\t\t\tconst entity = this._entityManager.getEntity(entityId);\n\t\t\tif (entity) {\n\t\t\t\tconst cascade = options?.cascade ?? true;\n\t\t\t\tif (cascade) {\n\t\t\t\t\tconst descendants = this._entityManager.getDescendants(entityId);\n\t\t\t\t\tfor (const descId of descendants) {\n\t\t\t\t\t\tthis._reactiveQueryManager.onEntityRemoved(descId);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tthis._reactiveQueryManager.onEntityRemoved(entityId);\n\t\t\t}\n\t\t\treturn originalRemoveEntity(entityOrId, options);\n\t\t};\n\t}\n\n\t/**\n\t\t* Creates a new ECSpresso builder for type-safe bundle installation.\n\t\t* This is the preferred way to create an ECSpresso instance with bundles.\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<BaseComponents, BaseEvents, BaseResources>()\n\t *\t .withBundle(bundle1)\n\t *\t .withBundle(bundle2)\n\t *\t .build();\n\t\t* ```\n\t*/\n\tstatic create<\n\t\tC extends Record<string, any> = {},\n\t\tE extends Record<string, any> = {},\n\t\tR extends Record<string, any> = {},\n\t\tA extends Record<string, unknown> = {},\n\t\tS extends Record<string, ScreenDefinition<any, any>> = {},\n\t>(): ECSpressoBuilder<C, E, R, A, S> {\n\t\treturn new ECSpressoBuilder<C, E, R, A, S>();\n\t}\n\n\t/**\n\t\t* Adds a system directly to this ECSpresso instance\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) {\n\t\treturn createEcspressoSystemBuilder<\n\t\t\tComponentTypes,\n\t\t\tEventTypes,\n\t\t\tResourceTypes\n\t\t>(label, this);\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\tconst currentScreen = (this._screenManager?.getCurrentScreen() ?? null) as string | null;\n\n\t\t// 1. preUpdate phase\n\t\tthis._executePhase(this._phaseSystems.preUpdate, deltaTime, currentScreen);\n\t\tthis._commandBuffer.playback(this);\n\n\t\t// 2. fixedUpdate phase — accumulate time and step N times\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\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._executePhase(this._phaseSystems.update, deltaTime, currentScreen);\n\t\tthis._commandBuffer.playback(this);\n\n\t\t// 4. postUpdate phase\n\t\tthis._executePhase(this._phaseSystems.postUpdate, deltaTime, currentScreen);\n\t\tthis._commandBuffer.playback(this);\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(this as unknown as ECSpresso<ComponentTypes, EventTypes, ResourceTypes>, deltaTime);\n\t\t}\n\n\t\t// 6. render phase\n\t\tthis._executePhase(this._phaseSystems.render, deltaTime, currentScreen);\n\t\tthis._commandBuffer.playback(this);\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<ComponentTypes, any, any, EventTypes, ResourceTypes, AssetTypes, ScreenStates>>,\n\t\tdeltaTime: number,\n\t\tcurrentScreen: string | null\n\t): void {\n\t\tfor (const system of systems) {\n\t\t\tif (!system.process) 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 as string)) {\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 as string)) {\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 as keyof AssetTypes)) {\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// Prepare query results for each defined query in the system\n\t\t\tconst queryResults: Record<string, any> = {};\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\tqueryResults[queryName] = this._entityManager.getEntitiesWithQuery(\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(queryResults[queryName].length) {\n\t\t\t\t\t\t\thasResults = true; // At least one query has results\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 (hasResults) {\n\t\t\t\tsystem.process(queryResults, deltaTime, this);\n\t\t\t} else if(!hasQueries) {\n\t\t\t\tsystem.process(EmptyQueryResults, deltaTime, this);\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 * 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 * @param resourceKeys Optional array of specific resource keys to initialize\n\t * @returns Promise that resolves when everything is initialized\n\t */\n\tasync initialize(): Promise<void> {\n\t\tawait this.initializeResources();\n\n\t\t// Set up asset manager if present\n\t\tif (this._assetManager) {\n\t\t\tthis._assetManager.setEventBus(this._eventBus as unknown as EventBus<any>);\n\t\t\tawait this._assetManager.loadEagerAssets();\n\t\t\tthis._resourceManager.add('$assets' as keyof ResourceTypes, this._assetManager.createResource() as unknown as ResourceTypes[keyof ResourceTypes]);\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<any>,\n\t\t\t\tthis._assetManager,\n\t\t\t\tthis as unknown as ECSpresso<any, any, any, any, any>\n\t\t\t);\n\t\t\tthis._resourceManager.add('$screen' as keyof ResourceTypes, this._screenManager.createResource() as unknown as ResourceTypes[keyof ResourceTypes]);\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 ResourceTypes>(...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: string, priority: number): boolean {\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: string, phase: SystemPhase): boolean {\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: string): 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: string): 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: string): 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: string): string[] {\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: string): boolean {\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 sequence tracking\n\t\tthis._systems.splice(index, 1);\n\t\tthis._systemLastSeqs.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<ComponentTypes, any, any, EventTypes, ResourceTypes, AssetTypes, ScreenStates>): 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\tthis._rebuildPhaseSystems();\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]?.handler;\n\t\t\tif (handler) {\n\t\t\t\tthis._eventBus.subscribe(eventName, (data) => {\n\t\t\t\t\thandler(data, 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 ResourceTypes>(key: K): boolean {\n\t\treturn this._resourceManager.has(key);\n\t}\n\n\t/**\n\t\t* Get a resource if it exists, or undefined if not\n\t*/\n\tgetResource<K extends keyof ResourceTypes>(key: K): ResourceTypes[K] {\n\t\tconst resource = this._resourceManager.get(key, this);\n\n\t\tif (!resource) throw new Error(`Resource '${String(key)}' not found. Available resources: [${this.getResourceKeys().map(k => String(k)).join(', ')}]`);\n\n\t\treturn resource;\n\t}\n\n\t/**\n\t\t* Add a resource to the ECS instance\n\t*/\n\taddResource<K extends keyof ResourceTypes>(\n\t\tkey: K,\n\t\tresource:\n\t\t\t| ResourceTypes[K]\n\t\t\t| ((ecs: ECSpresso<ComponentTypes, EventTypes, ResourceTypes>) => ResourceTypes[K] | Promise<ResourceTypes[K]>)\n\t\t\t| {\n\t\t\t\tdependsOn?: readonly string[];\n\t\t\t\tfactory: (ecs: ECSpresso<ComponentTypes, EventTypes, ResourceTypes>) => ResourceTypes[K] | Promise<ResourceTypes[K]>;\n\t\t\t\tonDispose?: (resource: ResourceTypes[K], ecs?: ECSpresso<ComponentTypes, EventTypes, ResourceTypes>) => void | Promise<void>;\n\t\t\t}\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 ResourceTypes>(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 ResourceTypes>(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 ResourceTypes>(\n\t\tkey: K,\n\t\tupdater: (current: ResourceTypes[K]) => ResourceTypes[K]\n\t): this {\n\t\tconst currentResource = this.getResource(key);\n\t\tconst updatedResource = updater(currentResource);\n\t\tthis._resourceManager.add(key, updatedResource);\n\t\treturn this;\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 ResourceTypes> {\n\t\treturn this._resourceManager.getKeys() as Array<keyof ResourceTypes>;\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 ResourceTypes>(key: K): boolean {\n\t\treturn this._resourceManager.needsInitialization(key);\n\t}\n\n\t/**\n\t\t* Check if an entity has a component\n\t*/\n\thasComponent<K extends keyof ComponentTypes>(\n\t\tentityId: number,\n\t\tcomponentName: K\n\t): boolean {\n\t\tconst component = this._entityManager.getComponent(entityId, componentName);\n\t\treturn component !== null;\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 ComponentTypes]?: ComponentTypes[K] }>(\n\t\tcomponents: T & Record<Exclude<keyof T, keyof ComponentTypes>, never>\n\t): FilteredEntity<ComponentTypes, keyof T & keyof ComponentTypes, never> {\n\t\tconst entity = this._entityManager.createEntity();\n\t\tthis._entityManager.addComponents(entity, components);\n\t\treturn entity as FilteredEntity<ComponentTypes, keyof T & keyof ComponentTypes, never>;\n\t}\n\n\t/**\n\t\t* Get all entities with specific components\n\t*/\n\tgetEntitiesWithQuery<\n\t\tWithComponents extends keyof ComponentTypes,\n\t\tWithoutComponents extends keyof ComponentTypes = never\n\t>(\n\t\twithComponents: ReadonlyArray<WithComponents>,\n\t\twithoutComponents: ReadonlyArray<WithoutComponents> = [],\n\t\tchangedComponents?: ReadonlyArray<keyof ComponentTypes>,\n\t\tparentHas?: ReadonlyArray<keyof ComponentTypes>,\n\t): Array<FilteredEntity<ComponentTypes, 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 ComponentTypes,\n\t\tWithoutComponents extends keyof ComponentTypes = never\n\t>(\n\t\twithComponents: ReadonlyArray<WithComponents>,\n\t\twithoutComponents: ReadonlyArray<WithoutComponents> = [] as unknown as ReadonlyArray<WithoutComponents>,\n\t): FilteredEntity<ComponentTypes, 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\treturn results[0]!;\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 ComponentTypes,\n\t\tWithoutComponents extends keyof ComponentTypes = never\n\t>(\n\t\twithComponents: ReadonlyArray<WithComponents>,\n\t\twithoutComponents: ReadonlyArray<WithoutComponents> = [] as unknown as ReadonlyArray<WithoutComponents>,\n\t): FilteredEntity<ComponentTypes, 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 entityOrId Entity or 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(entityOrId: number | Entity<ComponentTypes>, options?: RemoveEntityOptions): boolean {\n\t\treturn this._entityManager.removeEntity(entityOrId, 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 ComponentTypes]?: ComponentTypes[K] }>(\n\t\tparentId: number,\n\t\tcomponents: T & Record<Exclude<keyof T, keyof ComponentTypes>, never>\n\t): FilteredEntity<ComponentTypes, keyof T & keyof ComponentTypes, never> {\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 to set as a child\n\t * @param parentId The entity 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 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 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\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\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\n\t * @param childId The child entity 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 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 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 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 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\n\t * @param ancestorId The potential ancestor\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\n\t * @param descendantId The potential descendant\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 bundle IDs\n\t*/\n\tget installedBundles(): string[] {\n\t\treturn Array.from(this._installedBundles);\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\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/**\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 ComponentTypes>(entityId: number, componentName: K): void {\n\t\tthis._entityManager.markChanged(entityId, componentName);\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 ComponentTypes>(\n\t\tcomponentName: K,\n\t\thandler: (value: ComponentTypes[K], entity: Entity<ComponentTypes>) => 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 ComponentTypes>(\n\t\tcomponentName: K,\n\t\thandler: (oldValue: ComponentTypes[K], entity: Entity<ComponentTypes>) => 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 ComponentTypes,\n\t\tWithoutComponents extends keyof ComponentTypes = never,\n\t\tOptionalComponents extends keyof ComponentTypes = never,\n\t>(\n\t\tname: string,\n\t\tdefinition: ReactiveQueryDefinition<ComponentTypes, 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: string): 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 EventTypes>(\n\t\teventType: E,\n\t\tcallback: (data: EventTypes[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 EventTypes>(\n\t\teventType: E,\n\t\tcallback: (data: EventTypes[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: (ecs: ECSpresso<ComponentTypes, EventTypes, ResourceTypes>, deltaTime: 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\t/**\n\t * Get a loaded asset by key. Throws if not loaded.\n\t */\n\tgetAsset<K extends keyof AssetTypes>(key: K): AssetTypes[K] {\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.get(key);\n\t}\n\n\t/**\n\t * Get a loaded asset or undefined if not loaded\n\t */\n\tgetAssetOrUndefined<K extends keyof AssetTypes>(key: K): AssetTypes[K] | undefined {\n\t\treturn this._assetManager?.getOrUndefined(key);\n\t}\n\n\t/**\n\t * Get a handle to an asset with status information\n\t */\n\tgetAssetHandle<K extends keyof AssetTypes>(key: K): AssetHandle<AssetTypes[K]> {\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.getHandle(key);\n\t}\n\n\t/**\n\t * Check if an asset is loaded\n\t */\n\tisAssetLoaded<K extends keyof AssetTypes>(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 AssetTypes>(key: K): Promise<AssetTypes[K]> {\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.loadAsset(key);\n\t}\n\n\t/**\n\t * Load all assets in a group\n\t */\n\tasync loadAssetGroup(groupName: string): Promise<void> {\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.loadAssetGroup(groupName);\n\t}\n\n\t/**\n\t * Check if all assets in a group are loaded\n\t */\n\tisAssetGroupLoaded(groupName: string): 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: string): number {\n\t\treturn this._assetManager?.getGroupProgress(groupName) ?? 0;\n\t}\n\n\t// ==================== Screen Management ====================\n\n\t/**\n\t * Transition to a new screen, clearing the stack\n\t */\n\tasync setScreen<K extends keyof ScreenStates>(\n\t\tname: K,\n\t\tconfig: ScreenStates[K] extends ScreenDefinition<infer C, any> ? C : never\n\t): Promise<void> {\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.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 ScreenStates>(\n\t\tname: K,\n\t\tconfig: ScreenStates[K] extends ScreenDefinition<infer C, any> ? C : never\n\t): Promise<void> {\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.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\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.popScreen();\n\t}\n\n\t/**\n\t * Get the current screen name\n\t */\n\tgetCurrentScreen(): keyof ScreenStates | null {\n\t\treturn this._screenManager?.getCurrentScreen() ?? null;\n\t}\n\n\t/**\n\t * Get the current screen config (immutable)\n\t */\n\tgetScreenConfig<K extends keyof ScreenStates>(): ScreenStates[K] extends ScreenDefinition<infer C, any> ? Readonly<C> : never {\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.getConfig();\n\t}\n\n\t/**\n\t * Get the current screen config or null\n\t */\n\tgetScreenConfigOrNull<K extends keyof ScreenStates>(): (ScreenStates[K] extends ScreenDefinition<infer C, any> ? Readonly<C> : never) | null {\n\t\treturn this._screenManager?.getConfigOrNull() ?? null;\n\t}\n\n\t/**\n\t * Get the current screen state (mutable)\n\t */\n\tgetScreenState<K extends keyof ScreenStates>(): ScreenStates[K] extends ScreenDefinition<any, infer S> ? S : never {\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.getState();\n\t}\n\n\t/**\n\t * Get the current screen state or null\n\t */\n\tgetScreenStateOrNull<K extends keyof ScreenStates>(): (ScreenStates[K] extends ScreenDefinition<any, infer S> ? S : never) | null {\n\t\treturn this._screenManager?.getStateOrNull() ?? null;\n\t}\n\n\t/**\n\t * Update the current screen state\n\t */\n\tupdateScreenState<K extends keyof ScreenStates>(\n\t\tupdate: Partial<ScreenStates[K] extends ScreenDefinition<any, infer S> ? S : never> |\n\t\t\t((current: ScreenStates[K] extends ScreenDefinition<any, infer S> ? S : never) => Partial<ScreenStates[K] extends ScreenDefinition<any, infer S> ? S : never>)\n\t): void {\n\t\tif (!this._screenManager) {\n\t\t\tthrow new Error('Screen manager not configured. Use withScreens() in builder.');\n\t\t}\n\t\tthis._screenManager.updateState(update as any);\n\t}\n\n\t/**\n\t * Check if a screen is the current screen\n\t */\n\tisCurrentScreen(screenName: keyof ScreenStates): 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 ScreenStates): 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\n\t * @internal Used by ECSpressoBuilder\n\t */\n\t_setAssetManager(manager: AssetManager<AssetTypes>): void {\n\t\tthis._assetManager = manager;\n\t}\n\n\t/**\n\t * Internal method to set the screen manager\n\t * @internal Used by ECSpressoBuilder\n\t */\n\t_setScreenManager(manager: ScreenManager<ScreenStates>): void {\n\t\tthis._screenManager = manager;\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\t* Internal method to install a bundle into this ECSpresso instance.\n\t\t* Called by the ECSpressoBuilder during the build process.\n\t\t* The type safety is guaranteed by the builder's type system.\n\t*/\n\t_installBundle<\n\t\tC extends Record<string, any>,\n\t\tE extends Record<string, any>,\n\t\tR extends Record<string, any>,\n\t\tA extends Record<string, unknown> = {},\n\t\tS extends Record<string, ScreenDefinition<any, any>> = {},\n\t>(bundle: Bundle<C, E, R, A, S>): this {\n\t\t// Prevent duplicate installation of the same bundle\n\t\tif (this._installedBundles.has(bundle.id)) {\n\t\t\treturn this;\n\t\t}\n\n\t\t// Mark this bundle as installed\n\t\tthis._installedBundles.add(bundle.id);\n\n\t\t// Register systems from the bundle\n\t\t// The type compatibility is ensured by the builder's withBundle method\n\t\t// We need this cast due to TypeScript's limitations with generics\n\t\ttype BundleEcspresso = ECSpresso<C, E, R>;\n\t\tbundle.registerSystemsWithEcspresso(this as unknown as BundleEcspresso);\n\n\t\t// Register resources from the bundle\n\t\tconst resources = bundle.getResources();\n\t\tfor (const [key, value] of resources.entries()) {\n\t\t\t// Instead of casting, use the add method's flexibility\n\t\t\tthis._resourceManager.add(key as string, value);\n\t\t}\n\n\t\t// Register assets from the bundle if asset manager exists\n\t\tif (this._assetManager) {\n\t\t\tconst assets = bundle.getAssets();\n\t\t\tfor (const [key, definition] of assets.entries()) {\n\t\t\t\tthis._assetManager.register(key, definition as any);\n\t\t\t}\n\t\t}\n\n\t\t// Register screens from the bundle if screen manager exists\n\t\tif (this._screenManager) {\n\t\t\tconst screens = bundle.getScreens();\n\t\t\tfor (const [name, definition] of screens.entries()) {\n\t\t\t\tthis._screenManager.register(name, definition as any);\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t}\n}\n\n/**\n * Resource factory with optional dependencies and disposal callback\n */\ntype ResourceFactoryWithDeps<T> = {\n\tdependsOn?: readonly string[];\n\tfactory: (context?: any) => T | Promise<T>;\n\tonDispose?: (resource: T, context?: any) => void | Promise<void>;\n};\n\n/**\n\t* Builder class for ECSpresso that provides fluent type-safe bundle installation.\n\t* Handles type checking during build process to ensure type safety.\n*/\nexport class ECSpressoBuilder<\n\tC extends Record<string, any> = {},\n\tE extends Record<string, any> = {},\n\tR extends Record<string, any> = {},\n\tA extends Record<string, unknown> = {},\n\tS extends Record<string, ScreenDefinition<any, any>> = {},\n> {\n\t/** The ECSpresso instance being built*/\n\tprivate ecspresso: ECSpresso<C, E, R, A, S>;\n\t/** Asset configurator for collecting asset definitions */\n\tprivate assetConfigurator: AssetConfiguratorImpl<A> | null = null;\n\t/** Screen configurator for collecting screen definitions */\n\tprivate screenConfigurator: ScreenConfiguratorImpl<S> | null = null;\n\t/** Pending resources to add during build */\n\tprivate pendingResources: Array<{ key: string; value: unknown }> = [];\n\t/** Fixed timestep interval (null means use default 1/60) */\n\tprivate _fixedDt: number | null = null;\n\n\tconstructor() {\n\t\tthis.ecspresso = new ECSpresso<C, E, R, A, S>();\n\t}\n\n\t/**\n\t\t* Add the first bundle when starting with empty types.\n\t\t* This overload allows any bundle to be added to an empty ECSpresso instance.\n\t*/\n\twithBundle<\n\t\tBC extends Record<string, any>,\n\t\tBE extends Record<string, any>,\n\t\tBR extends Record<string, any>\n\t>(\n\t\tthis: ECSpressoBuilder<{}, {}, {}, A, S>,\n\t\tbundle: Bundle<BC, BE, BR>\n\t): ECSpressoBuilder<BC, BE, BR, A, S>;\n\n\t/**\n\t\t* Add a subsequent bundle with type checking.\n\t\t* This overload enforces bundle type compatibility.\n\t*/\n\twithBundle<\n\t\tBC extends Record<string, any>,\n\t\tBE extends Record<string, any>,\n\t\tBR extends Record<string, any>\n\t>(\n\t\tbundle: BundlesAreCompatible<C, BC, E, BE, R, BR> extends true\n\t\t\t? Bundle<BC, BE, BR>\n\t\t\t: never\n\t): ECSpressoBuilder<C & BC, E & BE, R & BR, A, S>;\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 bundle is compatible here.\n\t*/\n\twithBundle<\n\t\tBC extends Record<string, any>,\n\t\tBE extends Record<string, any>,\n\t\tBR extends Record<string, any>\n\t>(\n\t\tbundle: Bundle<BC, BE, BR>\n\t): ECSpressoBuilder<C & BC, E & BE, R & BR, A, S> {\n\t\t// Install the bundle\n\t\t// Type compatibility is guaranteed by method overloads\n\t\tthis.ecspresso._installBundle(bundle);\n\n\t\t// Return a builder with the updated type parameters\n\t\treturn this as unknown as ECSpressoBuilder<C & BC, E & BE, R & BR, A, S>;\n\t}\n\n\t/**\n\t * Add a resource during ECSpresso construction\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\t * @example\n\t * ```typescript\n\t * ECSpresso.create<Components, Events, Resources>()\n\t * .withResource('config', { debug: true })\n\t * .withResource('counter', () => 42)\n\t * .withResource('derived', {\n\t * dependsOn: ['base'],\n\t * factory: (ecs) => ecs.getResource('base') * 2,\n\t * onDispose: (value) => console.log('Disposed:', value)\n\t * })\n\t * .build();\n\t * ```\n\t */\n\twithResource<K extends string, V>(\n\t\tkey: K,\n\t\tresource: V | ((context?: any) => V | Promise<V>) | ResourceFactoryWithDeps<V>\n\t): ECSpressoBuilder<C, E, R & Record<K, V>, A, S> {\n\t\tthis.pendingResources.push({ key, value: resource });\n\t\treturn this as unknown as ECSpressoBuilder<C, E, R & Record<K, V>, A, S>;\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\t * @example\n\t * ```typescript\n\t * ECSpresso.create<Components, Events, Resources>()\n\t * .withAssets(assets => assets\n\t * .add('playerSprite', () => loadTexture('player.png'))\n\t * .addGroup('level1', {\n\t * background: () => loadTexture('level1-bg.png'),\n\t * music: () => loadAudio('level1.mp3'),\n\t * })\n\t * )\n\t * .build();\n\t * ```\n\t */\n\twithAssets<NewA extends Record<string, unknown>>(\n\t\tconfigurator: (assets: AssetConfigurator<{}>) => AssetConfigurator<NewA>\n\t): ECSpressoBuilder<C, E, R, A & NewA, S> {\n\t\tconst assetConfig = createAssetConfigurator<{}>();\n\t\tconfigurator(assetConfig);\n\t\tthis.assetConfigurator = assetConfig as unknown as AssetConfiguratorImpl<A>;\n\t\treturn this as unknown as ECSpressoBuilder<C, E, R, A & NewA, S>;\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\t * @example\n\t * ```typescript\n\t * ECSpresso.create<Components, Events, Resources>()\n\t * .withScreens(screens => screens\n\t * .add('loading', {\n\t * initialState: () => ({ progress: 0 }),\n\t * })\n\t * .add('gameplay', {\n\t * initialState: ({ level }) => ({ score: 0, level }),\n\t * requiredAssetGroups: ['level1'],\n\t * })\n\t * )\n\t * .build();\n\t * ```\n\t */\n\twithScreens<NewS extends Record<string, ScreenDefinition<any, any>>>(\n\t\tconfigurator: (screens: ScreenConfigurator<{}>) => ScreenConfigurator<NewS>\n\t): ECSpressoBuilder<C, E, R, A, S & NewS> {\n\t\tconst screenConfig = createScreenConfigurator<{}>();\n\t\tconfigurator(screenConfig);\n\t\tthis.screenConfigurator = screenConfig as unknown as ScreenConfiguratorImpl<S>;\n\t\treturn this as unknown as ECSpressoBuilder<C, E, R, A, S & NewS>;\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\t* Complete the build process and return the built ECSpresso instance\n\t*/\n\tbuild(): ECSpresso<C, E, R, A, S> {\n\t\t// Apply pending resources\n\t\tfor (const { key, value } of this.pendingResources) {\n\t\t\tthis.ecspresso.addResource(key as keyof R, value as any);\n\t\t}\n\n\t\t// Set up asset manager if configured\n\t\tif (this.assetConfigurator) {\n\t\t\tthis.ecspresso._setAssetManager(this.assetConfigurator.getManager() as unknown as AssetManager<A>);\n\t\t}\n\n\t\t// Set up screen manager if configured\n\t\tif (this.screenConfigurator) {\n\t\t\tthis.ecspresso._setScreenManager(this.screenConfigurator.getManager() as unknown as ScreenManager<S>);\n\t\t}\n\n\t\t// Set fixed timestep if configured\n\t\tif (this._fixedDt !== null) {\n\t\t\tthis.ecspresso._setFixedDt(this._fixedDt);\n\t\t}\n\n\t\treturn this.ecspresso;\n\t}\n}\n",
15
15
  "import { createBundleSystemBuilder, SystemBuilderWithBundle } from './system-builder';\nimport type ECSpresso from './ecspresso';\nimport type { AssetDefinition } from './asset-types';\nimport type { ScreenDefinition } from './screen-types';\nimport type { BundlesAreCompatible } from './type-utils';\n\n/**\n * Generates a unique ID for a bundle\n */\nfunction generateBundleId(): string {\n\treturn `bundle_${Date.now().toString(36)}_${Math.random().toString(36).substring(2, 9)}`;\n}\n\n/**\n * Bundle class that encapsulates a set of components, resources, events, and systems\n * that can be merged into a ECSpresso instance\n */\nexport default class Bundle<\n\tComponentTypes extends Record<string, any> = {},\n\tEventTypes extends Record<string, any> = {},\n\tResourceTypes extends Record<string, any> = {},\n\tAssetTypes extends Record<string, unknown> = {},\n\tScreenStates extends Record<string, ScreenDefinition<any, any>> = {},\n> {\n\tprivate _systems: SystemBuilderWithBundle<ComponentTypes, EventTypes, ResourceTypes, any>[] = [];\n\tprivate _resources: Map<keyof ResourceTypes, ResourceTypes[keyof ResourceTypes]> = new Map();\n\tprivate _assets: Map<string, AssetDefinition<unknown>> = new Map();\n\tprivate _assetGroups: Map<string, Map<string, () => Promise<unknown>>> = new Map();\n\tprivate _screens: Map<string, ScreenDefinition<any, any>> = new Map();\n\tprivate _id: string;\n\n\tconstructor(id?: string) {\n\t\tthis._id = id || generateBundleId();\n\t}\n\n\t/**\n\t * Get the unique ID of this bundle\n\t */\n\tget id(): string {\n\t\treturn this._id;\n\t}\n\n\t/**\n\t * Set the ID of this bundle\n\t * @internal Used by combineBundles\n\t */\n\tset id(value: string) {\n\t\tthis._id = value;\n\t}\n\n\t/**\n\t * Add a system to this bundle, by label (creating a new builder) or by reusing an existing one\n\t */\n\taddSystem<Q extends Record<string, any>>(builder: SystemBuilderWithBundle<ComponentTypes, EventTypes, ResourceTypes, Q>): SystemBuilderWithBundle<ComponentTypes, EventTypes, ResourceTypes, Q>;\n\taddSystem(label: string): SystemBuilderWithBundle<ComponentTypes, EventTypes, ResourceTypes, {}>;\n\taddSystem(builderOrLabel: string | SystemBuilderWithBundle<ComponentTypes, EventTypes, ResourceTypes, any>) {\n\t\tif (typeof builderOrLabel === 'string') {\n\t\t\tconst system = createBundleSystemBuilder<ComponentTypes, EventTypes, ResourceTypes>(builderOrLabel, this);\n\t\t\tthis._systems.push(system);\n\t\t\treturn system;\n\t\t} else {\n\t\t\tthis._systems.push(builderOrLabel);\n\t\t\treturn builderOrLabel;\n\t\t}\n\t}\n\n\t/**\n\t * Add a resource to this bundle\n\t * @param label The resource key\n\t * @param resource The resource value, a factory function, or a factory with dependencies\n\t */\n\taddResource<K extends keyof ResourceTypes>(\n\t\tlabel: K,\n\t\tresource:\n\t\t\t| ResourceTypes[K]\n\t\t\t| ((ecs: ECSpresso<ComponentTypes, EventTypes, ResourceTypes>) => ResourceTypes[K] | Promise<ResourceTypes[K]>)\n\t\t\t| { dependsOn: readonly string[]; factory: (ecs: ECSpresso<ComponentTypes, EventTypes, ResourceTypes>) => ResourceTypes[K] | Promise<ResourceTypes[K]> }\n\t) {\n\t\t// We need this cast because TypeScript doesn't recognize that a value of type\n\t\t// ResourceTypes[K] | (() => ResourceTypes[K] | Promise<ResourceTypes[K]>) | { dependsOn, factory }\n\t\t// can be properly assigned to Map<keyof ResourceTypes, ResourceTypes[keyof ResourceTypes]>\n\t\tthis._resources.set(label, resource as unknown as ResourceTypes[K]);\n\t\treturn this;\n\t}\n\n\t/**\n\t * Add an asset to this bundle\n\t * @param key The asset key\n\t * @param loader Function that loads and returns the asset\n\t * @param options Optional asset configuration\n\t */\n\taddAsset<K extends string, T>(\n\t\tkey: K,\n\t\tloader: () => Promise<T>,\n\t\toptions?: { eager?: boolean; group?: string }\n\t): Bundle<ComponentTypes, EventTypes, ResourceTypes, AssetTypes & Record<K, T>, ScreenStates> {\n\t\tthis._assets.set(key, {\n\t\t\tloader,\n\t\t\teager: options?.eager ?? true,\n\t\t\tgroup: options?.group,\n\t\t});\n\t\treturn this as unknown as Bundle<ComponentTypes, EventTypes, ResourceTypes, AssetTypes & Record<K, T>, ScreenStates>;\n\t}\n\n\t/**\n\t * Add a group of assets to this bundle\n\t * @param groupName The group name\n\t * @param assets Object mapping asset keys to loader functions\n\t */\n\taddAssetGroup<G extends string, T extends Record<string, () => Promise<unknown>>>(\n\t\tgroupName: G,\n\t\tassets: T\n\t): Bundle<ComponentTypes, EventTypes, ResourceTypes, AssetTypes & { [K in keyof T]: Awaited<ReturnType<T[K]>> }, ScreenStates> {\n\t\tconst groupAssets = new Map<string, () => Promise<unknown>>();\n\t\tfor (const [key, loader] of Object.entries(assets)) {\n\t\t\tgroupAssets.set(key, loader as () => Promise<unknown>);\n\t\t\tthis._assets.set(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\tthis._assetGroups.set(groupName, groupAssets);\n\t\treturn this as unknown as Bundle<ComponentTypes, EventTypes, ResourceTypes, AssetTypes & { [K in keyof T]: Awaited<ReturnType<T[K]>> }, ScreenStates>;\n\t}\n\n\t/**\n\t * Add a screen to this bundle\n\t * @param name The screen name\n\t * @param definition The screen definition\n\t */\n\taddScreen<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): Bundle<ComponentTypes, EventTypes, ResourceTypes, AssetTypes, ScreenStates & Record<K, ScreenDefinition<Config, State>>> {\n\t\tthis._screens.set(name, definition);\n\t\treturn this as unknown as Bundle<ComponentTypes, EventTypes, ResourceTypes, AssetTypes, ScreenStates & Record<K, ScreenDefinition<Config, State>>>;\n\t}\n\n\t/**\n\t * Get all asset definitions in this bundle\n\t */\n\tgetAssets(): Map<string, AssetDefinition<unknown>> {\n\t\treturn new Map(this._assets);\n\t}\n\n\t/**\n\t * Get all screen definitions in this bundle\n\t */\n\tgetScreens(): Map<string, ScreenDefinition<any, any>> {\n\t\treturn new Map(this._screens);\n\t}\n\n\t/**\n\t * Internal method to set a resource\n\t * @internal Used by mergeBundles\n\t */\n\t_setResource(key: string, value: unknown): void {\n\t\tthis._resources.set(key as keyof ResourceTypes, value as ResourceTypes[keyof ResourceTypes]);\n\t}\n\n\t/**\n\t * Internal method to set an asset definition\n\t * @internal Used by mergeBundles\n\t */\n\t_setAsset(key: string, definition: AssetDefinition<unknown>): void {\n\t\tthis._assets.set(key, definition);\n\t}\n\n\t/**\n\t * Internal method to set a screen definition\n\t * @internal Used by mergeBundles\n\t */\n\t_setScreen(name: string, definition: ScreenDefinition<any, any>): void {\n\t\tthis._screens.set(name, definition);\n\t}\n\n\t/**\n\t * Get all systems defined in this bundle\n\t * Returns built System objects instead of SystemBuilders\n\t */\n\tgetSystems() {\n\t\treturn this._systems.map(system => system.build());\n\t}\n\n\t/**\n\t * Register all systems in this bundle with an ECSpresso instance\n\t * @internal Used by ECSpresso when adding a bundle\n\t */\n\tregisterSystemsWithEcspresso(ecspresso: ECSpresso<ComponentTypes, EventTypes, ResourceTypes>) {\n\t\tfor (const systemBuilder of this._systems) {\n\t\t\tsystemBuilder.build(ecspresso);\n\t\t}\n\t}\n\n\t/**\n\t * Get all resources defined in this bundle\n\t */\n\tgetResources(): Map<keyof ResourceTypes, ResourceTypes[keyof ResourceTypes]> {\n\t\treturn new Map(this._resources);\n\t}\n\n\t/**\n\t * Get a specific resource by key\n\t * @param key The resource key\n\t * @returns The resource value or undefined if not found\n\t */\n\tgetResource<K extends keyof ResourceTypes>(key: K): ResourceTypes[K] {\n\t\treturn this._resources.get(key) as ResourceTypes[K];\n\t}\n\n\t/**\n\t * Get all system builders in this bundle\n\t */\n\tgetSystemBuilders(): SystemBuilderWithBundle<ComponentTypes, EventTypes, ResourceTypes, any>[] {\n\t\treturn [...this._systems];\n\t}\n\n\t/**\n\t * Check if this bundle has a specific resource\n\t * @param key The resource key to check\n\t * @returns True if the resource exists\n\t */\n\thasResource<K extends keyof ResourceTypes>(key: K): boolean {\n\t\treturn this._resources.has(key);\n\t}\n}\n\n/**\n * Function that merges multiple bundles into a single bundle\n */\nexport function mergeBundles<\n\tC1 extends Record<string, any>,\n\tE1 extends Record<string, any>,\n\tR1 extends Record<string, any>,\n\tA1 extends Record<string, unknown>,\n\tS1 extends Record<string, ScreenDefinition<any, any>>,\n\tC2 extends Record<string, any>,\n\tE2 extends Record<string, any>,\n\tR2 extends Record<string, any>,\n\tA2 extends Record<string, unknown>,\n\tS2 extends Record<string, ScreenDefinition<any, any>>,\n>(\n\tid: string,\n\tbundle1: Bundle<C1, E1, R1, A1, S1>,\n\tbundle2: BundlesAreCompatible<C1, C2, E1, E2, R1, R2, A1, A2, S1, S2> extends true\n\t\t? Bundle<C2, E2, R2, A2, S2>\n\t\t: never\n): Bundle<C1 & C2, E1 & E2, R1 & R2, A1 & A2, S1 & S2>;\n\nexport function mergeBundles<\n\tComponentTypes extends Record<string, any>,\n\tEventTypes extends Record<string, any>,\n\tResourceTypes extends Record<string, any>,\n\tAssetTypes extends Record<string, unknown>,\n\tScreenStates extends Record<string, ScreenDefinition<any, any>>,\n>(\n\tid: string,\n\t...bundles: Array<Bundle<ComponentTypes, EventTypes, ResourceTypes, AssetTypes, ScreenStates>>\n): Bundle<ComponentTypes, EventTypes, ResourceTypes, AssetTypes, ScreenStates>;\n\nexport function mergeBundles(\n\tid: string,\n\t...bundles: Array<Bundle<any, any, any, any, any>>\n): Bundle<any, any, any, any, any> {\n\tif (bundles.length === 0) {\n\t\treturn new Bundle(id);\n\t}\n\n\tconst combined = new Bundle(id);\n\n\tfor (const bundle of bundles) {\n\t\tfor (const system of bundle.getSystemBuilders()) {\n\t\t\t// reuse the full builder so we carry over queries, hooks, and handlers\n\t\t\tcombined.addSystem(system);\n\t\t}\n\n\t\t// Add resources from this bundle\n\t\tfor (const [label, resource] of bundle.getResources().entries()) {\n\t\t\tcombined._setResource(label as string, resource);\n\t\t}\n\n\t\t// Add assets from this bundle\n\t\tfor (const [key, definition] of bundle.getAssets().entries()) {\n\t\t\tcombined._setAsset(key, definition);\n\t\t}\n\n\t\t// Add screens from this bundle\n\t\tfor (const [name, definition] of bundle.getScreens().entries()) {\n\t\t\tcombined._setScreen(name, definition);\n\t\t}\n\t}\n\n\treturn combined;\n}\n",
16
- "import ECSpresso from \"./ecspresso\";\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 * Event data emitted when an entity's parent changes\n */\nexport\ninterface HierarchyChangedEvent {\n\t/** The entity whose parent changed */\n\tentityId: number;\n\t/** The previous parent, or null if entity had no parent */\n\toldParent: number | null;\n\t/** The new parent, or null if entity was orphaned */\n\tnewParent: number | null;\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 EventHandler<T> {\n\tcallback: (data: T) => void;\n\tonce: boolean;\n}\n\nexport\ninterface FilteredEntity<\n\tComponentTypes,\n\tWithComponents extends keyof ComponentTypes = never,\n\tWithoutComponents extends keyof ComponentTypes = never,\n> {\n\tid: number;\n\tcomponents: Omit<Partial<ComponentTypes>, WithoutComponents> & {\n\t\t[K in WithComponents]: ComponentTypes[K]\n\t};\n}\n\nexport\ninterface QueryConfig<\n\tComponentTypes,\n\tWithComponents extends keyof ComponentTypes,\n\tWithoutComponents extends keyof ComponentTypes,\n> {\n\twith: ReadonlyArray<WithComponents>;\n\twithout?: ReadonlyArray<WithoutComponents>;\n\tchanged?: ReadonlyArray<WithComponents>;\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}\n> = FilteredEntity<\n\tComponentTypes,\n\tQueryDef['with'][number],\n\tQueryDef['without'] extends ReadonlyArray<any> ? QueryDef['without'][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> = {\n\twith: ReadonlyArray<WithComponents>;\n\twithout?: ReadonlyArray<WithoutComponents>;\n\tchanged?: ReadonlyArray<WithComponents>;\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}\n>(queryDef: QueryDef): QueryDef {\n\treturn queryDef;\n}\n\nexport\ninterface System<\n\tComponentTypes extends Record<string, any> = {},\n\tWithComponents extends keyof ComponentTypes = never,\n\tWithoutComponents extends keyof ComponentTypes = never,\n\tEventTypes extends Record<string, any> = {},\n\tResourceTypes extends Record<string, any> = {},\n\tAssetTypes extends Record<string, unknown> = {},\n\tScreenStates extends Record<string, any> = {},\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?: 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?: 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?: string[];\n\tentityQueries?: {\n\t\t[queryName: string]: QueryConfig<ComponentTypes, WithComponents, WithoutComponents>;\n\t};\n\t/**\n\t * Process method that runs during each update cycle\n\t * @param queries The entity queries results based on system's entityQueries definition\n\t * @param deltaTime Time elapsed since the last update in seconds\n\t * @param ecs The ECSpresso instance providing access to all ECS functionality\n\t */\n\tprocess?(\n\t\tqueries: {\n\t\t\t[queryName: string]: Array<FilteredEntity<ComponentTypes, WithComponents, WithoutComponents>>;\n\t\t} | Array<FilteredEntity<ComponentTypes, WithComponents, WithoutComponents>>,\n\t\tdeltaTime: number,\n\t\tecs: ECSpresso<\n\t\t\tComponentTypes,\n\t\t\tEventTypes,\n\t\t\tResourceTypes,\n\t\t\tAssetTypes,\n\t\t\tScreenStates\n\t\t>\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<\n\t\t\tComponentTypes,\n\t\t\tEventTypes,\n\t\t\tResourceTypes,\n\t\t\tAssetTypes,\n\t\t\tScreenStates\n\t\t>\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<\n\t\t\tComponentTypes,\n\t\t\tEventTypes,\n\t\t\tResourceTypes,\n\t\t\tAssetTypes,\n\t\t\tScreenStates\n\t\t>\n\t): void;\n\n\t/**\n\t * Event handlers for specific event types\n\t */\n\teventHandlers?: {\n\t\t[EventName in keyof EventTypes]?: {\n\t\t\t/**\n\t\t\t * Event handler function\n\t\t\t * @param data The event data specific to this event type\n\t\t\t * @param ecs The ECSpresso instance providing access to all ECS functionality\n\t\t\t */\n\t\t\thandler(\n\t\t\t\tdata: EventTypes[EventName],\n\t\t\t\tecs: ECSpresso<\n\t\t\t\t\tComponentTypes,\n\t\t\t\t\tEventTypes,\n\t\t\t\t\tResourceTypes,\n\t\t\t\t\tAssetTypes,\n\t\t\t\t\tScreenStates\n\t\t\t\t>\n\t\t\t): void;\n\t\t};\n\t};\n}\n\n// Re-export utility types from type-utils to maintain backward compatibility\nexport type { Merge, MergeAll } from './type-utils';\n",
16
+ "import ECSpresso from \"./ecspresso\";\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 * Event data emitted when an entity's parent changes\n */\nexport\ninterface HierarchyChangedEvent {\n\t/** The entity whose parent changed */\n\tentityId: number;\n\t/** The previous parent, or null if entity had no parent */\n\toldParent: number | null;\n\t/** The new parent, or null if entity was orphaned */\n\tnewParent: number | null;\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 EventHandler<T> {\n\tcallback: (data: T) => void;\n\tonce: boolean;\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\tComponentTypes extends Record<string, any> = {},\n\tWithComponents extends keyof ComponentTypes = never,\n\tWithoutComponents extends keyof ComponentTypes = never,\n\tEventTypes extends Record<string, any> = {},\n\tResourceTypes extends Record<string, any> = {},\n\tAssetTypes extends Record<string, unknown> = {},\n\tScreenStates extends Record<string, any> = {},\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?: 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?: 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?: string[];\n\tentityQueries?: {\n\t\t[queryName: string]: QueryConfig<ComponentTypes, WithComponents, WithoutComponents>;\n\t};\n\t/**\n\t * Process method that runs during each update cycle\n\t * @param queries The entity queries results based on system's entityQueries definition\n\t * @param deltaTime Time elapsed since the last update in seconds\n\t * @param ecs The ECSpresso instance providing access to all ECS functionality\n\t */\n\tprocess?(\n\t\tqueries: {\n\t\t\t[queryName: string]: Array<FilteredEntity<ComponentTypes, WithComponents, WithoutComponents>>;\n\t\t} | Array<FilteredEntity<ComponentTypes, WithComponents, WithoutComponents>>,\n\t\tdeltaTime: number,\n\t\tecs: ECSpresso<\n\t\t\tComponentTypes,\n\t\t\tEventTypes,\n\t\t\tResourceTypes,\n\t\t\tAssetTypes,\n\t\t\tScreenStates\n\t\t>\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<\n\t\t\tComponentTypes,\n\t\t\tEventTypes,\n\t\t\tResourceTypes,\n\t\t\tAssetTypes,\n\t\t\tScreenStates\n\t\t>\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<\n\t\t\tComponentTypes,\n\t\t\tEventTypes,\n\t\t\tResourceTypes,\n\t\t\tAssetTypes,\n\t\t\tScreenStates\n\t\t>\n\t): void;\n\n\t/**\n\t * Event handlers for specific event types\n\t */\n\teventHandlers?: {\n\t\t[EventName in keyof EventTypes]?: {\n\t\t\t/**\n\t\t\t * Event handler function\n\t\t\t * @param data The event data specific to this event type\n\t\t\t * @param ecs The ECSpresso instance providing access to all ECS functionality\n\t\t\t */\n\t\t\thandler(\n\t\t\t\tdata: EventTypes[EventName],\n\t\t\t\tecs: ECSpresso<\n\t\t\t\t\tComponentTypes,\n\t\t\t\t\tEventTypes,\n\t\t\t\t\tResourceTypes,\n\t\t\t\t\tAssetTypes,\n\t\t\t\t\tScreenStates\n\t\t\t\t>\n\t\t\t): void;\n\t\t};\n\t};\n}\n\n// Re-export utility types from type-utils to maintain backward compatibility\nexport type { Merge, MergeAll } from './type-utils';\n",
17
17
  "import ECSpresso from './ecspresso';\nimport { SystemBuilder } from './system-builder';\nimport Bundle, { mergeBundles } from './bundle';\n\nexport * from './types';\nexport * from './asset-types';\nexport * from './screen-types';\nexport type { ReactiveQueryDefinition } from './reactive-query-manager';\nexport { default as EntityManager } from './entity-manager';\nexport { default as EventBus } from './event-bus';\nexport { default as CommandBuffer } from './command-buffer';\nexport { default as HierarchyManager } from './hierarchy-manager';\n/**\n * @internal ResourceManager is exported for testing purposes only.\n * Use ECSpresso resource methods instead: getResource(), addResource(), removeResource(), updateResource(), hasResource()\n */\nexport { default as ResourceManager } from './resource-manager';\nexport { default as AssetManager, createAssetConfigurator } from './asset-manager';\nexport { default as ScreenManager, createScreenConfigurator } from './screen-manager';\nexport { SystemBuilder };\nexport { Bundle, mergeBundles };\nexport default ECSpresso;\n"
18
18
  ],
19
- "mappings": "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",
20
- "debugId": "92E5E4E30405F52564756E2164756E21",
19
+ "mappings": "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",
20
+ "debugId": "D54EBCF6A31F22DB64756E2164756E21",
21
21
  "names": []
22
22
  }