@codehz/ecs 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/README.md +13 -1
- package/dist/builder.d.mts +59 -44
- package/dist/index.d.mts +2 -2
- package/dist/index.mjs +2 -2
- package/dist/testing.d.mts +1 -1
- package/dist/testing.mjs +1 -1
- package/dist/world.mjs +1136 -887
- package/dist/world.mjs.map +1 -1
- package/examples/spatial-grid.ts +1 -1
- package/package.json +1 -1
- package/src/__tests__/component/singleton.test.ts +76 -34
- package/src/__tests__/serialization/bounds.test.ts +2 -3
- package/src/__tests__/world/component-management.test.ts +6 -5
- package/src/index.ts +2 -0
- package/src/world/archetype-manager.ts +283 -0
- package/src/world/command-executor.ts +258 -0
- package/src/world/debug-stats.ts +147 -0
- package/src/world/operations.ts +88 -0
- package/src/world/singleton.ts +51 -0
- package/src/world/world.ts +178 -573
package/dist/world.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"world.mjs","names":[],"sources":["../src/entity/types.ts","../src/entity/relation.ts","../src/entity/manager.ts","../src/utils/bit-set.ts","../src/component/registry.ts","../src/world/builder.ts","../src/component/type-utils.ts","../src/types/index.ts","../src/utils/utils.ts","../src/archetype/helpers.ts","../src/archetype/archetype.ts","../src/archetype/store.ts","../src/commands/buffer.ts","../src/commands/changeset.ts","../src/component/entity-store.ts","../src/query/filter.ts","../src/query/query.ts","../src/query/registry.ts","../src/world/commands.ts","../src/world/hooks.ts","../src/utils/multi-map.ts","../src/world/references.ts","../src/storage/serialization.ts","../src/world/serialization.ts","../src/world/world.ts"],"sourcesContent":["/**\n * Unique symbol brand for associating component type information with EntityId\n */\ndeclare const __componentTypeMarker: unique symbol;\n\n/**\n * Unique symbol brand for tagging the kind of EntityId (e.g., 'component', 'entity-relation')\n */\ndeclare const __entityIdTypeTag: unique symbol;\n\n/**\n * Entity ID type for ECS architecture\n * Based on 52-bit integers within safe integer range\n * - Component IDs: 1-1023\n * - Entity IDs: 1024+\n * - Relation IDs: negative numbers encoding component and entity associations\n */\n/**\n * Branded numeric type representing an ECS identifier.\n *\n * - {@link ComponentId}: positive values in range `1–1023`\n * - Entity IDs: values `1024+`\n * - {@link RelationId}: negative values encoding `(componentId, targetId)`\n *\n * @template T - The data type associated with this ID\n * @template U - Discriminant for the ID kind (e.g. `\"component\"`, `\"entity-relation\"`)\n */\nexport type EntityId<T = unknown, U = unknown> = number & {\n readonly [__componentTypeMarker]: T;\n readonly [__entityIdTypeTag]: U;\n};\n\n/**\n * Component identifier. Valid values are `1` through `1023`.\n * Created with {@link component}.\n *\n * @template T - The data type stored by this component (`void` for tag components)\n */\nexport type ComponentId<T = void> = EntityId<T, \"component\">;\n\n/**\n * Relation identifier targeting an entity.\n * Created with {@link relation}.\n *\n * @template T - The data type stored by this relation\n */\nexport type EntityRelationId<T = void> = EntityId<T, \"entity-relation\">;\n\n/**\n * Relation identifier targeting another component (singleton relation).\n * Created with {@link relation}.\n *\n * @template T - The data type stored by this relation\n */\nexport type ComponentRelationId<T = void> = EntityId<T, \"component-relation\">;\n\n/**\n * Wildcard relation identifier used to query all targets of a given relation component.\n * Created with `relation(componentId, \"*\")`.\n *\n * @template T - The data type stored by the relation\n */\nexport type WildcardRelationId<T = void> = EntityId<T, \"wildcard-relation\">;\n\n/**\n * Union of all relation identifier kinds.\n *\n * @template T - The data type stored by the relation\n */\nexport type RelationId<T = void> = EntityRelationId<T> | ComponentRelationId<T> | WildcardRelationId<T>;\n\n/**\n * Constants for ID ranges\n */\nexport const INVALID_COMPONENT_ID = 0;\nexport const COMPONENT_ID_MAX = 1023;\nexport const ENTITY_ID_START = 1024;\n\n/**\n * Constants for relation ID encoding\n */\nexport const RELATION_SHIFT = 2 ** 42;\nexport const WILDCARD_TARGET_ID = 0;\n\n/**\n * Check if a component ID is valid (1-1023)\n */\nexport function isValidComponentId(componentId: number): boolean {\n return componentId >= 1 && componentId <= COMPONENT_ID_MAX;\n}\n\n/**\n * Check if an ID is a component ID\n */\nexport function isComponentId<T>(id: EntityId<T>): id is ComponentId<T> {\n return id >= 1 && id <= COMPONENT_ID_MAX;\n}\n\n/**\n * Check if an ID is an entity ID\n */\nexport function isEntityId<T>(id: EntityId<T>): id is EntityId<T> {\n return id >= ENTITY_ID_START;\n}\n\n/**\n * Check if an ID is a relation ID\n */\nexport function isRelationId<T>(id: EntityId<T>): id is RelationId<T> {\n return id < 0;\n}\n\n/**\n * Create a component ID\n * @param id Component identifier (1-1023)\n * @internal This function is for internal use and testing only. Use `component()` to create components.\n * @see component\n */\nexport function createComponentId<T = void>(id: number): ComponentId<T> {\n if (id < 1 || id > COMPONENT_ID_MAX) {\n throw new Error(`Component ID must be between 1 and ${COMPONENT_ID_MAX}`);\n }\n return id as ComponentId<T>;\n}\n\n/**\n * Create an entity ID\n * @param id Entity identifier (starting from 1024)\n */\nexport function createEntityId(id: number): EntityId {\n if (id < ENTITY_ID_START) {\n throw new Error(`Entity ID must be ${ENTITY_ID_START} or greater`);\n }\n return id as EntityId;\n}\n","import type {\n ComponentId,\n ComponentRelationId,\n EntityId,\n EntityRelationId,\n RelationId,\n WildcardRelationId,\n} from \"./types\";\nimport {\n ENTITY_ID_START,\n isComponentId,\n isEntityId,\n isValidComponentId,\n RELATION_SHIFT,\n WILDCARD_TARGET_ID,\n} from \"./types\";\n\n/**\n * Internal function to decode a relation ID into raw component and target IDs\n * @param id The EntityId to decode\n * @returns Object with componentId and targetId, or null if not a relation\n */\nexport function decodeRelationRaw(id: EntityId<any>): { componentId: number; targetId: number } | null {\n if (id >= 0) return null;\n const absId = -id;\n const componentId = Math.floor(absId / RELATION_SHIFT);\n const targetId = absId % RELATION_SHIFT;\n return { componentId, targetId };\n}\n\n/**\n * Type for relation ID based on component and target types\n */\ntype RelationIdType<T, R> =\n R extends ComponentId<infer U>\n ? U extends void\n ? ComponentRelationId<T>\n : ComponentRelationId<T extends void ? U : T>\n : R extends EntityId<any>\n ? EntityRelationId<T>\n : never;\n\n/**\n * Create a relation ID by associating a component with a target entity, component, or wildcard.\n *\n * Relations are encoded as negative numbers and can be used anywhere a regular component ID is accepted.\n * Use `\"*\"` as the target to create a wildcard relation for querying all targets of a given relation type.\n *\n * @param componentId - The base component ID (must be a valid component)\n * @param targetId - The target entity ID, component ID, or `\"*\"` for wildcard\n * @returns A relation ID that encodes both the component and target\n *\n * @throws {Error} If `componentId` is not a valid component ID\n * @throws {Error} If `targetId` is not a valid entity, component, or `\"*\"`\n *\n * @example\n * const ChildOf = component();\n * const parent = world.new();\n *\n * // Entity relation\n * const childRelation = relation(ChildOf, parent);\n * world.set(child, childRelation);\n *\n * // Wildcard relation (queries all targets)\n * const allChildren = world.createQuery([relation(ChildOf, \"*\")]);\n */\nexport function relation<T>(componentId: ComponentId<T>, targetId: \"*\"): WildcardRelationId<T>;\nexport function relation<T, R extends EntityId<any>>(componentId: ComponentId<T>, targetId: R): RelationIdType<T, R>;\nexport function relation<T>(componentId: ComponentId<T>, targetId: EntityId<any> | \"*\"): EntityId<any> {\n if (!isComponentId(componentId)) {\n throw new Error(\"First argument must be a valid component ID\");\n }\n\n let actualTargetId: number;\n if (targetId === \"*\") {\n actualTargetId = WILDCARD_TARGET_ID;\n } else {\n if (!isEntityId(targetId) && !isComponentId(targetId)) {\n throw new Error(\"Second argument must be a valid entity ID, component ID, or '*'\");\n }\n actualTargetId = targetId;\n }\n\n // Encode: negative number with component_id * 2^42 + target_id\n return -(componentId * RELATION_SHIFT + actualTargetId) as EntityId<any>;\n}\n\n/**\n * Check if an ID is a wildcard relation (created with `relation(componentId, \"*\")`).\n *\n * @param id - The ID to check\n * @returns `true` if the ID is a wildcard relation, `false` otherwise\n */\nexport function isWildcardRelationId<T>(id: EntityId<T>): id is WildcardRelationId<T> {\n const decoded = decodeRelationRaw(id);\n return decoded !== null && decoded.targetId === WILDCARD_TARGET_ID;\n}\n\n/**\n * Decode a relation ID into component and target IDs\n * @param relationId The relation ID (must be negative)\n * @returns Object with componentId, targetId, and relation type\n */\nexport function decodeRelationId(relationId: RelationId<any>): {\n componentId: ComponentId<any>;\n targetId: EntityId<any>;\n type: \"entity\" | \"component\" | \"wildcard\";\n} {\n const decoded = decodeRelationRaw(relationId);\n if (decoded === null) {\n throw new Error(\"ID is not a relation ID\");\n }\n\n const { componentId: rawComponentId, targetId: rawTargetId } = decoded;\n if (!isValidComponentId(rawComponentId)) {\n throw new Error(\"Invalid component ID in relation\");\n }\n\n const componentId = rawComponentId as ComponentId<any>;\n const targetId = rawTargetId as EntityId<any>;\n\n // Determine type based on targetId range\n if (targetId === WILDCARD_TARGET_ID) {\n return { componentId, targetId, type: \"wildcard\" };\n } else if (isEntityId(targetId)) {\n return { componentId, targetId, type: \"entity\" };\n } else if (isComponentId(targetId)) {\n return { componentId, targetId, type: \"component\" };\n } else {\n throw new Error(\"Invalid target ID in relation\");\n }\n}\n\n/**\n * Get the string representation of an ID type\n */\nexport function getIdType(\n id: EntityId<any>,\n): \"component\" | \"entity\" | \"entity-relation\" | \"component-relation\" | \"wildcard-relation\" | \"invalid\" {\n if (isComponentId(id)) return \"component\";\n if (isEntityId(id)) return \"entity\";\n\n if (id < 0) {\n const decoded = decodeRelationRaw(id as RelationId<any>);\n if (decoded === null) return \"invalid\";\n\n const { componentId: rawComponentId, targetId: rawTargetId } = decoded;\n\n // Validate component ID\n if (!isValidComponentId(rawComponentId)) return \"invalid\";\n\n // Determine type based on targetId range\n if (rawTargetId === WILDCARD_TARGET_ID) {\n return \"wildcard-relation\";\n } else if (isEntityId(rawTargetId as EntityId<any>)) {\n return \"entity-relation\";\n } else if (isComponentId(rawTargetId as ComponentId<any>)) {\n return \"component-relation\";\n } else {\n return \"invalid\";\n }\n }\n\n return \"invalid\"; // fallback for unknown/invalid IDs\n}\n\n/**\n * Get detailed type information for an EntityId\n * @param id The EntityId to analyze\n * @returns Detailed type information including relation subtypes\n */\nexport function getDetailedIdType(id: EntityId<any>):\n | {\n type: \"component\" | \"entity\" | \"invalid\";\n componentId?: never;\n targetId?: never;\n }\n | {\n type: \"entity-relation\" | \"wildcard-relation\";\n componentId: ComponentId<any>;\n targetId: EntityId<any>;\n }\n | {\n type: \"component-relation\";\n componentId: ComponentId<any>;\n targetId: ComponentId<any>;\n } {\n if (isComponentId(id)) {\n return { type: \"component\" };\n }\n\n if (isEntityId(id)) {\n return { type: \"entity\" };\n }\n\n if (id < 0) {\n const decoded = decodeRelationRaw(id as RelationId<any>);\n if (decoded === null) {\n return { type: \"invalid\" };\n }\n\n const { componentId: rawComponentId, targetId: rawTargetId } = decoded;\n\n // Validate component ID\n if (!isValidComponentId(rawComponentId)) {\n return { type: \"invalid\" };\n }\n\n const componentId = rawComponentId as ComponentId<any>;\n const targetId = rawTargetId as EntityId<any>;\n\n // Determine type based on targetId range\n if (targetId === WILDCARD_TARGET_ID) {\n return { type: \"wildcard-relation\", componentId, targetId };\n } else if (isEntityId(targetId)) {\n return { type: \"entity-relation\", componentId, targetId };\n } else if (isComponentId(targetId as any)) {\n return { type: \"component-relation\", componentId, targetId: targetId as ComponentId<any> };\n } else {\n return { type: \"invalid\" };\n }\n }\n\n // Unknown/invalid ID\n return { type: \"invalid\" };\n}\n\n/**\n * Inspect an EntityId and return a human-readable string representation\n * @param id The EntityId to inspect\n * @returns A friendly string representation of the ID\n */\nexport function inspectEntityId(id: EntityId<any>): string {\n if (id === 0) {\n return \"Invalid Component ID (0)\";\n }\n\n if (isComponentId(id)) {\n return `Component ID (${id})`;\n }\n\n if (isEntityId(id)) {\n return `Entity ID (${id})`;\n }\n\n if (id < 0) {\n const decoded = decodeRelationRaw(id as RelationId<any>);\n if (decoded === null) {\n return `Invalid Relation ID (${id})`;\n }\n\n const { componentId: rawComponentId, targetId: rawTargetId } = decoded;\n\n // Validate component ID\n if (!isValidComponentId(rawComponentId)) {\n return `Invalid Relation ID (${id})`;\n }\n\n // Determine target type and format output\n const componentStr = `Component ID (${rawComponentId})`;\n let targetStr: string;\n\n if (rawTargetId === WILDCARD_TARGET_ID) {\n targetStr = \"Wildcard (*)\";\n } else if (isEntityId(rawTargetId as EntityId<any>)) {\n targetStr = `Entity ID (${rawTargetId})`;\n } else if (isComponentId(rawTargetId as ComponentId<any>)) {\n targetStr = `Component ID (${rawTargetId})`;\n } else {\n return `Invalid Relation ID (${id})`;\n }\n\n return `Relation ID: ${componentStr} -> ${targetStr}`;\n }\n\n return `Unknown ID (${id})`;\n}\n\n/**\n * Get the componentId from a relation ID without fully decoding the relation.\n * Returns undefined for non-relation IDs or invalid component IDs.\n */\nexport function getComponentIdFromRelationId<T>(id: EntityId<T>): ComponentId<T> | undefined {\n const decoded = decodeRelationRaw(id);\n if (decoded === null || !isValidComponentId(decoded.componentId)) return undefined;\n return decoded.componentId as ComponentId<T>;\n}\n\n/**\n * Get the targetId from a relation ID without fully decoding the relation.\n * Returns undefined for non-relation IDs.\n */\nexport function getTargetIdFromRelationId(id: EntityId<any>): EntityId<any> | undefined {\n const decoded = decodeRelationRaw(id);\n return decoded?.targetId as EntityId<any>;\n}\n\n/**\n * Check if an ID is an entity-relation (relation targeting an entity, not a component or wildcard)\n */\nexport function isEntityRelation(id: EntityId<any>): boolean {\n const decoded = decodeRelationRaw(id);\n return decoded !== null && decoded.targetId >= ENTITY_ID_START;\n}\n\n/**\n * Check if an ID is a component-relation (relation targeting a component)\n */\nexport function isComponentRelation(id: EntityId<any>): boolean {\n const decoded = decodeRelationRaw(id);\n return decoded !== null && isValidComponentId(decoded.targetId);\n}\n\n/**\n * Check if an ID is any type of relation (entity, component, or wildcard)\n */\nexport function isAnyRelation(id: EntityId<any>): boolean {\n return id < 0;\n}\n","import type { ComponentId, EntityId } from \"./types\";\nimport { COMPONENT_ID_MAX, ENTITY_ID_START, isEntityId } from \"./types\";\n\n/**\n * Entity ID Manager for automatic allocation and freelist recycling\n */\nexport class EntityIdManager {\n private nextId: number = ENTITY_ID_START;\n /**\n * Free list uses a stack (LIFO) for better memory locality when reusing IDs.\n * We use an array instead of a Set for significantly better performance.\n */\n private freelist: EntityId[] = [];\n\n /**\n * Allocate a new entity ID\n * Uses freelist if available, otherwise increments counter\n */\n allocate(): EntityId {\n if (this.freelist.length > 0) {\n return this.freelist.pop()!;\n } else {\n const id = this.nextId;\n this.nextId++;\n // Check for overflow (though unlikely in practice)\n if (this.nextId >= Number.MAX_SAFE_INTEGER) {\n throw new Error(\"Entity ID overflow: reached maximum safe integer\");\n }\n return id as EntityId;\n }\n }\n\n /**\n * Deallocate an entity ID, adding it to the freelist for reuse\n * @param id The entity ID to deallocate\n */\n deallocate(id: EntityId<any>): void {\n if (!isEntityId(id)) {\n throw new Error(\"Can only deallocate valid entity IDs\");\n }\n if (id >= this.nextId) {\n throw new Error(\"Cannot deallocate an ID that was never allocated\");\n }\n this.freelist.push(id);\n }\n\n /**\n * Get the current freelist size (for debugging/monitoring)\n */\n getFreelistSize(): number {\n return this.freelist.length;\n }\n\n /**\n * Get the next ID that would be allocated (for debugging)\n */\n getNextId(): number {\n return this.nextId;\n }\n\n /**\n * Serialize internal state for persistence.\n * Returns a plain object representing allocator state. Values may be non-JSON-serializable.\n */\n serializeState(): { nextId: number; freelist: number[] } {\n return { nextId: this.nextId, freelist: Array.from(this.freelist) };\n }\n\n /**\n * Restore internal state from a previously-serialized object.\n * Overwrites the current nextId and freelist.\n */\n deserializeState(state: { nextId: number; freelist?: number[] }): void {\n if (typeof state.nextId !== \"number\") {\n throw new Error(\"Invalid state for EntityIdManager.deserializeState\");\n }\n this.nextId = state.nextId;\n this.freelist = (state.freelist || []) as EntityId[];\n }\n}\n\n/**\n * Component ID Manager for automatic allocation\n * Components are typically registered once and not recycled\n */\nexport class ComponentIdAllocator {\n private nextId: number = 1;\n\n /**\n * Allocate a new component ID\n * Increments counter sequentially from 1\n */\n allocate<T = void>(): ComponentId<T> {\n if (this.nextId > COMPONENT_ID_MAX) {\n throw new Error(`Component ID overflow: maximum ${COMPONENT_ID_MAX} components allowed`);\n }\n const id = this.nextId;\n this.nextId++;\n return id as ComponentId<T>;\n }\n\n /**\n * Get the next ID that would be allocated (for debugging)\n */\n getNextId(): number {\n return this.nextId;\n }\n\n /**\n * Check if more component IDs are available\n */\n hasAvailableIds(): boolean {\n return this.nextId <= COMPONENT_ID_MAX;\n }\n}\n","export class BitSet {\n private data: Uint32Array;\n private _length: number;\n\n constructor(length: number) {\n this._length = length;\n const numWords = Math.ceil(length / 32);\n this.data = new Uint32Array(numWords);\n }\n\n get length(): number {\n return this._length;\n }\n\n has(index: number): boolean {\n if (index < 0 || index >= this._length) return false;\n const word = index >>> 5; // divide by 32\n const bit = index & 31;\n return ((this.data[word]! >>> bit) & 1) !== 0;\n }\n\n set(index: number): void {\n if (index < 0 || index >= this._length) return;\n const word = index >>> 5;\n const bit = index & 31;\n this.data[word]! |= 1 << bit;\n }\n\n clear(index: number): void {\n if (index < 0 || index >= this._length) return;\n const word = index >>> 5;\n const bit = index & 31;\n this.data[word]! &= ~(1 << bit);\n }\n\n // set a range [lo, hi] inclusive to 1\n setRange(lo: number, hi: number): void {\n if (lo > hi) return;\n if (lo < 0) lo = 0;\n if (hi >= this._length) hi = this._length - 1;\n\n const firstWord = lo >>> 5;\n const lastWord = hi >>> 5;\n const loBit = lo & 31;\n const hiBit = hi & 31;\n\n // helper to produce mask for [a..b] within a single 32-bit word\n const maskFor = (a: number, b: number) => {\n const width = b - a + 1;\n if (width <= 0) return 0 >>> 0;\n if (width >= 32) return 0xffffffff >>> 0;\n return (((1 << width) - 1) << a) >>> 0;\n };\n\n if (firstWord === lastWord) {\n const mask = maskFor(loBit, hiBit);\n this.data[firstWord]! = (this.data[firstWord]! | mask) >>> 0;\n return;\n }\n\n // first partial word\n const firstMask = maskFor(loBit, 31);\n this.data[firstWord]! = (this.data[firstWord]! | firstMask) >>> 0;\n\n // middle full words\n for (let w = firstWord + 1; w <= lastWord - 1; w++) {\n this.data[w] = 0xffffffff >>> 0;\n }\n\n // last partial word\n const lastMask = maskFor(0, hiBit);\n this.data[lastWord]! = (this.data[lastWord]! | lastMask) >>> 0;\n }\n\n // check whether any bit in [lo, hi] is zero (i.e. not set)\n anyClearInRange(lo: number, hi: number): boolean {\n if (lo > hi) return false;\n if (lo < 0) lo = 0;\n if (hi >= this._length) hi = this._length - 1;\n\n const firstWord = lo >>> 5;\n const lastWord = hi >>> 5;\n const loBit = lo & 31;\n const hiBit = hi & 31;\n\n const maskFor = (a: number, b: number) => {\n const width = b - a + 1;\n if (width <= 0) return 0 >>> 0;\n if (width >= 32) return 0xffffffff >>> 0;\n return (((1 << width) - 1) << a) >>> 0;\n };\n\n if (firstWord === lastWord) {\n const mask = maskFor(loBit, hiBit);\n const bits = (this.data[firstWord]! & mask) >>> 0;\n return bits !== mask >>> 0;\n }\n\n // first partial word: if any bit in the mask is clear -> return true\n const firstMask = maskFor(loBit, 31);\n if ((this.data[firstWord]! & firstMask) >>> 0 !== firstMask >>> 0) return true;\n\n // middle full words\n for (let w = firstWord + 1; w <= lastWord - 1; w++) {\n if (this.data[w] !== 0xffffffff >>> 0) return true;\n }\n\n // last partial word\n const lastMask = maskFor(0, hiBit);\n if ((this.data[lastWord]! & lastMask) >>> 0 !== lastMask >>> 0) return true;\n\n return false;\n }\n\n // reset all bits to zero\n reset(): void {\n this.data.fill(0);\n }\n\n *[Symbol.iterator](): IterableIterator<number> {\n for (let wordIndex = 0; wordIndex < this.data.length; wordIndex++) {\n let word = this.data[wordIndex]!;\n if (word === 0) continue;\n const baseIndex = wordIndex * 32;\n for (let bit = 0; bit < 32 && baseIndex + bit < this._length; bit++) {\n if (word & 1) {\n yield baseIndex + bit;\n }\n word >>>= 1;\n }\n }\n }\n}\n","import { ComponentIdAllocator } from \"../entity/manager\";\nimport { decodeRelationRaw } from \"../entity/relation\";\nimport type { ComponentId, EntityId } from \"../entity/types\";\nimport {\n COMPONENT_ID_MAX,\n ENTITY_ID_START,\n isComponentId,\n isValidComponentId,\n WILDCARD_TARGET_ID,\n} from \"../entity/types\";\nimport { BitSet } from \"../utils/bit-set\";\n\nconst globalComponentIdAllocator = new ComponentIdAllocator();\n\nconst ComponentIdForNames: Map<string, ComponentId<any>> = new Map();\n\n/**\n * Merge function type for combining repeated `set()` values within a single sync batch.\n *\n * When `world.set(entity, componentType, value)` is called **multiple times** for the\n * same entity and same component type **before** the next `world.sync()`, the merge\n * callback is invoked to combine the values instead of simply overwriting. This allows\n * additive or custom composition of component data in a single frame.\n *\n * @typeParam T - The component's value type.\n *\n * @param prev - The value from the **previous** `set()` call (or the merged result of\n * earlier calls) for this entity/componentType pair within the current sync batch.\n * @param next - The value from the **current** `set()` call being processed.\n *\n * @returns The merged value to be stored. This becomes `prev` if another `set()` for\n * the same entity and componentType is encountered later in the same batch.\n *\n * @remarks\n * **Idempotency**: Merge functions **must be idempotent**. The ECS does not guarantee\n * that `world.sync()` won't be called multiple times in edge cases (e.g., intermediate\n * syncs during pipeline execution), so the merge result should not depend on call\n * count or non-deterministic state.\n *\n * **Single-batch scope**: Merging only applies to `set()` calls within the **same sync\n * batch** (i.e., between two `world.sync()` calls). After `world.sync()`, the component\n * value is committed to storage, and the next `set()` starts with a fresh `prev` value.\n *\n * @example\n * ```ts\n * // Accumulate damage events in a single frame\n * const DamageEvents = component<DamageEvent[]>({\n * merge: (prev, next) => [...prev, ...next],\n * });\n *\n * world.set(player, DamageEvents, [{ source: \"fire\", amount: 10 }]);\n * world.set(player, DamageEvents, [{ source: \"ice\", amount: 5 }]);\n * // After sync: player has [{ source: \"fire\", amount: 10 }, { source: \"ice\", amount: 5 }]\n * ```\n */\ntype ComponentMerge<T = any> = (prev: T, next: T) => T;\n\n/**\n * Component options that define intrinsic properties\n */\nexport interface ComponentOptions<T = any> {\n /**\n * An optional human-readable name for the component, used for debugging and\n * serialization.\n *\n * While `name` is **optional** at registration time, omitting it can cause\n * problems when serializing and later deserializing the world:\n *\n * 1. **Cross-session portability**: Without a name, the component is\n * serialized as a raw numeric ID. Component IDs are allocated sequentially\n * at registration time, so if the order of `component()` calls changes\n * between sessions (e.g. due to code refactoring, lazy-loading, or\n * tree-shaking), those numeric IDs will no longer point to the same\n * component type, leading to **silent data corruption** on restore.\n *\n * 2. **Runtime warnings**: `encodeEntityId` logs a `console.warn` for every\n * unnamed component it encounters during `world.serialize()`, which can be\n * noisy in production when serialization is used for save-games or\n * snapshots.\n *\n * 3. **Debugging ergonomics**: Named components make serialized snapshots\n * human-readable (e.g. `\"Position\"` instead of `42`), which is invaluable\n * when inspecting save files or network dumps.\n *\n * **Recommendation**: Always provide a `name` for any component that may\n * appear in a serialized world — even if it's just the same string as the\n * variable name.\n *\n * @example\n * ```ts\n * // ✅ Good: explicit name ensures stable serialization\n * const Position = component<{ x: number; y: number }>({ name: \"Position\" });\n *\n * // ⚠️ Risky: no name — serialization falls back to numeric ID\n * const Velocity = component<{ dx: number; dy: number }>();\n * ```\n */\n name?: string;\n /**\n * If `true`, an entity can have **at most one** relation per base component type.\n * When a new relation with the same base component is added, any existing relations\n * with that base component are **automatically removed** before the new one is applied.\n *\n * **Only applicable to relation components** — components used via\n * `relation(componentId, target)`. Regular (non-relation) components ignore this flag.\n *\n * ## Behavior\n *\n * Exclusive relations enforce a **one-to-one** constraint at the entity level:\n * each entity can hold at most one relation of a given exclusive component type.\n *\n * - **Same base component, different targets**: `set(entity, relation(Comp, A))`\n * followed by `set(entity, relation(Comp, B))` results in only `(Comp, B)` —\n * the `(Comp, A)` relation is automatically removed.\n * - **Same base component, same target**: Re-setting the same relation target\n * simply updates the component value (no extra removal overhead).\n * - **Different exclusive components**: Independent — `exclusive` on `CompA` does\n * not affect relations using `CompB`.\n *\n * The removal happens **during `world.sync()`**, as part of the command buffer\n * processing, so it respects the same deferred execution model as other structural\n * changes.\n *\n * ## Use cases\n *\n * - **Ownership**: An entity can only be owned by one parent at a time\n * (`ChildOf` with `exclusive: true`).\n * - **Equipment slots**: An item can only be in one slot at a time\n * (`EquippedBy` with `exclusive: true`).\n * - **Targeting**: An AI agent can only track one target at a time\n * (`Targeting` with `exclusive: true`).\n * - **State machines**: An entity can only have one active state from a set\n * (`ActiveState` with `exclusive: true`).\n *\n * ## Interaction with other options\n *\n * - **`cascadeDelete`**: Compatible. When an exclusive relation uses\n * `cascadeDelete`, deleting the target entity will both (a) delete the\n * referencing entity, and (b) the exclusivity constraint prevents the\n * entity from having multiple cascade-delete relations of the same type.\n * - **`sparse`**: Compatible. Exclusivity is enforced at the data level\n * regardless of whether the archetype is fragmented.\n *\n * @example\n * ```ts\n * // Without exclusive: entity can have multiple ChildOf relations\n * const ChildOf = component();\n * world.set(child, relation(ChildOf, parentA));\n * world.set(child, relation(ChildOf, parentB));\n * world.sync();\n * // child now has TWO ChildOf relations (parentA and parentB)\n * ```\n *\n * @example\n * ```ts\n * // With exclusive: only the last relation survives\n * const ChildOf = component({ exclusive: true });\n * world.set(child, relation(ChildOf, parentA));\n * world.set(child, relation(ChildOf, parentB));\n * world.sync();\n * // child has only (ChildOf, parentB); (ChildOf, parentA) was auto-removed\n * ```\n */\n exclusive?: boolean;\n /**\n * If true, when a relation target entity is deleted, all entities that reference\n * it through this component will also be deleted (cascade delete).\n *\n * Only applicable to entity-relation components.\n *\n * **Important distinction from default cleanup**:\n * By default, the ECS library **always** cleans up relation components that point\n * to a deleted entity — the relation component is removed from the referencing\n * entity, but the referencing entity itself **survives**. When `cascadeDelete` is\n * enabled, the **entire referencing entity** is deleted, not just the relation\n * component. This deletion is transitive: if entity C references entity B (which\n * is cascade-deleted), entity C will also be deleted, and so on.\n *\n * @example\n * // Without cascadeDelete (default behavior):\n * const ChildOf = component(); // no cascadeDelete\n * world.set(child, relation(ChildOf, parent));\n * world.sync();\n * world.delete(parent);\n * world.sync();\n * // child still exists, but the ChildOf relation is cleaned up\n *\n * @example\n * // With cascadeDelete:\n * const ChildOf = component({ cascadeDelete: true });\n * world.set(child, relation(ChildOf, parent));\n * world.sync();\n * world.delete(parent);\n * world.sync();\n * // child is also deleted (entity deleted, not just relation cleaned up)\n */\n cascadeDelete?: boolean;\n /**\n * If true, relations with this component use sparse storage and will not cause\n * archetype fragmentation.\n *\n * **Problem it solves**: By default, each unique relation pair `(component, target)`\n * creates a **separate archetype**. If 100 entities each have a `ChildOf` relation\n * to a different parent, you get 100 archetypes — this is **archetype fragmentation**.\n * Queries that iterate over all entities with a `ChildOf` relation must check all\n * 100 archetypes, which degrades iteration performance and increases memory overhead.\n *\n * **How it works (sparse storage)**: When `sparse` is enabled, the relation's target\n * does **not** contribute to the archetype signature. Entities with different targets\n * for the same relation component share a **single archetype**, and the per-entity\n * target data is stored in a separate side store (historically called\n * `DontFragmentStore`, now `SparseStore`). A wildcard relation marker (`relation(Comp, \"*\")`) is placed\n * in the archetype component list so queries can still discover matching archetypes.\n *\n * **Use cases**:\n * - **Hierarchy/ownership**: `ChildOf` relations where thousands of entities each\n * point to different parent entities.\n * - **Dynamic targeting**: Relations where targets change frequently (e.g., AI\n * targeting, inventory slots) — without `sparse`, each target change would cause\n * an archetype migration, which is expensive.\n * - **High-cardinality relations**: Any relation where the number of unique targets\n * is large compared to the number of entities.\n *\n * **Performance implications**:\n * - **Without `sparse`**: Archetype count grows linearly with unique targets.\n * Each archetype migration (changing a relation target) requires moving the entity's\n * data between component arrays.\n * - **With `sparse`**: Archetype count stays constant regardless of target diversity.\n * Changing a relation target is an O(1) update in the sparse side store.\n * The trade-off is an extra map lookup when accessing the relation data.\n *\n * **Constraints**:\n * - Only applicable to **relation components** (components used with `relation()`).\n * - Wildcard queries (e.g., `relation(Comp, \"*\")`) still work correctly — the\n * archetype carries a wildcard marker so queries can discover it.\n * - Works with `exclusive` and `cascadeDelete` simultaneously.\n *\n * **Backward compatibility**: The legacy key `dontFragment` is still accepted and\n * behaves identically. Prefer `sparse` in new code.\n *\n * @example\n * ```ts\n * // Without sparse: 100 entities with different parents = 100 archetypes\n * const ChildOf = component(); // default: fragmentation happens\n *\n * // With sparse: 100 entities with different parents = 1 archetype\n * const ChildOf = component({ sparse: true });\n *\n * for (let i = 0; i < 100; i++) {\n * const parent = world.new();\n * const child = world.new();\n * world.set(child, Position);\n * world.set(child, relation(ChildOf, parent));\n * }\n * world.sync();\n * // sparse: 1 archetype for all 100 entities\n * // without: 100 archetypes, one per unique parent\n * ```\n *\n * Inspired by Flecs' `DontFragment` trait (now exposed as the clearer `sparse` option).\n */\n sparse?: boolean;\n /**\n * @deprecated Use `sparse: true` instead. This key is kept solely for backward\n * compatibility; `component({ dontFragment: true })` continues to work exactly\n * as before and is equivalent to `sparse: true`.\n */\n dontFragment?: boolean;\n /**\n * Custom merge behavior for repeated `set()` of the same component type on the\n * same entity within a single sync batch.\n *\n * By default, calling `world.set(entity, comp, value)` multiple times for the same\n * entity and component before `world.sync()` simply overwrites the previous value —\n * the last `set()` wins. When `merge` is provided, the values are combined using\n * your function instead.\n *\n * @remarks\n * **Use cases**:\n * - **Accumulation**: Collecting events, tags, or modifiers that multiple systems\n * contribute to within the same frame.\n * - **Composition**: Merging partial updates into a single component value (e.g.,\n * applying multiple `Vec3` deltas to a position).\n * - **Conflict resolution**: Choosing the max/min/latest value when multiple\n * systems want to set the same component.\n *\n * **Scope**: This only affects `set()` calls on the **same entity** with the **same\n * component type** within **one sync batch** (i.e., between `world.sync()` calls).\n * It does NOT merge values across different entities or across sync boundaries.\n *\n * **Relation support**: If the component is used as a relation (via\n * `relation(componentId, target)`), the merge function also applies per-target.\n * `set(entity, relation(Comp, A), v1)` and `set(entity, relation(Comp, A), v2)`\n * will be merged, but `set(entity, relation(Comp, B), v)` is independent.\n *\n * **Idempotency required**: Your merge function should be idempotent — calling it\n * multiple times with the same inputs must produce the same result. The ECS\n * runtime does not guarantee exactly-once `sync()` execution in all scenarios.\n *\n * **Return value**: The function **must return** the merged value. It should not\n * mutate `prev` or `next` in place unless you intentionally want shared mutable\n * state (which is discouraged).\n *\n * @example\n * ```ts\n * // Collect tags from multiple systems in one frame\n * const Tags = component<string[]>({\n * merge: (prev, next) => [...prev, ...next],\n * });\n * ```\n *\n * @example\n * ```ts\n * // Only keep the highest priority value\n * const Alert = component<{ level: number; msg: string }>({\n * merge: (prev, next) => prev.level >= next.level ? prev : next,\n * });\n * ```\n *\n * @example\n * ```ts\n * // Accumulate numeric deltas (e.g., for movement)\n * const Velocity = component<{ x: number; y: number }>({\n * merge: (prev, next) => ({ x: prev.x + next.x, y: prev.y + next.y }),\n * });\n * ```\n */\n merge?: ComponentMerge<T>;\n}\n\n// Array for component names (Component ID range: 1-1023)\nconst componentNames: (string | undefined)[] = new Array(COMPONENT_ID_MAX + 1);\n\n// BitSets for fast component option checks (Component ID range: 1-1023)\nconst exclusiveFlags = new BitSet(COMPONENT_ID_MAX + 1);\nconst cascadeDeleteFlags = new BitSet(COMPONENT_ID_MAX + 1);\nconst sparseFlags = new BitSet(COMPONENT_ID_MAX + 1);\nconst componentMerges: (ComponentMerge<any> | undefined)[] = new Array(COMPONENT_ID_MAX + 1);\n\n/**\n * Allocate a new component ID from the global allocator.\n * @param nameOrOptions Optional name for the component (for serialization/debugging) or options object\n * @returns The allocated component ID\n * @example\n * // Just a name\n * const Position = component<Position>(\"Position\");\n *\n * // With options\n * const ChildOf = component({ exclusive: true, cascadeDelete: true });\n *\n * // With name and options\n * const ChildOf = component({ name: \"ChildOf\", exclusive: true });\n */\nexport function component<T = void>(nameOrOptions?: string | ComponentOptions<T>): ComponentId<T> {\n const id = globalComponentIdAllocator.allocate<T>();\n\n let name: string | undefined;\n let options: ComponentOptions<T> | undefined;\n\n // Parse the parameter\n if (typeof nameOrOptions === \"string\") {\n name = nameOrOptions;\n } else if (typeof nameOrOptions === \"object\" && nameOrOptions !== null) {\n options = nameOrOptions;\n name = options.name;\n }\n\n // Register name if provided\n if (name) {\n if (ComponentIdForNames.has(name)) {\n throw new Error(`Component name \"${name}\" is already registered`);\n }\n\n componentNames[id] = name;\n ComponentIdForNames.set(name, id);\n }\n\n // Register options if provided\n if (options) {\n // Set bitset flags for fast lookup\n if (options.exclusive) exclusiveFlags.set(id);\n if (options.cascadeDelete) cascadeDeleteFlags.set(id);\n // Support both `sparse` (preferred) and the legacy `dontFragment` alias for BC\n if (options.sparse || options.dontFragment) sparseFlags.set(id);\n if (options.merge) componentMerges[id] = options.merge;\n }\n\n return id;\n}\n\n/**\n * Get a component ID by its registered name\n * @param name The component name\n * @returns The component ID if found, undefined otherwise\n */\nexport function getComponentIdByName(name: string): ComponentId<any> | undefined {\n return ComponentIdForNames.get(name);\n}\n\n/** Get a component name by its ID\n * @param id The component ID\n * @returns The component name if found, undefined otherwise\n */\nexport function getComponentNameById(id: ComponentId<any>): string | undefined {\n return componentNames[id];\n}\n\n/**\n * Get component options by its ID\n * @param id The component ID\n * @returns The component options\n */\nexport function getComponentOptions<T = any>(id: ComponentId<T>): ComponentOptions<T> {\n if (!isComponentId(id)) {\n throw new Error(\"Invalid component ID\");\n }\n const hasName = componentNames[id] !== undefined;\n const hasExclusive = exclusiveFlags.has(id);\n const hasCascadeDelete = cascadeDeleteFlags.has(id);\n const hasSparse = sparseFlags.has(id);\n return {\n name: hasName ? componentNames[id] : undefined,\n exclusive: hasExclusive ? true : undefined,\n cascadeDelete: hasCascadeDelete ? true : undefined,\n sparse: hasSparse ? true : undefined,\n // For full backward compatibility with code that inspects options.dontFragment\n dontFragment: hasSparse ? true : undefined,\n merge: componentMerges[id] as ComponentMerge<T> | undefined,\n };\n}\n\nfunction getBaseComponentId(componentType: EntityId<any>): ComponentId<any> | undefined {\n if (isComponentId(componentType)) {\n return componentType;\n }\n\n const decoded = decodeRelationRaw(componentType);\n if (decoded === null) return undefined;\n return isValidComponentId(decoded.componentId) ? (decoded.componentId as ComponentId<any>) : undefined;\n}\n\n/**\n * Get the merge callback for a component type (including relation component types).\n *\n * Looks up the base component's merge function, resolving through relation wrappers.\n * For example, if `ChildOf` has a merge function and you pass `relation(ChildOf, parent)`,\n * the same merge function is returned.\n *\n * @param componentType - A raw component ID or a relation-wrapped component type\n * (e.g., `relation(MyComp, targetEntity)`).\n * @returns The merge callback if one was registered via {@link ComponentOptions.merge},\n * or `undefined` if no merge was configured for the base component.\n */\nexport function getComponentMerge<T = any>(componentType: EntityId<any>): ComponentMerge<T> | undefined {\n const baseComponentId = getBaseComponentId(componentType);\n if (baseComponentId === undefined) return undefined;\n return componentMerges[baseComponentId] as ComponentMerge<T> | undefined;\n}\n\n/**\n * Check if a component was created with `exclusive: true`.\n *\n * This is a fast O(1) bitset lookup that determines whether the component enforces\n * the one-to-one relation constraint — an entity can have at most one relation of\n * this component type, and setting a new relation target automatically removes the\n * previous one.\n *\n * **Note**: This only checks the component's intrinsic property, not whether a\n * specific entity/relation ID is actually an exclusive relation. For checking\n * runtime relation IDs (including wildcards), use {@link isExclusiveRelation}\n * or {@link isExclusiveWildcard}.\n *\n * @param id - The component ID to check. Must be a plain component ID (1–1023),\n * not a relation-wrapped ID.\n * @returns `true` if the component was created with `exclusive: true`.\n *\n * @see {@link ComponentOptions.exclusive} for the full explanation of exclusive\n * relation behavior.\n * @see {@link isExclusiveRelation} for checking specific-target exclusive relations.\n * @see {@link isExclusiveWildcard} for checking wildcard exclusive relations.\n */\nexport function isExclusiveComponent(id: ComponentId<any>): boolean {\n return exclusiveFlags.has(id);\n}\n\n/**\n * Check if a component is marked as cascade delete.\n *\n * When enabled, deleting the target entity of an entity-relation with this\n * component will cause the **entire referencing entity** to be deleted (not\n * just cleanup of the relation component, which happens by default for all\n * relations).\n *\n * @param id The component ID\n * @returns true if the component is cascade delete, false otherwise\n * @see {@link ComponentOptions.cascadeDelete}\n */\nexport function isCascadeDeleteComponent(id: ComponentId<any>): boolean {\n return cascadeDeleteFlags.has(id);\n}\n\n/**\n * Check if a component is marked as `sparse` (sparse storage for relations).\n *\n * When a component has `sparse: true`, relations using it do not cause archetype\n * fragmentation — entities with different relation targets can share the same\n * archetype. This is a fast O(1) bitset lookup. The legacy `dontFragment` key\n * is still accepted and sets the same internal flag.\n *\n * @param id - The component ID to check.\n * @returns `true` if the component was created with `sparse: true` (or the\n * legacy `dontFragment: true`).\n *\n * @see {@link ComponentOptions.sparse} for the full explanation of sparse storage.\n */\nexport function isSparseComponent(id: ComponentId<any>): boolean {\n return sparseFlags.has(id);\n}\n\n/**\n * Generic optimized function to check whether a relation ID's base component\n * has a specific flag in a bitset.\n *\n * Avoids the overhead of `getDetailedIdType` by directly decoding the relation\n * ID and checking: (1) the ID is a valid relation, (2) the component ID is in the\n * valid range, (3) the target satisfies the condition, and (4) the flag bit is set.\n *\n * Used as the fast-path implementation for `isSparseRelation`, `isSparseWildcard`,\n * `isExclusiveRelation`, `isExclusiveWildcard`, and `isCascadeDeleteRelation`.\n *\n * @param id - The entity/relation ID to check.\n * @param flagBitSet - The bitset tracking which component IDs have the flag.\n * @param targetCondition - Predicate on the target ID (e.g., check for wildcard\n * vs. specific entity target).\n * @returns `true` if the relation's base component has the flag and the target\n * condition is met.\n */\nfunction checkRelationFlag(\n id: EntityId<any>,\n flagBitSet: BitSet,\n targetCondition: (targetId: number) => boolean,\n): boolean {\n const decoded = decodeRelationRaw(id);\n if (decoded === null) return false;\n const { componentId, targetId } = decoded;\n return isValidComponentId(componentId) && targetCondition(targetId) && flagBitSet.has(componentId);\n}\n\n/**\n * Check if an ID is a specific (non-wildcard) relation backed by a `sparse`\n * component (i.e. stored in the side sparse store rather than the archetype).\n *\n * This is used in hot paths (archetype resolution, command processing) to determine\n * whether a relation should be excluded from the archetype signature.\n *\n * @param id - The entity/relation ID to check (must be a relation ID, not a plain\n * component ID).\n * @returns `true` if this is a specific-target relation (not wildcard) whose base\n * component was created with `sparse: true` (or legacy `dontFragment: true`).\n *\n * @see {@link isSparseWildcard} for the wildcard variant.\n * @see {@link ComponentOptions.sparse} for the full explanation.\n */\nexport function isSparseRelation(id: EntityId<any>): boolean {\n return checkRelationFlag(id, sparseFlags, (targetId) => targetId !== WILDCARD_TARGET_ID);\n}\n\n/**\n * Check if an ID is a wildcard relation (`relation(Comp, \"*\")`) backed by a\n * `sparse` component.\n *\n * Wildcard markers for sparse components are placed in the archetype component\n * list so that queries can discover archetypes containing entities with that\n * relation type.\n *\n * @param id - The entity/relation ID to check.\n * @returns `true` if this is a wildcard relation (`\"*\"` target) whose base\n * component was created with `sparse: true` (or legacy `dontFragment: true`).\n *\n * @see {@link isSparseRelation} for the specific-target variant.\n * @see {@link ComponentOptions.sparse} for the full explanation.\n */\nexport function isSparseWildcard(id: EntityId<any>): boolean {\n return checkRelationFlag(id, sparseFlags, (targetId) => targetId === WILDCARD_TARGET_ID);\n}\n\n/**\n * Check if an ID is a specific (non-wildcard) relation backed by an `exclusive`\n * component.\n *\n * This is used in hot paths (command buffer processing, relation management) to\n * determine whether setting this relation should trigger automatic removal of\n * other relations with the same base component on the same entity.\n *\n * This is an optimized function that avoids the overhead of `getDetailedIdType`\n * by directly decoding and checking the relation's component ID against the\n * `exclusive` bitset.\n *\n * @param id - The entity/relation ID to check (must be a relation ID, not a plain\n * component ID).\n * @returns `true` if this is a specific-target relation (not wildcard) whose base\n * component was created with `exclusive: true`.\n *\n * @see {@link isExclusiveWildcard} for the wildcard variant.\n * @see {@link ComponentOptions.exclusive} for the full explanation of exclusive\n * relation behavior.\n */\nexport function isExclusiveRelation(id: EntityId<any>): boolean {\n return checkRelationFlag(id, exclusiveFlags, (targetId) => targetId !== WILDCARD_TARGET_ID);\n}\n\n/**\n * Check if an ID is a wildcard relation (`relation(Comp, \"*\")`) backed by an\n * `exclusive` component.\n *\n * Wildcard markers for exclusive components are used to detect that an archetype\n * may contain exclusive relations, so the runtime can apply exclusivity enforcement\n * when processing relation commands.\n *\n * This is an optimized function that avoids the overhead of `getDetailedIdType`\n * by directly decoding and checking the relation's component ID against the\n * `exclusive` bitset.\n *\n * @param id - The entity/relation ID to check.\n * @returns `true` if this is a wildcard relation (`\"*\"` target) whose base\n * component was created with `exclusive: true`.\n *\n * @see {@link isExclusiveRelation} for the specific-target variant.\n * @see {@link ComponentOptions.exclusive} for the full explanation of exclusive\n * relation behavior.\n */\nexport function isExclusiveWildcard(id: EntityId<any>): boolean {\n return checkRelationFlag(id, exclusiveFlags, (targetId) => targetId === WILDCARD_TARGET_ID);\n}\n\n/**\n * Check if a relation ID is a cascade delete entity-relation.\n *\n * This is an optimized function that avoids the overhead of getDetailedIdType.\n *\n * Cascade delete only applies to entity-relations (not component-relations or\n * wildcards). When a cascade-delete-marked relation's target entity is deleted,\n * the **entire source entity** (the one holding the relation) is deleted — not\n * just the relation component. Without cascade delete, the relation component\n * is simply removed (which is the default cleanup for all relations when their\n * target is deleted).\n *\n * @param id The entity/relation ID to check\n * @returns true if this is an entity-relation with cascade delete, false otherwise\n * @see {@link ComponentOptions.cascadeDelete}\n */\nexport function isCascadeDeleteRelation(id: EntityId<any>): boolean {\n return checkRelationFlag(\n id,\n cascadeDeleteFlags,\n (targetId) => targetId !== WILDCARD_TARGET_ID && targetId >= ENTITY_ID_START,\n );\n}\n","import type { ComponentId, EntityId } from \"../entity\";\nimport { relation } from \"../entity\";\nimport type { World } from \"./world\";\n\n// =============================================================================\n// EntityBuilder - Fluent Entity Creation (moved from testing utilities)\n// =============================================================================\n\n/**\n * A component definition for entity building, supporting both regular components and relations\n */\nexport type ComponentDef<T = unknown> =\n | { type: \"component\"; id: EntityId<T>; value: T }\n | { type: \"relation\"; componentId: ComponentId<T>; targetId: EntityId<any>; value: T };\n\n/**\n * Fluent API for constructing entities with multiple components.\n * Create instances via {@link World.spawn}.\n *\n * @example\n * const entity = world.spawn()\n * .with(Position, { x: 0, y: 0 })\n * .withRelation(Parent, parentEntity)\n * .build();\n * world.sync();\n */\nexport class EntityBuilder {\n private world: World;\n private components: ComponentDef[] = [];\n\n constructor(world: World) {\n this.world = world;\n }\n\n /**\n * Add a regular component to the entity under construction.\n *\n * @template T - The component data type\n * @param componentId - The component type to add\n * @param args - Component data (omit for void components)\n * @returns This builder for chaining\n *\n * @example\n * builder.with(Position, { x: 10, y: 20 });\n * builder.with(Marker); // void component\n */\n with<T extends void>(componentId: EntityId<T>): this;\n with<T>(componentId: EntityId<T>, value: T): this;\n with<T>(componentId: EntityId<T>, value?: T): this {\n this.components.push({ type: \"component\", id: componentId, value: value as T });\n return this;\n }\n\n /**\n * Add a relation component to the entity under construction.\n *\n * @template T - The relation data type\n * @param componentId - The base component type for the relation\n * @param targetEntity - The target entity or component for the relation\n * @param args - Relation data (omit for void relations)\n * @returns This builder for chaining\n *\n * @example\n * builder.withRelation(Parent, parentEntity);\n * builder.withRelation(ChildOf, childEntity, { order: 1 });\n */\n withRelation<T extends void>(componentId: ComponentId<T>, targetEntity: EntityId<any>): this;\n withRelation<T>(componentId: ComponentId<T>, targetEntity: EntityId<any>, value: T): this;\n withRelation<T>(componentId: ComponentId<T>, targetEntity: EntityId<any>, value?: T): this {\n this.components.push({ type: \"relation\", componentId, targetId: targetEntity, value: value as T });\n return this;\n }\n\n /**\n * Create the entity and enqueue all configured components.\n * The entity and components are only materialised after {@link World.sync} is called.\n *\n * @returns The newly created entity ID\n *\n * @example\n * const entity = world.spawn()\n * .with(Position, { x: 0, y: 0 })\n * .build();\n * world.sync(); // Apply changes\n */\n build(): EntityId {\n const entity = this.world.new();\n\n for (const def of this.components) {\n if (def.type === \"component\") {\n this.world.set(entity, def.id, def.value as any);\n } else {\n const relationId = relation(def.componentId, def.targetId);\n this.world.set(entity, relationId, def.value as any);\n }\n }\n\n return entity;\n }\n}\n","import type { EntityId } from \"../entity\";\n\n/**\n * Normalize component type collections into a stable ascending order.\n * This keeps cache keys and archetype signatures deterministic.\n */\nexport function normalizeComponentTypes(componentTypes: Iterable<EntityId<any>>): EntityId<any>[] {\n return [...componentTypes].sort((a, b) => a - b);\n}\n","import type { EntityId, WildcardRelationId } from \"../entity\";\nimport type { QueryFilter } from \"../query/filter\";\n\n/**\n * Type-erased component ID, used for runtime container storage\n * @internal\n */\nexport type AnyComponentId = EntityId<any>;\n\n/**\n * Type-erased entity ID, used for runtime container storage\n * @internal\n */\nexport type AnyEntityId = EntityId<any>;\n\n/**\n * Lifecycle hook definition for reacting to component additions, updates, and removals.\n * Register hooks with {@link World.hook}.\n */\nexport interface LifecycleHook<T extends readonly ComponentType<any>[]> {\n /**\n * Called once for each entity that already matches the hook's component types\n * when the hook is first registered, and then for every new matching entity.\n */\n on_init?: (entityId: EntityId, ...components: ComponentTuple<T>) => void;\n /**\n * Called whenever a matching entity's component data is updated via `set()`.\n */\n on_set?: (entityId: EntityId, ...components: ComponentTuple<T>) => void;\n /**\n * Called whenever a matching entity loses one of the required components\n * or is deleted.\n */\n on_remove?: (entityId: EntityId, ...components: ComponentTuple<T>) => void;\n}\n\n/**\n * Shorthand callback style for multi-component lifecycle hooks.\n * The same function receives all three events distinguished by the `type` parameter.\n *\n * @example\n * world.hook([Position, Velocity], (type, entityId, position, velocity) => {\n * if (type === \"init\") console.log(\"spawned\");\n * if (type === \"set\") console.log(\"updated\");\n * if (type === \"remove\") console.log(\"despawned\");\n * });\n */\nexport type LifecycleCallback<T extends readonly ComponentType<any>[]> = (\n type: \"init\" | \"set\" | \"remove\",\n entityId: EntityId,\n ...components: ComponentTuple<T>\n) => void;\n\n/**\n * A component type used in queries and hooks.\n * Can be a plain {@link EntityId} or an {@link OptionalEntityId} wrapped with `.optional`.\n */\nexport type ComponentType<T> = EntityId<T> | OptionalEntityId<T>;\n\n/**\n * Wrapper that marks a component as optional in queries and hooks.\n * When a component is optional, entities missing it are still included in results.\n *\n * @example\n * world.createQuery([Position, { optional: Velocity }]);\n */\nexport type OptionalEntityId<T> = { optional: EntityId<T> };\n\nexport function isOptionalEntityId<T>(type: ComponentType<T>): type is OptionalEntityId<T> {\n return typeof type === \"object\" && type !== null && \"optional\" in type;\n}\n\nexport type ComponentTypeToData<T> = T extends { optional: infer U }\n ? { value: ComponentTypeToData<U> } | undefined\n : T extends WildcardRelationId<infer U>\n ? [EntityId<unknown>, U][]\n : T extends EntityId<infer U>\n ? U\n : never;\n\n/**\n * Maps an array of {@link ComponentType} to their corresponding data tuples.\n * Used by {@link World.query} and {@link Query.forEach} to type component results.\n */\nexport type ComponentTuple<T extends readonly ComponentType<any>[]> = {\n readonly [K in keyof T]: ComponentTypeToData<T[K]>;\n};\n\nexport interface LifecycleHookEntry {\n componentTypes: readonly ComponentType<any>[];\n requiredComponents: EntityId<any>[];\n optionalComponents: EntityId<any>[];\n filter: QueryFilter;\n hook: LifecycleHook<any>;\n /** Raw callback function; takes precedence over hook.on_* when present */\n callback?: LifecycleCallback<any>;\n /** Archetypes that match this hook, used for precise cleanup on unsubscription */\n matchedArchetypes?: Set<any>;\n}\n\n/**\n * Statistics payload delivered to callbacks registered via `World.createDebugStatsCollector`.\n *\n * All structural counts are snapshots taken after the sync that triggered delivery.\n * `activity` always reflects work performed during that specific sync.\n *\n * Timestamps are raw `performance.now()` values suitable for `performance.measure`.\n */\nexport interface SyncDebugStats {\n readonly timestamps: {\n readonly syncStart: number;\n readonly syncEnd: number;\n readonly commandBufferStart: number;\n readonly commandBufferEnd: number;\n };\n\n /** Number of iterations the internal command buffer loop performed during this sync. */\n readonly commandIterations: number;\n\n readonly entities: {\n readonly total: number;\n readonly freelistSize: number;\n readonly nextId: number;\n };\n\n readonly archetypes: {\n readonly total: number;\n readonly empty: number;\n };\n\n readonly queries: {\n readonly cached: number;\n readonly registered: number;\n };\n\n readonly hooks: {\n readonly total: number;\n };\n\n /** Sizes of stable internal reverse indices (conservative set). */\n readonly indices: {\n readonly entityReferences: number;\n readonly entityToReferencingArchetypes: number;\n readonly archetypesByComponent: number;\n };\n\n /**\n * Activity that occurred as a direct result of this sync.\n * All fields are always present (never optional).\n */\n readonly activity: {\n /** Number of entities that performed an archetype migration (hasArchetypeStructuralChange was true). */\n readonly migrations: number;\n /** Total number of individual hook callback invocations (invokeHook calls). */\n readonly hooksExecuted: number;\n /** Number of new archetypes created during this sync. */\n readonly archetypesCreated: number;\n /** Number of archetypes removed during this sync. */\n readonly archetypesRemoved: number;\n };\n}\n\n/**\n * Handle returned by `World.createDebugStatsCollector`.\n * The object itself carries no data — its only responsibility is lifetime management.\n * Use with `using` or call `[Symbol.dispose]()` when you no longer need collection.\n */\nexport interface DebugStatsCollector {\n [Symbol.dispose](): void;\n}\n","/**\n * Utility functions for ECS library\n */\n\n/**\n * Get a value from cache or compute and cache it if not present\n * @param cache The cache map\n * @param key The cache key\n * @param compute Function to compute the value if not cached (may have side effects)\n * @returns The cached or computed value\n */\nexport function getOrCompute<K, V>(cache: Map<K, V>, key: K, compute: () => V): V {\n let value = cache.get(key);\n if (value === undefined) {\n value = compute();\n cache.set(key, value);\n }\n return value;\n}\n","import type { ComponentId, EntityId, WildcardRelationId } from \"../entity\";\nimport {\n getComponentIdFromRelationId,\n getDetailedIdType,\n getIdType,\n getTargetIdFromRelationId,\n isRelationId,\n} from \"../entity\";\nimport { isOptionalEntityId, type ComponentType } from \"../types\";\nimport { MISSING_COMPONENT } from \"./archetype\";\nimport type { SparseStore } from \"./store\";\n\ntype DetailedIdType = ReturnType<typeof getDetailedIdType>;\n\ntype RelationDetailedType =\n | { type: \"entity-relation\"; componentId: ComponentId<any>; targetId: EntityId<any> }\n | { type: \"component-relation\"; componentId: ComponentId<any>; targetId: ComponentId<any> };\n\n/**\n * Find all wildcard relations matching a specific component ID from a components map\n * @param components - Component entity's components map\n * @param wildcardComponentId - The component ID to match (relation part)\n * @returns Array of matching relation IDs\n */\nexport function findWildcardRelations(components: Map<EntityId, any>, wildcardComponentId: EntityId): EntityId<any>[] {\n const result: EntityId<any>[] = [];\n for (const [relId] of components) {\n if (isRelationId(relId)) {\n const decoded = getComponentIdFromRelationId(relId);\n if (decoded === wildcardComponentId) {\n result.push(relId);\n }\n }\n }\n return result;\n}\n\n/**\n * Check if a components map has any wildcard relations matching a component ID\n * @param components - Component entity's components map\n * @param wildcardComponentId - The component ID to match\n * @returns True if at least one matching relation exists\n */\nexport function hasWildcardRelation(components: Map<EntityId, any>, wildcardComponentId: EntityId): boolean {\n for (const relId of components.keys()) {\n if (isRelationId(relId)) {\n const decoded = getComponentIdFromRelationId(relId);\n if (decoded === wildcardComponentId) return true;\n }\n }\n return false;\n}\n\n/**\n * Check if a detailed type represents a relation (entity or component)\n */\nexport function isRelationType(detailedType: DetailedIdType): detailedType is RelationDetailedType {\n return detailedType.type === \"entity-relation\" || detailedType.type === \"component-relation\";\n}\n\n/**\n * Check if a component type matches a given component ID for relations\n */\nexport function matchesRelationComponentId(componentType: EntityId<any>, componentId: EntityId<any>): boolean {\n const detailedType = getDetailedIdType(componentType);\n return isRelationType(detailedType) && detailedType.componentId === componentId;\n}\n\n/**\n * Build cache key for component types\n */\nexport function buildCacheKey(componentTypes: readonly ComponentType<any>[]): string {\n return componentTypes.map((id) => (isOptionalEntityId(id) ? `opt(${id.optional})` : `${id}`)).join(\",\");\n}\n\n/**\n * Get data source for wildcard relations from component types\n */\nexport function getWildcardRelationDataSource(\n componentTypes: EntityId<any>[],\n componentId: EntityId<any>,\n optional: boolean,\n): EntityId<any>[] | undefined {\n const matchingRelations = componentTypes.filter((ct) => matchesRelationComponentId(ct, componentId));\n return optional ? (matchingRelations.length > 0 ? matchingRelations : undefined) : matchingRelations;\n}\n\n/**\n * Build wildcard relation value from matching relations.\n * Receives the SparseStore directly for efficient per-component lookups.\n */\nexport function buildWildcardRelationValue(\n wildcardRelationType: WildcardRelationId<any>,\n matchingRelations: EntityId<any>[] | undefined,\n getDataAtIndex: (relType: EntityId<any>) => any,\n sparseStore: SparseStore,\n entityId: EntityId,\n optional: boolean,\n): any {\n const relations: [EntityId<unknown>, any][] = [];\n const targetComponentId = getComponentIdFromRelationId(wildcardRelationType);\n\n // Add regular archetype relations\n for (const relType of matchingRelations || []) {\n const data = getDataAtIndex(relType);\n const targetId = getTargetIdFromRelationId(relType)!;\n relations.push([targetId, data === MISSING_COMPONENT ? undefined : data]);\n }\n\n // Add sparse relations using the efficient store API (critical for wildcard query performance)\n if (targetComponentId !== undefined) {\n const dfMatches = sparseStore.getRelationsForComponent(entityId, targetComponentId);\n for (const m of dfMatches) {\n relations.push(m);\n }\n }\n\n if (relations.length === 0) {\n if (!optional) {\n const componentId = getComponentIdFromRelationId(wildcardRelationType);\n throw new Error(\n `No matching relations found for mandatory wildcard relation component ${componentId} on entity ${entityId}`,\n );\n }\n return undefined;\n }\n\n return optional ? { value: relations } : relations;\n}\n\n/**\n * Build regular component value from data source\n */\nexport function buildRegularComponentValue(dataSource: any[] | undefined, entityIndex: number, optional: boolean): any {\n if (dataSource === undefined) {\n if (optional) return undefined;\n throw new Error(`Component data not found for mandatory component type`);\n }\n\n const data = dataSource[entityIndex];\n const result = data === MISSING_COMPONENT ? undefined : data;\n return optional ? { value: result } : result;\n}\n\n/**\n * Build a single component value based on its type\n */\nexport function buildSingleComponent(\n compType: ComponentType<any>,\n dataSource: any[] | EntityId<any>[] | undefined,\n entityIndex: number,\n entityId: EntityId,\n getComponentData: (type: EntityId<any>) => any[],\n sparseRelations: SparseStore,\n): any {\n const optional = isOptionalEntityId(compType);\n const actualType = optional ? compType.optional : compType;\n\n if (getIdType(actualType) === \"wildcard-relation\") {\n return buildWildcardRelationValue(\n actualType as WildcardRelationId<any>,\n dataSource as EntityId<any>[] | undefined,\n (relType) => getComponentData(relType)[entityIndex],\n sparseRelations,\n entityId,\n optional,\n );\n } else {\n return buildRegularComponentValue(dataSource as any[] | undefined, entityIndex, optional);\n }\n}\n","import { normalizeComponentTypes } from \"../component/type-utils\";\nimport type { EntityId, WildcardRelationId } from \"../entity\";\nimport {\n getComponentIdFromRelationId,\n getDetailedIdType,\n getIdType,\n isSparseComponent,\n isWildcardRelationId,\n} from \"../entity\";\nimport type { SerializedComponent, SerializedEntity, SerializedEntityId } from \"../storage/serialization\";\nimport { isOptionalEntityId, type ComponentTuple, type ComponentType, type LifecycleHookEntry } from \"../types\";\nimport { getOrCompute } from \"../utils/utils\";\nimport { buildCacheKey, buildSingleComponent, getWildcardRelationDataSource, isRelationType } from \"./helpers\";\nimport type { SparseStore } from \"./store\";\n\n/**\n * Special value to represent missing component data\n */\nexport const MISSING_COMPONENT = Symbol(\"missing component\");\n\n/**\n * Archetype class for ECS architecture\n * Represents a group of entities that share the same set of components\n * Optimized for fast iteration and component access\n */\nexport class Archetype {\n /**\n * The component types that define this archetype\n */\n public readonly componentTypes: EntityId<any>[];\n\n /**\n * Set version of componentTypes for O(1) lookups in hot paths\n */\n public readonly componentTypeSet: ReadonlySet<EntityId<any>>;\n\n /**\n * List of entities in this archetype\n */\n private entities: EntityId[] = [];\n\n /**\n * Component data storage - maps component type to array of component data\n * Each array index corresponds to the entity index in the entities array\n */\n private componentData: Map<EntityId<any>, any[]> = new Map();\n\n /**\n * Reverse mapping from entity to its index in this archetype\n */\n private entityToIndex: Map<EntityId, number> = new Map();\n\n /**\n * SparseStore used for relations declared with `sparse: true`.\n * See store.ts for implementation details.\n */\n private sparseRelations: SparseStore;\n\n /**\n * Multi-hooks that match this archetype\n */\n public readonly matchingMultiHooks: Set<LifecycleHookEntry> = new Set();\n\n /**\n * Cache for pre-computed component data sources to avoid repeated calculations\n */\n private componentDataSourcesCache: Map<string, (any[] | EntityId<any>[] | undefined)[]> = new Map();\n\n constructor(componentTypes: EntityId<any>[], sparseStore: SparseStore) {\n this.componentTypes = normalizeComponentTypes(componentTypes);\n this.componentTypeSet = new Set(this.componentTypes);\n this.sparseRelations = sparseStore;\n\n for (const componentType of this.componentTypes) {\n this.componentData.set(componentType, []);\n }\n }\n\n get size(): number {\n return this.entities.length;\n }\n\n /**\n * Check if the given component types match this archetype\n * @param componentTypes - Component types to check (can be in any order)\n * @returns true if the types match this archetype's component set\n * @note This method handles unsorted input by internally sorting for comparison\n */\n matches(componentTypes: EntityId<any>[]): boolean {\n if (this.componentTypes.length !== componentTypes.length) return false;\n const sortedTypes = normalizeComponentTypes(componentTypes);\n return this.componentTypes.every((type, index) => type === sortedTypes[index]);\n }\n\n addEntity(entityId: EntityId, componentData: Map<EntityId<any>, any>): void {\n if (this.entityToIndex.has(entityId)) {\n throw new Error(`Entity ${entityId} is already in this archetype`);\n }\n\n const index = this.entities.length;\n this.entities.push(entityId);\n this.entityToIndex.set(entityId, index);\n\n // Add component data for regular components\n for (const componentType of this.componentTypes) {\n const data = componentData.get(componentType);\n this.getComponentData(componentType).push(!componentData.has(componentType) ? MISSING_COMPONENT : data);\n }\n\n // Add sparse-stored relations separately\n this.addSparseRelations(entityId, componentData);\n }\n\n private addSparseRelations(entityId: EntityId, componentData: Map<EntityId<any>, any>): void {\n for (const [componentType, data] of componentData) {\n if (this.componentTypeSet.has(componentType)) continue;\n\n const detailedType = getDetailedIdType(componentType);\n if (isRelationType(detailedType) && isSparseComponent(detailedType.componentId!)) {\n this.sparseRelations.setValue(entityId, componentType, data);\n }\n }\n }\n\n getEntity(entityId: EntityId): Map<EntityId<any>, any> | undefined {\n const index = this.entityToIndex.get(entityId);\n if (index === undefined) return undefined;\n\n const entityData = new Map<EntityId<any>, any>();\n\n // Add regular components\n for (const componentType of this.componentTypes) {\n const data = this.getComponentData(componentType)[index];\n entityData.set(componentType, data === MISSING_COMPONENT ? undefined : data);\n }\n\n // Add sparse-stored relations\n const sparseTuples = this.sparseRelations.getAllForEntity(entityId);\n for (const [componentType, data] of sparseTuples) {\n entityData.set(componentType, data);\n }\n\n return entityData;\n }\n\n /**\n * Returns all sparse-stored relations for the given entity.\n * Internal helper used by command processing and tests.\n */\n getEntitySparseRelations(entityId: EntityId): Map<EntityId<any>, any> | undefined {\n const tuples = this.sparseRelations.getAllForEntity(entityId);\n if (tuples.length === 0) return undefined;\n\n const map = new Map<EntityId<any>, any>();\n for (const [relType, data] of tuples) {\n map.set(relType, data);\n }\n return map;\n }\n\n dump(): Array<{ entity: EntityId; components: Map<EntityId<any>, any> }> {\n return this.entities.map((entity, i) => {\n const components = new Map<EntityId<any>, any>();\n\n for (const componentType of this.componentTypes) {\n const data = this.getComponentData(componentType)[i];\n components.set(componentType, data === MISSING_COMPONENT ? undefined : data);\n }\n\n const sparseTuples = this.sparseRelations.getAllForEntity(entity);\n for (const [componentType, data] of sparseTuples) {\n components.set(componentType, data);\n }\n\n return { entity, components };\n });\n }\n\n /**\n * @internal Serialization fast-path.\n *\n * Appends SerializedEntity records directly from the archetype's column storage\n * (componentData arrays) plus sparse relations, avoiding per-entity Map\n * allocation and repeated Array.from(entries()).\n *\n * Component type IDs should be pre-encoded by the caller (once per archetype)\n * and passed in `encodedComponentTypes` (same order and length as this.componentTypes).\n *\n * The provided `encode` function should be the cached variant for best performance\n * on entity IDs and any sparse relation type IDs.\n *\n * `sparseByEntity` is an optional pre-fetched map from a bulk\n * `SparseStore.getAllForEntities` call (further reduces per-entity calls).\n */\n appendSerializedEntities(\n out: SerializedEntity[],\n encode: (id: EntityId<any>) => SerializedEntityId,\n encodedComponentTypes: SerializedEntityId[],\n sparseByEntity?: Map<EntityId, Array<[EntityId<any>, any]>>,\n ): void {\n if (encodedComponentTypes.length !== this.componentTypes.length) {\n throw new Error(\"encodedComponentTypes length must match archetype componentTypes\");\n }\n\n for (let i = 0; i < this.entities.length; i++) {\n const entity = this.entities[i]!;\n\n const components: SerializedComponent[] = [];\n // Regular (non-sparse) components from column arrays\n for (let c = 0; c < this.componentTypes.length; c++) {\n const data = this.getComponentData(this.componentTypes[c]!)[i];\n components.push({\n type: encodedComponentTypes[c]!,\n value: data === MISSING_COMPONENT ? undefined : data,\n });\n }\n\n // Append any sparse relations for this entity (usually small or zero)\n const sparseTuples = sparseByEntity?.get(entity) ?? this.sparseRelations.getAllForEntity(entity);\n for (const [componentType, data] of sparseTuples) {\n components.push({\n type: encode(componentType),\n value: data,\n });\n }\n\n out.push({\n id: encode(entity),\n components,\n });\n }\n }\n\n removeEntity(entityId: EntityId): Map<EntityId<any>, any> | undefined {\n const index = this.entityToIndex.get(entityId);\n if (index === undefined) return undefined;\n\n // Extract component data before removal\n const removedData = new Map<EntityId<any>, any>();\n for (const componentType of this.componentTypes) {\n removedData.set(componentType, this.getComponentData(componentType)[index]);\n }\n\n // Include sparse relations\n const sparseTuples = this.sparseRelations.getAllForEntity(entityId);\n for (const [componentType, data] of sparseTuples) {\n removedData.set(componentType, data);\n }\n this.sparseRelations.deleteEntity(entityId);\n\n this.entityToIndex.delete(entityId);\n\n // Swap-and-pop for O(1) removal\n const lastIndex = this.entities.length - 1;\n if (index !== lastIndex) {\n const lastEntity = this.entities[lastIndex]!;\n this.entities[index] = lastEntity;\n this.entityToIndex.set(lastEntity, index);\n\n for (const componentType of this.componentTypes) {\n const dataArray = this.getComponentData(componentType);\n dataArray[index] = dataArray[lastIndex];\n }\n }\n\n this.entities.pop();\n for (const componentType of this.componentTypes) {\n this.getComponentData(componentType).pop();\n }\n\n return removedData;\n }\n\n exists(entityId: EntityId): boolean {\n return this.entityToIndex.has(entityId);\n }\n\n get<T>(entityId: EntityId, componentType: WildcardRelationId<T>): [EntityId<unknown>, any][];\n get<T>(entityId: EntityId, componentType: EntityId<T>): T;\n get<T>(entityId: EntityId, componentType: EntityId<T> | WildcardRelationId<T>): T | [EntityId<unknown>, any][] {\n const index = this.entityToIndex.get(entityId);\n if (index === undefined) {\n throw new Error(`Entity ${entityId} is not in this archetype`);\n }\n\n if (isWildcardRelationId(componentType)) {\n return this.getWildcardRelations(entityId, index, componentType);\n }\n\n return this.getRegularComponent(entityId, index, componentType);\n }\n\n private getWildcardRelations<T>(\n entityId: EntityId,\n index: number,\n componentType: WildcardRelationId<T>,\n ): [EntityId<unknown>, any][] {\n const componentId = getComponentIdFromRelationId(componentType);\n const relations: [EntityId<unknown>, any][] = [];\n\n // Check regular archetype components\n for (const relType of this.componentTypes) {\n const relDetailed = getDetailedIdType(relType);\n if (isRelationType(relDetailed) && relDetailed.componentId === componentId) {\n const dataArray = this.getComponentData(relType);\n if (dataArray && dataArray[index] !== undefined) {\n const data = dataArray[index];\n relations.push([relDetailed.targetId, data === MISSING_COMPONENT ? undefined : data]);\n }\n }\n }\n\n // Check sparse relations (now uses the efficient per-component path)\n if (componentId !== undefined) {\n const matches = this.sparseRelations.getRelationsForComponent(entityId, componentId);\n for (const m of matches) relations.push(m);\n }\n\n return relations;\n }\n\n private getRegularComponent<T>(entityId: EntityId, index: number, componentType: EntityId<T>): T {\n if (this.componentTypeSet.has(componentType)) {\n const data = this.getComponentData(componentType)[index]!;\n if (data === MISSING_COMPONENT) {\n throw new Error(`Component type ${componentType} not found for entity ${entityId}`);\n }\n return data as T;\n }\n\n const value = this.sparseRelations.getValue(entityId, componentType);\n if (value !== undefined || this.sparseRelations.getAllForEntity(entityId).some(([t]) => t === componentType)) {\n // Note: the extra check above handles the (rare) case where `undefined` is a legitimate stored value.\n // For the common case we just return whatever getValue gave us.\n return this.sparseRelations.getValue(entityId, componentType);\n }\n\n throw new Error(`Component type ${componentType} not found for entity ${entityId}`);\n }\n\n getOptional<T>(entityId: EntityId, componentType: EntityId<T>): { value: T } | undefined {\n const index = this.entityToIndex.get(entityId);\n if (index === undefined) {\n throw new Error(`Entity ${entityId} is not in this archetype`);\n }\n\n if (this.componentTypeSet.has(componentType)) {\n const data = this.getComponentData(componentType)[index]!;\n if (data === MISSING_COMPONENT) return undefined;\n return { value: data as T };\n }\n\n const value = this.sparseRelations.getValue(entityId, componentType);\n // We use getAllForEntity only as a presence check when the value itself might be undefined.\n if (value !== undefined) {\n return { value };\n }\n const all = this.sparseRelations.getAllForEntity(entityId);\n if (all.some(([t]) => t === componentType)) {\n return { value: this.sparseRelations.getValue(entityId, componentType) };\n }\n return undefined;\n }\n\n set<T>(entityId: EntityId, componentType: EntityId<T>, data: T): void {\n const index = this.entityToIndex.get(entityId);\n if (index === undefined) {\n throw new Error(`Entity ${entityId} is not in this archetype`);\n }\n\n if (this.componentData.has(componentType)) {\n this.getComponentData(componentType)[index] = data;\n return;\n }\n\n const detailedType = getDetailedIdType(componentType);\n if (isRelationType(detailedType) && isSparseComponent(detailedType.componentId!)) {\n this.sparseRelations.setValue(entityId, componentType, data);\n return;\n }\n\n throw new Error(`Component type ${componentType} is not in this archetype`);\n }\n\n getEntities(): EntityId[] {\n return this.entities;\n }\n\n getEntityToIndexMap(): Map<EntityId, number> {\n return this.entityToIndex;\n }\n\n getComponentData<T>(componentType: EntityId<T>): T[] {\n const data = this.componentData.get(componentType);\n if (!data) {\n throw new Error(`Component type ${componentType} is not in this archetype`);\n }\n return data;\n }\n\n getOptionalComponentData<T>(componentType: EntityId<T>): T[] | undefined {\n return this.componentData.get(componentType);\n }\n\n private getCachedComponentDataSources<const T extends readonly ComponentType<any>[]>(\n componentTypes: T,\n ): (any[] | EntityId<any>[] | undefined)[] {\n const cacheKey = buildCacheKey(componentTypes);\n return getOrCompute(this.componentDataSourcesCache, cacheKey, () =>\n componentTypes.map((compType) => this.getComponentDataSource(compType)),\n );\n }\n\n private getComponentDataSource(compType: ComponentType<any>): any[] | EntityId<any>[] | undefined {\n const optional = isOptionalEntityId(compType);\n const actualType = optional ? compType.optional : compType;\n const idType = getIdType(actualType);\n\n if (idType === \"wildcard-relation\") {\n const componentId = getComponentIdFromRelationId(actualType)!;\n return getWildcardRelationDataSource(this.componentTypes, componentId, optional);\n }\n\n return optional ? this.getOptionalComponentData(actualType) : this.getComponentData(actualType);\n }\n\n private buildComponentsForIndex<const T extends readonly ComponentType<any>[]>(\n componentTypes: T,\n componentDataSources: (any[] | EntityId<any>[] | undefined)[],\n entityIndex: number,\n entityId: EntityId,\n ): ComponentTuple<T> {\n return componentDataSources.map((dataSource, i) =>\n buildSingleComponent(\n componentTypes[i]!,\n dataSource,\n entityIndex,\n entityId,\n (type) => this.getComponentData(type),\n this.sparseRelations,\n ),\n ) as ComponentTuple<T>;\n }\n\n getEntitiesWithComponents<const T extends readonly ComponentType<any>[]>(\n componentTypes: T,\n ): Array<{ entity: EntityId; components: ComponentTuple<T> }> {\n const result: Array<{ entity: EntityId; components: ComponentTuple<T> }> = [];\n this.appendEntitiesWithComponents(componentTypes, result);\n return result;\n }\n\n appendEntitiesWithComponents<const T extends readonly ComponentType<any>[]>(\n componentTypes: T,\n result: Array<{ entity: EntityId; components: ComponentTuple<T> }>,\n ): void {\n this.forEachWithComponents(componentTypes, (entity, ...components) => {\n result.push({ entity, components });\n });\n }\n\n *iterateWithComponents<const T extends readonly ComponentType<any>[]>(\n componentTypes: T,\n ): IterableIterator<[EntityId, ...ComponentTuple<T>]> {\n const componentDataSources = this.getCachedComponentDataSources(componentTypes);\n\n for (let entityIndex = 0; entityIndex < this.entities.length; entityIndex++) {\n const entity = this.entities[entityIndex]!;\n const components = this.buildComponentsForIndex(componentTypes, componentDataSources, entityIndex, entity);\n yield [entity, ...components];\n }\n }\n\n forEachWithComponents<const T extends readonly ComponentType<any>[]>(\n componentTypes: T,\n callback: (entity: EntityId, ...components: ComponentTuple<T>) => void,\n ): void {\n const componentDataSources = this.getCachedComponentDataSources(componentTypes);\n\n for (let entityIndex = 0; entityIndex < this.entities.length; entityIndex++) {\n const entity = this.entities[entityIndex]!;\n const components = this.buildComponentsForIndex(componentTypes, componentDataSources, entityIndex, entity);\n callback(entity, ...components);\n }\n }\n\n forEach(callback: (entityId: EntityId, components: Map<EntityId<any>, any>) => void): void {\n for (let i = 0; i < this.entities.length; i++) {\n const entity = this.entities[i]!;\n const components = new Map<EntityId<any>, any>();\n for (const componentType of this.componentTypes) {\n const data = this.getComponentData(componentType)[i];\n components.set(componentType, data === MISSING_COMPONENT ? undefined : data);\n }\n\n // Append sparse relations (entity-wide enumeration; acceptable cost for forEach)\n const sparseTuples = this.sparseRelations.getAllForEntity(entity);\n for (const [componentType, data] of sparseTuples) {\n components.set(componentType, data);\n }\n\n callback(entity, components);\n }\n }\n\n hasRelationWithComponentId(componentId: EntityId<any>): boolean {\n // Check regular archetype components\n for (const componentType of this.componentTypes) {\n const detailedType = getDetailedIdType(componentType);\n if (isRelationType(detailedType) && detailedType.componentId === componentId) {\n return true;\n }\n }\n\n // Check sparse relations only for entities that actually belong to *this* archetype.\n // We must not use the global hasAnyForComponent here, otherwise unrelated archetypes\n // can be incorrectly pulled into wildcard queries when any entity in the world has the relation.\n for (const entityId of this.entities) {\n const rels = this.sparseRelations.getRelationsForComponent(entityId, componentId);\n if (rels.length > 0) {\n return true;\n }\n }\n return false;\n }\n}\n","import type { EntityId } from \"../entity\";\nimport { getComponentIdFromRelationId, getTargetIdFromRelationId } from \"../entity\";\n\n/**\n * Internal representation for the relations an entity has under one component kind.\n * 'single' is the optimized form for exclusive relations (vast majority of cases).\n */\ntype RelationEntry =\n | { type: \"single\"; relationType: EntityId<any>; target: EntityId; data: any }\n | { type: \"multi\"; targets: Map<EntityId, { relationType: EntityId<any>; data: any }> };\n\n/**\n * Interface for the sparse side store used by components declared with `sparse: true`\n * (or the legacy `dontFragment: true` alias).\n *\n * Relation data for these components lives here instead of in archetype columns,\n * preventing fragmentation for high-cardinality or frequently-changing relations.\n *\n * Storage is primarily keyed by base relation ComponentId. This enables efficient\n * per-component lookups required by wildcard queries (relation(Comp, \"*\")) and\n * archetype filtering, while still supporting full-entity enumeration when needed.\n */\nexport interface SparseStore {\n // High-frequency per-(entity, relation) operations (get/set/has/remove, structural changes)\n getValue(entityId: EntityId, relationType: EntityId<any>): any | undefined;\n setValue(entityId: EntityId, relationType: EntityId<any>, data: any): void;\n deleteValue(entityId: EntityId, relationType: EntityId<any>): boolean;\n\n // Hot paths for wildcard queries and archetype filtering (per-component lookups)\n hasAnyForComponent(componentId: EntityId<any>): boolean;\n getRelationsForComponent(entityId: EntityId, componentId: EntityId<any>): [target: EntityId, data: any][];\n\n // Entity-wide enumeration paths (used for snapshots, serialization, forEach, and rare presence checks)\n getAllForEntity(entityId: EntityId): Array<[relationType: EntityId<any>, data: any]>;\n deleteEntity(entityId: EntityId): void;\n\n /**\n * @internal Bulk helper for serialization of many entities.\n * Default implementation simply loops getAllForEntity; subclasses / future\n * implementations can provide a more efficient fused walk.\n */\n getAllForEntities(entityIds: readonly EntityId[]): Map<EntityId, Array<[EntityId<any>, any]>>;\n}\n\n/**\n * Production implementation of SparseStore.\n *\n * Internal layout (optimized):\n * - byComponent: baseComponentId → (entityId → RelationEntry)\n * RelationEntry uses a single-value form for the common exclusive case (1 target),\n * avoiding Map allocation for the vast majority of usage.\n * - entityIndex: entityId → Set<baseComponentId>\n * Lightweight reverse index.\n */\nexport class SparseStoreImpl implements SparseStore {\n /**\n * Primary storage, keyed by the base relation component ID.\n */\n private byComponent = new Map<\n EntityId<any>, // base componentId\n Map<EntityId, RelationEntry>\n >();\n\n /**\n * Reverse index: which base component kinds an entity participates in.\n * Only required to support getAllForEntity and deleteEntity efficiently.\n * The primary storage (byComponent) is deliberately not optimized for these operations.\n */\n private entityIndex = new Map<EntityId, Set<EntityId<any>>>();\n\n getValue(entityId: EntityId, relationType: EntityId<any>): any | undefined {\n const componentId = getComponentIdFromRelationId(relationType);\n if (componentId === undefined) return undefined;\n\n const entities = this.byComponent.get(componentId);\n if (!entities) return undefined;\n\n const entry = entities.get(entityId);\n if (!entry) return undefined;\n\n const targetId = getTargetIdFromRelationId(relationType)!;\n\n if (entry.type === \"single\") {\n return entry.target === targetId ? entry.data : undefined;\n } else {\n const item = entry.targets.get(targetId);\n return item ? item.data : undefined;\n }\n }\n\n setValue(entityId: EntityId, relationType: EntityId<any>, data: any): void {\n const componentId = getComponentIdFromRelationId(relationType);\n if (componentId === undefined) {\n throw new Error(\"setValue called with a non-relation type on SparseStore\");\n }\n\n let entities = this.byComponent.get(componentId);\n if (!entities) {\n entities = new Map();\n this.byComponent.set(componentId, entities);\n }\n\n const targetId = getTargetIdFromRelationId(relationType)!;\n let entry = entities.get(entityId);\n\n if (!entry) {\n // First relation for this (entity, component) — use single form (big win for exclusive)\n entry = { type: \"single\", relationType, target: targetId, data };\n entities.set(entityId, entry);\n } else if (entry.type === \"single\") {\n if (entry.target === targetId) {\n entry.data = data;\n entry.relationType = relationType; // update in case it changed\n } else {\n // Promote to multi\n const targets = new Map();\n targets.set(entry.target, { relationType: entry.relationType, data: entry.data });\n targets.set(targetId, { relationType, data });\n entities.set(entityId, { type: \"multi\", targets });\n }\n } else {\n entry.targets.set(targetId, { relationType, data });\n }\n\n // Maintain reverse index\n let components = this.entityIndex.get(entityId);\n if (!components) {\n components = new Set();\n this.entityIndex.set(entityId, components);\n }\n components.add(componentId);\n }\n\n deleteValue(entityId: EntityId, relationType: EntityId<any>): boolean {\n const componentId = getComponentIdFromRelationId(relationType);\n if (componentId === undefined) return false;\n\n const entities = this.byComponent.get(componentId);\n if (!entities) return false;\n\n const entry = entities.get(entityId);\n if (!entry) return false;\n\n const targetId = getTargetIdFromRelationId(relationType)!;\n let existed = false;\n\n if (entry.type === \"single\") {\n if (entry.target === targetId) {\n existed = true;\n entities.delete(entityId);\n }\n } else {\n existed = entry.targets.delete(targetId);\n if (entry.targets.size === 0) {\n entities.delete(entityId);\n } else if (entry.targets.size === 1) {\n // Demote to single\n const [first] = entry.targets.entries();\n const [t, item] = first!;\n entities.set(entityId, { type: \"single\", relationType: item.relationType, target: t, data: item.data });\n }\n }\n\n if (!entities.has(entityId) && entities.size === 0) {\n this.byComponent.delete(componentId);\n }\n\n // Update reverse index\n const components = this.entityIndex.get(entityId);\n if (components && !entities.has(entityId)) {\n components.delete(componentId);\n if (components.size === 0) {\n this.entityIndex.delete(entityId);\n }\n }\n\n return existed;\n }\n\n hasAnyForComponent(componentId: EntityId<any>): boolean {\n const entities = this.byComponent.get(componentId);\n return entities !== undefined && entities.size > 0;\n }\n\n getRelationsForComponent(entityId: EntityId, componentId: EntityId<any>): [EntityId, any][] {\n const result: [EntityId, any][] = [];\n\n const entities = this.byComponent.get(componentId);\n if (!entities) return result;\n\n const entry = entities.get(entityId);\n if (!entry) return result;\n\n if (entry.type === \"single\") {\n result.push([entry.target, entry.data]);\n } else {\n for (const [target, item] of entry.targets) {\n result.push([target, item.data]);\n }\n }\n\n return result;\n }\n\n getAllForEntity(entityId: EntityId): Array<[relationType: EntityId<any>, data: any]> {\n const components = this.entityIndex.get(entityId);\n if (!components || components.size === 0) return [];\n\n const result: Array<[EntityId<any>, any]> = [];\n\n for (const componentId of components) {\n const entities = this.byComponent.get(componentId);\n const entry = entities?.get(entityId);\n if (entry) {\n if (entry.type === \"single\") {\n result.push([entry.relationType, entry.data]);\n } else {\n for (const item of entry.targets.values()) {\n result.push([item.relationType, item.data]);\n }\n }\n }\n }\n\n return result;\n }\n\n deleteEntity(entityId: EntityId): void {\n const components = this.entityIndex.get(entityId);\n if (!components) return;\n\n for (const componentId of components) {\n const entities = this.byComponent.get(componentId);\n if (entities) {\n entities.delete(entityId);\n if (entities.size === 0) {\n this.byComponent.delete(componentId);\n }\n }\n }\n\n this.entityIndex.delete(entityId);\n }\n\n getAllForEntities(entityIds: readonly EntityId[]): Map<EntityId, Array<[EntityId<any>, any]>> {\n const result = new Map<EntityId, Array<[EntityId<any>, any]>>();\n for (const eid of entityIds) {\n const data = this.getAllForEntity(eid);\n if (data.length > 0) {\n result.set(eid, data);\n }\n }\n return result;\n }\n}\n","import type { EntityId } from \"../entity\";\n\n/**\n * Maximum number of command buffer execution iterations to prevent infinite loops\n */\nconst MAX_COMMAND_ITERATIONS = 100;\n\n/**\n * Command for deferred execution\n * Uses discriminated union for type safety\n */\nexport type Command =\n | { type: \"set\"; entityId: EntityId; componentType: EntityId<any>; component: any }\n | { type: \"delete\"; entityId: EntityId; componentType: EntityId<any> }\n | { type: \"destroy\"; entityId: EntityId };\n\n/**\n * Command buffer for deferred structural changes\n */\nexport class CommandBuffer {\n private commands: Command[] = [];\n private swapBuffer: Command[] = [];\n /** Reusable map to group commands by entity, avoids per-sync allocations */\n private entityCommands: Map<EntityId, Command[]> = new Map();\n private executeEntityCommands: (entityId: EntityId, commands: Command[]) => void;\n\n /**\n * Create a command buffer with an executor function\n */\n constructor(executeEntityCommands: (entityId: EntityId, commands: Command[]) => void) {\n this.executeEntityCommands = executeEntityCommands;\n }\n\n /**\n * Add a component to an entity (deferred)\n */\n set(entityId: EntityId, componentType: EntityId<void>): void;\n set<T>(entityId: EntityId, componentType: EntityId<T>, component: NoInfer<T>): void;\n set(entityId: EntityId, componentType: EntityId, component?: any): void {\n this.commands.push({ type: \"set\", entityId, componentType, component });\n }\n\n /**\n * Remove a component from an entity (deferred)\n */\n remove<T>(entityId: EntityId, componentType: EntityId<T>): void {\n this.commands.push({ type: \"delete\", entityId, componentType });\n }\n\n /**\n * Destroy an entity (deferred)\n */\n delete(entityId: EntityId): void {\n this.commands.push({ type: \"destroy\", entityId });\n }\n\n /**\n * Execute all commands and clear the buffer.\n * Returns the number of iterations performed (for debug stats).\n */\n execute(): number {\n let iterations = 0;\n\n while (this.commands.length > 0) {\n if (iterations >= MAX_COMMAND_ITERATIONS) {\n throw new Error(\"Command execution exceeded maximum iterations, possible infinite loop\");\n }\n iterations++;\n\n // Swap buffers to avoid allocation\n const currentCommands = this.commands;\n this.commands = this.swapBuffer;\n\n // Group commands by entity, reusing the persistent Map\n const entityCommands = this.entityCommands;\n for (const cmd of currentCommands) {\n const existing = entityCommands.get(cmd.entityId);\n if (existing !== undefined) {\n existing.push(cmd);\n } else {\n entityCommands.set(cmd.entityId, [cmd]);\n }\n }\n\n // Clear the consumed buffer for reuse\n currentCommands.length = 0;\n this.swapBuffer = currentCommands;\n\n // Process each entity's commands and clear the map (but not the arrays,\n // as callers may hold references to them after the executor returns)\n for (const [entityId, commands] of entityCommands) {\n this.executeEntityCommands(entityId, commands);\n }\n entityCommands.clear();\n }\n\n return iterations;\n }\n\n /**\n * Get current commands (for testing)\n */\n getCommands(): Command[] {\n return [...this.commands];\n }\n\n /**\n * Clear all commands\n */\n clear(): void {\n this.commands = [];\n }\n}\n","import type { EntityId } from \"../entity\";\n\n/**\n * @internal Represents a set of component changes to be applied to an entity\n */\nexport class ComponentChangeset {\n readonly adds = new Map<EntityId<any>, any>();\n readonly removes = new Set<EntityId<any>>();\n\n /**\n * Add a component to the changeset\n */\n set<T>(componentType: EntityId<T>, component: T): void {\n this.adds.set(componentType, component);\n this.removes.delete(componentType); // Remove from removes if it was going to be removed\n }\n\n /**\n * Remove a component from the changeset\n */\n delete<T>(componentType: EntityId<T>): void {\n this.removes.add(componentType);\n this.adds.delete(componentType); // Remove from adds if it was going to be added\n }\n\n /**\n * Check if the changeset has any changes\n */\n hasChanges(): boolean {\n return this.adds.size > 0 || this.removes.size > 0;\n }\n\n /**\n * Clear all changes\n */\n clear(): void {\n this.adds.clear();\n this.removes.clear();\n }\n\n /**\n * Merge another changeset into this one\n */\n merge(other: ComponentChangeset): void {\n // Merge additions\n for (const [componentType, component] of other.adds) {\n this.adds.set(componentType, component);\n this.removes.delete(componentType);\n }\n // Merge removals\n for (const componentType of other.removes) {\n this.removes.add(componentType);\n this.adds.delete(componentType);\n }\n }\n\n /**\n * Apply the changeset to existing components and return the final state\n */\n applyTo(existingComponents: Map<EntityId<any>, any>): Map<EntityId<any>, any> {\n // Apply removals\n for (const componentType of this.removes) {\n existingComponents.delete(componentType);\n }\n\n // Apply additions/updates\n for (const [componentType, component] of this.adds) {\n existingComponents.set(componentType, component);\n }\n\n return existingComponents;\n }\n}\n","import { hasWildcardRelation } from \"../archetype/helpers\";\nimport type { Command } from \"../commands/buffer\";\nimport {\n getComponentIdFromRelationId,\n getComponentMerge,\n getDetailedIdType,\n isWildcardRelationId,\n type ComponentId,\n type EntityId,\n type WildcardRelationId,\n} from \"../entity\";\n\n/**\n * Manages component entity (singleton) storage.\n *\n * Component entities use a flat Map-based storage rather than the Archetype-based\n * storage used for regular entities. Their IDs are in the component ID range\n * (or are relation IDs), distinguishing them from regular entity IDs.\n */\nexport class ComponentEntityStore {\n private readonly componentEntityComponents: Map<EntityId, Map<EntityId<any>, any>> = new Map();\n private readonly relationEntityIdsByTarget: Map<EntityId, Set<EntityId>> = new Map();\n\n /**\n * Check if an entity ID is a component entity type.\n * Returns true for component IDs, component-relation IDs, and entity-relation IDs —\n * i.e. anything that is NOT a plain entity or an invalid ID.\n */\n exists(entityId: EntityId): boolean {\n const detailed = getDetailedIdType(entityId);\n return detailed.type !== \"entity\" && detailed.type !== \"invalid\";\n }\n\n /**\n * Check if a component entity has a specific component.\n */\n has(entityId: EntityId, componentType: EntityId<any>): boolean {\n return this.componentEntityComponents.get(entityId)?.has(componentType) ?? false;\n }\n\n /**\n * Check if a singleton component has data — the has(componentId) overload.\n * In singleton usage the entity ID and the component type are the same value.\n */\n hasSingleton(componentId: EntityId<any>): boolean {\n return this.componentEntityComponents.get(componentId)?.has(componentId) ?? false;\n }\n\n /**\n * Check if a component entity has any wildcard relations matching a component ID.\n */\n hasWildcard(entityId: EntityId, componentId: ComponentId<any>): boolean {\n const data = this.componentEntityComponents.get(entityId);\n if (!data) return false;\n return hasWildcardRelation(data, componentId);\n }\n\n /**\n * Get a component value from a component entity.\n * Throws if the component does not exist.\n */\n get<T>(entityId: EntityId, componentType: EntityId<T>): T {\n const data = this.componentEntityComponents.get(entityId);\n if (!data || !data.has(componentType)) {\n throw new Error(\n `Entity ${entityId} does not have component ${componentType}. Use has() to check component existence before calling get().`,\n );\n }\n return data.get(componentType) as T;\n }\n\n /**\n * Get an optional component value from a component entity.\n * Returns undefined if the component does not exist.\n */\n getOptional<T>(entityId: EntityId, componentType: EntityId<T>): { value: T } | undefined {\n const data = this.componentEntityComponents.get(entityId);\n if (!data || !data.has(componentType)) return undefined;\n return { value: data.get(componentType) as T };\n }\n\n /**\n * Get all wildcard relations of a given type from a component entity.\n */\n getWildcard<T>(entityId: EntityId, wildcardComponentType: WildcardRelationId<T>): [EntityId<unknown>, T][] {\n const componentId = getComponentIdFromRelationId(wildcardComponentType);\n const data = this.componentEntityComponents.get(entityId);\n if (componentId === undefined || !data) return [];\n\n const relations: [EntityId<unknown>, T][] = [];\n for (const [key, value] of data.entries()) {\n if (getComponentIdFromRelationId(key) !== componentId) continue;\n const detailed = getDetailedIdType(key);\n if (detailed.type === \"entity-relation\" || detailed.type === \"component-relation\") {\n relations.push([detailed.targetId, value as T]);\n }\n }\n return relations;\n }\n\n /**\n * Clear all data for a component entity.\n */\n clear(entityId: EntityId): void {\n if (this.componentEntityComponents.delete(entityId)) {\n this.unregisterRelationEntityId(entityId);\n }\n }\n\n /**\n * Cleanup all component entities that reference a given target entity.\n * Called when a target entity is destroyed.\n */\n cleanupReferencesTo(targetId: EntityId): void {\n const relationEntities = this.relationEntityIdsByTarget.get(targetId);\n if (!relationEntities) return;\n for (const relationEntityId of relationEntities) {\n this.componentEntityComponents.delete(relationEntityId);\n }\n this.relationEntityIdsByTarget.delete(targetId);\n }\n\n /**\n * Execute a batch of commands for a component entity.\n */\n executeCommands(entityId: EntityId, commands: Command[]): void {\n if (commands.some((cmd) => cmd.type === \"destroy\")) {\n this.clear(entityId);\n return;\n }\n\n const pendingSetValues = new Map<EntityId<any>, any>();\n\n for (const command of commands) {\n if (command.type === \"set\" && command.componentType) {\n const merge = getComponentMerge(command.componentType);\n let nextValue = command.component;\n if (merge !== undefined && pendingSetValues.has(command.componentType)) {\n const prevValue = pendingSetValues.get(command.componentType);\n nextValue = merge(prevValue, command.component);\n }\n pendingSetValues.set(command.componentType, nextValue);\n\n let data = this.componentEntityComponents.get(entityId);\n if (!data) {\n data = new Map();\n this.componentEntityComponents.set(entityId, data);\n this.registerRelationEntityId(entityId);\n }\n data.set(command.componentType, nextValue);\n } else if (command.type === \"delete\" && command.componentType) {\n const data = this.componentEntityComponents.get(entityId);\n\n if (isWildcardRelationId(command.componentType)) {\n const componentId = getComponentIdFromRelationId(command.componentType);\n if (componentId !== undefined) {\n if (data) {\n for (const key of Array.from(data.keys())) {\n if (getComponentIdFromRelationId(key) === componentId) {\n data.delete(key);\n }\n }\n }\n for (const key of Array.from(pendingSetValues.keys())) {\n if (getComponentIdFromRelationId(key) === componentId) {\n pendingSetValues.delete(key);\n }\n }\n }\n } else {\n data?.delete(command.componentType);\n pendingSetValues.delete(command.componentType);\n }\n\n if (data?.size === 0) {\n this.clear(entityId);\n }\n }\n }\n }\n\n /**\n * Initialize a component entity from a deserialization snapshot.\n */\n initFromSnapshot(entityId: EntityId, componentMap: Map<EntityId<any>, any>): void {\n this.componentEntityComponents.set(entityId, componentMap);\n this.registerRelationEntityId(entityId);\n }\n\n /**\n * Iterate over all component entity entries.\n * Used for serialization.\n */\n entries(): IterableIterator<[EntityId, Map<EntityId<any>, any>]> {\n return this.componentEntityComponents.entries();\n }\n\n private registerRelationEntityId(entityId: EntityId): void {\n const detailed = getDetailedIdType(entityId);\n if (detailed.type !== \"entity-relation\") return;\n const targetId = detailed.targetId;\n if (targetId === undefined) return;\n const existing = this.relationEntityIdsByTarget.get(targetId);\n if (existing) {\n existing.add(entityId);\n return;\n }\n this.relationEntityIdsByTarget.set(targetId, new Set([entityId]));\n }\n\n private unregisterRelationEntityId(entityId: EntityId): void {\n const detailed = getDetailedIdType(entityId);\n if (detailed.type !== \"entity-relation\") return;\n const targetId = detailed.targetId;\n if (targetId === undefined) return;\n const existing = this.relationEntityIdsByTarget.get(targetId);\n if (!existing) return;\n existing.delete(entityId);\n if (existing.size === 0) {\n this.relationEntityIdsByTarget.delete(targetId);\n }\n }\n}\n","import type { Archetype } from \"../archetype/archetype\";\nimport type { EntityId } from \"../entity\";\nimport { getComponentIdFromRelationId, getDetailedIdType, isRelationId, isSparseComponent, relation } from \"../entity\";\n\n/**\n * Filter options for queries\n */\nexport interface QueryFilter {\n negativeComponentTypes?: EntityId<any>[];\n}\n\n/**\n * Serialize a QueryFilter into a deterministic string suitable for cache keys.\n * Currently only serializes `negativeComponentTypes`.\n */\nexport function serializeQueryFilter(filter: QueryFilter = {}): string {\n const negative = (filter.negativeComponentTypes || []).slice().sort((a, b) => a - b);\n if (negative.length === 0) return \"\";\n return `neg:${negative.join(\",\")}`;\n}\n\n/**\n * Check if an archetype matches the given component types\n */\nexport function matchesComponentTypes(archetype: Archetype, componentTypes: EntityId<any>[]): boolean {\n return componentTypes.every((type) => {\n const detailedType = getDetailedIdType(type);\n if (detailedType.type === \"wildcard-relation\") {\n // For wildcard relations, check if archetype contains the component relation\n return archetype.componentTypes.some((archetypeType) => {\n if (!isRelationId(archetypeType)) return false;\n const componentId = getComponentIdFromRelationId(archetypeType);\n return componentId === detailedType.componentId;\n });\n } else if (\n (detailedType.type === \"entity-relation\" || detailedType.type === \"component-relation\") &&\n detailedType.componentId !== undefined &&\n isSparseComponent(detailedType.componentId)\n ) {\n // For specific sparse relations, check if archetype has the wildcard marker\n const wildcardMarker = relation(detailedType.componentId, \"*\");\n return archetype.componentTypeSet.has(wildcardMarker);\n } else {\n // For regular components and non-sparse relations, check direct inclusion\n return archetype.componentTypeSet.has(type);\n }\n });\n}\n\n/**\n * Check if an archetype matches the filter conditions (only filtering logic)\n */\nexport function matchesFilter(archetype: Archetype, filter: QueryFilter): boolean {\n const negativeTypes = filter.negativeComponentTypes || [];\n return negativeTypes.every((type) => {\n const detailedType = getDetailedIdType(type);\n if (detailedType.type === \"wildcard-relation\") {\n // For wildcard relations in negative filter, exclude archetypes that contain ANY relation with the same component\n return !archetype.componentTypes.some((archetypeType) => {\n if (!isRelationId(archetypeType)) return false;\n const componentId = getComponentIdFromRelationId(archetypeType);\n return componentId === detailedType.componentId;\n });\n } else {\n // For regular components, check direct exclusion\n return !archetype.componentTypeSet.has(type);\n }\n });\n}\n","import type { Archetype } from \"../archetype/archetype\";\nimport { normalizeComponentTypes } from \"../component/type-utils\";\nimport type { EntityId, WildcardRelationId } from \"../entity\";\nimport { getDetailedIdType, isSparseComponent } from \"../entity\";\nimport type { ComponentTuple, ComponentType } from \"../types\";\nimport type { World } from \"../world/world\";\nimport { matchesComponentTypes, matchesFilter, type QueryFilter } from \"./filter\";\nimport type { QueryRegistry } from \"./registry\";\n\n/**\n * Cached query for efficiently iterating entities with specific components.\n *\n * Queries are created via {@link World.createQuery} and should be **reused across frames**\n * for optimal performance. The world automatically keeps the query's internal archetype cache\n * up to date as entities are created and destroyed.\n *\n * @example\n * const movementQuery = world.createQuery([Position, Velocity]);\n *\n * // In the game loop\n * movementQuery.forEach([Position, Velocity], (entity, pos, vel) => {\n * pos.x += vel.x;\n * pos.y += vel.y;\n * });\n */\nexport class Query {\n private world: World;\n private componentTypes: EntityId<any>[];\n private filter: QueryFilter;\n private cachedArchetypes: Archetype[] = [];\n private isDisposed = false;\n /** Cache key assigned by World for O(1) releaseQuery lookup */\n _cacheKey: string | undefined;\n /** Cached wildcard component types for faster entity filtering */\n private wildcardTypes: WildcardRelationId<any>[];\n /** Cached specific sparse relation types that need entity-level filtering */\n private specificSparseRelationTypes: EntityId<any>[];\n\n /**\n * @internal Queries should be created via {@link World.createQuery}, not instantiated directly.\n */\n constructor(world: World, componentTypes: EntityId<any>[], filter: QueryFilter = {}, registry?: QueryRegistry) {\n this.world = world;\n this.componentTypes = normalizeComponentTypes(componentTypes);\n this.filter = filter;\n // Pre-compute wildcard types once\n this.wildcardTypes = this.componentTypes.filter(\n (ct) => getDetailedIdType(ct).type === \"wildcard-relation\",\n ) as WildcardRelationId<any>[];\n // Pre-compute specific sparse relation types that need entity-level filtering\n this.specificSparseRelationTypes = this.componentTypes.filter((ct) => {\n const detailedType = getDetailedIdType(ct);\n return (\n (detailedType.type === \"entity-relation\" || detailedType.type === \"component-relation\") &&\n detailedType.componentId !== undefined &&\n isSparseComponent(detailedType.componentId)\n );\n });\n this.updateCache();\n // Register with registry for archetype updates\n if (registry) {\n registry.register(this);\n }\n }\n\n /**\n * Check if query is disposed and throw error if so\n */\n private ensureNotDisposed(): void {\n if (this.isDisposed) {\n throw new Error(\"Query has been disposed\");\n }\n }\n\n /**\n * Returns all entity IDs that match this query.\n *\n * @returns Array of matching entity IDs\n *\n * @example\n * const entities = query.getEntities();\n * for (const entity of entities) {\n * const pos = world.get(entity, Position);\n * }\n */\n getEntities(): EntityId[] {\n this.ensureNotDisposed();\n\n // Fast path: no wildcard relations and no specific sparse relations\n if (this.wildcardTypes.length === 0 && this.specificSparseRelationTypes.length === 0) {\n const result: EntityId[] = [];\n for (const archetype of this.cachedArchetypes) {\n for (const entity of archetype.getEntities()) {\n result.push(entity);\n }\n }\n return result;\n }\n\n // Slow path: need to filter entities that actually have the required relations\n // This is necessary for:\n // 1. Wildcard relations where an archetype can contain entities with/without the relation\n // 2. Specific sparse relations where the archetype only has the wildcard marker\n const result: EntityId[] = [];\n for (const archetype of this.cachedArchetypes) {\n for (const entity of archetype.getEntities()) {\n if (this.entityMatchesQuery(archetype, entity)) {\n result.push(entity);\n }\n }\n }\n return result;\n }\n\n /**\n * Check if entity matches all query requirements (wildcards and specific sparse relations)\n */\n private entityMatchesQuery(archetype: Archetype, entity: EntityId): boolean {\n // Check wildcard relations\n for (const wildcardType of this.wildcardTypes) {\n const relations = archetype.get(entity, wildcardType);\n if (!relations || relations.length === 0) {\n return false;\n }\n }\n\n // Check specific sparse relations\n for (const specificType of this.specificSparseRelationTypes) {\n const result = archetype.getOptional(entity, specificType);\n if (result === undefined) {\n return false;\n }\n }\n\n return true;\n }\n\n /**\n * Returns all matching entities along with their component data.\n *\n * @param componentTypes - Array of component types to retrieve\n * @returns Array of objects containing the entity ID and its component tuple\n *\n * @example\n * const results = query.getEntitiesWithComponents([Position, Velocity]);\n * results.forEach(({ entity, components: [pos, vel] }) => {\n * pos.x += vel.x;\n * });\n */\n getEntitiesWithComponents<const T extends readonly ComponentType<any>[]>(\n componentTypes: T,\n ): Array<{\n entity: EntityId;\n components: ComponentTuple<T>;\n }> {\n this.ensureNotDisposed();\n\n const result: Array<{\n entity: EntityId;\n components: ComponentTuple<T>;\n }> = [];\n\n for (const archetype of this.cachedArchetypes) {\n archetype.appendEntitiesWithComponents(componentTypes, result);\n }\n\n return result;\n }\n\n /**\n * Iterates over all matching entities and invokes the callback with their component data.\n * This is the preferred way to read and mutate components in a hot loop.\n *\n * @param componentTypes - Array of component types to retrieve\n * @param callback - Function called for each matching entity with its components\n *\n * @example\n * query.forEach([Position, Velocity], (entity, pos, vel) => {\n * pos.x += vel.x;\n * pos.y += vel.y;\n * });\n */\n forEach<const T extends readonly ComponentType<any>[]>(\n componentTypes: T,\n callback: (entity: EntityId, ...components: ComponentTuple<T>) => void,\n ): void {\n this.ensureNotDisposed();\n\n for (const archetype of this.cachedArchetypes) {\n archetype.forEachWithComponents(componentTypes, callback);\n }\n }\n\n /**\n * Generator that yields each matching entity together with its component data.\n *\n * @param componentTypes - Array of component types to retrieve\n * @yields Tuples of `[entityId, ...components]`\n *\n * @example\n * for (const [entity, pos, vel] of query.iterate([Position, Velocity])) {\n * pos.x += vel.x;\n * }\n */\n *iterate<const T extends readonly ComponentType<any>[]>(\n componentTypes: T,\n ): IterableIterator<[EntityId, ...ComponentTuple<T>]> {\n this.ensureNotDisposed();\n\n for (const archetype of this.cachedArchetypes) {\n yield* archetype.iterateWithComponents(componentTypes);\n }\n }\n\n /**\n * Returns an array containing the data of a single component for every matching entity.\n *\n * @param componentType - The component type to retrieve\n * @returns Array of component data (one entry per matching entity)\n *\n * @example\n * const positions = query.getComponentData(Position);\n */\n getComponentData<T>(componentType: EntityId<T>): T[] {\n this.ensureNotDisposed();\n\n const result: T[] = [];\n for (const archetype of this.cachedArchetypes) {\n for (const data of archetype.getComponentData(componentType)) {\n result.push(data);\n }\n }\n return result;\n }\n\n /**\n * @internal Rebuilds the cached archetype list. Called automatically by the world.\n */\n updateCache(): void {\n if (this.isDisposed) return;\n\n this.cachedArchetypes = this.world\n .getMatchingArchetypes(this.componentTypes)\n .filter((archetype: Archetype) => matchesFilter(archetype, this.filter));\n }\n\n /**\n * @internal Called by the world when a new archetype is created.\n */\n checkNewArchetype(archetype: Archetype): void {\n if (this.isDisposed) return;\n if (\n matchesComponentTypes(archetype, this.componentTypes) &&\n matchesFilter(archetype, this.filter) &&\n !this.cachedArchetypes.includes(archetype)\n ) {\n this.cachedArchetypes.push(archetype);\n }\n }\n\n /**\n * @internal Called by the world when an archetype is destroyed.\n */\n removeArchetype(archetype: Archetype): void {\n if (this.isDisposed) return;\n const index = this.cachedArchetypes.indexOf(archetype);\n if (index !== -1) {\n this.cachedArchetypes.splice(index, 1);\n }\n }\n\n /**\n * Request disposal of this query.\n * This will decrement the world's reference count for the query.\n * The query will only be fully disposed when the ref count reaches zero.\n */\n dispose(): void {\n // Ask the world to release this query (decrement refcount and fully dispose when zero)\n this.world.releaseQuery(this);\n }\n\n /**\n * @internal Fully disposes the query when the world's refCount reaches zero.\n */\n _disposeInternal(registry?: QueryRegistry): void {\n if (!this.isDisposed) {\n // Unregister from registry (remove from notification list)\n if (registry) {\n registry.unregister(this);\n }\n this.cachedArchetypes = [];\n this.isDisposed = true;\n }\n }\n\n /**\n * Using-with-disposals support. Calls {@link dispose} automatically.\n *\n * @example\n * using query = world.createQuery([Position]);\n * // query is released automatically when the block exits\n */\n [Symbol.dispose](): void {\n this.dispose();\n }\n\n /**\n * Whether the query has been disposed and can no longer be used.\n */\n get disposed(): boolean {\n return this.isDisposed;\n }\n}\n","import type { Archetype } from \"../archetype/archetype\";\nimport type { EntityId } from \"../entity\";\nimport type { QueryFilter } from \"../query/filter\";\nimport { Query } from \"../query/query\";\nimport type { World } from \"../world/world\";\n\n/**\n * Manages the lifecycle and caching of `Query` instances.\n *\n * Responsibilities:\n * - Create / reuse cached queries keyed by component-type + filter signature.\n * - Track reference counts so queries are only disposed when truly unused.\n * - Notify registered queries when new archetypes are created or destroyed.\n *\n * The `_cacheKey` string that was previously attached directly to `Query` is now\n * kept in a private `WeakMap` so the `Query` class doesn't need to expose it.\n */\nexport class QueryRegistry {\n /** All live queries that should receive archetype notifications. */\n private readonly queries = new Set<Query>();\n /** Cache of reusable queries keyed by a deterministic signature string. */\n private readonly cache = new Map<string, { query: Query; refCount: number }>();\n /** Maps each query to its cache key without polluting the Query public API. */\n private readonly cacheKeys = new WeakMap<Query, string>();\n\n /**\n * Returns (or creates) a cached query for the given component types and filter.\n * Increments the reference count on cache hits.\n *\n * @param world The world that owns this registry.\n * @param sortedTypes Normalized (sorted) component types.\n * @param key Combined cache key (`types|filter`).\n * @param filter The raw query filter (used when creating a new Query).\n */\n getOrCreate(world: World, sortedTypes: EntityId<any>[], key: string, filter: QueryFilter): Query {\n const cached = this.cache.get(key);\n if (cached) {\n cached.refCount++;\n return cached.query;\n }\n\n const query = new Query(world, sortedTypes, filter, this);\n this.cacheKeys.set(query, key);\n this.cache.set(key, { query, refCount: 1 });\n return query;\n }\n\n /**\n * Decrements the reference count for the given query.\n * When the count reaches zero the query is fully disposed.\n */\n release(query: Query): void {\n const key = this.cacheKeys.get(query);\n if (!key) return;\n\n const cached = this.cache.get(key);\n if (!cached || cached.query !== query) return;\n\n cached.refCount--;\n if (cached.refCount <= 0) {\n this.cache.delete(key);\n cached.query._disposeInternal(this);\n }\n }\n\n /**\n * Registers a query so it receives future archetype notifications.\n * Called automatically by the `Query` constructor via `world._registerQuery`.\n */\n register(query: Query): void {\n this.queries.add(query);\n }\n\n /**\n * Removes a query from the notification list.\n * Called by `Query._disposeInternal` via `world._unregisterQuery`.\n */\n unregister(query: Query): void {\n this.queries.delete(query);\n }\n\n /**\n * Notifies all live queries that a new archetype has been created.\n * Queries will add the archetype to their cache if it matches.\n */\n onNewArchetype(archetype: Archetype): void {\n for (const query of this.queries) {\n query.checkNewArchetype(archetype);\n }\n }\n\n /**\n * Notifies all live queries that an archetype has been destroyed.\n * Queries will remove the archetype from their internal cache.\n */\n onArchetypeRemoved(archetype: Archetype): void {\n for (const query of this.queries) {\n query.removeArchetype(archetype);\n }\n }\n}\n","import type { Archetype } from \"../archetype/archetype\";\nimport type { SparseStore } from \"../archetype/store\";\nimport type { Command } from \"../commands/buffer\";\nimport type { ComponentChangeset } from \"../commands/changeset\";\nimport { normalizeComponentTypes } from \"../component/type-utils\";\nimport {\n getComponentIdFromRelationId,\n getComponentMerge,\n isSparseComponent,\n isSparseRelation,\n isSparseWildcard,\n isWildcardRelationId,\n relation,\n type ComponentId,\n type EntityId,\n} from \"../entity\";\n\nexport interface CommandProcessorContext {\n sparseStore: SparseStore;\n ensureArchetype: (componentTypes: Iterable<EntityId<any>>) => Archetype;\n}\n\nexport function processCommands(\n entityId: EntityId,\n currentArchetype: Archetype,\n commands: Command[],\n changeset: ComponentChangeset,\n handleExclusiveRelation: (entityId: EntityId, archetype: Archetype, componentId: ComponentId<any>) => void,\n): void {\n for (const command of commands) {\n if (command.type === \"set\") {\n // TypeScript knows command.componentType and command.component exist\n processSetCommand(\n entityId,\n currentArchetype,\n command.componentType,\n command.component,\n changeset,\n handleExclusiveRelation,\n );\n } else if (command.type === \"delete\") {\n // TypeScript knows command.componentType exists\n processDeleteCommand(entityId, currentArchetype, command.componentType, changeset);\n }\n }\n}\n\nfunction processSetCommand(\n entityId: EntityId,\n currentArchetype: Archetype,\n componentType: EntityId<any>,\n component: any,\n changeset: ComponentChangeset,\n handleExclusiveRelation: (entityId: EntityId, archetype: Archetype, componentId: ComponentId<any>) => void,\n): void {\n // Extract componentId if it's a relation (fast path)\n const componentId = getComponentIdFromRelationId(componentType);\n if (componentId !== undefined) {\n // Handle exclusive relations by removing existing relations with the same base component\n handleExclusiveRelation(entityId, currentArchetype, componentId);\n\n // For sparse relations, ensure wildcard marker is in archetype signature\n if (isSparseComponent(componentId)) {\n const wildcardMarker = relation(componentId, \"*\");\n // Add wildcard marker to changeset if not already in archetype\n if (!currentArchetype.componentTypeSet.has(wildcardMarker)) {\n changeset.set(wildcardMarker, undefined);\n }\n }\n }\n\n const merge = getComponentMerge(componentType);\n if (merge !== undefined && changeset.adds.has(componentType)) {\n const prev = changeset.adds.get(componentType);\n changeset.set(componentType, merge(prev, component));\n return;\n }\n\n changeset.set(componentType, component);\n}\n\nfunction processDeleteCommand(\n entityId: EntityId,\n currentArchetype: Archetype,\n componentType: EntityId<any>,\n changeset: ComponentChangeset,\n): void {\n const componentId = getComponentIdFromRelationId(componentType);\n\n if (isWildcardRelationId(componentType) && componentId !== undefined) {\n removeWildcardRelations(entityId, currentArchetype, componentId, changeset);\n } else {\n changeset.delete(componentType);\n maybeRemoveWildcardMarker(entityId, currentArchetype, componentType, componentId, changeset);\n }\n}\n\nexport function removeMatchingRelations(\n entityId: EntityId,\n archetype: Archetype,\n baseComponentId: ComponentId<any>,\n changeset: ComponentChangeset,\n): void {\n // Check archetype components\n for (const componentType of archetype.componentTypes) {\n // Skip wildcard markers - they should only be removed by maybeRemoveWildcardMarker\n if (isWildcardRelationId(componentType)) continue;\n\n if (getComponentIdFromRelationId(componentType) === baseComponentId) {\n changeset.delete(componentType);\n }\n }\n\n // Check sparse relations stored on entity\n const sparseData = archetype.getEntitySparseRelations(entityId);\n if (sparseData) {\n for (const componentType of sparseData.keys()) {\n if (getComponentIdFromRelationId(componentType) === baseComponentId) {\n changeset.delete(componentType);\n }\n }\n }\n}\n\nfunction removeWildcardRelations(\n entityId: EntityId,\n currentArchetype: Archetype,\n baseComponentId: ComponentId<any>,\n changeset: ComponentChangeset,\n): void {\n removeMatchingRelations(entityId, currentArchetype, baseComponentId, changeset);\n\n // If removing sparse relations, also remove the wildcard marker\n if (isSparseComponent(baseComponentId)) {\n changeset.delete(relation(baseComponentId, \"*\"));\n }\n}\n\nexport function maybeRemoveWildcardMarker(\n entityId: EntityId,\n archetype: Archetype,\n removedComponentType: EntityId<any>,\n componentId: ComponentId<any> | undefined,\n changeset: ComponentChangeset,\n): void {\n if (componentId === undefined || !isSparseComponent(componentId)) {\n return;\n }\n\n const wildcardMarker = relation(componentId, \"*\");\n\n // Check if there are any other relations with the same component ID\n for (const otherComponentType of archetype.componentTypes) {\n if (otherComponentType === removedComponentType) continue;\n if (otherComponentType === wildcardMarker) continue;\n if (changeset.removes.has(otherComponentType)) continue;\n\n if (getComponentIdFromRelationId(otherComponentType) === componentId) {\n return; // Found another relation, keep the marker\n }\n }\n\n const sparseData = archetype.getEntitySparseRelations(entityId);\n if (sparseData) {\n for (const otherComponentType of sparseData.keys()) {\n if (otherComponentType === removedComponentType) continue;\n if (changeset.removes.has(otherComponentType)) continue;\n\n if (getComponentIdFromRelationId(otherComponentType) === componentId) {\n return; // Found another relation, keep the marker\n }\n }\n }\n\n // Also check if this changeset itself is adding another relation of the same kind\n // (common in exclusive sparse flips: remove old target + add new target in one batch)\n for (const addedType of changeset.adds.keys()) {\n if (addedType === removedComponentType) continue;\n if (getComponentIdFromRelationId(addedType) === componentId) {\n return; // Replacement is being added in the same changeset, keep the marker\n }\n }\n\n changeset.delete(wildcardMarker);\n}\n\nfunction hasEntityComponent(archetype: Archetype, entityId: EntityId, componentType: EntityId<any>): boolean {\n if (archetype.componentTypeSet.has(componentType)) {\n return true;\n }\n\n return archetype.getEntitySparseRelations(entityId)?.has(componentType) ?? false;\n}\n\nfunction pruneMissingRemovals(changeset: ComponentChangeset, archetype: Archetype, entityId: EntityId): void {\n // Collect to-prune entries first to avoid mutating the set during iteration\n let toPrune: EntityId<any>[] | undefined;\n for (const componentType of changeset.removes) {\n if (!hasEntityComponent(archetype, entityId, componentType)) {\n if (toPrune === undefined) toPrune = [];\n toPrune.push(componentType);\n }\n }\n if (toPrune !== undefined) {\n for (const componentType of toPrune) {\n changeset.removes.delete(componentType);\n }\n }\n}\n\nfunction hasArchetypeStructuralChange(changeset: ComponentChangeset, currentArchetype: Archetype): boolean {\n for (const componentType of changeset.removes) {\n if (!isSparseRelation(componentType) && currentArchetype.componentTypeSet.has(componentType)) {\n return true;\n }\n }\n\n for (const componentType of changeset.adds.keys()) {\n if (!isSparseRelation(componentType) && !currentArchetype.componentTypeSet.has(componentType)) {\n return true;\n }\n }\n\n return false;\n}\n\nfunction buildFinalRegularComponentTypes(currentArchetype: Archetype, changeset: ComponentChangeset): EntityId<any>[] {\n const finalRegularTypes = new Set(currentArchetype.componentTypes);\n\n for (const componentType of changeset.removes) {\n if (!isSparseRelation(componentType)) {\n finalRegularTypes.delete(componentType);\n }\n }\n\n for (const [componentType] of changeset.adds) {\n if (!isSparseRelation(componentType)) {\n finalRegularTypes.add(componentType);\n }\n }\n\n return Array.from(finalRegularTypes);\n}\n\nexport function applyChangeset(\n ctx: CommandProcessorContext,\n entityId: EntityId,\n currentArchetype: Archetype,\n changeset: ComponentChangeset,\n entityToArchetype: Map<EntityId, Archetype>,\n removedComponents: Map<EntityId<any>, any> | null,\n): Archetype {\n pruneMissingRemovals(changeset, currentArchetype, entityId);\n const archetypeChanged = hasArchetypeStructuralChange(changeset, currentArchetype);\n\n if (archetypeChanged) {\n const finalRegularTypes = buildFinalRegularComponentTypes(currentArchetype, changeset);\n const newArchetype = ctx.ensureArchetype(finalRegularTypes);\n const currentComponents = currentArchetype.removeEntity(entityId)!;\n\n if (removedComponents !== null) {\n for (const componentType of changeset.removes) {\n removedComponents.set(componentType, currentComponents.get(componentType));\n }\n }\n\n newArchetype.addEntity(entityId, changeset.applyTo(currentComponents));\n entityToArchetype.set(entityId, newArchetype);\n return newArchetype;\n }\n\n // No archetype move needed: only component payload updates and/or sparse relation updates.\n if (removedComponents !== null) {\n applySparseChanges(ctx.sparseStore, entityId, changeset, removedComponents);\n } else {\n applySparseChangesNoHooks(ctx.sparseStore, entityId, changeset);\n }\n\n // Direct update for regular components in archetype\n for (const [componentType, component] of changeset.adds) {\n if (isSparseRelation(componentType)) {\n continue;\n }\n currentArchetype.set(entityId, componentType, component);\n }\n\n return currentArchetype;\n}\n\nfunction applySparseChanges(\n sparseStore: SparseStore,\n entityId: EntityId,\n changeset: ComponentChangeset,\n removedComponents: Map<EntityId<any>, any>,\n): void {\n for (const componentType of changeset.removes) {\n if (isSparseRelation(componentType)) {\n const removedValue = sparseStore.getValue(entityId, componentType);\n // Record for hooks if we are actually removing something\n if (removedValue !== undefined || sparseStore.getAllForEntity(entityId).some(([t]) => t === componentType)) {\n removedComponents.set(componentType, removedValue);\n }\n sparseStore.deleteValue(entityId, componentType);\n }\n }\n\n for (const [componentType, component] of changeset.adds) {\n if (isSparseRelation(componentType)) {\n sparseStore.setValue(entityId, componentType, component);\n }\n }\n}\n\nfunction applySparseChangesNoHooks(sparseStore: SparseStore, entityId: EntityId, changeset: ComponentChangeset): void {\n for (const componentType of changeset.removes) {\n if (isSparseRelation(componentType)) {\n sparseStore.deleteValue(entityId, componentType);\n }\n }\n\n for (const [componentType, component] of changeset.adds) {\n if (isSparseRelation(componentType)) {\n sparseStore.setValue(entityId, componentType, component);\n }\n }\n}\n\nexport function filterRegularComponentTypes(componentTypes: Iterable<EntityId<any>>): EntityId<any>[] {\n const regularTypes: EntityId<any>[] = [];\n\n for (const componentType of componentTypes) {\n // Keep wildcard markers for sparse components (they mark the archetype)\n if (isSparseWildcard(componentType)) {\n regularTypes.push(componentType);\n continue;\n }\n\n // Skip specific sparse relations from archetype signature\n if (isSparseRelation(componentType)) {\n continue;\n }\n\n regularTypes.push(componentType);\n }\n\n return regularTypes;\n}\n\nexport function areComponentTypesEqual(types1: EntityId<any>[], types2: EntityId<any>[]): boolean {\n if (types1.length !== types2.length) return false;\n const sorted1 = normalizeComponentTypes(types1);\n const sorted2 = normalizeComponentTypes(types2);\n return sorted1.every((v, i) => v === sorted2[i]);\n}\n","import type { Archetype } from \"../archetype/archetype\";\nimport {\n getComponentIdFromRelationId,\n getTargetIdFromRelationId,\n isWildcardRelationId,\n type EntityId,\n} from \"../entity\";\nimport { isOptionalEntityId, type ComponentType, type LifecycleHookEntry } from \"../types\";\n\n/**\n * Debug-only counter incremented on every invokeHook call when armed.\n * World reads and resets this during armed syncs.\n */\nexport const debugHookExecutionCounter = { value: 0 };\n\n/**\n * Unified hook invocation: prefers entry.callback (callback style) over hook.on_* (object style).\n */\nfunction invokeHook(\n entry: LifecycleHookEntry,\n event: \"init\" | \"set\" | \"remove\",\n entityId: EntityId,\n components: any[],\n): void {\n debugHookExecutionCounter.value++;\n\n if (entry.callback) {\n entry.callback(event as any, entityId, ...components);\n return;\n }\n const hook = entry.hook;\n if (event === \"init\") hook.on_init?.(entityId, ...components);\n else if (event === \"set\") hook.on_set?.(entityId, ...components);\n else hook.on_remove?.(entityId, ...components);\n}\n\n/**\n * Check if a component change matches a hook component type.\n * Handles wildcard-relation matching: if hookComponent is a wildcard relation (e.g., relation(A, \"*\")),\n * it matches any concrete relation with the same component ID (e.g., relation(A, entity1)).\n */\nfunction componentMatchesHookType(changedComponent: EntityId<any>, hookComponent: EntityId<any>): boolean {\n if (changedComponent === hookComponent) return true;\n\n // Check if hookComponent is a wildcard relation and changedComponent is a matching relation\n if (isWildcardRelationId(hookComponent)) {\n const hookComponentId = getComponentIdFromRelationId(hookComponent);\n const changedComponentId = getComponentIdFromRelationId(changedComponent);\n if (hookComponentId !== undefined && changedComponentId !== undefined) {\n return hookComponentId === changedComponentId;\n }\n }\n\n return false;\n}\n\n/**\n * Check if any component in the changes map matches a hook component type.\n */\nfunction anyComponentMatches(changes: Map<EntityId<any>, any>, hookComponent: EntityId<any>): boolean {\n for (const changedComponent of changes.keys()) {\n if (componentMatchesHookType(changedComponent, hookComponent)) {\n return true;\n }\n }\n return false;\n}\n\n/**\n * Find a matching component in the changes map that matches the hook component type.\n * Returns [componentId, value] if found, undefined otherwise.\n */\nfunction findMatchingComponent(\n changes: Map<EntityId<any>, any>,\n hookComponent: EntityId<any>,\n): [EntityId<any>, any] | undefined {\n for (const [changedComponent, value] of changes.entries()) {\n if (componentMatchesHookType(changedComponent, hookComponent)) {\n return [changedComponent, value];\n }\n }\n return undefined;\n}\n\nexport interface HooksContext {\n multiHooks: Set<LifecycleHookEntry>;\n has: (entityId: EntityId, componentType: EntityId<any>) => boolean;\n get: <T>(entityId: EntityId, componentType: EntityId<T>) => T;\n getOptional: <T>(entityId: EntityId, componentType: EntityId<T>) => { value: T } | undefined;\n}\n\nexport function triggerLifecycleHooks(\n ctx: HooksContext,\n entityId: EntityId,\n addedComponents: Map<EntityId<any>, any>,\n removedComponents: Map<EntityId<any>, any>,\n oldArchetype: Archetype,\n newArchetype: Archetype,\n): void {\n triggerMultiComponentHooks(ctx, entityId, addedComponents, removedComponents, oldArchetype, newArchetype);\n}\n\n/**\n * Fast path for triggering lifecycle hooks when an entity is being deleted.\n * This avoids unnecessary archetype lookups and on_set checks since the entity\n * is being completely removed.\n */\nexport function triggerRemoveHooksForEntityDeletion(\n entityId: EntityId,\n removedComponents: Map<EntityId<any>, any>,\n oldArchetype: Archetype,\n): void {\n if (removedComponents.size === 0) return;\n\n // Trigger multi-component hooks - only on_remove since entity is being deleted\n for (const entry of oldArchetype.matchingMultiHooks) {\n const { requiredComponents, componentTypes } = entry;\n\n // Skip if neither callback-style nor hook-style on_remove is provided\n if (!entry.callback && !entry.hook.on_remove) continue;\n\n // Check if any required component was removed\n const anyRequiredRemoved = requiredComponents.some((c) => anyComponentMatches(removedComponents, c));\n if (!anyRequiredRemoved) continue;\n\n // For entity deletion, we know:\n // 1. All components are being removed, so entity \"had\" all required components\n // 2. Entity will no longer match after deletion\n // Just need to verify the entity actually had all required components before\n const hadAllRequired = requiredComponents.every((c) => anyComponentMatches(removedComponents, c));\n if (!hadAllRequired) continue;\n\n // Collect component values from removedComponents directly (no entity lookup needed)\n const components = collectComponentsFromRemoved(componentTypes, removedComponents);\n invokeHook(entry, \"remove\", entityId, components);\n }\n}\n\nfunction triggerMultiComponentHooks(\n ctx: HooksContext,\n entityId: EntityId,\n addedComponents: Map<EntityId<any>, any>,\n removedComponents: Map<EntityId<any>, any>,\n oldArchetype: Archetype,\n newArchetype: Archetype,\n): void {\n // Handle on_set:\n // 1. Required/optional components changed while entity still matches\n // 2. Entity entered the matching set (e.g. removed a negative filter component)\n for (const entry of newArchetype.matchingMultiHooks) {\n const { requiredComponents, optionalComponents, componentTypes } = entry;\n\n // Skip if neither callback-style nor hook-style on_set is provided\n if (!entry.callback && !entry.hook.on_set) continue;\n\n const anyRequiredAdded = requiredComponents.some((c) => anyComponentMatches(addedComponents, c));\n const anyOptionalAdded = optionalComponents.some((c) => anyComponentMatches(addedComponents, c));\n const anyOptionalRemoved = optionalComponents.some((c) => anyComponentMatches(removedComponents, c));\n const enteredMatchingSet = !oldArchetype.matchingMultiHooks.has(entry);\n const hasRelevantComponentChange = anyRequiredAdded || anyOptionalAdded || anyOptionalRemoved;\n const shouldTriggerSet =\n enteredMatchingSet || (hasRelevantComponentChange && entityHasAllComponents(ctx, entityId, requiredComponents));\n\n if (shouldTriggerSet) {\n const components = collectMultiHookComponents(ctx, entityId, componentTypes);\n invokeHook(entry, \"set\", entityId, components);\n }\n }\n\n // Handle on_remove:\n // 1. Required component removal made the entity stop matching\n // 2. Entity exited the matching set (e.g. added a negative filter component)\n for (const entry of oldArchetype.matchingMultiHooks) {\n const { requiredComponents, componentTypes } = entry;\n\n // Skip if neither callback-style nor hook-style on_remove is provided\n if (!entry.callback && !entry.hook.on_remove) continue;\n\n const anyRequiredRemoved = requiredComponents.some((c) => anyComponentMatches(removedComponents, c));\n const lostRequiredMatch =\n anyRequiredRemoved &&\n entityHadAllComponentsBefore(ctx, entityId, requiredComponents, removedComponents) &&\n !entityHasAllComponents(ctx, entityId, requiredComponents);\n const exitedMatchingSet = !newArchetype.matchingMultiHooks.has(entry);\n const shouldTriggerRemove = lostRequiredMatch || exitedMatchingSet;\n\n if (shouldTriggerRemove) {\n const components = collectMultiHookComponentsWithRemoved(ctx, entityId, componentTypes, removedComponents);\n invokeHook(entry, \"remove\", entityId, components);\n }\n }\n}\n\nfunction entityHasAllComponents(ctx: HooksContext, entityId: EntityId, requiredComponents: EntityId<any>[]): boolean {\n return requiredComponents.every((c) => {\n // For wildcard relations, check if the entity has the wildcard relation data\n if (isWildcardRelationId(c)) {\n const wildcardResult = ctx.getOptional(entityId, c);\n if (!wildcardResult) return false;\n const wildcardData = wildcardResult.value;\n return Array.isArray(wildcardData) && wildcardData.length > 0;\n }\n return ctx.has(entityId, c);\n });\n}\n\nfunction entityHadAllComponentsBefore(\n ctx: HooksContext,\n entityId: EntityId,\n requiredComponents: EntityId<any>[],\n removedComponents: Map<EntityId<any>, any>,\n): boolean {\n return requiredComponents.every((c) => {\n // Check if a matching component was removed\n if (anyComponentMatches(removedComponents, c)) return true;\n\n // For wildcard relations, check if the entity still has matching relations\n if (isWildcardRelationId(c)) {\n const wildcardResult = ctx.getOptional(entityId, c);\n if (!wildcardResult) return false;\n const wildcardData = wildcardResult.value;\n return Array.isArray(wildcardData) && wildcardData.length > 0;\n }\n return ctx.has(entityId, c);\n });\n}\n\nexport function collectMultiHookComponents(\n ctx: HooksContext,\n entityId: EntityId,\n componentTypes: readonly ComponentType<any>[],\n): any[] {\n return componentTypes.map((ct) =>\n isOptionalEntityId(ct) ? ctx.getOptional(entityId, ct.optional) : ctx.get(entityId, ct as EntityId<any>),\n );\n}\n\n/**\n * Reconstructs wildcard relation data by merging current data with removed components.\n * Returns an array of [targetId, value] tuples for the wildcard relation.\n *\n * This is used during \"on_remove\" hook invocation: the removed components have already\n * been taken out of the entity's archetype, but the hook callback expects to see the\n * full data as it existed *before* removal. We reconstruct that snapshot by taking the\n * current wildcard data (post-removal) and adding back the entries that were just removed.\n */\nfunction reconstructWildcardWithRemoved(\n ctx: HooksContext,\n entityId: EntityId,\n wildcardId: EntityId<any>,\n removedComponents: Map<EntityId<any>, any>,\n): [EntityId, any][] {\n // ctx.get() for a wildcard relation ID always returns [EntityId, any][] at runtime\n // (see Archetype.getWildcardRelations / ComponentEntityStore.getWildcard).\n // The HooksContext interface erases the WildcardRelationId overload for simplicity,\n // so we assert the expected shape here rather than silently falling back to [].\n const currentData = ctx.get(entityId, wildcardId);\n if (!Array.isArray(currentData)) {\n throw new Error(\n `Expected wildcard relation data to be an array, but got ${typeof currentData} ` +\n `for entity ${entityId} and wildcard ${wildcardId}. ` +\n `This indicates a HooksContext implementation that does not conform to the expected contract.`,\n );\n }\n\n // Spread-copy the array so that pushing removed entries below does not mutate\n // the archetype's internal storage. Without the copy, we would leak removed\n // component data back into the live entity data.\n const result = [...currentData];\n\n // Re-inject matching relations that were just removed, so the hook callback\n // sees the complete snapshot as it existed before the removal.\n for (const [removedCompId, removedValue] of removedComponents.entries()) {\n // Skip wildcard markers themselves — they encode WILDCARD_TARGET_ID=0 and\n // would produce spurious [0, undefined] entries in the hook callback.\n if (isWildcardRelationId(removedCompId)) continue;\n if (componentMatchesHookType(removedCompId, wildcardId)) {\n const targetId = getTargetIdFromRelationId(removedCompId);\n if (targetId !== undefined) {\n result.push([targetId, removedValue]);\n }\n }\n }\n\n return result;\n}\n\nfunction collectMultiHookComponentsWithRemoved(\n ctx: HooksContext,\n entityId: EntityId,\n componentTypes: readonly ComponentType<any>[],\n removedComponents: Map<EntityId<any>, any>,\n): any[] {\n return componentTypes.map((ct) => {\n if (isOptionalEntityId(ct)) {\n const optionalId = ct.optional;\n\n if (isWildcardRelationId(optionalId)) {\n const result = reconstructWildcardWithRemoved(ctx, entityId, optionalId, removedComponents);\n return result.length > 0 ? { value: result } : undefined;\n }\n\n const match = findMatchingComponent(removedComponents, optionalId);\n return match ? { value: match[1] } : ctx.getOptional(entityId, optionalId);\n }\n\n const compId = ct as EntityId<any>;\n\n if (isWildcardRelationId(compId)) {\n return reconstructWildcardWithRemoved(ctx, entityId, compId, removedComponents);\n }\n\n const match = findMatchingComponent(removedComponents, compId);\n return match ? match[1] : ctx.get(entityId, compId);\n });\n}\n\n/**\n * Collect component values directly from removedComponents map.\n * Used for entity deletion fast path where the entity no longer exists.\n */\nfunction collectComponentsFromRemoved(\n componentTypes: readonly ComponentType<any>[],\n removedComponents: Map<EntityId<any>, any>,\n): any[] {\n return componentTypes.map((ct) => {\n if (isOptionalEntityId(ct)) {\n const optionalId = ct.optional;\n\n if (isWildcardRelationId(optionalId)) {\n const result = collectWildcardFromRemoved(optionalId, removedComponents);\n return result.length > 0 ? { value: result } : undefined;\n }\n\n const match = findMatchingComponent(removedComponents, optionalId);\n return match ? { value: match[1] } : undefined;\n }\n\n const compId = ct as EntityId<any>;\n\n if (isWildcardRelationId(compId)) {\n return collectWildcardFromRemoved(compId, removedComponents);\n }\n\n const match = findMatchingComponent(removedComponents, compId);\n return match ? match[1] : undefined;\n });\n}\n\n/**\n * Collect all matching wildcard relation data from removed components.\n */\nfunction collectWildcardFromRemoved(\n wildcardId: EntityId<any>,\n removedComponents: Map<EntityId<any>, any>,\n): [EntityId, any][] {\n const result: [EntityId, any][] = [];\n\n for (const [removedCompId, removedValue] of removedComponents.entries()) {\n // Skip wildcard markers themselves — they encode WILDCARD_TARGET_ID=0.\n if (isWildcardRelationId(removedCompId)) continue;\n if (componentMatchesHookType(removedCompId, wildcardId)) {\n const targetId = getTargetIdFromRelationId(removedCompId);\n if (targetId !== undefined) {\n result.push([targetId, removedValue]);\n }\n }\n }\n\n return result;\n}\n","// A lightweight generic MultiMap implementation backed by Map<K, Set<V>>.\n// Provides usual operations: add, remove, get, has, keys, values, entries,\n// clear, deleteKey and size accessors.\n\nconst _MISSING = Symbol(\"missing\");\n\nclass MultiMap<K, V> {\n private map: Map<K, Set<V>> = new Map();\n\n // Number of value entries across all keys (not number of keys).\n private _valueCount = 0;\n\n get valueCount(): number {\n return this._valueCount;\n }\n\n get keyCount(): number {\n return this.map.size;\n }\n\n hasKey(key: K): boolean {\n return this.map.has(key);\n }\n\n has(key: K, value: V | typeof _MISSING = _MISSING): boolean {\n const set = this.map.get(key);\n if (!set) return false;\n if (value === _MISSING) return true;\n return set.has(value);\n }\n\n add(key: K, value: V): void {\n let set = this.map.get(key);\n if (!set) {\n set = new Set();\n this.map.set(key, set);\n }\n if (!set.has(value)) {\n set.add(value);\n this._valueCount++;\n }\n }\n\n // Remove a specific value for a key. Returns true if removed.\n remove(key: K, value: V): boolean {\n const set = this.map.get(key);\n if (!set) return false;\n if (!set.has(value)) return false;\n set.delete(value);\n this._valueCount--;\n if (set.size === 0) this.map.delete(key);\n return true;\n }\n\n // Delete entire key and all its values. Returns true if key existed.\n deleteKey(key: K): boolean {\n const set = this.map.get(key);\n if (!set) return false;\n this._valueCount -= set.size;\n this.map.delete(key);\n return true;\n }\n\n get(key: K): Set<V> {\n const set = this.map.get(key);\n return set ? new Set(set) : new Set();\n }\n\n // iterate keys, values and entries (key -> Set copy)\n *keys(): IterableIterator<K> {\n yield* this.map.keys();\n }\n\n *values(): IterableIterator<V> {\n for (const set of this.map.values()) {\n for (const v of set) yield v;\n }\n }\n\n [Symbol.iterator](): IterableIterator<[K, V]> {\n return this.entries();\n }\n\n *entries(): IterableIterator<[K, V]> {\n for (const [k, set] of this.map.entries()) {\n for (const v of set) yield [k, v];\n }\n }\n\n clear(): void {\n this.map.clear();\n this._valueCount = 0;\n }\n}\n\nexport { MultiMap };\n","import type { EntityId } from \"../entity\";\nimport { MultiMap } from \"../utils/multi-map\";\n\n/**\n * Reverse reference index: maps each target entity to the set of (source entity, component) pairs\n * that currently hold a reference to it.\n *\n * Used internally to support efficient entity deletion, including:\n * - Fast-path deletion for unreferenced entities\n * - Cascading deletes for relations marked with `cascadeDelete`\n * - Automatic cleanup of entity-valued components and entity-relations when their target is destroyed\n *\n * Structure:\n * targetEntityId -> MultiMap<sourceEntityId, componentOrRelationId>\n *\n * - For plain entity-valued components (component value is an EntityId):\n * componentOrRelationId === the component type (which is also the entity id being pointed to)\n * - For entity-relations (`relation(Comp, target)`):\n * componentOrRelationId is the encoded (negative) relation ID\n *\n * This index is maintained in sync with structural changes via `updateEntityReferences` in World.\n *\n * @internal\n */\nexport type EntityReferencesMap = Map<EntityId, MultiMap<EntityId, EntityId>>;\n\n/**\n * Record that `sourceEntityId` holds a reference to `targetEntityId` via the given component/relation.\n *\n * Called when an entity-valued component or an entity-relation is added to an entity.\n *\n * @param entityReferences - The shared reverse index map\n * @param sourceEntityId - The entity that contains the reference\n * @param componentType - The component type or encoded relation ID used for the reference\n * @param targetEntityId - The entity being referenced\n *\n * @internal\n */\nexport function trackEntityReference(\n entityReferences: EntityReferencesMap,\n sourceEntityId: EntityId,\n componentType: EntityId,\n targetEntityId: EntityId,\n): void {\n if (!entityReferences.has(targetEntityId)) {\n entityReferences.set(targetEntityId, new MultiMap());\n }\n entityReferences.get(targetEntityId)!.add(sourceEntityId, componentType);\n}\n\n/**\n * Remove the record that `sourceEntityId` references `targetEntityId` via the given component/relation.\n *\n * Called when an entity-valued component or entity-relation is removed (or during deletion).\n * Automatically prunes empty target entries from the map.\n *\n * @param entityReferences - The shared reverse index map\n * @param sourceEntityId - The entity that no longer holds the reference\n * @param componentType - The component type or encoded relation ID that was used\n * @param targetEntityId - The previously referenced entity\n *\n * @internal\n */\nexport function untrackEntityReference(\n entityReferences: EntityReferencesMap,\n sourceEntityId: EntityId,\n componentType: EntityId,\n targetEntityId: EntityId,\n): void {\n const references = entityReferences.get(targetEntityId);\n if (references) {\n references.remove(sourceEntityId, componentType);\n if (references.keyCount === 0) {\n entityReferences.delete(targetEntityId);\n }\n }\n}\n\n/**\n * Iterate over all (sourceEntityId, componentOrRelationId) pairs that currently reference the given target.\n *\n * Returns an empty iterable when the target has no incoming references.\n * The returned iterable yields `[source, componentType]` pairs suitable for cleanup decisions\n * (e.g. whether to cascade-delete the source or just remove the specific component/relation).\n *\n * @param entityReferences - The shared reverse index map\n * @param targetEntityId - The entity whose referrers we want to inspect\n * @returns Iterable of [sourceEntityId, componentOrRelationId]\n *\n * @internal\n */\nexport function getEntityReferences(\n entityReferences: EntityReferencesMap,\n targetEntityId: EntityId,\n): Iterable<[EntityId, EntityId]> {\n return entityReferences.get(targetEntityId) ?? new MultiMap();\n}\n","import type { ComponentId, EntityId } from \"../entity\";\nimport { getComponentIdByName, getComponentNameById, getDetailedIdType, relation } from \"../entity\";\n\n// -----------------------------------------------------------------------------\n// Serialization helpers for IDs\n// -----------------------------------------------------------------------------\n\nexport type SerializedEntityId = number | string | { component: string; target: number | string | \"*\" };\n\n/**\n * Serialized state of EntityIdManager\n */\nexport interface SerializedEntityIdManager {\n nextId: number;\n freelist?: number[];\n}\n\nexport type SerializedWorld = {\n version: number;\n entityManager: SerializedEntityIdManager;\n entities: SerializedEntity[];\n componentEntities?: SerializedEntity[];\n};\n\nexport type SerializedEntity = {\n id: SerializedEntityId;\n components: SerializedComponent[];\n};\n\nexport type SerializedComponent = {\n type: SerializedEntityId;\n value: any;\n};\n\n/**\n * Core encoding logic (no cache). Extracted so cached wrapper can reuse it without duplication.\n */\nfunction encodeEntityIdCore(id: EntityId<any>): SerializedEntityId {\n const detailed = getDetailedIdType(id);\n switch (detailed.type) {\n case \"component\": {\n const name = getComponentNameById(id as ComponentId);\n if (!name) {\n // Warn if component doesn't have a name; keep numeric fallback\n console.warn(`Component ID ${id} has no registered name, serializing as number`);\n }\n return name || (id as number);\n }\n case \"entity-relation\": {\n const componentName = getComponentNameById(detailed.componentId);\n if (!componentName) {\n console.warn(`Component ID ${detailed.componentId} in relation has no registered name`);\n }\n // Safe: targetId is guaranteed to exist for entity-relation type\n return { component: componentName || (detailed.componentId as number).toString(), target: detailed.targetId };\n }\n case \"component-relation\": {\n const componentName = getComponentNameById(detailed.componentId);\n // Safe: targetId is guaranteed to exist for component-relation type\n const targetName = getComponentNameById(detailed.targetId as ComponentId);\n if (!componentName) {\n console.warn(`Component ID ${detailed.componentId} in relation has no registered name`);\n }\n if (!targetName) {\n console.warn(`Target component ID ${detailed.targetId} in relation has no registered name`);\n }\n return {\n component: componentName || (detailed.componentId as number).toString(),\n target: targetName || (detailed.targetId as number),\n };\n }\n case \"wildcard-relation\": {\n const componentName = getComponentNameById(detailed.componentId);\n if (!componentName) {\n console.warn(`Component ID ${detailed.componentId} in relation has no registered name`);\n }\n return { component: componentName || (detailed.componentId as number).toString(), target: \"*\" };\n }\n default:\n return id as number;\n }\n}\n\n/**\n * Encode an internal EntityId into a SerializedEntityId for snapshots.\n * Use encodeEntityIdCached when serializing many entities to benefit from memoization\n * of repeated component/relation type IDs.\n */\nexport function encodeEntityId(id: EntityId<any>): SerializedEntityId {\n return encodeEntityIdCore(id);\n}\n\n/**\n * Encode an EntityId, using an optional cache Map to avoid repeated getDetailedIdType\n * + name lookup work for IDs that appear many times (typical during full world snapshot).\n */\nexport function encodeEntityIdCached(\n id: EntityId<any>,\n cache?: Map<EntityId<any>, SerializedEntityId>,\n): SerializedEntityId {\n if (cache) {\n const cached = cache.get(id);\n if (cached !== undefined) return cached;\n const result = encodeEntityIdCore(id);\n cache.set(id, result);\n return result;\n }\n return encodeEntityIdCore(id);\n}\n\n/**\n * Decode a SerializedEntityId back into an internal EntityId\n */\nexport function decodeSerializedId(sid: SerializedEntityId): EntityId<any> {\n if (typeof sid === \"number\") {\n return sid as EntityId<any>;\n }\n if (typeof sid === \"string\") {\n const id = getComponentIdByName(sid);\n if (id === undefined) {\n const num = parseInt(sid, 10);\n if (!isNaN(num)) return num as EntityId<any>;\n throw new Error(`Unknown component name in snapshot: ${sid}`);\n }\n return id;\n }\n if (typeof sid === \"object\" && sid !== null && typeof sid.component === \"string\") {\n let compId = getComponentIdByName(sid.component);\n if (compId === undefined) {\n const num = parseInt(sid.component, 10);\n if (!isNaN(num)) compId = num as ComponentId;\n }\n if (compId === undefined) {\n throw new Error(`Unknown component name in snapshot: ${sid.component}`);\n }\n\n if (sid.target === \"*\") {\n return relation(compId, \"*\");\n }\n\n let targetId: EntityId<any>;\n if (typeof sid.target === \"string\") {\n const tid = getComponentIdByName(sid.target);\n if (tid === undefined) {\n const num = parseInt(sid.target, 10);\n if (!isNaN(num)) targetId = num as EntityId<any>;\n else throw new Error(`Unknown target component name in snapshot: ${sid.target}`);\n } else {\n targetId = tid;\n }\n } else {\n targetId = sid.target as EntityId<any>;\n }\n return relation(compId, targetId as any);\n }\n throw new Error(`Invalid ID in snapshot: ${JSON.stringify(sid)}`);\n}\n","import { MISSING_COMPONENT, type Archetype } from \"../archetype/archetype\";\nimport type { ComponentEntityStore } from \"../component/entity-store\";\nimport { getDetailedIdType, type EntityId, type EntityIdManager } from \"../entity\";\nimport {\n decodeSerializedId,\n encodeEntityIdCached,\n type SerializedComponent,\n type SerializedEntity,\n type SerializedWorld,\n} from \"../storage/serialization\";\nimport { trackEntityReference, type EntityReferencesMap } from \"./references\";\n\n/**\n * Serializes the full world state to a plain JS object suitable for JSON encoding.\n */\nexport function serializeWorld(\n archetypes: Archetype[],\n componentEntities: ComponentEntityStore,\n entityIdManager: EntityIdManager,\n): SerializedWorld {\n // ID cache turns repeated encode work (especially component type IDs) into O(#unique IDs)\n const idCache = new Map<any, any>();\n\n const entities: SerializedEntity[] = [];\n\n for (const archetype of archetypes) {\n // Pre-encode this archetype's component type IDs exactly once (big win when many entities share the archetype)\n const encodedComponentTypes = archetype.componentTypes.map((t) => encodeEntityIdCached(t, idCache));\n\n // The append method will use the bulk helper internally when a pre-fetched map is supplied.\n // For now we rely on the per-entity fallback inside the archetype (already much cheaper than old dump path).\n archetype.appendSerializedEntities(entities, (id) => encodeEntityIdCached(id, idCache), encodedComponentTypes);\n }\n\n const componentEntitiesArr: SerializedEntity[] = [];\n for (const [entityId, components] of componentEntities.entries()) {\n componentEntitiesArr.push({\n id: encodeEntityIdCached(entityId, idCache),\n components: serializeComponentsFromMap(components, idCache),\n });\n }\n\n return {\n version: 1,\n entityManager: entityIdManager.serializeState(),\n entities,\n componentEntities: componentEntitiesArr,\n };\n}\n\n/** Small helper to avoid duplicating the \"Map → SerializedComponent[] with cache\" pattern. */\nfunction serializeComponentsFromMap(\n components: Map<EntityId<any>, any>,\n idCache: Map<any, any>,\n): SerializedComponent[] {\n const result: SerializedComponent[] = [];\n for (const [rawType, value] of components) {\n result.push({\n type: encodeEntityIdCached(rawType, idCache),\n value: value === MISSING_COMPONENT ? undefined : value,\n });\n }\n return result;\n}\n\n/**\n * Context needed by `deserializeWorld` to populate world-internal state.\n * Defined as an interface to avoid a circular import between world.ts and this module.\n */\nexport interface WorldDeserializationContext {\n entityIdManager: EntityIdManager;\n componentEntities: ComponentEntityStore;\n entityReferences: EntityReferencesMap;\n ensureArchetype(componentTypes: EntityId<any>[]): Archetype;\n setEntityToArchetype(entityId: EntityId, archetype: Archetype): void;\n}\n\n/**\n * Restores world state from a snapshot into the provided context.\n * Intended to be called from `World`'s constructor.\n */\nexport function deserializeWorld(ctx: WorldDeserializationContext, snapshot: SerializedWorld): void {\n if (snapshot.entityManager) {\n ctx.entityIdManager.deserializeState(snapshot.entityManager);\n }\n\n if (Array.isArray(snapshot.componentEntities)) {\n for (const entry of snapshot.componentEntities) {\n const entityId = decodeSerializedId(entry.id);\n if (!ctx.componentEntities.exists(entityId)) continue;\n\n const componentsArray: SerializedComponent[] = entry.components || [];\n const componentMap = new Map<EntityId<any>, any>();\n\n for (const componentEntry of componentsArray) {\n const componentType = decodeSerializedId(componentEntry.type);\n componentMap.set(componentType, componentEntry.value);\n }\n\n ctx.componentEntities.initFromSnapshot(entityId, componentMap);\n }\n }\n\n if (Array.isArray(snapshot.entities)) {\n for (const entry of snapshot.entities) {\n const entityId = decodeSerializedId(entry.id);\n const componentsArray: SerializedComponent[] = entry.components || [];\n\n const componentMap = new Map<EntityId<any>, any>();\n\n for (const componentEntry of componentsArray) {\n const componentType = decodeSerializedId(componentEntry.type);\n componentMap.set(componentType, componentEntry.value);\n }\n\n // Build the list of component types from the map we just populated (no redundant push loop)\n const componentTypes = Array.from(componentMap.keys());\n\n // ensureArchetype is internally memoized (getOrCompute on signature), so repeated calls\n // for the same component set are cheap after the first archetype is created.\n const archetype = ctx.ensureArchetype(componentTypes);\n archetype.addEntity(entityId, componentMap);\n ctx.setEntityToArchetype(entityId, archetype);\n\n for (const compType of componentTypes) {\n const detailedType = getDetailedIdType(compType);\n if (detailedType.type === \"entity-relation\") {\n // Safe: targetId guaranteed for entity-relation type\n trackEntityReference(ctx.entityReferences, entityId, compType, detailedType.targetId);\n } else if (detailedType.type === \"entity\") {\n trackEntityReference(ctx.entityReferences, entityId, compType, compType);\n }\n }\n }\n }\n}\n","import { Archetype } from \"../archetype/archetype\";\nimport { SparseStoreImpl } from \"../archetype/store\";\nimport { CommandBuffer, type Command } from \"../commands/buffer\";\nimport { ComponentChangeset } from \"../commands/changeset\";\nimport { ComponentEntityStore } from \"../component/entity-store\";\nimport { normalizeComponentTypes } from \"../component/type-utils\";\nimport type { ComponentId, EntityId, WildcardRelationId } from \"../entity\";\nimport {\n ENTITY_ID_START,\n EntityIdManager,\n RELATION_SHIFT,\n getComponentIdFromRelationId,\n getDetailedIdType,\n getTargetIdFromRelationId,\n isCascadeDeleteRelation,\n isEntityRelation,\n isExclusiveComponent,\n isSparseRelation,\n isSparseWildcard,\n isWildcardRelationId,\n relation,\n} from \"../entity\";\nimport { matchesFilter, serializeQueryFilter, type QueryFilter } from \"../query/filter\";\nimport type { Query } from \"../query/query\";\nimport { QueryRegistry } from \"../query/registry\";\nimport type { SerializedWorld } from \"../storage/serialization\";\nimport type {\n ComponentTuple,\n ComponentType,\n DebugStatsCollector,\n LifecycleCallback,\n LifecycleHook,\n LifecycleHookEntry,\n SyncDebugStats,\n} from \"../types\";\nimport { isOptionalEntityId } from \"../types\";\nimport { getOrCompute } from \"../utils/utils\";\nimport { EntityBuilder } from \"./builder\";\nimport {\n applyChangeset,\n filterRegularComponentTypes,\n maybeRemoveWildcardMarker,\n processCommands,\n removeMatchingRelations,\n type CommandProcessorContext,\n} from \"./commands\";\nimport {\n collectMultiHookComponents,\n debugHookExecutionCounter,\n triggerLifecycleHooks,\n triggerRemoveHooksForEntityDeletion,\n type HooksContext,\n} from \"./hooks\";\nimport {\n getEntityReferences,\n trackEntityReference,\n untrackEntityReference,\n type EntityReferencesMap,\n} from \"./references\";\nimport { deserializeWorld, serializeWorld } from \"./serialization\";\n\n/**\n * World class for ECS architecture\n * Manages entities and components\n */\nexport class World {\n // Core data structures for entity and archetype management\n private entityIdManager = new EntityIdManager();\n private archetypes: Archetype[] = [];\n private archetypeBySignature = new Map<string, Archetype>();\n private entityToArchetype = new Map<EntityId, Archetype>();\n private archetypesByComponent = new Map<EntityId<any>, Set<Archetype>>();\n private entityReferences: EntityReferencesMap = new Map();\n /** Reverse index: entity ID → set of archetypes whose componentTypes include that entity ID */\n private entityToReferencingArchetypes = new Map<EntityId, Set<Archetype>>();\n /** Sparse relation storage (for components created with `sparse: true`), shared with all Archetype instances */\n private readonly sparseStore = new SparseStoreImpl();\n /** Component entity (singleton) storage */\n private readonly componentEntities = new ComponentEntityStore();\n\n // Query registry – manages caching, ref counts, and archetype notifications\n private readonly queryRegistry = new QueryRegistry();\n\n // Lifecycle hooks (declared before cached contexts that reference them)\n private hooks: Set<LifecycleHookEntry> = new Set();\n\n // Debug observability collectors (armed only when non-empty)\n private readonly _debugCollectors = new Set<(stats: SyncDebugStats) => void>();\n\n // Transient counters for the current armed sync (reset each time)\n private _debugMigrations = 0;\n private _debugArchetypesCreated = 0;\n private _debugArchetypesRemoved = 0;\n\n // Command execution\n private commandBuffer = new CommandBuffer((entityId, commands) => this.executeEntityCommands(entityId, commands));\n\n // Reusable instances to reduce per-frame allocations\n private readonly _changeset = new ComponentChangeset();\n private readonly _removeChangeset = new ComponentChangeset();\n /** Cached command processor context to avoid per-entity object allocation */\n private readonly _commandCtx: CommandProcessorContext = {\n sparseStore: this.sparseStore,\n ensureArchetype: (ct) => this.ensureArchetype(ct),\n };\n /** Cached hooks context to avoid per-entity object allocation */\n private readonly _hooksCtx: HooksContext = {\n multiHooks: this.hooks,\n has: (eid, ct) => this.has(eid, ct),\n get: (eid, ct) => this.get(eid, ct),\n getOptional: (eid, ct) => this.getOptional(eid, ct),\n };\n\n constructor(snapshot?: SerializedWorld) {\n if (snapshot && typeof snapshot === \"object\") {\n deserializeWorld(\n {\n entityIdManager: this.entityIdManager,\n componentEntities: this.componentEntities,\n entityReferences: this.entityReferences,\n ensureArchetype: (ct) => this.ensureArchetype(ct),\n setEntityToArchetype: (eid, arch) => this.entityToArchetype.set(eid, arch),\n },\n snapshot,\n );\n }\n }\n\n private createArchetypeSignature(componentTypes: EntityId<any>[]): string {\n return componentTypes.join(\",\");\n }\n\n /**\n * Creates a new entity.\n * The entity is created with an empty component set and can be configured using `set()`.\n *\n * @template T - The initial component type (defaults to void if not specified)\n * @returns A unique identifier for the new entity\n *\n * @example\n * const entity = world.new<MyComponent>();\n * world.set(entity, MyComponent, { value: 42 });\n * world.sync();\n */\n new<T = void>(): EntityId<T> {\n const entityId = this.entityIdManager.allocate();\n let emptyArchetype = this.ensureArchetype([]);\n emptyArchetype.addEntity(entityId, new Map());\n this.entityToArchetype.set(entityId, emptyArchetype);\n return entityId as EntityId<T>;\n }\n\n /**\n * Semantic alias for `new()` to avoid confusion with the `new` keyword.\n * Creates a new entity with an empty component set.\n *\n * @example\n * const entity = world.create<MyComponent>();\n */\n create<T = void>(): EntityId<T> {\n return this.new<T>();\n }\n\n /** Fast path: destroy an entity that is not referenced by any other entity, skipping BFS */\n private destroySingleEntity(entityId: EntityId): void {\n const archetype = this.entityToArchetype.get(entityId);\n if (!archetype) return;\n\n // Handle entity references (this entity references other entities)\n for (const [sourceEntityId, componentType] of getEntityReferences(this.entityReferences, entityId)) {\n if (this.entityToArchetype.has(sourceEntityId)) {\n this.removeComponentImmediate(sourceEntityId, componentType, entityId);\n }\n }\n\n this.entityReferences.delete(entityId);\n const removedComponents = archetype.removeEntity(entityId)!;\n this.entityToArchetype.delete(entityId);\n\n triggerRemoveHooksForEntityDeletion(entityId, removedComponents, archetype);\n\n this.cleanupArchetypesReferencingEntity(entityId);\n this.entityIdManager.deallocate(entityId);\n this.componentEntities.cleanupReferencesTo(entityId);\n }\n\n private destroyEntityImmediate(entityId: EntityId): void {\n // Fast path: no other entity references this one, delete directly\n if (!this.entityReferences.has(entityId)) {\n this.destroySingleEntity(entityId);\n return;\n }\n\n const queue: EntityId[] = [entityId];\n const visited = new Set<EntityId>();\n let queueIndex = 0;\n\n while (queueIndex < queue.length) {\n const cur = queue[queueIndex++]!;\n if (visited.has(cur)) continue;\n visited.add(cur);\n\n const archetype = this.entityToArchetype.get(cur);\n if (!archetype) continue;\n\n // Process entity references before removal\n for (const [sourceEntityId, componentType] of getEntityReferences(this.entityReferences, cur)) {\n if (!this.entityToArchetype.has(sourceEntityId)) continue;\n\n if (isCascadeDeleteRelation(componentType)) {\n if (!visited.has(sourceEntityId)) {\n queue.push(sourceEntityId);\n }\n } else {\n this.removeComponentImmediate(sourceEntityId, componentType, cur);\n }\n }\n\n // Remove entity from archetype - this also cleans up sparse relations\n // and returns all removed component data\n this.entityReferences.delete(cur);\n const removedComponents = archetype.removeEntity(cur)!;\n this.entityToArchetype.delete(cur);\n\n // Trigger lifecycle hooks for removed components (fast path for entity deletion)\n triggerRemoveHooksForEntityDeletion(cur, removedComponents, archetype);\n\n this.cleanupArchetypesReferencingEntity(cur);\n this.entityIdManager.deallocate(cur);\n this.componentEntities.cleanupReferencesTo(cur);\n }\n }\n\n /**\n * Checks if an **entity** (not a component) exists in the world.\n *\n * This is specifically for checking entity liveness — whether the given entity ID\n * is currently alive in the world. For checking if a component is present on an\n * entity, use {@link has} instead.\n *\n * @param entityId - The entity identifier to check\n * @returns `true` if the entity exists, `false` otherwise\n *\n * @example\n * // Check if an entity is alive\n * if (world.exists(entityId)) {\n * console.log(\"Entity exists\");\n * }\n *\n * // To check for a component, use has() instead:\n * if (world.has(entity, Position)) { ... }\n */\n exists(entityId: EntityId): boolean {\n if (this.componentEntities.exists(entityId)) return true;\n return this.entityToArchetype.has(entityId);\n }\n\n private assertEntityExists(entityId: EntityId, label: \"Entity\" | \"Component entity\"): void {\n if (!this.exists(entityId)) {\n throw new Error(`${label} ${entityId} does not exist`);\n }\n }\n\n private assertComponentTypeValid(componentType: EntityId): void {\n const detailedType = getDetailedIdType(componentType);\n if (detailedType.type === \"invalid\") {\n throw new Error(`Invalid component type: ${componentType}`);\n }\n }\n\n private assertSetComponentTypeValid(componentType: EntityId): void {\n const detailedType = getDetailedIdType(componentType);\n if (detailedType.type === \"invalid\") {\n throw new Error(`Invalid component type: ${componentType}`);\n }\n if (detailedType.type === \"wildcard-relation\") {\n throw new Error(`Cannot directly add wildcard relation components: ${componentType}`);\n }\n }\n\n private resolveSetOperation(\n entityId: EntityId | ComponentId,\n componentTypeOrComponent?: EntityId | any,\n maybeComponent?: any,\n ): { entityId: EntityId; componentType: EntityId; component: any } {\n // Handle singleton component overload: set(componentId, data)\n if (maybeComponent === undefined && componentTypeOrComponent !== undefined) {\n const detailedType = getDetailedIdType(entityId);\n if (detailedType.type === \"component\" || detailedType.type === \"component-relation\") {\n const componentId = entityId as ComponentId;\n this.assertEntityExists(componentId, \"Component entity\");\n this.assertSetComponentTypeValid(componentId);\n return { entityId: componentId, componentType: componentId, component: componentTypeOrComponent };\n }\n }\n\n const targetEntityId = entityId as EntityId;\n const componentType = componentTypeOrComponent as EntityId;\n this.assertEntityExists(targetEntityId, \"Entity\");\n this.assertSetComponentTypeValid(componentType);\n\n return { entityId: targetEntityId, componentType, component: maybeComponent };\n }\n\n private resolveRemoveOperation<T>(\n entityId: EntityId | ComponentId,\n componentType?: EntityId<T>,\n ): { entityId: EntityId; componentType: EntityId } {\n // Handle singleton component overload: remove(componentId)\n if (componentType === undefined) {\n const componentId = entityId as ComponentId<T>;\n this.assertEntityExists(componentId, \"Component entity\");\n return { entityId: componentId, componentType: componentId };\n }\n\n const targetEntityId = entityId as EntityId;\n this.assertEntityExists(targetEntityId, \"Entity\");\n this.assertComponentTypeValid(componentType);\n\n return { entityId: targetEntityId, componentType };\n }\n\n /**\n * Adds or updates a component on an entity (or marks void component as present).\n * The change is buffered and takes effect after calling `world.sync()`.\n * If the entity does not exist, throws an error.\n *\n * @overload set(entityId: EntityId, componentType: EntityId<void>): void\n * Marks a void component as present on the entity\n *\n * @overload set<T>(entityId: EntityId, componentType: EntityId<T>, component: NoInfer<T>): void\n * Adds or updates a component with data on the entity\n *\n * @overload set<T>(componentId: ComponentId<T>, component: NoInfer<T>): void\n * Adds or updates a singleton component (shorthand for set(componentId, componentId, component))\n *\n * @throws {Error} If the entity does not exist\n * @throws {Error} If the component type is invalid or is a wildcard relation\n *\n * @example\n * world.set(entity, Position, { x: 10, y: 20 });\n * world.set(entity, Marker); // void component\n * world.set(GlobalConfig, { debug: true }); // singleton component\n * world.sync(); // Apply changes\n */\n set(entityId: EntityId, componentType: EntityId<void>): void;\n set<T>(entityId: EntityId, componentType: EntityId<T>, component: NoInfer<T>): void;\n set<T>(componentId: ComponentId<T>, component: NoInfer<T>): void;\n set(entityId: EntityId | ComponentId, componentTypeOrComponent?: EntityId | any, maybeComponent?: any): void {\n const {\n entityId: targetEntityId,\n componentType,\n component,\n } = this.resolveSetOperation(entityId, componentTypeOrComponent, maybeComponent);\n this.commandBuffer.set(targetEntityId, componentType, component);\n }\n\n /**\n * Removes a component from an entity.\n * The change is buffered and takes effect after calling `world.sync()`.\n * If the entity does not exist, throws an error.\n *\n * @overload remove<T>(entityId: EntityId, componentType: EntityId<T>): void\n * Removes a component from an entity.\n *\n * @overload remove<T>(componentId: ComponentId<T>): void\n * Removes a singleton component (shorthand for remove(componentId, componentId)).\n *\n * @template T - The component data type\n * @param entityId - The entity identifier\n * @param componentType - The component type to remove\n *\n * @throws {Error} If the entity does not exist\n * @throws {Error} If the component type is invalid\n *\n * @example\n * world.remove(entity, Position);\n * world.remove(GlobalConfig); // Remove singleton component\n * world.sync(); // Apply changes\n */\n remove<T>(componentId: ComponentId<T>): void;\n remove<T>(entityId: EntityId, componentType: EntityId<T>): void;\n remove<T>(entityId: EntityId | ComponentId, componentType?: EntityId<T>): void {\n const { entityId: targetEntityId, componentType: targetComponentType } = this.resolveRemoveOperation(\n entityId,\n componentType,\n );\n this.commandBuffer.remove(targetEntityId, targetComponentType);\n }\n\n /**\n * Deletes an entity and all its components from the world.\n * The change is buffered and takes effect after calling `world.sync()`.\n * Related entities may trigger cascade delete hooks if configured.\n *\n * @param entityId - The entity identifier to delete\n *\n * @example\n * world.delete(entity);\n * world.sync(); // Apply changes\n */\n delete(entityId: EntityId): void {\n this.commandBuffer.delete(entityId);\n }\n\n /**\n * Checks if a specific **component** is present on an entity.\n *\n * This is for component membership checks — does the given entity have this\n * component type? For checking whether an entity itself is alive, use\n * {@link exists} instead.\n *\n * Immediately reflects the current state without waiting for `sync()`.\n *\n * @overload has<T>(entityId: EntityId, componentType: EntityId<T>): boolean\n * Checks if a specific component type is present on the entity.\n *\n * @overload has<T>(componentId: ComponentId<T>): boolean\n * Shorthand for checking a **singleton component** — a component that is its own\n * entity (component-as-entity pattern). Equivalent to `has(componentId, componentId)`.\n *\n * @template T - The component data type\n * @param entityId - The entity identifier, or a singleton component ID\n * @param componentType - The component type to check\n * @returns `true` if the entity has the component, `false` otherwise\n *\n * @example\n * // Check if an entity has a component\n * if (world.has(entity, Position)) {\n * const pos = world.get(entity, Position);\n * }\n *\n * // Check a singleton component (component-as-entity)\n * if (world.has(GlobalConfig)) {\n * const config = world.get(GlobalConfig);\n * }\n *\n * // Use exists() for entity liveness checks\n * if (world.exists(entity)) { ... }\n */\n has<T>(componentId: ComponentId<T>): boolean;\n has<T>(entityId: EntityId, componentType: EntityId<T>): boolean;\n has<T>(entityId: EntityId | ComponentId, componentType?: EntityId<T>): boolean {\n // Handle singleton component overload: has(componentId)\n if (componentType === undefined) {\n const componentId = entityId as ComponentId<T>;\n return this.componentEntities.hasSingleton(componentId);\n }\n\n if (this.componentEntities.exists(entityId)) {\n if (isWildcardRelationId(componentType)) {\n const componentId = getComponentIdFromRelationId(componentType);\n if (componentId === undefined) return false;\n return this.componentEntities.hasWildcard(entityId, componentId);\n }\n return this.componentEntities.has(entityId, componentType);\n }\n\n const archetype = this.entityToArchetype.get(entityId);\n if (!archetype) return false;\n\n if (archetype.componentTypeSet.has(componentType)) return true;\n\n if (isSparseRelation(componentType)) {\n // Use getValue; presence check via getAllForEntity only if value can legitimately be undefined\n const val = this.sparseStore.getValue(entityId, componentType);\n if (val !== undefined) return true;\n return this.sparseStore.getAllForEntity(entityId).some(([t]) => t === componentType);\n }\n\n return false;\n }\n\n /**\n * Retrieves a component from an entity.\n * For wildcard relations, returns all relations of that type.\n * Throws an error if the component does not exist; use `has()` to check first or use `getOptional()`.\n *\n * @overload get<T>(entityId: EntityId<T>): T\n * When called with only an entity ID, retrieves the entity's primary component.\n *\n * @overload get<T>(entityId: EntityId, componentType: WildcardRelationId<T>): [EntityId<unknown>, T][]\n * For wildcard relations, returns an array of [target entity, component value] pairs.\n *\n * @overload get<T>(entityId: EntityId, componentType: EntityId<T>): T\n * Retrieves a specific component from the entity.\n *\n * @throws {Error} If the entity does not exist\n * @throws {Error} If the component does not exist on the entity\n *\n * @example\n * const position = world.get(entity, Position); // Throws if no Position\n * const relations = world.get(entity, relation(Parent, \"*\")); // Wildcard relation\n */\n get<T>(entityId: EntityId<T>): T;\n get<T>(entityId: EntityId, componentType: WildcardRelationId<T>): [EntityId<unknown>, T][];\n get<T>(entityId: EntityId, componentType: EntityId<T>): T;\n get<T>(\n entityId: EntityId,\n componentType: EntityId<T> | WildcardRelationId<T> = entityId as EntityId<T>,\n ): T | [EntityId<unknown>, any][] {\n if (this.componentEntities.exists(entityId)) {\n if (isWildcardRelationId(componentType as EntityId<any>)) {\n return this.componentEntities.getWildcard(entityId, componentType as WildcardRelationId<T>);\n }\n return this.componentEntities.get(entityId, componentType as EntityId<T>);\n }\n\n const archetype = this.entityToArchetype.get(entityId);\n if (!archetype) {\n throw new Error(`Entity ${entityId} does not exist`);\n }\n\n if (componentType >= 0 || componentType % RELATION_SHIFT !== 0) {\n const inArchetype = archetype.componentTypeSet.has(componentType);\n const hasSparse = isSparseRelation(componentType);\n const hasComponent =\n inArchetype ||\n (hasSparse &&\n (this.sparseStore.getValue(entityId, componentType) !== undefined ||\n this.sparseStore.getAllForEntity(entityId).some(([t]) => t === componentType)));\n\n if (!hasComponent) {\n throw new Error(\n `Entity ${entityId} does not have component ${componentType}. Use has() to check component existence before calling get().`,\n );\n }\n }\n\n return archetype.get(entityId, componentType) as T | [EntityId<unknown>, any][];\n }\n\n /**\n * Safely retrieves a component from an entity without throwing an error.\n * Returns `undefined` if the component does not exist.\n * For wildcard relations, returns `undefined` if there are no relations.\n *\n * @template T - The component data type\n * @overload getOptional<T>(entityId: EntityId<T>): { value: T } | undefined\n * Retrieves the entity's primary component safely.\n *\n * @overload getOptional<T>(entityId: EntityId, componentType: WildcardRelationId<T>): { value: [EntityId<unknown>, T][] } | undefined\n * Retrieves all matching relation values safely.\n *\n * @overload getOptional<T>(entityId: EntityId, componentType: EntityId<T>): { value: T } | undefined\n * Retrieves a specific component safely.\n *\n * @throws {Error} If the entity does not exist\n *\n * @example\n * const position = world.getOptional(entity, Position);\n * if (position) {\n * console.log(position.value.x);\n * }\n */\n getOptional<T>(entityId: EntityId<T>): { value: T } | undefined;\n getOptional<T>(\n entityId: EntityId,\n componentType: WildcardRelationId<T>,\n ): { value: [EntityId<unknown>, T][] } | undefined;\n getOptional<T>(entityId: EntityId, componentType: EntityId<T>): { value: T } | undefined;\n getOptional<T>(\n entityId: EntityId,\n componentType: EntityId<T> | WildcardRelationId<T> = entityId as EntityId<T>,\n ): { value: T } | { value: [EntityId<unknown>, T][] } | undefined {\n if (this.componentEntities.exists(entityId)) {\n if (isWildcardRelationId(componentType)) {\n const relations = this.componentEntities.getWildcard(entityId, componentType);\n if (relations.length === 0) return undefined;\n return { value: relations };\n }\n return this.componentEntities.getOptional(entityId, componentType);\n }\n\n const archetype = this.entityToArchetype.get(entityId);\n if (!archetype) {\n throw new Error(`Entity ${entityId} does not exist`);\n }\n\n if (isWildcardRelationId(componentType)) {\n // For wildcard relations, get the data and wrap in optional if non-empty\n const wildcardData = archetype.get(entityId, componentType) as [EntityId<unknown>, T][];\n if (Array.isArray(wildcardData) && wildcardData.length > 0) {\n return { value: wildcardData };\n }\n return undefined;\n }\n\n return archetype.getOptional(entityId, componentType);\n }\n\n // ==========================================================================\n // Relation & Hierarchy Companion Tools (public API)\n // ==========================================================================\n\n /**\n * Retrieves all targets (and their associated data) for relations of a given\n * base component on an entity.\n *\n * This is the ergonomic replacement for the common pattern:\n * world.get(entity, relation(Comp, \"*\"))\n *\n * @example\n * const ChildOf = component({ exclusive: true, sparse: true });\n * const children = world.getRelationTargets(parent, ChildOf); // usually []\n * const items = world.getRelationTargets(player, InInventory);\n *\n * // For common hierarchy use cases, prefer the higher-level helpers:\n * // world.getChildren(parent, ChildOf), world.getParent(child, ChildOf)\n */\n getRelationTargets<T = void>(\n entityId: EntityId,\n relationComp: ComponentId<T>,\n ): [target: EntityId<unknown>, data: T | undefined][] {\n this.assertEntityExists(entityId, \"Entity\");\n\n const wildcard = relation(relationComp, \"*\") as WildcardRelationId<T>;\n\n // For component entities (singletons) the path is different; they rarely host relations\n if (this.componentEntities.exists(entityId)) {\n return this.componentEntities.getWildcard(entityId, wildcard);\n }\n\n // Regular entity path — archetype.get for wildcard always materializes the array\n // (even if empty for a sparse relation that only has the marker)\n const data = this.get(entityId, wildcard);\n return data as [EntityId<unknown>, T | undefined][];\n }\n\n /**\n * Returns every entity that currently holds a relation of the given base\n * component pointing at `targetId`.\n *\n * This is the efficient **reverse** lookup. For common hierarchy cases,\n * prefer the higher-level `world.getChildren(parent, ChildOf)` instead.\n *\n * @example\n * const ChildOf = component({ exclusive: true, sparse: true });\n * const directChildren = world.getRelationSources(ship, ChildOf);\n */\n getRelationSources(targetId: EntityId, relationComp: ComponentId<any>): EntityId[] {\n const refs = getEntityReferences(this.entityReferences, targetId);\n const result: EntityId[] = [];\n\n for (const [source, relType] of refs) {\n // Only consider still-living sources\n if (!this.entityToArchetype.has(source) && !this.componentEntities.exists(source)) continue;\n\n const decodedComp = getComponentIdFromRelationId(relType);\n if (decodedComp === relationComp) {\n result.push(source);\n }\n }\n return result;\n }\n\n /**\n * Returns true if the entity has any (or a specific-target) relation of the\n * given base component.\n */\n hasRelation(entityId: EntityId, relationComp: ComponentId<any>, targetId?: EntityId): boolean {\n this.assertEntityExists(entityId, \"Entity\");\n\n if (targetId !== undefined) {\n const specific = relation(relationComp, targetId);\n return this.has(entityId, specific);\n }\n\n // Any target of this relation kind?\n const targets = this.getRelationTargets(entityId, relationComp);\n return targets.length > 0;\n }\n\n /**\n * Returns the number of relations of the given base component held by the entity.\n */\n countRelations(entityId: EntityId, relationComp: ComponentId<any>): number {\n this.assertEntityExists(entityId, \"Entity\");\n const targets = this.getRelationTargets(entityId, relationComp);\n return targets.length;\n }\n\n /**\n * For an *exclusive* relation (e.g. ChildOf, Owner), returns the single\n * target entity (or undefined if none).\n *\n * When the component was declared `exclusive: true`, this is the preferred\n * accessor (clearer intent than array destructuring).\n */\n getSingleRelationTarget<T = void>(entityId: EntityId, relationComp: ComponentId<T>): EntityId | undefined {\n const targets = this.getRelationTargets(entityId, relationComp);\n return targets.length > 0 ? (targets[0]![0] as EntityId) : undefined;\n }\n\n // --------------------------------------------------------------------------\n // High-level hierarchy helpers (convenience methods on World)\n // --------------------------------------------------------------------------\n\n /**\n * Returns the direct children of `parent` for the given relationship component\n * (typically a `ChildOf` or similar exclusive `sparse` relation).\n *\n * This is the recommended high-level API for hierarchy traversal.\n * It uses the internal reverse reference index for efficiency.\n *\n * @example\n * const ChildOf = component({ exclusive: true, sparse: true });\n * const kids = world.getChildren(ship, ChildOf);\n */\n getChildren(parent: EntityId, childOf: ComponentId<any>): EntityId[] {\n return this.getRelationSources(parent, childOf);\n }\n\n /**\n * Returns the parent of `child` for the given relationship component\n * (typically an exclusive `ChildOf` relation).\n *\n * @example\n * const ChildOf = component({ exclusive: true, sparse: true });\n * const parent = world.getParent(turret, ChildOf);\n */\n getParent(child: EntityId, childOf: ComponentId<any>): EntityId | undefined {\n return this.getSingleRelationTarget(child, childOf);\n }\n\n /**\n * Returns the ancestor chain from the immediate parent up to (but not\n * including) the root for the given relationship component.\n *\n * @example\n * const ChildOf = component({ exclusive: true, sparse: true });\n * const ancestors = world.getAncestors(muzzle, ChildOf); // [turret, ship]\n */\n getAncestors(entity: EntityId, childOf: ComponentId<any>): EntityId[] {\n const ancestors: EntityId[] = [];\n let cur = this.getParent(entity, childOf);\n while (cur !== undefined) {\n ancestors.push(cur);\n cur = this.getParent(cur, childOf);\n }\n return ancestors;\n }\n\n /**\n * Iteratively traverses all descendants of `root` in DFS pre-order.\n * This is a generator and is safe for very deep hierarchies.\n *\n * @example\n * for (const { entity, depth, parent } of world.iterateDescendants(root, ChildOf)) {\n * console.log(depth, entity);\n * }\n */\n *iterateDescendants(\n root: EntityId,\n childOf: ComponentId<any>,\n opts: { includeSelf?: boolean; maxDepth?: number } = {},\n ): IterableIterator<{ entity: EntityId; depth: number; parent: EntityId | null }> {\n const { includeSelf = false, maxDepth } = opts;\n const stack: Array<{ entity: EntityId; depth: number; parent: EntityId | null }> = [];\n\n if (includeSelf) {\n stack.push({ entity: root, depth: 0, parent: null });\n } else {\n for (const child of this.getChildren(root, childOf)) {\n stack.push({ entity: child, depth: 1, parent: root });\n }\n }\n\n while (stack.length > 0) {\n const current = stack.pop()!;\n if (maxDepth !== undefined && current.depth > maxDepth) continue;\n\n yield current;\n\n const kids = this.getChildren(current.entity, childOf);\n for (let i = kids.length - 1; i >= 0; i--) {\n const k = kids[i]!;\n stack.push({ entity: k, depth: current.depth + 1, parent: current.entity });\n }\n }\n }\n\n /**\n * Callback-based descendant traversal (hot path friendly).\n * Return `false` from the visitor to stop early.\n */\n traverseDescendants(\n root: EntityId,\n childOf: ComponentId<any>,\n visitor: (entity: EntityId, depth: number, parent: EntityId | null) => void | boolean,\n opts: { includeSelf?: boolean; maxDepth?: number } = {},\n ): void {\n for (const { entity, depth, parent } of this.iterateDescendants(root, childOf, opts)) {\n const res = visitor(entity, depth, parent);\n if (res === false) return;\n }\n }\n\n /**\n * Registers a lifecycle hook that responds to component changes.\n * The hook callback is invoked when components matching the specified types are added, updated, or removed.\n * @overload hook<const T extends readonly ComponentType<any>[]>(\n * componentTypes: T,\n * hook: LifecycleHook<T> | LifecycleCallback<T>,\n * filter?: QueryFilter,\n * ): () => void\n * Registers a hook for multiple component types.\n * The hook is triggered when entities enter/exit the matching set.\n *\n * @param componentTypes - Component types that define the matching entity set\n * @param hook - Either a hook object with on_init/on_set/on_remove handlers, or a callback function\n * @param filter - Optional query-style filter applied to the hook match set\n * @returns A function that unsubscribes the hook when called\n *\n * @throws {Error} If no required components are specified in array overload\n *\n * @example\n * const unsubscribe = world.hook([Position, Velocity], {\n * on_init: (entityId, position, velocity) => console.log(\"Initialized\"),\n * on_set: (entityId, position, velocity) => console.log(\"Updated\"),\n * on_remove: (entityId, position, velocity) => console.log(\"Removed\"),\n * });\n * unsubscribe(); // Remove hook\n *\n * // Callback style\n * const unsubscribe = world.hook([Position], (event, entityId, position) => {\n * if (event === \"init\") console.log(\"Initialized\");\n * });\n *\n * // With filter\n * const unsubscribe2 = world.hook(\n * [Position, Velocity],\n * {\n * on_set: (entityId, position, velocity) => console.log(entityId, position, velocity),\n * },\n * { negativeComponentTypes: [Disabled] },\n * );\n */\n hook<const T extends readonly ComponentType<any>[]>(\n componentTypes: T,\n hook: LifecycleHook<T> | LifecycleCallback<T>,\n filter?: QueryFilter,\n ): () => void;\n hook(\n componentTypes: readonly ComponentType<any>[],\n hook: LifecycleHook<any> | LifecycleCallback<any>,\n filter?: QueryFilter,\n ): () => void {\n const isCallback = typeof hook === \"function\";\n const callback = isCallback ? (hook as LifecycleCallback<any>) : undefined;\n\n const requiredComponents: EntityId<any>[] = [];\n const optionalComponents: EntityId<any>[] = [];\n for (const ct of componentTypes) {\n if (!isOptionalEntityId(ct)) {\n requiredComponents.push(ct as EntityId<any>);\n } else {\n optionalComponents.push(ct.optional);\n }\n }\n\n if (requiredComponents.length === 0) {\n throw new Error(\"Hook must have at least one required component\");\n }\n\n const entry: LifecycleHookEntry = {\n componentTypes,\n requiredComponents,\n optionalComponents,\n filter: filter || {},\n hook: isCallback ? ({} as LifecycleHook<any>) : (hook as LifecycleHook<any>),\n callback,\n matchedArchetypes: new Set(),\n };\n this.hooks.add(entry);\n\n // Single pass: collect matching archetypes\n const matchedArchetypes: Archetype[] = [];\n for (const archetype of this.archetypes) {\n if (this.archetypeMatchesHook(archetype, entry)) {\n archetype.matchingMultiHooks.add(entry);\n entry.matchedArchetypes!.add(archetype);\n matchedArchetypes.push(archetype);\n }\n }\n\n // Callback style: invoke callback(\"init\", ...); hook style: invoke hook.on_init(...)\n const shouldFireInit = isCallback || (hook as LifecycleHook<any>).on_init !== undefined;\n if (shouldFireInit) {\n for (const archetype of matchedArchetypes) {\n for (const entityId of archetype.getEntities()) {\n const components = collectMultiHookComponents(this.createHooksContext(), entityId, componentTypes);\n if (isCallback) {\n (callback as LifecycleCallback<any>)(\"init\", entityId, ...components);\n } else {\n (hook as LifecycleHook<any>).on_init!(entityId, ...components);\n }\n }\n }\n }\n\n return () => {\n this.hooks.delete(entry);\n if (entry.matchedArchetypes) {\n for (const archetype of entry.matchedArchetypes) {\n archetype.matchingMultiHooks.delete(entry);\n }\n }\n };\n }\n\n /**\n * Creates a debug stats collector that will receive a `SyncDebugStats` payload\n * after every subsequent `sync()`.\n *\n * The returned object is a pure lifecycle handle. It does not store data.\n * Collection stops when you call `[Symbol.dispose]()` (or use a `using` declaration).\n *\n * All active collectors receive the exact same stats object for a given sync.\n * Exceptions thrown by callbacks are ignored.\n *\n * This is intended for development/debugging and leak detection.\n */\n createDebugStatsCollector(callback: (stats: SyncDebugStats) => void): DebugStatsCollector {\n this._debugCollectors.add(callback);\n\n return {\n [Symbol.dispose]: () => {\n this._debugCollectors.delete(callback);\n },\n };\n }\n\n private _resetDebugActivityCounters(): void {\n this._debugMigrations = 0;\n this._debugArchetypesCreated = 0;\n this._debugArchetypesRemoved = 0;\n debugHookExecutionCounter.value = 0;\n }\n\n private _deliverDebugStats(timings: {\n syncStart: number;\n syncEnd: number;\n commandBufferStart: number;\n commandBufferEnd: number;\n commandIterations: number;\n }): void {\n // Build structural counts (post-sync)\n // Note: singletons (component-as-entity) are not included in the main archetype map.\n // For debug purposes the dominant number is regular entities; we keep it simple here.\n const entityCount = this.entityToArchetype.size;\n let emptyArchetypes = 0;\n for (const arch of this.archetypes) {\n if (arch.size === 0) emptyArchetypes++;\n }\n\n let archetypesByComponentSize = 0;\n for (const set of this.archetypesByComponent.values()) {\n archetypesByComponentSize += set.size;\n }\n\n const stats: SyncDebugStats = {\n timestamps: {\n syncStart: timings.syncStart,\n syncEnd: timings.syncEnd,\n commandBufferStart: timings.commandBufferStart,\n commandBufferEnd: timings.commandBufferEnd,\n },\n commandIterations: timings.commandIterations,\n\n entities: {\n total: entityCount,\n freelistSize: this.entityIdManager.getFreelistSize(),\n nextId: this.entityIdManager.getNextId(),\n },\n archetypes: {\n total: this.archetypes.length,\n empty: emptyArchetypes,\n },\n queries: {\n cached: (this.queryRegistry as any).cache?.size ?? 0,\n registered: (this.queryRegistry as any).queries?.size ?? 0,\n },\n hooks: {\n total: this.hooks.size,\n },\n indices: {\n entityReferences: this.entityReferences.size,\n entityToReferencingArchetypes: this.entityToReferencingArchetypes.size,\n archetypesByComponent: archetypesByComponentSize,\n },\n activity: {\n migrations: this._debugMigrations,\n hooksExecuted: debugHookExecutionCounter.value,\n archetypesCreated: this._debugArchetypesCreated,\n archetypesRemoved: this._debugArchetypesRemoved,\n },\n };\n\n for (const cb of this._debugCollectors) {\n try {\n cb(stats);\n } catch {\n // Intentionally ignore user callback errors\n }\n }\n }\n\n /**\n * Synchronizes all buffered commands (set/remove/delete) to the world.\n * This method must be called after making changes via `set()`, `remove()`, or `delete()` for them to take effect.\n * Typically called once per frame at the end of your game loop.\n *\n * @example\n * world.set(entity, Position, { x: 10, y: 20 });\n * world.remove(entity, OldComponent);\n * world.sync(); // Apply all buffered changes\n */\n sync(): void {\n const hasCollectors = this._debugCollectors.size > 0;\n\n const syncStart = hasCollectors ? performance.now() : 0;\n\n if (hasCollectors) {\n this._resetDebugActivityCounters();\n }\n\n const commandBufferStart = hasCollectors ? performance.now() : 0;\n const commandIterations = this.commandBuffer.execute();\n const commandBufferEnd = hasCollectors ? performance.now() : 0;\n\n const syncEnd = hasCollectors ? performance.now() : 0;\n\n if (hasCollectors) {\n this._deliverDebugStats({\n syncStart,\n syncEnd,\n commandBufferStart,\n commandBufferEnd,\n commandIterations,\n });\n }\n }\n\n /**\n * Creates a cached query for efficiently iterating entities with specific components.\n * The query is cached internally and reused across calls with the same component types and filter.\n *\n * **Important:** Store the query reference and reuse it across frames for optimal performance.\n * Creating a new query each frame defeats the caching mechanism.\n *\n * **Note on optional components:** Only **required** (non-optional) component types should be\n * passed to `createQuery`. Optional components (wrapped with `{ optional: ... }`) must be\n * specified at **iteration time** via {@link Query.forEach}, {@link Query.getEntitiesWithComponents},\n * or {@link Query.iterate} — NOT here. Including optional wrappers in `createQuery` will cause\n * undefined behavior because the internal normalization relies on numeric sorting of component IDs.\n *\n * @param componentTypes - Array of **required** component types to match (do not include optional wrappers)\n * @param filter - Optional filter for additional constraints (e.g., exclude entities with certain components)\n * @returns A Query instance that can be used to iterate matching entities\n *\n * @example\n * // Create once, reuse many times (required components only)\n * const movementQuery = world.createQuery([Position, Velocity]);\n *\n * // Optional components are passed at iteration time, not creation time:\n * movementQuery.forEach([Position, { optional: Velocity }], (entity, pos, vel) => {\n * pos.x += vel?.value?.x ?? 0;\n * });\n *\n * // With filter\n * const activeQuery = world.createQuery([Position], {\n * negativeComponentTypes: [Disabled]\n * });\n */\n createQuery(componentTypes: EntityId<any>[], filter: QueryFilter = {}): Query {\n const sortedTypes = normalizeComponentTypes(componentTypes);\n const filterKey = serializeQueryFilter(filter);\n const key = `${this.createArchetypeSignature(sortedTypes)}${filterKey ? `|${filterKey}` : \"\"}`;\n return this.queryRegistry.getOrCreate(this, sortedTypes, key, filter);\n }\n\n /**\n * Creates a new entity builder for fluent entity configuration.\n * Useful for building entities with multiple components in a single expression.\n *\n * @returns An EntityBuilder instance\n *\n * @example\n * const entity = world.spawn()\n * .with(Position, { x: 0, y: 0 })\n * .with(Velocity, { x: 1, y: 1 })\n * .build();\n * world.sync(); // Apply changes\n */\n spawn(): EntityBuilder {\n return new EntityBuilder(this);\n }\n\n /**\n * Spawns multiple entities with a configuration callback.\n * More efficient than calling `spawn()` multiple times when creating many entities.\n *\n * @param count - Number of entities to spawn\n * @param configure - Callback that receives an EntityBuilder and index; must return the configured builder\n * @returns Array of created entity IDs\n *\n * @example\n * const entities = world.spawnMany(100, (builder, index) => {\n * return builder\n * .with(Position, { x: index * 10, y: 0 })\n * .with(Velocity, { x: 0, y: 1 });\n * });\n * world.sync();\n */\n spawnMany(count: number, configure: (builder: EntityBuilder, index: number) => EntityBuilder): EntityId[] {\n const entities: EntityId[] = [];\n for (let i = 0; i < count; i++) {\n const builder = new EntityBuilder(this);\n entities.push(configure(builder, i).build());\n }\n return entities;\n }\n\n /**\n * Releases a cached query and frees its resources if no longer needed.\n * Call this when you're done using a query to allow the world to clean up its cache entry.\n *\n * @param query - The query to release\n *\n * @example\n * const query = world.createQuery([Position]);\n * // ... use query ...\n * world.releaseQuery(query); // Optional cleanup\n */\n releaseQuery(query: Query): void {\n this.queryRegistry.release(query);\n }\n\n /**\n * Returns all archetypes that contain entities with the specified components.\n * Used internally for query optimization but can be useful for debugging.\n *\n * @param componentTypes - Array of component types to match\n * @returns Array of Archetype objects containing matching components\n * @internal\n */\n getMatchingArchetypes(componentTypes: EntityId<any>[]): Archetype[] {\n if (componentTypes.length === 0) {\n return [...this.archetypes];\n }\n\n const regularComponents: EntityId<any>[] = [];\n const wildcardRelations: { componentId: ComponentId<any>; relationId: EntityId<any> }[] = [];\n\n for (const componentType of componentTypes) {\n if (isWildcardRelationId(componentType)) {\n const componentId = getComponentIdFromRelationId(componentType);\n if (componentId !== undefined) {\n wildcardRelations.push({ componentId, relationId: componentType });\n }\n } else {\n regularComponents.push(componentType);\n }\n }\n\n let matchingArchetypes = this.getArchetypesWithComponents(regularComponents);\n\n for (const { componentId, relationId } of wildcardRelations) {\n const markerSet = this.archetypesByComponent.get(relationId);\n const archetypesWithMarker = markerSet ? Array.from(markerSet) : [];\n matchingArchetypes =\n matchingArchetypes.length === 0\n ? archetypesWithMarker\n : matchingArchetypes.filter((a) => markerSet?.has(a) || a.hasRelationWithComponentId(componentId));\n }\n\n return matchingArchetypes;\n }\n\n private getArchetypesWithComponents(componentTypes: EntityId<any>[]): Archetype[] {\n if (componentTypes.length === 0) return [...this.archetypes];\n if (componentTypes.length === 1) {\n const set = this.archetypesByComponent.get(componentTypes[0]!);\n return set ? Array.from(set) : [];\n }\n\n // Sort by Set size, intersect starting from the smallest\n const sets = componentTypes\n .map((type) => this.archetypesByComponent.get(type))\n .filter((s): s is Set<Archetype> => s !== undefined && s.size > 0)\n .sort((a, b) => a.size - b.size);\n\n if (sets.length === 0) return [];\n if (sets.length < componentTypes.length) return []; // One component has no matching archetypes\n\n const smallest = sets[0]!;\n\n // 2-component fast path\n if (sets.length === 2) {\n const other = sets[1]!;\n return Array.from(smallest).filter((a) => other.has(a));\n }\n\n // Multi-component intersection\n let result = new Set(smallest);\n for (let i = 1; i < sets.length; i++) {\n for (const item of result) {\n if (!sets[i]!.has(item)) result.delete(item);\n }\n if (result.size === 0) return [];\n }\n return Array.from(result);\n }\n\n /**\n * Queries entities with specific components.\n * For simpler use cases, prefer using `createQuery()` with `forEach()` which is cached and more efficient.\n *\n * @overload query(componentTypes: EntityId<any>[]): EntityId[]\n * Returns an array of entity IDs that have all specified components.\n *\n * @overload query<const T extends readonly EntityId<any>[]>(\n * componentTypes: T,\n * includeComponents: true,\n * ): Array<{ entity: EntityId; components: ComponentTuple<T> }>\n * Returns entities along with their component data.\n *\n * @param componentTypes - Array of component types to query\n * @param includeComponents - If true, includes component data in results\n * @returns Array of entity IDs or objects with entities and components\n *\n * @example\n * // Just entity IDs\n * const entities = world.query([Position, Velocity]);\n *\n * // With components\n * const results = world.query([Position, Velocity], true);\n * results.forEach(({ entity, components: [pos, vel] }) => {\n * pos.x += vel.x;\n * });\n */\n query(componentTypes: EntityId<any>[]): EntityId[];\n query<const T extends readonly EntityId<any>[]>(\n componentTypes: T,\n includeComponents: true,\n ): Array<{ entity: EntityId; components: ComponentTuple<T> }>;\n query(\n componentTypes: EntityId<any>[],\n includeComponents?: boolean,\n ): EntityId[] | Array<{ entity: EntityId; components: any }> {\n const matchingArchetypes = this.getMatchingArchetypes(componentTypes);\n\n if (includeComponents) {\n const result: Array<{ entity: EntityId; components: any }> = [];\n for (const archetype of matchingArchetypes) {\n archetype.appendEntitiesWithComponents(componentTypes as EntityId<any>[], result);\n }\n return result;\n } else {\n const result: EntityId[] = [];\n for (const archetype of matchingArchetypes) {\n for (const entity of archetype.getEntities()) {\n result.push(entity);\n }\n }\n return result;\n }\n }\n\n private executeEntityCommands(entityId: EntityId, commands: Command[]): void {\n this._changeset.clear();\n\n // 1. Route: component entities use flat-map storage\n if (this.componentEntities.exists(entityId)) {\n this.componentEntities.executeCommands(entityId, commands);\n return;\n }\n\n // 2. Route: destroy uses fast path\n if (commands.some((cmd) => cmd.type === \"destroy\")) {\n this.destroyEntityImmediate(entityId);\n return;\n }\n\n // 3. Apply structural changes\n this.applyEntityCommands(entityId, commands);\n }\n\n private applyEntityCommands(entityId: EntityId, commands: Command[]): void {\n const currentArchetype = this.entityToArchetype.get(entityId);\n if (!currentArchetype) return;\n\n const changeset = this._changeset;\n processCommands(entityId, currentArchetype, commands, changeset, (eid, arch, compId) => {\n if (isExclusiveComponent(compId)) {\n removeMatchingRelations(eid, arch, compId, changeset);\n }\n });\n\n const hasStructuralChange = changeset.removes.size > 0 || changeset.adds.size > 0;\n\n if (this.hooks.size === 0) {\n // Fast path: no hooks, skip removedComponents map allocation and hook triggering\n const newArchetype = applyChangeset(\n this._commandCtx,\n entityId,\n currentArchetype,\n changeset,\n this.entityToArchetype,\n null,\n );\n if (hasStructuralChange) {\n this.updateEntityReferences(entityId, changeset);\n }\n if (this._debugCollectors.size > 0 && newArchetype !== currentArchetype) {\n this._debugMigrations++;\n }\n return;\n }\n\n const removedComponents = new Map<EntityId<any>, any>();\n const newArchetype = applyChangeset(\n this._commandCtx,\n entityId,\n currentArchetype,\n changeset,\n this.entityToArchetype,\n removedComponents,\n );\n\n if (hasStructuralChange) {\n this.updateEntityReferences(entityId, changeset);\n }\n\n if (this._debugCollectors.size > 0 && newArchetype !== currentArchetype) {\n this._debugMigrations++;\n }\n\n triggerLifecycleHooks(\n this.createHooksContext(),\n entityId,\n changeset.adds,\n removedComponents,\n currentArchetype,\n newArchetype,\n );\n }\n\n private createHooksContext(): HooksContext {\n return this._hooksCtx;\n }\n\n private removeComponentImmediate(entityId: EntityId, componentType: EntityId<any>, targetEntityId: EntityId): void {\n const sourceArchetype = this.entityToArchetype.get(entityId);\n if (!sourceArchetype) return;\n\n const changeset = this._removeChangeset;\n changeset.clear();\n changeset.delete(componentType);\n maybeRemoveWildcardMarker(\n entityId,\n sourceArchetype,\n componentType,\n getComponentIdFromRelationId(componentType),\n changeset,\n );\n\n const removedComponent = sourceArchetype.get(entityId, componentType);\n const newArchetype = applyChangeset(\n this._commandCtx,\n entityId,\n sourceArchetype,\n changeset,\n this.entityToArchetype,\n null,\n );\n untrackEntityReference(this.entityReferences, entityId, componentType, targetEntityId);\n triggerLifecycleHooks(\n this.createHooksContext(),\n entityId,\n new Map(),\n new Map([[componentType, removedComponent]]),\n sourceArchetype,\n newArchetype,\n );\n }\n\n private updateEntityReferences(entityId: EntityId, changeset: ComponentChangeset): void {\n for (const componentType of changeset.removes) {\n if (isEntityRelation(componentType)) {\n const targetId = getTargetIdFromRelationId(componentType)!;\n untrackEntityReference(this.entityReferences, entityId, componentType, targetId);\n } else if (componentType >= ENTITY_ID_START) {\n untrackEntityReference(this.entityReferences, entityId, componentType, componentType);\n }\n }\n\n for (const [componentType] of changeset.adds) {\n if (isEntityRelation(componentType)) {\n const targetId = getTargetIdFromRelationId(componentType)!;\n trackEntityReference(this.entityReferences, entityId, componentType, targetId);\n } else if (componentType >= ENTITY_ID_START) {\n trackEntityReference(this.entityReferences, entityId, componentType, componentType);\n }\n }\n }\n\n private ensureArchetype(componentTypes: Iterable<EntityId<any>>): Archetype {\n const regularTypes = filterRegularComponentTypes(componentTypes);\n const sortedTypes = normalizeComponentTypes(regularTypes);\n const hashKey = this.createArchetypeSignature(sortedTypes);\n\n return getOrCompute(this.archetypeBySignature, hashKey, () => this.createNewArchetype(sortedTypes));\n }\n\n /** Add componentType to the reverse index if it contains an entity ID */\n private addToReferencingIndex(componentType: EntityId<any>, archetype: Archetype): void {\n const detailedType = getDetailedIdType(componentType);\n let entityId: EntityId | undefined;\n\n if (detailedType.type === \"entity\") {\n entityId = componentType as EntityId;\n } else if (detailedType.type === \"entity-relation\") {\n entityId = detailedType.targetId;\n }\n\n if (entityId !== undefined) {\n let refs = this.entityToReferencingArchetypes.get(entityId);\n if (!refs) {\n refs = new Set();\n this.entityToReferencingArchetypes.set(entityId, refs);\n }\n refs.add(archetype);\n }\n }\n\n /** Remove componentType from the reverse index */\n private removeFromReferencingIndex(componentType: EntityId<any>, archetype: Archetype): void {\n const detailedType = getDetailedIdType(componentType);\n let entityId: EntityId | undefined;\n\n if (detailedType.type === \"entity\") {\n entityId = componentType as EntityId;\n } else if (detailedType.type === \"entity-relation\") {\n entityId = detailedType.targetId;\n }\n\n if (entityId !== undefined) {\n const refs = this.entityToReferencingArchetypes.get(entityId);\n if (refs) {\n refs.delete(archetype);\n if (refs.size === 0) {\n this.entityToReferencingArchetypes.delete(entityId);\n }\n }\n }\n }\n\n private createNewArchetype(componentTypes: EntityId<any>[]): Archetype {\n const newArchetype = new Archetype(componentTypes, this.sparseStore);\n this.archetypes.push(newArchetype);\n\n if (this._debugCollectors.size > 0) {\n this._debugArchetypesCreated++;\n }\n\n for (const componentType of componentTypes) {\n let archetypes = this.archetypesByComponent.get(componentType);\n if (!archetypes) {\n archetypes = new Set();\n this.archetypesByComponent.set(componentType, archetypes);\n }\n archetypes.add(newArchetype);\n\n // Update reverse index\n this.addToReferencingIndex(componentType, newArchetype);\n }\n\n this.queryRegistry.onNewArchetype(newArchetype);\n this.updateArchetypeHookMatches(newArchetype);\n\n return newArchetype;\n }\n\n private updateArchetypeHookMatches(archetype: Archetype): void {\n for (const entry of this.hooks) {\n if (this.archetypeMatchesHook(archetype, entry)) {\n archetype.matchingMultiHooks.add(entry);\n if (entry.matchedArchetypes) {\n entry.matchedArchetypes.add(archetype);\n }\n }\n }\n }\n\n private archetypeMatchesHook(archetype: Archetype, entry: LifecycleHookEntry): boolean {\n return (\n entry.requiredComponents.every((c: EntityId<any>) => {\n if (isWildcardRelationId(c)) {\n if (isSparseWildcard(c)) return true;\n const componentId = getComponentIdFromRelationId(c);\n return componentId !== undefined && archetype.hasRelationWithComponentId(componentId);\n }\n return archetype.componentTypeSet.has(c) || isSparseRelation(c);\n }) && matchesFilter(archetype, entry.filter)\n );\n }\n\n private cleanupArchetypesReferencingEntity(entityId: EntityId): void {\n const refs = this.entityToReferencingArchetypes.get(entityId);\n if (!refs) return;\n\n for (const archetype of refs) {\n if (archetype.getEntities().length === 0) {\n this.removeArchetype(archetype);\n }\n }\n // removeArchetype already cleans up the reverse index entries\n this.entityToReferencingArchetypes.delete(entityId);\n }\n\n private removeArchetype(archetype: Archetype): void {\n const index = this.archetypes.indexOf(archetype);\n if (index !== -1) {\n // swap-and-pop: O(1) removal\n const last = this.archetypes[this.archetypes.length - 1]!;\n this.archetypes[index] = last;\n this.archetypes.pop();\n }\n\n if (this._debugCollectors.size > 0) {\n this._debugArchetypesRemoved++;\n }\n\n this.archetypeBySignature.delete(this.createArchetypeSignature(archetype.componentTypes));\n\n for (const componentType of archetype.componentTypes) {\n const archetypes = this.archetypesByComponent.get(componentType);\n if (archetypes) {\n archetypes.delete(archetype);\n if (archetypes.size === 0) {\n this.archetypesByComponent.delete(componentType);\n }\n }\n\n // Clean up reverse index\n this.removeFromReferencingIndex(componentType, archetype);\n }\n\n this.queryRegistry.onArchetypeRemoved(archetype);\n }\n\n /**\n * Serializes the entire world state to a plain JavaScript object.\n * This creates a \"memory snapshot\" that can be stored or transmitted.\n * The snapshot can be restored using `new World(snapshot)`.\n *\n * **Note:** This is NOT automatically persistent storage. To persist data,\n * you must serialize the returned object to JSON or another format yourself.\n *\n * @returns A serializable object representing the world state\n *\n * @example\n * // Create snapshot\n * const snapshot = world.serialize();\n *\n * // Save to storage (example)\n * localStorage.setItem('save', JSON.stringify(snapshot));\n *\n * // Later, restore from snapshot\n * const savedData = JSON.parse(localStorage.getItem('save'));\n * const newWorld = new World(savedData);\n */\n serialize(): SerializedWorld {\n return serializeWorld(this.archetypes, this.componentEntities, this.entityIdManager);\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"world.mjs","names":[],"sources":["../src/entity/types.ts","../src/entity/relation.ts","../src/entity/manager.ts","../src/utils/bit-set.ts","../src/component/registry.ts","../src/world/builder.ts","../src/world/singleton.ts","../src/archetype/store.ts","../src/commands/buffer.ts","../src/types/index.ts","../src/component/type-utils.ts","../src/utils/utils.ts","../src/archetype/archetype.ts","../src/archetype/helpers.ts","../src/component/entity-store.ts","../src/query/filter.ts","../src/query/query.ts","../src/query/registry.ts","../src/world/commands.ts","../src/world/archetype-manager.ts","../src/commands/changeset.ts","../src/world/hooks.ts","../src/utils/multi-map.ts","../src/world/references.ts","../src/world/command-executor.ts","../src/world/debug-stats.ts","../src/world/operations.ts","../src/storage/serialization.ts","../src/world/serialization.ts","../src/world/world.ts"],"sourcesContent":["/**\n * Unique symbol brand for associating component type information with EntityId\n */\ndeclare const __componentTypeMarker: unique symbol;\n\n/**\n * Unique symbol brand for tagging the kind of EntityId (e.g., 'component', 'entity-relation')\n */\ndeclare const __entityIdTypeTag: unique symbol;\n\n/**\n * Entity ID type for ECS architecture\n * Based on 52-bit integers within safe integer range\n * - Component IDs: 1-1023\n * - Entity IDs: 1024+\n * - Relation IDs: negative numbers encoding component and entity associations\n */\n/**\n * Branded numeric type representing an ECS identifier.\n *\n * - {@link ComponentId}: positive values in range `1–1023`\n * - Entity IDs: values `1024+`\n * - {@link RelationId}: negative values encoding `(componentId, targetId)`\n *\n * @template T - The data type associated with this ID\n * @template U - Discriminant for the ID kind (e.g. `\"component\"`, `\"entity-relation\"`)\n */\nexport type EntityId<T = unknown, U = unknown> = number & {\n readonly [__componentTypeMarker]: T;\n readonly [__entityIdTypeTag]: U;\n};\n\n/**\n * Component identifier. Valid values are `1` through `1023`.\n * Created with {@link component}.\n *\n * @template T - The data type stored by this component (`void` for tag components)\n */\nexport type ComponentId<T = void> = EntityId<T, \"component\">;\n\n/**\n * Relation identifier targeting an entity.\n * Created with {@link relation}.\n *\n * @template T - The data type stored by this relation\n */\nexport type EntityRelationId<T = void> = EntityId<T, \"entity-relation\">;\n\n/**\n * Relation identifier targeting another component (singleton relation).\n * Created with {@link relation}.\n *\n * @template T - The data type stored by this relation\n */\nexport type ComponentRelationId<T = void> = EntityId<T, \"component-relation\">;\n\n/**\n * Wildcard relation identifier used to query all targets of a given relation component.\n * Created with `relation(componentId, \"*\")`.\n *\n * @template T - The data type stored by the relation\n */\nexport type WildcardRelationId<T = void> = EntityId<T, \"wildcard-relation\">;\n\n/**\n * Union of all relation identifier kinds.\n *\n * @template T - The data type stored by the relation\n */\nexport type RelationId<T = void> = EntityRelationId<T> | ComponentRelationId<T> | WildcardRelationId<T>;\n\n/**\n * Constants for ID ranges\n */\nexport const INVALID_COMPONENT_ID = 0;\nexport const COMPONENT_ID_MAX = 1023;\nexport const ENTITY_ID_START = 1024;\n\n/**\n * Constants for relation ID encoding\n */\nexport const RELATION_SHIFT = 2 ** 42;\nexport const WILDCARD_TARGET_ID = 0;\n\n/**\n * Check if a component ID is valid (1-1023)\n */\nexport function isValidComponentId(componentId: number): boolean {\n return componentId >= 1 && componentId <= COMPONENT_ID_MAX;\n}\n\n/**\n * Check if an ID is a component ID\n */\nexport function isComponentId<T>(id: EntityId<T>): id is ComponentId<T> {\n return id >= 1 && id <= COMPONENT_ID_MAX;\n}\n\n/**\n * Check if an ID is an entity ID\n */\nexport function isEntityId<T>(id: EntityId<T>): id is EntityId<T> {\n return id >= ENTITY_ID_START;\n}\n\n/**\n * Check if an ID is a relation ID\n */\nexport function isRelationId<T>(id: EntityId<T>): id is RelationId<T> {\n return id < 0;\n}\n\n/**\n * Create a component ID\n * @param id Component identifier (1-1023)\n * @internal This function is for internal use and testing only. Use `component()` to create components.\n * @see component\n */\nexport function createComponentId<T = void>(id: number): ComponentId<T> {\n if (id < 1 || id > COMPONENT_ID_MAX) {\n throw new Error(`Component ID must be between 1 and ${COMPONENT_ID_MAX}`);\n }\n return id as ComponentId<T>;\n}\n\n/**\n * Create an entity ID\n * @param id Entity identifier (starting from 1024)\n */\nexport function createEntityId(id: number): EntityId {\n if (id < ENTITY_ID_START) {\n throw new Error(`Entity ID must be ${ENTITY_ID_START} or greater`);\n }\n return id as EntityId;\n}\n","import type {\n ComponentId,\n ComponentRelationId,\n EntityId,\n EntityRelationId,\n RelationId,\n WildcardRelationId,\n} from \"./types\";\nimport {\n ENTITY_ID_START,\n isComponentId,\n isEntityId,\n isValidComponentId,\n RELATION_SHIFT,\n WILDCARD_TARGET_ID,\n} from \"./types\";\n\n/**\n * Internal function to decode a relation ID into raw component and target IDs\n * @param id The EntityId to decode\n * @returns Object with componentId and targetId, or null if not a relation\n */\nexport function decodeRelationRaw(id: EntityId<any>): { componentId: number; targetId: number } | null {\n if (id >= 0) return null;\n const absId = -id;\n const componentId = Math.floor(absId / RELATION_SHIFT);\n const targetId = absId % RELATION_SHIFT;\n return { componentId, targetId };\n}\n\n/**\n * Type for relation ID based on component and target types\n */\ntype RelationIdType<T, R> =\n R extends ComponentId<infer U>\n ? U extends void\n ? ComponentRelationId<T>\n : ComponentRelationId<T extends void ? U : T>\n : R extends EntityId<any>\n ? EntityRelationId<T>\n : never;\n\n/**\n * Create a relation ID by associating a component with a target entity, component, or wildcard.\n *\n * Relations are encoded as negative numbers and can be used anywhere a regular component ID is accepted.\n * Use `\"*\"` as the target to create a wildcard relation for querying all targets of a given relation type.\n *\n * @param componentId - The base component ID (must be a valid component)\n * @param targetId - The target entity ID, component ID, or `\"*\"` for wildcard\n * @returns A relation ID that encodes both the component and target\n *\n * @throws {Error} If `componentId` is not a valid component ID\n * @throws {Error} If `targetId` is not a valid entity, component, or `\"*\"`\n *\n * @example\n * const ChildOf = component();\n * const parent = world.new();\n *\n * // Entity relation\n * const childRelation = relation(ChildOf, parent);\n * world.set(child, childRelation);\n *\n * // Wildcard relation (queries all targets)\n * const allChildren = world.createQuery([relation(ChildOf, \"*\")]);\n */\nexport function relation<T>(componentId: ComponentId<T>, targetId: \"*\"): WildcardRelationId<T>;\nexport function relation<T, R extends EntityId<any>>(componentId: ComponentId<T>, targetId: R): RelationIdType<T, R>;\nexport function relation<T>(componentId: ComponentId<T>, targetId: EntityId<any> | \"*\"): EntityId<any> {\n if (!isComponentId(componentId)) {\n throw new Error(\"First argument must be a valid component ID\");\n }\n\n let actualTargetId: number;\n if (targetId === \"*\") {\n actualTargetId = WILDCARD_TARGET_ID;\n } else {\n if (!isEntityId(targetId) && !isComponentId(targetId)) {\n throw new Error(\"Second argument must be a valid entity ID, component ID, or '*'\");\n }\n actualTargetId = targetId;\n }\n\n // Encode: negative number with component_id * 2^42 + target_id\n return -(componentId * RELATION_SHIFT + actualTargetId) as EntityId<any>;\n}\n\n/**\n * Check if an ID is a wildcard relation (created with `relation(componentId, \"*\")`).\n *\n * @param id - The ID to check\n * @returns `true` if the ID is a wildcard relation, `false` otherwise\n */\nexport function isWildcardRelationId<T>(id: EntityId<T>): id is WildcardRelationId<T> {\n const decoded = decodeRelationRaw(id);\n return decoded !== null && decoded.targetId === WILDCARD_TARGET_ID;\n}\n\n/**\n * Decode a relation ID into component and target IDs\n * @param relationId The relation ID (must be negative)\n * @returns Object with componentId, targetId, and relation type\n */\nexport function decodeRelationId(relationId: RelationId<any>): {\n componentId: ComponentId<any>;\n targetId: EntityId<any>;\n type: \"entity\" | \"component\" | \"wildcard\";\n} {\n const decoded = decodeRelationRaw(relationId);\n if (decoded === null) {\n throw new Error(\"ID is not a relation ID\");\n }\n\n const { componentId: rawComponentId, targetId: rawTargetId } = decoded;\n if (!isValidComponentId(rawComponentId)) {\n throw new Error(\"Invalid component ID in relation\");\n }\n\n const componentId = rawComponentId as ComponentId<any>;\n const targetId = rawTargetId as EntityId<any>;\n\n // Determine type based on targetId range\n if (targetId === WILDCARD_TARGET_ID) {\n return { componentId, targetId, type: \"wildcard\" };\n } else if (isEntityId(targetId)) {\n return { componentId, targetId, type: \"entity\" };\n } else if (isComponentId(targetId)) {\n return { componentId, targetId, type: \"component\" };\n } else {\n throw new Error(\"Invalid target ID in relation\");\n }\n}\n\n/**\n * Get the string representation of an ID type\n */\nexport function getIdType(\n id: EntityId<any>,\n): \"component\" | \"entity\" | \"entity-relation\" | \"component-relation\" | \"wildcard-relation\" | \"invalid\" {\n if (isComponentId(id)) return \"component\";\n if (isEntityId(id)) return \"entity\";\n\n if (id < 0) {\n const decoded = decodeRelationRaw(id as RelationId<any>);\n if (decoded === null) return \"invalid\";\n\n const { componentId: rawComponentId, targetId: rawTargetId } = decoded;\n\n // Validate component ID\n if (!isValidComponentId(rawComponentId)) return \"invalid\";\n\n // Determine type based on targetId range\n if (rawTargetId === WILDCARD_TARGET_ID) {\n return \"wildcard-relation\";\n } else if (isEntityId(rawTargetId as EntityId<any>)) {\n return \"entity-relation\";\n } else if (isComponentId(rawTargetId as ComponentId<any>)) {\n return \"component-relation\";\n } else {\n return \"invalid\";\n }\n }\n\n return \"invalid\"; // fallback for unknown/invalid IDs\n}\n\n/**\n * Get detailed type information for an EntityId\n * @param id The EntityId to analyze\n * @returns Detailed type information including relation subtypes\n */\nexport function getDetailedIdType(id: EntityId<any>):\n | {\n type: \"component\" | \"entity\" | \"invalid\";\n componentId?: never;\n targetId?: never;\n }\n | {\n type: \"entity-relation\" | \"wildcard-relation\";\n componentId: ComponentId<any>;\n targetId: EntityId<any>;\n }\n | {\n type: \"component-relation\";\n componentId: ComponentId<any>;\n targetId: ComponentId<any>;\n } {\n if (isComponentId(id)) {\n return { type: \"component\" };\n }\n\n if (isEntityId(id)) {\n return { type: \"entity\" };\n }\n\n if (id < 0) {\n const decoded = decodeRelationRaw(id as RelationId<any>);\n if (decoded === null) {\n return { type: \"invalid\" };\n }\n\n const { componentId: rawComponentId, targetId: rawTargetId } = decoded;\n\n // Validate component ID\n if (!isValidComponentId(rawComponentId)) {\n return { type: \"invalid\" };\n }\n\n const componentId = rawComponentId as ComponentId<any>;\n const targetId = rawTargetId as EntityId<any>;\n\n // Determine type based on targetId range\n if (targetId === WILDCARD_TARGET_ID) {\n return { type: \"wildcard-relation\", componentId, targetId };\n } else if (isEntityId(targetId)) {\n return { type: \"entity-relation\", componentId, targetId };\n } else if (isComponentId(targetId as any)) {\n return { type: \"component-relation\", componentId, targetId: targetId as ComponentId<any> };\n } else {\n return { type: \"invalid\" };\n }\n }\n\n // Unknown/invalid ID\n return { type: \"invalid\" };\n}\n\n/**\n * Inspect an EntityId and return a human-readable string representation\n * @param id The EntityId to inspect\n * @returns A friendly string representation of the ID\n */\nexport function inspectEntityId(id: EntityId<any>): string {\n if (id === 0) {\n return \"Invalid Component ID (0)\";\n }\n\n if (isComponentId(id)) {\n return `Component ID (${id})`;\n }\n\n if (isEntityId(id)) {\n return `Entity ID (${id})`;\n }\n\n if (id < 0) {\n const decoded = decodeRelationRaw(id as RelationId<any>);\n if (decoded === null) {\n return `Invalid Relation ID (${id})`;\n }\n\n const { componentId: rawComponentId, targetId: rawTargetId } = decoded;\n\n // Validate component ID\n if (!isValidComponentId(rawComponentId)) {\n return `Invalid Relation ID (${id})`;\n }\n\n // Determine target type and format output\n const componentStr = `Component ID (${rawComponentId})`;\n let targetStr: string;\n\n if (rawTargetId === WILDCARD_TARGET_ID) {\n targetStr = \"Wildcard (*)\";\n } else if (isEntityId(rawTargetId as EntityId<any>)) {\n targetStr = `Entity ID (${rawTargetId})`;\n } else if (isComponentId(rawTargetId as ComponentId<any>)) {\n targetStr = `Component ID (${rawTargetId})`;\n } else {\n return `Invalid Relation ID (${id})`;\n }\n\n return `Relation ID: ${componentStr} -> ${targetStr}`;\n }\n\n return `Unknown ID (${id})`;\n}\n\n/**\n * Get the componentId from a relation ID without fully decoding the relation.\n * Returns undefined for non-relation IDs or invalid component IDs.\n */\nexport function getComponentIdFromRelationId<T>(id: EntityId<T>): ComponentId<T> | undefined {\n const decoded = decodeRelationRaw(id);\n if (decoded === null || !isValidComponentId(decoded.componentId)) return undefined;\n return decoded.componentId as ComponentId<T>;\n}\n\n/**\n * Get the targetId from a relation ID without fully decoding the relation.\n * Returns undefined for non-relation IDs.\n */\nexport function getTargetIdFromRelationId(id: EntityId<any>): EntityId<any> | undefined {\n const decoded = decodeRelationRaw(id);\n return decoded?.targetId as EntityId<any>;\n}\n\n/**\n * Check if an ID is an entity-relation (relation targeting an entity, not a component or wildcard)\n */\nexport function isEntityRelation(id: EntityId<any>): boolean {\n const decoded = decodeRelationRaw(id);\n return decoded !== null && decoded.targetId >= ENTITY_ID_START;\n}\n\n/**\n * Check if an ID is a component-relation (relation targeting a component)\n */\nexport function isComponentRelation(id: EntityId<any>): boolean {\n const decoded = decodeRelationRaw(id);\n return decoded !== null && isValidComponentId(decoded.targetId);\n}\n\n/**\n * Check if an ID is any type of relation (entity, component, or wildcard)\n */\nexport function isAnyRelation(id: EntityId<any>): boolean {\n return id < 0;\n}\n","import type { ComponentId, EntityId } from \"./types\";\nimport { COMPONENT_ID_MAX, ENTITY_ID_START, isEntityId } from \"./types\";\n\n/**\n * Entity ID Manager for automatic allocation and freelist recycling\n */\nexport class EntityIdManager {\n private nextId: number = ENTITY_ID_START;\n /**\n * Free list uses a stack (LIFO) for better memory locality when reusing IDs.\n * We use an array instead of a Set for significantly better performance.\n */\n private freelist: EntityId[] = [];\n\n /**\n * Allocate a new entity ID\n * Uses freelist if available, otherwise increments counter\n */\n allocate(): EntityId {\n if (this.freelist.length > 0) {\n return this.freelist.pop()!;\n } else {\n const id = this.nextId;\n this.nextId++;\n // Check for overflow (though unlikely in practice)\n if (this.nextId >= Number.MAX_SAFE_INTEGER) {\n throw new Error(\"Entity ID overflow: reached maximum safe integer\");\n }\n return id as EntityId;\n }\n }\n\n /**\n * Deallocate an entity ID, adding it to the freelist for reuse\n * @param id The entity ID to deallocate\n */\n deallocate(id: EntityId<any>): void {\n if (!isEntityId(id)) {\n throw new Error(\"Can only deallocate valid entity IDs\");\n }\n if (id >= this.nextId) {\n throw new Error(\"Cannot deallocate an ID that was never allocated\");\n }\n this.freelist.push(id);\n }\n\n /**\n * Get the current freelist size (for debugging/monitoring)\n */\n getFreelistSize(): number {\n return this.freelist.length;\n }\n\n /**\n * Get the next ID that would be allocated (for debugging)\n */\n getNextId(): number {\n return this.nextId;\n }\n\n /**\n * Serialize internal state for persistence.\n * Returns a plain object representing allocator state. Values may be non-JSON-serializable.\n */\n serializeState(): { nextId: number; freelist: number[] } {\n return { nextId: this.nextId, freelist: Array.from(this.freelist) };\n }\n\n /**\n * Restore internal state from a previously-serialized object.\n * Overwrites the current nextId and freelist.\n */\n deserializeState(state: { nextId: number; freelist?: number[] }): void {\n if (typeof state.nextId !== \"number\") {\n throw new Error(\"Invalid state for EntityIdManager.deserializeState\");\n }\n this.nextId = state.nextId;\n this.freelist = (state.freelist || []) as EntityId[];\n }\n}\n\n/**\n * Component ID Manager for automatic allocation\n * Components are typically registered once and not recycled\n */\nexport class ComponentIdAllocator {\n private nextId: number = 1;\n\n /**\n * Allocate a new component ID\n * Increments counter sequentially from 1\n */\n allocate<T = void>(): ComponentId<T> {\n if (this.nextId > COMPONENT_ID_MAX) {\n throw new Error(`Component ID overflow: maximum ${COMPONENT_ID_MAX} components allowed`);\n }\n const id = this.nextId;\n this.nextId++;\n return id as ComponentId<T>;\n }\n\n /**\n * Get the next ID that would be allocated (for debugging)\n */\n getNextId(): number {\n return this.nextId;\n }\n\n /**\n * Check if more component IDs are available\n */\n hasAvailableIds(): boolean {\n return this.nextId <= COMPONENT_ID_MAX;\n }\n}\n","export class BitSet {\n private data: Uint32Array;\n private _length: number;\n\n constructor(length: number) {\n this._length = length;\n const numWords = Math.ceil(length / 32);\n this.data = new Uint32Array(numWords);\n }\n\n get length(): number {\n return this._length;\n }\n\n has(index: number): boolean {\n if (index < 0 || index >= this._length) return false;\n const word = index >>> 5; // divide by 32\n const bit = index & 31;\n return ((this.data[word]! >>> bit) & 1) !== 0;\n }\n\n set(index: number): void {\n if (index < 0 || index >= this._length) return;\n const word = index >>> 5;\n const bit = index & 31;\n this.data[word]! |= 1 << bit;\n }\n\n clear(index: number): void {\n if (index < 0 || index >= this._length) return;\n const word = index >>> 5;\n const bit = index & 31;\n this.data[word]! &= ~(1 << bit);\n }\n\n // set a range [lo, hi] inclusive to 1\n setRange(lo: number, hi: number): void {\n if (lo > hi) return;\n if (lo < 0) lo = 0;\n if (hi >= this._length) hi = this._length - 1;\n\n const firstWord = lo >>> 5;\n const lastWord = hi >>> 5;\n const loBit = lo & 31;\n const hiBit = hi & 31;\n\n // helper to produce mask for [a..b] within a single 32-bit word\n const maskFor = (a: number, b: number) => {\n const width = b - a + 1;\n if (width <= 0) return 0 >>> 0;\n if (width >= 32) return 0xffffffff >>> 0;\n return (((1 << width) - 1) << a) >>> 0;\n };\n\n if (firstWord === lastWord) {\n const mask = maskFor(loBit, hiBit);\n this.data[firstWord]! = (this.data[firstWord]! | mask) >>> 0;\n return;\n }\n\n // first partial word\n const firstMask = maskFor(loBit, 31);\n this.data[firstWord]! = (this.data[firstWord]! | firstMask) >>> 0;\n\n // middle full words\n for (let w = firstWord + 1; w <= lastWord - 1; w++) {\n this.data[w] = 0xffffffff >>> 0;\n }\n\n // last partial word\n const lastMask = maskFor(0, hiBit);\n this.data[lastWord]! = (this.data[lastWord]! | lastMask) >>> 0;\n }\n\n // check whether any bit in [lo, hi] is zero (i.e. not set)\n anyClearInRange(lo: number, hi: number): boolean {\n if (lo > hi) return false;\n if (lo < 0) lo = 0;\n if (hi >= this._length) hi = this._length - 1;\n\n const firstWord = lo >>> 5;\n const lastWord = hi >>> 5;\n const loBit = lo & 31;\n const hiBit = hi & 31;\n\n const maskFor = (a: number, b: number) => {\n const width = b - a + 1;\n if (width <= 0) return 0 >>> 0;\n if (width >= 32) return 0xffffffff >>> 0;\n return (((1 << width) - 1) << a) >>> 0;\n };\n\n if (firstWord === lastWord) {\n const mask = maskFor(loBit, hiBit);\n const bits = (this.data[firstWord]! & mask) >>> 0;\n return bits !== mask >>> 0;\n }\n\n // first partial word: if any bit in the mask is clear -> return true\n const firstMask = maskFor(loBit, 31);\n if ((this.data[firstWord]! & firstMask) >>> 0 !== firstMask >>> 0) return true;\n\n // middle full words\n for (let w = firstWord + 1; w <= lastWord - 1; w++) {\n if (this.data[w] !== 0xffffffff >>> 0) return true;\n }\n\n // last partial word\n const lastMask = maskFor(0, hiBit);\n if ((this.data[lastWord]! & lastMask) >>> 0 !== lastMask >>> 0) return true;\n\n return false;\n }\n\n // reset all bits to zero\n reset(): void {\n this.data.fill(0);\n }\n\n *[Symbol.iterator](): IterableIterator<number> {\n for (let wordIndex = 0; wordIndex < this.data.length; wordIndex++) {\n let word = this.data[wordIndex]!;\n if (word === 0) continue;\n const baseIndex = wordIndex * 32;\n for (let bit = 0; bit < 32 && baseIndex + bit < this._length; bit++) {\n if (word & 1) {\n yield baseIndex + bit;\n }\n word >>>= 1;\n }\n }\n }\n}\n","import { ComponentIdAllocator } from \"../entity/manager\";\nimport { decodeRelationRaw } from \"../entity/relation\";\nimport type { ComponentId, EntityId } from \"../entity/types\";\nimport {\n COMPONENT_ID_MAX,\n ENTITY_ID_START,\n isComponentId,\n isValidComponentId,\n WILDCARD_TARGET_ID,\n} from \"../entity/types\";\nimport { BitSet } from \"../utils/bit-set\";\n\nconst globalComponentIdAllocator = new ComponentIdAllocator();\n\nconst ComponentIdForNames: Map<string, ComponentId<any>> = new Map();\n\n/**\n * Merge function type for combining repeated `set()` values within a single sync batch.\n *\n * When `world.set(entity, componentType, value)` is called **multiple times** for the\n * same entity and same component type **before** the next `world.sync()`, the merge\n * callback is invoked to combine the values instead of simply overwriting. This allows\n * additive or custom composition of component data in a single frame.\n *\n * @typeParam T - The component's value type.\n *\n * @param prev - The value from the **previous** `set()` call (or the merged result of\n * earlier calls) for this entity/componentType pair within the current sync batch.\n * @param next - The value from the **current** `set()` call being processed.\n *\n * @returns The merged value to be stored. This becomes `prev` if another `set()` for\n * the same entity and componentType is encountered later in the same batch.\n *\n * @remarks\n * **Idempotency**: Merge functions **must be idempotent**. The ECS does not guarantee\n * that `world.sync()` won't be called multiple times in edge cases (e.g., intermediate\n * syncs during pipeline execution), so the merge result should not depend on call\n * count or non-deterministic state.\n *\n * **Single-batch scope**: Merging only applies to `set()` calls within the **same sync\n * batch** (i.e., between two `world.sync()` calls). After `world.sync()`, the component\n * value is committed to storage, and the next `set()` starts with a fresh `prev` value.\n *\n * @example\n * ```ts\n * // Accumulate damage events in a single frame\n * const DamageEvents = component<DamageEvent[]>({\n * merge: (prev, next) => [...prev, ...next],\n * });\n *\n * world.set(player, DamageEvents, [{ source: \"fire\", amount: 10 }]);\n * world.set(player, DamageEvents, [{ source: \"ice\", amount: 5 }]);\n * // After sync: player has [{ source: \"fire\", amount: 10 }, { source: \"ice\", amount: 5 }]\n * ```\n */\ntype ComponentMerge<T = any> = (prev: T, next: T) => T;\n\n/**\n * Component options that define intrinsic properties\n */\nexport interface ComponentOptions<T = any> {\n /**\n * An optional human-readable name for the component, used for debugging and\n * serialization.\n *\n * While `name` is **optional** at registration time, omitting it can cause\n * problems when serializing and later deserializing the world:\n *\n * 1. **Cross-session portability**: Without a name, the component is\n * serialized as a raw numeric ID. Component IDs are allocated sequentially\n * at registration time, so if the order of `component()` calls changes\n * between sessions (e.g. due to code refactoring, lazy-loading, or\n * tree-shaking), those numeric IDs will no longer point to the same\n * component type, leading to **silent data corruption** on restore.\n *\n * 2. **Runtime warnings**: `encodeEntityId` logs a `console.warn` for every\n * unnamed component it encounters during `world.serialize()`, which can be\n * noisy in production when serialization is used for save-games or\n * snapshots.\n *\n * 3. **Debugging ergonomics**: Named components make serialized snapshots\n * human-readable (e.g. `\"Position\"` instead of `42`), which is invaluable\n * when inspecting save files or network dumps.\n *\n * **Recommendation**: Always provide a `name` for any component that may\n * appear in a serialized world — even if it's just the same string as the\n * variable name.\n *\n * @example\n * ```ts\n * // ✅ Good: explicit name ensures stable serialization\n * const Position = component<{ x: number; y: number }>({ name: \"Position\" });\n *\n * // ⚠️ Risky: no name — serialization falls back to numeric ID\n * const Velocity = component<{ dx: number; dy: number }>();\n * ```\n */\n name?: string;\n /**\n * If `true`, an entity can have **at most one** relation per base component type.\n * When a new relation with the same base component is added, any existing relations\n * with that base component are **automatically removed** before the new one is applied.\n *\n * **Only applicable to relation components** — components used via\n * `relation(componentId, target)`. Regular (non-relation) components ignore this flag.\n *\n * ## Behavior\n *\n * Exclusive relations enforce a **one-to-one** constraint at the entity level:\n * each entity can hold at most one relation of a given exclusive component type.\n *\n * - **Same base component, different targets**: `set(entity, relation(Comp, A))`\n * followed by `set(entity, relation(Comp, B))` results in only `(Comp, B)` —\n * the `(Comp, A)` relation is automatically removed.\n * - **Same base component, same target**: Re-setting the same relation target\n * simply updates the component value (no extra removal overhead).\n * - **Different exclusive components**: Independent — `exclusive` on `CompA` does\n * not affect relations using `CompB`.\n *\n * The removal happens **during `world.sync()`**, as part of the command buffer\n * processing, so it respects the same deferred execution model as other structural\n * changes.\n *\n * ## Use cases\n *\n * - **Ownership**: An entity can only be owned by one parent at a time\n * (`ChildOf` with `exclusive: true`).\n * - **Equipment slots**: An item can only be in one slot at a time\n * (`EquippedBy` with `exclusive: true`).\n * - **Targeting**: An AI agent can only track one target at a time\n * (`Targeting` with `exclusive: true`).\n * - **State machines**: An entity can only have one active state from a set\n * (`ActiveState` with `exclusive: true`).\n *\n * ## Interaction with other options\n *\n * - **`cascadeDelete`**: Compatible. When an exclusive relation uses\n * `cascadeDelete`, deleting the target entity will both (a) delete the\n * referencing entity, and (b) the exclusivity constraint prevents the\n * entity from having multiple cascade-delete relations of the same type.\n * - **`sparse`**: Compatible. Exclusivity is enforced at the data level\n * regardless of whether the archetype is fragmented.\n *\n * @example\n * ```ts\n * // Without exclusive: entity can have multiple ChildOf relations\n * const ChildOf = component();\n * world.set(child, relation(ChildOf, parentA));\n * world.set(child, relation(ChildOf, parentB));\n * world.sync();\n * // child now has TWO ChildOf relations (parentA and parentB)\n * ```\n *\n * @example\n * ```ts\n * // With exclusive: only the last relation survives\n * const ChildOf = component({ exclusive: true });\n * world.set(child, relation(ChildOf, parentA));\n * world.set(child, relation(ChildOf, parentB));\n * world.sync();\n * // child has only (ChildOf, parentB); (ChildOf, parentA) was auto-removed\n * ```\n */\n exclusive?: boolean;\n /**\n * If true, when a relation target entity is deleted, all entities that reference\n * it through this component will also be deleted (cascade delete).\n *\n * Only applicable to entity-relation components.\n *\n * **Important distinction from default cleanup**:\n * By default, the ECS library **always** cleans up relation components that point\n * to a deleted entity — the relation component is removed from the referencing\n * entity, but the referencing entity itself **survives**. When `cascadeDelete` is\n * enabled, the **entire referencing entity** is deleted, not just the relation\n * component. This deletion is transitive: if entity C references entity B (which\n * is cascade-deleted), entity C will also be deleted, and so on.\n *\n * @example\n * // Without cascadeDelete (default behavior):\n * const ChildOf = component(); // no cascadeDelete\n * world.set(child, relation(ChildOf, parent));\n * world.sync();\n * world.delete(parent);\n * world.sync();\n * // child still exists, but the ChildOf relation is cleaned up\n *\n * @example\n * // With cascadeDelete:\n * const ChildOf = component({ cascadeDelete: true });\n * world.set(child, relation(ChildOf, parent));\n * world.sync();\n * world.delete(parent);\n * world.sync();\n * // child is also deleted (entity deleted, not just relation cleaned up)\n */\n cascadeDelete?: boolean;\n /**\n * If true, relations with this component use sparse storage and will not cause\n * archetype fragmentation.\n *\n * **Problem it solves**: By default, each unique relation pair `(component, target)`\n * creates a **separate archetype**. If 100 entities each have a `ChildOf` relation\n * to a different parent, you get 100 archetypes — this is **archetype fragmentation**.\n * Queries that iterate over all entities with a `ChildOf` relation must check all\n * 100 archetypes, which degrades iteration performance and increases memory overhead.\n *\n * **How it works (sparse storage)**: When `sparse` is enabled, the relation's target\n * does **not** contribute to the archetype signature. Entities with different targets\n * for the same relation component share a **single archetype**, and the per-entity\n * target data is stored in a separate side store (historically called\n * `DontFragmentStore`, now `SparseStore`). A wildcard relation marker (`relation(Comp, \"*\")`) is placed\n * in the archetype component list so queries can still discover matching archetypes.\n *\n * **Use cases**:\n * - **Hierarchy/ownership**: `ChildOf` relations where thousands of entities each\n * point to different parent entities.\n * - **Dynamic targeting**: Relations where targets change frequently (e.g., AI\n * targeting, inventory slots) — without `sparse`, each target change would cause\n * an archetype migration, which is expensive.\n * - **High-cardinality relations**: Any relation where the number of unique targets\n * is large compared to the number of entities.\n *\n * **Performance implications**:\n * - **Without `sparse`**: Archetype count grows linearly with unique targets.\n * Each archetype migration (changing a relation target) requires moving the entity's\n * data between component arrays.\n * - **With `sparse`**: Archetype count stays constant regardless of target diversity.\n * Changing a relation target is an O(1) update in the sparse side store.\n * The trade-off is an extra map lookup when accessing the relation data.\n *\n * **Constraints**:\n * - Only applicable to **relation components** (components used with `relation()`).\n * - Wildcard queries (e.g., `relation(Comp, \"*\")`) still work correctly — the\n * archetype carries a wildcard marker so queries can discover it.\n * - Works with `exclusive` and `cascadeDelete` simultaneously.\n *\n * **Backward compatibility**: The legacy key `dontFragment` is still accepted and\n * behaves identically. Prefer `sparse` in new code.\n *\n * @example\n * ```ts\n * // Without sparse: 100 entities with different parents = 100 archetypes\n * const ChildOf = component(); // default: fragmentation happens\n *\n * // With sparse: 100 entities with different parents = 1 archetype\n * const ChildOf = component({ sparse: true });\n *\n * for (let i = 0; i < 100; i++) {\n * const parent = world.new();\n * const child = world.new();\n * world.set(child, Position);\n * world.set(child, relation(ChildOf, parent));\n * }\n * world.sync();\n * // sparse: 1 archetype for all 100 entities\n * // without: 100 archetypes, one per unique parent\n * ```\n *\n * Inspired by Flecs' `DontFragment` trait (now exposed as the clearer `sparse` option).\n */\n sparse?: boolean;\n /**\n * @deprecated Use `sparse: true` instead. This key is kept solely for backward\n * compatibility; `component({ dontFragment: true })` continues to work exactly\n * as before and is equivalent to `sparse: true`.\n */\n dontFragment?: boolean;\n /**\n * Custom merge behavior for repeated `set()` of the same component type on the\n * same entity within a single sync batch.\n *\n * By default, calling `world.set(entity, comp, value)` multiple times for the same\n * entity and component before `world.sync()` simply overwrites the previous value —\n * the last `set()` wins. When `merge` is provided, the values are combined using\n * your function instead.\n *\n * @remarks\n * **Use cases**:\n * - **Accumulation**: Collecting events, tags, or modifiers that multiple systems\n * contribute to within the same frame.\n * - **Composition**: Merging partial updates into a single component value (e.g.,\n * applying multiple `Vec3` deltas to a position).\n * - **Conflict resolution**: Choosing the max/min/latest value when multiple\n * systems want to set the same component.\n *\n * **Scope**: This only affects `set()` calls on the **same entity** with the **same\n * component type** within **one sync batch** (i.e., between `world.sync()` calls).\n * It does NOT merge values across different entities or across sync boundaries.\n *\n * **Relation support**: If the component is used as a relation (via\n * `relation(componentId, target)`), the merge function also applies per-target.\n * `set(entity, relation(Comp, A), v1)` and `set(entity, relation(Comp, A), v2)`\n * will be merged, but `set(entity, relation(Comp, B), v)` is independent.\n *\n * **Idempotency required**: Your merge function should be idempotent — calling it\n * multiple times with the same inputs must produce the same result. The ECS\n * runtime does not guarantee exactly-once `sync()` execution in all scenarios.\n *\n * **Return value**: The function **must return** the merged value. It should not\n * mutate `prev` or `next` in place unless you intentionally want shared mutable\n * state (which is discouraged).\n *\n * @example\n * ```ts\n * // Collect tags from multiple systems in one frame\n * const Tags = component<string[]>({\n * merge: (prev, next) => [...prev, ...next],\n * });\n * ```\n *\n * @example\n * ```ts\n * // Only keep the highest priority value\n * const Alert = component<{ level: number; msg: string }>({\n * merge: (prev, next) => prev.level >= next.level ? prev : next,\n * });\n * ```\n *\n * @example\n * ```ts\n * // Accumulate numeric deltas (e.g., for movement)\n * const Velocity = component<{ x: number; y: number }>({\n * merge: (prev, next) => ({ x: prev.x + next.x, y: prev.y + next.y }),\n * });\n * ```\n */\n merge?: ComponentMerge<T>;\n}\n\n// Array for component names (Component ID range: 1-1023)\nconst componentNames: (string | undefined)[] = new Array(COMPONENT_ID_MAX + 1);\n\n// BitSets for fast component option checks (Component ID range: 1-1023)\nconst exclusiveFlags = new BitSet(COMPONENT_ID_MAX + 1);\nconst cascadeDeleteFlags = new BitSet(COMPONENT_ID_MAX + 1);\nconst sparseFlags = new BitSet(COMPONENT_ID_MAX + 1);\nconst componentMerges: (ComponentMerge<any> | undefined)[] = new Array(COMPONENT_ID_MAX + 1);\n\n/**\n * Allocate a new component ID from the global allocator.\n * @param nameOrOptions Optional name for the component (for serialization/debugging) or options object\n * @returns The allocated component ID\n * @example\n * // Just a name\n * const Position = component<Position>(\"Position\");\n *\n * // With options\n * const ChildOf = component({ exclusive: true, cascadeDelete: true });\n *\n * // With name and options\n * const ChildOf = component({ name: \"ChildOf\", exclusive: true });\n */\nexport function component<T = void>(nameOrOptions?: string | ComponentOptions<T>): ComponentId<T> {\n const id = globalComponentIdAllocator.allocate<T>();\n\n let name: string | undefined;\n let options: ComponentOptions<T> | undefined;\n\n // Parse the parameter\n if (typeof nameOrOptions === \"string\") {\n name = nameOrOptions;\n } else if (typeof nameOrOptions === \"object\" && nameOrOptions !== null) {\n options = nameOrOptions;\n name = options.name;\n }\n\n // Register name if provided\n if (name) {\n if (ComponentIdForNames.has(name)) {\n throw new Error(`Component name \"${name}\" is already registered`);\n }\n\n componentNames[id] = name;\n ComponentIdForNames.set(name, id);\n }\n\n // Register options if provided\n if (options) {\n // Set bitset flags for fast lookup\n if (options.exclusive) exclusiveFlags.set(id);\n if (options.cascadeDelete) cascadeDeleteFlags.set(id);\n // Support both `sparse` (preferred) and the legacy `dontFragment` alias for BC\n if (options.sparse || options.dontFragment) sparseFlags.set(id);\n if (options.merge) componentMerges[id] = options.merge;\n }\n\n return id;\n}\n\n/**\n * Get a component ID by its registered name\n * @param name The component name\n * @returns The component ID if found, undefined otherwise\n */\nexport function getComponentIdByName(name: string): ComponentId<any> | undefined {\n return ComponentIdForNames.get(name);\n}\n\n/** Get a component name by its ID\n * @param id The component ID\n * @returns The component name if found, undefined otherwise\n */\nexport function getComponentNameById(id: ComponentId<any>): string | undefined {\n return componentNames[id];\n}\n\n/**\n * Get component options by its ID\n * @param id The component ID\n * @returns The component options\n */\nexport function getComponentOptions<T = any>(id: ComponentId<T>): ComponentOptions<T> {\n if (!isComponentId(id)) {\n throw new Error(\"Invalid component ID\");\n }\n const hasName = componentNames[id] !== undefined;\n const hasExclusive = exclusiveFlags.has(id);\n const hasCascadeDelete = cascadeDeleteFlags.has(id);\n const hasSparse = sparseFlags.has(id);\n return {\n name: hasName ? componentNames[id] : undefined,\n exclusive: hasExclusive ? true : undefined,\n cascadeDelete: hasCascadeDelete ? true : undefined,\n sparse: hasSparse ? true : undefined,\n // For full backward compatibility with code that inspects options.dontFragment\n dontFragment: hasSparse ? true : undefined,\n merge: componentMerges[id] as ComponentMerge<T> | undefined,\n };\n}\n\nfunction getBaseComponentId(componentType: EntityId<any>): ComponentId<any> | undefined {\n if (isComponentId(componentType)) {\n return componentType;\n }\n\n const decoded = decodeRelationRaw(componentType);\n if (decoded === null) return undefined;\n return isValidComponentId(decoded.componentId) ? (decoded.componentId as ComponentId<any>) : undefined;\n}\n\n/**\n * Get the merge callback for a component type (including relation component types).\n *\n * Looks up the base component's merge function, resolving through relation wrappers.\n * For example, if `ChildOf` has a merge function and you pass `relation(ChildOf, parent)`,\n * the same merge function is returned.\n *\n * @param componentType - A raw component ID or a relation-wrapped component type\n * (e.g., `relation(MyComp, targetEntity)`).\n * @returns The merge callback if one was registered via {@link ComponentOptions.merge},\n * or `undefined` if no merge was configured for the base component.\n */\nexport function getComponentMerge<T = any>(componentType: EntityId<any>): ComponentMerge<T> | undefined {\n const baseComponentId = getBaseComponentId(componentType);\n if (baseComponentId === undefined) return undefined;\n return componentMerges[baseComponentId] as ComponentMerge<T> | undefined;\n}\n\n/**\n * Check if a component was created with `exclusive: true`.\n *\n * This is a fast O(1) bitset lookup that determines whether the component enforces\n * the one-to-one relation constraint — an entity can have at most one relation of\n * this component type, and setting a new relation target automatically removes the\n * previous one.\n *\n * **Note**: This only checks the component's intrinsic property, not whether a\n * specific entity/relation ID is actually an exclusive relation. For checking\n * runtime relation IDs (including wildcards), use {@link isExclusiveRelation}\n * or {@link isExclusiveWildcard}.\n *\n * @param id - The component ID to check. Must be a plain component ID (1–1023),\n * not a relation-wrapped ID.\n * @returns `true` if the component was created with `exclusive: true`.\n *\n * @see {@link ComponentOptions.exclusive} for the full explanation of exclusive\n * relation behavior.\n * @see {@link isExclusiveRelation} for checking specific-target exclusive relations.\n * @see {@link isExclusiveWildcard} for checking wildcard exclusive relations.\n */\nexport function isExclusiveComponent(id: ComponentId<any>): boolean {\n return exclusiveFlags.has(id);\n}\n\n/**\n * Check if a component is marked as cascade delete.\n *\n * When enabled, deleting the target entity of an entity-relation with this\n * component will cause the **entire referencing entity** to be deleted (not\n * just cleanup of the relation component, which happens by default for all\n * relations).\n *\n * @param id The component ID\n * @returns true if the component is cascade delete, false otherwise\n * @see {@link ComponentOptions.cascadeDelete}\n */\nexport function isCascadeDeleteComponent(id: ComponentId<any>): boolean {\n return cascadeDeleteFlags.has(id);\n}\n\n/**\n * Check if a component is marked as `sparse` (sparse storage for relations).\n *\n * When a component has `sparse: true`, relations using it do not cause archetype\n * fragmentation — entities with different relation targets can share the same\n * archetype. This is a fast O(1) bitset lookup. The legacy `dontFragment` key\n * is still accepted and sets the same internal flag.\n *\n * @param id - The component ID to check.\n * @returns `true` if the component was created with `sparse: true` (or the\n * legacy `dontFragment: true`).\n *\n * @see {@link ComponentOptions.sparse} for the full explanation of sparse storage.\n */\nexport function isSparseComponent(id: ComponentId<any>): boolean {\n return sparseFlags.has(id);\n}\n\n/**\n * Generic optimized function to check whether a relation ID's base component\n * has a specific flag in a bitset.\n *\n * Avoids the overhead of `getDetailedIdType` by directly decoding the relation\n * ID and checking: (1) the ID is a valid relation, (2) the component ID is in the\n * valid range, (3) the target satisfies the condition, and (4) the flag bit is set.\n *\n * Used as the fast-path implementation for `isSparseRelation`, `isSparseWildcard`,\n * `isExclusiveRelation`, `isExclusiveWildcard`, and `isCascadeDeleteRelation`.\n *\n * @param id - The entity/relation ID to check.\n * @param flagBitSet - The bitset tracking which component IDs have the flag.\n * @param targetCondition - Predicate on the target ID (e.g., check for wildcard\n * vs. specific entity target).\n * @returns `true` if the relation's base component has the flag and the target\n * condition is met.\n */\nfunction checkRelationFlag(\n id: EntityId<any>,\n flagBitSet: BitSet,\n targetCondition: (targetId: number) => boolean,\n): boolean {\n const decoded = decodeRelationRaw(id);\n if (decoded === null) return false;\n const { componentId, targetId } = decoded;\n return isValidComponentId(componentId) && targetCondition(targetId) && flagBitSet.has(componentId);\n}\n\n/**\n * Check if an ID is a specific (non-wildcard) relation backed by a `sparse`\n * component (i.e. stored in the side sparse store rather than the archetype).\n *\n * This is used in hot paths (archetype resolution, command processing) to determine\n * whether a relation should be excluded from the archetype signature.\n *\n * @param id - The entity/relation ID to check (must be a relation ID, not a plain\n * component ID).\n * @returns `true` if this is a specific-target relation (not wildcard) whose base\n * component was created with `sparse: true` (or legacy `dontFragment: true`).\n *\n * @see {@link isSparseWildcard} for the wildcard variant.\n * @see {@link ComponentOptions.sparse} for the full explanation.\n */\nexport function isSparseRelation(id: EntityId<any>): boolean {\n return checkRelationFlag(id, sparseFlags, (targetId) => targetId !== WILDCARD_TARGET_ID);\n}\n\n/**\n * Check if an ID is a wildcard relation (`relation(Comp, \"*\")`) backed by a\n * `sparse` component.\n *\n * Wildcard markers for sparse components are placed in the archetype component\n * list so that queries can discover archetypes containing entities with that\n * relation type.\n *\n * @param id - The entity/relation ID to check.\n * @returns `true` if this is a wildcard relation (`\"*\"` target) whose base\n * component was created with `sparse: true` (or legacy `dontFragment: true`).\n *\n * @see {@link isSparseRelation} for the specific-target variant.\n * @see {@link ComponentOptions.sparse} for the full explanation.\n */\nexport function isSparseWildcard(id: EntityId<any>): boolean {\n return checkRelationFlag(id, sparseFlags, (targetId) => targetId === WILDCARD_TARGET_ID);\n}\n\n/**\n * Check if an ID is a specific (non-wildcard) relation backed by an `exclusive`\n * component.\n *\n * This is used in hot paths (command buffer processing, relation management) to\n * determine whether setting this relation should trigger automatic removal of\n * other relations with the same base component on the same entity.\n *\n * This is an optimized function that avoids the overhead of `getDetailedIdType`\n * by directly decoding and checking the relation's component ID against the\n * `exclusive` bitset.\n *\n * @param id - The entity/relation ID to check (must be a relation ID, not a plain\n * component ID).\n * @returns `true` if this is a specific-target relation (not wildcard) whose base\n * component was created with `exclusive: true`.\n *\n * @see {@link isExclusiveWildcard} for the wildcard variant.\n * @see {@link ComponentOptions.exclusive} for the full explanation of exclusive\n * relation behavior.\n */\nexport function isExclusiveRelation(id: EntityId<any>): boolean {\n return checkRelationFlag(id, exclusiveFlags, (targetId) => targetId !== WILDCARD_TARGET_ID);\n}\n\n/**\n * Check if an ID is a wildcard relation (`relation(Comp, \"*\")`) backed by an\n * `exclusive` component.\n *\n * Wildcard markers for exclusive components are used to detect that an archetype\n * may contain exclusive relations, so the runtime can apply exclusivity enforcement\n * when processing relation commands.\n *\n * This is an optimized function that avoids the overhead of `getDetailedIdType`\n * by directly decoding and checking the relation's component ID against the\n * `exclusive` bitset.\n *\n * @param id - The entity/relation ID to check.\n * @returns `true` if this is a wildcard relation (`\"*\"` target) whose base\n * component was created with `exclusive: true`.\n *\n * @see {@link isExclusiveRelation} for the specific-target variant.\n * @see {@link ComponentOptions.exclusive} for the full explanation of exclusive\n * relation behavior.\n */\nexport function isExclusiveWildcard(id: EntityId<any>): boolean {\n return checkRelationFlag(id, exclusiveFlags, (targetId) => targetId === WILDCARD_TARGET_ID);\n}\n\n/**\n * Check if a relation ID is a cascade delete entity-relation.\n *\n * This is an optimized function that avoids the overhead of getDetailedIdType.\n *\n * Cascade delete only applies to entity-relations (not component-relations or\n * wildcards). When a cascade-delete-marked relation's target entity is deleted,\n * the **entire source entity** (the one holding the relation) is deleted — not\n * just the relation component. Without cascade delete, the relation component\n * is simply removed (which is the default cleanup for all relations when their\n * target is deleted).\n *\n * @param id The entity/relation ID to check\n * @returns true if this is an entity-relation with cascade delete, false otherwise\n * @see {@link ComponentOptions.cascadeDelete}\n */\nexport function isCascadeDeleteRelation(id: EntityId<any>): boolean {\n return checkRelationFlag(\n id,\n cascadeDeleteFlags,\n (targetId) => targetId !== WILDCARD_TARGET_ID && targetId >= ENTITY_ID_START,\n );\n}\n","import type { ComponentId, EntityId } from \"../entity\";\nimport { relation } from \"../entity\";\nimport type { World } from \"./world\";\n\n// =============================================================================\n// EntityBuilder - Fluent Entity Creation (moved from testing utilities)\n// =============================================================================\n\n/**\n * A component definition for entity building, supporting both regular components and relations\n */\nexport type ComponentDef<T = unknown> =\n | { type: \"component\"; id: EntityId<T>; value: T }\n | { type: \"relation\"; componentId: ComponentId<T>; targetId: EntityId<any>; value: T };\n\n/**\n * Fluent API for constructing entities with multiple components.\n * Create instances via {@link World.spawn}.\n *\n * @example\n * const entity = world.spawn()\n * .with(Position, { x: 0, y: 0 })\n * .withRelation(Parent, parentEntity)\n * .build();\n * world.sync();\n */\nexport class EntityBuilder {\n private world: World;\n private components: ComponentDef[] = [];\n\n constructor(world: World) {\n this.world = world;\n }\n\n /**\n * Add a regular component to the entity under construction.\n *\n * @template T - The component data type\n * @param componentId - The component type to add\n * @param args - Component data (omit for void components)\n * @returns This builder for chaining\n *\n * @example\n * builder.with(Position, { x: 10, y: 20 });\n * builder.with(Marker); // void component\n */\n with<T extends void>(componentId: EntityId<T>): this;\n with<T>(componentId: EntityId<T>, value: T): this;\n with<T>(componentId: EntityId<T>, value?: T): this {\n this.components.push({ type: \"component\", id: componentId, value: value as T });\n return this;\n }\n\n /**\n * Add a relation component to the entity under construction.\n *\n * @template T - The relation data type\n * @param componentId - The base component type for the relation\n * @param targetEntity - The target entity or component for the relation\n * @param args - Relation data (omit for void relations)\n * @returns This builder for chaining\n *\n * @example\n * builder.withRelation(Parent, parentEntity);\n * builder.withRelation(ChildOf, childEntity, { order: 1 });\n */\n withRelation<T extends void>(componentId: ComponentId<T>, targetEntity: EntityId<any>): this;\n withRelation<T>(componentId: ComponentId<T>, targetEntity: EntityId<any>, value: T): this;\n withRelation<T>(componentId: ComponentId<T>, targetEntity: EntityId<any>, value?: T): this {\n this.components.push({ type: \"relation\", componentId, targetId: targetEntity, value: value as T });\n return this;\n }\n\n /**\n * Create the entity and enqueue all configured components.\n * The entity and components are only materialised after {@link World.sync} is called.\n *\n * @returns The newly created entity ID\n *\n * @example\n * const entity = world.spawn()\n * .with(Position, { x: 0, y: 0 })\n * .build();\n * world.sync(); // Apply changes\n */\n build(): EntityId {\n const entity = this.world.new();\n\n for (const def of this.components) {\n if (def.type === \"component\") {\n this.world.set(entity, def.id, def.value as any);\n } else {\n const relationId = relation(def.componentId, def.targetId);\n this.world.set(entity, relationId, def.value as any);\n }\n }\n\n return entity;\n }\n}\n","import type { ComponentId } from \"../entity\";\n\nexport interface SingletonHandleOps<T> {\n has(): boolean;\n get(): T;\n getOptional(): { value: T } | undefined;\n remove(): void;\n set(value: T | undefined): void;\n}\n\n/**\n * Explicit handle for a singleton component (component-as-entity).\n *\n * This provides an explicit and concise API for singleton components without\n * overloading `world.set()` semantics.\n *\n * @example\n * const config = world.singleton(Config);\n * config.set({ debug: true });\n * world.sync();\n * console.log(config.get());\n */\nexport class SingletonHandle<T = void> {\n readonly componentId: ComponentId<T>;\n private readonly ops: SingletonHandleOps<T>;\n\n constructor(componentId: ComponentId<T>, ops: SingletonHandleOps<T>) {\n this.componentId = componentId;\n this.ops = ops;\n }\n\n has(): boolean {\n return this.ops.has();\n }\n\n get(): T {\n return this.ops.get();\n }\n\n getOptional(): { value: T } | undefined {\n return this.ops.getOptional();\n }\n\n remove(): void {\n this.ops.remove();\n }\n\n set(...args: T extends void ? [] : [value: NoInfer<T>]): void {\n this.ops.set(args[0] as T | undefined);\n }\n}\n","import type { EntityId } from \"../entity\";\nimport { getComponentIdFromRelationId, getTargetIdFromRelationId } from \"../entity\";\n\n/**\n * Internal representation for the relations an entity has under one component kind.\n * 'single' is the optimized form for exclusive relations (vast majority of cases).\n */\ntype RelationEntry =\n | { type: \"single\"; relationType: EntityId<any>; target: EntityId; data: any }\n | { type: \"multi\"; targets: Map<EntityId, { relationType: EntityId<any>; data: any }> };\n\n/**\n * Interface for the sparse side store used by components declared with `sparse: true`\n * (or the legacy `dontFragment: true` alias).\n *\n * Relation data for these components lives here instead of in archetype columns,\n * preventing fragmentation for high-cardinality or frequently-changing relations.\n *\n * Storage is primarily keyed by base relation ComponentId. This enables efficient\n * per-component lookups required by wildcard queries (relation(Comp, \"*\")) and\n * archetype filtering, while still supporting full-entity enumeration when needed.\n */\nexport interface SparseStore {\n // High-frequency per-(entity, relation) operations (get/set/has/remove, structural changes)\n getValue(entityId: EntityId, relationType: EntityId<any>): any | undefined;\n setValue(entityId: EntityId, relationType: EntityId<any>, data: any): void;\n deleteValue(entityId: EntityId, relationType: EntityId<any>): boolean;\n\n // Hot paths for wildcard queries and archetype filtering (per-component lookups)\n hasAnyForComponent(componentId: EntityId<any>): boolean;\n getRelationsForComponent(entityId: EntityId, componentId: EntityId<any>): [target: EntityId, data: any][];\n\n // Entity-wide enumeration paths (used for snapshots, serialization, forEach, and rare presence checks)\n getAllForEntity(entityId: EntityId): Array<[relationType: EntityId<any>, data: any]>;\n deleteEntity(entityId: EntityId): void;\n\n /**\n * @internal Bulk helper for serialization of many entities.\n * Default implementation simply loops getAllForEntity; subclasses / future\n * implementations can provide a more efficient fused walk.\n */\n getAllForEntities(entityIds: readonly EntityId[]): Map<EntityId, Array<[EntityId<any>, any]>>;\n}\n\n/**\n * Production implementation of SparseStore.\n *\n * Internal layout (optimized):\n * - byComponent: baseComponentId → (entityId → RelationEntry)\n * RelationEntry uses a single-value form for the common exclusive case (1 target),\n * avoiding Map allocation for the vast majority of usage.\n * - entityIndex: entityId → Set<baseComponentId>\n * Lightweight reverse index.\n */\nexport class SparseStoreImpl implements SparseStore {\n /**\n * Primary storage, keyed by the base relation component ID.\n */\n private byComponent = new Map<\n EntityId<any>, // base componentId\n Map<EntityId, RelationEntry>\n >();\n\n /**\n * Reverse index: which base component kinds an entity participates in.\n * Only required to support getAllForEntity and deleteEntity efficiently.\n * The primary storage (byComponent) is deliberately not optimized for these operations.\n */\n private entityIndex = new Map<EntityId, Set<EntityId<any>>>();\n\n getValue(entityId: EntityId, relationType: EntityId<any>): any | undefined {\n const componentId = getComponentIdFromRelationId(relationType);\n if (componentId === undefined) return undefined;\n\n const entities = this.byComponent.get(componentId);\n if (!entities) return undefined;\n\n const entry = entities.get(entityId);\n if (!entry) return undefined;\n\n const targetId = getTargetIdFromRelationId(relationType)!;\n\n if (entry.type === \"single\") {\n return entry.target === targetId ? entry.data : undefined;\n } else {\n const item = entry.targets.get(targetId);\n return item ? item.data : undefined;\n }\n }\n\n setValue(entityId: EntityId, relationType: EntityId<any>, data: any): void {\n const componentId = getComponentIdFromRelationId(relationType);\n if (componentId === undefined) {\n throw new Error(\"setValue called with a non-relation type on SparseStore\");\n }\n\n let entities = this.byComponent.get(componentId);\n if (!entities) {\n entities = new Map();\n this.byComponent.set(componentId, entities);\n }\n\n const targetId = getTargetIdFromRelationId(relationType)!;\n let entry = entities.get(entityId);\n\n if (!entry) {\n // First relation for this (entity, component) — use single form (big win for exclusive)\n entry = { type: \"single\", relationType, target: targetId, data };\n entities.set(entityId, entry);\n } else if (entry.type === \"single\") {\n if (entry.target === targetId) {\n entry.data = data;\n entry.relationType = relationType; // update in case it changed\n } else {\n // Promote to multi\n const targets = new Map();\n targets.set(entry.target, { relationType: entry.relationType, data: entry.data });\n targets.set(targetId, { relationType, data });\n entities.set(entityId, { type: \"multi\", targets });\n }\n } else {\n entry.targets.set(targetId, { relationType, data });\n }\n\n // Maintain reverse index\n let components = this.entityIndex.get(entityId);\n if (!components) {\n components = new Set();\n this.entityIndex.set(entityId, components);\n }\n components.add(componentId);\n }\n\n deleteValue(entityId: EntityId, relationType: EntityId<any>): boolean {\n const componentId = getComponentIdFromRelationId(relationType);\n if (componentId === undefined) return false;\n\n const entities = this.byComponent.get(componentId);\n if (!entities) return false;\n\n const entry = entities.get(entityId);\n if (!entry) return false;\n\n const targetId = getTargetIdFromRelationId(relationType)!;\n let existed = false;\n\n if (entry.type === \"single\") {\n if (entry.target === targetId) {\n existed = true;\n entities.delete(entityId);\n }\n } else {\n existed = entry.targets.delete(targetId);\n if (entry.targets.size === 0) {\n entities.delete(entityId);\n } else if (entry.targets.size === 1) {\n // Demote to single\n const [first] = entry.targets.entries();\n const [t, item] = first!;\n entities.set(entityId, { type: \"single\", relationType: item.relationType, target: t, data: item.data });\n }\n }\n\n if (!entities.has(entityId) && entities.size === 0) {\n this.byComponent.delete(componentId);\n }\n\n // Update reverse index\n const components = this.entityIndex.get(entityId);\n if (components && !entities.has(entityId)) {\n components.delete(componentId);\n if (components.size === 0) {\n this.entityIndex.delete(entityId);\n }\n }\n\n return existed;\n }\n\n hasAnyForComponent(componentId: EntityId<any>): boolean {\n const entities = this.byComponent.get(componentId);\n return entities !== undefined && entities.size > 0;\n }\n\n getRelationsForComponent(entityId: EntityId, componentId: EntityId<any>): [EntityId, any][] {\n const result: [EntityId, any][] = [];\n\n const entities = this.byComponent.get(componentId);\n if (!entities) return result;\n\n const entry = entities.get(entityId);\n if (!entry) return result;\n\n if (entry.type === \"single\") {\n result.push([entry.target, entry.data]);\n } else {\n for (const [target, item] of entry.targets) {\n result.push([target, item.data]);\n }\n }\n\n return result;\n }\n\n getAllForEntity(entityId: EntityId): Array<[relationType: EntityId<any>, data: any]> {\n const components = this.entityIndex.get(entityId);\n if (!components || components.size === 0) return [];\n\n const result: Array<[EntityId<any>, any]> = [];\n\n for (const componentId of components) {\n const entities = this.byComponent.get(componentId);\n const entry = entities?.get(entityId);\n if (entry) {\n if (entry.type === \"single\") {\n result.push([entry.relationType, entry.data]);\n } else {\n for (const item of entry.targets.values()) {\n result.push([item.relationType, item.data]);\n }\n }\n }\n }\n\n return result;\n }\n\n deleteEntity(entityId: EntityId): void {\n const components = this.entityIndex.get(entityId);\n if (!components) return;\n\n for (const componentId of components) {\n const entities = this.byComponent.get(componentId);\n if (entities) {\n entities.delete(entityId);\n if (entities.size === 0) {\n this.byComponent.delete(componentId);\n }\n }\n }\n\n this.entityIndex.delete(entityId);\n }\n\n getAllForEntities(entityIds: readonly EntityId[]): Map<EntityId, Array<[EntityId<any>, any]>> {\n const result = new Map<EntityId, Array<[EntityId<any>, any]>>();\n for (const eid of entityIds) {\n const data = this.getAllForEntity(eid);\n if (data.length > 0) {\n result.set(eid, data);\n }\n }\n return result;\n }\n}\n","import type { EntityId } from \"../entity\";\n\n/**\n * Maximum number of command buffer execution iterations to prevent infinite loops\n */\nconst MAX_COMMAND_ITERATIONS = 100;\n\n/**\n * Command for deferred execution\n * Uses discriminated union for type safety\n */\nexport type Command =\n | { type: \"set\"; entityId: EntityId; componentType: EntityId<any>; component: any }\n | { type: \"delete\"; entityId: EntityId; componentType: EntityId<any> }\n | { type: \"destroy\"; entityId: EntityId };\n\n/**\n * Command buffer for deferred structural changes\n */\nexport class CommandBuffer {\n private commands: Command[] = [];\n private swapBuffer: Command[] = [];\n /** Reusable map to group commands by entity, avoids per-sync allocations */\n private entityCommands: Map<EntityId, Command[]> = new Map();\n private executeEntityCommands: (entityId: EntityId, commands: Command[]) => void;\n\n /**\n * Create a command buffer with an executor function\n */\n constructor(executeEntityCommands: (entityId: EntityId, commands: Command[]) => void) {\n this.executeEntityCommands = executeEntityCommands;\n }\n\n /**\n * Add a component to an entity (deferred)\n */\n set(entityId: EntityId, componentType: EntityId<void>): void;\n set<T>(entityId: EntityId, componentType: EntityId<T>, component: NoInfer<T>): void;\n set(entityId: EntityId, componentType: EntityId, component?: any): void {\n this.commands.push({ type: \"set\", entityId, componentType, component });\n }\n\n /**\n * Remove a component from an entity (deferred)\n */\n remove<T>(entityId: EntityId, componentType: EntityId<T>): void {\n this.commands.push({ type: \"delete\", entityId, componentType });\n }\n\n /**\n * Destroy an entity (deferred)\n */\n delete(entityId: EntityId): void {\n this.commands.push({ type: \"destroy\", entityId });\n }\n\n /**\n * Execute all commands and clear the buffer.\n * Returns the number of iterations performed (for debug stats).\n */\n execute(): number {\n let iterations = 0;\n\n while (this.commands.length > 0) {\n if (iterations >= MAX_COMMAND_ITERATIONS) {\n throw new Error(\"Command execution exceeded maximum iterations, possible infinite loop\");\n }\n iterations++;\n\n // Swap buffers to avoid allocation\n const currentCommands = this.commands;\n this.commands = this.swapBuffer;\n\n // Group commands by entity, reusing the persistent Map\n const entityCommands = this.entityCommands;\n for (const cmd of currentCommands) {\n const existing = entityCommands.get(cmd.entityId);\n if (existing !== undefined) {\n existing.push(cmd);\n } else {\n entityCommands.set(cmd.entityId, [cmd]);\n }\n }\n\n // Clear the consumed buffer for reuse\n currentCommands.length = 0;\n this.swapBuffer = currentCommands;\n\n // Process each entity's commands and clear the map (but not the arrays,\n // as callers may hold references to them after the executor returns)\n for (const [entityId, commands] of entityCommands) {\n this.executeEntityCommands(entityId, commands);\n }\n entityCommands.clear();\n }\n\n return iterations;\n }\n\n /**\n * Get current commands (for testing)\n */\n getCommands(): Command[] {\n return [...this.commands];\n }\n\n /**\n * Clear all commands\n */\n clear(): void {\n this.commands = [];\n }\n}\n","import type { EntityId, WildcardRelationId } from \"../entity\";\nimport type { QueryFilter } from \"../query/filter\";\n\n/**\n * Type-erased component ID, used for runtime container storage\n * @internal\n */\nexport type AnyComponentId = EntityId<any>;\n\n/**\n * Type-erased entity ID, used for runtime container storage\n * @internal\n */\nexport type AnyEntityId = EntityId<any>;\n\n/**\n * Lifecycle hook definition for reacting to component additions, updates, and removals.\n * Register hooks with {@link World.hook}.\n */\nexport interface LifecycleHook<T extends readonly ComponentType<any>[]> {\n /**\n * Called once for each entity that already matches the hook's component types\n * when the hook is first registered, and then for every new matching entity.\n */\n on_init?: (entityId: EntityId, ...components: ComponentTuple<T>) => void;\n /**\n * Called whenever a matching entity's component data is updated via `set()`.\n */\n on_set?: (entityId: EntityId, ...components: ComponentTuple<T>) => void;\n /**\n * Called whenever a matching entity loses one of the required components\n * or is deleted.\n */\n on_remove?: (entityId: EntityId, ...components: ComponentTuple<T>) => void;\n}\n\n/**\n * Shorthand callback style for multi-component lifecycle hooks.\n * The same function receives all three events distinguished by the `type` parameter.\n *\n * @example\n * world.hook([Position, Velocity], (type, entityId, position, velocity) => {\n * if (type === \"init\") console.log(\"spawned\");\n * if (type === \"set\") console.log(\"updated\");\n * if (type === \"remove\") console.log(\"despawned\");\n * });\n */\nexport type LifecycleCallback<T extends readonly ComponentType<any>[]> = (\n type: \"init\" | \"set\" | \"remove\",\n entityId: EntityId,\n ...components: ComponentTuple<T>\n) => void;\n\n/**\n * A component type used in queries and hooks.\n * Can be a plain {@link EntityId} or an {@link OptionalEntityId} wrapped with `.optional`.\n */\nexport type ComponentType<T> = EntityId<T> | OptionalEntityId<T>;\n\n/**\n * Wrapper that marks a component as optional in queries and hooks.\n * When a component is optional, entities missing it are still included in results.\n *\n * @example\n * world.createQuery([Position, { optional: Velocity }]);\n */\nexport type OptionalEntityId<T> = { optional: EntityId<T> };\n\nexport function isOptionalEntityId<T>(type: ComponentType<T>): type is OptionalEntityId<T> {\n return typeof type === \"object\" && type !== null && \"optional\" in type;\n}\n\nexport type ComponentTypeToData<T> = T extends { optional: infer U }\n ? { value: ComponentTypeToData<U> } | undefined\n : T extends WildcardRelationId<infer U>\n ? [EntityId<unknown>, U][]\n : T extends EntityId<infer U>\n ? U\n : never;\n\n/**\n * Maps an array of {@link ComponentType} to their corresponding data tuples.\n * Used by {@link World.query} and {@link Query.forEach} to type component results.\n */\nexport type ComponentTuple<T extends readonly ComponentType<any>[]> = {\n readonly [K in keyof T]: ComponentTypeToData<T[K]>;\n};\n\nexport interface LifecycleHookEntry {\n componentTypes: readonly ComponentType<any>[];\n requiredComponents: EntityId<any>[];\n optionalComponents: EntityId<any>[];\n filter: QueryFilter;\n hook: LifecycleHook<any>;\n /** Raw callback function; takes precedence over hook.on_* when present */\n callback?: LifecycleCallback<any>;\n /** Archetypes that match this hook, used for precise cleanup on unsubscription */\n matchedArchetypes?: Set<any>;\n}\n\n/**\n * Statistics payload delivered to callbacks registered via `World.createDebugStatsCollector`.\n *\n * All structural counts are snapshots taken after the sync that triggered delivery.\n * `activity` always reflects work performed during that specific sync.\n *\n * Timestamps are raw `performance.now()` values suitable for `performance.measure`.\n */\nexport interface SyncDebugStats {\n readonly timestamps: {\n readonly syncStart: number;\n readonly syncEnd: number;\n readonly commandBufferStart: number;\n readonly commandBufferEnd: number;\n };\n\n /** Number of iterations the internal command buffer loop performed during this sync. */\n readonly commandIterations: number;\n\n readonly entities: {\n readonly total: number;\n readonly freelistSize: number;\n readonly nextId: number;\n };\n\n readonly archetypes: {\n readonly total: number;\n readonly empty: number;\n };\n\n readonly queries: {\n readonly cached: number;\n readonly registered: number;\n };\n\n readonly hooks: {\n readonly total: number;\n };\n\n /** Sizes of stable internal reverse indices (conservative set). */\n readonly indices: {\n readonly entityReferences: number;\n readonly entityToReferencingArchetypes: number;\n readonly archetypesByComponent: number;\n };\n\n /**\n * Activity that occurred as a direct result of this sync.\n * All fields are always present (never optional).\n */\n readonly activity: {\n /** Number of entities that performed an archetype migration (hasArchetypeStructuralChange was true). */\n readonly migrations: number;\n /** Total number of individual hook callback invocations (invokeHook calls). */\n readonly hooksExecuted: number;\n /** Number of new archetypes created during this sync. */\n readonly archetypesCreated: number;\n /** Number of archetypes removed during this sync. */\n readonly archetypesRemoved: number;\n };\n}\n\n/**\n * Handle returned by `World.createDebugStatsCollector`.\n * The object itself carries no data — its only responsibility is lifetime management.\n * Use with `using` or call `[Symbol.dispose]()` when you no longer need collection.\n */\nexport interface DebugStatsCollector {\n [Symbol.dispose](): void;\n}\n","import type { EntityId } from \"../entity\";\n\n/**\n * Normalize component type collections into a stable ascending order.\n * This keeps cache keys and archetype signatures deterministic.\n */\nexport function normalizeComponentTypes(componentTypes: Iterable<EntityId<any>>): EntityId<any>[] {\n return [...componentTypes].sort((a, b) => a - b);\n}\n","/**\n * Utility functions for ECS library\n */\n\n/**\n * Get a value from cache or compute and cache it if not present\n * @param cache The cache map\n * @param key The cache key\n * @param compute Function to compute the value if not cached (may have side effects)\n * @returns The cached or computed value\n */\nexport function getOrCompute<K, V>(cache: Map<K, V>, key: K, compute: () => V): V {\n let value = cache.get(key);\n if (value === undefined) {\n value = compute();\n cache.set(key, value);\n }\n return value;\n}\n","import { normalizeComponentTypes } from \"../component/type-utils\";\nimport type { EntityId, WildcardRelationId } from \"../entity\";\nimport {\n getComponentIdFromRelationId,\n getDetailedIdType,\n getIdType,\n isSparseComponent,\n isWildcardRelationId,\n} from \"../entity\";\nimport type { SerializedComponent, SerializedEntity, SerializedEntityId } from \"../storage/serialization\";\nimport { isOptionalEntityId, type ComponentTuple, type ComponentType, type LifecycleHookEntry } from \"../types\";\nimport { getOrCompute } from \"../utils/utils\";\nimport { buildCacheKey, buildSingleComponent, getWildcardRelationDataSource, isRelationType } from \"./helpers\";\nimport type { SparseStore } from \"./store\";\n\n/**\n * Special value to represent missing component data\n */\nexport const MISSING_COMPONENT = Symbol(\"missing component\");\n\n/**\n * Archetype class for ECS architecture\n * Represents a group of entities that share the same set of components\n * Optimized for fast iteration and component access\n */\nexport class Archetype {\n /**\n * The component types that define this archetype\n */\n public readonly componentTypes: EntityId<any>[];\n\n /**\n * Set version of componentTypes for O(1) lookups in hot paths\n */\n public readonly componentTypeSet: ReadonlySet<EntityId<any>>;\n\n /**\n * List of entities in this archetype\n */\n private entities: EntityId[] = [];\n\n /**\n * Component data storage - maps component type to array of component data\n * Each array index corresponds to the entity index in the entities array\n */\n private componentData: Map<EntityId<any>, any[]> = new Map();\n\n /**\n * Reverse mapping from entity to its index in this archetype\n */\n private entityToIndex: Map<EntityId, number> = new Map();\n\n /**\n * SparseStore used for relations declared with `sparse: true`.\n * See store.ts for implementation details.\n */\n private sparseRelations: SparseStore;\n\n /**\n * Multi-hooks that match this archetype\n */\n public readonly matchingMultiHooks: Set<LifecycleHookEntry> = new Set();\n\n /**\n * Cache for pre-computed component data sources to avoid repeated calculations\n */\n private componentDataSourcesCache: Map<string, (any[] | EntityId<any>[] | undefined)[]> = new Map();\n\n constructor(componentTypes: EntityId<any>[], sparseStore: SparseStore) {\n this.componentTypes = normalizeComponentTypes(componentTypes);\n this.componentTypeSet = new Set(this.componentTypes);\n this.sparseRelations = sparseStore;\n\n for (const componentType of this.componentTypes) {\n this.componentData.set(componentType, []);\n }\n }\n\n get size(): number {\n return this.entities.length;\n }\n\n /**\n * Check if the given component types match this archetype\n * @param componentTypes - Component types to check (can be in any order)\n * @returns true if the types match this archetype's component set\n * @note This method handles unsorted input by internally sorting for comparison\n */\n matches(componentTypes: EntityId<any>[]): boolean {\n if (this.componentTypes.length !== componentTypes.length) return false;\n const sortedTypes = normalizeComponentTypes(componentTypes);\n return this.componentTypes.every((type, index) => type === sortedTypes[index]);\n }\n\n addEntity(entityId: EntityId, componentData: Map<EntityId<any>, any>): void {\n if (this.entityToIndex.has(entityId)) {\n throw new Error(`Entity ${entityId} is already in this archetype`);\n }\n\n const index = this.entities.length;\n this.entities.push(entityId);\n this.entityToIndex.set(entityId, index);\n\n // Add component data for regular components\n for (const componentType of this.componentTypes) {\n const data = componentData.get(componentType);\n this.getComponentData(componentType).push(!componentData.has(componentType) ? MISSING_COMPONENT : data);\n }\n\n // Add sparse-stored relations separately\n this.addSparseRelations(entityId, componentData);\n }\n\n private addSparseRelations(entityId: EntityId, componentData: Map<EntityId<any>, any>): void {\n for (const [componentType, data] of componentData) {\n if (this.componentTypeSet.has(componentType)) continue;\n\n const detailedType = getDetailedIdType(componentType);\n if (isRelationType(detailedType) && isSparseComponent(detailedType.componentId!)) {\n this.sparseRelations.setValue(entityId, componentType, data);\n }\n }\n }\n\n getEntity(entityId: EntityId): Map<EntityId<any>, any> | undefined {\n const index = this.entityToIndex.get(entityId);\n if (index === undefined) return undefined;\n\n const entityData = new Map<EntityId<any>, any>();\n\n // Add regular components\n for (const componentType of this.componentTypes) {\n const data = this.getComponentData(componentType)[index];\n entityData.set(componentType, data === MISSING_COMPONENT ? undefined : data);\n }\n\n // Add sparse-stored relations\n const sparseTuples = this.sparseRelations.getAllForEntity(entityId);\n for (const [componentType, data] of sparseTuples) {\n entityData.set(componentType, data);\n }\n\n return entityData;\n }\n\n /**\n * Returns all sparse-stored relations for the given entity.\n * Internal helper used by command processing and tests.\n */\n getEntitySparseRelations(entityId: EntityId): Map<EntityId<any>, any> | undefined {\n const tuples = this.sparseRelations.getAllForEntity(entityId);\n if (tuples.length === 0) return undefined;\n\n const map = new Map<EntityId<any>, any>();\n for (const [relType, data] of tuples) {\n map.set(relType, data);\n }\n return map;\n }\n\n dump(): Array<{ entity: EntityId; components: Map<EntityId<any>, any> }> {\n return this.entities.map((entity, i) => {\n const components = new Map<EntityId<any>, any>();\n\n for (const componentType of this.componentTypes) {\n const data = this.getComponentData(componentType)[i];\n components.set(componentType, data === MISSING_COMPONENT ? undefined : data);\n }\n\n const sparseTuples = this.sparseRelations.getAllForEntity(entity);\n for (const [componentType, data] of sparseTuples) {\n components.set(componentType, data);\n }\n\n return { entity, components };\n });\n }\n\n /**\n * @internal Serialization fast-path.\n *\n * Appends SerializedEntity records directly from the archetype's column storage\n * (componentData arrays) plus sparse relations, avoiding per-entity Map\n * allocation and repeated Array.from(entries()).\n *\n * Component type IDs should be pre-encoded by the caller (once per archetype)\n * and passed in `encodedComponentTypes` (same order and length as this.componentTypes).\n *\n * The provided `encode` function should be the cached variant for best performance\n * on entity IDs and any sparse relation type IDs.\n *\n * `sparseByEntity` is an optional pre-fetched map from a bulk\n * `SparseStore.getAllForEntities` call (further reduces per-entity calls).\n */\n appendSerializedEntities(\n out: SerializedEntity[],\n encode: (id: EntityId<any>) => SerializedEntityId,\n encodedComponentTypes: SerializedEntityId[],\n sparseByEntity?: Map<EntityId, Array<[EntityId<any>, any]>>,\n ): void {\n if (encodedComponentTypes.length !== this.componentTypes.length) {\n throw new Error(\"encodedComponentTypes length must match archetype componentTypes\");\n }\n\n for (let i = 0; i < this.entities.length; i++) {\n const entity = this.entities[i]!;\n\n const components: SerializedComponent[] = [];\n // Regular (non-sparse) components from column arrays\n for (let c = 0; c < this.componentTypes.length; c++) {\n const data = this.getComponentData(this.componentTypes[c]!)[i];\n components.push({\n type: encodedComponentTypes[c]!,\n value: data === MISSING_COMPONENT ? undefined : data,\n });\n }\n\n // Append any sparse relations for this entity (usually small or zero)\n const sparseTuples = sparseByEntity?.get(entity) ?? this.sparseRelations.getAllForEntity(entity);\n for (const [componentType, data] of sparseTuples) {\n components.push({\n type: encode(componentType),\n value: data,\n });\n }\n\n out.push({\n id: encode(entity),\n components,\n });\n }\n }\n\n removeEntity(entityId: EntityId): Map<EntityId<any>, any> | undefined {\n const index = this.entityToIndex.get(entityId);\n if (index === undefined) return undefined;\n\n // Extract component data before removal\n const removedData = new Map<EntityId<any>, any>();\n for (const componentType of this.componentTypes) {\n removedData.set(componentType, this.getComponentData(componentType)[index]);\n }\n\n // Include sparse relations\n const sparseTuples = this.sparseRelations.getAllForEntity(entityId);\n for (const [componentType, data] of sparseTuples) {\n removedData.set(componentType, data);\n }\n this.sparseRelations.deleteEntity(entityId);\n\n this.entityToIndex.delete(entityId);\n\n // Swap-and-pop for O(1) removal\n const lastIndex = this.entities.length - 1;\n if (index !== lastIndex) {\n const lastEntity = this.entities[lastIndex]!;\n this.entities[index] = lastEntity;\n this.entityToIndex.set(lastEntity, index);\n\n for (const componentType of this.componentTypes) {\n const dataArray = this.getComponentData(componentType);\n dataArray[index] = dataArray[lastIndex];\n }\n }\n\n this.entities.pop();\n for (const componentType of this.componentTypes) {\n this.getComponentData(componentType).pop();\n }\n\n return removedData;\n }\n\n exists(entityId: EntityId): boolean {\n return this.entityToIndex.has(entityId);\n }\n\n get<T>(entityId: EntityId, componentType: WildcardRelationId<T>): [EntityId<unknown>, any][];\n get<T>(entityId: EntityId, componentType: EntityId<T>): T;\n get<T>(entityId: EntityId, componentType: EntityId<T> | WildcardRelationId<T>): T | [EntityId<unknown>, any][] {\n const index = this.entityToIndex.get(entityId);\n if (index === undefined) {\n throw new Error(`Entity ${entityId} is not in this archetype`);\n }\n\n if (isWildcardRelationId(componentType)) {\n return this.getWildcardRelations(entityId, index, componentType);\n }\n\n return this.getRegularComponent(entityId, index, componentType);\n }\n\n private getWildcardRelations<T>(\n entityId: EntityId,\n index: number,\n componentType: WildcardRelationId<T>,\n ): [EntityId<unknown>, any][] {\n const componentId = getComponentIdFromRelationId(componentType);\n const relations: [EntityId<unknown>, any][] = [];\n\n // Check regular archetype components\n for (const relType of this.componentTypes) {\n const relDetailed = getDetailedIdType(relType);\n if (isRelationType(relDetailed) && relDetailed.componentId === componentId) {\n const dataArray = this.getComponentData(relType);\n if (dataArray && dataArray[index] !== undefined) {\n const data = dataArray[index];\n relations.push([relDetailed.targetId, data === MISSING_COMPONENT ? undefined : data]);\n }\n }\n }\n\n // Check sparse relations (now uses the efficient per-component path)\n if (componentId !== undefined) {\n const matches = this.sparseRelations.getRelationsForComponent(entityId, componentId);\n for (const m of matches) relations.push(m);\n }\n\n return relations;\n }\n\n private getRegularComponent<T>(entityId: EntityId, index: number, componentType: EntityId<T>): T {\n if (this.componentTypeSet.has(componentType)) {\n const data = this.getComponentData(componentType)[index]!;\n if (data === MISSING_COMPONENT) {\n throw new Error(`Component type ${componentType} not found for entity ${entityId}`);\n }\n return data as T;\n }\n\n const value = this.sparseRelations.getValue(entityId, componentType);\n if (value !== undefined || this.sparseRelations.getAllForEntity(entityId).some(([t]) => t === componentType)) {\n // Note: the extra check above handles the (rare) case where `undefined` is a legitimate stored value.\n // For the common case we just return whatever getValue gave us.\n return this.sparseRelations.getValue(entityId, componentType);\n }\n\n throw new Error(`Component type ${componentType} not found for entity ${entityId}`);\n }\n\n getOptional<T>(entityId: EntityId, componentType: EntityId<T>): { value: T } | undefined {\n const index = this.entityToIndex.get(entityId);\n if (index === undefined) {\n throw new Error(`Entity ${entityId} is not in this archetype`);\n }\n\n if (this.componentTypeSet.has(componentType)) {\n const data = this.getComponentData(componentType)[index]!;\n if (data === MISSING_COMPONENT) return undefined;\n return { value: data as T };\n }\n\n const value = this.sparseRelations.getValue(entityId, componentType);\n // We use getAllForEntity only as a presence check when the value itself might be undefined.\n if (value !== undefined) {\n return { value };\n }\n const all = this.sparseRelations.getAllForEntity(entityId);\n if (all.some(([t]) => t === componentType)) {\n return { value: this.sparseRelations.getValue(entityId, componentType) };\n }\n return undefined;\n }\n\n set<T>(entityId: EntityId, componentType: EntityId<T>, data: T): void {\n const index = this.entityToIndex.get(entityId);\n if (index === undefined) {\n throw new Error(`Entity ${entityId} is not in this archetype`);\n }\n\n if (this.componentData.has(componentType)) {\n this.getComponentData(componentType)[index] = data;\n return;\n }\n\n const detailedType = getDetailedIdType(componentType);\n if (isRelationType(detailedType) && isSparseComponent(detailedType.componentId!)) {\n this.sparseRelations.setValue(entityId, componentType, data);\n return;\n }\n\n throw new Error(`Component type ${componentType} is not in this archetype`);\n }\n\n getEntities(): EntityId[] {\n return this.entities;\n }\n\n getEntityToIndexMap(): Map<EntityId, number> {\n return this.entityToIndex;\n }\n\n getComponentData<T>(componentType: EntityId<T>): T[] {\n const data = this.componentData.get(componentType);\n if (!data) {\n throw new Error(`Component type ${componentType} is not in this archetype`);\n }\n return data;\n }\n\n getOptionalComponentData<T>(componentType: EntityId<T>): T[] | undefined {\n return this.componentData.get(componentType);\n }\n\n private getCachedComponentDataSources<const T extends readonly ComponentType<any>[]>(\n componentTypes: T,\n ): (any[] | EntityId<any>[] | undefined)[] {\n const cacheKey = buildCacheKey(componentTypes);\n return getOrCompute(this.componentDataSourcesCache, cacheKey, () =>\n componentTypes.map((compType) => this.getComponentDataSource(compType)),\n );\n }\n\n private getComponentDataSource(compType: ComponentType<any>): any[] | EntityId<any>[] | undefined {\n const optional = isOptionalEntityId(compType);\n const actualType = optional ? compType.optional : compType;\n const idType = getIdType(actualType);\n\n if (idType === \"wildcard-relation\") {\n const componentId = getComponentIdFromRelationId(actualType)!;\n return getWildcardRelationDataSource(this.componentTypes, componentId, optional);\n }\n\n return optional ? this.getOptionalComponentData(actualType) : this.getComponentData(actualType);\n }\n\n private buildComponentsForIndex<const T extends readonly ComponentType<any>[]>(\n componentTypes: T,\n componentDataSources: (any[] | EntityId<any>[] | undefined)[],\n entityIndex: number,\n entityId: EntityId,\n ): ComponentTuple<T> {\n return componentDataSources.map((dataSource, i) =>\n buildSingleComponent(\n componentTypes[i]!,\n dataSource,\n entityIndex,\n entityId,\n (type) => this.getComponentData(type),\n this.sparseRelations,\n ),\n ) as ComponentTuple<T>;\n }\n\n getEntitiesWithComponents<const T extends readonly ComponentType<any>[]>(\n componentTypes: T,\n ): Array<{ entity: EntityId; components: ComponentTuple<T> }> {\n const result: Array<{ entity: EntityId; components: ComponentTuple<T> }> = [];\n this.appendEntitiesWithComponents(componentTypes, result);\n return result;\n }\n\n appendEntitiesWithComponents<const T extends readonly ComponentType<any>[]>(\n componentTypes: T,\n result: Array<{ entity: EntityId; components: ComponentTuple<T> }>,\n ): void {\n this.forEachWithComponents(componentTypes, (entity, ...components) => {\n result.push({ entity, components });\n });\n }\n\n *iterateWithComponents<const T extends readonly ComponentType<any>[]>(\n componentTypes: T,\n ): IterableIterator<[EntityId, ...ComponentTuple<T>]> {\n const componentDataSources = this.getCachedComponentDataSources(componentTypes);\n\n for (let entityIndex = 0; entityIndex < this.entities.length; entityIndex++) {\n const entity = this.entities[entityIndex]!;\n const components = this.buildComponentsForIndex(componentTypes, componentDataSources, entityIndex, entity);\n yield [entity, ...components];\n }\n }\n\n forEachWithComponents<const T extends readonly ComponentType<any>[]>(\n componentTypes: T,\n callback: (entity: EntityId, ...components: ComponentTuple<T>) => void,\n ): void {\n const componentDataSources = this.getCachedComponentDataSources(componentTypes);\n\n for (let entityIndex = 0; entityIndex < this.entities.length; entityIndex++) {\n const entity = this.entities[entityIndex]!;\n const components = this.buildComponentsForIndex(componentTypes, componentDataSources, entityIndex, entity);\n callback(entity, ...components);\n }\n }\n\n forEach(callback: (entityId: EntityId, components: Map<EntityId<any>, any>) => void): void {\n for (let i = 0; i < this.entities.length; i++) {\n const entity = this.entities[i]!;\n const components = new Map<EntityId<any>, any>();\n for (const componentType of this.componentTypes) {\n const data = this.getComponentData(componentType)[i];\n components.set(componentType, data === MISSING_COMPONENT ? undefined : data);\n }\n\n // Append sparse relations (entity-wide enumeration; acceptable cost for forEach)\n const sparseTuples = this.sparseRelations.getAllForEntity(entity);\n for (const [componentType, data] of sparseTuples) {\n components.set(componentType, data);\n }\n\n callback(entity, components);\n }\n }\n\n hasRelationWithComponentId(componentId: EntityId<any>): boolean {\n // Check regular archetype components\n for (const componentType of this.componentTypes) {\n const detailedType = getDetailedIdType(componentType);\n if (isRelationType(detailedType) && detailedType.componentId === componentId) {\n return true;\n }\n }\n\n // Check sparse relations only for entities that actually belong to *this* archetype.\n // We must not use the global hasAnyForComponent here, otherwise unrelated archetypes\n // can be incorrectly pulled into wildcard queries when any entity in the world has the relation.\n for (const entityId of this.entities) {\n const rels = this.sparseRelations.getRelationsForComponent(entityId, componentId);\n if (rels.length > 0) {\n return true;\n }\n }\n return false;\n }\n}\n","import type { ComponentId, EntityId, WildcardRelationId } from \"../entity\";\nimport {\n getComponentIdFromRelationId,\n getDetailedIdType,\n getIdType,\n getTargetIdFromRelationId,\n isRelationId,\n} from \"../entity\";\nimport { isOptionalEntityId, type ComponentType } from \"../types\";\nimport { MISSING_COMPONENT } from \"./archetype\";\nimport type { SparseStore } from \"./store\";\n\ntype DetailedIdType = ReturnType<typeof getDetailedIdType>;\n\ntype RelationDetailedType =\n | { type: \"entity-relation\"; componentId: ComponentId<any>; targetId: EntityId<any> }\n | { type: \"component-relation\"; componentId: ComponentId<any>; targetId: ComponentId<any> };\n\n/**\n * Find all wildcard relations matching a specific component ID from a components map\n * @param components - Component entity's components map\n * @param wildcardComponentId - The component ID to match (relation part)\n * @returns Array of matching relation IDs\n */\nexport function findWildcardRelations(components: Map<EntityId, any>, wildcardComponentId: EntityId): EntityId<any>[] {\n const result: EntityId<any>[] = [];\n for (const [relId] of components) {\n if (isRelationId(relId)) {\n const decoded = getComponentIdFromRelationId(relId);\n if (decoded === wildcardComponentId) {\n result.push(relId);\n }\n }\n }\n return result;\n}\n\n/**\n * Check if a components map has any wildcard relations matching a component ID\n * @param components - Component entity's components map\n * @param wildcardComponentId - The component ID to match\n * @returns True if at least one matching relation exists\n */\nexport function hasWildcardRelation(components: Map<EntityId, any>, wildcardComponentId: EntityId): boolean {\n for (const relId of components.keys()) {\n if (isRelationId(relId)) {\n const decoded = getComponentIdFromRelationId(relId);\n if (decoded === wildcardComponentId) return true;\n }\n }\n return false;\n}\n\n/**\n * Check if a detailed type represents a relation (entity or component)\n */\nexport function isRelationType(detailedType: DetailedIdType): detailedType is RelationDetailedType {\n return detailedType.type === \"entity-relation\" || detailedType.type === \"component-relation\";\n}\n\n/**\n * Check if a component type matches a given component ID for relations\n */\nexport function matchesRelationComponentId(componentType: EntityId<any>, componentId: EntityId<any>): boolean {\n const detailedType = getDetailedIdType(componentType);\n return isRelationType(detailedType) && detailedType.componentId === componentId;\n}\n\n/**\n * Build cache key for component types\n */\nexport function buildCacheKey(componentTypes: readonly ComponentType<any>[]): string {\n return componentTypes.map((id) => (isOptionalEntityId(id) ? `opt(${id.optional})` : `${id}`)).join(\",\");\n}\n\n/**\n * Get data source for wildcard relations from component types\n */\nexport function getWildcardRelationDataSource(\n componentTypes: EntityId<any>[],\n componentId: EntityId<any>,\n optional: boolean,\n): EntityId<any>[] | undefined {\n const matchingRelations = componentTypes.filter((ct) => matchesRelationComponentId(ct, componentId));\n return optional ? (matchingRelations.length > 0 ? matchingRelations : undefined) : matchingRelations;\n}\n\n/**\n * Build wildcard relation value from matching relations.\n * Receives the SparseStore directly for efficient per-component lookups.\n */\nexport function buildWildcardRelationValue(\n wildcardRelationType: WildcardRelationId<any>,\n matchingRelations: EntityId<any>[] | undefined,\n getDataAtIndex: (relType: EntityId<any>) => any,\n sparseStore: SparseStore,\n entityId: EntityId,\n optional: boolean,\n): any {\n const relations: [EntityId<unknown>, any][] = [];\n const targetComponentId = getComponentIdFromRelationId(wildcardRelationType);\n\n // Add regular archetype relations\n for (const relType of matchingRelations || []) {\n const data = getDataAtIndex(relType);\n const targetId = getTargetIdFromRelationId(relType)!;\n relations.push([targetId, data === MISSING_COMPONENT ? undefined : data]);\n }\n\n // Add sparse relations using the efficient store API (critical for wildcard query performance)\n if (targetComponentId !== undefined) {\n const dfMatches = sparseStore.getRelationsForComponent(entityId, targetComponentId);\n for (const m of dfMatches) {\n relations.push(m);\n }\n }\n\n if (relations.length === 0) {\n if (!optional) {\n const componentId = getComponentIdFromRelationId(wildcardRelationType);\n throw new Error(\n `No matching relations found for mandatory wildcard relation component ${componentId} on entity ${entityId}`,\n );\n }\n return undefined;\n }\n\n return optional ? { value: relations } : relations;\n}\n\n/**\n * Build regular component value from data source\n */\nexport function buildRegularComponentValue(dataSource: any[] | undefined, entityIndex: number, optional: boolean): any {\n if (dataSource === undefined) {\n if (optional) return undefined;\n throw new Error(`Component data not found for mandatory component type`);\n }\n\n const data = dataSource[entityIndex];\n const result = data === MISSING_COMPONENT ? undefined : data;\n return optional ? { value: result } : result;\n}\n\n/**\n * Build a single component value based on its type\n */\nexport function buildSingleComponent(\n compType: ComponentType<any>,\n dataSource: any[] | EntityId<any>[] | undefined,\n entityIndex: number,\n entityId: EntityId,\n getComponentData: (type: EntityId<any>) => any[],\n sparseRelations: SparseStore,\n): any {\n const optional = isOptionalEntityId(compType);\n const actualType = optional ? compType.optional : compType;\n\n if (getIdType(actualType) === \"wildcard-relation\") {\n return buildWildcardRelationValue(\n actualType as WildcardRelationId<any>,\n dataSource as EntityId<any>[] | undefined,\n (relType) => getComponentData(relType)[entityIndex],\n sparseRelations,\n entityId,\n optional,\n );\n } else {\n return buildRegularComponentValue(dataSource as any[] | undefined, entityIndex, optional);\n }\n}\n","import { hasWildcardRelation } from \"../archetype/helpers\";\nimport type { Command } from \"../commands/buffer\";\nimport {\n getComponentIdFromRelationId,\n getComponentMerge,\n getDetailedIdType,\n isWildcardRelationId,\n type ComponentId,\n type EntityId,\n type WildcardRelationId,\n} from \"../entity\";\n\n/**\n * Manages component entity (singleton) storage.\n *\n * Component entities use a flat Map-based storage rather than the Archetype-based\n * storage used for regular entities. Their IDs are in the component ID range\n * (or are relation IDs), distinguishing them from regular entity IDs.\n */\nexport class ComponentEntityStore {\n private readonly componentEntityComponents: Map<EntityId, Map<EntityId<any>, any>> = new Map();\n private readonly relationEntityIdsByTarget: Map<EntityId, Set<EntityId>> = new Map();\n\n /**\n * Check if an entity ID is a component entity type.\n * Returns true for component IDs, component-relation IDs, and entity-relation IDs —\n * i.e. anything that is NOT a plain entity or an invalid ID.\n */\n exists(entityId: EntityId): boolean {\n const detailed = getDetailedIdType(entityId);\n return detailed.type !== \"entity\" && detailed.type !== \"invalid\";\n }\n\n /**\n * Check if a component entity has a specific component.\n */\n has(entityId: EntityId, componentType: EntityId<any>): boolean {\n return this.componentEntityComponents.get(entityId)?.has(componentType) ?? false;\n }\n\n /**\n * Check if a singleton component has data — the has(componentId) overload.\n * In singleton usage the entity ID and the component type are the same value.\n */\n hasSingleton(componentId: EntityId<any>): boolean {\n return this.componentEntityComponents.get(componentId)?.has(componentId) ?? false;\n }\n\n /**\n * Check if a component entity has any wildcard relations matching a component ID.\n */\n hasWildcard(entityId: EntityId, componentId: ComponentId<any>): boolean {\n const data = this.componentEntityComponents.get(entityId);\n if (!data) return false;\n return hasWildcardRelation(data, componentId);\n }\n\n /**\n * Get a component value from a component entity.\n * Throws if the component does not exist.\n */\n get<T>(entityId: EntityId, componentType: EntityId<T>): T {\n const data = this.componentEntityComponents.get(entityId);\n if (!data || !data.has(componentType)) {\n throw new Error(\n `Entity ${entityId} does not have component ${componentType}. Use has() to check component existence before calling get().`,\n );\n }\n return data.get(componentType) as T;\n }\n\n /**\n * Get an optional component value from a component entity.\n * Returns undefined if the component does not exist.\n */\n getOptional<T>(entityId: EntityId, componentType: EntityId<T>): { value: T } | undefined {\n const data = this.componentEntityComponents.get(entityId);\n if (!data || !data.has(componentType)) return undefined;\n return { value: data.get(componentType) as T };\n }\n\n /**\n * Get all wildcard relations of a given type from a component entity.\n */\n getWildcard<T>(entityId: EntityId, wildcardComponentType: WildcardRelationId<T>): [EntityId<unknown>, T][] {\n const componentId = getComponentIdFromRelationId(wildcardComponentType);\n const data = this.componentEntityComponents.get(entityId);\n if (componentId === undefined || !data) return [];\n\n const relations: [EntityId<unknown>, T][] = [];\n for (const [key, value] of data.entries()) {\n if (getComponentIdFromRelationId(key) !== componentId) continue;\n const detailed = getDetailedIdType(key);\n if (detailed.type === \"entity-relation\" || detailed.type === \"component-relation\") {\n relations.push([detailed.targetId, value as T]);\n }\n }\n return relations;\n }\n\n /**\n * Clear all data for a component entity.\n */\n clear(entityId: EntityId): void {\n if (this.componentEntityComponents.delete(entityId)) {\n this.unregisterRelationEntityId(entityId);\n }\n }\n\n /**\n * Cleanup all component entities that reference a given target entity.\n * Called when a target entity is destroyed.\n */\n cleanupReferencesTo(targetId: EntityId): void {\n const relationEntities = this.relationEntityIdsByTarget.get(targetId);\n if (!relationEntities) return;\n for (const relationEntityId of relationEntities) {\n this.componentEntityComponents.delete(relationEntityId);\n }\n this.relationEntityIdsByTarget.delete(targetId);\n }\n\n /**\n * Execute a batch of commands for a component entity.\n */\n executeCommands(entityId: EntityId, commands: Command[]): void {\n if (commands.some((cmd) => cmd.type === \"destroy\")) {\n this.clear(entityId);\n return;\n }\n\n const pendingSetValues = new Map<EntityId<any>, any>();\n\n for (const command of commands) {\n if (command.type === \"set\" && command.componentType) {\n const merge = getComponentMerge(command.componentType);\n let nextValue = command.component;\n if (merge !== undefined && pendingSetValues.has(command.componentType)) {\n const prevValue = pendingSetValues.get(command.componentType);\n nextValue = merge(prevValue, command.component);\n }\n pendingSetValues.set(command.componentType, nextValue);\n\n let data = this.componentEntityComponents.get(entityId);\n if (!data) {\n data = new Map();\n this.componentEntityComponents.set(entityId, data);\n this.registerRelationEntityId(entityId);\n }\n data.set(command.componentType, nextValue);\n } else if (command.type === \"delete\" && command.componentType) {\n const data = this.componentEntityComponents.get(entityId);\n\n if (isWildcardRelationId(command.componentType)) {\n const componentId = getComponentIdFromRelationId(command.componentType);\n if (componentId !== undefined) {\n if (data) {\n for (const key of Array.from(data.keys())) {\n if (getComponentIdFromRelationId(key) === componentId) {\n data.delete(key);\n }\n }\n }\n for (const key of Array.from(pendingSetValues.keys())) {\n if (getComponentIdFromRelationId(key) === componentId) {\n pendingSetValues.delete(key);\n }\n }\n }\n } else {\n data?.delete(command.componentType);\n pendingSetValues.delete(command.componentType);\n }\n\n if (data?.size === 0) {\n this.clear(entityId);\n }\n }\n }\n }\n\n /**\n * Initialize a component entity from a deserialization snapshot.\n */\n initFromSnapshot(entityId: EntityId, componentMap: Map<EntityId<any>, any>): void {\n this.componentEntityComponents.set(entityId, componentMap);\n this.registerRelationEntityId(entityId);\n }\n\n /**\n * Iterate over all component entity entries.\n * Used for serialization.\n */\n entries(): IterableIterator<[EntityId, Map<EntityId<any>, any>]> {\n return this.componentEntityComponents.entries();\n }\n\n private registerRelationEntityId(entityId: EntityId): void {\n const detailed = getDetailedIdType(entityId);\n if (detailed.type !== \"entity-relation\") return;\n const targetId = detailed.targetId;\n if (targetId === undefined) return;\n const existing = this.relationEntityIdsByTarget.get(targetId);\n if (existing) {\n existing.add(entityId);\n return;\n }\n this.relationEntityIdsByTarget.set(targetId, new Set([entityId]));\n }\n\n private unregisterRelationEntityId(entityId: EntityId): void {\n const detailed = getDetailedIdType(entityId);\n if (detailed.type !== \"entity-relation\") return;\n const targetId = detailed.targetId;\n if (targetId === undefined) return;\n const existing = this.relationEntityIdsByTarget.get(targetId);\n if (!existing) return;\n existing.delete(entityId);\n if (existing.size === 0) {\n this.relationEntityIdsByTarget.delete(targetId);\n }\n }\n}\n","import type { Archetype } from \"../archetype/archetype\";\nimport type { EntityId } from \"../entity\";\nimport { getComponentIdFromRelationId, getDetailedIdType, isRelationId, isSparseComponent, relation } from \"../entity\";\n\n/**\n * Filter options for queries\n */\nexport interface QueryFilter {\n negativeComponentTypes?: EntityId<any>[];\n}\n\n/**\n * Serialize a QueryFilter into a deterministic string suitable for cache keys.\n * Currently only serializes `negativeComponentTypes`.\n */\nexport function serializeQueryFilter(filter: QueryFilter = {}): string {\n const negative = (filter.negativeComponentTypes || []).slice().sort((a, b) => a - b);\n if (negative.length === 0) return \"\";\n return `neg:${negative.join(\",\")}`;\n}\n\n/**\n * Check if an archetype matches the given component types\n */\nexport function matchesComponentTypes(archetype: Archetype, componentTypes: EntityId<any>[]): boolean {\n return componentTypes.every((type) => {\n const detailedType = getDetailedIdType(type);\n if (detailedType.type === \"wildcard-relation\") {\n // For wildcard relations, check if archetype contains the component relation\n return archetype.componentTypes.some((archetypeType) => {\n if (!isRelationId(archetypeType)) return false;\n const componentId = getComponentIdFromRelationId(archetypeType);\n return componentId === detailedType.componentId;\n });\n } else if (\n (detailedType.type === \"entity-relation\" || detailedType.type === \"component-relation\") &&\n detailedType.componentId !== undefined &&\n isSparseComponent(detailedType.componentId)\n ) {\n // For specific sparse relations, check if archetype has the wildcard marker\n const wildcardMarker = relation(detailedType.componentId, \"*\");\n return archetype.componentTypeSet.has(wildcardMarker);\n } else {\n // For regular components and non-sparse relations, check direct inclusion\n return archetype.componentTypeSet.has(type);\n }\n });\n}\n\n/**\n * Check if an archetype matches the filter conditions (only filtering logic)\n */\nexport function matchesFilter(archetype: Archetype, filter: QueryFilter): boolean {\n const negativeTypes = filter.negativeComponentTypes || [];\n return negativeTypes.every((type) => {\n const detailedType = getDetailedIdType(type);\n if (detailedType.type === \"wildcard-relation\") {\n // For wildcard relations in negative filter, exclude archetypes that contain ANY relation with the same component\n return !archetype.componentTypes.some((archetypeType) => {\n if (!isRelationId(archetypeType)) return false;\n const componentId = getComponentIdFromRelationId(archetypeType);\n return componentId === detailedType.componentId;\n });\n } else {\n // For regular components, check direct exclusion\n return !archetype.componentTypeSet.has(type);\n }\n });\n}\n","import type { Archetype } from \"../archetype/archetype\";\nimport { normalizeComponentTypes } from \"../component/type-utils\";\nimport type { EntityId, WildcardRelationId } from \"../entity\";\nimport { getDetailedIdType, isSparseComponent } from \"../entity\";\nimport type { ComponentTuple, ComponentType } from \"../types\";\nimport type { World } from \"../world/world\";\nimport { matchesComponentTypes, matchesFilter, type QueryFilter } from \"./filter\";\nimport type { QueryRegistry } from \"./registry\";\n\n/**\n * Cached query for efficiently iterating entities with specific components.\n *\n * Queries are created via {@link World.createQuery} and should be **reused across frames**\n * for optimal performance. The world automatically keeps the query's internal archetype cache\n * up to date as entities are created and destroyed.\n *\n * @example\n * const movementQuery = world.createQuery([Position, Velocity]);\n *\n * // In the game loop\n * movementQuery.forEach([Position, Velocity], (entity, pos, vel) => {\n * pos.x += vel.x;\n * pos.y += vel.y;\n * });\n */\nexport class Query {\n private world: World;\n private componentTypes: EntityId<any>[];\n private filter: QueryFilter;\n private cachedArchetypes: Archetype[] = [];\n private isDisposed = false;\n /** Cache key assigned by World for O(1) releaseQuery lookup */\n _cacheKey: string | undefined;\n /** Cached wildcard component types for faster entity filtering */\n private wildcardTypes: WildcardRelationId<any>[];\n /** Cached specific sparse relation types that need entity-level filtering */\n private specificSparseRelationTypes: EntityId<any>[];\n\n /**\n * @internal Queries should be created via {@link World.createQuery}, not instantiated directly.\n */\n constructor(world: World, componentTypes: EntityId<any>[], filter: QueryFilter = {}, registry?: QueryRegistry) {\n this.world = world;\n this.componentTypes = normalizeComponentTypes(componentTypes);\n this.filter = filter;\n // Pre-compute wildcard types once\n this.wildcardTypes = this.componentTypes.filter(\n (ct) => getDetailedIdType(ct).type === \"wildcard-relation\",\n ) as WildcardRelationId<any>[];\n // Pre-compute specific sparse relation types that need entity-level filtering\n this.specificSparseRelationTypes = this.componentTypes.filter((ct) => {\n const detailedType = getDetailedIdType(ct);\n return (\n (detailedType.type === \"entity-relation\" || detailedType.type === \"component-relation\") &&\n detailedType.componentId !== undefined &&\n isSparseComponent(detailedType.componentId)\n );\n });\n this.updateCache();\n // Register with registry for archetype updates\n if (registry) {\n registry.register(this);\n }\n }\n\n /**\n * Check if query is disposed and throw error if so\n */\n private ensureNotDisposed(): void {\n if (this.isDisposed) {\n throw new Error(\"Query has been disposed\");\n }\n }\n\n /**\n * Returns all entity IDs that match this query.\n *\n * @returns Array of matching entity IDs\n *\n * @example\n * const entities = query.getEntities();\n * for (const entity of entities) {\n * const pos = world.get(entity, Position);\n * }\n */\n getEntities(): EntityId[] {\n this.ensureNotDisposed();\n\n // Fast path: no wildcard relations and no specific sparse relations\n if (this.wildcardTypes.length === 0 && this.specificSparseRelationTypes.length === 0) {\n const result: EntityId[] = [];\n for (const archetype of this.cachedArchetypes) {\n for (const entity of archetype.getEntities()) {\n result.push(entity);\n }\n }\n return result;\n }\n\n // Slow path: need to filter entities that actually have the required relations\n // This is necessary for:\n // 1. Wildcard relations where an archetype can contain entities with/without the relation\n // 2. Specific sparse relations where the archetype only has the wildcard marker\n const result: EntityId[] = [];\n for (const archetype of this.cachedArchetypes) {\n for (const entity of archetype.getEntities()) {\n if (this.entityMatchesQuery(archetype, entity)) {\n result.push(entity);\n }\n }\n }\n return result;\n }\n\n /**\n * Check if entity matches all query requirements (wildcards and specific sparse relations)\n */\n private entityMatchesQuery(archetype: Archetype, entity: EntityId): boolean {\n // Check wildcard relations\n for (const wildcardType of this.wildcardTypes) {\n const relations = archetype.get(entity, wildcardType);\n if (!relations || relations.length === 0) {\n return false;\n }\n }\n\n // Check specific sparse relations\n for (const specificType of this.specificSparseRelationTypes) {\n const result = archetype.getOptional(entity, specificType);\n if (result === undefined) {\n return false;\n }\n }\n\n return true;\n }\n\n /**\n * Returns all matching entities along with their component data.\n *\n * @param componentTypes - Array of component types to retrieve\n * @returns Array of objects containing the entity ID and its component tuple\n *\n * @example\n * const results = query.getEntitiesWithComponents([Position, Velocity]);\n * results.forEach(({ entity, components: [pos, vel] }) => {\n * pos.x += vel.x;\n * });\n */\n getEntitiesWithComponents<const T extends readonly ComponentType<any>[]>(\n componentTypes: T,\n ): Array<{\n entity: EntityId;\n components: ComponentTuple<T>;\n }> {\n this.ensureNotDisposed();\n\n const result: Array<{\n entity: EntityId;\n components: ComponentTuple<T>;\n }> = [];\n\n for (const archetype of this.cachedArchetypes) {\n archetype.appendEntitiesWithComponents(componentTypes, result);\n }\n\n return result;\n }\n\n /**\n * Iterates over all matching entities and invokes the callback with their component data.\n * This is the preferred way to read and mutate components in a hot loop.\n *\n * @param componentTypes - Array of component types to retrieve\n * @param callback - Function called for each matching entity with its components\n *\n * @example\n * query.forEach([Position, Velocity], (entity, pos, vel) => {\n * pos.x += vel.x;\n * pos.y += vel.y;\n * });\n */\n forEach<const T extends readonly ComponentType<any>[]>(\n componentTypes: T,\n callback: (entity: EntityId, ...components: ComponentTuple<T>) => void,\n ): void {\n this.ensureNotDisposed();\n\n for (const archetype of this.cachedArchetypes) {\n archetype.forEachWithComponents(componentTypes, callback);\n }\n }\n\n /**\n * Generator that yields each matching entity together with its component data.\n *\n * @param componentTypes - Array of component types to retrieve\n * @yields Tuples of `[entityId, ...components]`\n *\n * @example\n * for (const [entity, pos, vel] of query.iterate([Position, Velocity])) {\n * pos.x += vel.x;\n * }\n */\n *iterate<const T extends readonly ComponentType<any>[]>(\n componentTypes: T,\n ): IterableIterator<[EntityId, ...ComponentTuple<T>]> {\n this.ensureNotDisposed();\n\n for (const archetype of this.cachedArchetypes) {\n yield* archetype.iterateWithComponents(componentTypes);\n }\n }\n\n /**\n * Returns an array containing the data of a single component for every matching entity.\n *\n * @param componentType - The component type to retrieve\n * @returns Array of component data (one entry per matching entity)\n *\n * @example\n * const positions = query.getComponentData(Position);\n */\n getComponentData<T>(componentType: EntityId<T>): T[] {\n this.ensureNotDisposed();\n\n const result: T[] = [];\n for (const archetype of this.cachedArchetypes) {\n for (const data of archetype.getComponentData(componentType)) {\n result.push(data);\n }\n }\n return result;\n }\n\n /**\n * @internal Rebuilds the cached archetype list. Called automatically by the world.\n */\n updateCache(): void {\n if (this.isDisposed) return;\n\n this.cachedArchetypes = this.world\n .getMatchingArchetypes(this.componentTypes)\n .filter((archetype: Archetype) => matchesFilter(archetype, this.filter));\n }\n\n /**\n * @internal Called by the world when a new archetype is created.\n */\n checkNewArchetype(archetype: Archetype): void {\n if (this.isDisposed) return;\n if (\n matchesComponentTypes(archetype, this.componentTypes) &&\n matchesFilter(archetype, this.filter) &&\n !this.cachedArchetypes.includes(archetype)\n ) {\n this.cachedArchetypes.push(archetype);\n }\n }\n\n /**\n * @internal Called by the world when an archetype is destroyed.\n */\n removeArchetype(archetype: Archetype): void {\n if (this.isDisposed) return;\n const index = this.cachedArchetypes.indexOf(archetype);\n if (index !== -1) {\n this.cachedArchetypes.splice(index, 1);\n }\n }\n\n /**\n * Request disposal of this query.\n * This will decrement the world's reference count for the query.\n * The query will only be fully disposed when the ref count reaches zero.\n */\n dispose(): void {\n // Ask the world to release this query (decrement refcount and fully dispose when zero)\n this.world.releaseQuery(this);\n }\n\n /**\n * @internal Fully disposes the query when the world's refCount reaches zero.\n */\n _disposeInternal(registry?: QueryRegistry): void {\n if (!this.isDisposed) {\n // Unregister from registry (remove from notification list)\n if (registry) {\n registry.unregister(this);\n }\n this.cachedArchetypes = [];\n this.isDisposed = true;\n }\n }\n\n /**\n * Using-with-disposals support. Calls {@link dispose} automatically.\n *\n * @example\n * using query = world.createQuery([Position]);\n * // query is released automatically when the block exits\n */\n [Symbol.dispose](): void {\n this.dispose();\n }\n\n /**\n * Whether the query has been disposed and can no longer be used.\n */\n get disposed(): boolean {\n return this.isDisposed;\n }\n}\n","import type { Archetype } from \"../archetype/archetype\";\nimport type { EntityId } from \"../entity\";\nimport type { QueryFilter } from \"../query/filter\";\nimport { Query } from \"../query/query\";\nimport type { World } from \"../world/world\";\n\n/**\n * Manages the lifecycle and caching of `Query` instances.\n *\n * Responsibilities:\n * - Create / reuse cached queries keyed by component-type + filter signature.\n * - Track reference counts so queries are only disposed when truly unused.\n * - Notify registered queries when new archetypes are created or destroyed.\n *\n * The `_cacheKey` string that was previously attached directly to `Query` is now\n * kept in a private `WeakMap` so the `Query` class doesn't need to expose it.\n */\nexport class QueryRegistry {\n /** All live queries that should receive archetype notifications. */\n private readonly queries = new Set<Query>();\n /** Cache of reusable queries keyed by a deterministic signature string. */\n private readonly cache = new Map<string, { query: Query; refCount: number }>();\n /** Maps each query to its cache key without polluting the Query public API. */\n private readonly cacheKeys = new WeakMap<Query, string>();\n\n /**\n * Returns (or creates) a cached query for the given component types and filter.\n * Increments the reference count on cache hits.\n *\n * @param world The world that owns this registry.\n * @param sortedTypes Normalized (sorted) component types.\n * @param key Combined cache key (`types|filter`).\n * @param filter The raw query filter (used when creating a new Query).\n */\n getOrCreate(world: World, sortedTypes: EntityId<any>[], key: string, filter: QueryFilter): Query {\n const cached = this.cache.get(key);\n if (cached) {\n cached.refCount++;\n return cached.query;\n }\n\n const query = new Query(world, sortedTypes, filter, this);\n this.cacheKeys.set(query, key);\n this.cache.set(key, { query, refCount: 1 });\n return query;\n }\n\n /**\n * Decrements the reference count for the given query.\n * When the count reaches zero the query is fully disposed.\n */\n release(query: Query): void {\n const key = this.cacheKeys.get(query);\n if (!key) return;\n\n const cached = this.cache.get(key);\n if (!cached || cached.query !== query) return;\n\n cached.refCount--;\n if (cached.refCount <= 0) {\n this.cache.delete(key);\n cached.query._disposeInternal(this);\n }\n }\n\n /**\n * Registers a query so it receives future archetype notifications.\n * Called automatically by the `Query` constructor via `world._registerQuery`.\n */\n register(query: Query): void {\n this.queries.add(query);\n }\n\n /**\n * Removes a query from the notification list.\n * Called by `Query._disposeInternal` via `world._unregisterQuery`.\n */\n unregister(query: Query): void {\n this.queries.delete(query);\n }\n\n /**\n * Notifies all live queries that a new archetype has been created.\n * Queries will add the archetype to their cache if it matches.\n */\n onNewArchetype(archetype: Archetype): void {\n for (const query of this.queries) {\n query.checkNewArchetype(archetype);\n }\n }\n\n /**\n * Notifies all live queries that an archetype has been destroyed.\n * Queries will remove the archetype from their internal cache.\n */\n onArchetypeRemoved(archetype: Archetype): void {\n for (const query of this.queries) {\n query.removeArchetype(archetype);\n }\n }\n}\n","import type { Archetype } from \"../archetype/archetype\";\nimport type { SparseStore } from \"../archetype/store\";\nimport type { Command } from \"../commands/buffer\";\nimport type { ComponentChangeset } from \"../commands/changeset\";\nimport { normalizeComponentTypes } from \"../component/type-utils\";\nimport {\n getComponentIdFromRelationId,\n getComponentMerge,\n isSparseComponent,\n isSparseRelation,\n isSparseWildcard,\n isWildcardRelationId,\n relation,\n type ComponentId,\n type EntityId,\n} from \"../entity\";\n\nexport interface CommandProcessorContext {\n sparseStore: SparseStore;\n ensureArchetype: (componentTypes: Iterable<EntityId<any>>) => Archetype;\n}\n\nexport function processCommands(\n entityId: EntityId,\n currentArchetype: Archetype,\n commands: Command[],\n changeset: ComponentChangeset,\n handleExclusiveRelation: (entityId: EntityId, archetype: Archetype, componentId: ComponentId<any>) => void,\n): void {\n for (const command of commands) {\n if (command.type === \"set\") {\n // TypeScript knows command.componentType and command.component exist\n processSetCommand(\n entityId,\n currentArchetype,\n command.componentType,\n command.component,\n changeset,\n handleExclusiveRelation,\n );\n } else if (command.type === \"delete\") {\n // TypeScript knows command.componentType exists\n processDeleteCommand(entityId, currentArchetype, command.componentType, changeset);\n }\n }\n}\n\nfunction processSetCommand(\n entityId: EntityId,\n currentArchetype: Archetype,\n componentType: EntityId<any>,\n component: any,\n changeset: ComponentChangeset,\n handleExclusiveRelation: (entityId: EntityId, archetype: Archetype, componentId: ComponentId<any>) => void,\n): void {\n // Extract componentId if it's a relation (fast path)\n const componentId = getComponentIdFromRelationId(componentType);\n if (componentId !== undefined) {\n // Handle exclusive relations by removing existing relations with the same base component\n handleExclusiveRelation(entityId, currentArchetype, componentId);\n\n // For sparse relations, ensure wildcard marker is in archetype signature\n if (isSparseComponent(componentId)) {\n const wildcardMarker = relation(componentId, \"*\");\n // Add wildcard marker to changeset if not already in archetype\n if (!currentArchetype.componentTypeSet.has(wildcardMarker)) {\n changeset.set(wildcardMarker, undefined);\n }\n }\n }\n\n const merge = getComponentMerge(componentType);\n if (merge !== undefined && changeset.adds.has(componentType)) {\n const prev = changeset.adds.get(componentType);\n changeset.set(componentType, merge(prev, component));\n return;\n }\n\n changeset.set(componentType, component);\n}\n\nfunction processDeleteCommand(\n entityId: EntityId,\n currentArchetype: Archetype,\n componentType: EntityId<any>,\n changeset: ComponentChangeset,\n): void {\n const componentId = getComponentIdFromRelationId(componentType);\n\n if (isWildcardRelationId(componentType) && componentId !== undefined) {\n removeWildcardRelations(entityId, currentArchetype, componentId, changeset);\n } else {\n changeset.delete(componentType);\n maybeRemoveWildcardMarker(entityId, currentArchetype, componentType, componentId, changeset);\n }\n}\n\nexport function removeMatchingRelations(\n entityId: EntityId,\n archetype: Archetype,\n baseComponentId: ComponentId<any>,\n changeset: ComponentChangeset,\n): void {\n // Check archetype components\n for (const componentType of archetype.componentTypes) {\n // Skip wildcard markers - they should only be removed by maybeRemoveWildcardMarker\n if (isWildcardRelationId(componentType)) continue;\n\n if (getComponentIdFromRelationId(componentType) === baseComponentId) {\n changeset.delete(componentType);\n }\n }\n\n // Check sparse relations stored on entity\n const sparseData = archetype.getEntitySparseRelations(entityId);\n if (sparseData) {\n for (const componentType of sparseData.keys()) {\n if (getComponentIdFromRelationId(componentType) === baseComponentId) {\n changeset.delete(componentType);\n }\n }\n }\n}\n\nfunction removeWildcardRelations(\n entityId: EntityId,\n currentArchetype: Archetype,\n baseComponentId: ComponentId<any>,\n changeset: ComponentChangeset,\n): void {\n removeMatchingRelations(entityId, currentArchetype, baseComponentId, changeset);\n\n // If removing sparse relations, also remove the wildcard marker\n if (isSparseComponent(baseComponentId)) {\n changeset.delete(relation(baseComponentId, \"*\"));\n }\n}\n\nexport function maybeRemoveWildcardMarker(\n entityId: EntityId,\n archetype: Archetype,\n removedComponentType: EntityId<any>,\n componentId: ComponentId<any> | undefined,\n changeset: ComponentChangeset,\n): void {\n if (componentId === undefined || !isSparseComponent(componentId)) {\n return;\n }\n\n const wildcardMarker = relation(componentId, \"*\");\n\n // Check if there are any other relations with the same component ID\n for (const otherComponentType of archetype.componentTypes) {\n if (otherComponentType === removedComponentType) continue;\n if (otherComponentType === wildcardMarker) continue;\n if (changeset.removes.has(otherComponentType)) continue;\n\n if (getComponentIdFromRelationId(otherComponentType) === componentId) {\n return; // Found another relation, keep the marker\n }\n }\n\n const sparseData = archetype.getEntitySparseRelations(entityId);\n if (sparseData) {\n for (const otherComponentType of sparseData.keys()) {\n if (otherComponentType === removedComponentType) continue;\n if (changeset.removes.has(otherComponentType)) continue;\n\n if (getComponentIdFromRelationId(otherComponentType) === componentId) {\n return; // Found another relation, keep the marker\n }\n }\n }\n\n // Also check if this changeset itself is adding another relation of the same kind\n // (common in exclusive sparse flips: remove old target + add new target in one batch)\n for (const addedType of changeset.adds.keys()) {\n if (addedType === removedComponentType) continue;\n if (getComponentIdFromRelationId(addedType) === componentId) {\n return; // Replacement is being added in the same changeset, keep the marker\n }\n }\n\n changeset.delete(wildcardMarker);\n}\n\nfunction hasEntityComponent(archetype: Archetype, entityId: EntityId, componentType: EntityId<any>): boolean {\n if (archetype.componentTypeSet.has(componentType)) {\n return true;\n }\n\n return archetype.getEntitySparseRelations(entityId)?.has(componentType) ?? false;\n}\n\nfunction pruneMissingRemovals(changeset: ComponentChangeset, archetype: Archetype, entityId: EntityId): void {\n // Collect to-prune entries first to avoid mutating the set during iteration\n let toPrune: EntityId<any>[] | undefined;\n for (const componentType of changeset.removes) {\n if (!hasEntityComponent(archetype, entityId, componentType)) {\n if (toPrune === undefined) toPrune = [];\n toPrune.push(componentType);\n }\n }\n if (toPrune !== undefined) {\n for (const componentType of toPrune) {\n changeset.removes.delete(componentType);\n }\n }\n}\n\nfunction hasArchetypeStructuralChange(changeset: ComponentChangeset, currentArchetype: Archetype): boolean {\n for (const componentType of changeset.removes) {\n if (!isSparseRelation(componentType) && currentArchetype.componentTypeSet.has(componentType)) {\n return true;\n }\n }\n\n for (const componentType of changeset.adds.keys()) {\n if (!isSparseRelation(componentType) && !currentArchetype.componentTypeSet.has(componentType)) {\n return true;\n }\n }\n\n return false;\n}\n\nfunction buildFinalRegularComponentTypes(currentArchetype: Archetype, changeset: ComponentChangeset): EntityId<any>[] {\n const finalRegularTypes = new Set(currentArchetype.componentTypes);\n\n for (const componentType of changeset.removes) {\n if (!isSparseRelation(componentType)) {\n finalRegularTypes.delete(componentType);\n }\n }\n\n for (const [componentType] of changeset.adds) {\n if (!isSparseRelation(componentType)) {\n finalRegularTypes.add(componentType);\n }\n }\n\n return Array.from(finalRegularTypes);\n}\n\nexport function applyChangeset(\n ctx: CommandProcessorContext,\n entityId: EntityId,\n currentArchetype: Archetype,\n changeset: ComponentChangeset,\n entityToArchetype: Map<EntityId, Archetype>,\n removedComponents: Map<EntityId<any>, any> | null,\n): Archetype {\n pruneMissingRemovals(changeset, currentArchetype, entityId);\n const archetypeChanged = hasArchetypeStructuralChange(changeset, currentArchetype);\n\n if (archetypeChanged) {\n const finalRegularTypes = buildFinalRegularComponentTypes(currentArchetype, changeset);\n const newArchetype = ctx.ensureArchetype(finalRegularTypes);\n const currentComponents = currentArchetype.removeEntity(entityId)!;\n\n if (removedComponents !== null) {\n for (const componentType of changeset.removes) {\n removedComponents.set(componentType, currentComponents.get(componentType));\n }\n }\n\n newArchetype.addEntity(entityId, changeset.applyTo(currentComponents));\n entityToArchetype.set(entityId, newArchetype);\n return newArchetype;\n }\n\n // No archetype move needed: only component payload updates and/or sparse relation updates.\n if (removedComponents !== null) {\n applySparseChanges(ctx.sparseStore, entityId, changeset, removedComponents);\n } else {\n applySparseChangesNoHooks(ctx.sparseStore, entityId, changeset);\n }\n\n // Direct update for regular components in archetype\n for (const [componentType, component] of changeset.adds) {\n if (isSparseRelation(componentType)) {\n continue;\n }\n currentArchetype.set(entityId, componentType, component);\n }\n\n return currentArchetype;\n}\n\nfunction applySparseChanges(\n sparseStore: SparseStore,\n entityId: EntityId,\n changeset: ComponentChangeset,\n removedComponents: Map<EntityId<any>, any>,\n): void {\n for (const componentType of changeset.removes) {\n if (isSparseRelation(componentType)) {\n const removedValue = sparseStore.getValue(entityId, componentType);\n // Record for hooks if we are actually removing something\n if (removedValue !== undefined || sparseStore.getAllForEntity(entityId).some(([t]) => t === componentType)) {\n removedComponents.set(componentType, removedValue);\n }\n sparseStore.deleteValue(entityId, componentType);\n }\n }\n\n for (const [componentType, component] of changeset.adds) {\n if (isSparseRelation(componentType)) {\n sparseStore.setValue(entityId, componentType, component);\n }\n }\n}\n\nfunction applySparseChangesNoHooks(sparseStore: SparseStore, entityId: EntityId, changeset: ComponentChangeset): void {\n for (const componentType of changeset.removes) {\n if (isSparseRelation(componentType)) {\n sparseStore.deleteValue(entityId, componentType);\n }\n }\n\n for (const [componentType, component] of changeset.adds) {\n if (isSparseRelation(componentType)) {\n sparseStore.setValue(entityId, componentType, component);\n }\n }\n}\n\nexport function filterRegularComponentTypes(componentTypes: Iterable<EntityId<any>>): EntityId<any>[] {\n const regularTypes: EntityId<any>[] = [];\n\n for (const componentType of componentTypes) {\n // Keep wildcard markers for sparse components (they mark the archetype)\n if (isSparseWildcard(componentType)) {\n regularTypes.push(componentType);\n continue;\n }\n\n // Skip specific sparse relations from archetype signature\n if (isSparseRelation(componentType)) {\n continue;\n }\n\n regularTypes.push(componentType);\n }\n\n return regularTypes;\n}\n\nexport function areComponentTypesEqual(types1: EntityId<any>[], types2: EntityId<any>[]): boolean {\n if (types1.length !== types2.length) return false;\n const sorted1 = normalizeComponentTypes(types1);\n const sorted2 = normalizeComponentTypes(types2);\n return sorted1.every((v, i) => v === sorted2[i]);\n}\n","import { Archetype } from \"../archetype/archetype\";\nimport type { SparseStore } from \"../archetype/store\";\nimport { normalizeComponentTypes } from \"../component/type-utils\";\nimport type { EntityId } from \"../entity\";\nimport {\n getComponentIdFromRelationId,\n getDetailedIdType,\n isSparseRelation,\n isSparseWildcard,\n isWildcardRelationId,\n} from \"../entity\";\nimport { matchesFilter } from \"../query/filter\";\nimport type { QueryRegistry } from \"../query/registry\";\nimport type { LifecycleHookEntry } from \"../types\";\nimport { getOrCompute } from \"../utils/utils\";\nimport { filterRegularComponentTypes } from \"./commands\";\n\n/**\n * Context provided to ArchetypeManager for notifying dependent systems\n * (query caching and lifecycle hooks) without creating tight coupling or cycles.\n * Follows the same callback/context injection pattern used by CommandProcessorContext,\n * HooksContext, and WorldDeserializationContext.\n */\nexport interface ArchetypeManagerContext {\n queryRegistry: QueryRegistry;\n hooks: Set<LifecycleHookEntry>;\n /** Called only when debug collectors are active (mirrors original guard in World) */\n recordArchetypeCreated?: () => void;\n recordArchetypeRemoved?: () => void;\n}\n\n/**\n * Encapsulates all archetype storage, indexing, creation, removal, and reverse\n * referencing logic that was previously scattered as private methods + maps\n * directly on the World class.\n *\n * Responsibilities:\n * - Archetype memoization by signature\n * - Component-type reverse index (archetypesByComponent)\n * - Entity → current Archetype map\n * - Reverse \"who references this entity via component/relation\" index\n * - Creation + removal with proper notifications to QueryRegistry + hook matching\n * - Cleanup of empty archetypes after entity cascades\n *\n * This extraction shrinks World while keeping the same behavior and hot-path characteristics.\n */\nexport class ArchetypeManager {\n // Public for performance (hot paths access these maps frequently).\n // This intentionally breaks encapsulation a bit for speed, as requested.\n readonly archetypes: Archetype[] = [];\n readonly archetypeBySignature = new Map<string, Archetype>();\n readonly entityToArchetype = new Map<EntityId, Archetype>();\n readonly archetypesByComponent = new Map<EntityId<any>, Set<Archetype>>();\n readonly entityToReferencingArchetypes = new Map<EntityId, Set<Archetype>>();\n\n private readonly sparseStore: SparseStore;\n private readonly ctx: ArchetypeManagerContext;\n\n constructor(ctx: ArchetypeManagerContext, sparseStore: SparseStore) {\n this.ctx = ctx;\n this.sparseStore = sparseStore;\n }\n\n // ------------------------------------------------------------------\n // Public / package-internal surface used by World and its close collaborators\n // (commands.ts applyChangeset, serialization deserialization context, etc.)\n // ------------------------------------------------------------------\n\n /** Primary entry point — memoized archetype creation/lookup. */\n ensureArchetype(componentTypes: Iterable<EntityId<any>>): Archetype {\n const regularTypes = filterRegularComponentTypes(componentTypes);\n const sortedTypes = normalizeComponentTypes(regularTypes);\n const hashKey = this.createArchetypeSignature(sortedTypes);\n\n return getOrCompute(this.archetypeBySignature, hashKey, () => this.createNewArchetype(sortedTypes));\n }\n\n getArchetypeForEntity(entityId: EntityId): Archetype | undefined {\n return this.entityToArchetype.get(entityId);\n }\n\n setEntityToArchetype(entityId: EntityId, archetype: Archetype): void {\n this.entityToArchetype.set(entityId, archetype);\n }\n\n // Query helpers (moved from World for cohesion)\n getMatchingArchetypes(componentTypes: EntityId<any>[]): Archetype[] {\n if (componentTypes.length === 0) {\n return [...this.archetypes];\n }\n\n const regularComponents: EntityId<any>[] = [];\n const wildcardRelations: { componentId: EntityId<any>; relationId: EntityId<any> }[] = [];\n\n for (const componentType of componentTypes) {\n if (isWildcardRelationId(componentType)) {\n const componentId = getComponentIdFromRelationId(componentType);\n if (componentId !== undefined) {\n wildcardRelations.push({ componentId, relationId: componentType });\n }\n } else {\n regularComponents.push(componentType);\n }\n }\n\n let matchingArchetypes = this.getArchetypesWithComponents(regularComponents);\n\n for (const { componentId, relationId } of wildcardRelations) {\n const markerSet = this.archetypesByComponent.get(relationId);\n const archetypesWithMarker = markerSet ? Array.from(markerSet) : [];\n matchingArchetypes =\n matchingArchetypes.length === 0\n ? archetypesWithMarker\n : matchingArchetypes.filter((a) => markerSet?.has(a) || a.hasRelationWithComponentId(componentId));\n }\n\n return matchingArchetypes;\n }\n\n getArchetypesWithComponents(componentTypes: EntityId<any>[]): Archetype[] {\n if (componentTypes.length === 0) return [...this.archetypes];\n if (componentTypes.length === 1) {\n const set = this.archetypesByComponent.get(componentTypes[0]!);\n return set ? Array.from(set) : [];\n }\n\n // Sort by Set size, intersect starting from the smallest\n const sets = componentTypes\n .map((type) => this.archetypesByComponent.get(type))\n .filter((s): s is Set<Archetype> => s !== undefined && s.size > 0)\n .sort((a, b) => a.size - b.size);\n\n if (sets.length === 0) return [];\n if (sets.length < componentTypes.length) return []; // One component has no matching archetypes\n\n const smallest = sets[0]!;\n\n // 2-component fast path\n if (sets.length === 2) {\n const other = sets[1]!;\n return Array.from(smallest).filter((a) => other.has(a));\n }\n\n // Multi-component intersection\n let result = new Set(smallest);\n for (let i = 1; i < sets.length; i++) {\n for (const item of result) {\n if (!sets[i]!.has(item)) result.delete(item);\n }\n if (result.size === 0) return [];\n }\n return Array.from(result);\n }\n\n // ------------------------------------------------------------------\n // Internal creation / removal (core of the original cluster)\n // ------------------------------------------------------------------\n\n private createArchetypeSignature(componentTypes: EntityId<any>[]): string {\n return componentTypes.join(\",\");\n }\n\n /** Deduplicated version of the original pair of methods. */\n private updateReferencingIndex(componentType: EntityId<any>, archetype: Archetype, isAdd: boolean): void {\n const detailedType = getDetailedIdType(componentType);\n let entityId: EntityId | undefined;\n\n if (detailedType.type === \"entity\") {\n entityId = componentType as EntityId;\n } else if (detailedType.type === \"entity-relation\") {\n entityId = detailedType.targetId;\n }\n\n if (entityId !== undefined) {\n let refs = this.entityToReferencingArchetypes.get(entityId);\n if (isAdd) {\n if (!refs) {\n refs = new Set();\n this.entityToReferencingArchetypes.set(entityId, refs);\n }\n refs.add(archetype);\n } else {\n if (refs) {\n refs.delete(archetype);\n if (refs.size === 0) {\n this.entityToReferencingArchetypes.delete(entityId);\n }\n }\n }\n }\n }\n\n private createNewArchetype(componentTypes: EntityId<any>[]): Archetype {\n const newArchetype = new Archetype(componentTypes, this.sparseStore);\n this.archetypes.push(newArchetype);\n\n this.ctx.recordArchetypeCreated?.();\n\n for (const componentType of componentTypes) {\n let archetypes = this.archetypesByComponent.get(componentType);\n if (!archetypes) {\n archetypes = new Set();\n this.archetypesByComponent.set(componentType, archetypes);\n }\n archetypes.add(newArchetype);\n\n // Update reverse index (deduped)\n this.updateReferencingIndex(componentType, newArchetype, true);\n }\n\n this.ctx.queryRegistry.onNewArchetype(newArchetype);\n this.updateArchetypeHookMatches(newArchetype);\n\n return newArchetype;\n }\n\n private updateArchetypeHookMatches(archetype: Archetype): void {\n for (const entry of this.ctx.hooks) {\n if (this.archetypeMatchesHook(archetype, entry)) {\n archetype.matchingMultiHooks.add(entry);\n if (entry.matchedArchetypes) {\n entry.matchedArchetypes.add(archetype);\n }\n }\n }\n }\n\n public archetypeMatchesHook(archetype: Archetype, entry: LifecycleHookEntry): boolean {\n return (\n entry.requiredComponents.every((c: EntityId<any>) => {\n if (isWildcardRelationId(c)) {\n if (isSparseWildcard(c)) return true;\n const componentId = getComponentIdFromRelationId(c);\n return componentId !== undefined && archetype.hasRelationWithComponentId(componentId);\n }\n return archetype.componentTypeSet.has(c) || isSparseRelation(c);\n }) && matchesFilter(archetype, entry.filter)\n );\n }\n\n /** Called during cascade deletion cleanup. */\n cleanupArchetypesReferencingEntity(entityId: EntityId): void {\n const refs = this.entityToReferencingArchetypes.get(entityId);\n if (!refs) return;\n\n for (const archetype of refs) {\n if (archetype.getEntities().length === 0) {\n this.removeArchetype(archetype);\n }\n }\n // removeArchetype already cleans up the reverse index entries for the archetypes themselves\n this.entityToReferencingArchetypes.delete(entityId);\n }\n\n private removeArchetype(archetype: Archetype): void {\n const index = this.archetypes.indexOf(archetype);\n if (index !== -1) {\n // swap-and-pop: O(1) removal\n const last = this.archetypes[this.archetypes.length - 1]!;\n this.archetypes[index] = last;\n this.archetypes.pop();\n }\n\n this.ctx.recordArchetypeRemoved?.();\n\n this.archetypeBySignature.delete(this.createArchetypeSignature(archetype.componentTypes));\n\n for (const componentType of archetype.componentTypes) {\n const archetypes = this.archetypesByComponent.get(componentType);\n if (archetypes) {\n archetypes.delete(archetype);\n if (archetypes.size === 0) {\n this.archetypesByComponent.delete(componentType);\n }\n }\n\n // Clean up reverse index (deduped)\n this.updateReferencingIndex(componentType, archetype, false);\n }\n\n this.ctx.queryRegistry.onArchetypeRemoved(archetype);\n }\n}\n","import type { EntityId } from \"../entity\";\n\n/**\n * @internal Represents a set of component changes to be applied to an entity\n */\nexport class ComponentChangeset {\n readonly adds = new Map<EntityId<any>, any>();\n readonly removes = new Set<EntityId<any>>();\n\n /**\n * Add a component to the changeset\n */\n set<T>(componentType: EntityId<T>, component: T): void {\n this.adds.set(componentType, component);\n this.removes.delete(componentType); // Remove from removes if it was going to be removed\n }\n\n /**\n * Remove a component from the changeset\n */\n delete<T>(componentType: EntityId<T>): void {\n this.removes.add(componentType);\n this.adds.delete(componentType); // Remove from adds if it was going to be added\n }\n\n /**\n * Check if the changeset has any changes\n */\n hasChanges(): boolean {\n return this.adds.size > 0 || this.removes.size > 0;\n }\n\n /**\n * Clear all changes\n */\n clear(): void {\n this.adds.clear();\n this.removes.clear();\n }\n\n /**\n * Merge another changeset into this one\n */\n merge(other: ComponentChangeset): void {\n // Merge additions\n for (const [componentType, component] of other.adds) {\n this.adds.set(componentType, component);\n this.removes.delete(componentType);\n }\n // Merge removals\n for (const componentType of other.removes) {\n this.removes.add(componentType);\n this.adds.delete(componentType);\n }\n }\n\n /**\n * Apply the changeset to existing components and return the final state\n */\n applyTo(existingComponents: Map<EntityId<any>, any>): Map<EntityId<any>, any> {\n // Apply removals\n for (const componentType of this.removes) {\n existingComponents.delete(componentType);\n }\n\n // Apply additions/updates\n for (const [componentType, component] of this.adds) {\n existingComponents.set(componentType, component);\n }\n\n return existingComponents;\n }\n}\n","import type { Archetype } from \"../archetype/archetype\";\nimport {\n getComponentIdFromRelationId,\n getTargetIdFromRelationId,\n isWildcardRelationId,\n type EntityId,\n} from \"../entity\";\nimport { isOptionalEntityId, type ComponentType, type LifecycleHookEntry } from \"../types\";\n\n/**\n * Debug-only counter incremented on every invokeHook call when armed.\n * World reads and resets this during armed syncs.\n */\nexport const debugHookExecutionCounter = { value: 0 };\n\n/**\n * Unified hook invocation: prefers entry.callback (callback style) over hook.on_* (object style).\n */\nfunction invokeHook(\n entry: LifecycleHookEntry,\n event: \"init\" | \"set\" | \"remove\",\n entityId: EntityId,\n components: any[],\n): void {\n debugHookExecutionCounter.value++;\n\n if (entry.callback) {\n entry.callback(event as any, entityId, ...components);\n return;\n }\n const hook = entry.hook;\n if (event === \"init\") hook.on_init?.(entityId, ...components);\n else if (event === \"set\") hook.on_set?.(entityId, ...components);\n else hook.on_remove?.(entityId, ...components);\n}\n\n/**\n * Check if a component change matches a hook component type.\n * Handles wildcard-relation matching: if hookComponent is a wildcard relation (e.g., relation(A, \"*\")),\n * it matches any concrete relation with the same component ID (e.g., relation(A, entity1)).\n */\nfunction componentMatchesHookType(changedComponent: EntityId<any>, hookComponent: EntityId<any>): boolean {\n if (changedComponent === hookComponent) return true;\n\n // Check if hookComponent is a wildcard relation and changedComponent is a matching relation\n if (isWildcardRelationId(hookComponent)) {\n const hookComponentId = getComponentIdFromRelationId(hookComponent);\n const changedComponentId = getComponentIdFromRelationId(changedComponent);\n if (hookComponentId !== undefined && changedComponentId !== undefined) {\n return hookComponentId === changedComponentId;\n }\n }\n\n return false;\n}\n\n/**\n * Check if any component in the changes map matches a hook component type.\n */\nfunction anyComponentMatches(changes: Map<EntityId<any>, any>, hookComponent: EntityId<any>): boolean {\n for (const changedComponent of changes.keys()) {\n if (componentMatchesHookType(changedComponent, hookComponent)) {\n return true;\n }\n }\n return false;\n}\n\n/**\n * Find a matching component in the changes map that matches the hook component type.\n * Returns [componentId, value] if found, undefined otherwise.\n */\nfunction findMatchingComponent(\n changes: Map<EntityId<any>, any>,\n hookComponent: EntityId<any>,\n): [EntityId<any>, any] | undefined {\n for (const [changedComponent, value] of changes.entries()) {\n if (componentMatchesHookType(changedComponent, hookComponent)) {\n return [changedComponent, value];\n }\n }\n return undefined;\n}\n\nexport interface HooksContext {\n multiHooks: Set<LifecycleHookEntry>;\n has: (entityId: EntityId, componentType: EntityId<any>) => boolean;\n get: <T>(entityId: EntityId, componentType: EntityId<T>) => T;\n getOptional: <T>(entityId: EntityId, componentType: EntityId<T>) => { value: T } | undefined;\n}\n\nexport function triggerLifecycleHooks(\n ctx: HooksContext,\n entityId: EntityId,\n addedComponents: Map<EntityId<any>, any>,\n removedComponents: Map<EntityId<any>, any>,\n oldArchetype: Archetype,\n newArchetype: Archetype,\n): void {\n triggerMultiComponentHooks(ctx, entityId, addedComponents, removedComponents, oldArchetype, newArchetype);\n}\n\n/**\n * Fast path for triggering lifecycle hooks when an entity is being deleted.\n * This avoids unnecessary archetype lookups and on_set checks since the entity\n * is being completely removed.\n */\nexport function triggerRemoveHooksForEntityDeletion(\n entityId: EntityId,\n removedComponents: Map<EntityId<any>, any>,\n oldArchetype: Archetype,\n): void {\n if (removedComponents.size === 0) return;\n\n // Trigger multi-component hooks - only on_remove since entity is being deleted\n for (const entry of oldArchetype.matchingMultiHooks) {\n const { requiredComponents, componentTypes } = entry;\n\n // Skip if neither callback-style nor hook-style on_remove is provided\n if (!entry.callback && !entry.hook.on_remove) continue;\n\n // Check if any required component was removed\n const anyRequiredRemoved = requiredComponents.some((c) => anyComponentMatches(removedComponents, c));\n if (!anyRequiredRemoved) continue;\n\n // For entity deletion, we know:\n // 1. All components are being removed, so entity \"had\" all required components\n // 2. Entity will no longer match after deletion\n // Just need to verify the entity actually had all required components before\n const hadAllRequired = requiredComponents.every((c) => anyComponentMatches(removedComponents, c));\n if (!hadAllRequired) continue;\n\n // Collect component values from removedComponents directly (no entity lookup needed)\n const components = collectComponentsFromRemoved(componentTypes, removedComponents);\n invokeHook(entry, \"remove\", entityId, components);\n }\n}\n\nfunction triggerMultiComponentHooks(\n ctx: HooksContext,\n entityId: EntityId,\n addedComponents: Map<EntityId<any>, any>,\n removedComponents: Map<EntityId<any>, any>,\n oldArchetype: Archetype,\n newArchetype: Archetype,\n): void {\n // Handle on_set:\n // 1. Required/optional components changed while entity still matches\n // 2. Entity entered the matching set (e.g. removed a negative filter component)\n for (const entry of newArchetype.matchingMultiHooks) {\n const { requiredComponents, optionalComponents, componentTypes } = entry;\n\n // Skip if neither callback-style nor hook-style on_set is provided\n if (!entry.callback && !entry.hook.on_set) continue;\n\n const anyRequiredAdded = requiredComponents.some((c) => anyComponentMatches(addedComponents, c));\n const anyOptionalAdded = optionalComponents.some((c) => anyComponentMatches(addedComponents, c));\n const anyOptionalRemoved = optionalComponents.some((c) => anyComponentMatches(removedComponents, c));\n const enteredMatchingSet = !oldArchetype.matchingMultiHooks.has(entry);\n const hasRelevantComponentChange = anyRequiredAdded || anyOptionalAdded || anyOptionalRemoved;\n const shouldTriggerSet =\n enteredMatchingSet || (hasRelevantComponentChange && entityHasAllComponents(ctx, entityId, requiredComponents));\n\n if (shouldTriggerSet) {\n const components = collectMultiHookComponents(ctx, entityId, componentTypes);\n invokeHook(entry, \"set\", entityId, components);\n }\n }\n\n // Handle on_remove:\n // 1. Required component removal made the entity stop matching\n // 2. Entity exited the matching set (e.g. added a negative filter component)\n for (const entry of oldArchetype.matchingMultiHooks) {\n const { requiredComponents, componentTypes } = entry;\n\n // Skip if neither callback-style nor hook-style on_remove is provided\n if (!entry.callback && !entry.hook.on_remove) continue;\n\n const anyRequiredRemoved = requiredComponents.some((c) => anyComponentMatches(removedComponents, c));\n const lostRequiredMatch =\n anyRequiredRemoved &&\n entityHadAllComponentsBefore(ctx, entityId, requiredComponents, removedComponents) &&\n !entityHasAllComponents(ctx, entityId, requiredComponents);\n const exitedMatchingSet = !newArchetype.matchingMultiHooks.has(entry);\n const shouldTriggerRemove = lostRequiredMatch || exitedMatchingSet;\n\n if (shouldTriggerRemove) {\n const components = collectMultiHookComponentsWithRemoved(ctx, entityId, componentTypes, removedComponents);\n invokeHook(entry, \"remove\", entityId, components);\n }\n }\n}\n\nfunction entityHasAllComponents(ctx: HooksContext, entityId: EntityId, requiredComponents: EntityId<any>[]): boolean {\n return requiredComponents.every((c) => {\n // For wildcard relations, check if the entity has the wildcard relation data\n if (isWildcardRelationId(c)) {\n const wildcardResult = ctx.getOptional(entityId, c);\n if (!wildcardResult) return false;\n const wildcardData = wildcardResult.value;\n return Array.isArray(wildcardData) && wildcardData.length > 0;\n }\n return ctx.has(entityId, c);\n });\n}\n\nfunction entityHadAllComponentsBefore(\n ctx: HooksContext,\n entityId: EntityId,\n requiredComponents: EntityId<any>[],\n removedComponents: Map<EntityId<any>, any>,\n): boolean {\n return requiredComponents.every((c) => {\n // Check if a matching component was removed\n if (anyComponentMatches(removedComponents, c)) return true;\n\n // For wildcard relations, check if the entity still has matching relations\n if (isWildcardRelationId(c)) {\n const wildcardResult = ctx.getOptional(entityId, c);\n if (!wildcardResult) return false;\n const wildcardData = wildcardResult.value;\n return Array.isArray(wildcardData) && wildcardData.length > 0;\n }\n return ctx.has(entityId, c);\n });\n}\n\nexport function collectMultiHookComponents(\n ctx: HooksContext,\n entityId: EntityId,\n componentTypes: readonly ComponentType<any>[],\n): any[] {\n return componentTypes.map((ct) =>\n isOptionalEntityId(ct) ? ctx.getOptional(entityId, ct.optional) : ctx.get(entityId, ct as EntityId<any>),\n );\n}\n\n/**\n * Reconstructs wildcard relation data by merging current data with removed components.\n * Returns an array of [targetId, value] tuples for the wildcard relation.\n *\n * This is used during \"on_remove\" hook invocation: the removed components have already\n * been taken out of the entity's archetype, but the hook callback expects to see the\n * full data as it existed *before* removal. We reconstruct that snapshot by taking the\n * current wildcard data (post-removal) and adding back the entries that were just removed.\n */\nfunction reconstructWildcardWithRemoved(\n ctx: HooksContext,\n entityId: EntityId,\n wildcardId: EntityId<any>,\n removedComponents: Map<EntityId<any>, any>,\n): [EntityId, any][] {\n // ctx.get() for a wildcard relation ID always returns [EntityId, any][] at runtime\n // (see Archetype.getWildcardRelations / ComponentEntityStore.getWildcard).\n // The HooksContext interface erases the WildcardRelationId overload for simplicity,\n // so we assert the expected shape here rather than silently falling back to [].\n const currentData = ctx.get(entityId, wildcardId);\n if (!Array.isArray(currentData)) {\n throw new Error(\n `Expected wildcard relation data to be an array, but got ${typeof currentData} ` +\n `for entity ${entityId} and wildcard ${wildcardId}. ` +\n `This indicates a HooksContext implementation that does not conform to the expected contract.`,\n );\n }\n\n // Spread-copy the array so that pushing removed entries below does not mutate\n // the archetype's internal storage. Without the copy, we would leak removed\n // component data back into the live entity data.\n const result = [...currentData];\n\n // Re-inject matching relations that were just removed, so the hook callback\n // sees the complete snapshot as it existed before the removal.\n for (const [removedCompId, removedValue] of removedComponents.entries()) {\n // Skip wildcard markers themselves — they encode WILDCARD_TARGET_ID=0 and\n // would produce spurious [0, undefined] entries in the hook callback.\n if (isWildcardRelationId(removedCompId)) continue;\n if (componentMatchesHookType(removedCompId, wildcardId)) {\n const targetId = getTargetIdFromRelationId(removedCompId);\n if (targetId !== undefined) {\n result.push([targetId, removedValue]);\n }\n }\n }\n\n return result;\n}\n\nfunction collectMultiHookComponentsWithRemoved(\n ctx: HooksContext,\n entityId: EntityId,\n componentTypes: readonly ComponentType<any>[],\n removedComponents: Map<EntityId<any>, any>,\n): any[] {\n return componentTypes.map((ct) => {\n if (isOptionalEntityId(ct)) {\n const optionalId = ct.optional;\n\n if (isWildcardRelationId(optionalId)) {\n const result = reconstructWildcardWithRemoved(ctx, entityId, optionalId, removedComponents);\n return result.length > 0 ? { value: result } : undefined;\n }\n\n const match = findMatchingComponent(removedComponents, optionalId);\n return match ? { value: match[1] } : ctx.getOptional(entityId, optionalId);\n }\n\n const compId = ct as EntityId<any>;\n\n if (isWildcardRelationId(compId)) {\n return reconstructWildcardWithRemoved(ctx, entityId, compId, removedComponents);\n }\n\n const match = findMatchingComponent(removedComponents, compId);\n return match ? match[1] : ctx.get(entityId, compId);\n });\n}\n\n/**\n * Collect component values directly from removedComponents map.\n * Used for entity deletion fast path where the entity no longer exists.\n */\nfunction collectComponentsFromRemoved(\n componentTypes: readonly ComponentType<any>[],\n removedComponents: Map<EntityId<any>, any>,\n): any[] {\n return componentTypes.map((ct) => {\n if (isOptionalEntityId(ct)) {\n const optionalId = ct.optional;\n\n if (isWildcardRelationId(optionalId)) {\n const result = collectWildcardFromRemoved(optionalId, removedComponents);\n return result.length > 0 ? { value: result } : undefined;\n }\n\n const match = findMatchingComponent(removedComponents, optionalId);\n return match ? { value: match[1] } : undefined;\n }\n\n const compId = ct as EntityId<any>;\n\n if (isWildcardRelationId(compId)) {\n return collectWildcardFromRemoved(compId, removedComponents);\n }\n\n const match = findMatchingComponent(removedComponents, compId);\n return match ? match[1] : undefined;\n });\n}\n\n/**\n * Collect all matching wildcard relation data from removed components.\n */\nfunction collectWildcardFromRemoved(\n wildcardId: EntityId<any>,\n removedComponents: Map<EntityId<any>, any>,\n): [EntityId, any][] {\n const result: [EntityId, any][] = [];\n\n for (const [removedCompId, removedValue] of removedComponents.entries()) {\n // Skip wildcard markers themselves — they encode WILDCARD_TARGET_ID=0.\n if (isWildcardRelationId(removedCompId)) continue;\n if (componentMatchesHookType(removedCompId, wildcardId)) {\n const targetId = getTargetIdFromRelationId(removedCompId);\n if (targetId !== undefined) {\n result.push([targetId, removedValue]);\n }\n }\n }\n\n return result;\n}\n","// A lightweight generic MultiMap implementation backed by Map<K, Set<V>>.\n// Provides usual operations: add, remove, get, has, keys, values, entries,\n// clear, deleteKey and size accessors.\n\nconst _MISSING = Symbol(\"missing\");\n\nclass MultiMap<K, V> {\n private map: Map<K, Set<V>> = new Map();\n\n // Number of value entries across all keys (not number of keys).\n private _valueCount = 0;\n\n get valueCount(): number {\n return this._valueCount;\n }\n\n get keyCount(): number {\n return this.map.size;\n }\n\n hasKey(key: K): boolean {\n return this.map.has(key);\n }\n\n has(key: K, value: V | typeof _MISSING = _MISSING): boolean {\n const set = this.map.get(key);\n if (!set) return false;\n if (value === _MISSING) return true;\n return set.has(value);\n }\n\n add(key: K, value: V): void {\n let set = this.map.get(key);\n if (!set) {\n set = new Set();\n this.map.set(key, set);\n }\n if (!set.has(value)) {\n set.add(value);\n this._valueCount++;\n }\n }\n\n // Remove a specific value for a key. Returns true if removed.\n remove(key: K, value: V): boolean {\n const set = this.map.get(key);\n if (!set) return false;\n if (!set.has(value)) return false;\n set.delete(value);\n this._valueCount--;\n if (set.size === 0) this.map.delete(key);\n return true;\n }\n\n // Delete entire key and all its values. Returns true if key existed.\n deleteKey(key: K): boolean {\n const set = this.map.get(key);\n if (!set) return false;\n this._valueCount -= set.size;\n this.map.delete(key);\n return true;\n }\n\n get(key: K): Set<V> {\n const set = this.map.get(key);\n return set ? new Set(set) : new Set();\n }\n\n // iterate keys, values and entries (key -> Set copy)\n *keys(): IterableIterator<K> {\n yield* this.map.keys();\n }\n\n *values(): IterableIterator<V> {\n for (const set of this.map.values()) {\n for (const v of set) yield v;\n }\n }\n\n [Symbol.iterator](): IterableIterator<[K, V]> {\n return this.entries();\n }\n\n *entries(): IterableIterator<[K, V]> {\n for (const [k, set] of this.map.entries()) {\n for (const v of set) yield [k, v];\n }\n }\n\n clear(): void {\n this.map.clear();\n this._valueCount = 0;\n }\n}\n\nexport { MultiMap };\n","import type { EntityId } from \"../entity\";\nimport { MultiMap } from \"../utils/multi-map\";\n\n/**\n * Reverse reference index: maps each target entity to the set of (source entity, component) pairs\n * that currently hold a reference to it.\n *\n * Used internally to support efficient entity deletion, including:\n * - Fast-path deletion for unreferenced entities\n * - Cascading deletes for relations marked with `cascadeDelete`\n * - Automatic cleanup of entity-valued components and entity-relations when their target is destroyed\n *\n * Structure:\n * targetEntityId -> MultiMap<sourceEntityId, componentOrRelationId>\n *\n * - For plain entity-valued components (component value is an EntityId):\n * componentOrRelationId === the component type (which is also the entity id being pointed to)\n * - For entity-relations (`relation(Comp, target)`):\n * componentOrRelationId is the encoded (negative) relation ID\n *\n * This index is maintained in sync with structural changes via `updateEntityReferences` in World.\n *\n * @internal\n */\nexport type EntityReferencesMap = Map<EntityId, MultiMap<EntityId, EntityId>>;\n\n/**\n * Record that `sourceEntityId` holds a reference to `targetEntityId` via the given component/relation.\n *\n * Called when an entity-valued component or an entity-relation is added to an entity.\n *\n * @param entityReferences - The shared reverse index map\n * @param sourceEntityId - The entity that contains the reference\n * @param componentType - The component type or encoded relation ID used for the reference\n * @param targetEntityId - The entity being referenced\n *\n * @internal\n */\nexport function trackEntityReference(\n entityReferences: EntityReferencesMap,\n sourceEntityId: EntityId,\n componentType: EntityId,\n targetEntityId: EntityId,\n): void {\n if (!entityReferences.has(targetEntityId)) {\n entityReferences.set(targetEntityId, new MultiMap());\n }\n entityReferences.get(targetEntityId)!.add(sourceEntityId, componentType);\n}\n\n/**\n * Remove the record that `sourceEntityId` references `targetEntityId` via the given component/relation.\n *\n * Called when an entity-valued component or entity-relation is removed (or during deletion).\n * Automatically prunes empty target entries from the map.\n *\n * @param entityReferences - The shared reverse index map\n * @param sourceEntityId - The entity that no longer holds the reference\n * @param componentType - The component type or encoded relation ID that was used\n * @param targetEntityId - The previously referenced entity\n *\n * @internal\n */\nexport function untrackEntityReference(\n entityReferences: EntityReferencesMap,\n sourceEntityId: EntityId,\n componentType: EntityId,\n targetEntityId: EntityId,\n): void {\n const references = entityReferences.get(targetEntityId);\n if (references) {\n references.remove(sourceEntityId, componentType);\n if (references.keyCount === 0) {\n entityReferences.delete(targetEntityId);\n }\n }\n}\n\n/**\n * Iterate over all (sourceEntityId, componentOrRelationId) pairs that currently reference the given target.\n *\n * Returns an empty iterable when the target has no incoming references.\n * The returned iterable yields `[source, componentType]` pairs suitable for cleanup decisions\n * (e.g. whether to cascade-delete the source or just remove the specific component/relation).\n *\n * @param entityReferences - The shared reverse index map\n * @param targetEntityId - The entity whose referrers we want to inspect\n * @returns Iterable of [sourceEntityId, componentOrRelationId]\n *\n * @internal\n */\nexport function getEntityReferences(\n entityReferences: EntityReferencesMap,\n targetEntityId: EntityId,\n): Iterable<[EntityId, EntityId]> {\n return entityReferences.get(targetEntityId) ?? new MultiMap();\n}\n","import type { Archetype } from \"../archetype/archetype\";\nimport type { SparseStore } from \"../archetype/store\";\nimport type { Command } from \"../commands/buffer\";\nimport { ComponentChangeset } from \"../commands/changeset\";\nimport type { ComponentEntityStore } from \"../component/entity-store\";\nimport {\n getComponentIdFromRelationId,\n getTargetIdFromRelationId,\n isEntityRelation,\n isExclusiveComponent,\n type EntityId,\n} from \"../entity\";\nimport type { LifecycleHookEntry } from \"../types\";\nimport {\n applyChangeset,\n maybeRemoveWildcardMarker,\n processCommands,\n removeMatchingRelations,\n type CommandProcessorContext,\n} from \"./commands\";\nimport type { triggerLifecycleHooks } from \"./hooks\";\nimport { type HooksContext } from \"./hooks\";\nimport { trackEntityReference, untrackEntityReference, type EntityReferencesMap } from \"./references\";\n\n/**\n * Dependencies provided by World to the CommandExecutor.\n * Keeps the executor decoupled while allowing efficient hot-path access\n * (maps passed by reference where hot code already expects them).\n */\nexport interface CommandExecutorContext {\n /** For component-entity (singleton) fast path in execute */\n componentEntities: ComponentEntityStore;\n\n /** Reverse reference index for cascades and entity-valued components */\n entityReferences: EntityReferencesMap;\n\n /** For the no-hooks fast path guard */\n hooks: Set<LifecycleHookEntry>;\n\n /** Direct map access (hot path in applyChangeset and various places) */\n entityToArchetype: Map<EntityId, Archetype>;\n\n /** Archetype creation/lookup (passed through CommandProcessorContext) */\n ensureArchetype: (componentTypes: Iterable<EntityId<any>>) => Archetype;\n\n /** Sparse store (needed for CommandProcessorContext) */\n sparseStore: SparseStore;\n\n /** Factories for the HooksContext (used by triggerLifecycleHooks) */\n has: (entityId: EntityId, componentType: EntityId<any>) => boolean;\n get: <T>(entityId: EntityId, componentType: EntityId<T>) => T;\n getOptional: <T>(entityId: EntityId, componentType: EntityId<T>) => { value: T } | undefined;\n\n /** Destroy fast-path delegation (BFS + cascade logic stays in World) */\n destroyEntityImmediate: (entityId: EntityId) => void;\n\n /** Debug migration counter (now routed through DebugStatsManager) */\n incrementMigrations: () => void;\n\n /** Hook triggering (the function from hooks.ts) */\n triggerLifecycleHooks: typeof triggerLifecycleHooks;\n\n /** Remove hook fast path for full entity deletion (used by destroy paths in World) */\n triggerRemoveHooksForEntityDeletion: (\n entityId: EntityId,\n removedComponents: Map<EntityId<any>, any>,\n oldArchetype: Archetype,\n ) => void;\n}\n\n/**\n * Encapsulates the command execution pipeline, reusable changesets,\n * and related orchestration that was previously private methods + fields on World.\n *\n * Responsibilities:\n * - executeEntityCommands (routing for singletons / destroy / structural changes)\n * - applyEntityCommands (changeset processing + exclusive relations + apply + refs + hooks)\n * - removeComponentImmediate (used by cascade deletion)\n * - updateEntityReferences (keeps the reverse index in sync)\n *\n * This extraction significantly reduces World line count while preserving\n * every fast-path branch and allocation-avoidance characteristic.\n */\nexport class CommandExecutor {\n private readonly _changeset = new ComponentChangeset();\n private readonly _removeChangeset = new ComponentChangeset();\n\n private readonly _commandCtx: CommandProcessorContext;\n private readonly _hooksCtx: HooksContext;\n\n constructor(private readonly ctx: CommandExecutorContext) {\n this._commandCtx = {\n sparseStore: ctx.sparseStore,\n ensureArchetype: ctx.ensureArchetype,\n };\n\n this._hooksCtx = {\n multiHooks: ctx.hooks,\n has: ctx.has,\n get: ctx.get,\n getOptional: ctx.getOptional,\n };\n }\n\n /**\n * Entry point used by the CommandBuffer.\n * Routes to singleton handling, destroy fast path, or structural apply.\n */\n executeEntityCommands(entityId: EntityId, commands: Command[]): void {\n this._changeset.clear();\n\n // 1. Route: component entities use flat-map storage\n if (this.ctx.componentEntities.exists(entityId)) {\n this.ctx.componentEntities.executeCommands(entityId, commands);\n return;\n }\n\n // 2. Route: destroy uses fast path (BFS/cascade stays in World)\n if (commands.some((cmd) => cmd.type === \"destroy\")) {\n this.ctx.destroyEntityImmediate(entityId);\n return;\n }\n\n // 3. Apply structural changes\n this.applyEntityCommands(entityId, commands);\n }\n\n private applyEntityCommands(entityId: EntityId, commands: Command[]): void {\n const currentArchetype = this.ctx.entityToArchetype.get(entityId);\n if (!currentArchetype) return;\n\n const changeset = this._changeset;\n processCommands(entityId, currentArchetype, commands, changeset, (eid, arch, compId) => {\n if (isExclusiveComponent(compId)) {\n removeMatchingRelations(eid, arch, compId, changeset);\n }\n });\n\n const hasStructuralChange = changeset.removes.size > 0 || changeset.adds.size > 0;\n\n if (this.ctx.hooks.size === 0) {\n // Fast path: no hooks, skip removedComponents map allocation and hook triggering\n const newArchetype = applyChangeset(\n this._commandCtx,\n entityId,\n currentArchetype,\n changeset,\n this.ctx.entityToArchetype,\n null,\n );\n if (hasStructuralChange) {\n this.updateEntityReferences(entityId, changeset);\n }\n if (newArchetype !== currentArchetype) {\n this.ctx.incrementMigrations();\n }\n return;\n }\n\n const removedComponents = new Map<EntityId<any>, any>();\n const newArchetype = applyChangeset(\n this._commandCtx,\n entityId,\n currentArchetype,\n changeset,\n this.ctx.entityToArchetype,\n removedComponents,\n );\n\n if (hasStructuralChange) {\n this.updateEntityReferences(entityId, changeset);\n }\n\n if (newArchetype !== currentArchetype) {\n this.ctx.incrementMigrations();\n }\n\n this.ctx.triggerLifecycleHooks(\n this._hooksCtx,\n entityId,\n changeset.adds,\n removedComponents,\n currentArchetype,\n newArchetype,\n );\n }\n\n /**\n * Immediate (non-buffered) component removal used during cascade deletion.\n * Called from destroy* paths (which remain in World).\n */\n removeComponentImmediate(entityId: EntityId, componentType: EntityId<any>, targetEntityId: EntityId): void {\n const sourceArchetype = this.ctx.entityToArchetype.get(entityId);\n if (!sourceArchetype) return;\n\n const changeset = this._removeChangeset;\n changeset.clear();\n changeset.delete(componentType);\n maybeRemoveWildcardMarker(\n entityId,\n sourceArchetype,\n componentType,\n getComponentIdFromRelationId(componentType),\n changeset,\n );\n\n const removedComponent = sourceArchetype.get(entityId, componentType);\n const newArchetype = applyChangeset(\n this._commandCtx,\n entityId,\n sourceArchetype,\n changeset,\n this.ctx.entityToArchetype,\n null,\n );\n untrackEntityReference(this.ctx.entityReferences, entityId, componentType, targetEntityId);\n\n this.ctx.triggerLifecycleHooks(\n this._hooksCtx,\n entityId,\n new Map(),\n new Map([[componentType, removedComponent]]),\n sourceArchetype,\n newArchetype,\n );\n }\n\n /**\n * Keeps the entity reference reverse index in sync after structural changes.\n * Called from apply paths.\n */\n updateEntityReferences(entityId: EntityId, changeset: ComponentChangeset): void {\n for (const componentType of changeset.removes) {\n if (isEntityRelation(componentType)) {\n const targetId = getTargetIdFromRelationId(componentType)!;\n untrackEntityReference(this.ctx.entityReferences, entityId, componentType, targetId);\n } else if (componentType >= 1024) {\n untrackEntityReference(this.ctx.entityReferences, entityId, componentType, componentType);\n }\n }\n\n for (const [componentType] of changeset.adds) {\n if (isEntityRelation(componentType)) {\n const targetId = getTargetIdFromRelationId(componentType)!;\n trackEntityReference(this.ctx.entityReferences, entityId, componentType, targetId);\n } else if (componentType >= 1024) {\n trackEntityReference(this.ctx.entityReferences, entityId, componentType, componentType);\n }\n }\n }\n\n /**\n * Exposed for any future direct needs (currently not required outside the executor).\n */\n getHooksContext(): HooksContext {\n return this._hooksCtx;\n }\n}\n","import type { DebugStatsCollector, SyncDebugStats } from \"../types\";\nimport { debugHookExecutionCounter } from \"./hooks\";\n\n/**\n * Manages debug stats collectors and transient activity counters for World#sync().\n *\n * Extracted from World to shrink the main class while keeping the entire debug/observability\n * path isolated, zero-cost when no collectors are active, and easy to test/maintain.\n *\n * Follows the same context/callback injection style as ArchetypeManager, CommandProcessorContext,\n * and HooksContext to avoid tight coupling.\n *\n * All collectors receive the *exact same* stats object for a given sync (as before).\n * Exceptions in user callbacks are swallowed (as before).\n */\nexport class DebugStatsManager {\n private readonly collectors = new Set<(stats: SyncDebugStats) => void>();\n\n // Transient activity counters for the current armed sync (reset each time collectors are present)\n private migrations = 0;\n private archetypesCreated = 0;\n private archetypesRemoved = 0;\n\n /** Fast check used to arm timing + reset + counting in hot paths. */\n hasActiveCollectors(): boolean {\n return this.collectors.size > 0;\n }\n\n /**\n * Registers a collector. Returns a disposable handle (supports `using`).\n * Collection stops when the handle is disposed.\n */\n createCollector(callback: (stats: SyncDebugStats) => void): DebugStatsCollector {\n this.collectors.add(callback);\n\n return {\n [Symbol.dispose]: () => {\n this.collectors.delete(callback);\n },\n };\n }\n\n // ------------------------------------------------------------------\n // Recording hooks (called from ArchetypeManager ctx and command apply paths)\n // These are cheap no-ops when no collectors are active.\n // ------------------------------------------------------------------\n\n recordArchetypeCreated(): void {\n if (this.hasActiveCollectors()) {\n this.archetypesCreated++;\n }\n }\n\n recordArchetypeRemoved(): void {\n if (this.hasActiveCollectors()) {\n this.archetypesRemoved++;\n }\n }\n\n incrementMigrations(): void {\n if (this.hasActiveCollectors()) {\n this.migrations++;\n }\n }\n\n /** Reset all activity counters + the shared hook execution counter. Called at start of an armed sync. */\n resetActivity(): void {\n this.migrations = 0;\n this.archetypesCreated = 0;\n this.archetypesRemoved = 0;\n debugHookExecutionCounter.value = 0;\n }\n\n /**\n * Build and deliver a SyncDebugStats payload to every active collector.\n * World supplies the pre-computed snapshot numbers (keeps debug manager decoupled from\n * internal World maps/registries while preserving exact original stats shape and values).\n */\n deliver(\n timings: {\n syncStart: number;\n syncEnd: number;\n commandBufferStart: number;\n commandBufferEnd: number;\n commandIterations: number;\n },\n data: {\n entityCount: number;\n freelistSize: number;\n nextId: number;\n archetypeCount: number;\n emptyArchetypes: number;\n archetypesByComponentSize: number;\n cachedQueryCount: number;\n registeredQueryCount: number;\n hookCount: number;\n entityReferencesSize: number;\n entityToReferencingArchetypesSize: number;\n },\n ): void {\n const stats: SyncDebugStats = {\n timestamps: {\n syncStart: timings.syncStart,\n syncEnd: timings.syncEnd,\n commandBufferStart: timings.commandBufferStart,\n commandBufferEnd: timings.commandBufferEnd,\n },\n commandIterations: timings.commandIterations,\n\n entities: {\n total: data.entityCount,\n freelistSize: data.freelistSize,\n nextId: data.nextId,\n },\n archetypes: {\n total: data.archetypeCount,\n empty: data.emptyArchetypes,\n },\n queries: {\n cached: data.cachedQueryCount,\n registered: data.registeredQueryCount,\n },\n hooks: {\n total: data.hookCount,\n },\n indices: {\n entityReferences: data.entityReferencesSize,\n entityToReferencingArchetypes: data.entityToReferencingArchetypesSize,\n archetypesByComponent: data.archetypesByComponentSize,\n },\n activity: {\n migrations: this.migrations,\n hooksExecuted: debugHookExecutionCounter.value,\n archetypesCreated: this.archetypesCreated,\n archetypesRemoved: this.archetypesRemoved,\n },\n };\n\n for (const cb of this.collectors) {\n try {\n cb(stats);\n } catch {\n // Intentionally ignore user callback errors (preserves original behavior)\n }\n }\n }\n}\n","import type { ComponentId, EntityId } from \"../entity\";\nimport { getDetailedIdType } from \"../entity\";\n\n/**\n * Validation and overload-resolution helpers extracted from World.\n *\n * These were previously private methods on World. Moving them reduces line count\n * in the core class with almost zero coupling (the only dep is a liveness predicate\n * for assertEntityExists, supplied by the caller).\n *\n * Pure type checks (assert*TypeValid) and the resolve* helpers for set/remove\n * overloads live here.\n */\n\n/**\n * Assert that an entity (or component-entity) is alive in the world.\n * The caller supplies the liveness check (World.exists or equivalent) to keep\n * this module free of direct references to stores.\n */\nexport function assertEntityExists(\n entityId: EntityId,\n label: \"Entity\" | \"Component entity\",\n exists: (id: EntityId) => boolean,\n): void {\n if (!exists(entityId)) {\n throw new Error(`${label} ${entityId} does not exist`);\n }\n}\n\nexport function assertComponentTypeValid(componentType: EntityId): void {\n const detailedType = getDetailedIdType(componentType);\n if (detailedType.type === \"invalid\") {\n throw new Error(`Invalid component type: ${componentType}`);\n }\n}\n\nexport function assertSetComponentTypeValid(componentType: EntityId): void {\n const detailedType = getDetailedIdType(componentType);\n if (detailedType.type === \"invalid\") {\n throw new Error(`Invalid component type: ${componentType}`);\n }\n if (detailedType.type === \"wildcard-relation\") {\n throw new Error(`Cannot directly add wildcard relation components: ${componentType}`);\n }\n}\n\n/**\n * Resolve the (entity, componentType, value) for a set() call.\n */\nexport function resolveSetOperation(\n entityId: EntityId | ComponentId,\n componentTypeOrComponent?: EntityId | any,\n maybeComponent?: any,\n exists: (id: EntityId) => boolean = () => true, // default permissive for tests / internal\n): { entityId: EntityId; componentType: EntityId; component: any } {\n const targetEntityId = entityId as EntityId;\n const componentType = componentTypeOrComponent as EntityId;\n assertEntityExists(targetEntityId, \"Entity\", exists);\n assertSetComponentTypeValid(componentType);\n\n return { entityId: targetEntityId, componentType, component: maybeComponent };\n}\n\n/**\n * Resolve the (entity, componentType) for a remove() call, handling the\n * singleton component overload (remove(componentId)).\n */\nexport function resolveRemoveOperation<T>(\n entityId: EntityId | ComponentId,\n componentType?: EntityId<T>,\n exists: (id: EntityId) => boolean = () => true,\n): { entityId: EntityId; componentType: EntityId } {\n // Handle singleton component overload: remove(componentId)\n if (componentType === undefined) {\n const componentId = entityId as ComponentId<T>;\n assertEntityExists(componentId, \"Component entity\", exists);\n return { entityId: componentId, componentType: componentId };\n }\n\n const targetEntityId = entityId as EntityId;\n assertEntityExists(targetEntityId, \"Entity\", exists);\n assertComponentTypeValid(componentType);\n\n return { entityId: targetEntityId, componentType };\n}\n\n// Re-export the type for callers that need it in signatures (ComponentId lives in entity)\nexport type { ComponentId } from \"../entity\";\n","import type { ComponentId, EntityId } from \"../entity\";\nimport { getComponentIdByName, getComponentNameById, getDetailedIdType, relation } from \"../entity\";\n\n// -----------------------------------------------------------------------------\n// Serialization helpers for IDs\n// -----------------------------------------------------------------------------\n\nexport type SerializedEntityId = number | string | { component: string; target: number | string | \"*\" };\n\n/**\n * Serialized state of EntityIdManager\n */\nexport interface SerializedEntityIdManager {\n nextId: number;\n freelist?: number[];\n}\n\nexport type SerializedWorld = {\n version: number;\n entityManager: SerializedEntityIdManager;\n entities: SerializedEntity[];\n componentEntities?: SerializedEntity[];\n};\n\nexport type SerializedEntity = {\n id: SerializedEntityId;\n components: SerializedComponent[];\n};\n\nexport type SerializedComponent = {\n type: SerializedEntityId;\n value: any;\n};\n\n/**\n * Core encoding logic (no cache). Extracted so cached wrapper can reuse it without duplication.\n */\nfunction encodeEntityIdCore(id: EntityId<any>): SerializedEntityId {\n const detailed = getDetailedIdType(id);\n switch (detailed.type) {\n case \"component\": {\n const name = getComponentNameById(id as ComponentId);\n if (!name) {\n // Warn if component doesn't have a name; keep numeric fallback\n console.warn(`Component ID ${id} has no registered name, serializing as number`);\n }\n return name || (id as number);\n }\n case \"entity-relation\": {\n const componentName = getComponentNameById(detailed.componentId);\n if (!componentName) {\n console.warn(`Component ID ${detailed.componentId} in relation has no registered name`);\n }\n // Safe: targetId is guaranteed to exist for entity-relation type\n return { component: componentName || (detailed.componentId as number).toString(), target: detailed.targetId };\n }\n case \"component-relation\": {\n const componentName = getComponentNameById(detailed.componentId);\n // Safe: targetId is guaranteed to exist for component-relation type\n const targetName = getComponentNameById(detailed.targetId as ComponentId);\n if (!componentName) {\n console.warn(`Component ID ${detailed.componentId} in relation has no registered name`);\n }\n if (!targetName) {\n console.warn(`Target component ID ${detailed.targetId} in relation has no registered name`);\n }\n return {\n component: componentName || (detailed.componentId as number).toString(),\n target: targetName || (detailed.targetId as number),\n };\n }\n case \"wildcard-relation\": {\n const componentName = getComponentNameById(detailed.componentId);\n if (!componentName) {\n console.warn(`Component ID ${detailed.componentId} in relation has no registered name`);\n }\n return { component: componentName || (detailed.componentId as number).toString(), target: \"*\" };\n }\n default:\n return id as number;\n }\n}\n\n/**\n * Encode an internal EntityId into a SerializedEntityId for snapshots.\n * Use encodeEntityIdCached when serializing many entities to benefit from memoization\n * of repeated component/relation type IDs.\n */\nexport function encodeEntityId(id: EntityId<any>): SerializedEntityId {\n return encodeEntityIdCore(id);\n}\n\n/**\n * Encode an EntityId, using an optional cache Map to avoid repeated getDetailedIdType\n * + name lookup work for IDs that appear many times (typical during full world snapshot).\n */\nexport function encodeEntityIdCached(\n id: EntityId<any>,\n cache?: Map<EntityId<any>, SerializedEntityId>,\n): SerializedEntityId {\n if (cache) {\n const cached = cache.get(id);\n if (cached !== undefined) return cached;\n const result = encodeEntityIdCore(id);\n cache.set(id, result);\n return result;\n }\n return encodeEntityIdCore(id);\n}\n\n/**\n * Decode a SerializedEntityId back into an internal EntityId\n */\nexport function decodeSerializedId(sid: SerializedEntityId): EntityId<any> {\n if (typeof sid === \"number\") {\n return sid as EntityId<any>;\n }\n if (typeof sid === \"string\") {\n const id = getComponentIdByName(sid);\n if (id === undefined) {\n const num = parseInt(sid, 10);\n if (!isNaN(num)) return num as EntityId<any>;\n throw new Error(`Unknown component name in snapshot: ${sid}`);\n }\n return id;\n }\n if (typeof sid === \"object\" && sid !== null && typeof sid.component === \"string\") {\n let compId = getComponentIdByName(sid.component);\n if (compId === undefined) {\n const num = parseInt(sid.component, 10);\n if (!isNaN(num)) compId = num as ComponentId;\n }\n if (compId === undefined) {\n throw new Error(`Unknown component name in snapshot: ${sid.component}`);\n }\n\n if (sid.target === \"*\") {\n return relation(compId, \"*\");\n }\n\n let targetId: EntityId<any>;\n if (typeof sid.target === \"string\") {\n const tid = getComponentIdByName(sid.target);\n if (tid === undefined) {\n const num = parseInt(sid.target, 10);\n if (!isNaN(num)) targetId = num as EntityId<any>;\n else throw new Error(`Unknown target component name in snapshot: ${sid.target}`);\n } else {\n targetId = tid;\n }\n } else {\n targetId = sid.target as EntityId<any>;\n }\n return relation(compId, targetId as any);\n }\n throw new Error(`Invalid ID in snapshot: ${JSON.stringify(sid)}`);\n}\n","import { MISSING_COMPONENT, type Archetype } from \"../archetype/archetype\";\nimport type { ComponentEntityStore } from \"../component/entity-store\";\nimport { getDetailedIdType, type EntityId, type EntityIdManager } from \"../entity\";\nimport {\n decodeSerializedId,\n encodeEntityIdCached,\n type SerializedComponent,\n type SerializedEntity,\n type SerializedWorld,\n} from \"../storage/serialization\";\nimport { trackEntityReference, type EntityReferencesMap } from \"./references\";\n\n/**\n * Serializes the full world state to a plain JS object suitable for JSON encoding.\n */\nexport function serializeWorld(\n archetypes: Archetype[],\n componentEntities: ComponentEntityStore,\n entityIdManager: EntityIdManager,\n): SerializedWorld {\n // ID cache turns repeated encode work (especially component type IDs) into O(#unique IDs)\n const idCache = new Map<any, any>();\n\n const entities: SerializedEntity[] = [];\n\n for (const archetype of archetypes) {\n // Pre-encode this archetype's component type IDs exactly once (big win when many entities share the archetype)\n const encodedComponentTypes = archetype.componentTypes.map((t) => encodeEntityIdCached(t, idCache));\n\n // The append method will use the bulk helper internally when a pre-fetched map is supplied.\n // For now we rely on the per-entity fallback inside the archetype (already much cheaper than old dump path).\n archetype.appendSerializedEntities(entities, (id) => encodeEntityIdCached(id, idCache), encodedComponentTypes);\n }\n\n const componentEntitiesArr: SerializedEntity[] = [];\n for (const [entityId, components] of componentEntities.entries()) {\n componentEntitiesArr.push({\n id: encodeEntityIdCached(entityId, idCache),\n components: serializeComponentsFromMap(components, idCache),\n });\n }\n\n return {\n version: 1,\n entityManager: entityIdManager.serializeState(),\n entities,\n componentEntities: componentEntitiesArr,\n };\n}\n\n/** Small helper to avoid duplicating the \"Map → SerializedComponent[] with cache\" pattern. */\nfunction serializeComponentsFromMap(\n components: Map<EntityId<any>, any>,\n idCache: Map<any, any>,\n): SerializedComponent[] {\n const result: SerializedComponent[] = [];\n for (const [rawType, value] of components) {\n result.push({\n type: encodeEntityIdCached(rawType, idCache),\n value: value === MISSING_COMPONENT ? undefined : value,\n });\n }\n return result;\n}\n\n/**\n * Context needed by `deserializeWorld` to populate world-internal state.\n * Defined as an interface to avoid a circular import between world.ts and this module.\n */\nexport interface WorldDeserializationContext {\n entityIdManager: EntityIdManager;\n componentEntities: ComponentEntityStore;\n entityReferences: EntityReferencesMap;\n ensureArchetype(componentTypes: EntityId<any>[]): Archetype;\n setEntityToArchetype(entityId: EntityId, archetype: Archetype): void;\n}\n\n/**\n * Restores world state from a snapshot into the provided context.\n * Intended to be called from `World`'s constructor.\n */\nexport function deserializeWorld(ctx: WorldDeserializationContext, snapshot: SerializedWorld): void {\n if (snapshot.entityManager) {\n ctx.entityIdManager.deserializeState(snapshot.entityManager);\n }\n\n if (Array.isArray(snapshot.componentEntities)) {\n for (const entry of snapshot.componentEntities) {\n const entityId = decodeSerializedId(entry.id);\n if (!ctx.componentEntities.exists(entityId)) continue;\n\n const componentsArray: SerializedComponent[] = entry.components || [];\n const componentMap = new Map<EntityId<any>, any>();\n\n for (const componentEntry of componentsArray) {\n const componentType = decodeSerializedId(componentEntry.type);\n componentMap.set(componentType, componentEntry.value);\n }\n\n ctx.componentEntities.initFromSnapshot(entityId, componentMap);\n }\n }\n\n if (Array.isArray(snapshot.entities)) {\n for (const entry of snapshot.entities) {\n const entityId = decodeSerializedId(entry.id);\n const componentsArray: SerializedComponent[] = entry.components || [];\n\n const componentMap = new Map<EntityId<any>, any>();\n\n for (const componentEntry of componentsArray) {\n const componentType = decodeSerializedId(componentEntry.type);\n componentMap.set(componentType, componentEntry.value);\n }\n\n // Build the list of component types from the map we just populated (no redundant push loop)\n const componentTypes = Array.from(componentMap.keys());\n\n // ensureArchetype is internally memoized (getOrCompute on signature), so repeated calls\n // for the same component set are cheap after the first archetype is created.\n const archetype = ctx.ensureArchetype(componentTypes);\n archetype.addEntity(entityId, componentMap);\n ctx.setEntityToArchetype(entityId, archetype);\n\n for (const compType of componentTypes) {\n const detailedType = getDetailedIdType(compType);\n if (detailedType.type === \"entity-relation\") {\n // Safe: targetId guaranteed for entity-relation type\n trackEntityReference(ctx.entityReferences, entityId, compType, detailedType.targetId);\n } else if (detailedType.type === \"entity\") {\n trackEntityReference(ctx.entityReferences, entityId, compType, compType);\n }\n }\n }\n }\n}\n","import type { Archetype } from \"../archetype/archetype\";\nimport { SparseStoreImpl } from \"../archetype/store\";\nimport { CommandBuffer } from \"../commands/buffer\";\nimport { ComponentEntityStore } from \"../component/entity-store\";\nimport { normalizeComponentTypes } from \"../component/type-utils\";\nimport type { ComponentId, EntityId, WildcardRelationId } from \"../entity\";\nimport {\n EntityIdManager,\n RELATION_SHIFT,\n getComponentIdFromRelationId,\n isCascadeDeleteRelation,\n isSparseRelation,\n isWildcardRelationId,\n relation,\n} from \"../entity\";\nimport { serializeQueryFilter, type QueryFilter } from \"../query/filter\";\nimport type { Query } from \"../query/query\";\nimport { QueryRegistry } from \"../query/registry\";\nimport type { SerializedWorld } from \"../storage/serialization\";\nimport type {\n ComponentTuple,\n ComponentType,\n DebugStatsCollector,\n LifecycleCallback,\n LifecycleHook,\n LifecycleHookEntry,\n SyncDebugStats,\n} from \"../types\";\nimport { isOptionalEntityId } from \"../types\";\nimport { ArchetypeManager } from \"./archetype-manager\";\nimport { EntityBuilder } from \"./builder\";\nimport { CommandExecutor, type CommandExecutorContext } from \"./command-executor\";\nimport { DebugStatsManager } from \"./debug-stats\";\nimport {\n collectMultiHookComponents,\n triggerLifecycleHooks,\n triggerRemoveHooksForEntityDeletion,\n type HooksContext,\n} from \"./hooks\";\nimport {\n assertEntityExists,\n assertSetComponentTypeValid,\n resolveRemoveOperation,\n resolveSetOperation,\n} from \"./operations\";\nimport { getEntityReferences, type EntityReferencesMap } from \"./references\";\nimport { deserializeWorld, serializeWorld } from \"./serialization\";\nimport { SingletonHandle } from \"./singleton\";\n\n/**\n * World class for ECS architecture\n * Manages entities and components\n */\nexport class World {\n // Core data structures for entity and archetype management\n private entityIdManager = new EntityIdManager();\n private entityReferences: EntityReferencesMap = new Map();\n /** Sparse relation storage (for components created with `sparse: true`), shared with all Archetype instances */\n private readonly sparseStore = new SparseStoreImpl();\n /** Component entity (singleton) storage */\n private readonly componentEntities = new ComponentEntityStore();\n\n // Archetype storage, indexes, creation/removal, and referencing are now encapsulated\n // in ArchetypeManager (extracted to reduce World line count and improve cohesion).\n private archetypeManager!: ArchetypeManager;\n\n // Temporary forwarding accessors so the rest of World (and its internal collaborators)\n // can continue using the familiar names with almost zero call-site changes.\n // These can be removed in a follow-up cleanup pass if desired.\n private get archetypes() {\n return this.archetypeManager.archetypes;\n }\n private get entityToArchetype() {\n return this.archetypeManager.entityToArchetype;\n }\n private get archetypesByComponent() {\n return this.archetypeManager.archetypesByComponent;\n }\n private get entityToReferencingArchetypes() {\n return this.archetypeManager.entityToReferencingArchetypes;\n }\n\n // Query registry – manages caching, ref counts, and archetype notifications\n private readonly queryRegistry = new QueryRegistry();\n\n // Lifecycle hooks (declared before cached contexts that reference them)\n private hooks: Set<LifecycleHookEntry> = new Set();\n\n // Debug observability (extracted to DebugStatsManager to reduce World line count)\n private readonly debugStats = new DebugStatsManager();\n\n // Command execution (orchestration extracted to CommandExecutor)\n private commandBuffer!: CommandBuffer;\n private commandExecutor!: CommandExecutor;\n\n constructor(snapshot?: SerializedWorld) {\n // Must create the manager before any code that may invoke ensureArchetype\n // (including the snapshot deserialization path below, and the closures\n // captured in the field-initialized _commandCtx).\n this.archetypeManager = new ArchetypeManager(\n {\n queryRegistry: this.queryRegistry,\n hooks: this.hooks,\n recordArchetypeCreated: () => this.debugStats.recordArchetypeCreated(),\n recordArchetypeRemoved: () => this.debugStats.recordArchetypeRemoved(),\n },\n this.sparseStore,\n );\n\n if (snapshot && typeof snapshot === \"object\") {\n deserializeWorld(\n {\n entityIdManager: this.entityIdManager,\n componentEntities: this.componentEntities,\n entityReferences: this.entityReferences,\n ensureArchetype: (ct) => this.ensureArchetype(ct),\n setEntityToArchetype: (eid, arch) => this.archetypeManager.entityToArchetype.set(eid, arch),\n },\n snapshot,\n );\n }\n\n // CommandExecutor must be created after archetypeManager (and debugStats) because its context\n // closes over several pieces and the destroy fast path.\n const execCtx: CommandExecutorContext = {\n componentEntities: this.componentEntities,\n entityReferences: this.entityReferences,\n hooks: this.hooks,\n entityToArchetype: this.entityToArchetype,\n ensureArchetype: (ct) => this.ensureArchetype(ct),\n sparseStore: this.sparseStore,\n has: (eid, ct) => this.has(eid, ct),\n get: (eid, ct) => this.get(eid, ct),\n getOptional: (eid, ct) => this.getOptional(eid, ct),\n destroyEntityImmediate: (eid) => this.destroyEntityImmediate(eid),\n incrementMigrations: () => this.debugStats.incrementMigrations(),\n triggerLifecycleHooks,\n triggerRemoveHooksForEntityDeletion,\n };\n this.commandExecutor = new CommandExecutor(execCtx);\n\n this.commandBuffer = new CommandBuffer((entityId, commands) =>\n this.commandExecutor.executeEntityCommands(entityId, commands),\n );\n }\n\n /**\n * Creates a new entity.\n * The entity is created with an empty component set and can be configured using `set()`.\n *\n * @template T - The initial component type (defaults to void if not specified)\n * @returns A unique identifier for the new entity\n *\n * @example\n * const entity = world.new<MyComponent>();\n * world.set(entity, MyComponent, { value: 42 });\n * world.sync();\n */\n new<T = void>(): EntityId<T> {\n const entityId = this.entityIdManager.allocate();\n let emptyArchetype = this.ensureArchetype([]);\n emptyArchetype.addEntity(entityId, new Map());\n this.entityToArchetype.set(entityId, emptyArchetype);\n return entityId as EntityId<T>;\n }\n\n /**\n * Semantic alias for `new()` to avoid confusion with the `new` keyword.\n * Creates a new entity with an empty component set.\n *\n * @example\n * const entity = world.create<MyComponent>();\n */\n create<T = void>(): EntityId<T> {\n return this.new<T>();\n }\n\n /** Fast path: destroy an entity that is not referenced by any other entity, skipping BFS */\n private destroySingleEntity(entityId: EntityId): void {\n const archetype = this.entityToArchetype.get(entityId);\n if (!archetype) return;\n\n // Handle entity references (this entity references other entities)\n for (const [sourceEntityId, componentType] of getEntityReferences(this.entityReferences, entityId)) {\n if (this.entityToArchetype.has(sourceEntityId)) {\n this.removeComponentImmediate(sourceEntityId, componentType, entityId);\n }\n }\n\n this.entityReferences.delete(entityId);\n const removedComponents = archetype.removeEntity(entityId)!;\n this.entityToArchetype.delete(entityId);\n\n triggerRemoveHooksForEntityDeletion(entityId, removedComponents, archetype);\n\n this.cleanupArchetypesReferencingEntity(entityId);\n this.entityIdManager.deallocate(entityId);\n this.componentEntities.cleanupReferencesTo(entityId);\n }\n\n private destroyEntityImmediate(entityId: EntityId): void {\n // Fast path: no other entity references this one, delete directly\n if (!this.entityReferences.has(entityId)) {\n this.destroySingleEntity(entityId);\n return;\n }\n\n const queue: EntityId[] = [entityId];\n const visited = new Set<EntityId>();\n let queueIndex = 0;\n\n while (queueIndex < queue.length) {\n const cur = queue[queueIndex++]!;\n if (visited.has(cur)) continue;\n visited.add(cur);\n\n const archetype = this.entityToArchetype.get(cur);\n if (!archetype) continue;\n\n // Process entity references before removal\n for (const [sourceEntityId, componentType] of getEntityReferences(this.entityReferences, cur)) {\n if (!this.entityToArchetype.has(sourceEntityId)) continue;\n\n if (isCascadeDeleteRelation(componentType)) {\n if (!visited.has(sourceEntityId)) {\n queue.push(sourceEntityId);\n }\n } else {\n this.removeComponentImmediate(sourceEntityId, componentType, cur);\n }\n }\n\n // Remove entity from archetype - this also cleans up sparse relations\n // and returns all removed component data\n this.entityReferences.delete(cur);\n const removedComponents = archetype.removeEntity(cur)!;\n this.entityToArchetype.delete(cur);\n\n // Trigger lifecycle hooks for removed components (fast path for entity deletion)\n triggerRemoveHooksForEntityDeletion(cur, removedComponents, archetype);\n\n this.cleanupArchetypesReferencingEntity(cur);\n this.entityIdManager.deallocate(cur);\n this.componentEntities.cleanupReferencesTo(cur);\n }\n }\n\n /**\n * Checks if an **entity** (not a component) exists in the world.\n *\n * This is specifically for checking entity liveness — whether the given entity ID\n * is currently alive in the world. For checking if a component is present on an\n * entity, use {@link has} instead.\n *\n * @param entityId - The entity identifier to check\n * @returns `true` if the entity exists, `false` otherwise\n *\n * @example\n * // Check if an entity is alive\n * if (world.exists(entityId)) {\n * console.log(\"Entity exists\");\n * }\n *\n * // To check for a component, use has() instead:\n * if (world.has(entity, Position)) { ... }\n */\n exists(entityId: EntityId): boolean {\n if (this.componentEntities.exists(entityId)) return true;\n return this.entityToArchetype.has(entityId);\n }\n\n /**\n * Adds or updates a component on an entity (or marks void component as present).\n * The change is buffered and takes effect after calling `world.sync()`.\n * If the entity does not exist, throws an error.\n *\n * @overload set(entityId: EntityId, componentType: EntityId<void>): void\n * Marks a void component as present on the entity\n *\n * @overload set<T>(entityId: EntityId, componentType: EntityId<T>, component: NoInfer<T>): void\n * Adds or updates a component with data on the entity\n *\n * @throws {Error} If the entity does not exist\n * @throws {Error} If the component type is invalid or is a wildcard relation\n *\n * @example\n * world.set(entity, Position, { x: 10, y: 20 });\n * world.set(entity, Marker); // void component\n * world.singleton(GlobalConfig).set({ debug: true }); // singleton component\n * world.sync(); // Apply changes\n */\n set(entityId: EntityId, componentType: EntityId<void>): void;\n set<T>(entityId: EntityId, componentType: EntityId<T>, component: NoInfer<T>): void;\n set(entityId: EntityId | ComponentId, componentTypeOrComponent?: EntityId | any, maybeComponent?: any): void {\n const {\n entityId: targetEntityId,\n componentType,\n component,\n } = resolveSetOperation(entityId, componentTypeOrComponent, maybeComponent, (id) => this.exists(id));\n this.commandBuffer.set(targetEntityId, componentType, component);\n }\n\n /**\n * Removes a component from an entity.\n * The change is buffered and takes effect after calling `world.sync()`.\n * If the entity does not exist, throws an error.\n *\n * @overload remove<T>(entityId: EntityId, componentType: EntityId<T>): void\n * Removes a component from an entity.\n *\n * @overload remove<T>(componentId: ComponentId<T>): void\n * Removes a singleton component (shorthand for remove(componentId, componentId)).\n *\n * @template T - The component data type\n * @param entityId - The entity identifier\n * @param componentType - The component type to remove\n *\n * @throws {Error} If the entity does not exist\n * @throws {Error} If the component type is invalid\n *\n * @example\n * world.remove(entity, Position);\n * world.remove(GlobalConfig); // Remove singleton component\n * world.sync(); // Apply changes\n */\n remove<T>(componentId: ComponentId<T>): void;\n remove<T>(entityId: EntityId, componentType: EntityId<T>): void;\n remove<T>(entityId: EntityId | ComponentId, componentType?: EntityId<T>): void {\n const { entityId: targetEntityId, componentType: targetComponentType } = resolveRemoveOperation(\n entityId,\n componentType,\n (id) => this.exists(id),\n );\n this.commandBuffer.remove(targetEntityId, targetComponentType);\n }\n\n /**\n * Deletes an entity and all its components from the world.\n * The change is buffered and takes effect after calling `world.sync()`.\n * Related entities may trigger cascade delete hooks if configured.\n *\n * @param entityId - The entity identifier to delete\n *\n * @example\n * world.delete(entity);\n * world.sync(); // Apply changes\n */\n delete(entityId: EntityId): void {\n this.commandBuffer.delete(entityId);\n }\n\n /**\n * Returns an explicit handle for a singleton component (component-as-entity).\n *\n * This is the preferred API for singleton components.\n *\n * @example\n * const config = world.singleton(GlobalConfig);\n * config.set({ debug: true });\n * world.sync();\n * console.log(config.get());\n */\n singleton<T>(componentId: ComponentId<T>): SingletonHandle<T> {\n assertEntityExists(componentId, \"Component entity\", (id) => this.exists(id));\n assertSetComponentTypeValid(componentId);\n\n return new SingletonHandle(componentId, {\n has: () => this.componentEntities.hasSingleton(componentId),\n get: () => this.get(componentId),\n getOptional: () => this.getOptional(componentId),\n remove: () => this.commandBuffer.remove(componentId, componentId),\n set: (value) => {\n this.commandBuffer.set(componentId, componentId as EntityId<any>, value as any);\n },\n });\n }\n\n /**\n * Checks if a specific **component** is present on an entity.\n *\n * This is for component membership checks — does the given entity have this\n * component type? For checking whether an entity itself is alive, use\n * {@link exists} instead.\n *\n * Immediately reflects the current state without waiting for `sync()`.\n *\n * @overload has<T>(entityId: EntityId, componentType: EntityId<T>): boolean\n * Checks if a specific component type is present on the entity.\n *\n * @overload has<T>(componentId: ComponentId<T>): boolean\n * Shorthand for checking a **singleton component** — a component that is its own\n * entity (component-as-entity pattern). Equivalent to `has(componentId, componentId)`.\n *\n * @template T - The component data type\n * @param entityId - The entity identifier, or a singleton component ID\n * @param componentType - The component type to check\n * @returns `true` if the entity has the component, `false` otherwise\n *\n * @example\n * // Check if an entity has a component\n * if (world.has(entity, Position)) {\n * const pos = world.get(entity, Position);\n * }\n *\n * // Check a singleton component (component-as-entity)\n * if (world.has(GlobalConfig)) {\n * const config = world.get(GlobalConfig);\n * }\n *\n * // Use exists() for entity liveness checks\n * if (world.exists(entity)) { ... }\n */\n has<T>(componentId: ComponentId<T>): boolean;\n has<T>(entityId: EntityId, componentType: EntityId<T>): boolean;\n has<T>(entityId: EntityId | ComponentId, componentType?: EntityId<T>): boolean {\n // Handle singleton component overload: has(componentId)\n if (componentType === undefined) {\n const componentId = entityId as ComponentId<T>;\n return this.componentEntities.hasSingleton(componentId);\n }\n\n if (this.componentEntities.exists(entityId)) {\n if (isWildcardRelationId(componentType)) {\n const componentId = getComponentIdFromRelationId(componentType);\n if (componentId === undefined) return false;\n return this.componentEntities.hasWildcard(entityId, componentId);\n }\n return this.componentEntities.has(entityId, componentType);\n }\n\n const archetype = this.entityToArchetype.get(entityId);\n if (!archetype) return false;\n\n if (archetype.componentTypeSet.has(componentType)) return true;\n\n if (isSparseRelation(componentType)) {\n // Use getValue; presence check via getAllForEntity only if value can legitimately be undefined\n const val = this.sparseStore.getValue(entityId, componentType);\n if (val !== undefined) return true;\n return this.sparseStore.getAllForEntity(entityId).some(([t]) => t === componentType);\n }\n\n return false;\n }\n\n /**\n * Retrieves a component from an entity.\n * For wildcard relations, returns all relations of that type.\n * Throws an error if the component does not exist; use `has()` to check first or use `getOptional()`.\n *\n * @overload get<T>(entityId: EntityId<T>): T\n * When called with only an entity ID, retrieves the entity's primary component.\n *\n * @overload get<T>(entityId: EntityId, componentType: WildcardRelationId<T>): [EntityId<unknown>, T][]\n * For wildcard relations, returns an array of [target entity, component value] pairs.\n *\n * @overload get<T>(entityId: EntityId, componentType: EntityId<T>): T\n * Retrieves a specific component from the entity.\n *\n * @throws {Error} If the entity does not exist\n * @throws {Error} If the component does not exist on the entity\n *\n * @example\n * const position = world.get(entity, Position); // Throws if no Position\n * const relations = world.get(entity, relation(Parent, \"*\")); // Wildcard relation\n */\n get<T>(entityId: EntityId<T>): T;\n get<T>(entityId: EntityId, componentType: WildcardRelationId<T>): [EntityId<unknown>, T][];\n get<T>(entityId: EntityId, componentType: EntityId<T>): T;\n get<T>(\n entityId: EntityId,\n componentType: EntityId<T> | WildcardRelationId<T> = entityId as EntityId<T>,\n ): T | [EntityId<unknown>, any][] {\n if (this.componentEntities.exists(entityId)) {\n if (isWildcardRelationId(componentType as EntityId<any>)) {\n return this.componentEntities.getWildcard(entityId, componentType as WildcardRelationId<T>);\n }\n return this.componentEntities.get(entityId, componentType as EntityId<T>);\n }\n\n const archetype = this.entityToArchetype.get(entityId);\n if (!archetype) {\n throw new Error(`Entity ${entityId} does not exist`);\n }\n\n if (componentType >= 0 || componentType % RELATION_SHIFT !== 0) {\n const inArchetype = archetype.componentTypeSet.has(componentType);\n const hasSparse = isSparseRelation(componentType);\n const hasComponent =\n inArchetype ||\n (hasSparse &&\n (this.sparseStore.getValue(entityId, componentType) !== undefined ||\n this.sparseStore.getAllForEntity(entityId).some(([t]) => t === componentType)));\n\n if (!hasComponent) {\n throw new Error(\n `Entity ${entityId} does not have component ${componentType}. Use has() to check component existence before calling get().`,\n );\n }\n }\n\n return archetype.get(entityId, componentType) as T | [EntityId<unknown>, any][];\n }\n\n /**\n * Safely retrieves a component from an entity without throwing an error.\n * Returns `undefined` if the component does not exist.\n * For wildcard relations, returns `undefined` if there are no relations.\n *\n * @template T - The component data type\n * @overload getOptional<T>(entityId: EntityId<T>): { value: T } | undefined\n * Retrieves the entity's primary component safely.\n *\n * @overload getOptional<T>(entityId: EntityId, componentType: WildcardRelationId<T>): { value: [EntityId<unknown>, T][] } | undefined\n * Retrieves all matching relation values safely.\n *\n * @overload getOptional<T>(entityId: EntityId, componentType: EntityId<T>): { value: T } | undefined\n * Retrieves a specific component safely.\n *\n * @throws {Error} If the entity does not exist\n *\n * @example\n * const position = world.getOptional(entity, Position);\n * if (position) {\n * console.log(position.value.x);\n * }\n */\n getOptional<T>(entityId: EntityId<T>): { value: T } | undefined;\n getOptional<T>(\n entityId: EntityId,\n componentType: WildcardRelationId<T>,\n ): { value: [EntityId<unknown>, T][] } | undefined;\n getOptional<T>(entityId: EntityId, componentType: EntityId<T>): { value: T } | undefined;\n getOptional<T>(\n entityId: EntityId,\n componentType: EntityId<T> | WildcardRelationId<T> = entityId as EntityId<T>,\n ): { value: T } | { value: [EntityId<unknown>, T][] } | undefined {\n if (this.componentEntities.exists(entityId)) {\n if (isWildcardRelationId(componentType)) {\n const relations = this.componentEntities.getWildcard(entityId, componentType);\n if (relations.length === 0) return undefined;\n return { value: relations };\n }\n return this.componentEntities.getOptional(entityId, componentType);\n }\n\n const archetype = this.entityToArchetype.get(entityId);\n if (!archetype) {\n throw new Error(`Entity ${entityId} does not exist`);\n }\n\n if (isWildcardRelationId(componentType)) {\n // For wildcard relations, get the data and wrap in optional if non-empty\n const wildcardData = archetype.get(entityId, componentType) as [EntityId<unknown>, T][];\n if (Array.isArray(wildcardData) && wildcardData.length > 0) {\n return { value: wildcardData };\n }\n return undefined;\n }\n\n return archetype.getOptional(entityId, componentType);\n }\n\n // ==========================================================================\n // Relation & Hierarchy Companion Tools (public API)\n // ==========================================================================\n\n /**\n * Retrieves all targets (and their associated data) for relations of a given\n * base component on an entity.\n *\n * This is the ergonomic replacement for the common pattern:\n * world.get(entity, relation(Comp, \"*\"))\n *\n * @example\n * const ChildOf = component({ exclusive: true, sparse: true });\n * const children = world.getRelationTargets(parent, ChildOf); // usually []\n * const items = world.getRelationTargets(player, InInventory);\n *\n * // For common hierarchy use cases, prefer the higher-level helpers:\n * // world.getChildren(parent, ChildOf), world.getParent(child, ChildOf)\n */\n getRelationTargets<T = void>(\n entityId: EntityId,\n relationComp: ComponentId<T>,\n ): [target: EntityId<unknown>, data: T | undefined][] {\n assertEntityExists(entityId, \"Entity\", (id) => this.exists(id));\n\n const wildcard = relation(relationComp, \"*\") as WildcardRelationId<T>;\n\n // For component entities (singletons) the path is different; they rarely host relations\n if (this.componentEntities.exists(entityId)) {\n return this.componentEntities.getWildcard(entityId, wildcard);\n }\n\n // Regular entity path — archetype.get for wildcard always materializes the array\n // (even if empty for a sparse relation that only has the marker)\n const data = this.get(entityId, wildcard);\n return data as [EntityId<unknown>, T | undefined][];\n }\n\n /**\n * Returns every entity that currently holds a relation of the given base\n * component pointing at `targetId`.\n *\n * This is the efficient **reverse** lookup. For common hierarchy cases,\n * prefer the higher-level `world.getChildren(parent, ChildOf)` instead.\n *\n * @example\n * const ChildOf = component({ exclusive: true, sparse: true });\n * const directChildren = world.getRelationSources(ship, ChildOf);\n */\n getRelationSources(targetId: EntityId, relationComp: ComponentId<any>): EntityId[] {\n const refs = getEntityReferences(this.entityReferences, targetId);\n const result: EntityId[] = [];\n\n for (const [source, relType] of refs) {\n // Only consider still-living sources\n if (!this.entityToArchetype.has(source) && !this.componentEntities.exists(source)) continue;\n\n const decodedComp = getComponentIdFromRelationId(relType);\n if (decodedComp === relationComp) {\n result.push(source);\n }\n }\n return result;\n }\n\n /**\n * Returns true if the entity has any (or a specific-target) relation of the\n * given base component.\n */\n hasRelation(entityId: EntityId, relationComp: ComponentId<any>, targetId?: EntityId): boolean {\n assertEntityExists(entityId, \"Entity\", (id) => this.exists(id));\n\n if (targetId !== undefined) {\n const specific = relation(relationComp, targetId);\n return this.has(entityId, specific);\n }\n\n // Any target of this relation kind?\n const targets = this.getRelationTargets(entityId, relationComp);\n return targets.length > 0;\n }\n\n /**\n * Returns the number of relations of the given base component held by the entity.\n */\n countRelations(entityId: EntityId, relationComp: ComponentId<any>): number {\n assertEntityExists(entityId, \"Entity\", (id) => this.exists(id));\n const targets = this.getRelationTargets(entityId, relationComp);\n return targets.length;\n }\n\n /**\n * For an *exclusive* relation (e.g. ChildOf, Owner), returns the single\n * target entity (or undefined if none).\n *\n * When the component was declared `exclusive: true`, this is the preferred\n * accessor (clearer intent than array destructuring).\n */\n getSingleRelationTarget<T = void>(entityId: EntityId, relationComp: ComponentId<T>): EntityId | undefined {\n const targets = this.getRelationTargets(entityId, relationComp);\n return targets.length > 0 ? (targets[0]![0] as EntityId) : undefined;\n }\n\n // --------------------------------------------------------------------------\n // High-level hierarchy helpers (convenience methods on World)\n // --------------------------------------------------------------------------\n\n /**\n * Returns the direct children of `parent` for the given relationship component\n * (typically a `ChildOf` or similar exclusive `sparse` relation).\n *\n * This is the recommended high-level API for hierarchy traversal.\n * It uses the internal reverse reference index for efficiency.\n *\n * @example\n * const ChildOf = component({ exclusive: true, sparse: true });\n * const kids = world.getChildren(ship, ChildOf);\n */\n getChildren(parent: EntityId, childOf: ComponentId<any>): EntityId[] {\n return this.getRelationSources(parent, childOf);\n }\n\n /**\n * Returns the parent of `child` for the given relationship component\n * (typically an exclusive `ChildOf` relation).\n *\n * @example\n * const ChildOf = component({ exclusive: true, sparse: true });\n * const parent = world.getParent(turret, ChildOf);\n */\n getParent(child: EntityId, childOf: ComponentId<any>): EntityId | undefined {\n return this.getSingleRelationTarget(child, childOf);\n }\n\n /**\n * Returns the ancestor chain from the immediate parent up to (but not\n * including) the root for the given relationship component.\n *\n * @example\n * const ChildOf = component({ exclusive: true, sparse: true });\n * const ancestors = world.getAncestors(muzzle, ChildOf); // [turret, ship]\n */\n getAncestors(entity: EntityId, childOf: ComponentId<any>): EntityId[] {\n const ancestors: EntityId[] = [];\n let cur = this.getParent(entity, childOf);\n while (cur !== undefined) {\n ancestors.push(cur);\n cur = this.getParent(cur, childOf);\n }\n return ancestors;\n }\n\n /**\n * Iteratively traverses all descendants of `root` in DFS pre-order.\n * This is a generator and is safe for very deep hierarchies.\n *\n * @example\n * for (const { entity, depth, parent } of world.iterateDescendants(root, ChildOf)) {\n * console.log(depth, entity);\n * }\n */\n *iterateDescendants(\n root: EntityId,\n childOf: ComponentId<any>,\n opts: { includeSelf?: boolean; maxDepth?: number } = {},\n ): IterableIterator<{ entity: EntityId; depth: number; parent: EntityId | null }> {\n const { includeSelf = false, maxDepth } = opts;\n const stack: Array<{ entity: EntityId; depth: number; parent: EntityId | null }> = [];\n\n if (includeSelf) {\n stack.push({ entity: root, depth: 0, parent: null });\n } else {\n for (const child of this.getChildren(root, childOf)) {\n stack.push({ entity: child, depth: 1, parent: root });\n }\n }\n\n while (stack.length > 0) {\n const current = stack.pop()!;\n if (maxDepth !== undefined && current.depth > maxDepth) continue;\n\n yield current;\n\n const kids = this.getChildren(current.entity, childOf);\n for (let i = kids.length - 1; i >= 0; i--) {\n const k = kids[i]!;\n stack.push({ entity: k, depth: current.depth + 1, parent: current.entity });\n }\n }\n }\n\n /**\n * Callback-based descendant traversal (hot path friendly).\n * Return `false` from the visitor to stop early.\n */\n traverseDescendants(\n root: EntityId,\n childOf: ComponentId<any>,\n visitor: (entity: EntityId, depth: number, parent: EntityId | null) => void | boolean,\n opts: { includeSelf?: boolean; maxDepth?: number } = {},\n ): void {\n for (const { entity, depth, parent } of this.iterateDescendants(root, childOf, opts)) {\n const res = visitor(entity, depth, parent);\n if (res === false) return;\n }\n }\n\n /**\n * Registers a lifecycle hook that responds to component changes.\n * The hook callback is invoked when components matching the specified types are added, updated, or removed.\n * @overload hook<const T extends readonly ComponentType<any>[]>(\n * componentTypes: T,\n * hook: LifecycleHook<T> | LifecycleCallback<T>,\n * filter?: QueryFilter,\n * ): () => void\n * Registers a hook for multiple component types.\n * The hook is triggered when entities enter/exit the matching set.\n *\n * @param componentTypes - Component types that define the matching entity set\n * @param hook - Either a hook object with on_init/on_set/on_remove handlers, or a callback function\n * @param filter - Optional query-style filter applied to the hook match set\n * @returns A function that unsubscribes the hook when called\n *\n * @throws {Error} If no required components are specified in array overload\n *\n * @example\n * const unsubscribe = world.hook([Position, Velocity], {\n * on_init: (entityId, position, velocity) => console.log(\"Initialized\"),\n * on_set: (entityId, position, velocity) => console.log(\"Updated\"),\n * on_remove: (entityId, position, velocity) => console.log(\"Removed\"),\n * });\n * unsubscribe(); // Remove hook\n *\n * // Callback style\n * const unsubscribe = world.hook([Position], (event, entityId, position) => {\n * if (event === \"init\") console.log(\"Initialized\");\n * });\n *\n * // With filter\n * const unsubscribe2 = world.hook(\n * [Position, Velocity],\n * {\n * on_set: (entityId, position, velocity) => console.log(entityId, position, velocity),\n * },\n * { negativeComponentTypes: [Disabled] },\n * );\n */\n hook<const T extends readonly ComponentType<any>[]>(\n componentTypes: T,\n hook: LifecycleHook<T> | LifecycleCallback<T>,\n filter?: QueryFilter,\n ): () => void;\n hook(\n componentTypes: readonly ComponentType<any>[],\n hook: LifecycleHook<any> | LifecycleCallback<any>,\n filter?: QueryFilter,\n ): () => void {\n const isCallback = typeof hook === \"function\";\n const callback = isCallback ? (hook as LifecycleCallback<any>) : undefined;\n\n const requiredComponents: EntityId<any>[] = [];\n const optionalComponents: EntityId<any>[] = [];\n for (const ct of componentTypes) {\n if (!isOptionalEntityId(ct)) {\n requiredComponents.push(ct as EntityId<any>);\n } else {\n optionalComponents.push(ct.optional);\n }\n }\n\n if (requiredComponents.length === 0) {\n throw new Error(\"Hook must have at least one required component\");\n }\n\n const entry: LifecycleHookEntry = {\n componentTypes,\n requiredComponents,\n optionalComponents,\n filter: filter || {},\n hook: isCallback ? ({} as LifecycleHook<any>) : (hook as LifecycleHook<any>),\n callback,\n matchedArchetypes: new Set(),\n };\n this.hooks.add(entry);\n\n // Single pass: collect matching archetypes\n const matchedArchetypes: Archetype[] = [];\n for (const archetype of this.archetypes) {\n if (this.archetypeMatchesHook(archetype, entry)) {\n archetype.matchingMultiHooks.add(entry);\n entry.matchedArchetypes!.add(archetype);\n matchedArchetypes.push(archetype);\n }\n }\n\n // Callback style: invoke callback(\"init\", ...); hook style: invoke hook.on_init(...)\n const shouldFireInit = isCallback || (hook as LifecycleHook<any>).on_init !== undefined;\n if (shouldFireInit) {\n for (const archetype of matchedArchetypes) {\n for (const entityId of archetype.getEntities()) {\n const components = collectMultiHookComponents(this.createHooksContext(), entityId, componentTypes);\n if (isCallback) {\n (callback as LifecycleCallback<any>)(\"init\", entityId, ...components);\n } else {\n (hook as LifecycleHook<any>).on_init!(entityId, ...components);\n }\n }\n }\n }\n\n return () => {\n this.hooks.delete(entry);\n if (entry.matchedArchetypes) {\n for (const archetype of entry.matchedArchetypes) {\n archetype.matchingMultiHooks.delete(entry);\n }\n }\n };\n }\n\n /**\n * Creates a debug stats collector that will receive a `SyncDebugStats` payload\n * after every subsequent `sync()`.\n *\n * The returned object is a pure lifecycle handle. It does not store data.\n * Collection stops when you call `[Symbol.dispose]()` (or use a `using` declaration).\n *\n * All active collectors receive the exact same stats object for a given sync.\n * Exceptions thrown by callbacks are ignored.\n *\n * This is intended for development/debugging and leak detection.\n */\n createDebugStatsCollector(callback: (stats: SyncDebugStats) => void): DebugStatsCollector {\n return this.debugStats.createCollector(callback);\n }\n\n /**\n * Synchronizes all buffered commands (set/remove/delete) to the world.\n * This method must be called after making changes via `set()`, `remove()`, or `delete()` for them to take effect.\n * Typically called once per frame at the end of your game loop.\n *\n * @example\n * world.set(entity, Position, { x: 10, y: 20 });\n * world.remove(entity, OldComponent);\n * world.sync(); // Apply all buffered changes\n */\n sync(): void {\n if (!this.debugStats.hasActiveCollectors()) {\n // Fast path: no debug collectors, skip all timing and stats work\n this.commandBuffer.execute();\n return;\n }\n\n // Slow path: full instrumentation for active debug stats collectors\n const syncStart = performance.now();\n this.debugStats.resetActivity();\n\n const commandBufferStart = performance.now();\n const commandIterations = this.commandBuffer.execute();\n const commandBufferEnd = performance.now();\n\n const syncEnd = performance.now();\n\n // Build the data bag for the extracted manager (keeps it decoupled from internal maps)\n const entityCount = this.entityToArchetype.size;\n let emptyArchetypes = 0;\n for (const arch of this.archetypes) {\n if (arch.size === 0) emptyArchetypes++;\n }\n\n let archetypesByComponentSize = 0;\n for (const set of this.archetypesByComponent.values()) {\n archetypesByComponentSize += set.size;\n }\n\n this.debugStats.deliver(\n {\n syncStart,\n syncEnd,\n commandBufferStart,\n commandBufferEnd,\n commandIterations,\n },\n {\n entityCount,\n freelistSize: this.entityIdManager.getFreelistSize(),\n nextId: this.entityIdManager.getNextId(),\n archetypeCount: this.archetypes.length,\n emptyArchetypes,\n archetypesByComponentSize,\n cachedQueryCount: (this.queryRegistry as any).cache?.size ?? 0,\n registeredQueryCount: (this.queryRegistry as any).queries?.size ?? 0,\n hookCount: this.hooks.size,\n entityReferencesSize: this.entityReferences.size,\n entityToReferencingArchetypesSize: this.entityToReferencingArchetypes.size,\n },\n );\n }\n\n /**\n * Creates a cached query for efficiently iterating entities with specific components.\n * The query is cached internally and reused across calls with the same component types and filter.\n *\n * **Important:** Store the query reference and reuse it across frames for optimal performance.\n * Creating a new query each frame defeats the caching mechanism.\n *\n * **Note on optional components:** Only **required** (non-optional) component types should be\n * passed to `createQuery`. Optional components (wrapped with `{ optional: ... }`) must be\n * specified at **iteration time** via {@link Query.forEach}, {@link Query.getEntitiesWithComponents},\n * or {@link Query.iterate} — NOT here. Including optional wrappers in `createQuery` will cause\n * undefined behavior because the internal normalization relies on numeric sorting of component IDs.\n *\n * @param componentTypes - Array of **required** component types to match (do not include optional wrappers)\n * @param filter - Optional filter for additional constraints (e.g., exclude entities with certain components)\n * @returns A Query instance that can be used to iterate matching entities\n *\n * @example\n * // Create once, reuse many times (required components only)\n * const movementQuery = world.createQuery([Position, Velocity]);\n *\n * // Optional components are passed at iteration time, not creation time:\n * movementQuery.forEach([Position, { optional: Velocity }], (entity, pos, vel) => {\n * pos.x += vel?.value?.x ?? 0;\n * });\n *\n * // With filter\n * const activeQuery = world.createQuery([Position], {\n * negativeComponentTypes: [Disabled]\n * });\n */\n createQuery(componentTypes: EntityId<any>[], filter: QueryFilter = {}): Query {\n const sortedTypes = normalizeComponentTypes(componentTypes);\n const filterKey = serializeQueryFilter(filter);\n const key = `${sortedTypes.join(\",\")}${filterKey ? `|${filterKey}` : \"\"}`;\n return this.queryRegistry.getOrCreate(this, sortedTypes, key, filter);\n }\n\n /**\n * Creates a new entity builder for fluent entity configuration.\n * Useful for building entities with multiple components in a single expression.\n *\n * @returns An EntityBuilder instance\n *\n * @example\n * const entity = world.spawn()\n * .with(Position, { x: 0, y: 0 })\n * .with(Velocity, { x: 1, y: 1 })\n * .build();\n * world.sync(); // Apply changes\n */\n spawn(): EntityBuilder {\n return new EntityBuilder(this);\n }\n\n /**\n * Spawns multiple entities with a configuration callback.\n * More efficient than calling `spawn()` multiple times when creating many entities.\n *\n * @param count - Number of entities to spawn\n * @param configure - Callback that receives an EntityBuilder and index; must return the configured builder\n * @returns Array of created entity IDs\n *\n * @example\n * const entities = world.spawnMany(100, (builder, index) => {\n * return builder\n * .with(Position, { x: index * 10, y: 0 })\n * .with(Velocity, { x: 0, y: 1 });\n * });\n * world.sync();\n */\n spawnMany(count: number, configure: (builder: EntityBuilder, index: number) => EntityBuilder): EntityId[] {\n const entities: EntityId[] = [];\n for (let i = 0; i < count; i++) {\n const builder = new EntityBuilder(this);\n entities.push(configure(builder, i).build());\n }\n return entities;\n }\n\n /**\n * Releases a cached query and frees its resources if no longer needed.\n * Call this when you're done using a query to allow the world to clean up its cache entry.\n *\n * @param query - The query to release\n *\n * @example\n * const query = world.createQuery([Position]);\n * // ... use query ...\n * world.releaseQuery(query); // Optional cleanup\n */\n releaseQuery(query: Query): void {\n this.queryRegistry.release(query);\n }\n\n /**\n * Returns all archetypes that contain entities with the specified components.\n * Used internally for query optimization but can be useful for debugging.\n *\n * @param componentTypes - Array of component types to match\n * @returns Array of Archetype objects containing matching components\n * @internal\n */\n getMatchingArchetypes(componentTypes: EntityId<any>[]): Archetype[] {\n return this.archetypeManager.getMatchingArchetypes(componentTypes);\n }\n\n /**\n * Queries entities with specific components.\n * For simpler use cases, prefer using `createQuery()` with `forEach()` which is cached and more efficient.\n *\n * @overload query(componentTypes: EntityId<any>[]): EntityId[]\n * Returns an array of entity IDs that have all specified components.\n *\n * @overload query<const T extends readonly EntityId<any>[]>(\n * componentTypes: T,\n * includeComponents: true,\n * ): Array<{ entity: EntityId; components: ComponentTuple<T> }>\n * Returns entities along with their component data.\n *\n * @param componentTypes - Array of component types to query\n * @param includeComponents - If true, includes component data in results\n * @returns Array of entity IDs or objects with entities and components\n *\n * @example\n * // Just entity IDs\n * const entities = world.query([Position, Velocity]);\n *\n * // With components\n * const results = world.query([Position, Velocity], true);\n * results.forEach(({ entity, components: [pos, vel] }) => {\n * pos.x += vel.x;\n * });\n */\n query(componentTypes: EntityId<any>[]): EntityId[];\n query<const T extends readonly EntityId<any>[]>(\n componentTypes: T,\n includeComponents: true,\n ): Array<{ entity: EntityId; components: ComponentTuple<T> }>;\n query(\n componentTypes: EntityId<any>[],\n includeComponents?: boolean,\n ): EntityId[] | Array<{ entity: EntityId; components: any }> {\n const matchingArchetypes = this.getMatchingArchetypes(componentTypes);\n\n if (includeComponents) {\n const result: Array<{ entity: EntityId; components: any }> = [];\n for (const archetype of matchingArchetypes) {\n archetype.appendEntitiesWithComponents(componentTypes as EntityId<any>[], result);\n }\n return result;\n } else {\n const result: EntityId[] = [];\n for (const archetype of matchingArchetypes) {\n for (const entity of archetype.getEntities()) {\n result.push(entity);\n }\n }\n return result;\n }\n }\n\n // Delegators to the extracted ArchetypeManager (keeps public + internal call sites unchanged).\n private ensureArchetype(componentTypes: Iterable<EntityId<any>>): Archetype {\n return this.archetypeManager.ensureArchetype(componentTypes);\n }\n\n private cleanupArchetypesReferencingEntity(entityId: EntityId): void {\n this.archetypeManager.cleanupArchetypesReferencingEntity(entityId);\n }\n\n private archetypeMatchesHook(archetype: Archetype, entry: LifecycleHookEntry): boolean {\n return this.archetypeManager.archetypeMatchesHook(archetype, entry);\n }\n\n /**\n * Serializes the entire world state to a plain JavaScript object.\n * This creates a \"memory snapshot\" that can be stored or transmitted.\n * The snapshot can be restored using `new World(snapshot)`.\n *\n * **Note:** This is NOT automatically persistent storage. To persist data,\n * you must serialize the returned object to JSON or another format yourself.\n *\n * @returns A serializable object representing the world state\n *\n * @example\n * // Create snapshot\n * const snapshot = world.serialize();\n *\n * // Save to storage (example)\n * localStorage.setItem('save', JSON.stringify(snapshot));\n *\n * // Later, restore from snapshot\n * const savedData = JSON.parse(localStorage.getItem('save'));\n * const newWorld = new World(savedData);\n */\n // Thin delegator to the extracted CommandExecutor for cascade paths (destroy* methods).\n private removeComponentImmediate(entityId: EntityId, componentType: EntityId<any>, targetEntityId: EntityId): void {\n this.commandExecutor.removeComponentImmediate(entityId, componentType, targetEntityId);\n }\n\n private createHooksContext(): HooksContext {\n // The executor owns the current HooksContext; expose for any remaining internal use.\n return (\n (this.commandExecutor as any).getHooksContext?.() ?? {\n multiHooks: this.hooks,\n has: (eid, ct) => this.has(eid, ct),\n get: (eid, ct) => this.get(eid, ct),\n getOptional: (eid, ct) => this.getOptional(eid, ct),\n }\n );\n }\n\n serialize(): SerializedWorld {\n return serializeWorld(\n this.archetypeManager.archetypes as Archetype[],\n this.componentEntities,\n this.entityIdManager,\n );\n }\n}\n"],"mappings":"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"}
|