@codehz/ecs 0.6.5 → 0.6.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/builder.d.mts +306 -1
- package/package.json +1 -1
- package/world.mjs +311 -3
- package/world.mjs.map +1 -1
package/world.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"world.mjs","names":["actualTargetId: number","type: \"entity-relation\" | \"component-relation\" | \"wildcard-relation\"","ComponentIdForNames: Map<string, ComponentId<any>>","componentNames: (string | undefined)[]","name: string | undefined","options: ComponentOptions | undefined","component","result: EntityId[]","result","result: Array<{\n entity: EntityId;\n components: ComponentTuple<T>;\n }>","result: T[]","relations: [EntityId<unknown>, any][]","relations: [EntityId<unknown>, any][]","result: Array<{ entity: EntityId; components: ComponentTuple<T> }>","targetId: EntityId<any>","component","regularTypes: EntityId<any>[]","component","match","result: [EntityId, any][]","componentsArray: SerializedComponent[]","componentTypes: EntityId<any>[]","queue: EntityId[]","component","requiredComponents: EntityId<any>[]","optionalComponents: EntityId<any>[]","entry: LifecycleHookEntry","entities: EntityId[]","regularComponents: EntityId<any>[]","wildcardRelations: { componentId: ComponentId<any>; relationId: EntityId<any> }[]","result: Array<{ entity: EntityId; components: any }>","result: EntityId[]","entities: SerializedEntity[]"],"sources":["../src/core/entity-types.ts","../src/core/entity-relation.ts","../src/core/entity-manager.ts","../src/utils/bit-set.ts","../src/core/component-registry.ts","../src/core/builder.ts","../src/commands/changeset.ts","../src/commands/command-buffer.ts","../src/query/filter.ts","../src/query/query.ts","../src/utils/utils.ts","../src/core/types.ts","../src/core/archetype-helpers.ts","../src/core/archetype.ts","../src/core/serialization.ts","../src/core/world-commands.ts","../src/core/world-hooks.ts","../src/utils/multi-map.ts","../src/core/world-references.ts","../src/core/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 */\nexport type EntityId<T = unknown, U = unknown> = number & {\n readonly [__componentTypeMarker]: T;\n readonly [__entityIdTypeTag]: U;\n};\n\nexport type ComponentId<T = void> = EntityId<T, \"component\">;\nexport type EntityRelationId<T = void> = EntityId<T, \"entity-relation\">;\nexport type ComponentRelationId<T = void> = EntityId<T, \"component-relation\">;\nexport type WildcardRelationId<T = void> = EntityId<T, \"wildcard-relation\">;\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 \"./entity-types\";\nimport {\n ENTITY_ID_START,\n isComponentId,\n isEntityId,\n isValidComponentId,\n RELATION_SHIFT,\n WILDCARD_TARGET_ID,\n} from \"./entity-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 another ID (entity or component)\n * @param componentId The component ID (0-1023)\n * @param targetId The target ID (entity, component, or '*' for wildcard)\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 id\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 try {\n const decoded = decodeRelationId(id as RelationId<any>);\n // Validate that componentId and targetId are valid (decodeRelationId already checks componentId)\n if (decoded.type !== \"wildcard\" && !isEntityId(decoded.targetId) && !isComponentId(decoded.targetId)) {\n return \"invalid\";\n }\n switch (decoded.type) {\n case \"entity\":\n return \"entity-relation\";\n case \"component\":\n return \"component-relation\";\n case \"wildcard\":\n return \"wildcard-relation\";\n }\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n } catch (_error) {\n return \"invalid\"; // fallback for invalid relation IDs\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 try {\n const decoded = decodeRelationId(id as RelationId<any>);\n // Validate that targetId is valid (decodeRelationId already checks componentId)\n if (decoded.type !== \"wildcard\" && !isEntityId(decoded.targetId) && !isComponentId(decoded.targetId)) {\n return { type: \"invalid\" };\n }\n let type: \"entity-relation\" | \"component-relation\" | \"wildcard-relation\";\n\n switch (decoded.type) {\n case \"entity\":\n type = \"entity-relation\";\n break;\n case \"component\":\n type = \"component-relation\";\n break;\n case \"wildcard\":\n type = \"wildcard-relation\";\n break;\n }\n\n return {\n type,\n componentId: decoded.componentId,\n targetId: decoded.targetId as any,\n };\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n } catch (_error) {\n // Invalid relation ID\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 try {\n const decoded = decodeRelationId(id as RelationId<any>);\n // Validate that targetId is valid (decodeRelationId already checks componentId)\n if (decoded.type !== \"wildcard\" && !isEntityId(decoded.targetId) && !isComponentId(decoded.targetId)) {\n return `Invalid Relation ID (${id})`;\n }\n const componentStr = `Component ID (${decoded.componentId})`;\n const targetStr =\n decoded.type === \"entity\"\n ? `Entity ID (${decoded.targetId})`\n : decoded.type === \"component\"\n ? `Component ID (${decoded.targetId})`\n : \"Wildcard (*)\";\n return `Relation ID: ${componentStr} -> ${targetStr}`;\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n } catch (_error) {\n return `Invalid Relation ID (${id})`;\n }\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 \"./entity-types\";\nimport { COMPONENT_ID_MAX, ENTITY_ID_START, isEntityId } from \"./entity-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 private freelist: Set<EntityId> = new Set();\n\n /**\n * Allocate a new entity ID\n * Uses freelist if available, otherwise increments counter\n */\n allocate(): EntityId {\n if (this.freelist.size > 0) {\n const id = this.freelist.values().next().value!;\n this.freelist.delete(id);\n return id;\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.add(id);\n }\n\n /**\n * Get the current freelist size (for debugging/monitoring)\n */\n getFreelistSize(): number {\n return this.freelist.size;\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 = new Set((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 { BitSet } from \"../utils/bit-set\";\nimport { 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\";\n\nconst globalComponentIdAllocator = new ComponentIdAllocator();\n\nconst ComponentIdForNames: Map<string, ComponentId<any>> = new Map();\n\n/**\n * Component options that define intrinsic properties\n */\nexport interface ComponentOptions {\n /**\n * Optional name for the component (for serialization/debugging)\n */\n name?: string;\n /**\n * If true, an entity can have at most one relation per base component.\n * When adding a new relation with the same base component, any existing relations\n * with that base component are automatically removed.\n * Only applicable to relation components.\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 * Only applicable to entity-relation components.\n */\n cascadeDelete?: boolean;\n /**\n * If true, relations with this component will not cause archetype fragmentation.\n * Entities with different target entities for this relation component will be stored\n * in the same archetype, preventing fragmentation when there are many different targets.\n * Only applicable to relation components.\n * Inspired by Flecs' DontFragment trait.\n */\n dontFragment?: boolean;\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);\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): ComponentId<T> {\n const id = globalComponentIdAllocator.allocate<T>();\n\n let name: string | undefined;\n let options: ComponentOptions | 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 }\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(id: ComponentId<any>): ComponentOptions {\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 };\n}\n\n/**\n * Check if a component is marked as exclusive\n * @param id The component ID\n * @returns true if the component is exclusive, false otherwise\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 * @param id The component ID\n * @returns true if the component is cascade delete, false otherwise\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 * @param id The component ID\n * @returns true if the component is dontFragment, false otherwise\n */\nexport function isDontFragmentComponent(id: ComponentId<any>): boolean {\n return dontFragmentFlags.has(id);\n}\n\n/**\n * Generic function to check relation flags with specific target conditions\n * @param id The entity/relation ID to check\n * @param flagBitSet The bitset for the flag\n * @param targetCondition Function to check target ID condition\n * @returns true if the condition is met, false otherwise\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 a relation ID is a dontFragment relation (entity-relation or component-relation with dontFragment component)\n * This is an optimized function that avoids the overhead of getDetailedIdType\n * @param id The entity/relation ID to check\n * @returns true if this is a dontFragment relation, false otherwise\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 with dontFragment component\n * This is an optimized function for filtering archetype component types\n * @param id The entity/relation ID to check\n * @returns true if this is a wildcard relation with dontFragment component, false otherwise\n */\nexport function isDontFragmentWildcard(id: EntityId<any>): boolean {\n return checkRelationFlag(id, dontFragmentFlags, (targetId) => targetId === WILDCARD_TARGET_ID);\n}\n\n/**\n * Check if a relation ID is an exclusive relation (entity-relation or component-relation with exclusive component)\n * This avoids the full getDetailedIdType overhead for hot paths\n * @param id The entity/relation ID to check\n * @returns true if this is an exclusive relation, false otherwise\n */\nexport function isExclusiveRelation(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 wildcard relation with exclusive component\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 * This is an optimized function that avoids the overhead of getDetailedIdType\n * Note: Cascade delete only applies to entity-relations (not component-relations or wildcards)\n * @param id The entity/relation ID to check\n * @returns true if this is an entity-relation with cascade delete, false otherwise\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\nexport class EntityBuilder {\n private world: World;\n private components: ComponentDef[] = [];\n\n constructor(world: World) {\n this.world = world;\n }\n\n with<T>(componentId: EntityId<T>, ...args: T extends void ? [] | [void] : [T]): this {\n const value = (args.length > 0 ? args[0] : undefined) as T;\n this.components.push({ type: \"component\", id: componentId, value });\n return this;\n }\n\n /**\n * @deprecated Use `with(componentId)` instead for void components\n */\n withTag(componentId: EntityId<void>): this {\n this.components.push({ type: \"component\", id: componentId, value: undefined as void });\n return this;\n }\n\n withRelation<T>(\n componentId: ComponentId<T>,\n targetEntity: EntityId<any>,\n ...args: T extends void ? [] | [void] : [T]\n ): this {\n const value = (args.length > 0 ? args[0] : undefined) as T;\n this.components.push({ type: \"relation\", componentId, targetId: targetEntity, value });\n return this;\n }\n\n /**\n * @deprecated Use `withRelation(componentId, targetEntity)` instead for void relations\n */\n withRelationTag(componentId: ComponentId<void>, targetEntity: EntityId<any>): this {\n this.components.push({ type: \"relation\", componentId, targetId: targetEntity, value: undefined as void });\n return this;\n }\n\n /**\n * Create an entity and enqueue components to be applied. This method\n * does NOT call `world.sync()` automatically; callers must invoke\n * `world.sync()` to apply deferred commands.\n * (Previously auto-synced; now a breaking change — buildDeferred() removed.)\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 \"../core/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 type { EntityId } from \"../core/entity\";\n\n/**\n * Command for deferred execution\n */\nexport interface Command {\n type: \"set\" | \"delete\" | \"destroy\";\n entityId: EntityId;\n componentType?: EntityId<any>;\n component?: any;\n}\n\n/**\n * Command buffer for deferred structural changes\n */\nexport class CommandBuffer {\n private commands: Command[] = [];\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 const MAX_ITERATIONS = 100;\n let iterations = 0;\n\n while (this.commands.length > 0) {\n if (iterations >= MAX_ITERATIONS) {\n throw new Error(\"Command execution exceeded maximum iterations, possible infinite loop\");\n }\n iterations++;\n\n const currentCommands = [...this.commands];\n this.commands = [];\n\n // Group commands by entity\n const entityCommands = new Map<EntityId, Command[]>();\n for (const cmd of currentCommands) {\n if (!entityCommands.has(cmd.entityId)) {\n entityCommands.set(cmd.entityId, []);\n }\n entityCommands.get(cmd.entityId)!.push(cmd);\n }\n\n // Process each entity's commands with optimization\n for (const [entityId, commands] of entityCommands) {\n this.executeEntityCommands(entityId, commands);\n }\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 { Archetype } from \"../core/archetype\";\nimport type { EntityId } from \"../core/entity\";\nimport {\n getComponentIdFromRelationId,\n getDetailedIdType,\n isDontFragmentComponent,\n isRelationId,\n relation,\n} from \"../core/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.componentTypes.includes(wildcardMarker);\n } else {\n // For regular components and non-dontFragment relations, check direct inclusion\n return archetype.componentTypes.includes(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.componentTypes.includes(type);\n }\n });\n}\n","import type { Archetype } from \"../core/archetype\";\nimport type { EntityId, WildcardRelationId } from \"../core/entity\";\nimport { getDetailedIdType, isDontFragmentComponent } from \"../core/entity\";\nimport type { ComponentTuple, ComponentType } from \"../core/types\";\nimport type { World } from \"../core/world\";\nimport { matchesComponentTypes, matchesFilter, type QueryFilter } from \"./filter\";\n\n/**\n * Query class for efficient entity queries with cached archetypes\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 /** 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 constructor(world: World, componentTypes: EntityId<any>[], filter: QueryFilter = {}) {\n this.world = world;\n this.componentTypes = [...componentTypes].sort((a, b) => a - b);\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 world for archetype updates\n world._registerQuery(this);\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 * Get all entities matching the query\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 result.push(...archetype.getEntities());\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 * Get entities with their component data\n * @param componentTypes Array of component types to retrieve\n * @returns Array of objects with entity and component data\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 const entitiesWithData = archetype.getEntitiesWithComponents(componentTypes);\n result.push(...entitiesWithData);\n }\n\n return result;\n }\n\n /**\n * Iterate over entities with their component data\n * @param componentTypes Array of component types to retrieve\n * @param callback Function called for each entity with its components\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 * Iterate over entities with their component data (generator)\n * @param componentTypes Array of component types to retrieve\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 * Get component data arrays for all matching entities\n * @param componentType The component type to retrieve\n * @returns Array of component data for all matching entities\n */\n getComponentData<T>(componentType: EntityId<T>): T[] {\n this.ensureNotDisposed();\n\n const result: T[] = [];\n for (const archetype of this.cachedArchetypes) {\n result.push(...archetype.getComponentData(componentType));\n }\n return result;\n }\n\n /**\n * Update the cached archetypes\n * Called when new archetypes are created\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 * Check if a new archetype matches this query and add to cache if it does\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 * Remove an archetype from the cached archetypes\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 full dispose called by World when refCount reaches zero.\n */\n _disposeInternal(): void {\n if (!this.isDisposed) {\n // Unregister from world (remove from notification list)\n this.world._unregisterQuery(this);\n this.cachedArchetypes = [];\n this.isDisposed = true;\n }\n }\n\n /**\n * Symbol.dispose implementation for automatic resource management\n */\n [Symbol.dispose](): void {\n this.dispose();\n }\n\n /**\n * Check if the query has been disposed\n */\n get disposed(): boolean {\n return this.isDisposed;\n }\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\n * @returns The cached or computed value\n */\nexport function getOrComputeCache<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\n/**\n * Get a value from cache or create and cache it if not present, allowing side effects during creation\n * @param cache The cache map\n * @param key The cache key\n * @param create Function to create the value if not cached (can have side effects)\n * @returns The cached or created value\n */\nexport function getOrCreateWithSideEffect<K, V>(cache: Map<K, V>, key: K, create: () => V): V {\n let value = cache.get(key);\n if (value === undefined) {\n value = create();\n cache.set(key, value);\n }\n return value;\n}\n","import type { EntityId, WildcardRelationId } from \"./entity\";\n\n/**\n * Hook types for component lifecycle events\n */\nexport interface LegacyLifecycleHook<T = unknown> {\n /**\n * Called when a component is added to an entity\n */\n on_init?: (entityId: EntityId, componentType: EntityId<T>, component: T) => void;\n /**\n * Called when a component is added to an entity\n */\n on_set?: (entityId: EntityId, componentType: EntityId<T>, component: T) => void;\n /**\n * Called when a component is deleted from an entity\n */\n on_remove?: (entityId: EntityId, componentType: EntityId<T>, component: T) => void;\n}\n\nexport interface LifecycleHook<T extends readonly ComponentType<any>[]> {\n on_init?: (entityId: EntityId, ...components: ComponentTuple<T>) => void;\n on_set?: (entityId: EntityId, ...components: ComponentTuple<T>) => void;\n on_remove?: (entityId: EntityId, ...components: ComponentTuple<T>) => void;\n}\n\n/**\n * Convenience function type for single component lifecycle events\n * Combines on_init, on_set, and on_remove into a single callback\n */\nexport type LegacyLifecycleCallback<T = unknown> = (\n type: \"init\" | \"set\" | \"remove\",\n entityId: EntityId,\n componentType: EntityId<T>,\n component: T,\n) => void;\n\n/**\n * Convenience function type for multi-component lifecycle events\n * Combines on_init, on_set, and on_remove into a single callback\n */\nexport type LifecycleCallback<T extends readonly ComponentType<any>[]> = (\n type: \"init\" | \"set\" | \"remove\",\n entityId: EntityId,\n ...components: ComponentTuple<T>\n) => void;\n\nexport type ComponentType<T> = EntityId<T> | OptionalEntityId<T>;\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 * Type helper for component tuples extracted from EntityId array\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 hook: LifecycleHook<any>;\n}\n","import { MISSING_COMPONENT } from \"./archetype\";\nimport type { ComponentId, EntityId, WildcardRelationId } from \"./entity\";\nimport { getComponentIdFromRelationId, getDetailedIdType, getIdType, getTargetIdFromRelationId } from \"./entity\";\nimport { isOptionalEntityId, type ComponentType } from \"./types\";\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 * 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): [EntityId<unknown>, any][] {\n const relations: [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 relations.push(...findMatchingDontFragmentRelations(dontFragmentData, targetComponentId));\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: Map<EntityId, Map<EntityId<any>, any>>,\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 { getOrComputeCache } from \"../utils/utils\";\nimport {\n buildCacheKey,\n buildSingleComponent,\n findMatchingDontFragmentRelations,\n getWildcardRelationDataSource,\n isRelationType,\n} from \"./archetype-helpers\";\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\";\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 * 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 * Reference to dontFragment relations storage from World\n * This allows entities with different relation targets to share the same archetype\n * Stored in World to avoid migration overhead when entities change archetypes\n */\n private dontFragmentRelations: Map<EntityId, Map<EntityId<any>, any>>;\n\n /**\n * Cache for pre-computed component data sources to avoid repeated calculations\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: Map<EntityId, Map<EntityId<any>, any>>) {\n this.componentTypes = [...componentTypes].sort((a, b) => a - b);\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 matches(componentTypes: EntityId<any>[]): boolean {\n if (this.componentTypes.length !== componentTypes.length) return false;\n const sortedTypes = [...componentTypes].sort((a, b) => a - b);\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.componentTypes.includes(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 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 relations.push(...findMatchingDontFragmentRelations(this.dontFragmentRelations.get(entityId), componentId));\n }\n\n return relations;\n }\n\n private getRegularComponent<T>(entityId: EntityId, index: number, componentType: EntityId<T>): T {\n if (this.componentTypes.includes(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.componentTypes.includes(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 getOrComputeCache(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.forEachWithComponents(componentTypes, (entity, ...components) => {\n result.push({ entity, components });\n });\n return result;\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 { 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\nexport type SerializedWorld = {\n version: number;\n entityManager: any;\n entities: 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 return { component: componentName || (detailed.componentId as number).toString(), target: detailed.targetId! };\n }\n case \"component-relation\": {\n const componentName = getComponentNameById(detailed.componentId);\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 type { ComponentChangeset } from \"../commands/changeset\";\nimport type { Command } from \"../commands/command-buffer\";\nimport type { Archetype } from \"./archetype\";\nimport {\n getComponentIdFromRelationId,\n isDontFragmentComponent,\n isDontFragmentRelation,\n isDontFragmentWildcard,\n isWildcardRelationId,\n relation,\n type ComponentId,\n type EntityId,\n} from \"./entity\";\n\nexport interface CommandProcessorContext {\n dontFragmentRelations: Map<EntityId, Map<EntityId<any>, any>>;\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\" && command.componentType) {\n processSetCommand(\n entityId,\n currentArchetype,\n command.componentType,\n command.component,\n changeset,\n handleExclusiveRelation,\n );\n } else if (command.type === \"delete\" && command.componentType) {\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.componentTypes.includes(wildcardMarker)) {\n changeset.set(wildcardMarker, undefined);\n }\n }\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 entityData = archetype.getEntity(entityId);\n if (entityData) {\n for (const [componentType] of entityData) {\n if (archetype.componentTypes.includes(componentType)) continue;\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 const entityData = archetype.getEntity(entityId);\n if (!entityData) {\n changeset.delete(wildcardMarker);\n return;\n }\n\n // Check if there are any other relations with the same component ID\n for (const [otherComponentType] of entityData) {\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 changeset.delete(wildcardMarker);\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>; newArchetype: Archetype } {\n const currentEntityData = currentArchetype.getEntity(entityId);\n const allCurrentComponentTypes = currentEntityData\n ? Array.from(currentEntityData.keys())\n : currentArchetype.componentTypes;\n\n const finalComponentTypes = changeset.getFinalComponentTypes(allCurrentComponentTypes);\n const removedComponents = new Map<EntityId<any>, any>();\n\n if (finalComponentTypes) {\n // Check if archetype-affecting components actually changed\n // (dontFragment components don't affect archetype signature)\n const currentRegularTypes = filterRegularComponentTypes(allCurrentComponentTypes);\n const finalRegularTypes = filterRegularComponentTypes(finalComponentTypes);\n const archetypeChanged = !areComponentTypesEqual(currentRegularTypes, finalRegularTypes);\n\n if (archetypeChanged) {\n // Move to new archetype (regular components changed)\n const newArchetype = moveEntityToNewArchetype(\n ctx,\n entityId,\n currentArchetype,\n finalComponentTypes,\n changeset,\n removedComponents,\n entityToArchetype,\n );\n return { removedComponents, newArchetype };\n } else {\n // Only dontFragment components changed, stay in same archetype\n updateEntityInSameArchetype(ctx, entityId, currentArchetype, changeset, removedComponents);\n }\n } else {\n // Update in same archetype\n updateEntityInSameArchetype(ctx, entityId, currentArchetype, changeset, removedComponents);\n }\n\n return { removedComponents, newArchetype: currentArchetype };\n}\n\nfunction moveEntityToNewArchetype(\n ctx: CommandProcessorContext,\n entityId: EntityId,\n currentArchetype: Archetype,\n finalComponentTypes: EntityId<any>[],\n changeset: ComponentChangeset,\n removedComponents: Map<EntityId<any>, any>,\n entityToArchetype: Map<EntityId, Archetype>,\n): Archetype {\n const newArchetype = ctx.ensureArchetype(finalComponentTypes);\n const currentComponents = currentArchetype.removeEntity(entityId)!;\n\n // Track removed components\n for (const componentType of changeset.removes) {\n removedComponents.set(componentType, currentComponents.get(componentType));\n }\n\n // Add to new archetype with updated components\n newArchetype.addEntity(entityId, changeset.applyTo(currentComponents));\n entityToArchetype.set(entityId, newArchetype);\n return newArchetype;\n}\n\nfunction updateEntityInSameArchetype(\n ctx: CommandProcessorContext,\n entityId: EntityId,\n currentArchetype: Archetype,\n changeset: ComponentChangeset,\n removedComponents: Map<EntityId<any>, any>,\n): void {\n // Process dontFragment relation changes directly on World's storage\n applyDontFragmentChanges(ctx.dontFragmentRelations, entityId, changeset, removedComponents);\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\nfunction applyDontFragmentChanges(\n dontFragmentRelations: Map<EntityId, Map<EntityId<any>, any>>,\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\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 = [...types1].sort((a, b) => a - b);\n const sorted2 = [...types2].sort((a, b) => a - b);\n return sorted1.every((v, i) => v === sorted2[i]);\n}\n","import type { Archetype } from \"./archetype\";\nimport {\n getComponentIdFromRelationId,\n getTargetIdFromRelationId,\n isWildcardRelationId,\n relation,\n type EntityId,\n} from \"./entity\";\nimport { isOptionalEntityId, type ComponentType, type LegacyLifecycleHook, type LifecycleHookEntry } from \"./types\";\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 type HooksMap = Map<EntityId<any>, Set<LegacyLifecycleHook<any>>>;\n\nexport interface HooksContext {\n hooks: HooksMap;\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 invokeHooksForComponents(ctx.hooks, entityId, addedComponents, \"on_set\");\n invokeHooksForComponents(ctx.hooks, entityId, removedComponents, \"on_remove\");\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 ctx: HooksContext,\n entityId: EntityId,\n removedComponents: Map<EntityId<any>, any>,\n oldArchetype: Archetype,\n): void {\n if (removedComponents.size === 0) return;\n\n // Trigger legacy hooks for removed components\n invokeHooksForComponents(ctx.hooks, entityId, removedComponents, \"on_remove\");\n\n // Trigger multi-component hooks - only on_remove since entity is being deleted\n for (const entry of oldArchetype.matchingMultiHooks) {\n const { hook, requiredComponents, componentTypes } = entry;\n if (!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 hook.on_remove(entityId, ...components);\n }\n}\n\nfunction invokeHooksForComponents(\n hooks: HooksMap,\n entityId: EntityId,\n components: Map<EntityId<any>, any>,\n hookType: \"on_set\" | \"on_remove\",\n): void {\n for (const [componentType, component] of components) {\n // Trigger direct component hooks\n const directHooks = hooks.get(componentType);\n if (directHooks) {\n for (const hook of directHooks) {\n hook[hookType]?.(entityId, componentType, component);\n }\n }\n\n // Trigger wildcard relation hooks\n const componentId = getComponentIdFromRelationId(componentType);\n if (componentId !== undefined) {\n const wildcardHooks = hooks.get(relation(componentId, \"*\"));\n if (wildcardHooks) {\n for (const hook of wildcardHooks) {\n hook[hookType]?.(entityId, componentType, component);\n }\n }\n }\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: triggers if any required or optional component was added/removed and entity still matches\n for (const entry of newArchetype.matchingMultiHooks) {\n const { hook, requiredComponents, optionalComponents, componentTypes } = entry;\n if (!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\n if (\n (anyRequiredAdded || anyOptionalAdded || anyOptionalRemoved) &&\n entityHasAllComponents(ctx, entityId, requiredComponents)\n ) {\n hook.on_set(entityId, ...collectMultiHookComponents(ctx, entityId, componentTypes));\n }\n }\n\n // Handle on_remove: triggers if any required component was removed and entity no longer matches\n if (removedComponents.size > 0) {\n for (const entry of oldArchetype.matchingMultiHooks) {\n const { hook, requiredComponents, componentTypes } = entry;\n if (!hook.on_remove) continue;\n\n const anyRequiredRemoved = requiredComponents.some((c) => anyComponentMatches(removedComponents, c));\n\n // Only trigger if:\n // 1. A required component was removed\n // 2. Entity matched before (had all required components)\n // 3. Entity no longer matches after removal\n if (\n anyRequiredRemoved &&\n entityHadAllComponentsBefore(ctx, entityId, requiredComponents, removedComponents) &&\n !entityHasAllComponents(ctx, entityId, requiredComponents)\n ) {\n hook.on_remove(\n entityId,\n ...collectMultiHookComponentsWithRemoved(ctx, entityId, componentTypes, removedComponents),\n );\n }\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 // (ctx.get will return an array of matching relations, empty if none exist)\n if (isWildcardRelationId(c)) {\n try {\n const wildcardData = ctx.get(entityId, c);\n return Array.isArray(wildcardData) && wildcardData.length > 0;\n } catch {\n return false;\n }\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 try {\n const wildcardData = ctx.get(entityId, c);\n return Array.isArray(wildcardData) && wildcardData.length > 0;\n } catch {\n return false;\n }\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 */\nfunction reconstructWildcardWithRemoved(\n ctx: HooksContext,\n entityId: EntityId,\n wildcardId: EntityId<any>,\n removedComponents: Map<EntityId<any>, any>,\n): [EntityId, any][] {\n const currentData = ctx.get(entityId, wildcardId);\n const result = Array.isArray(currentData) ? [...currentData] : [];\n\n // Add removed matching relations\n for (const [removedCompId, removedValue] of removedComponents.entries()) {\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 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\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): boolean {\n const set = this.map.get(key);\n if (!set) return false;\n if (arguments.length === 1) return true;\n return set.has(value as V);\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 };\nexport type { MultiMap as MultiMapType };\n","import { MultiMap } from \"../utils/multi-map\";\nimport type { EntityId } from \"./entity\";\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 { ComponentChangeset } from \"../commands/changeset\";\nimport { CommandBuffer, type Command } from \"../commands/command-buffer\";\nimport { serializeQueryFilter, type QueryFilter } from \"../query/filter\";\nimport { Query } from \"../query/query\";\nimport { getOrCreateWithSideEffect } from \"../utils/utils\";\nimport { Archetype, MISSING_COMPONENT } from \"./archetype\";\nimport { EntityBuilder } from \"./builder\";\nimport type { ComponentId, EntityId, WildcardRelationId } from \"./entity\";\nimport {\n EntityIdManager,\n getComponentIdFromRelationId,\n getDetailedIdType,\n getTargetIdFromRelationId,\n isCascadeDeleteRelation,\n isDontFragmentRelation,\n isDontFragmentWildcard,\n isEntityRelation,\n isExclusiveComponent,\n isWildcardRelationId,\n} from \"./entity\";\nimport type { SerializedComponent, SerializedEntity, SerializedWorld } from \"./serialization\";\nimport { decodeSerializedId, encodeEntityId } from \"./serialization\";\nimport type {\n ComponentTuple,\n ComponentType,\n LegacyLifecycleCallback,\n LegacyLifecycleHook,\n LifecycleCallback,\n LifecycleHook,\n LifecycleHookEntry,\n} from \"./types\";\nimport { isOptionalEntityId } from \"./types\";\nimport {\n applyChangeset,\n filterRegularComponentTypes,\n maybeRemoveWildcardMarker,\n processCommands,\n removeMatchingRelations,\n} from \"./world-commands\";\nimport {\n collectMultiHookComponents,\n triggerLifecycleHooks,\n triggerRemoveHooksForEntityDeletion,\n type HooksContext,\n} from \"./world-hooks\";\nimport {\n getEntityReferences,\n trackEntityReference,\n untrackEntityReference,\n type EntityReferencesMap,\n} from \"./world-references\";\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>, Archetype[]>();\n private entityReferences: EntityReferencesMap = new Map();\n private dontFragmentRelations: Map<EntityId, Map<EntityId<any>, any>> = new Map();\n\n // Query management\n private queries: Query[] = [];\n private queryCache = new Map<string, { query: Query; refCount: number }>();\n\n // Command execution\n private commandBuffer = new CommandBuffer((entityId, commands) => this.executeEntityCommands(entityId, commands));\n\n // Lifecycle hooks\n private legacyHooks = new Map<EntityId<any>, Set<LegacyLifecycleHook<any>>>();\n private hooks: Set<LifecycleHookEntry> = new Set();\n\n constructor(snapshot?: SerializedWorld) {\n if (snapshot && typeof snapshot === \"object\") {\n this.deserializeSnapshot(snapshot);\n }\n }\n\n private deserializeSnapshot(snapshot: SerializedWorld): void {\n if (snapshot.entityManager) {\n this.entityIdManager.deserializeState(snapshot.entityManager);\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 = this.ensureArchetype(componentTypes);\n archetype.addEntity(entityId, componentMap);\n this.entityToArchetype.set(entityId, archetype);\n\n for (const compType of componentTypes) {\n const detailedType = getDetailedIdType(compType);\n if (detailedType.type === \"entity-relation\") {\n trackEntityReference(this.entityReferences, entityId, compType, detailedType.targetId!);\n } else if (detailedType.type === \"entity\") {\n trackEntityReference(this.entityReferences, entityId, compType, compType);\n }\n }\n }\n }\n }\n\n private createArchetypeSignature(componentTypes: EntityId<any>[]): string {\n return componentTypes.join(\",\");\n }\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 private destroyEntityImmediate(entityId: EntityId): void {\n const queue: EntityId[] = [entityId];\n const visited = new Set<EntityId>();\n\n while (queue.length > 0) {\n const cur = queue.shift()!;\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(this.createHooksContext(), cur, removedComponents, archetype);\n\n this.cleanupArchetypesReferencingEntity(cur);\n this.entityIdManager.deallocate(cur);\n }\n }\n\n exists(entityId: EntityId): boolean {\n return this.entityToArchetype.has(entityId);\n }\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 if (!this.exists(entityId)) {\n throw new Error(`Entity ${entityId} does not exist`);\n }\n\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 this.commandBuffer.set(entityId, componentType, component);\n }\n\n remove<T>(entityId: EntityId, componentType: EntityId<T>): void {\n if (!this.exists(entityId)) {\n throw new Error(`Entity ${entityId} does not exist`);\n }\n\n const detailedType = getDetailedIdType(componentType);\n if (detailedType.type === \"invalid\") {\n throw new Error(`Invalid component type: ${componentType}`);\n }\n\n this.commandBuffer.remove(entityId, componentType);\n }\n\n delete(entityId: EntityId): void {\n this.commandBuffer.delete(entityId);\n }\n\n has<T>(entityId: EntityId, componentType: EntityId<T>): boolean {\n const archetype = this.entityToArchetype.get(entityId);\n if (!archetype) return false;\n\n if (archetype.componentTypes.includes(componentType)) return true;\n\n if (isDontFragmentRelation(componentType)) {\n return this.dontFragmentRelations.get(entityId)?.has(componentType) ?? false;\n }\n\n return false;\n }\n\n get<T>(entityId: EntityId, componentType: WildcardRelationId<T>): [EntityId<unknown>, T][];\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 archetype = this.entityToArchetype.get(entityId);\n if (!archetype) {\n throw new Error(`Entity ${entityId} does not exist`);\n }\n\n if (componentType >= 0 || componentType % 2 ** 42 !== 0) {\n const inArchetype = archetype.componentTypes.includes(componentType);\n const hasDontFragment = isDontFragmentRelation(componentType);\n const hasComponent =\n inArchetype || (hasDontFragment && this.dontFragmentRelations.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);\n }\n\n getOptional<T>(entityId: EntityId, componentType: EntityId<T>): { value: T } | undefined {\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 any);\n if (Array.isArray(wildcardData) && wildcardData.length > 0) {\n return { value: wildcardData as T };\n }\n return undefined;\n }\n\n return archetype.getOptional(entityId, componentType);\n }\n\n /**\n * @deprecated use array overload with LifecycleCallback\n */\n hook<T>(componentType: EntityId<T>, hook: LegacyLifecycleHook<T> | LegacyLifecycleCallback<T>): () => void;\n hook<const T extends readonly ComponentType<any>[]>(\n componentTypes: T,\n hook: LifecycleHook<T> | LifecycleCallback<T>,\n ): () => void;\n hook(\n componentTypesOrSingle: EntityId<any> | readonly ComponentType<any>[],\n hook: LegacyLifecycleHook<any> | LifecycleHook<any> | LegacyLifecycleCallback<any> | LifecycleCallback<any>,\n ): () => void {\n // Normalize callback functions to hook objects\n if (typeof hook === \"function\") {\n if (Array.isArray(componentTypesOrSingle)) {\n const callback = hook as LifecycleCallback<any>;\n hook = {\n on_init: (entityId, ...components) => callback(\"init\", entityId, ...components),\n on_set: (entityId, ...components) => callback(\"set\", entityId, ...components),\n on_remove: (entityId, ...components) => callback(\"remove\", entityId, ...components),\n } as LifecycleHook<any>;\n } else {\n const callback = hook as LegacyLifecycleCallback<any>;\n hook = {\n on_init: (entityId, componentType, component) => callback(\"init\", entityId, componentType, component),\n on_set: (entityId, componentType, component) => callback(\"set\", entityId, componentType, component),\n on_remove: (entityId, componentType, component) => callback(\"remove\", entityId, componentType, component),\n } as LegacyLifecycleHook<any>;\n }\n }\n\n if (Array.isArray(componentTypesOrSingle)) {\n const componentTypes = componentTypesOrSingle as readonly ComponentType<any>[];\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 hook: hook as LifecycleHook<any>,\n };\n this.hooks.add(entry);\n\n // Add to archetypes\n for (const archetype of this.archetypes) {\n if (this.archetypeMatchesHook(archetype, entry)) {\n archetype.matchingMultiHooks.add(entry);\n }\n }\n\n const multiHook = hook as LifecycleHook<any>;\n if (multiHook.on_init !== undefined) {\n const matchingArchetypes = this.getMatchingArchetypes(requiredComponents);\n for (const archetype of matchingArchetypes) {\n for (const entityId of archetype.getEntities()) {\n const components = collectMultiHookComponents(this.createHooksContext(), entityId, componentTypes);\n multiHook.on_init(entityId, ...components);\n }\n }\n }\n\n return () => {\n this.hooks.delete(entry);\n for (const archetype of this.archetypes) {\n archetype.matchingMultiHooks.delete(entry);\n }\n };\n } else {\n const componentType = componentTypesOrSingle as EntityId<any>;\n if (!this.legacyHooks.has(componentType)) {\n this.legacyHooks.set(componentType, new Set());\n }\n const legacyHook = hook as LegacyLifecycleHook<any>;\n this.legacyHooks.get(componentType)!.add(legacyHook);\n\n if (legacyHook.on_init !== undefined) {\n this.archetypesByComponent.get(componentType)?.forEach((archetype) => {\n const entities = archetype.getEntityToIndexMap();\n const componentData = archetype.getComponentData<any>(componentType);\n for (const [entity, index] of entities) {\n const data = componentData[index];\n const value = data === MISSING_COMPONENT ? undefined : data;\n legacyHook.on_init?.(entity, componentType, value);\n }\n });\n }\n\n return () => {\n const hooks = this.legacyHooks.get(componentType);\n if (hooks) {\n hooks.delete(legacyHook);\n if (hooks.size === 0) {\n this.legacyHooks.delete(componentType);\n }\n }\n };\n }\n }\n\n /** @deprecated use the unsubscribe function returned by hook() instead */\n unhook<T>(componentType: EntityId<T>, hook: LegacyLifecycleHook<T>): void;\n /** @deprecated use the unsubscribe function returned by hook() instead */\n unhook<const T extends readonly ComponentType<any>[]>(componentTypes: T, hook: LifecycleHook<T>): void;\n /** @deprecated use the unsubscribe function returned by hook() instead */\n unhook(\n componentTypesOrSingle: EntityId<any> | readonly ComponentType<any>[],\n hook: LegacyLifecycleHook<any> | LifecycleHook<any>,\n ): void {\n // Note: Callback functions passed to hook() are converted to hook objects internally,\n // so unhook() only accepts the original hook object references.\n if (Array.isArray(componentTypesOrSingle)) {\n for (const entry of this.hooks) {\n if (entry.hook === hook) {\n this.hooks.delete(entry);\n for (const archetype of this.archetypes) {\n archetype.matchingMultiHooks.delete(entry);\n }\n break;\n }\n }\n } else {\n const componentType = componentTypesOrSingle as EntityId<any>;\n const hooks = this.legacyHooks.get(componentType);\n if (hooks) {\n hooks.delete(hook as LegacyLifecycleHook<any>);\n if (hooks.size === 0) {\n this.legacyHooks.delete(componentType);\n }\n }\n }\n }\n\n sync(): void {\n this.commandBuffer.execute();\n }\n\n createQuery(componentTypes: EntityId<any>[], filter: QueryFilter = {}): Query {\n const sortedTypes = [...componentTypes].sort((a, b) => a - b);\n const filterKey = serializeQueryFilter(filter);\n const key = `${this.createArchetypeSignature(sortedTypes)}${filterKey ? `|${filterKey}` : \"\"}`;\n\n const cached = this.queryCache.get(key);\n if (cached) {\n cached.refCount++;\n return cached.query;\n }\n\n const query = new Query(this, sortedTypes, filter);\n this.queryCache.set(key, { query, refCount: 1 });\n return query;\n }\n\n spawn(): EntityBuilder {\n return new EntityBuilder(this);\n }\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 _registerQuery(query: Query): void {\n this.queries.push(query);\n }\n\n _unregisterQuery(query: Query): void {\n const index = this.queries.indexOf(query);\n if (index !== -1) {\n this.queries.splice(index, 1);\n }\n }\n\n releaseQuery(query: Query): void {\n for (const [k, v] of this.queryCache.entries()) {\n if (v.query === query) {\n v.refCount--;\n if (v.refCount <= 0) {\n this.queryCache.delete(k);\n this._unregisterQuery(query);\n v.query._disposeInternal();\n }\n return;\n }\n }\n }\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 archetypesWithMarker = this.archetypesByComponent.get(relationId) || [];\n matchingArchetypes =\n matchingArchetypes.length === 0\n ? archetypesWithMarker\n : matchingArchetypes.filter(\n (a) => archetypesWithMarker.includes(a) || a.hasRelationWithComponentId(componentId),\n );\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) return this.archetypesByComponent.get(componentTypes[0]!) || [];\n\n const archetypeLists = componentTypes.map((type) => this.archetypesByComponent.get(type) || []);\n const firstList = archetypeLists[0]!;\n return firstList.filter((archetype) => archetypeLists.slice(1).every((list) => list.includes(archetype)));\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 result.push(...archetype.getEntitiesWithComponents(componentTypes as EntityId<any>[]));\n }\n return result;\n } else {\n const result: EntityId[] = [];\n for (const archetype of matchingArchetypes) {\n result.push(...archetype.getEntities());\n }\n return result;\n }\n }\n\n executeEntityCommands(entityId: EntityId, commands: Command[]): ComponentChangeset {\n const changeset = new ComponentChangeset();\n\n if (commands.some((cmd) => cmd.type === \"destroy\")) {\n this.destroyEntityImmediate(entityId);\n return changeset;\n }\n\n const currentArchetype = this.entityToArchetype.get(entityId);\n if (!currentArchetype) return changeset;\n\n processCommands(entityId, currentArchetype, commands, changeset, (eid, arch, compId) => {\n if (isExclusiveComponent(compId)) {\n removeMatchingRelations(eid, arch, compId, changeset);\n }\n });\n\n const { removedComponents, newArchetype } = applyChangeset(\n { dontFragmentRelations: this.dontFragmentRelations, ensureArchetype: (ct) => this.ensureArchetype(ct) },\n entityId,\n currentArchetype,\n changeset,\n this.entityToArchetype,\n );\n\n this.updateEntityReferences(entityId, changeset);\n triggerLifecycleHooks(\n this.createHooksContext(),\n entityId,\n changeset.adds,\n removedComponents,\n currentArchetype,\n newArchetype,\n );\n\n return changeset;\n }\n\n private createHooksContext(): HooksContext {\n return {\n hooks: this.legacyHooks,\n multiHooks: this.hooks,\n has: (eid, ct) => this.has(eid, ct),\n get: (eid, ct) => this.get(eid, ct),\n getOptional: (eid, ct) => this.getOptional(eid, ct),\n };\n }\n\n 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 = new ComponentChangeset();\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 { dontFragmentRelations: this.dontFragmentRelations, ensureArchetype: (ct) => this.ensureArchetype(ct) },\n entityId,\n sourceArchetype,\n changeset,\n this.entityToArchetype,\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 >= 1024) {\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 >= 1024) {\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 = regularTypes.sort((a, b) => a - b);\n const hashKey = this.createArchetypeSignature(sortedTypes);\n\n return getOrCreateWithSideEffect(this.archetypeBySignature, hashKey, () => this.createNewArchetype(sortedTypes));\n }\n\n private createNewArchetype(componentTypes: EntityId<any>[]): Archetype {\n const newArchetype = new Archetype(componentTypes, this.dontFragmentRelations);\n this.archetypes.push(newArchetype);\n\n for (const componentType of componentTypes) {\n const archetypes = this.archetypesByComponent.get(componentType) || [];\n archetypes.push(newArchetype);\n this.archetypesByComponent.set(componentType, archetypes);\n }\n\n for (const query of this.queries) {\n query.checkNewArchetype(newArchetype);\n }\n\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 }\n }\n }\n\n private archetypeMatchesHook(archetype: Archetype, entry: LifecycleHookEntry): boolean {\n return 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.componentTypes.includes(c) || isDontFragmentRelation(c);\n });\n }\n\n private archetypeReferencesEntity(archetype: Archetype, entityId: EntityId): boolean {\n return archetype.componentTypes.some(\n (ct) => ct === entityId || (isEntityRelation(ct) && getTargetIdFromRelationId(ct) === entityId),\n );\n }\n\n private cleanupArchetypesReferencingEntity(entityId: EntityId): void {\n for (let i = this.archetypes.length - 1; i >= 0; i--) {\n const archetype = this.archetypes[i]!;\n if (archetype.getEntities().length === 0 && this.archetypeReferencesEntity(archetype, entityId)) {\n this.removeArchetype(archetype);\n }\n }\n }\n\n private removeArchetype(archetype: Archetype): void {\n const index = this.archetypes.indexOf(archetype);\n if (index !== -1) {\n this.archetypes.splice(index, 1);\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 const compIndex = archetypes.indexOf(archetype);\n if (compIndex !== -1) {\n archetypes.splice(compIndex, 1);\n if (archetypes.length === 0) {\n this.archetypesByComponent.delete(componentType);\n }\n }\n }\n }\n\n for (const query of this.queries) {\n query.removeArchetype(archetype);\n }\n }\n\n serialize(): SerializedWorld {\n const entities: SerializedEntity[] = [];\n\n for (const archetype of this.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 return {\n version: 1,\n entityManager: this.entityIdManager.serializeState(),\n entities,\n };\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"world.mjs","names":["actualTargetId: number","type: \"entity-relation\" | \"component-relation\" | \"wildcard-relation\"","ComponentIdForNames: Map<string, ComponentId<any>>","componentNames: (string | undefined)[]","name: string | undefined","options: ComponentOptions | undefined","component","result: EntityId[]","result","result: Array<{\n entity: EntityId;\n components: ComponentTuple<T>;\n }>","result: T[]","relations: [EntityId<unknown>, any][]","relations: [EntityId<unknown>, any][]","result: Array<{ entity: EntityId; components: ComponentTuple<T> }>","targetId: EntityId<any>","component","regularTypes: EntityId<any>[]","component","match","result: [EntityId, any][]","componentsArray: SerializedComponent[]","componentTypes: EntityId<any>[]","queue: EntityId[]","component","data","relations: [EntityId<unknown>, any][]","requiredComponents: EntityId<any>[]","optionalComponents: EntityId<any>[]","entry: LifecycleHookEntry","entities: EntityId[]","regularComponents: EntityId<any>[]","wildcardRelations: { componentId: ComponentId<any>; relationId: EntityId<any> }[]","result: Array<{ entity: EntityId; components: any }>","result: EntityId[]","entities: SerializedEntity[]","componentEntities: SerializedEntity[]"],"sources":["../src/core/entity-types.ts","../src/core/entity-relation.ts","../src/core/entity-manager.ts","../src/utils/bit-set.ts","../src/core/component-registry.ts","../src/core/builder.ts","../src/commands/changeset.ts","../src/commands/command-buffer.ts","../src/query/filter.ts","../src/query/query.ts","../src/utils/utils.ts","../src/core/types.ts","../src/core/archetype-helpers.ts","../src/core/archetype.ts","../src/core/serialization.ts","../src/core/world-commands.ts","../src/core/world-hooks.ts","../src/utils/multi-map.ts","../src/core/world-references.ts","../src/core/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 */\nexport type EntityId<T = unknown, U = unknown> = number & {\n readonly [__componentTypeMarker]: T;\n readonly [__entityIdTypeTag]: U;\n};\n\nexport type ComponentId<T = void> = EntityId<T, \"component\">;\nexport type EntityRelationId<T = void> = EntityId<T, \"entity-relation\">;\nexport type ComponentRelationId<T = void> = EntityId<T, \"component-relation\">;\nexport type WildcardRelationId<T = void> = EntityId<T, \"wildcard-relation\">;\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 \"./entity-types\";\nimport {\n ENTITY_ID_START,\n isComponentId,\n isEntityId,\n isValidComponentId,\n RELATION_SHIFT,\n WILDCARD_TARGET_ID,\n} from \"./entity-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 another ID (entity or component)\n * @param componentId The component ID (0-1023)\n * @param targetId The target ID (entity, component, or '*' for wildcard)\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 id\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 try {\n const decoded = decodeRelationId(id as RelationId<any>);\n // Validate that componentId and targetId are valid (decodeRelationId already checks componentId)\n if (decoded.type !== \"wildcard\" && !isEntityId(decoded.targetId) && !isComponentId(decoded.targetId)) {\n return \"invalid\";\n }\n switch (decoded.type) {\n case \"entity\":\n return \"entity-relation\";\n case \"component\":\n return \"component-relation\";\n case \"wildcard\":\n return \"wildcard-relation\";\n }\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n } catch (_error) {\n return \"invalid\"; // fallback for invalid relation IDs\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 try {\n const decoded = decodeRelationId(id as RelationId<any>);\n // Validate that targetId is valid (decodeRelationId already checks componentId)\n if (decoded.type !== \"wildcard\" && !isEntityId(decoded.targetId) && !isComponentId(decoded.targetId)) {\n return { type: \"invalid\" };\n }\n let type: \"entity-relation\" | \"component-relation\" | \"wildcard-relation\";\n\n switch (decoded.type) {\n case \"entity\":\n type = \"entity-relation\";\n break;\n case \"component\":\n type = \"component-relation\";\n break;\n case \"wildcard\":\n type = \"wildcard-relation\";\n break;\n }\n\n return {\n type,\n componentId: decoded.componentId,\n targetId: decoded.targetId as any,\n };\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n } catch (_error) {\n // Invalid relation ID\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 try {\n const decoded = decodeRelationId(id as RelationId<any>);\n // Validate that targetId is valid (decodeRelationId already checks componentId)\n if (decoded.type !== \"wildcard\" && !isEntityId(decoded.targetId) && !isComponentId(decoded.targetId)) {\n return `Invalid Relation ID (${id})`;\n }\n const componentStr = `Component ID (${decoded.componentId})`;\n const targetStr =\n decoded.type === \"entity\"\n ? `Entity ID (${decoded.targetId})`\n : decoded.type === \"component\"\n ? `Component ID (${decoded.targetId})`\n : \"Wildcard (*)\";\n return `Relation ID: ${componentStr} -> ${targetStr}`;\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n } catch (_error) {\n return `Invalid Relation ID (${id})`;\n }\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 \"./entity-types\";\nimport { COMPONENT_ID_MAX, ENTITY_ID_START, isEntityId } from \"./entity-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 private freelist: Set<EntityId> = new Set();\n\n /**\n * Allocate a new entity ID\n * Uses freelist if available, otherwise increments counter\n */\n allocate(): EntityId {\n if (this.freelist.size > 0) {\n const id = this.freelist.values().next().value!;\n this.freelist.delete(id);\n return id;\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.add(id);\n }\n\n /**\n * Get the current freelist size (for debugging/monitoring)\n */\n getFreelistSize(): number {\n return this.freelist.size;\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 = new Set((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 { BitSet } from \"../utils/bit-set\";\nimport { 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\";\n\nconst globalComponentIdAllocator = new ComponentIdAllocator();\n\nconst ComponentIdForNames: Map<string, ComponentId<any>> = new Map();\n\n/**\n * Component options that define intrinsic properties\n */\nexport interface ComponentOptions {\n /**\n * Optional name for the component (for serialization/debugging)\n */\n name?: string;\n /**\n * If true, an entity can have at most one relation per base component.\n * When adding a new relation with the same base component, any existing relations\n * with that base component are automatically removed.\n * Only applicable to relation components.\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 * Only applicable to entity-relation components.\n */\n cascadeDelete?: boolean;\n /**\n * If true, relations with this component will not cause archetype fragmentation.\n * Entities with different target entities for this relation component will be stored\n * in the same archetype, preventing fragmentation when there are many different targets.\n * Only applicable to relation components.\n * Inspired by Flecs' DontFragment trait.\n */\n dontFragment?: boolean;\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);\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): ComponentId<T> {\n const id = globalComponentIdAllocator.allocate<T>();\n\n let name: string | undefined;\n let options: ComponentOptions | 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 }\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(id: ComponentId<any>): ComponentOptions {\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 };\n}\n\n/**\n * Check if a component is marked as exclusive\n * @param id The component ID\n * @returns true if the component is exclusive, false otherwise\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 * @param id The component ID\n * @returns true if the component is cascade delete, false otherwise\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 * @param id The component ID\n * @returns true if the component is dontFragment, false otherwise\n */\nexport function isDontFragmentComponent(id: ComponentId<any>): boolean {\n return dontFragmentFlags.has(id);\n}\n\n/**\n * Generic function to check relation flags with specific target conditions\n * @param id The entity/relation ID to check\n * @param flagBitSet The bitset for the flag\n * @param targetCondition Function to check target ID condition\n * @returns true if the condition is met, false otherwise\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 a relation ID is a dontFragment relation (entity-relation or component-relation with dontFragment component)\n * This is an optimized function that avoids the overhead of getDetailedIdType\n * @param id The entity/relation ID to check\n * @returns true if this is a dontFragment relation, false otherwise\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 with dontFragment component\n * This is an optimized function for filtering archetype component types\n * @param id The entity/relation ID to check\n * @returns true if this is a wildcard relation with dontFragment component, false otherwise\n */\nexport function isDontFragmentWildcard(id: EntityId<any>): boolean {\n return checkRelationFlag(id, dontFragmentFlags, (targetId) => targetId === WILDCARD_TARGET_ID);\n}\n\n/**\n * Check if a relation ID is an exclusive relation (entity-relation or component-relation with exclusive component)\n * This avoids the full getDetailedIdType overhead for hot paths\n * @param id The entity/relation ID to check\n * @returns true if this is an exclusive relation, false otherwise\n */\nexport function isExclusiveRelation(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 wildcard relation with exclusive component\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 * This is an optimized function that avoids the overhead of getDetailedIdType\n * Note: Cascade delete only applies to entity-relations (not component-relations or wildcards)\n * @param id The entity/relation ID to check\n * @returns true if this is an entity-relation with cascade delete, false otherwise\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\nexport class EntityBuilder {\n private world: World;\n private components: ComponentDef[] = [];\n\n constructor(world: World) {\n this.world = world;\n }\n\n with<T>(componentId: EntityId<T>, ...args: T extends void ? [] | [void] : [T]): this {\n const value = (args.length > 0 ? args[0] : undefined) as T;\n this.components.push({ type: \"component\", id: componentId, value });\n return this;\n }\n\n /**\n * @deprecated Use `with(componentId)` instead for void components\n */\n withTag(componentId: EntityId<void>): this {\n this.components.push({ type: \"component\", id: componentId, value: undefined as void });\n return this;\n }\n\n withRelation<T>(\n componentId: ComponentId<T>,\n targetEntity: EntityId<any>,\n ...args: T extends void ? [] | [void] : [T]\n ): this {\n const value = (args.length > 0 ? args[0] : undefined) as T;\n this.components.push({ type: \"relation\", componentId, targetId: targetEntity, value });\n return this;\n }\n\n /**\n * @deprecated Use `withRelation(componentId, targetEntity)` instead for void relations\n */\n withRelationTag(componentId: ComponentId<void>, targetEntity: EntityId<any>): this {\n this.components.push({ type: \"relation\", componentId, targetId: targetEntity, value: undefined as void });\n return this;\n }\n\n /**\n * Create an entity and enqueue components to be applied. This method\n * does NOT call `world.sync()` automatically; callers must invoke\n * `world.sync()` to apply deferred commands.\n * (Previously auto-synced; now a breaking change — buildDeferred() removed.)\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 \"../core/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 type { EntityId } from \"../core/entity\";\n\n/**\n * Command for deferred execution\n */\nexport interface Command {\n type: \"set\" | \"delete\" | \"destroy\";\n entityId: EntityId;\n componentType?: EntityId<any>;\n component?: any;\n}\n\n/**\n * Command buffer for deferred structural changes\n */\nexport class CommandBuffer {\n private commands: Command[] = [];\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 const MAX_ITERATIONS = 100;\n let iterations = 0;\n\n while (this.commands.length > 0) {\n if (iterations >= MAX_ITERATIONS) {\n throw new Error(\"Command execution exceeded maximum iterations, possible infinite loop\");\n }\n iterations++;\n\n const currentCommands = [...this.commands];\n this.commands = [];\n\n // Group commands by entity\n const entityCommands = new Map<EntityId, Command[]>();\n for (const cmd of currentCommands) {\n if (!entityCommands.has(cmd.entityId)) {\n entityCommands.set(cmd.entityId, []);\n }\n entityCommands.get(cmd.entityId)!.push(cmd);\n }\n\n // Process each entity's commands with optimization\n for (const [entityId, commands] of entityCommands) {\n this.executeEntityCommands(entityId, commands);\n }\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 { Archetype } from \"../core/archetype\";\nimport type { EntityId } from \"../core/entity\";\nimport {\n getComponentIdFromRelationId,\n getDetailedIdType,\n isDontFragmentComponent,\n isRelationId,\n relation,\n} from \"../core/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.componentTypes.includes(wildcardMarker);\n } else {\n // For regular components and non-dontFragment relations, check direct inclusion\n return archetype.componentTypes.includes(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.componentTypes.includes(type);\n }\n });\n}\n","import type { Archetype } from \"../core/archetype\";\nimport type { EntityId, WildcardRelationId } from \"../core/entity\";\nimport { getDetailedIdType, isDontFragmentComponent } from \"../core/entity\";\nimport type { ComponentTuple, ComponentType } from \"../core/types\";\nimport type { World } from \"../core/world\";\nimport { matchesComponentTypes, matchesFilter, type QueryFilter } from \"./filter\";\n\n/**\n * Query class for efficient entity queries with cached archetypes\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 /** 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 constructor(world: World, componentTypes: EntityId<any>[], filter: QueryFilter = {}) {\n this.world = world;\n this.componentTypes = [...componentTypes].sort((a, b) => a - b);\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 world for archetype updates\n world._registerQuery(this);\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 * Get all entities matching the query\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 result.push(...archetype.getEntities());\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 * Get entities with their component data\n * @param componentTypes Array of component types to retrieve\n * @returns Array of objects with entity and component data\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 const entitiesWithData = archetype.getEntitiesWithComponents(componentTypes);\n result.push(...entitiesWithData);\n }\n\n return result;\n }\n\n /**\n * Iterate over entities with their component data\n * @param componentTypes Array of component types to retrieve\n * @param callback Function called for each entity with its components\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 * Iterate over entities with their component data (generator)\n * @param componentTypes Array of component types to retrieve\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 * Get component data arrays for all matching entities\n * @param componentType The component type to retrieve\n * @returns Array of component data for all matching entities\n */\n getComponentData<T>(componentType: EntityId<T>): T[] {\n this.ensureNotDisposed();\n\n const result: T[] = [];\n for (const archetype of this.cachedArchetypes) {\n result.push(...archetype.getComponentData(componentType));\n }\n return result;\n }\n\n /**\n * Update the cached archetypes\n * Called when new archetypes are created\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 * Check if a new archetype matches this query and add to cache if it does\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 * Remove an archetype from the cached archetypes\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 full dispose called by World when refCount reaches zero.\n */\n _disposeInternal(): void {\n if (!this.isDisposed) {\n // Unregister from world (remove from notification list)\n this.world._unregisterQuery(this);\n this.cachedArchetypes = [];\n this.isDisposed = true;\n }\n }\n\n /**\n * Symbol.dispose implementation for automatic resource management\n */\n [Symbol.dispose](): void {\n this.dispose();\n }\n\n /**\n * Check if the query has been disposed\n */\n get disposed(): boolean {\n return this.isDisposed;\n }\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\n * @returns The cached or computed value\n */\nexport function getOrComputeCache<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\n/**\n * Get a value from cache or create and cache it if not present, allowing side effects during creation\n * @param cache The cache map\n * @param key The cache key\n * @param create Function to create the value if not cached (can have side effects)\n * @returns The cached or created value\n */\nexport function getOrCreateWithSideEffect<K, V>(cache: Map<K, V>, key: K, create: () => V): V {\n let value = cache.get(key);\n if (value === undefined) {\n value = create();\n cache.set(key, value);\n }\n return value;\n}\n","import type { EntityId, WildcardRelationId } from \"./entity\";\n\n/**\n * Hook types for component lifecycle events\n */\nexport interface LegacyLifecycleHook<T = unknown> {\n /**\n * Called when a component is added to an entity\n */\n on_init?: (entityId: EntityId, componentType: EntityId<T>, component: T) => void;\n /**\n * Called when a component is added to an entity\n */\n on_set?: (entityId: EntityId, componentType: EntityId<T>, component: T) => void;\n /**\n * Called when a component is deleted from an entity\n */\n on_remove?: (entityId: EntityId, componentType: EntityId<T>, component: T) => void;\n}\n\nexport interface LifecycleHook<T extends readonly ComponentType<any>[]> {\n on_init?: (entityId: EntityId, ...components: ComponentTuple<T>) => void;\n on_set?: (entityId: EntityId, ...components: ComponentTuple<T>) => void;\n on_remove?: (entityId: EntityId, ...components: ComponentTuple<T>) => void;\n}\n\n/**\n * Convenience function type for single component lifecycle events\n * Combines on_init, on_set, and on_remove into a single callback\n */\nexport type LegacyLifecycleCallback<T = unknown> = (\n type: \"init\" | \"set\" | \"remove\",\n entityId: EntityId,\n componentType: EntityId<T>,\n component: T,\n) => void;\n\n/**\n * Convenience function type for multi-component lifecycle events\n * Combines on_init, on_set, and on_remove into a single callback\n */\nexport type LifecycleCallback<T extends readonly ComponentType<any>[]> = (\n type: \"init\" | \"set\" | \"remove\",\n entityId: EntityId,\n ...components: ComponentTuple<T>\n) => void;\n\nexport type ComponentType<T> = EntityId<T> | OptionalEntityId<T>;\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 * Type helper for component tuples extracted from EntityId array\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 hook: LifecycleHook<any>;\n}\n","import { MISSING_COMPONENT } from \"./archetype\";\nimport type { ComponentId, EntityId, WildcardRelationId } from \"./entity\";\nimport { getComponentIdFromRelationId, getDetailedIdType, getIdType, getTargetIdFromRelationId } from \"./entity\";\nimport { isOptionalEntityId, type ComponentType } from \"./types\";\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 * 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): [EntityId<unknown>, any][] {\n const relations: [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 relations.push(...findMatchingDontFragmentRelations(dontFragmentData, targetComponentId));\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: Map<EntityId, Map<EntityId<any>, any>>,\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 { getOrComputeCache } from \"../utils/utils\";\nimport {\n buildCacheKey,\n buildSingleComponent,\n findMatchingDontFragmentRelations,\n getWildcardRelationDataSource,\n isRelationType,\n} from \"./archetype-helpers\";\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\";\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 * 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 * Reference to dontFragment relations storage from World\n * This allows entities with different relation targets to share the same archetype\n * Stored in World to avoid migration overhead when entities change archetypes\n */\n private dontFragmentRelations: Map<EntityId, Map<EntityId<any>, any>>;\n\n /**\n * Cache for pre-computed component data sources to avoid repeated calculations\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: Map<EntityId, Map<EntityId<any>, any>>) {\n this.componentTypes = [...componentTypes].sort((a, b) => a - b);\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 matches(componentTypes: EntityId<any>[]): boolean {\n if (this.componentTypes.length !== componentTypes.length) return false;\n const sortedTypes = [...componentTypes].sort((a, b) => a - b);\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.componentTypes.includes(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 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 relations.push(...findMatchingDontFragmentRelations(this.dontFragmentRelations.get(entityId), componentId));\n }\n\n return relations;\n }\n\n private getRegularComponent<T>(entityId: EntityId, index: number, componentType: EntityId<T>): T {\n if (this.componentTypes.includes(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.componentTypes.includes(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 getOrComputeCache(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.forEachWithComponents(componentTypes, (entity, ...components) => {\n result.push({ entity, components });\n });\n return result;\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 { 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\nexport type SerializedWorld = {\n version: number;\n entityManager: any;\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 return { component: componentName || (detailed.componentId as number).toString(), target: detailed.targetId! };\n }\n case \"component-relation\": {\n const componentName = getComponentNameById(detailed.componentId);\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 type { ComponentChangeset } from \"../commands/changeset\";\nimport type { Command } from \"../commands/command-buffer\";\nimport type { Archetype } from \"./archetype\";\nimport {\n getComponentIdFromRelationId,\n isDontFragmentComponent,\n isDontFragmentRelation,\n isDontFragmentWildcard,\n isWildcardRelationId,\n relation,\n type ComponentId,\n type EntityId,\n} from \"./entity\";\n\nexport interface CommandProcessorContext {\n dontFragmentRelations: Map<EntityId, Map<EntityId<any>, any>>;\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\" && command.componentType) {\n processSetCommand(\n entityId,\n currentArchetype,\n command.componentType,\n command.component,\n changeset,\n handleExclusiveRelation,\n );\n } else if (command.type === \"delete\" && command.componentType) {\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.componentTypes.includes(wildcardMarker)) {\n changeset.set(wildcardMarker, undefined);\n }\n }\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 entityData = archetype.getEntity(entityId);\n if (entityData) {\n for (const [componentType] of entityData) {\n if (archetype.componentTypes.includes(componentType)) continue;\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 const entityData = archetype.getEntity(entityId);\n if (!entityData) {\n changeset.delete(wildcardMarker);\n return;\n }\n\n // Check if there are any other relations with the same component ID\n for (const [otherComponentType] of entityData) {\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 changeset.delete(wildcardMarker);\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>; newArchetype: Archetype } {\n const currentEntityData = currentArchetype.getEntity(entityId);\n const allCurrentComponentTypes = currentEntityData\n ? Array.from(currentEntityData.keys())\n : currentArchetype.componentTypes;\n\n const finalComponentTypes = changeset.getFinalComponentTypes(allCurrentComponentTypes);\n const removedComponents = new Map<EntityId<any>, any>();\n\n if (finalComponentTypes) {\n // Check if archetype-affecting components actually changed\n // (dontFragment components don't affect archetype signature)\n const currentRegularTypes = filterRegularComponentTypes(allCurrentComponentTypes);\n const finalRegularTypes = filterRegularComponentTypes(finalComponentTypes);\n const archetypeChanged = !areComponentTypesEqual(currentRegularTypes, finalRegularTypes);\n\n if (archetypeChanged) {\n // Move to new archetype (regular components changed)\n const newArchetype = moveEntityToNewArchetype(\n ctx,\n entityId,\n currentArchetype,\n finalComponentTypes,\n changeset,\n removedComponents,\n entityToArchetype,\n );\n return { removedComponents, newArchetype };\n } else {\n // Only dontFragment components changed, stay in same archetype\n updateEntityInSameArchetype(ctx, entityId, currentArchetype, changeset, removedComponents);\n }\n } else {\n // Update in same archetype\n updateEntityInSameArchetype(ctx, entityId, currentArchetype, changeset, removedComponents);\n }\n\n return { removedComponents, newArchetype: currentArchetype };\n}\n\nfunction moveEntityToNewArchetype(\n ctx: CommandProcessorContext,\n entityId: EntityId,\n currentArchetype: Archetype,\n finalComponentTypes: EntityId<any>[],\n changeset: ComponentChangeset,\n removedComponents: Map<EntityId<any>, any>,\n entityToArchetype: Map<EntityId, Archetype>,\n): Archetype {\n const newArchetype = ctx.ensureArchetype(finalComponentTypes);\n const currentComponents = currentArchetype.removeEntity(entityId)!;\n\n // Track removed components\n for (const componentType of changeset.removes) {\n removedComponents.set(componentType, currentComponents.get(componentType));\n }\n\n // Add to new archetype with updated components\n newArchetype.addEntity(entityId, changeset.applyTo(currentComponents));\n entityToArchetype.set(entityId, newArchetype);\n return newArchetype;\n}\n\nfunction updateEntityInSameArchetype(\n ctx: CommandProcessorContext,\n entityId: EntityId,\n currentArchetype: Archetype,\n changeset: ComponentChangeset,\n removedComponents: Map<EntityId<any>, any>,\n): void {\n // Process dontFragment relation changes directly on World's storage\n applyDontFragmentChanges(ctx.dontFragmentRelations, entityId, changeset, removedComponents);\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\nfunction applyDontFragmentChanges(\n dontFragmentRelations: Map<EntityId, Map<EntityId<any>, any>>,\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\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 = [...types1].sort((a, b) => a - b);\n const sorted2 = [...types2].sort((a, b) => a - b);\n return sorted1.every((v, i) => v === sorted2[i]);\n}\n","import type { Archetype } from \"./archetype\";\nimport {\n getComponentIdFromRelationId,\n getTargetIdFromRelationId,\n isWildcardRelationId,\n relation,\n type EntityId,\n} from \"./entity\";\nimport { isOptionalEntityId, type ComponentType, type LegacyLifecycleHook, type LifecycleHookEntry } from \"./types\";\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 type HooksMap = Map<EntityId<any>, Set<LegacyLifecycleHook<any>>>;\n\nexport interface HooksContext {\n hooks: HooksMap;\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 invokeHooksForComponents(ctx.hooks, entityId, addedComponents, \"on_set\");\n invokeHooksForComponents(ctx.hooks, entityId, removedComponents, \"on_remove\");\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 ctx: HooksContext,\n entityId: EntityId,\n removedComponents: Map<EntityId<any>, any>,\n oldArchetype: Archetype,\n): void {\n if (removedComponents.size === 0) return;\n\n // Trigger legacy hooks for removed components\n invokeHooksForComponents(ctx.hooks, entityId, removedComponents, \"on_remove\");\n\n // Trigger multi-component hooks - only on_remove since entity is being deleted\n for (const entry of oldArchetype.matchingMultiHooks) {\n const { hook, requiredComponents, componentTypes } = entry;\n if (!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 hook.on_remove(entityId, ...components);\n }\n}\n\nfunction invokeHooksForComponents(\n hooks: HooksMap,\n entityId: EntityId,\n components: Map<EntityId<any>, any>,\n hookType: \"on_set\" | \"on_remove\",\n): void {\n for (const [componentType, component] of components) {\n // Trigger direct component hooks\n const directHooks = hooks.get(componentType);\n if (directHooks) {\n for (const hook of directHooks) {\n hook[hookType]?.(entityId, componentType, component);\n }\n }\n\n // Trigger wildcard relation hooks\n const componentId = getComponentIdFromRelationId(componentType);\n if (componentId !== undefined) {\n const wildcardHooks = hooks.get(relation(componentId, \"*\"));\n if (wildcardHooks) {\n for (const hook of wildcardHooks) {\n hook[hookType]?.(entityId, componentType, component);\n }\n }\n }\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: triggers if any required or optional component was added/removed and entity still matches\n for (const entry of newArchetype.matchingMultiHooks) {\n const { hook, requiredComponents, optionalComponents, componentTypes } = entry;\n if (!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\n if (\n (anyRequiredAdded || anyOptionalAdded || anyOptionalRemoved) &&\n entityHasAllComponents(ctx, entityId, requiredComponents)\n ) {\n hook.on_set(entityId, ...collectMultiHookComponents(ctx, entityId, componentTypes));\n }\n }\n\n // Handle on_remove: triggers if any required component was removed and entity no longer matches\n if (removedComponents.size > 0) {\n for (const entry of oldArchetype.matchingMultiHooks) {\n const { hook, requiredComponents, componentTypes } = entry;\n if (!hook.on_remove) continue;\n\n const anyRequiredRemoved = requiredComponents.some((c) => anyComponentMatches(removedComponents, c));\n\n // Only trigger if:\n // 1. A required component was removed\n // 2. Entity matched before (had all required components)\n // 3. Entity no longer matches after removal\n if (\n anyRequiredRemoved &&\n entityHadAllComponentsBefore(ctx, entityId, requiredComponents, removedComponents) &&\n !entityHasAllComponents(ctx, entityId, requiredComponents)\n ) {\n hook.on_remove(\n entityId,\n ...collectMultiHookComponentsWithRemoved(ctx, entityId, componentTypes, removedComponents),\n );\n }\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 // (ctx.get will return an array of matching relations, empty if none exist)\n if (isWildcardRelationId(c)) {\n try {\n const wildcardData = ctx.get(entityId, c);\n return Array.isArray(wildcardData) && wildcardData.length > 0;\n } catch {\n return false;\n }\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 try {\n const wildcardData = ctx.get(entityId, c);\n return Array.isArray(wildcardData) && wildcardData.length > 0;\n } catch {\n return false;\n }\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 */\nfunction reconstructWildcardWithRemoved(\n ctx: HooksContext,\n entityId: EntityId,\n wildcardId: EntityId<any>,\n removedComponents: Map<EntityId<any>, any>,\n): [EntityId, any][] {\n const currentData = ctx.get(entityId, wildcardId);\n const result = Array.isArray(currentData) ? [...currentData] : [];\n\n // Add removed matching relations\n for (const [removedCompId, removedValue] of removedComponents.entries()) {\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 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\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): boolean {\n const set = this.map.get(key);\n if (!set) return false;\n if (arguments.length === 1) return true;\n return set.has(value as V);\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 };\nexport type { MultiMap as MultiMapType };\n","import { MultiMap } from \"../utils/multi-map\";\nimport type { EntityId } from \"./entity\";\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 { ComponentChangeset } from \"../commands/changeset\";\nimport { CommandBuffer, type Command } from \"../commands/command-buffer\";\nimport { serializeQueryFilter, type QueryFilter } from \"../query/filter\";\nimport { Query } from \"../query/query\";\nimport { getOrCreateWithSideEffect } from \"../utils/utils\";\nimport { Archetype, MISSING_COMPONENT } from \"./archetype\";\nimport { EntityBuilder } from \"./builder\";\nimport type { ComponentId, EntityId, WildcardRelationId } from \"./entity\";\nimport {\n EntityIdManager,\n getComponentIdFromRelationId,\n getDetailedIdType,\n getTargetIdFromRelationId,\n isCascadeDeleteRelation,\n isDontFragmentRelation,\n isDontFragmentWildcard,\n isEntityRelation,\n isExclusiveComponent,\n isWildcardRelationId,\n} from \"./entity\";\nimport type { SerializedComponent, SerializedEntity, SerializedWorld } from \"./serialization\";\nimport { decodeSerializedId, encodeEntityId } from \"./serialization\";\nimport type {\n ComponentTuple,\n ComponentType,\n LegacyLifecycleCallback,\n LegacyLifecycleHook,\n LifecycleCallback,\n LifecycleHook,\n LifecycleHookEntry,\n} from \"./types\";\nimport { isOptionalEntityId } from \"./types\";\nimport {\n applyChangeset,\n filterRegularComponentTypes,\n maybeRemoveWildcardMarker,\n processCommands,\n removeMatchingRelations,\n} from \"./world-commands\";\nimport {\n collectMultiHookComponents,\n triggerLifecycleHooks,\n triggerRemoveHooksForEntityDeletion,\n type HooksContext,\n} from \"./world-hooks\";\nimport {\n getEntityReferences,\n trackEntityReference,\n untrackEntityReference,\n type EntityReferencesMap,\n} from \"./world-references\";\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>, Archetype[]>();\n private entityReferences: EntityReferencesMap = new Map();\n private dontFragmentRelations: Map<EntityId, Map<EntityId<any>, any>> = new Map();\n private componentEntityComponents: Map<EntityId, Map<EntityId<any>, any>> = new Map();\n private relationEntityIdsByTarget: Map<EntityId, Set<EntityId>> = new Map();\n\n // Query management\n private queries: Query[] = [];\n private queryCache = new Map<string, { query: Query; refCount: number }>();\n\n // Command execution\n private commandBuffer = new CommandBuffer((entityId, commands) => this.executeEntityCommands(entityId, commands));\n\n // Lifecycle hooks\n private legacyHooks = new Map<EntityId<any>, Set<LegacyLifecycleHook<any>>>();\n private hooks: Set<LifecycleHookEntry> = new Set();\n\n constructor(snapshot?: SerializedWorld) {\n if (snapshot && typeof snapshot === \"object\") {\n this.deserializeSnapshot(snapshot);\n }\n }\n\n private deserializeSnapshot(snapshot: SerializedWorld): void {\n if (snapshot.entityManager) {\n this.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 (!this.isComponentEntityId(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 this.componentEntityComponents.set(entityId, componentMap);\n this.registerRelationEntityId(entityId);\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 = this.ensureArchetype(componentTypes);\n archetype.addEntity(entityId, componentMap);\n this.entityToArchetype.set(entityId, archetype);\n\n for (const compType of componentTypes) {\n const detailedType = getDetailedIdType(compType);\n if (detailedType.type === \"entity-relation\") {\n trackEntityReference(this.entityReferences, entityId, compType, detailedType.targetId!);\n } else if (detailedType.type === \"entity\") {\n trackEntityReference(this.entityReferences, entityId, compType, compType);\n }\n }\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 private isComponentEntityId(entityId: EntityId): boolean {\n const detailed = getDetailedIdType(entityId);\n return detailed.type !== \"entity\" && detailed.type !== \"invalid\";\n }\n\n private registerRelationEntityId(entityId: EntityId): void {\n const detailed = getDetailedIdType(entityId);\n if (detailed.type !== \"entity-relation\") return;\n\n const targetId = detailed.targetId;\n if (targetId === undefined) return;\n\n const existing = this.relationEntityIdsByTarget.get(targetId);\n if (existing) {\n existing.add(entityId);\n return;\n }\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\n const targetId = detailed.targetId;\n if (targetId === undefined) return;\n\n const existing = this.relationEntityIdsByTarget.get(targetId);\n if (!existing) return;\n\n existing.delete(entityId);\n if (existing.size === 0) {\n this.relationEntityIdsByTarget.delete(targetId);\n }\n }\n\n private getComponentEntityComponents(entityId: EntityId, create: boolean): Map<EntityId<any>, any> | undefined {\n let data = this.componentEntityComponents.get(entityId);\n if (!data && create) {\n data = new Map();\n this.componentEntityComponents.set(entityId, data);\n this.registerRelationEntityId(entityId);\n }\n return data;\n }\n\n private clearComponentEntityComponents(entityId: EntityId): void {\n if (this.componentEntityComponents.delete(entityId)) {\n this.unregisterRelationEntityId(entityId);\n }\n }\n\n private cleanupComponentEntitiesReferencingEntity(targetId: EntityId): void {\n const relationEntities = this.relationEntityIdsByTarget.get(targetId);\n if (!relationEntities) return;\n\n for (const relationEntityId of relationEntities) {\n this.componentEntityComponents.delete(relationEntityId);\n }\n this.relationEntityIdsByTarget.delete(targetId);\n }\n\n private destroyEntityImmediate(entityId: EntityId): void {\n const queue: EntityId[] = [entityId];\n const visited = new Set<EntityId>();\n\n while (queue.length > 0) {\n const cur = queue.shift()!;\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(this.createHooksContext(), cur, removedComponents, archetype);\n\n this.cleanupArchetypesReferencingEntity(cur);\n this.entityIdManager.deallocate(cur);\n this.cleanupComponentEntitiesReferencingEntity(cur);\n }\n }\n\n /**\n * Checks if an entity exists in the world.\n *\n * @param entityId - The entity identifier to check\n * @returns `true` if the entity exists, `false` otherwise\n *\n * @example\n * if (world.exists(entityId)) {\n * console.log(\"Entity exists\");\n * }\n */\n exists(entityId: EntityId): boolean {\n if (this.isComponentEntityId(entityId)) return true;\n return this.entityToArchetype.has(entityId);\n }\n\n /**\n * Adds or updates a component on an entity (or marks void component as present).\n * The change is buffered and takes effect after calling `world.sync()`.\n * If the entity does not exist, throws an error.\n *\n * @overload set(entityId: EntityId, componentType: EntityId<void>): void\n * Marks a void component as present on the entity\n *\n * @overload set<T>(entityId: EntityId, componentType: EntityId<T>, component: NoInfer<T>): void\n * Adds or updates a component with data on the entity\n *\n * @throws {Error} If the entity does not exist\n * @throws {Error} If the component type is invalid or is a wildcard relation\n *\n * @example\n * world.set(entity, Position, { x: 10, y: 20 });\n * world.set(entity, Marker); // void component\n * world.sync(); // Apply changes\n */\n set(entityId: EntityId, componentType: EntityId<void>): void;\n set<T>(entityId: EntityId, componentType: EntityId<T>, component: NoInfer<T>): void;\n set(entityId: EntityId, componentType: EntityId, component?: any): void {\n if (!this.exists(entityId)) {\n throw new Error(`Entity ${entityId} does not exist`);\n }\n\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 this.commandBuffer.set(entityId, 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 * @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.sync(); // Apply changes\n */\n remove<T>(entityId: EntityId, componentType: EntityId<T>): void {\n if (!this.exists(entityId)) {\n throw new Error(`Entity ${entityId} does not exist`);\n }\n\n const detailedType = getDetailedIdType(componentType);\n if (detailedType.type === \"invalid\") {\n throw new Error(`Invalid component type: ${componentType}`);\n }\n\n this.commandBuffer.remove(entityId, componentType);\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 an entity has a specific component.\n * Immediately reflects the current state without waiting for `sync()`.\n *\n * @template T - The component data type\n * @param entityId - The entity identifier\n * @param componentType - The component type to check\n * @returns `true` if the entity has the component, `false` otherwise\n *\n * @example\n * if (world.has(entity, Position)) {\n * const pos = world.get(entity, Position);\n * }\n */\n has<T>(entityId: EntityId, componentType: EntityId<T>): boolean {\n if (this.isComponentEntityId(entityId)) {\n if (isWildcardRelationId(componentType)) {\n const componentId = getComponentIdFromRelationId(componentType);\n if (componentId === undefined) return false;\n\n const data = this.componentEntityComponents.get(entityId);\n if (!data) return false;\n\n for (const key of data.keys()) {\n if (getComponentIdFromRelationId(key) === componentId) return true;\n }\n return false;\n }\n\n return this.componentEntityComponents.get(entityId)?.has(componentType) ?? false;\n }\n\n const archetype = this.entityToArchetype.get(entityId);\n if (!archetype) return false;\n\n if (archetype.componentTypes.includes(componentType)) return true;\n\n if (isDontFragmentRelation(componentType)) {\n return this.dontFragmentRelations.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.isComponentEntityId(entityId)) {\n if (isWildcardRelationId(componentType as EntityId<any>)) {\n const componentId = getComponentIdFromRelationId(componentType as EntityId<any>);\n const data = this.componentEntityComponents.get(entityId);\n const relations: [EntityId<unknown>, any][] = [];\n\n if (componentId !== undefined && data) {\n for (const [key, value] of data.entries()) {\n if (getComponentIdFromRelationId(key) === componentId) {\n const detailed = getDetailedIdType(key);\n if (detailed.type === \"entity-relation\" || detailed.type === \"component-relation\") {\n relations.push([detailed.targetId!, value]);\n }\n }\n }\n }\n\n return relations;\n }\n\n const data = this.componentEntityComponents.get(entityId);\n if (!data || !data.has(componentType as EntityId<any>)) {\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 EntityId<any>);\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 % 2 ** 42 !== 0) {\n const inArchetype = archetype.componentTypes.includes(componentType);\n const hasDontFragment = isDontFragmentRelation(componentType);\n const hasComponent =\n inArchetype || (hasDontFragment && this.dontFragmentRelations.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);\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: 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>(entityId: EntityId, componentType: EntityId<T>): { value: T } | undefined;\n getOptional<T>(entityId: EntityId, componentType: EntityId<T> = entityId as EntityId<T>): { value: T } | undefined {\n if (this.isComponentEntityId(entityId)) {\n if (isWildcardRelationId(componentType)) {\n const componentId = getComponentIdFromRelationId(componentType);\n if (componentId === undefined) return undefined;\n\n const data = this.componentEntityComponents.get(entityId);\n if (!data) return undefined;\n\n const relations: [EntityId<unknown>, any][] = [];\n for (const [key, value] of data.entries()) {\n if (getComponentIdFromRelationId(key) === componentId) {\n const detailed = getDetailedIdType(key);\n if (detailed.type === \"entity-relation\" || detailed.type === \"component-relation\") {\n relations.push([detailed.targetId!, value]);\n }\n }\n }\n\n if (relations.length === 0) return undefined;\n return { value: relations as T };\n }\n\n const data = this.componentEntityComponents.get(entityId);\n if (!data || !data.has(componentType)) return undefined;\n return { value: data.get(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 any);\n if (Array.isArray(wildcardData) && wildcardData.length > 0) {\n return { value: wildcardData as T };\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 *\n * @deprecated For single components, use the array overload with LifecycleCallback for better multi-component support\n *\n * @overload hook<T>(componentType: EntityId<T>, hook: LegacyLifecycleHook<T> | LegacyLifecycleCallback<T>): () => void\n * Registers a hook for a single component type (legacy API).\n *\n * @overload hook<const T extends readonly ComponentType<any>[]>(\n * componentTypes: T,\n * hook: LifecycleHook<T> | LifecycleCallback<T>,\n * ): () => void\n * Registers a hook for multiple component types.\n * The hook is triggered when all required components change together.\n *\n * @param componentTypesOrSingle - A single component type or an array of component types\n * @param hook - Either a hook object with on_init/on_set/on_remove handlers, or a callback function\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 * // Array overload (recommended)\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 hook<T>(componentType: EntityId<T>, hook: LegacyLifecycleHook<T> | LegacyLifecycleCallback<T>): () => void;\n hook<const T extends readonly ComponentType<any>[]>(\n componentTypes: T,\n hook: LifecycleHook<T> | LifecycleCallback<T>,\n ): () => void;\n hook(\n componentTypesOrSingle: EntityId<any> | readonly ComponentType<any>[],\n hook: LegacyLifecycleHook<any> | LifecycleHook<any> | LegacyLifecycleCallback<any> | LifecycleCallback<any>,\n ): () => void {\n // Normalize callback functions to hook objects\n if (typeof hook === \"function\") {\n if (Array.isArray(componentTypesOrSingle)) {\n const callback = hook as LifecycleCallback<any>;\n hook = {\n on_init: (entityId, ...components) => callback(\"init\", entityId, ...components),\n on_set: (entityId, ...components) => callback(\"set\", entityId, ...components),\n on_remove: (entityId, ...components) => callback(\"remove\", entityId, ...components),\n } as LifecycleHook<any>;\n } else {\n const callback = hook as LegacyLifecycleCallback<any>;\n hook = {\n on_init: (entityId, componentType, component) => callback(\"init\", entityId, componentType, component),\n on_set: (entityId, componentType, component) => callback(\"set\", entityId, componentType, component),\n on_remove: (entityId, componentType, component) => callback(\"remove\", entityId, componentType, component),\n } as LegacyLifecycleHook<any>;\n }\n }\n\n if (Array.isArray(componentTypesOrSingle)) {\n const componentTypes = componentTypesOrSingle as readonly ComponentType<any>[];\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 hook: hook as LifecycleHook<any>,\n };\n this.hooks.add(entry);\n\n // Add to archetypes\n for (const archetype of this.archetypes) {\n if (this.archetypeMatchesHook(archetype, entry)) {\n archetype.matchingMultiHooks.add(entry);\n }\n }\n\n const multiHook = hook as LifecycleHook<any>;\n if (multiHook.on_init !== undefined) {\n const matchingArchetypes = this.getMatchingArchetypes(requiredComponents);\n for (const archetype of matchingArchetypes) {\n for (const entityId of archetype.getEntities()) {\n const components = collectMultiHookComponents(this.createHooksContext(), entityId, componentTypes);\n multiHook.on_init(entityId, ...components);\n }\n }\n }\n\n return () => {\n this.hooks.delete(entry);\n for (const archetype of this.archetypes) {\n archetype.matchingMultiHooks.delete(entry);\n }\n };\n } else {\n const componentType = componentTypesOrSingle as EntityId<any>;\n if (!this.legacyHooks.has(componentType)) {\n this.legacyHooks.set(componentType, new Set());\n }\n const legacyHook = hook as LegacyLifecycleHook<any>;\n this.legacyHooks.get(componentType)!.add(legacyHook);\n\n if (legacyHook.on_init !== undefined) {\n this.archetypesByComponent.get(componentType)?.forEach((archetype) => {\n const entities = archetype.getEntityToIndexMap();\n const componentData = archetype.getComponentData<any>(componentType);\n for (const [entity, index] of entities) {\n const data = componentData[index];\n const value = data === MISSING_COMPONENT ? undefined : data;\n legacyHook.on_init?.(entity, componentType, value);\n }\n });\n }\n\n return () => {\n const hooks = this.legacyHooks.get(componentType);\n if (hooks) {\n hooks.delete(legacyHook);\n if (hooks.size === 0) {\n this.legacyHooks.delete(componentType);\n }\n }\n };\n }\n }\n\n /** @deprecated use the unsubscribe function returned by hook() instead */\n unhook<T>(componentType: EntityId<T>, hook: LegacyLifecycleHook<T>): void;\n /** @deprecated use the unsubscribe function returned by hook() instead */\n unhook<const T extends readonly ComponentType<any>[]>(componentTypes: T, hook: LifecycleHook<T>): void;\n /** @deprecated use the unsubscribe function returned by hook() instead */\n unhook(\n componentTypesOrSingle: EntityId<any> | readonly ComponentType<any>[],\n hook: LegacyLifecycleHook<any> | LifecycleHook<any>,\n ): void {\n // Note: Callback functions passed to hook() are converted to hook objects internally,\n // so unhook() only accepts the original hook object references.\n if (Array.isArray(componentTypesOrSingle)) {\n for (const entry of this.hooks) {\n if (entry.hook === hook) {\n this.hooks.delete(entry);\n for (const archetype of this.archetypes) {\n archetype.matchingMultiHooks.delete(entry);\n }\n break;\n }\n }\n } else {\n const componentType = componentTypesOrSingle as EntityId<any>;\n const hooks = this.legacyHooks.get(componentType);\n if (hooks) {\n hooks.delete(hook as LegacyLifecycleHook<any>);\n if (hooks.size === 0) {\n this.legacyHooks.delete(componentType);\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 * @param componentTypes - Array of component types to match\n * @param filter - Optional filter for additional constraints (e.g., without specific components)\n * @returns A Query instance that can be used to iterate matching entities\n *\n * @example\n * // Create once, reuse many times\n * const movementQuery = world.createQuery([Position, Velocity]);\n *\n * // In game loop\n * movementQuery.forEach((entity) => {\n * const pos = world.get(entity, Position);\n * const vel = world.get(entity, Velocity);\n * pos.x += vel.x;\n * pos.y += vel.y;\n * });\n *\n * // With filter\n * const activeQuery = world.createQuery([Position], {\n * without: [Disabled]\n * });\n */\n createQuery(componentTypes: EntityId<any>[], filter: QueryFilter = {}): Query {\n const sortedTypes = [...componentTypes].sort((a, b) => a - b);\n const filterKey = serializeQueryFilter(filter);\n const key = `${this.createArchetypeSignature(sortedTypes)}${filterKey ? `|${filterKey}` : \"\"}`;\n\n const cached = this.queryCache.get(key);\n if (cached) {\n cached.refCount++;\n return cached.query;\n }\n\n const query = new Query(this, sortedTypes, filter);\n this.queryCache.set(key, { query, refCount: 1 });\n return query;\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 _registerQuery(query: Query): void {\n this.queries.push(query);\n }\n\n _unregisterQuery(query: Query): void {\n const index = this.queries.indexOf(query);\n if (index !== -1) {\n this.queries.splice(index, 1);\n }\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 for (const [k, v] of this.queryCache.entries()) {\n if (v.query === query) {\n v.refCount--;\n if (v.refCount <= 0) {\n this.queryCache.delete(k);\n this._unregisterQuery(query);\n v.query._disposeInternal();\n }\n return;\n }\n }\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 archetypesWithMarker = this.archetypesByComponent.get(relationId) || [];\n matchingArchetypes =\n matchingArchetypes.length === 0\n ? archetypesWithMarker\n : matchingArchetypes.filter(\n (a) => archetypesWithMarker.includes(a) || a.hasRelationWithComponentId(componentId),\n );\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) return this.archetypesByComponent.get(componentTypes[0]!) || [];\n\n const archetypeLists = componentTypes.map((type) => this.archetypesByComponent.get(type) || []);\n const firstList = archetypeLists[0]!;\n return firstList.filter((archetype) => archetypeLists.slice(1).every((list) => list.includes(archetype)));\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 result.push(...archetype.getEntitiesWithComponents(componentTypes as EntityId<any>[]));\n }\n return result;\n } else {\n const result: EntityId[] = [];\n for (const archetype of matchingArchetypes) {\n result.push(...archetype.getEntities());\n }\n return result;\n }\n }\n\n executeEntityCommands(entityId: EntityId, commands: Command[]): ComponentChangeset {\n const changeset = new ComponentChangeset();\n\n if (this.isComponentEntityId(entityId)) {\n this.executeComponentEntityCommands(entityId, commands);\n return changeset;\n }\n\n if (commands.some((cmd) => cmd.type === \"destroy\")) {\n this.destroyEntityImmediate(entityId);\n return changeset;\n }\n\n const currentArchetype = this.entityToArchetype.get(entityId);\n if (!currentArchetype) return changeset;\n\n processCommands(entityId, currentArchetype, commands, changeset, (eid, arch, compId) => {\n if (isExclusiveComponent(compId)) {\n removeMatchingRelations(eid, arch, compId, changeset);\n }\n });\n\n const { removedComponents, newArchetype } = applyChangeset(\n { dontFragmentRelations: this.dontFragmentRelations, ensureArchetype: (ct) => this.ensureArchetype(ct) },\n entityId,\n currentArchetype,\n changeset,\n this.entityToArchetype,\n );\n\n this.updateEntityReferences(entityId, changeset);\n triggerLifecycleHooks(\n this.createHooksContext(),\n entityId,\n changeset.adds,\n removedComponents,\n currentArchetype,\n newArchetype,\n );\n\n return changeset;\n }\n\n private executeComponentEntityCommands(entityId: EntityId, commands: Command[]): void {\n if (commands.some((cmd) => cmd.type === \"destroy\")) {\n this.clearComponentEntityComponents(entityId);\n return;\n }\n\n for (const command of commands) {\n if (command.type === \"set\" && command.componentType) {\n const data = this.getComponentEntityComponents(entityId, true)!;\n data.set(command.componentType, command.component);\n } else if (command.type === \"delete\" && command.componentType) {\n const data = this.componentEntityComponents.get(entityId);\n if (!data) continue;\n\n if (isWildcardRelationId(command.componentType)) {\n const componentId = getComponentIdFromRelationId(command.componentType);\n if (componentId !== undefined) {\n for (const key of Array.from(data.keys())) {\n if (getComponentIdFromRelationId(key) === componentId) {\n data.delete(key);\n }\n }\n }\n } else {\n data.delete(command.componentType);\n }\n\n if (data.size === 0) {\n this.clearComponentEntityComponents(entityId);\n }\n }\n }\n }\n\n private createHooksContext(): HooksContext {\n return {\n hooks: this.legacyHooks,\n multiHooks: this.hooks,\n has: (eid, ct) => this.has(eid, ct),\n get: (eid, ct) => this.get(eid, ct),\n getOptional: (eid, ct) => this.getOptional(eid, ct),\n };\n }\n\n 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 = new ComponentChangeset();\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 { dontFragmentRelations: this.dontFragmentRelations, ensureArchetype: (ct) => this.ensureArchetype(ct) },\n entityId,\n sourceArchetype,\n changeset,\n this.entityToArchetype,\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 >= 1024) {\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 >= 1024) {\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 = regularTypes.sort((a, b) => a - b);\n const hashKey = this.createArchetypeSignature(sortedTypes);\n\n return getOrCreateWithSideEffect(this.archetypeBySignature, hashKey, () => this.createNewArchetype(sortedTypes));\n }\n\n private createNewArchetype(componentTypes: EntityId<any>[]): Archetype {\n const newArchetype = new Archetype(componentTypes, this.dontFragmentRelations);\n this.archetypes.push(newArchetype);\n\n for (const componentType of componentTypes) {\n const archetypes = this.archetypesByComponent.get(componentType) || [];\n archetypes.push(newArchetype);\n this.archetypesByComponent.set(componentType, archetypes);\n }\n\n for (const query of this.queries) {\n query.checkNewArchetype(newArchetype);\n }\n\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 }\n }\n }\n\n private archetypeMatchesHook(archetype: Archetype, entry: LifecycleHookEntry): boolean {\n return 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.componentTypes.includes(c) || isDontFragmentRelation(c);\n });\n }\n\n private archetypeReferencesEntity(archetype: Archetype, entityId: EntityId): boolean {\n return archetype.componentTypes.some(\n (ct) => ct === entityId || (isEntityRelation(ct) && getTargetIdFromRelationId(ct) === entityId),\n );\n }\n\n private cleanupArchetypesReferencingEntity(entityId: EntityId): void {\n for (let i = this.archetypes.length - 1; i >= 0; i--) {\n const archetype = this.archetypes[i]!;\n if (archetype.getEntities().length === 0 && this.archetypeReferencesEntity(archetype, entityId)) {\n this.removeArchetype(archetype);\n }\n }\n }\n\n private removeArchetype(archetype: Archetype): void {\n const index = this.archetypes.indexOf(archetype);\n if (index !== -1) {\n this.archetypes.splice(index, 1);\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 const compIndex = archetypes.indexOf(archetype);\n if (compIndex !== -1) {\n archetypes.splice(compIndex, 1);\n if (archetypes.length === 0) {\n this.archetypesByComponent.delete(componentType);\n }\n }\n }\n }\n\n for (const query of this.queries) {\n query.removeArchetype(archetype);\n }\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 const entities: SerializedEntity[] = [];\n\n for (const archetype of this.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 componentEntities: SerializedEntity[] = [];\n for (const [entityId, components] of this.componentEntityComponents.entries()) {\n componentEntities.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: this.entityIdManager.serializeState(),\n entities,\n componentEntities,\n };\n }\n}\n"],"mappings":"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"}
|