@codehz/ecs 0.8.0 → 0.8.1

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.
@@ -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 * - **`dontFragment`**: 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 will not cause 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**: When `dontFragment` is enabled, the relation's target does **not**\n * contribute to the archetype signature. Entities with different targets for the same\n * relation component share a **single archetype**, and the per-entity target data is\n * stored in a separate `DontFragmentStore` (a `Map<EntityId, Map<EntityId, any>>`).\n * A wildcard relation marker (`relation(Comp, \"*\")`) is placed in the archetype\n * 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 `dontFragment`, each target change would\n * cause 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 `dontFragment`**: 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 `dontFragment`**: Archetype count stays constant regardless of target\n * diversity. Changing a relation target is an O(1) update in the `DontFragmentStore`.\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 * @example\n * ```ts\n * // Without dontFragment: 100 entities with different parents = 100 archetypes\n * const ChildOf = component(); // default: fragmentation happens\n *\n * // With dontFragment: 100 entities with different parents = 1 archetype\n * const ChildOf = component({ dontFragment: 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 * // dontFragment: 1 archetype for all 100 entities\n * // without: 100 archetypes, one per unique parent\n * ```\n *\n * Inspired by Flecs' `DontFragment` trait.\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 dontFragmentFlags = 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 if (options.dontFragment) dontFragmentFlags.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 hasDontFragment = dontFragmentFlags.has(id);\n return {\n name: hasName ? componentNames[id] : undefined,\n exclusive: hasExclusive ? true : undefined,\n cascadeDelete: hasCascadeDelete ? true : undefined,\n dontFragment: hasDontFragment ? 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 `dontFragment`.\n *\n * When a component has `dontFragment: true`, relations using it do not cause\n * archetype fragmentation — entities with different relation targets can share\n * the same archetype. This is a fast O(1) bitset lookup.\n *\n * @param id - The component ID to check.\n * @returns `true` if the component was created with `dontFragment: true`.\n *\n * @see {@link ComponentOptions.dontFragment} for the full explanation of how\n * `dontFragment` prevents archetype fragmentation.\n */\nexport function isDontFragmentComponent(id: ComponentId<any>): boolean {\n return dontFragmentFlags.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 `isDontFragmentRelation`,\n * `isDontFragmentWildcard`, `isExclusiveRelation`, `isExclusiveWildcard`,\n * 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 `dontFragment`\n * component.\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. Relations with\n * `dontFragment` components are stored in the shared {@link DontFragmentStore} instead\n * of being part of the archetype's component type list.\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 * `dontFragment` 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 `dontFragment: true`.\n *\n * @see {@link isDontFragmentWildcard} for the wildcard variant.\n * @see {@link ComponentOptions.dontFragment} for the full explanation.\n */\nexport function isDontFragmentRelation(id: EntityId<any>): boolean {\n return checkRelationFlag(id, dontFragmentFlags, (targetId) => targetId !== WILDCARD_TARGET_ID);\n}\n\n/**\n * Check if an ID is a wildcard relation (`relation(Comp, \"*\")`) backed by a\n * `dontFragment` component.\n *\n * Wildcard markers for `dontFragment` components are placed in the archetype\n * component list so that queries can discover archetypes containing entities\n * with that relation type. This function is used in `filterRegularComponentTypes`\n * to **keep** these wildcard markers in the archetype signature while stripping\n * out specific-target `dontFragment` relations.\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 * `dontFragment` 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 `dontFragment: true`.\n *\n * @see {@link isDontFragmentRelation} for the specific-target variant.\n * @see {@link ComponentOptions.dontFragment} for the full explanation.\n */\nexport function isDontFragmentWildcard(id: EntityId<any>): boolean {\n return checkRelationFlag(id, dontFragmentFlags, (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 * 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 { DontFragmentStore } 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 * Find all relations in dontFragment data that match a component ID\n */\nexport function findMatchingDontFragmentRelations(\n dontFragmentData: Map<EntityId<any>, any> | undefined,\n componentId: EntityId<any>,\n relations: [EntityId<unknown>, any][] = [],\n): [EntityId<unknown>, any][] {\n if (!dontFragmentData) return relations;\n\n for (const [relType, data] of dontFragmentData) {\n const relDetailed = getDetailedIdType(relType);\n if (isRelationType(relDetailed) && relDetailed.componentId === componentId) {\n relations.push([relDetailed.targetId, data]);\n }\n }\n return relations;\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 */\nexport function buildWildcardRelationValue(\n wildcardRelationType: WildcardRelationId<any>,\n matchingRelations: EntityId<any>[] | undefined,\n getDataAtIndex: (relType: EntityId<any>) => any,\n dontFragmentData: Map<EntityId<any>, any> | undefined,\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 dontFragment relations\n if (targetComponentId !== undefined) {\n findMatchingDontFragmentRelations(dontFragmentData, targetComponentId, relations);\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 dontFragmentRelations: DontFragmentStore,\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 dontFragmentRelations.get(entityId),\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 isDontFragmentComponent,\n isWildcardRelationId,\n} from \"../entity\";\nimport { isOptionalEntityId, type ComponentTuple, type ComponentType, type LifecycleHookEntry } from \"../types\";\nimport { getOrCompute } from \"../utils/utils\";\nimport {\n buildCacheKey,\n buildSingleComponent,\n findMatchingDontFragmentRelations,\n getWildcardRelationDataSource,\n isRelationType,\n} from \"./helpers\";\nimport type { DontFragmentStore } 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 * DontFragmentStore for relation data keyed by entity ID.\n * This allows entities with different relation targets to share the same archetype\n * without migration overhead when entities change archetypes.\n */\n private dontFragmentRelations: DontFragmentStore;\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>[], dontFragmentRelations: DontFragmentStore) {\n this.componentTypes = normalizeComponentTypes(componentTypes);\n this.componentTypeSet = new Set(this.componentTypes);\n this.dontFragmentRelations = dontFragmentRelations;\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 dontFragment relations separately\n this.addDontFragmentRelations(entityId, componentData);\n }\n\n private addDontFragmentRelations(entityId: EntityId, componentData: Map<EntityId<any>, any>): void {\n const dontFragmentData = new Map<EntityId<any>, any>();\n\n for (const [componentType, data] of componentData) {\n if (this.componentTypeSet.has(componentType)) continue;\n\n const detailedType = getDetailedIdType(componentType);\n if (isRelationType(detailedType) && isDontFragmentComponent(detailedType.componentId!)) {\n dontFragmentData.set(componentType, data);\n }\n }\n\n if (dontFragmentData.size > 0) {\n this.dontFragmentRelations.set(entityId, dontFragmentData);\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 dontFragment relations\n const dontFragmentData = this.dontFragmentRelations.get(entityId);\n if (dontFragmentData) {\n for (const [componentType, data] of dontFragmentData) {\n entityData.set(componentType, data);\n }\n }\n\n return entityData;\n }\n\n getEntityDontFragmentRelations(entityId: EntityId): Map<EntityId<any>, any> | undefined {\n return this.dontFragmentRelations.get(entityId);\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 dontFragmentData = this.dontFragmentRelations.get(entity);\n if (dontFragmentData) {\n for (const [componentType, data] of dontFragmentData) {\n components.set(componentType, data);\n }\n }\n\n return { entity, components };\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 dontFragment relations\n const dontFragmentData = this.dontFragmentRelations.get(entityId);\n if (dontFragmentData) {\n for (const [componentType, data] of dontFragmentData) {\n removedData.set(componentType, data);\n }\n this.dontFragmentRelations.delete(entityId);\n }\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 dontFragment relations\n if (componentId !== undefined) {\n findMatchingDontFragmentRelations(this.dontFragmentRelations.get(entityId), componentId, relations);\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 dontFragmentData = this.dontFragmentRelations.get(entityId);\n if (dontFragmentData?.has(componentType)) {\n return dontFragmentData.get(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 dontFragmentData = this.dontFragmentRelations.get(entityId);\n if (dontFragmentData?.has(componentType)) {\n return { value: dontFragmentData.get(componentType) };\n }\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) && isDontFragmentComponent(detailedType.componentId!)) {\n let dontFragmentData = this.dontFragmentRelations.get(entityId);\n if (!dontFragmentData) {\n dontFragmentData = new Map();\n this.dontFragmentRelations.set(entityId, dontFragmentData);\n }\n dontFragmentData.set(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.dontFragmentRelations,\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 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 callback(this.entities[i]!, 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 dontFragment relations\n for (const entityId of this.entities) {\n const entityDontFragmentRelations = this.dontFragmentRelations.get(entityId);\n if (entityDontFragmentRelations) {\n for (const relationType of entityDontFragmentRelations.keys()) {\n const detailedType = getDetailedIdType(relationType);\n if (isRelationType(detailedType) && detailedType.componentId === componentId) {\n return true;\n }\n }\n }\n }\n\n return false;\n }\n}\n","import type { EntityId } from \"../entity\";\n\n/**\n * Minimal interface for storing dontFragment relation data keyed by entity ID.\n *\n * Using an interface here decouples `Archetype` (and `world-commands.ts`) from\n * the concrete `Map` used by `World`, making archetypes independently testable.\n */\nexport interface DontFragmentStore {\n get(entityId: EntityId): Map<EntityId<any>, any> | undefined;\n set(entityId: EntityId, data: Map<EntityId<any>, any>): void;\n delete(entityId: EntityId): void;\n}\n\n/**\n * Default implementation backed by a plain `Map`.\n * Created once by `World` and shared with every `Archetype`.\n */\nexport class DontFragmentStoreImpl implements DontFragmentStore {\n private readonly data: Map<EntityId, Map<EntityId<any>, any>> = new Map();\n\n get(entityId: EntityId): Map<EntityId<any>, any> | undefined {\n return this.data.get(entityId);\n }\n\n set(entityId: EntityId, data: Map<EntityId<any>, any>): void {\n this.data.set(entityId, data);\n }\n\n delete(entityId: EntityId): void {\n this.data.delete(entityId);\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 */\n execute(): void {\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\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 /**\n * Get the final component types after applying the changeset\n * @param existingComponentTypes - The current component types on the entity\n * @returns The final component types or undefined if no changes\n */\n getFinalComponentTypes(existingComponentTypes: EntityId<any>[]): EntityId<any>[] | undefined {\n const finalComponentTypes = new Set<EntityId<any>>(existingComponentTypes);\n let changed = false;\n\n // Apply removals\n for (const componentType of this.removes) {\n if (!finalComponentTypes.has(componentType)) {\n this.removes.delete(componentType);\n continue; // Component not present, skip\n }\n changed = true;\n finalComponentTypes.delete(componentType);\n }\n\n // Apply additions\n for (const componentType of this.adds.keys()) {\n if (finalComponentTypes.has(componentType)) {\n continue; // Component already present, skip\n }\n changed = true;\n finalComponentTypes.add(componentType);\n }\n\n return changed ? Array.from(finalComponentTypes) : undefined;\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 {\n getComponentIdFromRelationId,\n getDetailedIdType,\n isDontFragmentComponent,\n isRelationId,\n relation,\n} 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 isDontFragmentComponent(detailedType.componentId)\n ) {\n // For specific dontFragment 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-dontFragment 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, isDontFragmentComponent } 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 dontFragment relation types that need entity-level filtering */\n private specificDontFragmentTypes: 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 dontFragment relation types that need entity-level filtering\n this.specificDontFragmentTypes = 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 isDontFragmentComponent(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 dontFragment relations\n if (this.wildcardTypes.length === 0 && this.specificDontFragmentTypes.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 dontFragment 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 dontFragment 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 dontFragment relations\n for (const specificType of this.specificDontFragmentTypes) {\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 { DontFragmentStore } 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 isDontFragmentComponent,\n isDontFragmentRelation,\n isDontFragmentWildcard,\n isWildcardRelationId,\n relation,\n type ComponentId,\n type EntityId,\n} from \"../entity\";\n\nexport interface CommandProcessorContext {\n dontFragmentStore: DontFragmentStore;\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 dontFragment relations, ensure wildcard marker is in archetype signature\n if (isDontFragmentComponent(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 dontFragment relations stored on entity\n const dontFragmentData = archetype.getEntityDontFragmentRelations(entityId);\n if (dontFragmentData) {\n for (const componentType of dontFragmentData.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 dontFragment relations, also remove the wildcard marker\n if (isDontFragmentComponent(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 || !isDontFragmentComponent(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 dontFragmentData = archetype.getEntityDontFragmentRelations(entityId);\n if (dontFragmentData) {\n for (const otherComponentType of dontFragmentData.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 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.getEntityDontFragmentRelations(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 (!isDontFragmentRelation(componentType) && currentArchetype.componentTypeSet.has(componentType)) {\n return true;\n }\n }\n\n for (const componentType of changeset.adds.keys()) {\n if (!isDontFragmentRelation(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 (!isDontFragmentRelation(componentType)) {\n finalRegularTypes.delete(componentType);\n }\n }\n\n for (const [componentType] of changeset.adds) {\n if (!isDontFragmentRelation(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 dontFragment relation updates.\n if (removedComponents !== null) {\n applyDontFragmentChanges(ctx.dontFragmentStore, entityId, changeset, removedComponents);\n } else {\n applyDontFragmentChangesNoHooks(ctx.dontFragmentStore, entityId, changeset);\n }\n\n // Direct update for regular components in archetype\n for (const [componentType, component] of changeset.adds) {\n if (isDontFragmentRelation(componentType)) {\n continue;\n }\n currentArchetype.set(entityId, componentType, component);\n }\n\n return currentArchetype;\n}\n\n/**\n * No-hooks variant of applyDontFragmentChanges that skips tracking removed component data.\n */\nfunction applyDontFragmentChanges(\n dontFragmentRelations: DontFragmentStore,\n entityId: EntityId,\n changeset: ComponentChangeset,\n removedComponents: Map<EntityId<any>, any>,\n): void {\n // Get or create the entity's dontFragment relations map\n let entityRelations = dontFragmentRelations.get(entityId);\n\n for (const componentType of changeset.removes) {\n if (isDontFragmentRelation(componentType)) {\n if (entityRelations) {\n const removedValue = entityRelations.get(componentType);\n if (removedValue !== undefined || entityRelations.has(componentType)) {\n removedComponents.set(componentType, removedValue);\n entityRelations.delete(componentType);\n }\n }\n }\n }\n\n for (const [componentType, component] of changeset.adds) {\n if (isDontFragmentRelation(componentType)) {\n if (!entityRelations) {\n entityRelations = new Map();\n dontFragmentRelations.set(entityId, entityRelations);\n }\n entityRelations.set(componentType, component);\n }\n }\n\n // Clean up empty map\n if (entityRelations && entityRelations.size === 0) {\n dontFragmentRelations.delete(entityId);\n }\n}\n\nfunction applyDontFragmentChangesNoHooks(\n dontFragmentRelations: DontFragmentStore,\n entityId: EntityId,\n changeset: ComponentChangeset,\n): void {\n let entityRelations = dontFragmentRelations.get(entityId);\n\n for (const componentType of changeset.removes) {\n if (isDontFragmentRelation(componentType)) {\n if (entityRelations) {\n entityRelations.delete(componentType);\n }\n }\n }\n\n for (const [componentType, component] of changeset.adds) {\n if (isDontFragmentRelation(componentType)) {\n if (!entityRelations) {\n entityRelations = new Map();\n dontFragmentRelations.set(entityId, entityRelations);\n }\n entityRelations.set(componentType, component);\n }\n }\n\n // Clean up empty map\n if (entityRelations && entityRelations.size === 0) {\n dontFragmentRelations.delete(entityId);\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 dontFragment components (they mark the archetype)\n if (isDontFragmentWildcard(componentType)) {\n regularTypes.push(componentType);\n continue;\n }\n\n // Skip specific dontFragment relations from archetype signature\n if (isDontFragmentRelation(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 * 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 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\nexport type EntityReferencesMap = Map<EntityId, MultiMap<EntityId, EntityId>>;\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\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\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 * Encode an internal EntityId into a SerializedEntityId for snapshots\n */\nexport function encodeEntityId(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 * 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 encodeEntityId,\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 const entities: SerializedEntity[] = [];\n\n for (const archetype of archetypes) {\n const dumpedEntities = archetype.dump();\n for (const { entity, components } of dumpedEntities) {\n entities.push({\n id: encodeEntityId(entity),\n components: Array.from(components.entries()).map(([rawType, value]) => ({\n type: encodeEntityId(rawType),\n value: value === MISSING_COMPONENT ? undefined : value,\n })),\n });\n }\n }\n\n const componentEntitiesArr: SerializedEntity[] = [];\n for (const [entityId, components] of componentEntities.entries()) {\n componentEntitiesArr.push({\n id: encodeEntityId(entityId),\n components: Array.from(components.entries()).map(([rawType, value]) => ({\n type: encodeEntityId(rawType),\n value: value === MISSING_COMPONENT ? undefined : value,\n })),\n });\n }\n\n return {\n version: 1,\n entityManager: entityIdManager.serializeState(),\n entities,\n componentEntities: componentEntitiesArr,\n };\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 const componentTypes: EntityId<any>[] = [];\n\n for (const componentEntry of componentsArray) {\n const componentType = decodeSerializedId(componentEntry.type);\n componentMap.set(componentType, componentEntry.value);\n componentTypes.push(componentType);\n }\n\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 { DontFragmentStoreImpl } 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 isDontFragmentRelation,\n isDontFragmentWildcard,\n isEntityRelation,\n isExclusiveComponent,\n isWildcardRelationId,\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 { ComponentTuple, ComponentType, LifecycleCallback, LifecycleHook, LifecycleHookEntry } 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 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 /** DontFragment relation storage, shared with all Archetype instances */\n private readonly dontFragmentStore = new DontFragmentStoreImpl();\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 // 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 dontFragmentStore: this.dontFragmentStore,\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 dontFragment 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 (isDontFragmentRelation(componentType)) {\n return this.dontFragmentStore.get(entityId)?.has(componentType) ?? false;\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 hasDontFragment = isDontFragmentRelation(componentType);\n const hasComponent = inArchetype || (hasDontFragment && this.dontFragmentStore.get(entityId)?.has(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 * 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 * 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 this.commandBuffer.execute();\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 applyChangeset(this._commandCtx, entityId, currentArchetype, changeset, this.entityToArchetype, null);\n if (hasStructuralChange) {\n this.updateEntityReferences(entityId, changeset);\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 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.dontFragmentStore);\n this.archetypes.push(newArchetype);\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 (isDontFragmentWildcard(c)) return true;\n const componentId = getComponentIdFromRelationId(c);\n return componentId !== undefined && archetype.hasRelationWithComponentId(componentId);\n }\n return archetype.componentTypeSet.has(c) || isDontFragmentRelation(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 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/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 * - **`dontFragment`**: 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 will not cause 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**: When `dontFragment` is enabled, the relation's target does **not**\n * contribute to the archetype signature. Entities with different targets for the same\n * relation component share a **single archetype**, and the per-entity target data is\n * stored in a separate `DontFragmentStore` (a `Map<EntityId, Map<EntityId, any>>`).\n * A wildcard relation marker (`relation(Comp, \"*\")`) is placed in the archetype\n * 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 `dontFragment`, each target change would\n * cause 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 `dontFragment`**: 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 `dontFragment`**: Archetype count stays constant regardless of target\n * diversity. Changing a relation target is an O(1) update in the `DontFragmentStore`.\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 * @example\n * ```ts\n * // Without dontFragment: 100 entities with different parents = 100 archetypes\n * const ChildOf = component(); // default: fragmentation happens\n *\n * // With dontFragment: 100 entities with different parents = 1 archetype\n * const ChildOf = component({ dontFragment: 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 * // dontFragment: 1 archetype for all 100 entities\n * // without: 100 archetypes, one per unique parent\n * ```\n *\n * Inspired by Flecs' `DontFragment` trait.\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 dontFragmentFlags = 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 if (options.dontFragment) dontFragmentFlags.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 hasDontFragment = dontFragmentFlags.has(id);\n return {\n name: hasName ? componentNames[id] : undefined,\n exclusive: hasExclusive ? true : undefined,\n cascadeDelete: hasCascadeDelete ? true : undefined,\n dontFragment: hasDontFragment ? 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 `dontFragment`.\n *\n * When a component has `dontFragment: true`, relations using it do not cause\n * archetype fragmentation — entities with different relation targets can share\n * the same archetype. This is a fast O(1) bitset lookup.\n *\n * @param id - The component ID to check.\n * @returns `true` if the component was created with `dontFragment: true`.\n *\n * @see {@link ComponentOptions.dontFragment} for the full explanation of how\n * `dontFragment` prevents archetype fragmentation.\n */\nexport function isDontFragmentComponent(id: ComponentId<any>): boolean {\n return dontFragmentFlags.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 `isDontFragmentRelation`,\n * `isDontFragmentWildcard`, `isExclusiveRelation`, `isExclusiveWildcard`,\n * 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 `dontFragment`\n * component.\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. Relations with\n * `dontFragment` components are stored in the shared {@link DontFragmentStore} instead\n * of being part of the archetype's component type list.\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 * `dontFragment` 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 `dontFragment: true`.\n *\n * @see {@link isDontFragmentWildcard} for the wildcard variant.\n * @see {@link ComponentOptions.dontFragment} for the full explanation.\n */\nexport function isDontFragmentRelation(id: EntityId<any>): boolean {\n return checkRelationFlag(id, dontFragmentFlags, (targetId) => targetId !== WILDCARD_TARGET_ID);\n}\n\n/**\n * Check if an ID is a wildcard relation (`relation(Comp, \"*\")`) backed by a\n * `dontFragment` component.\n *\n * Wildcard markers for `dontFragment` components are placed in the archetype\n * component list so that queries can discover archetypes containing entities\n * with that relation type. This function is used in `filterRegularComponentTypes`\n * to **keep** these wildcard markers in the archetype signature while stripping\n * out specific-target `dontFragment` relations.\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 * `dontFragment` 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 `dontFragment: true`.\n *\n * @see {@link isDontFragmentRelation} for the specific-target variant.\n * @see {@link ComponentOptions.dontFragment} for the full explanation.\n */\nexport function isDontFragmentWildcard(id: EntityId<any>): boolean {\n return checkRelationFlag(id, dontFragmentFlags, (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 * 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 { DontFragmentStore } 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 * Find all relations in dontFragment data that match a component ID.\n *\n * @deprecated Prefer calling `DontFragmentStore.getRelationsForComponent` directly.\n * This helper is kept temporarily for any remaining call sites during the refactor.\n */\nexport function findMatchingDontFragmentRelations(\n dontFragmentData: Map<EntityId<any>, any> | undefined,\n componentId: EntityId<any>,\n relations: [EntityId<unknown>, any][] = [],\n): [EntityId<unknown>, any][] {\n if (!dontFragmentData) return relations;\n\n for (const [relType, data] of dontFragmentData) {\n const relDetailed = getDetailedIdType(relType);\n if (isRelationType(relDetailed) && relDetailed.componentId === componentId) {\n relations.push([relDetailed.targetId, data]);\n }\n }\n return relations;\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 * Now receives the DontFragmentStore 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 dontFragmentStore: DontFragmentStore,\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 dontFragment relations using the efficient store API (key win for X-class workload)\n if (targetComponentId !== undefined) {\n const dfMatches = dontFragmentStore.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 dontFragmentRelations: DontFragmentStore,\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 dontFragmentRelations,\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 isDontFragmentComponent,\n isWildcardRelationId,\n} from \"../entity\";\nimport { isOptionalEntityId, type ComponentTuple, type ComponentType, type LifecycleHookEntry } from \"../types\";\nimport { getOrCompute } from \"../utils/utils\";\nimport { buildCacheKey, buildSingleComponent, getWildcardRelationDataSource, isRelationType } from \"./helpers\";\nimport type { DontFragmentStore } 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 * DontFragmentStore (keyed primarily by relation ComponentId).\n * Uses optimized RelationEntry (single/multi) for the common exclusive case.\n * See store.ts for implementation details.\n */\n private dontFragmentRelations: DontFragmentStore;\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>[], dontFragmentRelations: DontFragmentStore) {\n this.componentTypes = normalizeComponentTypes(componentTypes);\n this.componentTypeSet = new Set(this.componentTypes);\n this.dontFragmentRelations = dontFragmentRelations;\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 dontFragment relations separately\n this.addDontFragmentRelations(entityId, componentData);\n }\n\n private addDontFragmentRelations(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) && isDontFragmentComponent(detailedType.componentId!)) {\n this.dontFragmentRelations.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 dontFragment relations\n const dontFragmentTuples = this.dontFragmentRelations.getAllForEntity(entityId);\n for (const [componentType, data] of dontFragmentTuples) {\n entityData.set(componentType, data);\n }\n\n return entityData;\n }\n\n /**\n * Returns all dontFragment relations for the given entity as an array of tuples.\n * This is a compatibility adapter during the store refactor.\n *\n * Prefer the new DontFragmentStore methods when possible.\n */\n getEntityDontFragmentRelations(entityId: EntityId): Map<EntityId<any>, any> | undefined {\n const tuples = this.dontFragmentRelations.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 dontFragmentTuples = this.dontFragmentRelations.getAllForEntity(entity);\n for (const [componentType, data] of dontFragmentTuples) {\n components.set(componentType, data);\n }\n\n return { entity, components };\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 dontFragment relations\n const dontFragmentTuples = this.dontFragmentRelations.getAllForEntity(entityId);\n for (const [componentType, data] of dontFragmentTuples) {\n removedData.set(componentType, data);\n }\n this.dontFragmentRelations.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 dontFragment relations (now uses the efficient per-component path)\n if (componentId !== undefined) {\n const matches = this.dontFragmentRelations.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.dontFragmentRelations.getValue(entityId, componentType);\n if (\n value !== undefined ||\n this.dontFragmentRelations.getAllForEntity(entityId).some(([t]) => t === componentType)\n ) {\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.dontFragmentRelations.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.dontFragmentRelations.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.dontFragmentRelations.getAllForEntity(entityId);\n if (all.some(([t]) => t === componentType)) {\n return { value: this.dontFragmentRelations.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) && isDontFragmentComponent(detailedType.componentId!)) {\n this.dontFragmentRelations.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.dontFragmentRelations,\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 dontFragment relations (Y-class path, acceptable cost)\n const dontFragmentTuples = this.dontFragmentRelations.getAllForEntity(entity);\n for (const [componentType, data] of dontFragmentTuples) {\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 dontFragment 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.dontFragmentRelations.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 storing dontFragment relation data.\n *\n * Storage is now primarily keyed by relation ComponentId (the \"kind\" of relation)\n * rather than by entity. This provides O(1) or near-O(1) answers for the hot\n * wildcard-related paths (hasRelationWithComponentId, wildcard materialization\n * during iteration, hook matching, etc.).\n *\n * A lightweight reverse index (entity -> Set of base ComponentIds) is maintained\n * to efficiently support the infrequent \"get all dontFragment data for this entity\"\n * operations (removeEntity, dump, getEntity, serialization).\n *\n * The interface no longer leaks internal Map structures. Callers work with\n * semantic operations only.\n */\nexport interface DontFragmentStore {\n // High-frequency operations (used by get/set/getOptional and 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 // Wildcard / filtering hot paths (X-class priority)\n hasAnyForComponent(componentId: EntityId<any>): boolean;\n getRelationsForComponent(entityId: EntityId, componentId: EntityId<any>): [target: EntityId, data: any][];\n\n // Low-frequency \"get everything for entity\" paths (Y-class, acceptable cost)\n getAllForEntity(entityId: EntityId): Array<[relationType: EntityId<any>, data: any]>;\n deleteEntity(entityId: EntityId): void;\n}\n\n/**\n * Production implementation of DontFragmentStore.\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 entirely for the vast majority of dontFragment usage.\n * - entityIndex: entityId → Set<baseComponentId>\n * Lightweight reverse index.\n */\nexport class DontFragmentStoreImpl implements DontFragmentStore {\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 * Used only by the infrequent getAllForEntity / deleteEntity paths.\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 DontFragmentStore\");\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","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 */\n execute(): void {\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\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 /**\n * Get the final component types after applying the changeset\n * @param existingComponentTypes - The current component types on the entity\n * @returns The final component types or undefined if no changes\n */\n getFinalComponentTypes(existingComponentTypes: EntityId<any>[]): EntityId<any>[] | undefined {\n const finalComponentTypes = new Set<EntityId<any>>(existingComponentTypes);\n let changed = false;\n\n // Apply removals\n for (const componentType of this.removes) {\n if (!finalComponentTypes.has(componentType)) {\n this.removes.delete(componentType);\n continue; // Component not present, skip\n }\n changed = true;\n finalComponentTypes.delete(componentType);\n }\n\n // Apply additions\n for (const componentType of this.adds.keys()) {\n if (finalComponentTypes.has(componentType)) {\n continue; // Component already present, skip\n }\n changed = true;\n finalComponentTypes.add(componentType);\n }\n\n return changed ? Array.from(finalComponentTypes) : undefined;\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 {\n getComponentIdFromRelationId,\n getDetailedIdType,\n isDontFragmentComponent,\n isRelationId,\n relation,\n} 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 isDontFragmentComponent(detailedType.componentId)\n ) {\n // For specific dontFragment 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-dontFragment 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, isDontFragmentComponent } 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 dontFragment relation types that need entity-level filtering */\n private specificDontFragmentTypes: 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 dontFragment relation types that need entity-level filtering\n this.specificDontFragmentTypes = 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 isDontFragmentComponent(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 dontFragment relations\n if (this.wildcardTypes.length === 0 && this.specificDontFragmentTypes.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 dontFragment 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 dontFragment 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 dontFragment relations\n for (const specificType of this.specificDontFragmentTypes) {\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 { DontFragmentStore } 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 isDontFragmentComponent,\n isDontFragmentRelation,\n isDontFragmentWildcard,\n isWildcardRelationId,\n relation,\n type ComponentId,\n type EntityId,\n} from \"../entity\";\n\nexport interface CommandProcessorContext {\n dontFragmentStore: DontFragmentStore;\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 dontFragment relations, ensure wildcard marker is in archetype signature\n if (isDontFragmentComponent(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 dontFragment relations stored on entity\n const dontFragmentData = archetype.getEntityDontFragmentRelations(entityId);\n if (dontFragmentData) {\n for (const componentType of dontFragmentData.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 dontFragment relations, also remove the wildcard marker\n if (isDontFragmentComponent(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 || !isDontFragmentComponent(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 dontFragmentData = archetype.getEntityDontFragmentRelations(entityId);\n if (dontFragmentData) {\n for (const otherComponentType of dontFragmentData.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 dontFragment 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.getEntityDontFragmentRelations(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 (!isDontFragmentRelation(componentType) && currentArchetype.componentTypeSet.has(componentType)) {\n return true;\n }\n }\n\n for (const componentType of changeset.adds.keys()) {\n if (!isDontFragmentRelation(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 (!isDontFragmentRelation(componentType)) {\n finalRegularTypes.delete(componentType);\n }\n }\n\n for (const [componentType] of changeset.adds) {\n if (!isDontFragmentRelation(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 dontFragment relation updates.\n if (removedComponents !== null) {\n applyDontFragmentChanges(ctx.dontFragmentStore, entityId, changeset, removedComponents);\n } else {\n applyDontFragmentChangesNoHooks(ctx.dontFragmentStore, entityId, changeset);\n }\n\n // Direct update for regular components in archetype\n for (const [componentType, component] of changeset.adds) {\n if (isDontFragmentRelation(componentType)) {\n continue;\n }\n currentArchetype.set(entityId, componentType, component);\n }\n\n return currentArchetype;\n}\n\n/**\n * No-hooks variant of applyDontFragmentChanges that skips tracking removed component data.\n *\n * Rewritten for the new DontFragmentStore interface (ComponentId-primary storage).\n */\nfunction applyDontFragmentChanges(\n dontFragmentRelations: DontFragmentStore,\n entityId: EntityId,\n changeset: ComponentChangeset,\n removedComponents: Map<EntityId<any>, any>,\n): void {\n for (const componentType of changeset.removes) {\n if (isDontFragmentRelation(componentType)) {\n const removedValue = dontFragmentRelations.getValue(entityId, componentType);\n // Record for hooks if we are actually removing something\n if (\n removedValue !== undefined ||\n dontFragmentRelations.getAllForEntity(entityId).some(([t]) => t === componentType)\n ) {\n removedComponents.set(componentType, removedValue);\n }\n dontFragmentRelations.deleteValue(entityId, componentType);\n }\n }\n\n for (const [componentType, component] of changeset.adds) {\n if (isDontFragmentRelation(componentType)) {\n dontFragmentRelations.setValue(entityId, componentType, component);\n }\n }\n}\n\nfunction applyDontFragmentChangesNoHooks(\n dontFragmentRelations: DontFragmentStore,\n entityId: EntityId,\n changeset: ComponentChangeset,\n): void {\n for (const componentType of changeset.removes) {\n if (isDontFragmentRelation(componentType)) {\n dontFragmentRelations.deleteValue(entityId, componentType);\n }\n }\n\n for (const [componentType, component] of changeset.adds) {\n if (isDontFragmentRelation(componentType)) {\n dontFragmentRelations.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 dontFragment components (they mark the archetype)\n if (isDontFragmentWildcard(componentType)) {\n regularTypes.push(componentType);\n continue;\n }\n\n // Skip specific dontFragment relations from archetype signature\n if (isDontFragmentRelation(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 * 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 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 * Encode an internal EntityId into a SerializedEntityId for snapshots\n */\nexport function encodeEntityId(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 * 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 encodeEntityId,\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 const entities: SerializedEntity[] = [];\n\n for (const archetype of archetypes) {\n const dumpedEntities = archetype.dump();\n for (const { entity, components } of dumpedEntities) {\n entities.push({\n id: encodeEntityId(entity),\n components: Array.from(components.entries()).map(([rawType, value]) => ({\n type: encodeEntityId(rawType),\n value: value === MISSING_COMPONENT ? undefined : value,\n })),\n });\n }\n }\n\n const componentEntitiesArr: SerializedEntity[] = [];\n for (const [entityId, components] of componentEntities.entries()) {\n componentEntitiesArr.push({\n id: encodeEntityId(entityId),\n components: Array.from(components.entries()).map(([rawType, value]) => ({\n type: encodeEntityId(rawType),\n value: value === MISSING_COMPONENT ? undefined : value,\n })),\n });\n }\n\n return {\n version: 1,\n entityManager: entityIdManager.serializeState(),\n entities,\n componentEntities: componentEntitiesArr,\n };\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 const componentTypes: EntityId<any>[] = [];\n\n for (const componentEntry of componentsArray) {\n const componentType = decodeSerializedId(componentEntry.type);\n componentMap.set(componentType, componentEntry.value);\n componentTypes.push(componentType);\n }\n\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 { DontFragmentStoreImpl } 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 isDontFragmentRelation,\n isDontFragmentWildcard,\n isEntityRelation,\n isExclusiveComponent,\n isWildcardRelationId,\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 { ComponentTuple, ComponentType, LifecycleCallback, LifecycleHook, LifecycleHookEntry } 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 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 /** DontFragment relation storage, shared with all Archetype instances */\n private readonly dontFragmentStore = new DontFragmentStoreImpl();\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 // 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 dontFragmentStore: this.dontFragmentStore,\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 dontFragment 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 (isDontFragmentRelation(componentType)) {\n // Use getValue; presence check via getAllForEntity only if value can legitimately be undefined\n const val = this.dontFragmentStore.getValue(entityId, componentType);\n if (val !== undefined) return true;\n return this.dontFragmentStore.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 hasDontFragment = isDontFragmentRelation(componentType);\n const hasComponent =\n inArchetype ||\n (hasDontFragment &&\n (this.dontFragmentStore.getValue(entityId, componentType) !== undefined ||\n this.dontFragmentStore.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 * 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 * 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 this.commandBuffer.execute();\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 applyChangeset(this._commandCtx, entityId, currentArchetype, changeset, this.entityToArchetype, null);\n if (hasStructuralChange) {\n this.updateEntityReferences(entityId, changeset);\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 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.dontFragmentStore);\n this.archetypes.push(newArchetype);\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 (isDontFragmentWildcard(c)) return true;\n const componentId = getComponentIdFromRelationId(c);\n return componentId !== undefined && archetype.hasRelationWithComponentId(componentId);\n }\n return archetype.componentTypeSet.has(c) || isDontFragmentRelation(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 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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"}