@daneren2005/shared-memory-ecs 1.7.2 → 1.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -14,7 +14,8 @@ systems, and domain data.
14
14
  config to the raw block values) and `attach(entity, memory, index)` (builds the accessor over that block).
15
15
  Loading a component is `attach(entity, memory, memory.create(toBlock(config)))`; splitting it this way lets a
16
16
  worker build the block off-thread (it calls only `toBlock`) and the main thread wrap it (`attach`) when it
17
- adopts the entity. Plus an optional `save(component)`, `free(component)`, and `died(component, entity, world)`.
17
+ adopts the entity. `attach` also receives the load config as an optional fourth argument, for main-thread-only
18
+ state kept off the block (e.g. a display name); it is `undefined` when adopting a worker-built block. Plus an optional `save(component)`, `free(component)`, and `died(component, entity, world)`.
18
19
  A component's data splits into `Config` (defining props supplied up front, e.g. `maxHealth`) and
19
20
  `Serialization` (runtime-derived state, e.g. current `health`); `toBlock` sees `Config & Serialization` while
20
21
  `save` returns only the `Serialization` slice. `free` runs when the component is torn down (see
@@ -272,7 +273,7 @@ class DamageSystem extends EntityWorkerSystem<Components, { health: Int32Array }
272
273
  }
273
274
  ```
274
275
 
275
- ### Update-function hooks: `init` and `preRun`
276
+ ### Update-function hooks: `init`, `queryChanged` and `preRun`
276
277
 
277
278
  `addDataToWorld` runs on the main thread and re-sends its data every run. When the data instead needs to
278
279
  *live in the worker* — computed once, or too big to ship each frame — attach hooks to the update function
@@ -330,6 +331,21 @@ damageUpdate.preRun = (world, entities, queries, callbacks) => {
330
331
  };
331
332
  ```
332
333
 
334
+ **`queryChanged`** runs before `preRun`, once for each sub-query in `queries` whose membership changed this run,
335
+ with that query's name and its `{ added, removed }` delta. Use it to keep a worker-local structure in sync with a
336
+ set of entities that rarely changes - a navigation grid of static walls, a lookup of static targets - instead of
337
+ rescanning the whole query every run. `added` can repeat an entity already in the query (its components changed
338
+ and its blocks were re-sent), so treat it as an upsert. Keep that structure on the `init`-returned state so a
339
+ reloaded world rebuilds it from scratch; the reload re-sends every member as added:
340
+
341
+ ```ts
342
+ wallUpdate.init = () => ({ walls: new Map<number, Rect>() });
343
+ wallUpdate.queryChanged = (world, queryName, delta) => {
344
+ delta.removed.forEach(entityId => world.walls.delete(entityId));
345
+ delta.added.forEach(({ entityId, components }) => world.walls.set(entityId, rectOf(components.transform)));
346
+ };
347
+ ```
348
+
333
349
  (An `entityRemoved(world, entityId, callbacks)` hook completes the set — it fires once per entity that left
334
350
  the system this run, so a worker can release any per-entity state it was holding.)
335
351
 
@@ -374,7 +390,7 @@ import { createSystemWorker } from '@daneren2005/shared-memory-ecs/worker';
374
390
  createSystemWorker(self, spawnerUpdate, registry);
375
391
  ```
376
392
 
377
- The run function may carry the same `init` / `entityRemoved` hooks as an `updateFunction`. Everything else —
393
+ The run function may carry the same `init` / `queryChanged` / `entityRemoved` hooks as an `updateFunction`. Everything else —
378
394
  callbacks, worker fallback, off-thread creation — behaves exactly as an `EntityWorkerSystem`.
379
395
 
380
396
  ### Importing in workers
@@ -15,7 +15,7 @@ export interface ComponentDefinition<Component extends BaseComponent, T extends
15
15
  loadProperties: Array<keyof Config & string>;
16
16
  loadInFinishLoading?: boolean;
17
17
  toBlock(config: Config & Serialization, entity?: BaseEntity): Array<number>;
18
- attach(entity: BaseEntity, memory: MemoryComponent<T>, index: number): Component;
18
+ attach(entity: BaseEntity, memory: MemoryComponent<T>, index: number, config?: Config & Serialization): Component;
19
19
  save?(component: Component): Serialization;
20
20
  free?(component: Component): void;
21
21
  died?(component: Component, entity: BaseEntity, world: BaseWorld): void;
@@ -283,7 +283,18 @@ function b(t, n, r) {
283
283
  componentName: String(t)
284
284
  });
285
285
  }
286
- }, D = !1;
286
+ };
287
+ if (n.queryChanged) {
288
+ for (let [e, t] of Object.entries(S.queries)) if (t.added.length || t.removed.length) try {
289
+ n.queryChanged(S.world, e, t, E);
290
+ } catch (e) {
291
+ w.push({
292
+ error: e,
293
+ phase: "queryChanged"
294
+ });
295
+ }
296
+ }
297
+ let D = !1;
287
298
  if (n.preRun) try {
288
299
  n.preRun(S.world, l, T, E);
289
300
  } catch (e) {
@@ -334,7 +345,7 @@ function x(e, t) {
334
345
  //#region src/systems/workers/create-system-worker.ts
335
346
  function S(e) {
336
347
  let t = (() => {});
337
- return t.preRun = (t, n, r, i) => e(t, r, i), e.init && (t.init = e.init), e.entityRemoved && (t.entityRemoved = e.entityRemoved), t;
348
+ return t.preRun = (t, n, r, i) => e(t, r, i), e.init && (t.init = e.init), e.queryChanged && (t.queryChanged = e.queryChanged), e.entityRemoved && (t.entityRemoved = e.entityRemoved), t;
338
349
  }
339
350
  function C(e, t, n) {
340
351
  b(e, S(t), n);
@@ -342,4 +353,4 @@ function C(e, t, n) {
342
353
  //#endregion
343
354
  export { a as _, v as a, p as c, f as d, h as f, o as g, s as h, y as i, u as l, c as m, S as n, _ as o, l as p, b as r, g as s, C as t, d as u, i as v };
344
355
 
345
- //# sourceMappingURL=create-system-worker-CDQmmww7.js.map
356
+ //# sourceMappingURL=create-system-worker-C4aS3-3R.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"create-system-worker-CDQmmww7.js","names":[],"sources":["../src/memory-component.ts","../src/constant-string-cache.ts","../src/systems/workers/apply-query-delta.ts","../src/actions/build-worker-entity.ts","../src/component.ts","../src/entity-component.ts","../src/actions/kill-entity-worker.ts","../src/actions/create-entity-worker.ts","../src/actions/add-component-worker.ts","../src/actions/remove-component-worker.ts","../src/systems/workers/create-entity-system-worker.ts","../src/systems/workers/create-system-worker.ts"],"sourcesContent":["import SharedPool from '@daneren2005/shared-memory-objects/shared-pool';\nimport type { SharedPoolMemory } from '@daneren2005/shared-memory-objects/shared-pool';\nimport type MemoryHeap from '@daneren2005/shared-memory-objects/memory-heap';\nimport type { TypedArrayConstructor } from '@daneren2005/shared-memory-objects/interfaces/typed-array-constructor';\n\nexport type ComponentTypedArray = Uint32Array | Int32Array | Float32Array | Float64Array;\n\n// Backed by a SharedPool: all bookkeeping lives in the shared heap, so a worker can reconstruct a handle over\n// the same pool (pass the owner's getSharedMemory() as `memory`) and allocate/read blocks off-thread.\nexport default class MemoryComponent<T extends ComponentTypedArray = ComponentTypedArray> {\n\theap: MemoryHeap;\n\tpool: SharedPool<T>;\n\n\tconstructor(heap: MemoryHeap, type: TypedArrayConstructor<T>, dataLength: number, memory?: SharedPoolMemory) {\n\t\tthis.heap = heap;\n\t\tthis.pool = memory\n\t\t\t? new SharedPool<T>(heap, memory)\n\t\t\t: new SharedPool<T>(heap, {\n\t\t\t\ttype,\n\t\t\t\tdataLength,\n\t\t\t});\n\t}\n\n\t// Reconstructs a handle over an existing pool (from the owner's getSharedMemory()) — used in a worker, where the\n\t// pool's type/dataLength are already recorded in the heap header, so no definition is needed.\n\tstatic fromSharedMemory<T extends ComponentTypedArray = ComponentTypedArray>(heap: MemoryHeap, memory: SharedPoolMemory): MemoryComponent<T> {\n\t\treturn new MemoryComponent<T>(heap, Uint32Array as unknown as TypedArrayConstructor<T>, 1, memory);\n\t}\n\n\tgetSharedMemory(): SharedPoolMemory {\n\t\treturn this.pool.getSharedMemory();\n\t}\n\n\tget length() {\n\t\treturn this.pool.length;\n\t}\n\tget rawLength() {\n\t\treturn this.pool.bufferLength;\n\t}\n\n\tcreate(values: Array<number>): number {\n\t\treturn this.pool.push(values);\n\t}\n\n\tgetBlock(index: number): T {\n\t\treturn this.pool.at(index);\n\t}\n\tget(index: number, dataIndex: number): number {\n\t\treturn this.pool.get(index, dataIndex);\n\t}\n\tset(index: number, dataIndex: number, value: number) {\n\t\tlet array = this.pool.at(index);\n\t\tarray[dataIndex] = value;\n\t}\n\n\tdelete(index: number) {\n\t\tthis.pool.deleteIndex(index);\n\t}\n\tclear() {\n\t\tthis.pool.clear();\n\t}\n}\n","import ConstantString from '@daneren2005/shared-memory-objects/constant-string';\nimport { getPointer } from '@daneren2005/shared-memory-objects/utils/pointer';\nimport type MemoryHeap from '@daneren2005/shared-memory-objects/memory-heap';\n\n// Interns immutable strings in the heap and resolves them back from a pointer. Every distinct value is allocated\n// once as a single ConstantString shared by all users (15 \"Space Ship\" entities point at one allocation), and a\n// pointer resolves to its string through a Map hit before ever rebuilding it from memory. Both sides of the\n// worker boundary hold one: the main thread creates + interns; a worker (with a heap reconstructed from the same\n// SharedArrayBuffers) only ever resolves pointers and caches the results.\nexport default class ConstantStringCache {\n\tprivate heap: MemoryHeap;\n\t// value -> the one interned allocation. Only the creating (main) thread populates this; it owns the memory.\n\tprivate byValue = new Map<string, ConstantString>();\n\t// pointer -> value: the fast lookup every thread checks before touching memory.\n\tprivate byPointer = new Map<number, string>();\n\n\tconstructor(heap: MemoryHeap) {\n\t\tthis.heap = heap;\n\t}\n\n\t// Dedupes on value, so repeated types share a single ConstantString. Main-thread only.\n\tgetOrCreate(value: string): ConstantString {\n\t\tlet existing = this.byValue.get(value);\n\t\tif(existing) {\n\t\t\treturn existing;\n\t\t}\n\n\t\tconst string = new ConstantString(this.heap, value);\n\t\tthis.byValue.set(value, string);\n\t\tthis.byPointer.set(string.pointer, value);\n\n\t\treturn string;\n\t}\n\n\t// pointer -> string, checking the cache before rebuilding from memory. A pointer of 0 is the empty string; a\n\t// pointer into a buffer that has not synced to this thread yet returns undefined.\n\tgetString(pointer: number): string | undefined {\n\t\tif(pointer === 0) {\n\t\t\treturn '';\n\t\t}\n\n\t\tlet cached = this.byPointer.get(pointer);\n\t\tif(cached !== undefined) {\n\t\t\treturn cached;\n\t\t}\n\n\t\tconst memory = getPointer(pointer, this.heap.positionBits);\n\t\tif(this.heap.buffers[memory.bufferPosition] === undefined) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\tconst value = new ConstantString(this.heap, memory).value;\n\t\tthis.byPointer.set(pointer, value);\n\n\t\treturn value;\n\t}\n\n\t// Frees every allocation this cache owns and empties the lookups. A worker's cache owns nothing (it only ever\n\t// resolved views), so this just drops its pointer lookups.\n\tclear() {\n\t\tthis.byValue.forEach(string => string.free());\n\t\tthis.byValue.clear();\n\t\tthis.byPointer.clear();\n\t}\n}\n","import type { EntityUpdateComponents, QueryDelta, UpdateEntityConfigObject } from '../entity-worker-system';\n\n// Applies a run's delta to a query's persistent list: drop the entities that left, upsert those that joined or\n// changed. A steady-state run carries empty arrays and returns the list untouched. Returns the list (removals\n// rebuild it via filter), so callers must store the returned reference back.\nexport function applyQueryDelta<T extends EntityUpdateComponents>(\n\tlist: Array<UpdateEntityConfigObject<T>>,\n\tdelta: QueryDelta<T>,\n): Array<UpdateEntityConfigObject<T>> {\n\tif(delta.removed.length) {\n\t\tconst removedSet = new Set(delta.removed);\n\t\tlist = list.filter(entry => !removedSet.has(entry.entityId));\n\t}\n\n\tif(delta.added.length) {\n\t\t// Index existing members so a re-added entity replaces its entry in place instead of duplicating.\n\t\tconst indexByEid = new Map<number, number>();\n\t\tlist.forEach((entry, index) => indexByEid.set(entry.entityId, index));\n\n\t\tfor(let entity of delta.added) {\n\t\t\tconst existing = indexByEid.get(entity.entityId);\n\t\t\tif(existing !== undefined) {\n\t\t\t\tlist[existing] = entity;\n\t\t\t} else {\n\t\t\t\tindexByEid.set(entity.entityId, list.length);\n\t\t\t\tlist.push(entity);\n\t\t\t}\n\t\t}\n\t}\n\n\treturn list;\n}\n","import type { WorkerAllocator, WorkerCreateEntityConfig, WorkerCreatedComponent, WorkerCreatedEntity } from '../systems/entity-worker-system';\nimport type { WorkerEntityClassRegistry } from '../entity-class';\n\n// The slice of a component definition worker-side creation needs. Both the game's ComponentDefinitionMap and the\n// world's RegisteredComponentRegistry satisfy it.\nexport interface WorkerCreatableComponent {\n\tloadProperties: Array<string>\n\tloadInFinishLoading?: boolean\n\ttoBlock(config: Record<string, unknown>): Array<number>\n}\nexport type WorkerCreateRegistry = { [name: string]: WorkerCreatableComponent };\nexport type FactoryConfigs = { [type: string]: Record<string, unknown> };\n\n// Turns a factory-style config ({ type, ...overrides }) into a WorkerCreatedEntity, off-thread: layers the type's\n// factory template under the overrides, mints an id, and allocates + writes each triggered component's block via its\n// toBlock(). The always-present `entity` component is NOT built here - the main thread builds it on adopt (interning\n// the type is main-thread-only), reading `type`/`isStatic` off this descriptor. Shared by the real worker and the\n// main-thread fallback so both behave identically.\nexport function buildWorkerEntity(\n\tconfig: WorkerCreateEntityConfig,\n\tfactoryConfigs: FactoryConfigs,\n\tregistry: WorkerCreateRegistry,\n\tallocator: WorkerAllocator,\n\tclasses?: WorkerEntityClassRegistry,\n): WorkerCreatedEntity {\n\tconst template = factoryConfigs[config.type] ?? {};\n\tif(classes && Object.prototype.hasOwnProperty.call(config, 'class')) {\n\t\tthrow new Error('Entity class comes from its type template and cannot be supplied by a worker config');\n\t}\n\tconst merged: Record<string, unknown> = { ...template, ...config };\n\tconst entityClass = typeof template.class === 'string' ? template.class : undefined;\n\tlet componentNames = Object.keys(registry);\n\tif(classes) {\n\t\tif(template.type !== config.type) {\n\t\t\tthrow new Error(`Entity template ${config.type} must declare the same type`);\n\t\t}\n\t\tconst definition = entityClass ? classes[entityClass] : undefined;\n\t\tif(!definition) {\n\t\t\tthrow new Error(`Entity type ${config.type} has unknown class ${entityClass ?? ''}`);\n\t\t}\n\t\tcomponentNames = definition.components;\n\t}\n\n\tconst eid = allocator.allocateEid();\n\tconst components: { [name: string]: number } = {};\n\tfor(let name of componentNames) {\n\t\t// The entity component is always built on the main thread when the descriptor is adopted (interning the type),\n\t\t// never off-thread - skip it here whether or not the registry includes it.\n\t\tif(name === 'entity') {\n\t\t\tcontinue;\n\t\t}\n\t\tconst definition = registry[name];\n\t\tif(!definition) {\n\t\t\tthrow new Error(`Entity class ${entityClass ?? ''} contains unknown component ${name}`);\n\t\t}\n\t\t// Deferred components need the whole world (other entities) that a worker doesn't have; skip them.\n\t\tif(definition.loadInFinishLoading) {\n\t\t\tcontinue;\n\t\t}\n\t\tif(definition.loadProperties.some(prop => prop in merged)) {\n\t\t\tcomponents[name] = allocator.allocateComponentBlock(name, definition.toBlock(merged));\n\t\t}\n\t}\n\n\treturn {\n\t\teid,\n\t\ttype: config.type,\n\t\tclass: entityClass,\n\t\tisStatic: merged.isStatic as boolean | undefined,\n\t\tcomponents,\n\t};\n}\n\nexport function buildWorkerComponent(\n\tname: string,\n\tconfig: Record<string, unknown>,\n\tregistry: WorkerCreateRegistry,\n\tallocator: WorkerAllocator,\n): WorkerCreatedComponent {\n\tif(name === 'entity') {\n\t\tthrow new Error('The entity component cannot be added at runtime');\n\t}\n\tconst definition = registry[name];\n\tif(!definition) {\n\t\tthrow new Error(`Unknown component: ${name}`);\n\t}\n\tif(definition.loadInFinishLoading) {\n\t\tthrow new Error(`Component ${name} requires main-thread finishLoading and cannot be added in a worker`);\n\t}\n\n\treturn {\n\t\tname,\n\t\tindex: allocator.allocateComponentBlock(name, definition.toBlock(config)),\n\t};\n}\n","import type { ComponentTypedArray } from './memory-component';\nimport type { BaseComponent } from './component-definition';\n\n// Base class for a memory-backed component accessor. Subclass it, declare prototype get/set accessors over\n// `this.block` indexed by the component's exported *_INDEX constants, and return `new YourComponent(block, index)`\n// from `attach`. Because the accessors live on one shared prototype - not fresh closures captured per entity -\n// reads off thousands of entities every frame stay monomorphic and inline, and constructing a component allocates\n// just the instance instead of a closure per accessor. Components that own no extra memory need nothing else; a\n// subclass that does can take more constructor args (the entity, another pool) and store them as fields.\nexport default abstract class Component<T extends ComponentTypedArray = ComponentTypedArray> implements BaseComponent {\n\treadonly index: number;\n\treadonly block: T;\n\n\tconstructor(block: T, index: number) {\n\t\tthis.block = block;\n\t\tthis.index = index;\n\t}\n}\n","import type { ComponentDefinition } from './component-definition';\nimport Component from './component';\nimport type ConstantStringCache from './constant-string-cache';\n\nexport interface EntityComponent {\n\tindex: number\n\treadonly type: string\n\treadonly class: string\n\tdead: boolean\n\tisStatic: boolean\n}\n\nexport interface EntityComponentConfig {\n\ttype: string\n\tisStatic?: boolean\n}\n\nexport interface EntityClassConfig {\n\treadonly class: string\n}\n\nexport interface EntityComponentSerialization {\n\ttype?: string\n\tdead?: boolean\n}\n\nexport const DEAD_INDEX = 0;\nexport const STATIC_INDEX = 1;\nexport const TYPE_INDEX = 2;\nexport const CLASS_INDEX = 3;\n\n// Identity strings are interned, so the accessor needs the world's cache to resolve their pointers.\nclass EntityComponentImpl extends Component<Uint32Array> implements EntityComponent {\n\tprivate cache: ConstantStringCache;\n\n\tconstructor(block: Uint32Array, index: number, cache: ConstantStringCache) {\n\t\tsuper(block, index);\n\t\tthis.cache = cache;\n\t}\n\n\tget type() {\n\t\treturn this.cache.getString(this.block[TYPE_INDEX]) ?? '';\n\t}\n\tget class() {\n\t\treturn this.cache.getString(this.block[CLASS_INDEX]) ?? '';\n\t}\n\tget dead() {\n\t\treturn this.block[DEAD_INDEX] === 1;\n\t}\n\tset dead(value: boolean) {\n\t\tthis.block[DEAD_INDEX] = value ? 1 : 0;\n\t}\n\tget isStatic() {\n\t\treturn this.block[STATIC_INDEX] === 1;\n\t}\n\tset isStatic(value: boolean) {\n\t\tthis.block[STATIC_INDEX] = value ? 1 : 0;\n\t}\n}\n\nexport const entityDefinition: ComponentDefinition<EntityComponent, Uint32Array, EntityComponentConfig & Partial<EntityClassConfig>, EntityComponentSerialization> = {\n\ttype: Uint32Array,\n\tsize: 4,\n\tloadProperties: ['type', 'isStatic'],\n\t// The only component that reads the entity (never worker-created): it interns its identity strings through the heap and\n\t// stores the pointer. `entity` is always passed here since loadComponent runs on the main thread.\n\ttoBlock(config, entity) {\n\t\tconst cache = entity!.world.constantStrings;\n\t\tconst typePointer = config.type ? cache.getOrCreate(config.type).pointer : 0;\n\t\tconst classPointer = config.class ? cache.getOrCreate(config.class).pointer : 0;\n\t\treturn [config.dead ? 1 : 0, config.isStatic ? 1 : 0, typePointer, classPointer];\n\t},\n\tattach(entity, memory, index) {\n\t\treturn new EntityComponentImpl(memory.getBlock(index), index, entity.world.constantStrings);\n\t},\n\tsave(component) {\n\t\tconst config: EntityComponentSerialization = {};\n\t\tif(component.type) {\n\t\t\tconfig.type = component.type;\n\t\t}\n\t\tif(component.dead) {\n\t\t\tconfig.dead = true;\n\t\t}\n\n\t\treturn config;\n\t},\n};\n","import type { ComponentTypedArray } from '../memory-component';\nimport type { EntityWorkerSystemCallbacks, EntityUpdateComponents } from '../systems/entity-worker-system';\nimport { DEAD_INDEX } from '../entity-component';\n\n// Worker-side killEntity: flags the entity dead in its block and reports the death back via callbacks. The\n// entity component must be in the system's query for its block to be available here.\nexport default function killEntityWorker(entityId: number, components: EntityUpdateComponents, callbacks: EntityWorkerSystemCallbacks): void {\n\tconst block = (components as { entity?: ComponentTypedArray }).entity;\n\tif(block) {\n\t\tblock[DEAD_INDEX] = 1;\n\t}\n\n\tcallbacks.entityDied(entityId);\n}\n","import type { EntityWorkerSystemCallbacks, EntityWorkerSystemWorld, WorkerCreateEntityConfig } from '../systems/entity-worker-system';\n\n// Worker-side entity creation from a factory config. The worker merges the selected type template, resolves its\n// optional class, mints a unique id, and allocates + writes every allowed, triggered component block\n// directly into the shared pools (off-thread) via each component's toBlock(). It reports the descriptor back; the main\n// thread adopts it on run-complete (world.adoptEntity), building the `entity` component and class wrapper there\n// worker-written blocks, so the entity first exists on the following frame.\n//\n// Requires the system to be registered with `createsEntities: true` and its worker entry to pass the component\n// registry to createEntitySystemWorker (so the worker has each component's toBlock).\nexport default function createEntityWorker(world: EntityWorkerSystemWorld, config: WorkerCreateEntityConfig, callbacks: EntityWorkerSystemCallbacks): void {\n\tif(!world.buildEntityDescriptor) {\n\t\tthrow new Error('createEntityWorker requires the system to be registered with createsEntities: true and the component registry passed to createEntitySystemWorker');\n\t}\n\n\tcallbacks.createEntity(world.buildEntityDescriptor(config));\n}\n","import type { ComponentMap } from '../component-definition';\nimport type { EntityWorkerSystemCallbacks, EntityWorkerSystemWorld } from '../systems/entity-worker-system';\n\n// Allocates a component block in the worker and asks the main thread to attach it after the run. The entity's\n// current query snapshot is intentionally unchanged until the next run.\nexport default function addComponentWorker<C extends ComponentMap, K extends keyof C>(\n\tworld: EntityWorkerSystemWorld,\n\tentityId: number,\n\tcomponentName: K,\n\tconfig: Record<string, unknown>,\n\tcallbacks: EntityWorkerSystemCallbacks<C>,\n): void {\n\tif(!world.buildComponentDescriptor) {\n\t\tthrow new Error('addComponentWorker requires addsComponents: true and the component registry passed to createEntitySystemWorker');\n\t}\n\n\tcallbacks.addComponent(entityId, world.buildComponentDescriptor(String(componentName), config));\n}\n","import type { ComponentMap } from '../component-definition';\nimport type { EntityWorkerSystemCallbacks } from '../systems/entity-worker-system';\n\n// Requests a main-thread detach after the worker run. Shared memory is freed only after every system that could\n// still hold the old block has completed a run.\nexport default function removeComponentWorker<C extends ComponentMap, K extends keyof C>(\n\tentityId: number,\n\tcomponentName: K,\n\tcallbacks: EntityWorkerSystemCallbacks<C>,\n): void {\n\tcallbacks.removeComponent(entityId, componentName);\n}\n","import MemoryHeap from '@daneren2005/shared-memory-objects/memory-heap';\nimport type AllocatedMemory from '@daneren2005/shared-memory-objects/allocated-memory';\nimport type EntitySystemWorkerMessage from './entity-system-worker-message';\nimport type { EntityEvent, SystemEvents, WorkerRunError } from './entity-system-worker-message';\nimport ConstantStringCache from '../../constant-string-cache';\nimport MemoryComponent from '../../memory-component';\nimport type { ComponentDefinitionMap, ComponentMap } from '../../component-definition';\nimport type {\n\tEntityWorkerSystemCallbacks, EntityWorkerSystemWorld, EntityQueryComponents, EntityUpdateComponents,\n\tEntityUpdateFunction, QueryDelta, UpdateEntityConfigObject, WorkerComponentChange, WorkerCreatedEntity,\n} from '../entity-worker-system';\nimport { buildWorkerComponent, buildWorkerEntity, type FactoryConfigs } from '../../actions/build-worker-entity';\nimport type { WorkerEntityClassRegistry } from '../../entity-class';\nimport { applyQueryDelta } from './apply-query-delta';\n\n// The slice of the worker global scope createEntitySystemWorker touches. Passing `self` explicitly (rather than\n// using the global) lets runners like @vitest/web-worker, which inject `self` as a module local, drive it.\nexport interface EntitySystemWorkerScope {\n\tonmessage: ((e: MessageEvent) => void) | null\n\tpostMessage(message: EntitySystemWorkerMessage): void\n}\n\nexport default function createEntitySystemWorker<\n\tC extends ComponentMap,\n\tT extends EntityUpdateComponents<C>,\n\tW extends EntityWorkerSystemWorld = EntityWorkerSystemWorld,\n\tD = unknown,\n>(scope: EntitySystemWorkerScope, updateFunction: EntityUpdateFunction<C, T, W, D>, definitions?: ComponentDefinitionMap) {\n\t// Persistent lists, carried across runs and mutated by each run's delta (see applyQueryDelta).\n\tlet entities: Array<UpdateEntityConfigObject<T>> = [];\n\tconst queryEntities: { [key: string]: Array<UpdateEntityConfigObject<T>> } = {};\n\t// What updateFunction.init returned: persistent state (e.g. a seeded RNG) merged onto `world` each run.\n\tlet worldExtension: Partial<W> | undefined;\n\tlet heap: MemoryHeap | undefined;\n\tlet stringCache: ConstantStringCache | undefined;\n\t// Reconstructed pool handles over the world's shared state, plus the factory templates - for off-thread entity\n\t// allocation. `definitions` (passed by the game's worker entry) supplies each component's toBlock/loadProperties.\n\tlet pools: { [name: string]: MemoryComponent } = {};\n\tlet eidCounter: AllocatedMemory | undefined;\n\tlet factoryConfigs: FactoryConfigs | undefined;\n\tlet factoryClasses: WorkerEntityClassRegistry | undefined;\n\tlet addsComponents = false;\n\tconst getString = (pointer: number): string => stringCache?.getString(pointer) ?? '';\n\n\tscope.onmessage = function(e) {\n\t\tconst message = e.data as EntitySystemWorkerMessage<W, D>;\n\n\t\tif(message.type === 'init') {\n\t\t\tpostMessageTyped(scope, {\n\t\t\t\ttype: 'init-complete',\n\t\t\t});\n\t\t} else if(message.type === 'load') {\n\t\t\tif(message.heap) {\n\t\t\t\theap = new MemoryHeap(message.heap);\n\t\t\t\tstringCache = new ConstantStringCache(heap);\n\t\t\t\t// Report any buffer this worker grows (while allocating off-thread) back to the main thread, which adopts\n\t\t\t\t// it and fans it out to sibling workers.\n\t\t\t\theap.addOnGrowBufferHandlers(buffer => postMessageTyped(scope, { type: 'grow-buffer-from-worker', buffer }));\n\t\t\t}\n\t\t\tif(heap && message.sharedMemory) {\n\t\t\t\tpools = {};\n\t\t\t\tfor(const name of Object.keys(message.sharedMemory.components)) {\n\t\t\t\t\tpools[name] = MemoryComponent.fromSharedMemory(heap, message.sharedMemory.components[name]);\n\t\t\t\t}\n\t\t\t\teidCounter = heap.getSharedAlloc(message.sharedMemory.eidCounter);\n\t\t\t}\n\t\t\tfactoryConfigs = message.factoryConfigs;\n\t\t\tfactoryClasses = message.factoryClasses;\n\t\t\taddsComponents = !!message.addsComponents;\n\t\t\tworldExtension = updateFunction.init?.(message.data) ?? undefined;\n\t\t\tpostMessageTyped(scope, {\n\t\t\t\ttype: 'loaded',\n\t\t\t});\n\t\t} else if(message.type === 'grow-buffer') {\n\t\t\t// Never replace a buffer this worker already holds: the main thread fans a worker-grown buffer back out to\n\t\t\t// every worker (including the one that grew it), and overwriting our own live MemoryBuffer would discard its\n\t\t\t// allocation bookkeeping. The SharedArrayBuffer at that position is already the same one.\n\t\t\tif(heap && heap.buffers[message.buffer.bufferPosition] === undefined) {\n\t\t\t\theap.addSharedBuffer(message.buffer);\n\t\t\t}\n\t\t} else if(message.type === 'reset') {\n\t\t\t// Drop the persistent lists so a reused world starts empty; worldExtension is refreshed by the next load.\n\t\t\tentities = [];\n\t\t\tfor(const key of Object.keys(queryEntities)) {\n\t\t\t\tdelete queryEntities[key];\n\t\t\t}\n\t\t\tworldExtension = undefined;\n\t\t} else if(message.type === 'run') {\n\t\t\tif(worldExtension) {\n\t\t\t\tObject.assign(message.world, worldExtension);\n\t\t\t}\n\t\t\tmessage.world.getString = getString;\n\t\t\tmessage.world.heap = heap;\n\t\t\tconst allocator = {\n\t\t\t\tallocateEid: () => eidCounter ? Atomics.add(eidCounter.data, 0, 1) + 1 : 0,\n\t\t\t\tallocateComponentBlock: (name: string, values: Array<number>) => pools[name].create(values),\n\t\t\t};\n\t\t\tmessage.world.allocate = allocator;\n\t\t\t// Only a system registered with createsEntities (factoryConfigs shipped) whose worker entry passed the\n\t\t\t// component definitions can create entities from a config.\n\t\t\tif(factoryConfigs && definitions) {\n\t\t\t\tmessage.world.buildEntityDescriptor = config => buildWorkerEntity(config, factoryConfigs!, definitions, allocator, factoryClasses);\n\t\t\t}\n\t\t\tif(addsComponents && definitions) {\n\t\t\t\tmessage.world.buildComponentDescriptor = (name, config) => buildWorkerComponent(name, config, definitions, allocator);\n\t\t\t}\n\t\t\tconst start = performance.now();\n\t\t\tlet entityEvents: Array<EntityEvent> = [];\n\t\t\tlet systemEvents: SystemEvents = {};\n\t\t\tlet createdEntities: Array<WorkerCreatedEntity> = [];\n\t\t\tlet componentChanges: Array<WorkerComponentChange> = [];\n\t\t\tlet errors: Array<WorkerRunError> = [];\n\n\t\t\tentities = applyQueryDelta(entities, message.entities as QueryDelta<T>);\n\n\t\t\tlet queries: EntityQueryComponents<C> = {};\n\t\t\tObject.entries(message.queries).forEach(([queryKey, delta]) => {\n\t\t\t\tconst list = applyQueryDelta(queryEntities[queryKey] ?? [], delta as QueryDelta<T>);\n\t\t\t\tqueryEntities[queryKey] = list;\n\t\t\t\tqueries[queryKey] = list;\n\t\t\t});\n\n\t\t\tlet callbacks: EntityWorkerSystemCallbacks<C> = {\n\t\t\t\tentityComponentChanged<K extends keyof C, P extends keyof C[K]>(entityId: number, componentName: K, prop: P, value: C[K][P]) {\n\t\t\t\t\tentityEvents.push({\n\t\t\t\t\t\tentityId,\n\t\t\t\t\t\tevent: 'component-property-updated',\n\t\t\t\t\t\targs: [componentName, prop, value],\n\t\t\t\t\t});\n\t\t\t\t},\n\t\t\t\temitEntityEvent(entityId: number, event: string, ...args: Array<unknown>) {\n\t\t\t\t\tentityEvents.push({\n\t\t\t\t\t\tentityId,\n\t\t\t\t\t\tevent,\n\t\t\t\t\t\targs,\n\t\t\t\t\t});\n\t\t\t\t},\n\t\t\t\temitSystemEvent(event: string, entityId: number) {\n\t\t\t\t\t(systemEvents[event] ?? (systemEvents[event] = [])).push(entityId);\n\t\t\t\t},\n\t\t\t\tentityDied(entityId: number) {\n\t\t\t\t\tentityEvents.push({\n\t\t\t\t\t\tentityId,\n\t\t\t\t\t\tevent: 'death',\n\t\t\t\t\t\targs: [],\n\t\t\t\t\t});\n\t\t\t\t},\n\t\t\t\tcreateEntity(entity: WorkerCreatedEntity) {\n\t\t\t\t\tcreatedEntities.push(entity);\n\t\t\t\t},\n\t\t\t\taddComponent(entityId, component) {\n\t\t\t\t\tcomponentChanges.push({ type: 'add', entityId, component });\n\t\t\t\t},\n\t\t\t\tremoveComponent(entityId, componentName) {\n\t\t\t\t\tcomponentChanges.push({ type: 'remove', entityId, componentName: String(componentName) });\n\t\t\t\t},\n\t\t\t};\n\t\t\tlet preRunFailed = false;\n\t\t\tif(updateFunction.preRun) {\n\t\t\t\ttry {\n\t\t\t\t\tupdateFunction.preRun(message.world, entities, queries, callbacks);\n\t\t\t\t} catch(err) {\n\t\t\t\t\tpreRunFailed = true;\n\t\t\t\t\terrors.push({ error: err as Error, phase: 'preRun' });\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// preRun sets up the run's state; if it threw, skip the entity loop rather than run over half-prepared data.\n\t\t\tif(!preRunFailed) {\n\t\t\t\tentities.forEach(entity => {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tupdateFunction(message.world, entity.entityId, entity.components, queries, callbacks);\n\t\t\t\t\t} catch(err) {\n\t\t\t\t\t\t// One entity failing must not stop the rest of the run.\n\t\t\t\t\t\terrors.push({ error: err as Error, phase: 'update', entityId: entity.entityId });\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tif(updateFunction.entityRemoved) {\n\t\t\t\tmessage.entities.removed.forEach(entityId => {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tupdateFunction.entityRemoved!(message.world, entityId, callbacks);\n\t\t\t\t\t} catch(err) {\n\t\t\t\t\t\terrors.push({ error: err as Error, phase: 'entityRemoved', entityId });\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t\tconst runTime = performance.now() - start;\n\n\t\t\tpostMessageTyped(scope, {\n\t\t\t\ttype: 'run-complete',\n\t\t\t\tgeneration: message.generation,\n\t\t\t\trunTime,\n\t\t\t\tevents: entityEvents,\n\t\t\t\tsystemEvents,\n\t\t\t\tcreated: createdEntities,\n\t\t\t\tcomponentChanges,\n\t\t\t\terrors,\n\t\t\t});\n\t\t}\n\t};\n}\n\nfunction postMessageTyped(scope: EntitySystemWorkerScope, message: EntitySystemWorkerMessage) {\n\tscope.postMessage(message);\n}\n","import createEntitySystemWorker, { type EntitySystemWorkerScope } from './create-entity-system-worker';\nimport type { ComponentDefinitionMap, ComponentMap } from '../../component-definition';\nimport type {\n\tEntityWorkerSystemCallbacks, EntityWorkerSystemWorld, EntityQueryComponents, EntityUpdateComponents,\n\tEntityUpdateFunction, EntityUpdateInitFunction, EntityRemovedFunction,\n} from '../entity-worker-system';\n\n// A WorkerSystem's single per-run function: called once per run over the named sub-queries, not once per entity.\n// Optional `init`/`entityRemoved` mirror EntityUpdateFunction's hooks.\nexport type WorkerSystemRunFunction<\n\tC extends ComponentMap,\n\tW extends EntityWorkerSystemWorld = EntityWorkerSystemWorld,\n\tD = unknown,\n> = ((world: W, queries: EntityQueryComponents<C>, callbacks: EntityWorkerSystemCallbacks<C>) => void) & {\n\tinit?: EntityUpdateInitFunction<W, D>\n\tentityRemoved?: EntityRemovedFunction<C, W>\n};\n\n// A WorkerSystem reuses the EntityWorkerSystem worker machinery: the single run function becomes `preRun` (which runs\n// once with query access) and the per-entity body is a no-op, since a WorkerSystem never populates its main query.\nexport function toEntityUpdateFunction<\n\tC extends ComponentMap,\n\tW extends EntityWorkerSystemWorld = EntityWorkerSystemWorld,\n\tD = unknown,\n>(run: WorkerSystemRunFunction<C, W, D>): EntityUpdateFunction<C, EntityUpdateComponents<C>, W, D> {\n\tconst updateFunction = (() => {}) as EntityUpdateFunction<C, EntityUpdateComponents<C>, W, D>;\n\tupdateFunction.preRun = (world, _entities, queries, callbacks) => run(world, queries, callbacks);\n\tif(run.init) {\n\t\tupdateFunction.init = run.init;\n\t}\n\tif(run.entityRemoved) {\n\t\tupdateFunction.entityRemoved = run.entityRemoved;\n\t}\n\n\treturn updateFunction;\n}\n\n// Worker entry helper for a WorkerSystem (mirrors createEntitySystemWorker). Pass the component registry only for a\n// worker that creates entities.\nexport default function createSystemWorker<\n\tC extends ComponentMap,\n\tW extends EntityWorkerSystemWorld = EntityWorkerSystemWorld,\n\tD = unknown,\n>(scope: EntitySystemWorkerScope, runFunction: WorkerSystemRunFunction<C, W, D>, definitions?: ComponentDefinitionMap) {\n\tcreateEntitySystemWorker(scope, toEntityUpdateFunction(runFunction), definitions);\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"create-system-worker-C4aS3-3R.js","names":[],"sources":["../src/memory-component.ts","../src/constant-string-cache.ts","../src/systems/workers/apply-query-delta.ts","../src/actions/build-worker-entity.ts","../src/component.ts","../src/entity-component.ts","../src/actions/kill-entity-worker.ts","../src/actions/create-entity-worker.ts","../src/actions/add-component-worker.ts","../src/actions/remove-component-worker.ts","../src/systems/workers/create-entity-system-worker.ts","../src/systems/workers/create-system-worker.ts"],"sourcesContent":["import SharedPool from '@daneren2005/shared-memory-objects/shared-pool';\nimport type { SharedPoolMemory } from '@daneren2005/shared-memory-objects/shared-pool';\nimport type MemoryHeap from '@daneren2005/shared-memory-objects/memory-heap';\nimport type { TypedArrayConstructor } from '@daneren2005/shared-memory-objects/interfaces/typed-array-constructor';\n\nexport type ComponentTypedArray = Uint32Array | Int32Array | Float32Array | Float64Array;\n\n// Backed by a SharedPool: all bookkeeping lives in the shared heap, so a worker can reconstruct a handle over\n// the same pool (pass the owner's getSharedMemory() as `memory`) and allocate/read blocks off-thread.\nexport default class MemoryComponent<T extends ComponentTypedArray = ComponentTypedArray> {\n\theap: MemoryHeap;\n\tpool: SharedPool<T>;\n\n\tconstructor(heap: MemoryHeap, type: TypedArrayConstructor<T>, dataLength: number, memory?: SharedPoolMemory) {\n\t\tthis.heap = heap;\n\t\tthis.pool = memory\n\t\t\t? new SharedPool<T>(heap, memory)\n\t\t\t: new SharedPool<T>(heap, {\n\t\t\t\ttype,\n\t\t\t\tdataLength,\n\t\t\t});\n\t}\n\n\t// Reconstructs a handle over an existing pool (from the owner's getSharedMemory()) — used in a worker, where the\n\t// pool's type/dataLength are already recorded in the heap header, so no definition is needed.\n\tstatic fromSharedMemory<T extends ComponentTypedArray = ComponentTypedArray>(heap: MemoryHeap, memory: SharedPoolMemory): MemoryComponent<T> {\n\t\treturn new MemoryComponent<T>(heap, Uint32Array as unknown as TypedArrayConstructor<T>, 1, memory);\n\t}\n\n\tgetSharedMemory(): SharedPoolMemory {\n\t\treturn this.pool.getSharedMemory();\n\t}\n\n\tget length() {\n\t\treturn this.pool.length;\n\t}\n\tget rawLength() {\n\t\treturn this.pool.bufferLength;\n\t}\n\n\tcreate(values: Array<number>): number {\n\t\treturn this.pool.push(values);\n\t}\n\n\tgetBlock(index: number): T {\n\t\treturn this.pool.at(index);\n\t}\n\tget(index: number, dataIndex: number): number {\n\t\treturn this.pool.get(index, dataIndex);\n\t}\n\tset(index: number, dataIndex: number, value: number) {\n\t\tlet array = this.pool.at(index);\n\t\tarray[dataIndex] = value;\n\t}\n\n\tdelete(index: number) {\n\t\tthis.pool.deleteIndex(index);\n\t}\n\tclear() {\n\t\tthis.pool.clear();\n\t}\n}\n","import ConstantString from '@daneren2005/shared-memory-objects/constant-string';\nimport { getPointer } from '@daneren2005/shared-memory-objects/utils/pointer';\nimport type MemoryHeap from '@daneren2005/shared-memory-objects/memory-heap';\n\n// Interns immutable strings in the heap and resolves them back from a pointer. Every distinct value is allocated\n// once as a single ConstantString shared by all users (15 \"Space Ship\" entities point at one allocation), and a\n// pointer resolves to its string through a Map hit before ever rebuilding it from memory. Both sides of the\n// worker boundary hold one: the main thread creates + interns; a worker (with a heap reconstructed from the same\n// SharedArrayBuffers) only ever resolves pointers and caches the results.\nexport default class ConstantStringCache {\n\tprivate heap: MemoryHeap;\n\t// value -> the one interned allocation. Only the creating (main) thread populates this; it owns the memory.\n\tprivate byValue = new Map<string, ConstantString>();\n\t// pointer -> value: the fast lookup every thread checks before touching memory.\n\tprivate byPointer = new Map<number, string>();\n\n\tconstructor(heap: MemoryHeap) {\n\t\tthis.heap = heap;\n\t}\n\n\t// Dedupes on value, so repeated types share a single ConstantString. Main-thread only.\n\tgetOrCreate(value: string): ConstantString {\n\t\tlet existing = this.byValue.get(value);\n\t\tif(existing) {\n\t\t\treturn existing;\n\t\t}\n\n\t\tconst string = new ConstantString(this.heap, value);\n\t\tthis.byValue.set(value, string);\n\t\tthis.byPointer.set(string.pointer, value);\n\n\t\treturn string;\n\t}\n\n\t// pointer -> string, checking the cache before rebuilding from memory. A pointer of 0 is the empty string; a\n\t// pointer into a buffer that has not synced to this thread yet returns undefined.\n\tgetString(pointer: number): string | undefined {\n\t\tif(pointer === 0) {\n\t\t\treturn '';\n\t\t}\n\n\t\tlet cached = this.byPointer.get(pointer);\n\t\tif(cached !== undefined) {\n\t\t\treturn cached;\n\t\t}\n\n\t\tconst memory = getPointer(pointer, this.heap.positionBits);\n\t\tif(this.heap.buffers[memory.bufferPosition] === undefined) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\tconst value = new ConstantString(this.heap, memory).value;\n\t\tthis.byPointer.set(pointer, value);\n\n\t\treturn value;\n\t}\n\n\t// Frees every allocation this cache owns and empties the lookups. A worker's cache owns nothing (it only ever\n\t// resolved views), so this just drops its pointer lookups.\n\tclear() {\n\t\tthis.byValue.forEach(string => string.free());\n\t\tthis.byValue.clear();\n\t\tthis.byPointer.clear();\n\t}\n}\n","import type { EntityUpdateComponents, QueryDelta, UpdateEntityConfigObject } from '../entity-worker-system';\n\n// Applies a run's delta to a query's persistent list: drop the entities that left, upsert those that joined or\n// changed. A steady-state run carries empty arrays and returns the list untouched. Returns the list (removals\n// rebuild it via filter), so callers must store the returned reference back.\nexport function applyQueryDelta<T extends EntityUpdateComponents>(\n\tlist: Array<UpdateEntityConfigObject<T>>,\n\tdelta: QueryDelta<T>,\n): Array<UpdateEntityConfigObject<T>> {\n\tif(delta.removed.length) {\n\t\tconst removedSet = new Set(delta.removed);\n\t\tlist = list.filter(entry => !removedSet.has(entry.entityId));\n\t}\n\n\tif(delta.added.length) {\n\t\t// Index existing members so a re-added entity replaces its entry in place instead of duplicating.\n\t\tconst indexByEid = new Map<number, number>();\n\t\tlist.forEach((entry, index) => indexByEid.set(entry.entityId, index));\n\n\t\tfor(let entity of delta.added) {\n\t\t\tconst existing = indexByEid.get(entity.entityId);\n\t\t\tif(existing !== undefined) {\n\t\t\t\tlist[existing] = entity;\n\t\t\t} else {\n\t\t\t\tindexByEid.set(entity.entityId, list.length);\n\t\t\t\tlist.push(entity);\n\t\t\t}\n\t\t}\n\t}\n\n\treturn list;\n}\n","import type { WorkerAllocator, WorkerCreateEntityConfig, WorkerCreatedComponent, WorkerCreatedEntity } from '../systems/entity-worker-system';\nimport type { WorkerEntityClassRegistry } from '../entity-class';\n\n// The slice of a component definition worker-side creation needs. Both the game's ComponentDefinitionMap and the\n// world's RegisteredComponentRegistry satisfy it.\nexport interface WorkerCreatableComponent {\n\tloadProperties: Array<string>\n\tloadInFinishLoading?: boolean\n\ttoBlock(config: Record<string, unknown>): Array<number>\n}\nexport type WorkerCreateRegistry = { [name: string]: WorkerCreatableComponent };\nexport type FactoryConfigs = { [type: string]: Record<string, unknown> };\n\n// Turns a factory-style config ({ type, ...overrides }) into a WorkerCreatedEntity, off-thread: layers the type's\n// factory template under the overrides, mints an id, and allocates + writes each triggered component's block via its\n// toBlock(). The always-present `entity` component is NOT built here - the main thread builds it on adopt (interning\n// the type is main-thread-only), reading `type`/`isStatic` off this descriptor. Shared by the real worker and the\n// main-thread fallback so both behave identically.\nexport function buildWorkerEntity(\n\tconfig: WorkerCreateEntityConfig,\n\tfactoryConfigs: FactoryConfigs,\n\tregistry: WorkerCreateRegistry,\n\tallocator: WorkerAllocator,\n\tclasses?: WorkerEntityClassRegistry,\n): WorkerCreatedEntity {\n\tconst template = factoryConfigs[config.type] ?? {};\n\tif(classes && Object.prototype.hasOwnProperty.call(config, 'class')) {\n\t\tthrow new Error('Entity class comes from its type template and cannot be supplied by a worker config');\n\t}\n\tconst merged: Record<string, unknown> = { ...template, ...config };\n\tconst entityClass = typeof template.class === 'string' ? template.class : undefined;\n\tlet componentNames = Object.keys(registry);\n\tif(classes) {\n\t\tif(template.type !== config.type) {\n\t\t\tthrow new Error(`Entity template ${config.type} must declare the same type`);\n\t\t}\n\t\tconst definition = entityClass ? classes[entityClass] : undefined;\n\t\tif(!definition) {\n\t\t\tthrow new Error(`Entity type ${config.type} has unknown class ${entityClass ?? ''}`);\n\t\t}\n\t\tcomponentNames = definition.components;\n\t}\n\n\tconst eid = allocator.allocateEid();\n\tconst components: { [name: string]: number } = {};\n\tfor(let name of componentNames) {\n\t\t// The entity component is always built on the main thread when the descriptor is adopted (interning the type),\n\t\t// never off-thread - skip it here whether or not the registry includes it.\n\t\tif(name === 'entity') {\n\t\t\tcontinue;\n\t\t}\n\t\tconst definition = registry[name];\n\t\tif(!definition) {\n\t\t\tthrow new Error(`Entity class ${entityClass ?? ''} contains unknown component ${name}`);\n\t\t}\n\t\t// Deferred components need the whole world (other entities) that a worker doesn't have; skip them.\n\t\tif(definition.loadInFinishLoading) {\n\t\t\tcontinue;\n\t\t}\n\t\tif(definition.loadProperties.some(prop => prop in merged)) {\n\t\t\tcomponents[name] = allocator.allocateComponentBlock(name, definition.toBlock(merged));\n\t\t}\n\t}\n\n\treturn {\n\t\teid,\n\t\ttype: config.type,\n\t\tclass: entityClass,\n\t\tisStatic: merged.isStatic as boolean | undefined,\n\t\tcomponents,\n\t};\n}\n\nexport function buildWorkerComponent(\n\tname: string,\n\tconfig: Record<string, unknown>,\n\tregistry: WorkerCreateRegistry,\n\tallocator: WorkerAllocator,\n): WorkerCreatedComponent {\n\tif(name === 'entity') {\n\t\tthrow new Error('The entity component cannot be added at runtime');\n\t}\n\tconst definition = registry[name];\n\tif(!definition) {\n\t\tthrow new Error(`Unknown component: ${name}`);\n\t}\n\tif(definition.loadInFinishLoading) {\n\t\tthrow new Error(`Component ${name} requires main-thread finishLoading and cannot be added in a worker`);\n\t}\n\n\treturn {\n\t\tname,\n\t\tindex: allocator.allocateComponentBlock(name, definition.toBlock(config)),\n\t};\n}\n","import type { ComponentTypedArray } from './memory-component';\nimport type { BaseComponent } from './component-definition';\n\n// Base class for a memory-backed component accessor. Subclass it, declare prototype get/set accessors over\n// `this.block` indexed by the component's exported *_INDEX constants, and return `new YourComponent(block, index)`\n// from `attach`. Because the accessors live on one shared prototype - not fresh closures captured per entity -\n// reads off thousands of entities every frame stay monomorphic and inline, and constructing a component allocates\n// just the instance instead of a closure per accessor. Components that own no extra memory need nothing else; a\n// subclass that does can take more constructor args (the entity, another pool) and store them as fields.\nexport default abstract class Component<T extends ComponentTypedArray = ComponentTypedArray> implements BaseComponent {\n\treadonly index: number;\n\treadonly block: T;\n\n\tconstructor(block: T, index: number) {\n\t\tthis.block = block;\n\t\tthis.index = index;\n\t}\n}\n","import type { ComponentDefinition } from './component-definition';\nimport Component from './component';\nimport type ConstantStringCache from './constant-string-cache';\n\nexport interface EntityComponent {\n\tindex: number\n\treadonly type: string\n\treadonly class: string\n\tdead: boolean\n\tisStatic: boolean\n}\n\nexport interface EntityComponentConfig {\n\ttype: string\n\tisStatic?: boolean\n}\n\nexport interface EntityClassConfig {\n\treadonly class: string\n}\n\nexport interface EntityComponentSerialization {\n\ttype?: string\n\tdead?: boolean\n}\n\nexport const DEAD_INDEX = 0;\nexport const STATIC_INDEX = 1;\nexport const TYPE_INDEX = 2;\nexport const CLASS_INDEX = 3;\n\n// Identity strings are interned, so the accessor needs the world's cache to resolve their pointers.\nclass EntityComponentImpl extends Component<Uint32Array> implements EntityComponent {\n\tprivate cache: ConstantStringCache;\n\n\tconstructor(block: Uint32Array, index: number, cache: ConstantStringCache) {\n\t\tsuper(block, index);\n\t\tthis.cache = cache;\n\t}\n\n\tget type() {\n\t\treturn this.cache.getString(this.block[TYPE_INDEX]) ?? '';\n\t}\n\tget class() {\n\t\treturn this.cache.getString(this.block[CLASS_INDEX]) ?? '';\n\t}\n\tget dead() {\n\t\treturn this.block[DEAD_INDEX] === 1;\n\t}\n\tset dead(value: boolean) {\n\t\tthis.block[DEAD_INDEX] = value ? 1 : 0;\n\t}\n\tget isStatic() {\n\t\treturn this.block[STATIC_INDEX] === 1;\n\t}\n\tset isStatic(value: boolean) {\n\t\tthis.block[STATIC_INDEX] = value ? 1 : 0;\n\t}\n}\n\nexport const entityDefinition: ComponentDefinition<EntityComponent, Uint32Array, EntityComponentConfig & Partial<EntityClassConfig>, EntityComponentSerialization> = {\n\ttype: Uint32Array,\n\tsize: 4,\n\tloadProperties: ['type', 'isStatic'],\n\t// The only component that reads the entity (never worker-created): it interns its identity strings through the heap and\n\t// stores the pointer. `entity` is always passed here since loadComponent runs on the main thread.\n\ttoBlock(config, entity) {\n\t\tconst cache = entity!.world.constantStrings;\n\t\tconst typePointer = config.type ? cache.getOrCreate(config.type).pointer : 0;\n\t\tconst classPointer = config.class ? cache.getOrCreate(config.class).pointer : 0;\n\t\treturn [config.dead ? 1 : 0, config.isStatic ? 1 : 0, typePointer, classPointer];\n\t},\n\tattach(entity, memory, index) {\n\t\treturn new EntityComponentImpl(memory.getBlock(index), index, entity.world.constantStrings);\n\t},\n\tsave(component) {\n\t\tconst config: EntityComponentSerialization = {};\n\t\tif(component.type) {\n\t\t\tconfig.type = component.type;\n\t\t}\n\t\tif(component.dead) {\n\t\t\tconfig.dead = true;\n\t\t}\n\n\t\treturn config;\n\t},\n};\n","import type { ComponentTypedArray } from '../memory-component';\nimport type { EntityWorkerSystemCallbacks, EntityUpdateComponents } from '../systems/entity-worker-system';\nimport { DEAD_INDEX } from '../entity-component';\n\n// Worker-side killEntity: flags the entity dead in its block and reports the death back via callbacks. The\n// entity component must be in the system's query for its block to be available here.\nexport default function killEntityWorker(entityId: number, components: EntityUpdateComponents, callbacks: EntityWorkerSystemCallbacks): void {\n\tconst block = (components as { entity?: ComponentTypedArray }).entity;\n\tif(block) {\n\t\tblock[DEAD_INDEX] = 1;\n\t}\n\n\tcallbacks.entityDied(entityId);\n}\n","import type { EntityWorkerSystemCallbacks, EntityWorkerSystemWorld, WorkerCreateEntityConfig } from '../systems/entity-worker-system';\n\n// Worker-side entity creation from a factory config. The worker merges the selected type template, resolves its\n// optional class, mints a unique id, and allocates + writes every allowed, triggered component block\n// directly into the shared pools (off-thread) via each component's toBlock(). It reports the descriptor back; the main\n// thread adopts it on run-complete (world.adoptEntity), building the `entity` component and class wrapper there\n// worker-written blocks, so the entity first exists on the following frame.\n//\n// Requires the system to be registered with `createsEntities: true` and its worker entry to pass the component\n// registry to createEntitySystemWorker (so the worker has each component's toBlock).\nexport default function createEntityWorker(world: EntityWorkerSystemWorld, config: WorkerCreateEntityConfig, callbacks: EntityWorkerSystemCallbacks): void {\n\tif(!world.buildEntityDescriptor) {\n\t\tthrow new Error('createEntityWorker requires the system to be registered with createsEntities: true and the component registry passed to createEntitySystemWorker');\n\t}\n\n\tcallbacks.createEntity(world.buildEntityDescriptor(config));\n}\n","import type { ComponentMap } from '../component-definition';\nimport type { EntityWorkerSystemCallbacks, EntityWorkerSystemWorld } from '../systems/entity-worker-system';\n\n// Allocates a component block in the worker and asks the main thread to attach it after the run. The entity's\n// current query snapshot is intentionally unchanged until the next run.\nexport default function addComponentWorker<C extends ComponentMap, K extends keyof C>(\n\tworld: EntityWorkerSystemWorld,\n\tentityId: number,\n\tcomponentName: K,\n\tconfig: Record<string, unknown>,\n\tcallbacks: EntityWorkerSystemCallbacks<C>,\n): void {\n\tif(!world.buildComponentDescriptor) {\n\t\tthrow new Error('addComponentWorker requires addsComponents: true and the component registry passed to createEntitySystemWorker');\n\t}\n\n\tcallbacks.addComponent(entityId, world.buildComponentDescriptor(String(componentName), config));\n}\n","import type { ComponentMap } from '../component-definition';\nimport type { EntityWorkerSystemCallbacks } from '../systems/entity-worker-system';\n\n// Requests a main-thread detach after the worker run. Shared memory is freed only after every system that could\n// still hold the old block has completed a run.\nexport default function removeComponentWorker<C extends ComponentMap, K extends keyof C>(\n\tentityId: number,\n\tcomponentName: K,\n\tcallbacks: EntityWorkerSystemCallbacks<C>,\n): void {\n\tcallbacks.removeComponent(entityId, componentName);\n}\n","import MemoryHeap from '@daneren2005/shared-memory-objects/memory-heap';\nimport type AllocatedMemory from '@daneren2005/shared-memory-objects/allocated-memory';\nimport type EntitySystemWorkerMessage from './entity-system-worker-message';\nimport type { EntityEvent, SystemEvents, WorkerRunError } from './entity-system-worker-message';\nimport ConstantStringCache from '../../constant-string-cache';\nimport MemoryComponent from '../../memory-component';\nimport type { ComponentDefinitionMap, ComponentMap } from '../../component-definition';\nimport type {\n\tEntityWorkerSystemCallbacks, EntityWorkerSystemWorld, EntityQueryComponents, EntityUpdateComponents,\n\tEntityUpdateFunction, QueryDelta, UpdateEntityConfigObject, WorkerComponentChange, WorkerCreatedEntity,\n} from '../entity-worker-system';\nimport { buildWorkerComponent, buildWorkerEntity, type FactoryConfigs } from '../../actions/build-worker-entity';\nimport type { WorkerEntityClassRegistry } from '../../entity-class';\nimport { applyQueryDelta } from './apply-query-delta';\n\n// The slice of the worker global scope createEntitySystemWorker touches. Passing `self` explicitly (rather than\n// using the global) lets runners like @vitest/web-worker, which inject `self` as a module local, drive it.\nexport interface EntitySystemWorkerScope {\n\tonmessage: ((e: MessageEvent) => void) | null\n\tpostMessage(message: EntitySystemWorkerMessage): void\n}\n\nexport default function createEntitySystemWorker<\n\tC extends ComponentMap,\n\tT extends EntityUpdateComponents<C>,\n\tW extends EntityWorkerSystemWorld = EntityWorkerSystemWorld,\n\tD = unknown,\n>(scope: EntitySystemWorkerScope, updateFunction: EntityUpdateFunction<C, T, W, D>, definitions?: ComponentDefinitionMap) {\n\t// Persistent lists, carried across runs and mutated by each run's delta (see applyQueryDelta).\n\tlet entities: Array<UpdateEntityConfigObject<T>> = [];\n\tconst queryEntities: { [key: string]: Array<UpdateEntityConfigObject<T>> } = {};\n\t// What updateFunction.init returned: persistent state (e.g. a seeded RNG) merged onto `world` each run.\n\tlet worldExtension: Partial<W> | undefined;\n\tlet heap: MemoryHeap | undefined;\n\tlet stringCache: ConstantStringCache | undefined;\n\t// Reconstructed pool handles over the world's shared state, plus the factory templates - for off-thread entity\n\t// allocation. `definitions` (passed by the game's worker entry) supplies each component's toBlock/loadProperties.\n\tlet pools: { [name: string]: MemoryComponent } = {};\n\tlet eidCounter: AllocatedMemory | undefined;\n\tlet factoryConfigs: FactoryConfigs | undefined;\n\tlet factoryClasses: WorkerEntityClassRegistry | undefined;\n\tlet addsComponents = false;\n\tconst getString = (pointer: number): string => stringCache?.getString(pointer) ?? '';\n\n\tscope.onmessage = function(e) {\n\t\tconst message = e.data as EntitySystemWorkerMessage<W, D>;\n\n\t\tif(message.type === 'init') {\n\t\t\tpostMessageTyped(scope, {\n\t\t\t\ttype: 'init-complete',\n\t\t\t});\n\t\t} else if(message.type === 'load') {\n\t\t\tif(message.heap) {\n\t\t\t\theap = new MemoryHeap(message.heap);\n\t\t\t\tstringCache = new ConstantStringCache(heap);\n\t\t\t\t// Report any buffer this worker grows (while allocating off-thread) back to the main thread, which adopts\n\t\t\t\t// it and fans it out to sibling workers.\n\t\t\t\theap.addOnGrowBufferHandlers(buffer => postMessageTyped(scope, { type: 'grow-buffer-from-worker', buffer }));\n\t\t\t}\n\t\t\tif(heap && message.sharedMemory) {\n\t\t\t\tpools = {};\n\t\t\t\tfor(const name of Object.keys(message.sharedMemory.components)) {\n\t\t\t\t\tpools[name] = MemoryComponent.fromSharedMemory(heap, message.sharedMemory.components[name]);\n\t\t\t\t}\n\t\t\t\teidCounter = heap.getSharedAlloc(message.sharedMemory.eidCounter);\n\t\t\t}\n\t\t\tfactoryConfigs = message.factoryConfigs;\n\t\t\tfactoryClasses = message.factoryClasses;\n\t\t\taddsComponents = !!message.addsComponents;\n\t\t\tworldExtension = updateFunction.init?.(message.data) ?? undefined;\n\t\t\tpostMessageTyped(scope, {\n\t\t\t\ttype: 'loaded',\n\t\t\t});\n\t\t} else if(message.type === 'grow-buffer') {\n\t\t\t// Never replace a buffer this worker already holds: the main thread fans a worker-grown buffer back out to\n\t\t\t// every worker (including the one that grew it), and overwriting our own live MemoryBuffer would discard its\n\t\t\t// allocation bookkeeping. The SharedArrayBuffer at that position is already the same one.\n\t\t\tif(heap && heap.buffers[message.buffer.bufferPosition] === undefined) {\n\t\t\t\theap.addSharedBuffer(message.buffer);\n\t\t\t}\n\t\t} else if(message.type === 'reset') {\n\t\t\t// Drop the persistent lists so a reused world starts empty; worldExtension is refreshed by the next load.\n\t\t\tentities = [];\n\t\t\tfor(const key of Object.keys(queryEntities)) {\n\t\t\t\tdelete queryEntities[key];\n\t\t\t}\n\t\t\tworldExtension = undefined;\n\t\t} else if(message.type === 'run') {\n\t\t\tif(worldExtension) {\n\t\t\t\tObject.assign(message.world, worldExtension);\n\t\t\t}\n\t\t\tmessage.world.getString = getString;\n\t\t\tmessage.world.heap = heap;\n\t\t\tconst allocator = {\n\t\t\t\tallocateEid: () => eidCounter ? Atomics.add(eidCounter.data, 0, 1) + 1 : 0,\n\t\t\t\tallocateComponentBlock: (name: string, values: Array<number>) => pools[name].create(values),\n\t\t\t};\n\t\t\tmessage.world.allocate = allocator;\n\t\t\t// Only a system registered with createsEntities (factoryConfigs shipped) whose worker entry passed the\n\t\t\t// component definitions can create entities from a config.\n\t\t\tif(factoryConfigs && definitions) {\n\t\t\t\tmessage.world.buildEntityDescriptor = config => buildWorkerEntity(config, factoryConfigs!, definitions, allocator, factoryClasses);\n\t\t\t}\n\t\t\tif(addsComponents && definitions) {\n\t\t\t\tmessage.world.buildComponentDescriptor = (name, config) => buildWorkerComponent(name, config, definitions, allocator);\n\t\t\t}\n\t\t\tconst start = performance.now();\n\t\t\tlet entityEvents: Array<EntityEvent> = [];\n\t\t\tlet systemEvents: SystemEvents = {};\n\t\t\tlet createdEntities: Array<WorkerCreatedEntity> = [];\n\t\t\tlet componentChanges: Array<WorkerComponentChange> = [];\n\t\t\tlet errors: Array<WorkerRunError> = [];\n\n\t\t\tentities = applyQueryDelta(entities, message.entities as QueryDelta<T>);\n\n\t\t\tlet queries: EntityQueryComponents<C> = {};\n\t\t\tObject.entries(message.queries).forEach(([queryKey, delta]) => {\n\t\t\t\tconst list = applyQueryDelta(queryEntities[queryKey] ?? [], delta as QueryDelta<T>);\n\t\t\t\tqueryEntities[queryKey] = list;\n\t\t\t\tqueries[queryKey] = list;\n\t\t\t});\n\n\t\t\tlet callbacks: EntityWorkerSystemCallbacks<C> = {\n\t\t\t\tentityComponentChanged<K extends keyof C, P extends keyof C[K]>(entityId: number, componentName: K, prop: P, value: C[K][P]) {\n\t\t\t\t\tentityEvents.push({\n\t\t\t\t\t\tentityId,\n\t\t\t\t\t\tevent: 'component-property-updated',\n\t\t\t\t\t\targs: [componentName, prop, value],\n\t\t\t\t\t});\n\t\t\t\t},\n\t\t\t\temitEntityEvent(entityId: number, event: string, ...args: Array<unknown>) {\n\t\t\t\t\tentityEvents.push({\n\t\t\t\t\t\tentityId,\n\t\t\t\t\t\tevent,\n\t\t\t\t\t\targs,\n\t\t\t\t\t});\n\t\t\t\t},\n\t\t\t\temitSystemEvent(event: string, entityId: number) {\n\t\t\t\t\t(systemEvents[event] ?? (systemEvents[event] = [])).push(entityId);\n\t\t\t\t},\n\t\t\t\tentityDied(entityId: number) {\n\t\t\t\t\tentityEvents.push({\n\t\t\t\t\t\tentityId,\n\t\t\t\t\t\tevent: 'death',\n\t\t\t\t\t\targs: [],\n\t\t\t\t\t});\n\t\t\t\t},\n\t\t\t\tcreateEntity(entity: WorkerCreatedEntity) {\n\t\t\t\t\tcreatedEntities.push(entity);\n\t\t\t\t},\n\t\t\t\taddComponent(entityId, component) {\n\t\t\t\t\tcomponentChanges.push({ type: 'add', entityId, component });\n\t\t\t\t},\n\t\t\t\tremoveComponent(entityId, componentName) {\n\t\t\t\t\tcomponentChanges.push({ type: 'remove', entityId, componentName: String(componentName) });\n\t\t\t\t},\n\t\t\t};\n\t\t\tif(updateFunction.queryChanged) {\n\t\t\t\tfor(const [queryName, delta] of Object.entries(message.queries)) {\n\t\t\t\t\tif(!delta.added.length && !delta.removed.length) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\ttry {\n\t\t\t\t\t\tupdateFunction.queryChanged(message.world, queryName, delta, callbacks);\n\t\t\t\t\t} catch(err) {\n\t\t\t\t\t\terrors.push({ error: err as Error, phase: 'queryChanged' });\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tlet preRunFailed = false;\n\t\t\tif(updateFunction.preRun) {\n\t\t\t\ttry {\n\t\t\t\t\tupdateFunction.preRun(message.world, entities, queries, callbacks);\n\t\t\t\t} catch(err) {\n\t\t\t\t\tpreRunFailed = true;\n\t\t\t\t\terrors.push({ error: err as Error, phase: 'preRun' });\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// preRun sets up the run's state; if it threw, skip the entity loop rather than run over half-prepared data.\n\t\t\tif(!preRunFailed) {\n\t\t\t\tentities.forEach(entity => {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tupdateFunction(message.world, entity.entityId, entity.components, queries, callbacks);\n\t\t\t\t\t} catch(err) {\n\t\t\t\t\t\t// One entity failing must not stop the rest of the run.\n\t\t\t\t\t\terrors.push({ error: err as Error, phase: 'update', entityId: entity.entityId });\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tif(updateFunction.entityRemoved) {\n\t\t\t\tmessage.entities.removed.forEach(entityId => {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tupdateFunction.entityRemoved!(message.world, entityId, callbacks);\n\t\t\t\t\t} catch(err) {\n\t\t\t\t\t\terrors.push({ error: err as Error, phase: 'entityRemoved', entityId });\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t\tconst runTime = performance.now() - start;\n\n\t\t\tpostMessageTyped(scope, {\n\t\t\t\ttype: 'run-complete',\n\t\t\t\tgeneration: message.generation,\n\t\t\t\trunTime,\n\t\t\t\tevents: entityEvents,\n\t\t\t\tsystemEvents,\n\t\t\t\tcreated: createdEntities,\n\t\t\t\tcomponentChanges,\n\t\t\t\terrors,\n\t\t\t});\n\t\t}\n\t};\n}\n\nfunction postMessageTyped(scope: EntitySystemWorkerScope, message: EntitySystemWorkerMessage) {\n\tscope.postMessage(message);\n}\n","import createEntitySystemWorker, { type EntitySystemWorkerScope } from './create-entity-system-worker';\nimport type { ComponentDefinitionMap, ComponentMap } from '../../component-definition';\nimport type {\n\tEntityWorkerSystemCallbacks, EntityWorkerSystemWorld, EntityQueryComponents, EntityUpdateComponents,\n\tEntityUpdateFunction, EntityUpdateInitFunction, EntityRemovedFunction, EntityQueryChangedFunction,\n} from '../entity-worker-system';\n\n// A WorkerSystem's single per-run function: called once per run over the named sub-queries, not once per entity.\n// Optional `init`/`queryChanged`/`entityRemoved` mirror EntityUpdateFunction's hooks.\nexport type WorkerSystemRunFunction<\n\tC extends ComponentMap,\n\tW extends EntityWorkerSystemWorld = EntityWorkerSystemWorld,\n\tD = unknown,\n> = ((world: W, queries: EntityQueryComponents<C>, callbacks: EntityWorkerSystemCallbacks<C>) => void) & {\n\tinit?: EntityUpdateInitFunction<W, D>\n\tqueryChanged?: EntityQueryChangedFunction<C, W>\n\tentityRemoved?: EntityRemovedFunction<C, W>\n};\n\n// A WorkerSystem reuses the EntityWorkerSystem worker machinery: the single run function becomes `preRun` (which runs\n// once with query access) and the per-entity body is a no-op, since a WorkerSystem never populates its main query.\nexport function toEntityUpdateFunction<\n\tC extends ComponentMap,\n\tW extends EntityWorkerSystemWorld = EntityWorkerSystemWorld,\n\tD = unknown,\n>(run: WorkerSystemRunFunction<C, W, D>): EntityUpdateFunction<C, EntityUpdateComponents<C>, W, D> {\n\tconst updateFunction = (() => {}) as EntityUpdateFunction<C, EntityUpdateComponents<C>, W, D>;\n\tupdateFunction.preRun = (world, _entities, queries, callbacks) => run(world, queries, callbacks);\n\tif(run.init) {\n\t\tupdateFunction.init = run.init;\n\t}\n\tif(run.queryChanged) {\n\t\tupdateFunction.queryChanged = run.queryChanged;\n\t}\n\tif(run.entityRemoved) {\n\t\tupdateFunction.entityRemoved = run.entityRemoved;\n\t}\n\n\treturn updateFunction;\n}\n\n// Worker entry helper for a WorkerSystem (mirrors createEntitySystemWorker). Pass the component registry only for a\n// worker that creates entities.\nexport default function createSystemWorker<\n\tC extends ComponentMap,\n\tW extends EntityWorkerSystemWorld = EntityWorkerSystemWorld,\n\tD = unknown,\n>(scope: EntitySystemWorkerScope, runFunction: WorkerSystemRunFunction<C, W, D>, definitions?: ComponentDefinitionMap) {\n\tcreateEntitySystemWorker(scope, toEntityUpdateFunction(runFunction), definitions);\n}\n"],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -27,7 +27,7 @@ export type { EntitySystemConfig } from './systems/entity-system';
27
27
  export { default as EntityWorkerSystem } from './systems/entity-worker-system';
28
28
  export { default as WorkerSystem } from './systems/worker-system';
29
29
  export type { WorkerSystemConfig, WorkerSystemRunFunction } from './systems/worker-system';
30
- export type { EntityWorkerSystemConfig, EntityWorkerSystemQuery, EntityWorkerSystemWorld, EntityWorkerSystemCallbacks, WorkerAllocator, WorkerCreateEntityConfig, WorkerCreatedEntity, WorkerCreatedComponent, WorkerComponentChange, EntityUpdateComponents, EntityQueryComponents, EntityUpdateFunction, EntityUpdateInitFunction, EntityUpdatePreRunFunction, EntityRemovedFunction, UpdateEntityConfig, UpdateEntityConfigObject, } from './systems/entity-worker-system';
30
+ export type { EntityWorkerSystemConfig, EntityWorkerSystemQuery, EntityWorkerSystemWorld, EntityWorkerSystemCallbacks, WorkerAllocator, WorkerCreateEntityConfig, WorkerCreatedEntity, WorkerCreatedComponent, WorkerComponentChange, EntityUpdateComponents, EntityQueryComponents, EntityUpdateFunction, EntityUpdateInitFunction, EntityUpdatePreRunFunction, EntityQueryChangedFunction, QueryDelta, EntityRemovedFunction, UpdateEntityConfig, UpdateEntityConfigObject, } from './systems/entity-worker-system';
31
31
  export { default as WebWorker } from './systems/workers/web-worker';
32
32
  export { default as EntitySystemWebWorker } from './systems/workers/entity-system-web-worker';
33
33
  export { default as createEntitySystemWorker } from './systems/workers/create-entity-system-worker';
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { _ as e, a as t, c as n, d as r, f as i, g as a, h as o, i as s, l as c, m as l, n as u, o as d, p as f, r as p, s as m, t as h, u as g, v as _ } from "./create-system-worker-CDQmmww7.js";
1
+ import { _ as e, a as t, c as n, d as r, f as i, g as a, h as o, i as s, l as c, m as l, n as u, o as d, p as f, r as p, s as m, t as h, u as g, v as _ } from "./create-system-worker-C4aS3-3R.js";
2
2
  import v from "@daneren2005/shared-memory-objects/memory-heap";
3
3
  import { MAX_BYTE_OFFSET_LENGTH as y } from "@daneren2005/shared-memory-objects/utils/pointer";
4
4
  //#region \0rolldown/runtime.js
@@ -8,7 +8,7 @@ var b = Object.create, x = Object.defineProperty, S = Object.getOwnPropertyDescr
8
8
  enumerable: !(r = S(t, s)) || r.enumerable
9
9
  });
10
10
  return e;
11
- }, O = /* @__PURE__ */ ((e, t, n) => (n = e == null ? {} : b(w(e)), D(t || !e || !e.__esModule ? x(n, "default", {
11
+ }, O = /* @__PURE__ */ ((e, t, n) => (n = e == null ? {} : b(w(e)), D(t || !e || !e.__esModule || !T.call(e, "default") ? x(n, "default", {
12
12
  value: e,
13
13
  enumerable: !0
14
14
  }) : n, e)))((/* @__PURE__ */ E(((e, t) => {
@@ -116,7 +116,8 @@ var b = Object.create, x = Object.defineProperty, S = Object.getOwnPropertyDescr
116
116
  if (this.currentDelta += e, this.currentDelta >= this.deltaBetweenRuns || this.firstRun) {
117
117
  let e = 0;
118
118
  return this.deltaBetweenRuns > 0 && (e = this.currentDelta % this.deltaBetweenRuns), this.run(this.currentDelta - e), this.currentDelta = e, this.firstRun = !1, this.onRunFinished(), !0;
119
- } else return !1;
119
+ }
120
+ return !1;
120
121
  }
121
122
  onError(e, t = {}) {
122
123
  let n = t.entityId === void 0 ? "" : ` (entity ${t.entityId})`;
@@ -316,7 +317,18 @@ var b = Object.create, x = Object.defineProperty, S = Object.getOwnPropertyDescr
316
317
  componentName: String(t)
317
318
  });
318
319
  }
319
- }, f = !1;
320
+ };
321
+ if (this.updateFunction.queryChanged) {
322
+ for (let [t, n] of Object.entries(e.queries)) if (n.added.length || n.removed.length) try {
323
+ this.updateFunction.queryChanged(e.world, t, n, d);
324
+ } catch (e) {
325
+ c.push({
326
+ error: e,
327
+ phase: "queryChanged"
328
+ });
329
+ }
330
+ }
331
+ let f = !1;
320
332
  if (this.updateFunction.preRun) try {
321
333
  this.updateFunction.preRun(e.world, this.entities, u, d);
322
334
  } catch (e) {
@@ -593,7 +605,7 @@ var b = Object.create, x = Object.defineProperty, S = Object.getOwnPropertyDescr
593
605
  }
594
606
  loadComponent(e, t, n = !0) {
595
607
  this.assertComponentAllowed(e);
596
- let r = this.world.registry[e], i = r.memoryComponent, a = i.create(r.toBlock(t, this)), o = r.attach(this, i, a);
608
+ let r = this.world.registry[e], i = r.memoryComponent, a = i.create(r.toBlock(t, this)), o = r.attach(this, i, a, t);
597
609
  return o.block ??= i.getBlock(a), this.components[e] = o, n && this.emit("component-added", e, o), o;
598
610
  }
599
611
  attachComponent(e, t, n = !1) {
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../node_modules/eventemitter3/index.js","../node_modules/eventemitter3/index.mjs","../src/systems/system.ts","../src/systems/iterable-system.ts","../src/systems/entity-system.ts","../src/systems/workers/web-worker.ts","../src/systems/workers/entity-system-web-worker.ts","../src/systems/entity-worker-system.ts","../src/entity.ts","../src/entity-factory.ts","../src/world.ts","../src/entity-class.ts","../src/actions/kill-entity.ts","../src/performance-timing.ts","../src/systems/worker-system.ts"],"sourcesContent":["'use strict';\n\nvar has = Object.prototype.hasOwnProperty\n , prefix = '~';\n\n/**\n * Constructor to create a storage for our `EE` objects.\n * An `Events` instance is a plain object whose properties are event names.\n *\n * @constructor\n * @private\n */\nfunction Events() {}\n\n//\n// We try to not inherit from `Object.prototype`. In some engines creating an\n// instance in this way is faster than calling `Object.create(null)` directly.\n// If `Object.create(null)` is not supported we prefix the event names with a\n// character to make sure that the built-in object properties are not\n// overridden or used as an attack vector.\n//\nif (Object.create) {\n Events.prototype = Object.create(null);\n\n //\n // This hack is needed because the `__proto__` property is still inherited in\n // some old browsers like Android 4, iPhone 5.1, Opera 11 and Safari 5.\n //\n if (!new Events().__proto__) prefix = false;\n}\n\n/**\n * Representation of a single event listener.\n *\n * @param {Function} fn The listener function.\n * @param {*} context The context to invoke the listener with.\n * @param {Boolean} [once=false] Specify if the listener is a one-time listener.\n * @constructor\n * @private\n */\nfunction EE(fn, context, once) {\n this.fn = fn;\n this.context = context;\n this.once = once || false;\n}\n\n/**\n * Add a listener for a given event.\n *\n * @param {EventEmitter} emitter Reference to the `EventEmitter` instance.\n * @param {(String|Symbol)} event The event name.\n * @param {Function} fn The listener function.\n * @param {*} context The context to invoke the listener with.\n * @param {Boolean} once Specify if the listener is a one-time listener.\n * @returns {EventEmitter}\n * @private\n */\nfunction addListener(emitter, event, fn, context, once) {\n if (typeof fn !== 'function') {\n throw new TypeError('The listener must be a function');\n }\n\n var listener = new EE(fn, context || emitter, once)\n , evt = prefix ? prefix + event : event;\n\n if (!emitter._events[evt]) emitter._events[evt] = listener, emitter._eventsCount++;\n else if (!emitter._events[evt].fn) emitter._events[evt].push(listener);\n else emitter._events[evt] = [emitter._events[evt], listener];\n\n return emitter;\n}\n\n/**\n * Clear event by name.\n *\n * @param {EventEmitter} emitter Reference to the `EventEmitter` instance.\n * @param {(String|Symbol)} evt The Event name.\n * @private\n */\nfunction clearEvent(emitter, evt) {\n if (--emitter._eventsCount === 0) emitter._events = new Events();\n else delete emitter._events[evt];\n}\n\n/**\n * Minimal `EventEmitter` interface that is molded against the Node.js\n * `EventEmitter` interface.\n *\n * @constructor\n * @public\n */\nfunction EventEmitter() {\n this._events = new Events();\n this._eventsCount = 0;\n}\n\n/**\n * Return an array listing the events for which the emitter has registered\n * listeners.\n *\n * @returns {Array}\n * @public\n */\nEventEmitter.prototype.eventNames = function eventNames() {\n var names = []\n , events\n , name;\n\n if (this._eventsCount === 0) return names;\n\n for (name in (events = this._events)) {\n if (has.call(events, name)) names.push(prefix ? name.slice(1) : name);\n }\n\n if (Object.getOwnPropertySymbols) {\n return names.concat(Object.getOwnPropertySymbols(events));\n }\n\n return names;\n};\n\n/**\n * Return the listeners registered for a given event.\n *\n * @param {(String|Symbol)} event The event name.\n * @returns {Array} The registered listeners.\n * @public\n */\nEventEmitter.prototype.listeners = function listeners(event) {\n var evt = prefix ? prefix + event : event\n , handlers = this._events[evt];\n\n if (!handlers) return [];\n if (handlers.fn) return [handlers.fn];\n\n for (var i = 0, l = handlers.length, ee = new Array(l); i < l; i++) {\n ee[i] = handlers[i].fn;\n }\n\n return ee;\n};\n\n/**\n * Return the number of listeners listening to a given event.\n *\n * @param {(String|Symbol)} event The event name.\n * @returns {Number} The number of listeners.\n * @public\n */\nEventEmitter.prototype.listenerCount = function listenerCount(event) {\n var evt = prefix ? prefix + event : event\n , listeners = this._events[evt];\n\n if (!listeners) return 0;\n if (listeners.fn) return 1;\n return listeners.length;\n};\n\n/**\n * Calls each of the listeners registered for a given event.\n *\n * @param {(String|Symbol)} event The event name.\n * @returns {Boolean} `true` if the event had listeners, else `false`.\n * @public\n */\nEventEmitter.prototype.emit = function emit(event, a1, a2, a3, a4, a5) {\n var evt = prefix ? prefix + event : event;\n\n if (!this._events[evt]) return false;\n\n var listeners = this._events[evt]\n , len = arguments.length\n , args\n , i;\n\n if (listeners.fn) {\n if (listeners.once) this.removeListener(event, listeners.fn, undefined, true);\n\n switch (len) {\n case 1: return listeners.fn.call(listeners.context), true;\n case 2: return listeners.fn.call(listeners.context, a1), true;\n case 3: return listeners.fn.call(listeners.context, a1, a2), true;\n case 4: return listeners.fn.call(listeners.context, a1, a2, a3), true;\n case 5: return listeners.fn.call(listeners.context, a1, a2, a3, a4), true;\n case 6: return listeners.fn.call(listeners.context, a1, a2, a3, a4, a5), true;\n }\n\n for (i = 1, args = new Array(len -1); i < len; i++) {\n args[i - 1] = arguments[i];\n }\n\n listeners.fn.apply(listeners.context, args);\n } else {\n var length = listeners.length\n , j;\n\n for (i = 0; i < length; i++) {\n if (listeners[i].once) this.removeListener(event, listeners[i].fn, undefined, true);\n\n switch (len) {\n case 1: listeners[i].fn.call(listeners[i].context); break;\n case 2: listeners[i].fn.call(listeners[i].context, a1); break;\n case 3: listeners[i].fn.call(listeners[i].context, a1, a2); break;\n case 4: listeners[i].fn.call(listeners[i].context, a1, a2, a3); break;\n default:\n if (!args) for (j = 1, args = new Array(len -1); j < len; j++) {\n args[j - 1] = arguments[j];\n }\n\n listeners[i].fn.apply(listeners[i].context, args);\n }\n }\n }\n\n return true;\n};\n\n/**\n * Add a listener for a given event.\n *\n * @param {(String|Symbol)} event The event name.\n * @param {Function} fn The listener function.\n * @param {*} [context=this] The context to invoke the listener with.\n * @returns {EventEmitter} `this`.\n * @public\n */\nEventEmitter.prototype.on = function on(event, fn, context) {\n return addListener(this, event, fn, context, false);\n};\n\n/**\n * Add a one-time listener for a given event.\n *\n * @param {(String|Symbol)} event The event name.\n * @param {Function} fn The listener function.\n * @param {*} [context=this] The context to invoke the listener with.\n * @returns {EventEmitter} `this`.\n * @public\n */\nEventEmitter.prototype.once = function once(event, fn, context) {\n return addListener(this, event, fn, context, true);\n};\n\n/**\n * Remove the listeners of a given event.\n *\n * @param {(String|Symbol)} event The event name.\n * @param {Function} fn Only remove the listeners that match this function.\n * @param {*} context Only remove the listeners that have this context.\n * @param {Boolean} once Only remove one-time listeners.\n * @returns {EventEmitter} `this`.\n * @public\n */\nEventEmitter.prototype.removeListener = function removeListener(event, fn, context, once) {\n var evt = prefix ? prefix + event : event;\n\n if (!this._events[evt]) return this;\n if (!fn) {\n clearEvent(this, evt);\n return this;\n }\n\n var listeners = this._events[evt];\n\n if (listeners.fn) {\n if (\n listeners.fn === fn &&\n (!once || listeners.once) &&\n (!context || listeners.context === context)\n ) {\n clearEvent(this, evt);\n }\n } else {\n for (var i = 0, events = [], length = listeners.length; i < length; i++) {\n if (\n listeners[i].fn !== fn ||\n (once && !listeners[i].once) ||\n (context && listeners[i].context !== context)\n ) {\n events.push(listeners[i]);\n }\n }\n\n //\n // Reset the array, or remove it completely if we have no more listeners.\n //\n if (events.length) this._events[evt] = events.length === 1 ? events[0] : events;\n else clearEvent(this, evt);\n }\n\n return this;\n};\n\n/**\n * Remove all listeners, or those of the specified event.\n *\n * @param {(String|Symbol)} [event] The event name.\n * @returns {EventEmitter} `this`.\n * @public\n */\nEventEmitter.prototype.removeAllListeners = function removeAllListeners(event) {\n var evt;\n\n if (event) {\n evt = prefix ? prefix + event : event;\n if (this._events[evt]) clearEvent(this, evt);\n } else {\n this._events = new Events();\n this._eventsCount = 0;\n }\n\n return this;\n};\n\n//\n// Alias methods names because people roll like that.\n//\nEventEmitter.prototype.off = EventEmitter.prototype.removeListener;\nEventEmitter.prototype.addListener = EventEmitter.prototype.on;\n\n//\n// Expose the prefix.\n//\nEventEmitter.prefixed = prefix;\n\n//\n// Allow `EventEmitter` to be imported as module namespace.\n//\nEventEmitter.EventEmitter = EventEmitter;\n\n//\n// Expose the module.\n//\nif ('undefined' !== typeof module) {\n module.exports = EventEmitter;\n}\n","import EventEmitter from './index.js'\n\nexport { EventEmitter }\nexport default EventEmitter\n","import { EventEmitter } from 'eventemitter3';\nimport type BaseWorld from '../world';\nimport type { ComponentDefinitionMap, ComponentMap } from '../component-definition';\n\n// Base system: runs on an optional fixed timestep (deltaBetweenRuns), driven by BaseWorld#update.\nexport default abstract class System<C extends ComponentMap = ComponentMap> extends EventEmitter {\n\tworld: BaseWorld<ComponentDefinitionMap, C>;\n\tname: string;\n\tcurrentDelta: number = 0;\n\tdeltaBetweenRuns: number;\n\tfirstRun: boolean;\n\n\tconstructor(world: BaseWorld<ComponentDefinitionMap, C>, options: SystemConfig = { name: 'System' }) {\n\t\tsuper();\n\n\t\tthis.name = options.name;\n\t\tthis.world = world;\n\n\t\tthis.deltaBetweenRuns = options.deltaBetweenRuns ?? 0;\n\t\tthis.firstRun = options.firstRun !== undefined ? options.firstRun : false;\n\t}\n\n\tinit(): void | Promise<void> {}\n\n\tclear() {\n\t\tthis.currentDelta = 0;\n\t}\n\t// Called once the world's entities all exist: the point a system hands its startup data off (see EntityWorkerSystem).\n\tfinishLoading(): void | Promise<void> {}\n\n\tupdate(elapsedTime: number): boolean {\n\t\tthis.currentDelta += elapsedTime;\n\n\t\tif(this.currentDelta >= this.deltaBetweenRuns || this.firstRun) {\n\t\t\tlet leftOverDelta = 0;\n\t\t\tif(this.deltaBetweenRuns > 0) {\n\t\t\t\t// Carry the remainder so a run that overshoots its timestep doesn't drift the next one later.\n\t\t\t\tleftOverDelta = this.currentDelta % this.deltaBetweenRuns;\n\t\t\t}\n\n\t\t\tthis.run(this.currentDelta - leftOverDelta);\n\t\t\tthis.currentDelta = leftOverDelta;\n\t\t\tthis.firstRun = false;\n\t\t\tthis.onRunFinished();\n\n\t\t\treturn true;\n\t\t} else {\n\t\t\treturn false;\n\t\t}\n\t}\n\tabstract run(elapsedTime: number): void;\n\n\t// Logs and surfaces an error thrown by user code (an update body, preRun, etc.) on the main thread: a\n\t// `system-error` event carrying the system name, so a run keeps going past one failure instead of aborting.\n\tprotected onError(error: Error, context: { entityId?: number, phase?: SystemErrorPhase } = {}) {\n\t\tconst where = context.entityId !== undefined ? ` (entity ${context.entityId})` : '';\n\t\tconsole.error(`Error in system ${this.name}${where}: ${error.message}`, error);\n\t\tconst payload: SystemError = { system: this.name, error, entityId: context.entityId, phase: context.phase };\n\t\tthis.world.emit('system-error', payload);\n\t}\n\n\t// Marks one run as fully applied. Synchronous systems finish inside update(); subclasses whose work is\n\t// deferred (spread across frames, or off-thread) override this and call it at their real completion point.\n\tprotected onRunFinished() {\n\t\tthis.world.notifySystemRunCompleted(this);\n\t}\n\t// True while a run is still in progress between update() calls (a worker round-trip, or an iteration spread\n\t// across frames). Used by the world to keep waiting on a system that is mid-run over memory it may free.\n\tisCurrentlyRunning(): boolean {\n\t\treturn false;\n\t}\n\t// Resolves once any in-flight run has finished, so the world's clear() knows nothing is still reading memory\n\twaitForRunToComplete(): void | Promise<void> {}\n\n\tshouldRun(): boolean {\n\t\treturn true;\n\t}\n\n\tdestroy() {\n\t\tthis.removeAllListeners();\n\t}\n}\n\nexport interface SystemConfig {\n\tname: string\n\tdeltaBetweenRuns?: number\n\tfirstRun?: boolean\n}\n\n// Which part of a run threw, for the `system-error` event.\nexport type SystemErrorPhase = 'preRun' | 'update' | 'entityRemoved' | 'run' | 'died';\nexport interface SystemError {\n\tsystem: string\n\terror: Error\n\tentityId?: number\n\tphase?: SystemErrorPhase\n}\n","import type BaseWorld from '../world';\nimport type { ComponentDefinitionMap, ComponentMap } from '../component-definition';\nimport System, { type SystemConfig } from './system';\n\nexport default abstract class IterableSystem<C extends ComponentMap, T> extends System<C> {\n\tremainingInstancesToRun: Array<T> = [];\n\tremainingInstancesStartTime: number | null = null;\n\titerationsPerCheck: number;\n\tmaxMsPerFrame: number;\n\n\tconstructor(world: BaseWorld<ComponentDefinitionMap, C>, options: IterableSystemConfig) {\n\t\tsuper(world, options);\n\n\t\tthis.iterationsPerCheck = options.iterationsPerCheck ?? 1;\n\t\tthis.maxMsPerFrame = options.maxMsPerFrame ?? 10;\n\t}\n\n\tclear() {\n\t\tsuper.clear();\n\n\t\tthis.remainingInstancesToRun = [];\n\t\tthis.remainingInstancesStartTime = null;\n\t}\n\n\tupdate(elapsedTime: number): boolean {\n\t\tif(this.remainingInstancesToRun.length) {\n\t\t\tthis.runIterables(this.remainingInstancesToRun, this.remainingInstancesStartTime ?? 0);\n\t\t\tthis.currentDelta += elapsedTime;\n\t\t\tif(!this.remainingInstancesToRun.length) {\n\t\t\t\tthis.onRunFinished();\n\t\t\t}\n\n\t\t\treturn true;\n\t\t} else {\n\t\t\treturn super.update(elapsedTime);\n\t\t}\n\t}\n\trun(elapsedTime: number): void {\n\t\tlet iterables = this.getIterables();\n\t\tthis.runIterables(iterables, elapsedTime);\n\t}\n\t// A run that overflowed onto a later frame isn't finished yet; only count it once the queue drains (handled\n\t// by update() when it empties remainingInstancesToRun).\n\tprotected onRunFinished() {\n\t\tif(this.remainingInstancesToRun.length) {\n\t\t\treturn;\n\t\t}\n\n\t\tsuper.onRunFinished();\n\t}\n\tisCurrentlyRunning(): boolean {\n\t\treturn this.remainingInstancesToRun.length > 0;\n\t}\n\n\trunIterables(iterables: Array<T>, elapsedTime: number) {\n\t\tlet started = performance.now();\n\t\ttry {\n\t\t\tthis.beforeRunIterables();\n\t\t} catch(e) {\n\t\t\t// preRun failed: skip the iteration this frame rather than run over half-prepared state.\n\t\t\tthis.onError(e as Error, { phase: 'preRun' });\n\t\t\tthis.remainingInstancesToRun = [];\n\t\t\tthis.remainingInstancesStartTime = null;\n\t\t\treturn;\n\t\t}\n\t\tfor(let i = 0; i < iterables.length; i++) {\n\t\t\ttry {\n\t\t\t\tthis.updateIterable(iterables[i], elapsedTime);\n\t\t\t} catch(e) {\n\t\t\t\t// One iterable failing must not stop the rest of the run.\n\t\t\t\tthis.onError(e as Error, { phase: 'update', entityId: this.getIterableEntityId(iterables[i]) });\n\t\t\t}\n\n\t\t\tif(i % this.iterationsPerCheck === 0) {\n\t\t\t\tlet now = performance.now();\n\t\t\t\tif(now - started >= this.maxMsPerFrame) {\n\t\t\t\t\tthis.remainingInstancesToRun = iterables.slice(i + 1);\n\t\t\t\t\tthis.remainingInstancesStartTime = elapsedTime;\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tthis.remainingInstancesToRun = [];\n\t\tthis.remainingInstancesStartTime = null;\n\t}\n\tbeforeRunIterables() {}\n\t// Best-effort eid for a failed iterable, so `system-error` can name it. Subclasses whose T carries an eid override.\n\tprotected getIterableEntityId(_iterable: T): number | undefined {\n\t\treturn undefined;\n\t}\n\n\tabstract getIterables(): Array<T>;\n\tabstract updateIterable(iterable: T, elapsedTime: number): void;\n}\n\nexport interface IterableSystemConfig extends SystemConfig {\n\titerationsPerCheck?: number\n\tmaxMsPerFrame?: number\n}\n","import type BaseWorld from '../world';\nimport type BaseEntity from '../entity';\nimport type { ComponentDefinitionMap, ComponentMap } from '../component-definition';\nimport IterableSystem, { type IterableSystemConfig } from './iterable-system';\n\n// Iterates the entities owning a given set of components on the main thread; membership tracks world events.\nexport default abstract class EntitySystem<C extends ComponentMap, T extends BaseEntity<C> = BaseEntity<C>> extends IterableSystem<C, T> {\n\tentities: Map<number, T> = new Map();\n\toptions: EntitySystemConfig<C>;\n\n\tconstructor(world: BaseWorld<ComponentDefinitionMap, C>, options: EntitySystemConfig<C> = { name: 'EntitySystem' }) {\n\t\tif(!options.iterationsPerCheck) {\n\t\t\toptions.iterationsPerCheck = 10;\n\t\t}\n\t\tif(!options.maxMsPerFrame) {\n\t\t\toptions.maxMsPerFrame = 4;\n\t\t}\n\n\t\tsuper(world, options);\n\t\tthis.options = options;\n\n\t\tworld.on('entity-added', (entity: BaseEntity<C>) => {\n\t\t\tif(this.checkAddEntity(entity) && this.options.updateEntityOnAdd) {\n\t\t\t\tthis.updateEntity(entity as T, 0);\n\t\t\t}\n\t\t});\n\t\tworld.on('entity-removed', (entity: BaseEntity<C>) => {\n\t\t\tthis.removeEntity(entity);\n\t\t});\n\n\t\tworld.entities.forEach(entity => {\n\t\t\tthis.checkAddEntity(entity);\n\t\t});\n\t}\n\n\tgetIterables(): Array<T> {\n\t\tconst iterables: Array<T> = [];\n\t\tthis.entities.forEach(entity => {\n\t\t\tif(!entity.components.entity.dead) {\n\t\t\t\titerables.push(entity);\n\t\t\t}\n\t\t});\n\n\t\treturn iterables;\n\t}\n\tupdateIterable(entity: T, elapsedTime: number): void {\n\t\t// A multi-frame snapshot can outlive query membership. Revalidate the exact instance before touching it.\n\t\tif(entity.components.entity.dead || this.entities.get(entity.eid) !== entity) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.updateEntity(entity, elapsedTime);\n\t}\n\tfilterEntity(entity: BaseEntity<C>): boolean {\n\t\treturn !entity.components.entity.isStatic;\n\t}\n\tprotected getIterableEntityId(entity: T): number {\n\t\treturn entity.eid;\n\t}\n\tisEntityInSystem(entity: BaseEntity<C>) {\n\t\treturn this.entities.has(entity.eid);\n\t}\n\tabstract updateEntity(entity: T, elapsedTime: number): void;\n\n\tcheckAddEntity(entity: BaseEntity<C>): boolean {\n\t\tif(this.options.components && this.options.components.filter(component => !!entity.components[component]).length !== this.options.components.length) {\n\t\t\treturn false;\n\t\t}\n\n\t\tif(this.filterEntity(entity)) {\n\t\t\tthis.entities.set(entity.eid, entity as T);\n\t\t\treturn true;\n\t\t} else {\n\t\t\treturn false;\n\t\t}\n\t}\n\tremoveEntity(entity: BaseEntity<C>) {\n\t\tthis.entities.delete(entity.eid);\n\t}\n\n\tshouldRun(): boolean {\n\t\t// A continuation must drain even if every live member left since the previous frame.\n\t\treturn this.isCurrentlyRunning() || this.entities.size > 0;\n\t}\n}\n\nexport interface EntitySystemConfig<C extends ComponentMap> extends IterableSystemConfig {\n\tcomponents?: Array<keyof C>\n\tupdateEntityOnAdd?: boolean\n}\n","// Minimal Worker-like base for the main-thread fallback. Loose params: this mirrors the DOM Worker boundary.\nexport default abstract class WebWorker {\n\tabstract postMessage(message: any): void | Promise<void>;\n\tonmessage(message: any, transferrables: Array<any> = []): void {\n\n\t}\n}\n","import WebWorker from './web-worker';\nimport { applyQueryDelta } from './apply-query-delta';\nimport type EntitySystemWorkerMessage from './entity-system-worker-message';\nimport type { EntityEvent, SystemEvents, WorkerRunError } from './entity-system-worker-message';\nimport type BaseWorld from '../../world';\nimport type { ComponentDefinitionMap, ComponentMap, RegisteredComponentRegistry } from '../../component-definition';\nimport type {\n\tEntityWorkerSystemCallbacks, EntityWorkerSystemWorld, EntityQueryComponents, EntityUpdateComponents,\n\tEntityUpdateFunction, QueryDelta, UpdateEntityConfigObject, WorkerAllocator, WorkerComponentChange, WorkerCreatedEntity,\n} from '../entity-worker-system';\nimport { buildWorkerComponent, buildWorkerEntity, type WorkerCreateRegistry } from '../../actions/build-worker-entity';\n\n// Main-thread fallback that runs the update function synchronously, mirroring the real worker's behavior.\nexport default class EntitySystemWebWorker<C extends ComponentMap, T extends EntityUpdateComponents<C>, W extends EntityWorkerSystemWorld = EntityWorkerSystemWorld, D = unknown> extends WebWorker {\n\tprivate updateFunction: EntityUpdateFunction<C, T, W, D>;\n\tprivate entities: Array<UpdateEntityConfigObject<T>> = [];\n\tprivate queryEntities: { [key: string]: Array<UpdateEntityConfigObject<T>> } = {};\n\t// Mirrors createEntitySystemWorker: updateFunction.init's result, merged onto `world` each run.\n\tprivate worldExtension: Partial<W> | undefined;\n\t// Running on the main thread, this shares the world (its string cache, registry pools, eid counter) directly.\n\tprivate world: BaseWorld<ComponentDefinitionMap, C>;\n\tprivate allocator: WorkerAllocator;\n\tprivate createsEntities: boolean;\n\tprivate addsComponents: boolean;\n\n\tconstructor(\n\t\tupdateFunction: EntityUpdateFunction<C, T, W, D>,\n\t\tworld: BaseWorld<ComponentDefinitionMap, C>,\n\t\tcreatesEntities = false,\n\t\taddsComponents = false,\n\t) {\n\t\tsuper();\n\t\tthis.updateFunction = updateFunction;\n\t\tthis.world = world;\n\t\tthis.createsEntities = createsEntities;\n\t\tthis.addsComponents = addsComponents;\n\t\tconst registry = world.registry as RegisteredComponentRegistry<C>;\n\t\tthis.allocator = {\n\t\t\tallocateEid: () => world.allocateEid(),\n\t\t\tallocateComponentBlock: (name, values) => registry[name as keyof C].memoryComponent.create(values),\n\t\t};\n\t}\n\n\tpostMessage(message: EntitySystemWorkerMessage<W, D>): void {\n\t\tif(message.type === 'init') {\n\t\t\tthis.onMessageTyped({\n\t\t\t\ttype: 'init-complete',\n\t\t\t});\n\t\t} else if(message.type === 'load') {\n\t\t\tthis.worldExtension = this.updateFunction.init?.(message.data) ?? undefined;\n\t\t\tthis.onMessageTyped({\n\t\t\t\ttype: 'loaded',\n\t\t\t});\n\t\t} else if(message.type === 'reset') {\n\t\t\t// Drop the persistent lists so a reused world starts empty; worldExtension is refreshed by the next load.\n\t\t\tthis.entities = [];\n\t\t\tthis.queryEntities = {};\n\t\t} else if(message.type === 'run') {\n\t\t\tif(this.worldExtension) {\n\t\t\t\tObject.assign(message.world, this.worldExtension);\n\t\t\t}\n\t\t\tmessage.world.getString = (pointer: number) => this.world.constantStrings.getString(pointer) ?? '';\n\t\t\tmessage.world.heap = this.world.heap;\n\t\t\tmessage.world.allocate = this.allocator;\n\t\t\tif(this.createsEntities) {\n\t\t\t\tconst registry: WorkerCreateRegistry = this.world.registry;\n\t\t\t\tmessage.world.buildEntityDescriptor = config => buildWorkerEntity(\n\t\t\t\t\tconfig,\n\t\t\t\t\tthis.world.factory.configs,\n\t\t\t\t\tregistry,\n\t\t\t\t\tthis.allocator,\n\t\t\t\t\tthis.world.factory.getWorkerClasses(),\n\t\t\t\t);\n\t\t\t}\n\t\t\tif(this.addsComponents) {\n\t\t\t\tconst registry: WorkerCreateRegistry = this.world.registry;\n\t\t\t\tmessage.world.buildComponentDescriptor = (name, config) => buildWorkerComponent(name, config, registry, this.allocator);\n\t\t\t}\n\t\t\t// Timed like the real worker so a forceMainThread system reports a real run cost, not zero.\n\t\t\tconst start = performance.now();\n\t\t\tlet entityEvents: Array<EntityEvent> = [];\n\t\t\tlet systemEvents: SystemEvents = {};\n\t\t\tlet createdEntities: Array<WorkerCreatedEntity> = [];\n\t\t\tlet componentChanges: Array<WorkerComponentChange> = [];\n\t\t\tlet errors: Array<WorkerRunError> = [];\n\n\t\t\tthis.entities = applyQueryDelta(this.entities, message.entities as QueryDelta<T>);\n\n\t\t\tlet queries: EntityQueryComponents<C> = {};\n\t\t\tObject.entries(message.queries).forEach(([queryKey, delta]) => {\n\t\t\t\tconst list = applyQueryDelta(this.queryEntities[queryKey] ?? [], delta as QueryDelta<T>);\n\t\t\t\tthis.queryEntities[queryKey] = list;\n\t\t\t\tqueries[queryKey] = list;\n\t\t\t});\n\n\t\t\tlet callbacks: EntityWorkerSystemCallbacks<C> = {\n\t\t\t\tentityComponentChanged<K extends keyof C, P extends keyof C[K]>(entityId: number, componentName: K, prop: P, value: C[K][P]) {\n\t\t\t\t\tentityEvents.push({\n\t\t\t\t\t\tentityId,\n\t\t\t\t\t\tevent: 'component-property-updated',\n\t\t\t\t\t\targs: [componentName, prop, value],\n\t\t\t\t\t});\n\t\t\t\t},\n\t\t\t\temitEntityEvent(entityId: number, event: string, ...args: Array<unknown>) {\n\t\t\t\t\tentityEvents.push({\n\t\t\t\t\t\tentityId,\n\t\t\t\t\t\tevent,\n\t\t\t\t\t\targs,\n\t\t\t\t\t});\n\t\t\t\t},\n\t\t\t\temitSystemEvent(event: string, entityId: number) {\n\t\t\t\t\t(systemEvents[event] ?? (systemEvents[event] = [])).push(entityId);\n\t\t\t\t},\n\t\t\t\tentityDied(entityId: number) {\n\t\t\t\t\tentityEvents.push({\n\t\t\t\t\t\tentityId,\n\t\t\t\t\t\tevent: 'death',\n\t\t\t\t\t\targs: [],\n\t\t\t\t\t});\n\t\t\t\t},\n\t\t\t\tcreateEntity(entity: WorkerCreatedEntity) {\n\t\t\t\t\tcreatedEntities.push(entity);\n\t\t\t\t},\n\t\t\t\taddComponent(entityId, component) {\n\t\t\t\t\tcomponentChanges.push({ type: 'add', entityId, component });\n\t\t\t\t},\n\t\t\t\tremoveComponent(entityId, componentName) {\n\t\t\t\t\tcomponentChanges.push({ type: 'remove', entityId, componentName: String(componentName) });\n\t\t\t\t},\n\t\t\t};\n\t\t\tlet preRunFailed = false;\n\t\t\tif(this.updateFunction.preRun) {\n\t\t\t\ttry {\n\t\t\t\t\tthis.updateFunction.preRun(message.world, this.entities, queries, callbacks);\n\t\t\t\t} catch(e) {\n\t\t\t\t\tpreRunFailed = true;\n\t\t\t\t\terrors.push({ error: e as Error, phase: 'preRun' });\n\t\t\t\t}\n\t\t\t}\n\t\t\t// preRun sets up the run's state; if it threw, skip the entity loop rather than run over half-prepared data.\n\t\t\tif(!preRunFailed) {\n\t\t\t\tthis.entities.forEach(entity => {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tthis.updateFunction(message.world, entity.entityId, entity.components, queries, callbacks);\n\t\t\t\t\t} catch(e) {\n\t\t\t\t\t\t// One entity failing must not stop the rest of the run.\n\t\t\t\t\t\terrors.push({ error: e as Error, phase: 'update', entityId: entity.entityId });\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tif(this.updateFunction.entityRemoved) {\n\t\t\t\tfor(let entityId of message.entities.removed) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tthis.updateFunction.entityRemoved(message.world, entityId, callbacks);\n\t\t\t\t\t} catch(e) {\n\t\t\t\t\t\terrors.push({ error: e as Error, phase: 'entityRemoved', entityId });\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst runTime = performance.now() - start;\n\n\t\t\tthis.onMessageTyped({\n\t\t\t\ttype: 'run-complete',\n\t\t\t\tgeneration: message.generation,\n\t\t\t\trunTime,\n\t\t\t\tevents: entityEvents,\n\t\t\t\tsystemEvents,\n\t\t\t\tcreated: createdEntities,\n\t\t\t\tcomponentChanges,\n\t\t\t\terrors,\n\t\t\t});\n\t\t}\n\t}\n\n\tonMessageTyped(message: EntitySystemWorkerMessage<W, D>) {\n\t\tthis.onmessage({\n\t\t\tdata: message,\n\t\t});\n\t}\n}\n","import type MemoryHeap from '@daneren2005/shared-memory-objects/memory-heap';\nimport type { GrowBufferData } from '@daneren2005/shared-memory-objects/memory-heap';\nimport type BaseWorld from '../world';\nimport type BaseEntity from '../entity';\nimport type { BaseComponent, ComponentDefinitionMap, ComponentMap } from '../component-definition';\nimport type { ComponentTypedArray } from '../memory-component';\nimport System, { type SystemConfig } from './system';\nimport type EntitySystemWorkerMessage from './workers/entity-system-worker-message';\nimport EntitySystemWebWorker from './workers/entity-system-web-worker';\n\nconst MAIN_QUERY_NAME = '___main';\n\n// Runs an update function over the raw shared-memory blocks of its matched entities. Uses getWorker() when\n// Web Workers + SharedArrayBuffer exist, else falls back to EntitySystemWebWorker on the main thread. No game\n// concepts; games inject per-run data via addDataToWorld.\nexport default abstract class EntityWorkerSystem<\n\tC extends ComponentMap,\n\tT extends EntityUpdateComponents<C>,\n\tW extends EntityWorkerSystemWorld = EntityWorkerSystemWorld,\n\tD = unknown,\n> extends System<C> {\n\tentities: Map<number, BaseEntity<C>> = new Map();\n\toptions: EntityWorkerSystemConfig<C, T, W, D>;\n\n\tworker: Worker | EntitySystemWebWorker<C, T, W, D>;\n\tisWorkerThread: boolean;\n\n\tprivate initialized = false;\n\tprivate initPromise: Resolvable | null = null;\n\tprivate loadingPromise: Resolvable | null = null;\n\tprivate runCompletePromise: Resolvable | null = null;\n\tprivate isRunning = false;\n\t// Bumped by clear(); checked on each event to make certain we are dealing with the correct world\n\tprivate generation = 0;\n\tprotected queryEntities: { [key: string]: Map<number, BaseEntity<C>> } = {};\n\t// Membership changes since the last run(), flushed each run as a delta so a steady-state run sends empty\n\t// arrays rather than re-transmitting every eid. The worker applies these to its own list (see applyQueryDelta).\n\tprivate queryDeltas: { [key: string]: MembershipDelta<C> } = {};\n\n\taddDataToWorld?(world: W): void;\n\n\tconstructor(world: BaseWorld<ComponentDefinitionMap, C>, options: EntityWorkerSystemConfig<C, T, W, D>) {\n\t\tsuper(world, options);\n\t\tthis.options = options;\n\t\tObject.keys(this.options.queries ?? {}).forEach(queryName => {\n\t\t\tthis.queryEntities[queryName] = new Map();\n\t\t});\n\n\t\tworld.on('entity-added', (entity: BaseEntity<C>) => {\n\t\t\tthis.checkAddEntity(entity);\n\t\t});\n\t\tworld.on('entity-removed', (entity: BaseEntity<C>) => {\n\t\t\tthis.removeEntity(entity);\n\t\t});\n\n\t\tworld.entities.forEach(entity => {\n\t\t\tthis.checkAddEntity(entity);\n\t\t});\n\n\t\tif(!options.forceMainThread && typeof globalThis.Worker !== 'undefined' && typeof globalThis.SharedArrayBuffer !== 'undefined') {\n\t\t\tthis.worker = options.getWorker();\n\t\t\tthis.isWorkerThread = true;\n\t\t\t// Forward heap growth so the worker's reconstructed heap can resolve pointers into new buffers.\n\t\t\tworld.on('grow-buffer', (buffer: GrowBufferData) => {\n\t\t\t\tthis.worker.postMessage({ type: 'grow-buffer', buffer });\n\t\t\t});\n\t\t} else {\n\t\t\tthis.worker = new EntitySystemWebWorker(options.updateFunction, world, !!options.createsEntities, !!options.addsComponents);\n\t\t\tthis.isWorkerThread = false;\n\t\t}\n\n\t\tthis.initWorker();\n\t}\n\n\tprivate initWorker() {\n\t\tthis.worker.onmessage = (e: MessageEvent) => {\n\t\t\tlet message = e.data as EntitySystemWorkerMessage;\n\t\t\tif(message.type === 'init-complete') {\n\t\t\t\tthis.initialized = true;\n\t\t\t\tif(this.initPromise) {\n\t\t\t\t\tthis.initPromise.resolve();\n\t\t\t\t\tthis.initPromise = null;\n\t\t\t\t}\n\t\t\t} else if(message.type === 'loaded') {\n\t\t\t\tif(this.loadingPromise) {\n\t\t\t\t\tthis.loadingPromise.resolve();\n\t\t\t\t\tthis.loadingPromise = null;\n\t\t\t\t}\n\t\t\t} else if(message.type === 'grow-buffer-from-worker') {\n\t\t\t\t// A buffer this worker grew while allocating: adopt into the main heap and fan out to sibling workers.\n\t\t\t\tthis.world.addGrownBuffer(message.buffer);\n\t\t\t} else if(message.type === 'run-complete') {\n\t\t\t\t// A reply from a run that started before a clear(): the world it ran over is gone, so drop it whole.\n\t\t\t\tif(message.generation !== this.generation) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tthis.isRunning = false;\n\t\t\t\tthis.world.emit(`system-${this.name}-worker-finished`, message.runTime);\n\n\t\t\t\t// User-code errors caught inside the run: log + emit on the main thread, one per failure.\n\t\t\t\tmessage.errors.forEach(({ error, entityId, phase }) => {\n\t\t\t\t\tthis.onError(error, { entityId, phase });\n\t\t\t\t});\n\n\t\t\t\t// Structural changes are applied only after the worker has finished iterating its snapshot. Attaching emits\n\t\t\t\t// the same entity events as a main-thread mutation, which rechecks every affected system/query and queues\n\t\t\t\t// refreshed component bundles for their next run.\n\t\t\t\t(message.componentChanges ?? []).forEach(change => {\n\t\t\t\t\tconst entity = this.world.getEntityByEid(change.entityId);\n\t\t\t\t\tif(change.type === 'add') {\n\t\t\t\t\t\tconst definition = this.world.registry[change.component.name as keyof C];\n\t\t\t\t\t\tif(!entity || !definition || change.component.name === 'entity') {\n\t\t\t\t\t\t\tdefinition?.memoryComponent.delete(change.component.index);\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tconst componentName = change.component.name as keyof C;\n\t\t\t\t\t\tentity.removeComponent(componentName);\n\t\t\t\t\t\tentity.attachComponent(componentName, change.component.index, true);\n\t\t\t\t\t} else if(entity && change.componentName !== 'entity') {\n\t\t\t\t\t\tentity.removeComponent(change.componentName);\n\t\t\t\t\t}\n\t\t\t\t});\n\n\t\t\t\t// Before the per-entity events: an entity killed this run is still in the world here, since `death`\n\t\t\t\t// is dispatched below and removes it.\n\t\t\t\tfor(const event of Object.keys(message.systemEvents)) {\n\t\t\t\t\tthis.emit(event, message.systemEvents[event]);\n\t\t\t\t}\n\n\t\t\t\tmessage.events.forEach(event => {\n\t\t\t\t\t// Look up on the world, not the query cache, so events for sub-query-only entities still route.\n\t\t\t\t\tconst entity = this.world.getEntityByEid(event.entityId);\n\t\t\t\t\tif(!entity) {\n\t\t\t\t\t\tconsole.warn(`${this.name}-event ${event.event}: Could not find entity with id ${event.entityId}`);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tentity.emit(event.event, ...event.args);\n\t\t\t\t});\n\n\t\t\t\t// After deaths, so an entity created this run isn't immediately removed. Adopts the blocks the worker\n\t\t\t\t// already allocated + wrote, rather than re-creating them.\n\t\t\t\tmessage.created.forEach(descriptor => {\n\t\t\t\t\tthis.world.adoptEntity(descriptor);\n\t\t\t\t});\n\n\t\t\t\tthis.world.emit(`system-${this.name}-worker-events-finished`, message.runTime);\n\t\t\t\tthis.world.notifySystemRunCompleted(this);\n\n\t\t\t\tif(this.runCompletePromise) {\n\t\t\t\t\tthis.runCompletePromise.resolve();\n\t\t\t\t\tthis.runCompletePromise = null;\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\n\t\tconst message: EntitySystemWorkerMessage<W, D> = {\n\t\t\ttype: 'init',\n\t\t};\n\n\t\tthis.worker.postMessage(message);\n\t}\n\n\tinit(): Promise<void> | void {\n\t\tif(this.initialized) {\n\t\t\treturn;\n\t\t} else if(this.initPromise) {\n\t\t\treturn this.initPromise.promise;\n\t\t}\n\n\t\tlet { promise, resolve } = Promise.withResolvers<void>();\n\t\tthis.initPromise = {\n\t\t\tpromise,\n\t\t\tresolve,\n\t\t};\n\t\treturn promise;\n\t}\n\n\t// Sends the init data over and runs the update function's own init in the worker\n\tfinishLoading(): Promise<void> {\n\t\tlet { promise, resolve } = Promise.withResolvers<void>();\n\t\t// Assigned before posting: the main-thread fallback replies synchronously from inside postMessage.\n\t\tthis.loadingPromise = {\n\t\t\tpromise,\n\t\t\tresolve,\n\t\t};\n\n\t\tconst message: EntitySystemWorkerMessage<W, D> = {\n\t\t\ttype: 'load',\n\t\t\tdata: this.options.getInitData?.(),\n\t\t\t// Only a real worker needs the buffers to rebuild a heap, plus the pools + eid counter to allocate off-thread.\n\t\t\theap: this.isWorkerThread ? this.world.heap.getSharedMemory() : undefined,\n\t\t\tsharedMemory: this.isWorkerThread ? this.world.getSharedComponentMemory() : undefined,\n\t\t\t// Factory templates only go to workers that create entities.\n\t\t\tfactoryConfigs: this.isWorkerThread && this.options.createsEntities ? this.world.factory.configs : undefined,\n\t\t\tfactoryClasses: this.isWorkerThread && this.options.createsEntities ? this.world.factory.getWorkerClasses() : undefined,\n\t\t\taddsComponents: !!this.options.addsComponents,\n\t\t};\n\t\tthis.worker.postMessage(message);\n\n\t\treturn promise;\n\t}\n\n\t// Un-initializes the system so its world can be reused\n\tclear() {\n\t\tsuper.clear();\n\n\t\tif(this.isRunning) {\n\t\t\tif(!this.runCompletePromise) {\n\t\t\t\tconst { promise, resolve } = Promise.withResolvers<void>();\n\t\t\t\tthis.runCompletePromise = { promise, resolve };\n\t\t\t}\n\t\t}\n\t\tthis.isRunning = false;\n\t\tthis.generation++;\n\n\t\tthis.entities.clear();\n\t\tObject.values(this.queryEntities).forEach(list => list.clear());\n\t\tthis.queryDeltas = {};\n\n\t\tconst message: EntitySystemWorkerMessage = { type: 'reset' };\n\t\tthis.worker.postMessage(message);\n\t}\n\n\tupdate(elapsedTime: number): boolean {\n\t\tif(this.isRunning) {\n\t\t\tthis.currentDelta += elapsedTime;\n\n\t\t\treturn false;\n\t\t} else {\n\t\t\treturn super.update(elapsedTime);\n\t\t}\n\t}\n\t// A run finishes off-thread, not when update() returns; completedRuns is bumped on the worker's run-complete.\n\tprotected onRunFinished() {}\n\tisCurrentlyRunning(): boolean {\n\t\treturn this.isRunning;\n\t}\n\twaitForRunToComplete(): void | Promise<void> {\n\t\tif(!this.isRunning) {\n\t\t\treturn;\n\t\t}\n\t\tif(!this.runCompletePromise) {\n\t\t\tconst { promise, resolve } = Promise.withResolvers<void>();\n\t\t\tthis.runCompletePromise = { promise, resolve };\n\t\t}\n\t\treturn this.runCompletePromise.promise;\n\t}\n\trun(elapsedTime: number): void {\n\t\tconst world = {\n\t\t\tgameTime: this.world.gameTime,\n\t\t\telapsedTime,\n\t\t} as W;\n\t\tthis.addDataToWorld?.(world);\n\n\t\tthis.isRunning = true;\n\t\tlet entities = this.buildQueryDelta(MAIN_QUERY_NAME, this.options);\n\t\tlet queries: { [key: string]: QueryDelta<T> } = {};\n\t\tObject.entries(this.options.queries ?? {}).forEach(([queryKey, query]) => {\n\t\t\tqueries[queryKey] = this.buildQueryDelta(queryKey, query);\n\t\t});\n\t\tlet message: EntitySystemWorkerMessage<W> = {\n\t\t\ttype: 'run',\n\t\t\tgeneration: this.generation,\n\t\t\tworld,\n\t\t\tentities,\n\t\t\tqueries,\n\t\t};\n\t\tthis.worker.postMessage(message);\n\t}\n\n\tprivate buildQueryDelta(queryName: string, query: EntityWorkerSystemQuery<C>): QueryDelta<T> {\n\t\tconst delta = this.getQueryDelta(queryName);\n\t\tconst added: Array<UpdateEntityConfigObject<T>> = [];\n\t\tdelta.added.forEach(entity => {\n\t\t\tadded.push({\n\t\t\t\tentityId: entity.eid,\n\t\t\t\tcomponents: this.buildComponents(entity, query),\n\t\t\t});\n\t\t});\n\t\tconst removed = Array.from(delta.removed);\n\t\tthis.queryDeltas[queryName] = { added: new Set(), removed: new Set() };\n\n\t\treturn { added, removed };\n\t}\n\tprivate buildComponents(entity: BaseEntity<C>, query: EntityWorkerSystemQuery<C>): T {\n\t\tconst components = {} as T;\n\t\t[\n\t\t\t...query.required,\n\t\t\t...query.optional ?? [],\n\t\t].forEach(componentName => {\n\t\t\t// Reuse the view cached on the accessor at attach: getBlock allocates a fresh subarray every call and an\n\t\t\t// entity joins many systems, so re-looking it up here per system was a measurable spawn-time cost.\n\t\t\tconst block = entity.components[componentName]?.block;\n\t\t\tif(block) {\n\t\t\t\tcomponents[componentName] = block as T[typeof componentName];\n\t\t\t}\n\t\t});\n\n\t\treturn components;\n\t}\n\n\tisEntityInSystem(entity: BaseEntity<C>) {\n\t\treturn this.entities.has(entity.eid);\n\t}\n\tprotected matchesQuery(entity: BaseEntity<C>, query: EntityWorkerSystemQuery<C>): boolean {\n\t\tif(entity.components.entity.dead) {\n\t\t\treturn false;\n\t\t}\n\n\t\tif(query.required.find(component => !entity.components[component])) {\n\t\t\treturn false;\n\t\t}\n\t\tif(query.not?.find(component => !!entity.components[component])) {\n\t\t\treturn false;\n\t\t}\n\t\tif(query.filter && !query.filter(entity)) {\n\t\t\treturn false;\n\t\t}\n\n\t\treturn true;\n\t}\n\tprivate getQueryDelta(queryName: string): MembershipDelta<C> {\n\t\tlet delta = this.queryDeltas[queryName];\n\t\tif(!delta) {\n\t\t\tdelta = this.queryDeltas[queryName] = { added: new Set(), removed: new Set() };\n\t\t}\n\n\t\treturn delta;\n\t}\n\t// A pending removal this same frame is cancelled, so the net effect is a re-send rather than remove+add churn.\n\tprivate markAdded(delta: MembershipDelta<C>, entity: BaseEntity<C>) {\n\t\tdelta.removed.delete(entity.eid);\n\t\tdelta.added.add(entity);\n\t}\n\tprivate markRemoved(delta: MembershipDelta<C>, entity: BaseEntity<C>) {\n\t\tif(delta.added.delete(entity)) {\n\t\t\treturn;\n\t\t}\n\n\t\tdelta.removed.add(entity.eid);\n\t}\n\tprotected updateEntityList(queryName: string, list: Map<number, BaseEntity<C>>, entity: BaseEntity<C>, shouldInclude: boolean) {\n\t\tconst delta = this.getQueryDelta(queryName);\n\t\tif(shouldInclude) {\n\t\t\tlist.set(entity.eid, entity);\n\t\t\tthis.markAdded(delta, entity);\n\t\t} else if(list.delete(entity.eid)) {\n\t\t\tthis.markRemoved(delta, entity);\n\t\t}\n\t}\n\n\tcheckAddEntity(entity: BaseEntity<C>): boolean {\n\t\tconst shouldAddToMain = this.matchesQuery(entity, this.options);\n\t\tthis.updateEntityList(MAIN_QUERY_NAME, this.entities, entity, shouldAddToMain);\n\n\t\tObject.entries(this.options.queries ?? {}).forEach(([queryName, query]) => {\n\t\t\tconst queryList = this.queryEntities[queryName] ?? (this.queryEntities[queryName] = new Map());\n\t\t\tthis.updateEntityList(queryName, queryList, entity, this.matchesQuery(entity, query));\n\t\t});\n\n\t\treturn shouldAddToMain;\n\t}\n\tremoveEntity(entity: BaseEntity<C>) {\n\t\tthis.updateEntityList(MAIN_QUERY_NAME, this.entities, entity, false);\n\t\tObject.entries(this.queryEntities).forEach(([queryName, list]) => {\n\t\t\tthis.updateEntityList(queryName, list, entity, false);\n\t\t});\n\t}\n\n\t// Re-evaluates every entity's membership against the current queries. Needed when a `filter` closes over mutable\n\t// state (e.g. a scope keyed on which group is active) and that state changes with no entity event to react to\n\trecheckMembership() {\n\t\tthis.world.entities.forEach(entity => {\n\t\t\tthis.checkAddEntity(entity);\n\t\t});\n\t}\n\n\tshouldRun(): boolean {\n\t\treturn this.entities.size > 0;\n\t}\n\n\tdestroy() {\n\t\tsuper.destroy();\n\n\t\tif('terminate' in this.worker) {\n\t\t\tthis.worker.terminate();\n\t\t}\n\t}\n}\n\ninterface Resolvable {\n\tpromise: Promise<void>\n\tresolve: (value: void | PromiseLike<void>) => void\n}\n\nexport type EntityUpdateComponents<C extends ComponentMap = ComponentMap> = { [K in keyof C]?: ComponentTypedArray };\nexport type EntityQueryComponents<C extends ComponentMap = ComponentMap> = { [key: string]: Array<{ entityId: number, components: EntityUpdateComponents<C> }> };\ntype EntityUpdateFunctionImpl<C extends ComponentMap, T extends EntityUpdateComponents<C>, W extends EntityWorkerSystemWorld = EntityWorkerSystemWorld> = (\n\tworld: W,\n\tentityId: number,\n\tcomponents: T,\n\tqueries: EntityQueryComponents<C>,\n\tcallbacks: EntityWorkerSystemCallbacks<C>,\n) => void;\nexport type EntityUpdateFunction<\n\tC extends ComponentMap,\n\tT extends EntityUpdateComponents<C>,\n\tW extends EntityWorkerSystemWorld = EntityWorkerSystemWorld,\n\tD = unknown,\n> = EntityUpdateFunctionImpl<C, T, W> & {\n\tpreRun?: EntityUpdatePreRunFunction<C, T, W>\n\tentityRemoved?: EntityRemovedFunction<C, W>\n\tinit?: EntityUpdateInitFunction<W, D>\n};\nexport type EntityUpdateInitFunction<W extends EntityWorkerSystemWorld = EntityWorkerSystemWorld, D = unknown> = (data: D | undefined) => Partial<W> | void;\nexport type EntityUpdatePreRunFunction<C extends ComponentMap, T extends EntityUpdateComponents<C>, W extends EntityWorkerSystemWorld = EntityWorkerSystemWorld> = (\n\tworld: W,\n\tentities: Array<UpdateEntityConfigObject<T>>,\n\tqueries: EntityQueryComponents<C>,\n\tcallbacks: EntityWorkerSystemCallbacks<C>,\n) => void;\nexport type EntityRemovedFunction<C extends ComponentMap = ComponentMap, W extends EntityWorkerSystemWorld = EntityWorkerSystemWorld> = (\n\tworld: W,\n\tentityId: number,\n\tcallbacks: EntityWorkerSystemCallbacks<C>,\n) => void;\nexport type UpdateEntityConfig<T extends EntityUpdateComponents = EntityUpdateComponents> = number | UpdateEntityConfigObject<T>;\nexport type UpdateEntityConfigObject<T extends EntityUpdateComponents> = {\n\tentityId: number\n\tcomponents: T\n};\n\nexport interface QueryDelta<T extends EntityUpdateComponents = EntityUpdateComponents> {\n\tadded: Array<UpdateEntityConfigObject<T>>\n\tremoved: Array<number>\n}\n// Sets so queuing can check for an already-queued or opposite change without scanning a growing array.\ninterface MembershipDelta<C extends ComponentMap> {\n\tadded: Set<BaseEntity<C>>\n\tremoved: Set<number>\n}\n\n// Low-level off-thread allocation primitives, injected onto the worker `world` each run. `allocateEid` mints a\n// heap-unique id; `allocateComponentBlock` pushes a block into a component's shared pool and returns its index.\n// These are the foundation a future worker-side createEntity builds on (allocate + write blocks, then report the\n// eid/indexes back for the main thread to adopt).\nexport interface WorkerAllocator {\n\tallocateEid(): number\n\tallocateComponentBlock(name: string, values: Array<number>): number\n}\n\nexport interface EntityWorkerSystemWorld {\n\tgameTime: number\n\telapsedTime: number\n\tgetString(pointer: number): string\n\t// The reconstructed heap (real worker) or the shared main-thread heap (fallback), injected each run so an\n\t// update function can rebuild heap-backed structures (a SharedMap/SharedList) from a pointer in a component\n\t// block. Undefined only before the first run.\n\theap?: MemoryHeap\n\tallocate?: WorkerAllocator\n\t// Injected each run on a system registered with createsEntities: builds a WorkerCreatedEntity descriptor from a\n\t// factory config (merges the type's template, allocates + writes each component's block). Drives createEntityWorker.\n\tbuildEntityDescriptor?(config: WorkerCreateEntityConfig): WorkerCreatedEntity\n\t// Injected for systems with addsComponents. Allocates/writes a block off-thread; the main thread attaches it\n\t// after run completion so no running update observes a changing component set.\n\tbuildComponentDescriptor?(name: string, config: Record<string, unknown>): WorkerCreatedComponent\n}\n// What a game passes to createEntityWorker: a factory-style config - the entity `type` plus any overrides layered\n// over that type's factory template. The worker merges template + overrides, then allocates + writes each triggered\n// component's block off-thread via the component's toBlock(config). The \"entity\" component is built on the main\n// thread when the descriptor is adopted, since interning the type is main-thread-only.\nexport type WorkerCreateEntityConfig = { type: string, class?: never } & { [key: string]: unknown };\n// The result reported back on run-complete: the minted id plus, per game component, the pool index the worker\n// allocated. world.adoptEntity turns this into a real BaseEntity.\nexport interface WorkerCreatedEntity {\n\teid: number\n\ttype: string\n\tclass?: string\n\tisStatic?: boolean\n\tcomponents: { [name: string]: number }\n}\n\nexport interface WorkerCreatedComponent {\n\tname: string\n\tindex: number\n}\n\nexport type WorkerComponentChange =\n\t| { type: 'add', entityId: number, component: WorkerCreatedComponent }\n\t| { type: 'remove', entityId: number, componentName: string };\n\nexport interface EntityWorkerSystemCallbacks<C extends ComponentMap = ComponentMap> {\n\tentityComponentChanged<K extends keyof C, P extends keyof C[K]>(entityId: number, componentName: K, prop: P, value: C[K][P]): void\n\t// Args are structured-cloned, so plain values only.\n\temitEntityEvent(entityId: number, event: string, ...args: Array<unknown>): void\n\t// Emitted **on the system** with all its ids in one array. The allocation-free path for something that\n\t// happens to most entities every run; carries no args (values are already in shared memory).\n\temitSystemEvent(event: string, entityId: number): void\n\tentityDied(entityId: number): void\n\tcreateEntity(entity: WorkerCreatedEntity): void\n\taddComponent(entityId: number, component: WorkerCreatedComponent): void\n\tremoveComponent<K extends keyof C>(entityId: number, componentName: K): void\n}\n\nexport interface EntityWorkerSystemQuery<C extends ComponentMap = ComponentMap> {\n\trequired: Array<keyof C>\n\toptional?: Array<keyof C>\n\tnot?: Array<keyof C>\n\tfilter?: (entity: BaseEntity<C>) => boolean\n}\n\nexport interface EntityWorkerSystemConfig<\n\tC extends ComponentMap,\n\tT extends EntityUpdateComponents<C>,\n\tW extends EntityWorkerSystemWorld = EntityWorkerSystemWorld,\n\tD = unknown,\n> extends SystemConfig, EntityWorkerSystemQuery<C> {\n\tupdateFunction: EntityUpdateFunction<C, T, W, D>\n\tgetWorker: () => Worker\n\tforceMainThread?: boolean\n\tgetInitData?: () => D\n\t// Opt in to worker-side entity creation (createEntityWorker). When set, factory templates and serializable class\n\t// allowlists are shipped to this system's worker; the worker entry must also pass the component registry to\n\t// createEntitySystemWorker so it has each component's toBlock(). Only systems that create entities need either.\n\tcreatesEntities?: boolean\n\t// Opt in to worker-side component allocation through addComponentWorker. The worker entry must also pass the\n\t// component registry to createEntitySystemWorker so the worker has each component's toBlock().\n\taddsComponents?: boolean\n\n\tqueries?: { [key: string]: EntityWorkerSystemQuery<C> }\n}\n\nexport type { BaseComponent };\n","import { EventEmitter } from 'eventemitter3';\nimport type BaseWorld from './world';\nimport type { BaseComponent, ComponentDefinitionMap, ComponentMap, RegisteredComponentRegistry } from './component-definition';\nimport type { EntityComponent } from './entity-component';\n\nexport default class BaseEntity<C extends ComponentMap = ComponentMap, Cfg = any> extends EventEmitter {\n\treadonly eid: number;\n\tconfig?: Cfg;\n\n\tworld: BaseWorld<ComponentDefinitionMap, C, Cfg>;\n\tprivate componentMemoryDeletionScheduled = false;\n\tprivate allowedComponents?: ReadonlySet<string>;\n\t// entity is always present; game components are partial.\n\tcomponents: Partial<C> & { entity: EntityComponent } = {} as Partial<C> & { entity: EntityComponent };\n\n\t// `adoptEid`: build an empty shell around a pre-minted id (an entity a worker created off-thread), skipping the\n\t// automatic entity-component load - the caller (world.adoptEntity) loads the entity component and attaches the\n\t// worker-allocated blocks itself.\n\tconstructor(\n\t\tworld: BaseWorld<ComponentDefinitionMap, C, Cfg>,\n\t\tconfig?: Cfg,\n\t\tadoptEid?: number,\n\t\tallowedComponents?: ReadonlySet<string>,\n\t) {\n\t\tsuper();\n\n\t\tthis.world = world;\n\t\tthis.eid = adoptEid ?? world.allocateEid();\n\t\tthis.allowedComponents = allowedComponents ?? world.factory.getAllowedComponentsForConfig(config);\n\t\tif(adoptEid !== undefined) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.loadComponent('entity', config ?? {}, false);\n\t\tif(config) {\n\t\t\tthis.load(config);\n\t\t}\n\t}\n\tget id(): number {\n\t\treturn this.eid;\n\t}\n\tget dead(): boolean {\n\t\treturn this.components.entity.dead;\n\t}\n\tget type(): string {\n\t\treturn this.components.entity.type;\n\t}\n\n\tloadComponent<K extends keyof C>(name: K, config: any, emitAdded = true): C[K] {\n\t\tthis.assertComponentAllowed(name);\n\t\tconst definition = (this.world.registry as RegisteredComponentRegistry<C>)[name];\n\t\tconst memoryComponent = definition.memoryComponent;\n\t\tconst index = memoryComponent.create(definition.toBlock(config, this));\n\t\tconst component = definition.attach(this, memoryComponent, index);\n\t\t// A Component subclass already holds its block; only fetch one for a plain-object accessor that didn't.\n\t\t(component as BaseComponent).block ??= memoryComponent.getBlock(index);\n\t\t(this.components as Partial<C>)[name] = component;\n\t\tif(emitAdded) {\n\t\t\tthis.emit('component-added', name, component);\n\t\t}\n\n\t\treturn component;\n\t}\n\t// Builds an accessor over an existing block (allocated + written by a worker) instead of creating a new one - the\n\t// adopt half of loadComponent, without the create.\n\tattachComponent<K extends keyof C>(name: K, index: number, emitAdded = false): C[K] {\n\t\tthis.assertComponentAllowed(name);\n\t\tconst definition = (this.world.registry as RegisteredComponentRegistry<C>)[name];\n\t\tconst component = definition.attach(this, definition.memoryComponent, index);\n\t\t(component as BaseComponent).block ??= definition.memoryComponent.getBlock(index);\n\t\t(this.components as Partial<C>)[name] = component;\n\t\tif(emitAdded) {\n\t\t\tthis.emit('component-added', name, component);\n\t\t}\n\t\treturn component;\n\t}\n\tremoveComponent<K extends keyof C>(name: K) {\n\t\tif(this.componentMemoryDeletionScheduled) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst component = (this.components as Partial<C>)[name];\n\t\tif(component) {\n\t\t\tconst definition = (this.world.registry as RegisteredComponentRegistry<C>)[name];\n\t\t\tthis.world.deferComponentMemoryFree(definition.memoryComponent, component.index, definition.free ? () => definition.free!(component) : undefined);\n\t\t\tdelete this.components[name];\n\t\t\tthis.emit('component-removed', name);\n\t\t}\n\t}\n\tsetComponent<K extends keyof C, P extends keyof C[K]>(componentName: K, prop: P, value: C[K][P]) {\n\t\tthis.assertComponentPropertyMutable(componentName, prop);\n\t\tconst component = this.components[componentName];\n\t\tif(!component) {\n\t\t\treturn;\n\t\t}\n\n\t\t(component as unknown as Record<P, C[K][P]>)[prop] = value;\n\t\tthis.emit('component-property-updated', componentName, prop, value);\n\t}\n\t/**\n\t * NOTE: Does not emit component-property-updated!\n\t */\n\tsetComponentBulk<K extends keyof C>(componentName: K, values: Partial<C[K]>) {\n\t\tfor(const prop of Object.keys(values)) {\n\t\t\tthis.assertComponentPropertyMutable(componentName, prop);\n\t\t}\n\t\tconst component = this.components[componentName];\n\t\tif(!component) {\n\t\t\treturn;\n\t\t}\n\n\t\tObject.assign(component, values);\n\t}\n\tdeleteComponent<K extends keyof C>(componentName: K, prop: keyof C[K]) {\n\t\tthis.assertComponentPropertyMutable(componentName, prop);\n\t\tconst component = this.components[componentName];\n\t\tif(!component) {\n\t\t\treturn;\n\t\t}\n\n\t\tdelete (component as Partial<C[K]>)[prop];\n\t\tthis.emit('component-property-deleted', componentName, prop);\n\t}\n\n\tdeleteAllComponentMemory() {\n\t\tif(this.componentMemoryDeletionScheduled) {\n\t\t\treturn;\n\t\t}\n\t\tthis.componentMemoryDeletionScheduled = true;\n\n\t\tconst registry = this.world.registry as RegisteredComponentRegistry<C>;\n\t\tconst components = this.components as Partial<C>;\n\t\tfor(let name of Object.keys(components) as Array<keyof C>) {\n\t\t\tconst definition = registry[name];\n\t\t\tconst component = components[name];\n\t\t\tif(component) {\n\t\t\t\tthis.world.deferComponentMemoryFree(definition.memoryComponent, component.index, definition.free ? () => definition.free!(component) : undefined);\n\t\t\t}\n\t\t}\n\t}\n\n\tload(config: Cfg) {\n\t\tconst props = config as Record<string, unknown>;\n\t\tconst registry = this.world.registry as RegisteredComponentRegistry<C>;\n\t\tfor(let name of Object.keys(registry) as Array<keyof C>) {\n\t\t\tif(name === 'entity') {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif(!this.isComponentAllowed(name)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst definition = registry[name];\n\t\t\tif(definition.loadInFinishLoading) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif(definition.loadProperties.some(prop => prop in props)) {\n\t\t\t\tthis.loadComponent(name, config, false);\n\t\t\t}\n\t\t}\n\n\t\tthis.config = config;\n\t}\n\tsave(): Cfg {\n\t\tconst config: { [key: string]: any } = {};\n\n\t\tconst registry = this.world.registry as RegisteredComponentRegistry<C>;\n\t\tconst components = this.components as Partial<C>;\n\t\tfor(let name of Object.keys(components) as Array<keyof C>) {\n\t\t\tconst definition = registry[name];\n\t\t\tconst component = components[name];\n\t\t\tif(definition.save && component) {\n\t\t\t\tObject.assign(config, definition.save(component));\n\t\t\t}\n\t\t}\n\n\t\treturn config as Cfg;\n\t}\n\t// Second pass once every entity in a load batch exists; loads the deferred (loadInFinishLoading)\n\t// components load skipped. Overrides should call super.\n\tfinishLoading() {\n\t\tconst config = this.config;\n\t\tif(!config) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst props = config as Record<string, unknown>;\n\t\tconst registry = this.world.registry as RegisteredComponentRegistry<C>;\n\t\tfor(let name of Object.keys(registry) as Array<keyof C>) {\n\t\t\tif(name === 'entity') {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif(!this.isComponentAllowed(name)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst definition = registry[name];\n\t\t\tif(definition.loadInFinishLoading && definition.loadProperties.some(prop => prop in props)) {\n\t\t\t\tthis.loadComponent(name, config, false);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate isComponentAllowed(name: keyof C): boolean {\n\t\treturn name === 'entity' || !this.allowedComponents || this.allowedComponents.has(String(name));\n\t}\n\tsetAllowedComponents(allowedComponents: ReadonlySet<string> | undefined): void {\n\t\tif(this.allowedComponents && this.allowedComponents !== allowedComponents) {\n\t\t\tthrow new Error('Entity component allowlist is immutable');\n\t\t}\n\t\tthis.allowedComponents = allowedComponents;\n\t}\n\tprivate assertComponentAllowed(name: keyof C): void {\n\t\tif(!this.isComponentAllowed(name)) {\n\t\t\tthrow new Error(`Component ${String(name)} is not allowed for entity type ${this.type}`);\n\t\t}\n\t}\n\tprivate assertComponentPropertyMutable(componentName: keyof C, prop: PropertyKey): void {\n\t\tif(componentName === 'entity' && (prop === 'type' || prop === 'class')) {\n\t\t\tthrow new Error(`Entity ${prop} is immutable`);\n\t\t}\n\t}\n}\n","import BaseEntity from './entity';\nimport type BaseWorld from './world';\nimport type { ComponentDefinitionMap, ComponentMap } from './component-definition';\nimport type { EntityClassDefinition, EntityClassRegistry, WorkerEntityClassRegistry } from './entity-class';\n\n// Maps type to a template and optionally maps the template's class to a wrapper + component allowlist.\nexport default class EntityFactory<\n\tC extends ComponentMap = ComponentMap,\n\tCfg = any,\n\tE extends BaseEntity<C, Cfg> = BaseEntity<C, Cfg>,\n> {\n\tworld!: BaseWorld<ComponentDefinitionMap, C, Cfg, E>;\n\tconfigs: { [type: string]: Cfg };\n\tclasses: EntityClassRegistry;\n\tprivate allowedComponents = new Map<string, ReadonlySet<string>>();\n\n\tconstructor(configs: { [type: string]: Cfg } = {}, classes: EntityClassRegistry = {}) {\n\t\tthis.configs = configs;\n\t\tthis.classes = classes;\n\t\tfor(const name of Object.keys(classes)) {\n\t\t\tthis.allowedComponents.set(name, new Set(classes[name].components));\n\t\t}\n\t}\n\n\tregister(type: string, config: Cfg) {\n\t\tif(this.world) {\n\t\t\tthis.validateTemplate(type, config);\n\t\t}\n\t\tthis.configs[type] = config;\n\t}\n\n\tsetWorld(world: BaseWorld<ComponentDefinitionMap, C, Cfg, E>): void {\n\t\tthis.world = world;\n\t\tfor(const name of Object.keys(this.classes)) {\n\t\t\tconst constructor = this.classes[name].entity;\n\t\t\tif(constructor !== BaseEntity && !(constructor.prototype instanceof BaseEntity)) {\n\t\t\t\tthrow new Error(`Entity class ${name} must extend BaseEntity`);\n\t\t\t}\n\t\t\tfor(const component of this.classes[name].components) {\n\t\t\t\tif(component === 'entity' || !(component in world.registry)) {\n\t\t\t\t\tthrow new Error(`Entity class ${name} contains unknown or reserved component ${component}`);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tfor(const type of Object.keys(this.configs)) {\n\t\t\tthis.validateTemplate(type, this.configs[type]);\n\t\t}\n\t}\n\n\tgetConfig(config: Cfg): Cfg {\n\t\tconst input = config as { type?: string, class?: unknown } | undefined;\n\t\tconst type = input?.type;\n\t\tconst base = type ? this.configs[type] : undefined;\n\t\tif(this.hasClasses) {\n\t\t\tif(!type || !base) {\n\t\t\t\tthrow new Error(`Unknown entity type: ${type ?? ''}`);\n\t\t\t}\n\t\t\tif(Object.prototype.hasOwnProperty.call(input, 'class')) {\n\t\t\t\tthrow new Error('Entity class comes from its type template and cannot be supplied by an instance config');\n\t\t\t}\n\t\t}\n\t\tconst merged = base ? { ...base, ...config } : config;\n\t\tif(this.hasClasses && type) {\n\t\t\tthis.validateResolvedConfig(type, merged);\n\t\t}\n\t\treturn merged;\n\t}\n\n\tloadEntity(config: Cfg, created = true): E {\n\t\tconst requestedType = (config as { type?: string }).type;\n\t\tconst merged = this.getConfig(config);\n\t\tif(this.hasClasses && requestedType) {\n\t\t\tthis.validateResolvedConfig(requestedType, merged);\n\t\t}\n\t\tconst definition = this.getClassDefinition(merged);\n\t\tconst entity = definition\n\t\t\t? this.constructEntity(definition, merged)\n\t\t\t: this.createEntity(merged);\n\t\treturn this.world.addEntity(entity, created);\n\t}\n\n\tcreateAdoptedEntity(type: string, entityClass: string | undefined, eid: number): E {\n\t\tif(!entityClass) {\n\t\t\tif(this.hasClasses) {\n\t\t\t\tthrow new Error(`Entity type ${type} has no class`);\n\t\t\t}\n\t\t\treturn new BaseEntity<C, Cfg>(this.world, undefined, eid) as E;\n\t\t}\n\t\tconst definition = this.classes[entityClass];\n\t\tif(!definition) {\n\t\t\tthrow new Error(`Unknown entity class: ${entityClass}`);\n\t\t}\n\t\tthis.validateTypeClass(type, entityClass);\n\t\tconst entity = Reflect.construct(definition.entity, [this.world, undefined, eid, this.allowedComponents.get(entityClass)]) as E;\n\t\tentity.setAllowedComponents(this.allowedComponents.get(entityClass));\n\t\treturn entity;\n\t}\n\n\tisComponentAllowed(entityClass: string | undefined, component: string): boolean {\n\t\treturn !entityClass || !this.hasClasses || this.allowedComponents.get(entityClass)?.has(component) === true;\n\t}\n\n\tgetWorkerClasses(): WorkerEntityClassRegistry | undefined {\n\t\tif(!this.hasClasses) {\n\t\t\treturn undefined;\n\t\t}\n\t\tconst classes: WorkerEntityClassRegistry = {};\n\t\tfor(const name of Object.keys(this.classes)) {\n\t\t\tclasses[name] = { components: [...this.classes[name].components] };\n\t\t}\n\t\treturn classes;\n\t}\n\n\tgetAllowedComponentsForConfig(config: Cfg | undefined): ReadonlySet<string> | undefined {\n\t\treturn config ? this.getAllowedComponents(config) : undefined;\n\t}\n\n\tprotected createEntity(config: Cfg): E {\n\t\treturn new BaseEntity<C, Cfg>(this.world, config) as E;\n\t}\n\n\tprivate get hasClasses(): boolean {\n\t\treturn this.allowedComponents.size > 0;\n\t}\n\tprivate getClassDefinition(config: Cfg): EntityClassDefinition | undefined {\n\t\tconst entityClass = (config as { class?: string }).class;\n\t\treturn entityClass ? this.classes[entityClass] : undefined;\n\t}\n\tprivate getAllowedComponents(config: Cfg): ReadonlySet<string> | undefined {\n\t\tconst entityClass = (config as { class?: string }).class;\n\t\treturn entityClass ? this.allowedComponents.get(entityClass) : undefined;\n\t}\n\tprivate constructEntity(definition: EntityClassDefinition, config: Cfg): E {\n\t\tconst entityClass = (config as { class?: string }).class;\n\t\treturn Reflect.construct(definition.entity, [this.world, config, undefined, this.allowedComponents.get(entityClass ?? '')]) as E;\n\t}\n\tprivate validateTemplate(type: string, config: Cfg): void {\n\t\tif(!this.hasClasses) {\n\t\t\treturn;\n\t\t}\n\t\tconst identity = config as { type?: string, class?: string };\n\t\tif(identity.type !== type) {\n\t\t\tthrow new Error(`Entity template ${type} must declare the same type`);\n\t\t}\n\t\tif(!identity.class || !this.classes[identity.class]) {\n\t\t\tthrow new Error(`Entity template ${type} has unknown class ${identity.class ?? ''}`);\n\t\t}\n\t\tthis.validateComponentTriggers(type, identity.class, config);\n\t}\n\tprivate validateResolvedConfig(type: string, config: Cfg): void {\n\t\tconst identity = config as { type?: string, class?: string };\n\t\tif(identity.type !== type) {\n\t\t\tthrow new Error(`Entity type ${type} is immutable`);\n\t\t}\n\t\tif(!identity.class || !this.classes[identity.class]) {\n\t\t\tthrow new Error(`Entity type ${type} has unknown class ${identity.class ?? ''}`);\n\t\t}\n\t\tthis.validateTypeClass(type, identity.class);\n\t\tthis.validateComponentTriggers(type, identity.class, config);\n\t}\n\tprivate validateTypeClass(type: string, entityClass: string): void {\n\t\tconst template = this.configs[type] as { class?: string } | undefined;\n\t\tif(!template || template.class !== entityClass) {\n\t\t\tthrow new Error(`Entity type ${type} does not belong to class ${entityClass}`);\n\t\t}\n\t}\n\tprivate validateComponentTriggers(type: string, entityClass: string, config: Cfg): void {\n\t\tconst allowed = this.allowedComponents.get(entityClass)!;\n\t\tconst allowedProperties = new Set<string>();\n\t\tfor(const component of allowed) {\n\t\t\tfor(const prop of this.world.registry[component as keyof C].loadProperties) {\n\t\t\t\tallowedProperties.add(prop);\n\t\t\t}\n\t\t}\n\t\tconst props = config as Record<string, unknown>;\n\t\tfor(const name of Object.keys(this.world.registry)) {\n\t\t\tif(name === 'entity' || allowed.has(name)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tconst definition = this.world.registry[name as keyof C];\n\t\t\tconst forbidden = definition.loadProperties.find(prop => prop in props && !allowedProperties.has(prop));\n\t\t\tif(forbidden) {\n\t\t\t\tthrow new Error(`Entity type ${type} class ${entityClass} cannot load component ${name} from property ${forbidden}`);\n\t\t\t}\n\t\t}\n\t}\n}\n","import { EventEmitter } from 'eventemitter3';\nimport MemoryHeap from '@daneren2005/shared-memory-objects/memory-heap';\nimport type { GrowBufferData } from '@daneren2005/shared-memory-objects/memory-heap';\nimport type AllocatedMemory from '@daneren2005/shared-memory-objects/allocated-memory';\nimport type { SharedAllocatedMemory } from '@daneren2005/shared-memory-objects/allocated-memory';\nimport type { SharedPoolMemory } from '@daneren2005/shared-memory-objects/shared-pool';\nimport { MAX_BYTE_OFFSET_LENGTH } from '@daneren2005/shared-memory-objects/utils/pointer';\nimport MemoryComponent from './memory-component';\nimport ConstantStringCache from './constant-string-cache';\nimport type BaseEntity from './entity';\nimport type System from './systems/system';\nimport EntitySystem from './systems/entity-system';\nimport EntityWorkerSystem from './systems/entity-worker-system';\nimport type { WorkerCreatedEntity } from './systems/entity-worker-system';\nimport type {\n\tBaseComponent, ComponentDefinitionMap, ComponentMap, ComponentRegistry, ComponentsOf,\n\tEntityConfigOf, RegisteredComponentDefinition, RegisteredComponentRegistry,\n} from './component-definition';\nimport { entityDefinition, type EntityComponent } from './entity-component';\nimport EntityFactory from './entity-factory';\n\nconst DEFAULT_HEAP_SIZE = MAX_BYTE_OFFSET_LENGTH;\nconst FREE_BUFFER_STUCK_MS = 10000;\n\ninterface DeferredComponentFree {\n\tmemoryComponent: MemoryComponent\n\tindex: number\n\t// The definition's free hook, deferred to fire alongside the block free rather than the instant the entity dies.\n\tfree?: () => void\n}\n// A batch of component blocks queued to be freed, plus the systems that must each finish a run before it is safe to free them\ninterface ComponentFreeBuffer<C extends ComponentMap> {\n\tfrees: Array<DeferredComponentFree>\n\twaitingSystems: Set<System<C>>\n\twaitElapsed: number\n}\n\nexport interface WorldOptions<\n\tC extends ComponentMap = ComponentMap,\n\tCfg = any,\n\tE extends BaseEntity<C, Cfg> = BaseEntity<C, Cfg>,\n> {\n\theapSize?: number\n\tfactory?: EntityFactory<C, Cfg, E>\n}\n\nexport interface WorldConfig<Cfg = any> {\n\tentities: Array<Cfg>\n\tgameTime?: number\n\tplayerTime?: number\n\ttimeScale?: number\n}\n\n// Shipped to a worker so it can reconstruct handles over this world's shared state (see getSharedComponentMemory).\nexport interface WorldSharedMemory {\n\tcomponents: { [name: string]: SharedPoolMemory }\n\teidCounter: SharedAllocatedMemory\n}\n\nexport default class BaseWorld<\n\tR extends ComponentDefinitionMap = ComponentDefinitionMap,\n\tC extends ComponentMap = ComponentsOf<R>,\n\tCfg = EntityConfigOf<R>,\n\tE extends BaseEntity<C, Cfg> = BaseEntity<C, Cfg>,\n> extends EventEmitter {\n\theap: MemoryHeap;\n\t// Interns entity type names (and any other constant strings) in the heap\n\tconstantStrings: ConstantStringCache;\n\t// Single heap-backed counter every thread bumps atomically, so eids stay unique whether an entity is created on\n\t// the main thread or inside a worker.\n\tprivate eidCounter: AllocatedMemory;\n\tregistry: RegisteredComponentRegistry<C> & { entity: RegisteredComponentDefinition<EntityComponent> };\n\tfactory: EntityFactory<C, Cfg, E>;\n\n\t// Keyed by eid: entities leave from the middle one at a time (every death), so a Map deletes in constant\n\t// time while still iterating in insertion order, preserving load/save order.\n\tentities: Map<number, E> = new Map();\n\tsystems: Array<System<C>> = [];\n\n\tgameTime = 0;\n\t// Keeps advancing while paused and is never scaled by timeScale (unlike gameTime).\n\tplayerTime = 0;\n\ttimeScale = 1;\n\tpaused = false;\n\tdestroyed = false;\n\t// True while the world has never been loaded into\n\tpristine = true;\n\n\t// Two rolling buffers of component blocks awaiting a safe free. New deferrals land in `next`; `active` is the\n\t// one currently waiting for its systems to each finish a run before its blocks can be reused\n\tprivate activeFreeBuffer: ComponentFreeBuffer<C> = { frees: [], waitingSystems: new Set(), waitElapsed: 0 };\n\tprivate nextFreeBuffer: ComponentFreeBuffer<C> = { frees: [], waitingSystems: new Set(), waitElapsed: 0 };\n\n\t// The entity component is added automatically, so it must not be part of the passed registry.\n\tconstructor(registry: R, options: WorldOptions<C, Cfg, E> = {}) {\n\t\tsuper();\n\n\t\tthis.heap = new MemoryHeap({ bufferSize: options.heapSize ?? DEFAULT_HEAP_SIZE });\n\t\tthis.constantStrings = new ConstantStringCache(this.heap);\n\t\tthis.eidCounter = this.heap.allocUI32(1);\n\t\t// A grown buffer must reach every worker's reconstructed heap so pointers into it still resolve.\n\t\tthis.heap.addOnGrowBufferHandlers((data: GrowBufferData) => this.emit('grow-buffer', data));\n\n\t\tconst inputRegistry = { ...registry, entity: entityDefinition } as ComponentRegistry<C> & { entity: typeof entityDefinition };\n\t\tconst registry_: Record<string, RegisteredComponentDefinition<BaseComponent>> = {};\n\t\tfor(let name of Object.keys(inputRegistry)) {\n\t\t\tconst definition = inputRegistry[name as keyof typeof inputRegistry];\n\t\t\tregistry_[name] = {\n\t\t\t\t...definition,\n\t\t\t\tmemoryComponent: new MemoryComponent(this.heap, definition.type, definition.size),\n\t\t\t};\n\t\t}\n\t\tthis.registry = registry_ as RegisteredComponentRegistry<C> & { entity: RegisteredComponentDefinition<EntityComponent> };\n\n\t\tthis.factory = options.factory ?? new EntityFactory<C, Cfg, E>();\n\t\tthis.factory.setWorld(this);\n\t}\n\n\t// Returns a fresh, unique entity id. Backed by a heap atomic so a worker allocating an entity gets an id that can\n\t// never collide with one the main thread (or another worker) hands out. First id is 1, matching the old counter.\n\tallocateEid(): number {\n\t\treturn Atomics.add(this.eidCounter.data, 0, 1) + 1;\n\t}\n\t// Everything a worker needs to reconstruct handles over this world's shared state: one SharedPoolMemory per\n\t// registered component (so it can allocate/read blocks) plus the eid counter (so it can mint unique ids).\n\tgetSharedComponentMemory(): WorldSharedMemory {\n\t\tconst components: { [name: string]: SharedPoolMemory } = {};\n\t\tfor(let name of Object.keys(this.registry)) {\n\t\t\tcomponents[name] = this.registry[name as keyof typeof this.registry].memoryComponent.getSharedMemory();\n\t\t}\n\t\treturn {\n\t\t\tcomponents,\n\t\t\teidCounter: this.eidCounter.getSharedMemory(),\n\t\t};\n\t}\n\t// A buffer that was grown inside a worker: adopt it into the main heap (if not already present) and fan it out to\n\t// every other worker so their heaps can resolve pointers into it. The heap's BUFFER_COUNT is authoritative, so\n\t// re-adding an already-known position is a harmless overwrite of the same SharedArrayBuffer.\n\taddGrownBuffer(data: GrowBufferData) {\n\t\tif(this.heap.buffers[data.bufferPosition] === undefined) {\n\t\t\tthis.heap.addSharedBuffer(data);\n\t\t}\n\t\tthis.emit('grow-buffer', data);\n\t}\n\n\t// Only an off-thread EntityWorkerSystem that creates entities or adds components allocates in a worker, so only\n\t// then is a pre-fanned-out spare buffer worth keeping. The main-thread fallback allocates on the main thread, where\n\t// growth fans out inline, so it never needs one.\n\tprivate get needsSpareBuffer(): boolean {\n\t\treturn this.systems.some(system => system instanceof EntityWorkerSystem\n\t\t\t&& system.isWorkerThread\n\t\t\t&& (!!system.options.createsEntities || !!system.options.addsComponents));\n\t}\n\n\tasync init() {\n\t\tawait Promise.all(this.systems.map(system => system.init()).filter(promise => promise instanceof Promise));\n\t}\n\tprivate finishLoadingSystems() {\n\t\treturn Promise.all(this.systems.map(system => system.finishLoading()).filter(promise => promise instanceof Promise));\n\t}\n\n\taddEntity(entity: E, created = true): E {\n\t\tthis.entities.set(entity.eid, entity);\n\t\tentity.world = this;\n\t\t// Any entity in the world means there is state to tear down on the next load/clear.\n\t\tthis.pristine = false;\n\n\t\tentity.on('component-added', (name: keyof C) => {\n\t\t\tthis.addEntityToEntityWorkerSystem(entity, name);\n\t\t});\n\t\tentity.on('component-removed', (name: keyof C) => {\n\t\t\tthis.removeEntityFromEntityWorkerSystem(entity, name);\n\t\t});\n\n\t\tif(created) {\n\t\t\tentity.finishLoading();\n\t\t\tthis.emit('entity-added', entity);\n\t\t\tentity.on('death', () => {\n\t\t\t\tthis.onEntityDied(entity);\n\t\t\t});\n\t\t}\n\n\t\treturn entity;\n\t}\n\tloadEntity(config: Cfg, created = true): E {\n\t\treturn this.factory.loadEntity(config, created);\n\t}\n\t// Materializes an entity a worker created off-thread (see createEntityWorker): the worker already minted the id and\n\t// allocated + wrote every game-component block, so this only builds the `entity` component on the main thread\n\t// (interning its type) and adopts each worker-allocated block by index, then wires it into the world like any new\n\t// entity. The factory selects the same class wrapper a main-thread load would use.\n\tadoptEntity(descriptor: WorkerCreatedEntity): E {\n\t\tlet entity: E | undefined;\n\t\tconst attached = new Set<string>();\n\t\ttry {\n\t\t\tfor(const name of Object.keys(descriptor.components)) {\n\t\t\t\tif(!(name in this.registry)) {\n\t\t\t\t\tthrow new Error(`Worker-created entity contains unknown component ${name}`);\n\t\t\t\t}\n\t\t\t\tif(!this.factory.isComponentAllowed(descriptor.class, name)) {\n\t\t\t\t\tthrow new Error(`Component ${name} is not allowed for entity class ${descriptor.class ?? ''}`);\n\t\t\t\t}\n\t\t\t}\n\t\t\tentity = this.factory.createAdoptedEntity(descriptor.type, descriptor.class, descriptor.eid);\n\t\t\tentity.loadComponent('entity', { type: descriptor.type, class: descriptor.class, isStatic: descriptor.isStatic }, false);\n\t\t\tfor(let name of Object.keys(descriptor.components)) {\n\t\t\t\tentity.attachComponent(name, descriptor.components[name]);\n\t\t\t\tattached.add(name);\n\t\t\t}\n\t\t\treturn this.addEntity(entity, true);\n\t\t} catch(error) {\n\t\t\tentity?.deleteAllComponentMemory();\n\t\t\tfor(const name of Object.keys(descriptor.components)) {\n\t\t\t\tif(!attached.has(name) && name in this.registry) {\n\t\t\t\t\tthis.deferComponentMemoryFree(this.registry[name as keyof C].memoryComponent, descriptor.components[name]);\n\t\t\t\t}\n\t\t\t}\n\t\t\tthrow error;\n\t\t}\n\t}\n\t// Replaces the world's contents. Entities load with created = false so no finishLoading runs mid-batch;\n\t// finishLoading is called on each once the whole batch exists, so cross-entity dependencies can resolve.\n\tload(config: WorldConfig<Cfg>) {\n\t\t// A pristine world (fresh or just cleared) has nothing to tear down, so skip the per-system clear.\n\t\tif(!this.pristine) {\n\t\t\t// Iterate over a copy since removeEntity mutates `this.entities`.\n\t\t\tfor(let entity of Array.from(this.entities.values())) {\n\t\t\t\tthis.removeEntity(entity);\n\t\t\t}\n\t\t\tthis.systems.forEach(system => system.clear());\n\t\t\tthis.consolidateFreeBuffersForReload();\n\t\t}\n\n\t\t// Intern a constant string for every type the factory knows, so a worker can resolve any type - even one no\n\t\t// currently-loaded entity uses. Deduped, so the types actually loaded below cost nothing extra.\n\t\tfor(let type of Object.keys(this.factory.configs)) {\n\t\t\tthis.constantStrings.getOrCreate(type);\n\t\t}\n\t\tfor(let entityClass of Object.keys(this.factory.classes)) {\n\t\t\tthis.constantStrings.getOrCreate(entityClass);\n\t\t}\n\n\t\tconst entities = config.entities.map(entityConfig => this.loadEntity(entityConfig, false));\n\t\tfor(let entity of entities) {\n\t\t\tentity.finishLoading();\n\t\t\tthis.emit('entity-added', entity);\n\t\t\tentity.on('death', () => {\n\t\t\t\tthis.onEntityDied(entity);\n\t\t\t});\n\t\t}\n\n\t\tthis.gameTime = config.gameTime ?? 0;\n\t\tthis.playerTime = config.playerTime ?? 0;\n\t\tthis.timeScale = config.timeScale ?? 1;\n\n\t\t// EntityWorkerSystem re-sends its init data here.\n\t\tvoid this.finishLoadingSystems();\n\t}\n\tasync clear(): Promise<void> {\n\t\tif(this.pristine) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Capture and await active runs before clear() resets their state. Component blocks cannot be released while a\n\t\t// worker still holds views over them, since the pool may immediately reuse those indexes after clear resolves.\n\t\tawait Promise.all(\n\t\t\tthis.systems\n\t\t\t\t.map(system => system.waitForRunToComplete())\n\t\t\t\t.filter(promise => promise instanceof Promise),\n\t\t);\n\t\tfor(let entity of Array.from(this.entities.values())) {\n\t\t\tthis.removeEntity(entity);\n\t\t}\n\t\tthis.systems.forEach(system => system.clear());\n\t\tthis.freeAllPendingBuffers();\n\n\t\tthis.pristine = true;\n\t}\n\tremoveEntity(entity: E) {\n\t\t// Match the instance as well as the eid: a stale entity must not remove a newer entity that owns the same key.\n\t\tif(this.entities.get(entity.eid) !== entity) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.entities.delete(entity.eid);\n\t\tthis.emit('entity-removed', entity);\n\t\tentity.deleteAllComponentMemory();\n\t}\n\t// Fires the death hooks then removes the entity\n\tonEntityDied(entity: E) {\n\t\tif(this.entities.get(entity.eid) !== entity) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst registry = this.registry as RegisteredComponentRegistry<C>;\n\t\tconst components = entity.components as Partial<C>;\n\t\tfor(let name of Object.keys(components) as Array<keyof C>) {\n\t\t\tconst definition = registry[name];\n\t\t\tconst component = components[name];\n\t\t\tif(definition?.died && component) {\n\t\t\t\t// A bad hook must not abort the death; mirror the update-loop convention and surface a system-error.\n\t\t\t\ttry {\n\t\t\t\t\tdefinition.died(component, entity, this as unknown as BaseWorld);\n\t\t\t\t} catch(e) {\n\t\t\t\t\tconst error = e as Error;\n\t\t\t\t\tconsole.error(`Error in died hook for component ${String(name)} (entity ${entity.eid}): ${error.message}`, error);\n\t\t\t\t\tthis.emit('system-error', { system: String(name), error, entityId: entity.eid, phase: 'died' });\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tthis.emit('entity-died', entity);\n\t\tthis.removeEntity(entity);\n\t}\n\tgetEntityByEid(eid: number): E | undefined {\n\t\treturn this.entities.get(eid);\n\t}\n\n\t// Queues a component block to be freed when all systems done using it, running the definition's free hook (if any)\n\t// at that same deferred point so a system still mid-run can't observe the resource being torn down early.\n\tdeferComponentMemoryFree(memoryComponent: MemoryComponent, index: number, free?: () => void) {\n\t\tthis.nextFreeBuffer.frees.push({ memoryComponent, index, free });\n\t}\n\t// A system finished a run; if the active buffer was waiting on it, drop it and, once nothing is left to wait\n\t// for, free the buffer. One completion is enough: the system is now done touching the block for that run, and\n\t// every later run applies the pending removed-delta before its update loop, so it can never process the freed\n\t// entity again.\n\tnotifySystemRunCompleted(system: System<C>) {\n\t\tif(this.activeFreeBuffer.waitingSystems.delete(system) && this.activeFreeBuffer.waitingSystems.size === 0) {\n\t\t\tthis.processFreeBuffers();\n\t\t}\n\t}\n\tprivate processFreeBuffers() {\n\t\t// Loop so a promoted buffer with no systems to wait for is freed the same tick rather than a frame later.\n\t\twhile(this.activeFreeBuffer.waitingSystems.size === 0) {\n\t\t\tif(this.activeFreeBuffer.frees.length > 0) {\n\t\t\t\tthis.performFrees(this.activeFreeBuffer);\n\t\t\t}\n\t\t\tif(this.nextFreeBuffer.frees.length === 0) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tthis.promoteNextFreeBuffer();\n\t\t}\n\t}\n\tprivate promoteNextFreeBuffer() {\n\t\t// active is now empty (its frees were performed); swap roles and reuse it as the new next buffer.\n\t\tconst emptied = this.activeFreeBuffer;\n\t\tthis.activeFreeBuffer = this.nextFreeBuffer;\n\t\tthis.nextFreeBuffer = emptied;\n\n\t\tconst active = this.activeFreeBuffer;\n\t\tactive.waitElapsed = 0;\n\t\tactive.waitingSystems.clear();\n\t\tfor(let system of this.systems) {\n\t\t\t// Wait on a system if it will run (and so might pick up this block) or is already mid-run over memory we\n\t\t\t// may free. A system that is neither can't touch these blocks, so there's nothing to wait for.\n\t\t\tif(system.shouldRun() || system.isCurrentlyRunning()) {\n\t\t\t\tactive.waitingSystems.add(system);\n\t\t\t}\n\t\t}\n\t}\n\t// On reload every system was just cleared (its completedRuns reset and worker told to drop its lists), so the\n\t// old targets no longer apply. Collapse whatever was pending into `next` with a fresh (empty) active buffer\n\tprivate consolidateFreeBuffersForReload() {\n\t\tif(this.activeFreeBuffer.frees.length > 0) {\n\t\t\tthis.nextFreeBuffer.frees.push(...this.activeFreeBuffer.frees);\n\t\t\tthis.activeFreeBuffer.frees.length = 0;\n\t\t}\n\t\tthis.activeFreeBuffer.waitingSystems.clear();\n\t\tthis.activeFreeBuffer.waitElapsed = 0;\n\t}\n\t// Frees both buffers outright. Only safe once every system's in-flight run has finished (see clear()), since it\n\t// skips the per-system wait the update loop normally enforces.\n\tprivate freeAllPendingBuffers() {\n\t\tthis.performFrees(this.activeFreeBuffer);\n\t\tthis.performFrees(this.nextFreeBuffer);\n\t\tthis.activeFreeBuffer.waitingSystems.clear();\n\t\tthis.activeFreeBuffer.waitElapsed = 0;\n\t\tthis.nextFreeBuffer.waitingSystems.clear();\n\t\tthis.nextFreeBuffer.waitElapsed = 0;\n\t}\n\tprivate performFrees(buffer: ComponentFreeBuffer<C>) {\n\t\tfor(let deferred of buffer.frees) {\n\t\t\tdeferred.free?.();\n\t\t\tdeferred.memoryComponent.delete(deferred.index);\n\t\t}\n\t\tbuffer.frees.length = 0;\n\t}\n\tprivate checkFreeBufferTimeout(elapsedTime: number) {\n\t\tconst active = this.activeFreeBuffer;\n\t\tif(active.waitingSystems.size === 0) {\n\t\t\treturn;\n\t\t}\n\n\t\tactive.waitElapsed += elapsedTime;\n\t\tif(active.waitElapsed >= FREE_BUFFER_STUCK_MS) {\n\t\t\tconst stuck = Array.from(active.waitingSystems).map(system => system.name).join(', ');\n\t\t\tconsole.warn(`shared-memory-ecs: deferred component free waited over ${FREE_BUFFER_STUCK_MS}ms on system(s): ${stuck}; freeing anyway`);\n\t\t\tactive.waitingSystems.clear();\n\t\t\tthis.processFreeBuffers();\n\t\t}\n\t}\n\n\taddSystem<T extends System<C>>(system: T): T {\n\t\tthis.systems.push(system);\n\t\tthis.emit('system-added', system);\n\t\treturn system;\n\t}\n\taddSystemIfNotExists(system: System<C>) {\n\t\tlet index = this.systems.findIndex(otherSystem => system.name === otherSystem.name);\n\t\tif(index === -1) {\n\t\t\tthis.systems.push(system);\n\t\t\tthis.emit('system-added', system);\n\t\t}\n\t}\n\tremoveSystem(name: string) {\n\t\tlet index = this.systems.findIndex(system => system.name === name);\n\t\tif(index !== -1) {\n\t\t\tconst [system] = this.systems.splice(index, 1);\n\t\t\tthis.emit('system-removed', system);\n\t\t}\n\t}\n\n\tupdate(elapsedTime: number): { lastSystemError?: Error | null } {\n\t\tthis.emit('update-started', elapsedTime);\n\t\tconst result = this.runUpdate(elapsedTime);\n\t\tthis.emit('update-finished', elapsedTime);\n\n\t\treturn result;\n\t}\n\tprivate runUpdate(elapsedTime: number): { lastSystemError?: Error | null } {\n\t\tthis.playerTime += elapsedTime;\n\t\tif(this.paused) {\n\t\t\treturn {};\n\t\t}\n\t\tconst unscaledElapsedTime = elapsedTime;\n\t\telapsedTime = this.timeScale * elapsedTime;\n\n\t\tthis.gameTime += elapsedTime;\n\n\t\t// Promote before running: a run this same update then counts toward the wait, instead of after it.\n\t\tthis.processFreeBuffers();\n\n\t\t// Keep an empty heap buffer fanned out ahead of any worker that allocates off-thread, so its allocations land in\n\t\t// a buffer every thread already holds. Done here (before dispatching runs) so the resulting grow-buffer message\n\t\t// is queued to each worker before its run message - postMessage is FIFO, so the worker has the buffer first.\n\t\tif(this.needsSpareBuffer) {\n\t\t\tthis.heap.ensureSpareBuffer();\n\t\t}\n\n\t\tlet lastSystemError: Error | null = null;\n\t\tthis.systems.forEach(system => {\n\t\t\tlet shouldRun = true;\n\t\t\tlet ran = false;\n\t\t\tlet failed = false;\n\t\t\tthis.emit(`system-${system.name}-started`);\n\t\t\ttry {\n\t\t\t\tshouldRun = system.shouldRun();\n\t\t\t\tif(shouldRun) {\n\t\t\t\t\tran = system.update(elapsedTime);\n\t\t\t\t}\n\t\t\t} catch(e) {\n\t\t\t\tconst error = e as Error;\n\t\t\t\tconsole.error(error.message, error);\n\t\t\t\tfailed = true;\n\t\t\t\tlastSystemError = error;\n\t\t\t\tthis.emit('system-error', { system: system.name, error, phase: 'run' });\n\t\t\t}\n\t\t\tthis.emit(`system-${system.name}-finished`, {\n\t\t\t\tran,\n\t\t\t\tshouldRun,\n\t\t\t\tfailed,\n\t\t\t});\n\t\t});\n\n\t\tthis.checkFreeBufferTimeout(unscaledElapsedTime);\n\n\t\treturn {\n\t\t\tlastSystemError,\n\t\t};\n\t}\n\tpause() {\n\t\tthis.paused = true;\n\t}\n\tresume() {\n\t\tthis.paused = false;\n\t}\n\n\taddEntityToEntityWorkerSystem(entity: BaseEntity<C>, component: keyof C) {\n\t\tthis.systems.forEach(system => {\n\t\t\tif(system instanceof EntitySystem && system.options.components?.includes(component)) {\n\t\t\t\tsystem.checkAddEntity(entity);\n\t\t\t} else if(system instanceof EntityWorkerSystem) {\n\t\t\t\tif(this.componentAffectsEntityWorkerSystem(system, component)) {\n\t\t\t\t\tsystem.checkAddEntity(entity);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t}\n\tremoveEntityFromEntityWorkerSystem(entity: BaseEntity<C>, component: keyof C) {\n\t\tthis.systems.forEach(system => {\n\t\t\tif(system instanceof EntitySystem && system.options.components?.includes(component)) {\n\t\t\t\tsystem.removeEntity(entity);\n\t\t\t} else if(system instanceof EntityWorkerSystem) {\n\t\t\t\tif(this.componentAffectsEntityWorkerSystem(system, component)) {\n\t\t\t\t\tsystem.checkAddEntity(entity);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t}\n\tprivate componentAffectsEntityWorkerSystem(system: EntityWorkerSystem<C, any>, component: keyof C): boolean {\n\t\tconst affectsMainQuery = system.options.required.includes(component)\n\t\t\t|| !!system.options.not?.includes(component)\n\t\t\t|| !!system.options.optional?.includes(component);\n\t\tconst affectsSubQuery = Object.values(system.options.queries ?? {}).some(query => {\n\t\t\treturn query.required.includes(component)\n\t\t\t\t|| !!query.not?.includes(component)\n\t\t\t\t|| !!query.optional?.includes(component);\n\t\t});\n\n\t\treturn affectsMainQuery || affectsSubQuery;\n\t}\n\n\tdestroy() {\n\t\tif(this.destroyed) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.systems.forEach(system => {\n\t\t\tsystem.destroy();\n\t\t});\n\t\tthis.destroyed = true;\n\t}\n}\n","import type { ComponentDefinitionMap, EntityConfigOf } from './component-definition';\n\nexport type EntityClassConstructor = abstract new (...args: never[]) => { readonly eid: number };\n\nexport interface EntityClassDefinition {\n\tentity: EntityClassConstructor\n\tcomponents: ReadonlyArray<string>\n}\n\nexport type EntityClassRegistry = Record<string, EntityClassDefinition>;\n\ndeclare const ENTITY_CLASSES_TYPE: unique symbol;\n\nexport type DefinedEntityClasses<\n\tR extends ComponentDefinitionMap,\n\tClasses extends EntityClassRegistry,\n> = Classes & { readonly [ENTITY_CLASSES_TYPE]: R };\n\nexport type EntityInstancesOf<Classes extends EntityClassRegistry> = InstanceType<Classes[keyof Classes & string]['entity']>;\n\ntype RegistryOf<Classes extends EntityClassRegistry> = Classes extends DefinedEntityClasses<infer R, EntityClassRegistry> ? R : never;\ntype ComponentKeysOf<Definition> = Definition extends { components: ReadonlyArray<infer K> } ? K : never;\n\nexport type EntityClassTemplateConfig<\n\tClasses extends EntityClassRegistry,\n\tClassName extends keyof Classes & string,\n\tR extends ComponentDefinitionMap = RegistryOf<Classes>,\n> = EntityConfigOf<Pick<R, Extract<ComponentKeysOf<Classes[ClassName]>, keyof R>>> & {\n\ttype: string\n\tclass: ClassName\n};\n\nexport type EntityTemplateConfigOf<Classes extends EntityClassRegistry> = {\n\t[ClassName in keyof Classes & string]: EntityClassTemplateConfig<Classes, ClassName>\n}[keyof Classes & string];\n\nexport type EntityInstanceConfigOf<Classes extends EntityClassRegistry> = EntityTemplateConfigOf<Classes> extends infer Config\n\t? Config extends object ? Omit<Config, 'class'> & { class?: never } : never\n\t: never;\n\ntype EntityClassInput<R extends ComponentDefinitionMap> = Record<string, {\n\tentity: EntityClassConstructor\n\tcomponents: ReadonlyArray<keyof R & string>\n}>;\n\ntype ExactEntityConfig<Classes extends EntityClassRegistry, ClassName extends keyof Classes & string, Type, Config> = Config\n\t& EntityClassTemplateConfig<Classes, ClassName>\n\t& { type: Type }\n\t& Record<Exclude<keyof Config, keyof EntityClassTemplateConfig<Classes, ClassName>>, never>;\n\ntype CheckedEntityConfig<Classes extends EntityClassRegistry, Type, Config> =\n\tConfig extends { class: infer ClassName }\n\t\t? ClassName extends keyof Classes & string\n\t\t\t? ExactEntityConfig<Classes, ClassName, Type, Config>\n\t\t\t: never\n\t\t: never;\n\ntype CheckedEntityConfigs<Classes extends EntityClassRegistry, Configs> = {\n\t[K in keyof Configs]: CheckedEntityConfig<Classes, K, Configs[K]>\n};\n\nexport function defineEntityClasses<\n\tR extends ComponentDefinitionMap,\n\tconst Classes extends EntityClassInput<R>,\n>(_registry: R, classes: Classes): DefinedEntityClasses<R, Classes> {\n\treturn classes as DefinedEntityClasses<R, Classes>;\n}\n\nexport function defineEntityConfigs<\n\tClasses extends EntityClassRegistry,\n\tconst Configs extends Record<string, { type: string, class: keyof Classes & string }>,\n>(_classes: Classes, configs: Configs & CheckedEntityConfigs<Classes, Configs>): Configs {\n\treturn configs;\n}\n\nexport interface WorkerEntityClassDefinition {\n\tcomponents: Array<string>\n}\n\nexport type WorkerEntityClassRegistry = Record<string, WorkerEntityClassDefinition>;\n","import type BaseEntity from '../entity';\n\n// Flags the entity dead in shared memory and emits `death`; BaseWorld listens for it to remove the entity.\nexport default function killEntity(entity: BaseEntity): void {\n\tentity.components.entity.dead = true;\n\tentity.emit('death');\n}\n","import { EventEmitter } from 'eventemitter3';\nimport type BaseWorld from './world';\nimport type { ComponentDefinitionMap, ComponentMap } from './component-definition';\nimport type System from './systems/system';\n\nexport const DEFAULT_TICKS_BETWEEN_UPDATES = 1_000;\n\nexport interface TimingStats {\n\tavg: number\n\tmin: number\n\tmax: number\n\tsamples: number\n}\n\nexport interface SystemTimingStats {\n\tname: string\n\trun: TimingStats\n\tevents: TimingStats\n}\n\nexport interface PerformanceStats {\n\tupdate: TimingStats\n\tsystems: Array<SystemTimingStats>\n\tevents: TimingStats\n}\n\nexport interface PerformanceTimingOptions {\n\tticksBetweenUpdates?: number\n}\n\ninterface SystemTiming {\n\trun: Array<number>\n\tevents: Array<number>\n\t// -1 when no run is being dispatched.\n\teventStart: number\n\tonRunFinished: (runTime: number) => void\n\tonEventsFinished: () => void\n}\n\nconst EMPTY_TIMING: TimingStats = { avg: 0, min: 0, max: 0, samples: 0 };\n\n// An empty window reads as zeroes (not an infinite min) so a snapshot is always safe to render.\nfunction summarize(samples: Array<number>): TimingStats {\n\tif(!samples.length) {\n\t\treturn { ...EMPTY_TIMING };\n\t}\n\n\tlet total = 0;\n\tlet min = Infinity;\n\tlet max = 0;\n\tfor(let sample of samples) {\n\t\ttotal += sample;\n\t\tif(sample < min) {\n\t\t\tmin = sample;\n\t\t}\n\t\tif(sample > max) {\n\t\t\tmax = sample;\n\t\t}\n\t}\n\n\treturn {\n\t\tavg: total / samples.length,\n\t\tmin,\n\t\tmax,\n\t\tsamples: samples.length,\n\t};\n}\n\n// Watches a world and reports what it costs to run, driven off events the world emits. Emits `stats-updated`\n// every `ticksBetweenUpdates`; paused frames are skipped.\nexport default class PerformanceTiming<C extends ComponentMap = ComponentMap> extends EventEmitter {\n\tworld: BaseWorld<ComponentDefinitionMap, C>;\n\tticksBetweenUpdates: number;\n\tstats: PerformanceStats = {\n\t\tupdate: { ...EMPTY_TIMING },\n\t\tsystems: [],\n\t\tevents: { ...EMPTY_TIMING },\n\t};\n\n\tprivate ticks = 0;\n\tprivate updateStart = 0;\n\tprivate updateTimes: Array<number> = [];\n\tprivate systemTimings = new Map<string, SystemTiming>();\n\tprivate destroyed = false;\n\n\tconstructor(world: BaseWorld<ComponentDefinitionMap, C>, options: PerformanceTimingOptions = {}) {\n\t\tsuper();\n\n\t\tthis.world = world;\n\t\tthis.ticksBetweenUpdates = options.ticksBetweenUpdates ?? DEFAULT_TICKS_BETWEEN_UPDATES;\n\n\t\tworld.on('update-started', this.onUpdateStarted);\n\t\tworld.on('update-finished', this.onUpdateFinished);\n\t\tworld.on('system-added', this.onSystemAdded);\n\t\tworld.on('system-removed', this.onSystemRemoved);\n\t\tworld.systems.forEach(system => this.trackSystem(system));\n\t}\n\n\tgetSystemStats(name: string): SystemTimingStats | undefined {\n\t\treturn this.stats.systems.find(system => system.name === name);\n\t}\n\n\treset() {\n\t\tthis.ticks = 0;\n\t\tthis.updateTimes = [];\n\t\tthis.systemTimings.forEach(timing => {\n\t\t\ttiming.run = [];\n\t\t\ttiming.events = [];\n\t\t\ttiming.eventStart = -1;\n\t\t});\n\t\tthis.stats = {\n\t\t\tupdate: { ...EMPTY_TIMING },\n\t\t\tsystems: [],\n\t\t\tevents: { ...EMPTY_TIMING },\n\t\t};\n\t}\n\n\tdestroy() {\n\t\tif(this.destroyed) {\n\t\t\treturn;\n\t\t}\n\t\tthis.destroyed = true;\n\n\t\tthis.world.off('update-started', this.onUpdateStarted);\n\t\tthis.world.off('update-finished', this.onUpdateFinished);\n\t\tthis.world.off('system-added', this.onSystemAdded);\n\t\tthis.world.off('system-removed', this.onSystemRemoved);\n\t\tArray.from(this.systemTimings.keys()).forEach(name => this.untrackSystem(name));\n\t\tthis.removeAllListeners();\n\t}\n\n\tprivate onUpdateStarted = () => {\n\t\tthis.updateStart = performance.now();\n\t};\n\n\tprivate onUpdateFinished = (elapsedTime: number) => {\n\t\tif(this.world.paused) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.updateTimes.push(performance.now() - this.updateStart);\n\n\t\tthis.ticks += elapsedTime;\n\t\tif(this.ticks >= this.ticksBetweenUpdates) {\n\t\t\tthis.recalculate();\n\t\t}\n\t};\n\n\tprivate onSystemAdded = (system: System<C>) => {\n\t\tthis.trackSystem(system);\n\t};\n\n\tprivate onSystemRemoved = (system: System<C>) => {\n\t\tthis.untrackSystem(system.name);\n\t};\n\n\t// The gap between `-worker-finished` (before events dispatch) and `-worker-events-finished` (after) is what\n\t// that run cost this thread. Both fire for the main-thread fallback too.\n\tprivate trackSystem(system: System<C>) {\n\t\tif(this.systemTimings.has(system.name)) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst timing: SystemTiming = {\n\t\t\trun: [],\n\t\t\tevents: [],\n\t\t\teventStart: -1,\n\t\t\tonRunFinished: (runTime: number) => {\n\t\t\t\ttiming.run.push(runTime);\n\t\t\t\ttiming.eventStart = performance.now();\n\t\t\t},\n\t\t\tonEventsFinished: () => {\n\t\t\t\tif(timing.eventStart < 0) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\ttiming.events.push(performance.now() - timing.eventStart);\n\t\t\t\ttiming.eventStart = -1;\n\t\t\t},\n\t\t};\n\n\t\tthis.world.on(`system-${system.name}-worker-finished`, timing.onRunFinished);\n\t\tthis.world.on(`system-${system.name}-worker-events-finished`, timing.onEventsFinished);\n\t\tthis.systemTimings.set(system.name, timing);\n\t}\n\n\tprivate untrackSystem(name: string) {\n\t\tconst timing = this.systemTimings.get(name);\n\t\tif(!timing) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.world.off(`system-${name}-worker-finished`, timing.onRunFinished);\n\t\tthis.world.off(`system-${name}-worker-events-finished`, timing.onEventsFinished);\n\t\tthis.systemTimings.delete(name);\n\t}\n\n\tprivate recalculate() {\n\t\tconst systems = this.world.systems.map(system => {\n\t\t\tconst timing = this.systemTimings.get(system.name);\n\t\t\treturn {\n\t\t\t\tname: system.name,\n\t\t\t\trun: summarize(timing?.run ?? []),\n\t\t\t\tevents: summarize(timing?.events ?? []),\n\t\t\t};\n\t\t});\n\n\t\tconst events: TimingStats = { ...EMPTY_TIMING };\n\t\tsystems.forEach(system => {\n\t\t\tevents.avg += system.events.avg;\n\t\t\tevents.min += system.events.min;\n\t\t\tevents.max += system.events.max;\n\t\t\tevents.samples += system.events.samples;\n\t\t});\n\n\t\tthis.stats = {\n\t\t\tupdate: summarize(this.updateTimes),\n\t\t\tsystems,\n\t\t\tevents,\n\t\t};\n\n\t\tthis.ticks = 0;\n\t\tthis.updateTimes = [];\n\t\tthis.systemTimings.forEach(timing => {\n\t\t\ttiming.run = [];\n\t\t\ttiming.events = [];\n\t\t});\n\n\t\tthis.emit('stats-updated', this.stats);\n\t}\n}\n","import type BaseWorld from '../world';\nimport type BaseEntity from '../entity';\nimport type { ComponentDefinitionMap, ComponentMap } from '../component-definition';\nimport type { SystemConfig } from './system';\nimport EntityWorkerSystem, {\n\ttype EntityWorkerSystemQuery, type EntityWorkerSystemWorld, type EntityUpdateComponents,\n} from './entity-worker-system';\nimport { toEntityUpdateFunction, type WorkerSystemRunFunction } from './workers/create-system-worker';\n\n// An EntityWorkerSystem that runs its update function once per tick instead of once per entity. It accepts the same\n// named `queries` (so it can count/scan other entities), runs on its own worker, can create entities off-thread, and\n// receives fresh per-run data via addDataToWorld — all reusing the EntityWorkerSystem machinery. It has no main query:\n// all work happens in the single run function over the named sub-queries.\nexport default class WorkerSystem<\n\tC extends ComponentMap,\n\tW extends EntityWorkerSystemWorld = EntityWorkerSystemWorld,\n\tD = unknown,\n> extends EntityWorkerSystem<C, EntityUpdateComponents<C>, W, D> {\n\tconstructor(world: BaseWorld<ComponentDefinitionMap, C>, options: WorkerSystemConfig<C, W, D>) {\n\t\tsuper(world, {\n\t\t\t...options,\n\t\t\t// No main query: the run function works entirely over the named sub-queries.\n\t\t\trequired: [],\n\t\t\tupdateFunction: toEntityUpdateFunction(options.updateFunction),\n\t\t});\n\t}\n\n\t// Never populate the main query — an empty `required` would otherwise match every entity. Sub-query membership\n\t// is maintained as usual so the run function still sees it.\n\tcheckAddEntity(entity: BaseEntity<C>): boolean {\n\t\tObject.entries(this.options.queries ?? {}).forEach(([queryName, query]) => {\n\t\t\tconst queryList = this.queryEntities[queryName] ?? (this.queryEntities[queryName] = new Map());\n\t\t\tthis.updateEntityList(queryName, queryList, entity, this.matchesQuery(entity, query));\n\t\t});\n\n\t\treturn false;\n\t}\n\n\t// Runs every interval regardless of membership, since its work is the single run function over sub-queries.\n\tshouldRun(): boolean {\n\t\treturn true;\n\t}\n}\n\nexport interface WorkerSystemConfig<\n\tC extends ComponentMap,\n\tW extends EntityWorkerSystemWorld = EntityWorkerSystemWorld,\n\tD = unknown,\n> extends SystemConfig {\n\tupdateFunction: WorkerSystemRunFunction<C, W, D>\n\tgetWorker: () => Worker\n\tforceMainThread?: boolean\n\tgetInitData?: () => D\n\tcreatesEntities?: boolean\n\tqueries?: { [key: string]: EntityWorkerSystemQuery<C> }\n}\n\nexport type { WorkerSystemRunFunction };\n"],"x_google_ignoreList":[0,1],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../node_modules/eventemitter3/index.js","../node_modules/eventemitter3/index.mjs","../src/systems/system.ts","../src/systems/iterable-system.ts","../src/systems/entity-system.ts","../src/systems/workers/web-worker.ts","../src/systems/workers/entity-system-web-worker.ts","../src/systems/entity-worker-system.ts","../src/entity.ts","../src/entity-factory.ts","../src/world.ts","../src/entity-class.ts","../src/actions/kill-entity.ts","../src/performance-timing.ts","../src/systems/worker-system.ts"],"sourcesContent":["'use strict';\n\nvar has = Object.prototype.hasOwnProperty\n , prefix = '~';\n\n/**\n * Constructor to create a storage for our `EE` objects.\n * An `Events` instance is a plain object whose properties are event names.\n *\n * @constructor\n * @private\n */\nfunction Events() {}\n\n//\n// We try to not inherit from `Object.prototype`. In some engines creating an\n// instance in this way is faster than calling `Object.create(null)` directly.\n// If `Object.create(null)` is not supported we prefix the event names with a\n// character to make sure that the built-in object properties are not\n// overridden or used as an attack vector.\n//\nif (Object.create) {\n Events.prototype = Object.create(null);\n\n //\n // This hack is needed because the `__proto__` property is still inherited in\n // some old browsers like Android 4, iPhone 5.1, Opera 11 and Safari 5.\n //\n if (!new Events().__proto__) prefix = false;\n}\n\n/**\n * Representation of a single event listener.\n *\n * @param {Function} fn The listener function.\n * @param {*} context The context to invoke the listener with.\n * @param {Boolean} [once=false] Specify if the listener is a one-time listener.\n * @constructor\n * @private\n */\nfunction EE(fn, context, once) {\n this.fn = fn;\n this.context = context;\n this.once = once || false;\n}\n\n/**\n * Add a listener for a given event.\n *\n * @param {EventEmitter} emitter Reference to the `EventEmitter` instance.\n * @param {(String|Symbol)} event The event name.\n * @param {Function} fn The listener function.\n * @param {*} context The context to invoke the listener with.\n * @param {Boolean} once Specify if the listener is a one-time listener.\n * @returns {EventEmitter}\n * @private\n */\nfunction addListener(emitter, event, fn, context, once) {\n if (typeof fn !== 'function') {\n throw new TypeError('The listener must be a function');\n }\n\n var listener = new EE(fn, context || emitter, once)\n , evt = prefix ? prefix + event : event;\n\n if (!emitter._events[evt]) emitter._events[evt] = listener, emitter._eventsCount++;\n else if (!emitter._events[evt].fn) emitter._events[evt].push(listener);\n else emitter._events[evt] = [emitter._events[evt], listener];\n\n return emitter;\n}\n\n/**\n * Clear event by name.\n *\n * @param {EventEmitter} emitter Reference to the `EventEmitter` instance.\n * @param {(String|Symbol)} evt The Event name.\n * @private\n */\nfunction clearEvent(emitter, evt) {\n if (--emitter._eventsCount === 0) emitter._events = new Events();\n else delete emitter._events[evt];\n}\n\n/**\n * Minimal `EventEmitter` interface that is molded against the Node.js\n * `EventEmitter` interface.\n *\n * @constructor\n * @public\n */\nfunction EventEmitter() {\n this._events = new Events();\n this._eventsCount = 0;\n}\n\n/**\n * Return an array listing the events for which the emitter has registered\n * listeners.\n *\n * @returns {Array}\n * @public\n */\nEventEmitter.prototype.eventNames = function eventNames() {\n var names = []\n , events\n , name;\n\n if (this._eventsCount === 0) return names;\n\n for (name in (events = this._events)) {\n if (has.call(events, name)) names.push(prefix ? name.slice(1) : name);\n }\n\n if (Object.getOwnPropertySymbols) {\n return names.concat(Object.getOwnPropertySymbols(events));\n }\n\n return names;\n};\n\n/**\n * Return the listeners registered for a given event.\n *\n * @param {(String|Symbol)} event The event name.\n * @returns {Array} The registered listeners.\n * @public\n */\nEventEmitter.prototype.listeners = function listeners(event) {\n var evt = prefix ? prefix + event : event\n , handlers = this._events[evt];\n\n if (!handlers) return [];\n if (handlers.fn) return [handlers.fn];\n\n for (var i = 0, l = handlers.length, ee = new Array(l); i < l; i++) {\n ee[i] = handlers[i].fn;\n }\n\n return ee;\n};\n\n/**\n * Return the number of listeners listening to a given event.\n *\n * @param {(String|Symbol)} event The event name.\n * @returns {Number} The number of listeners.\n * @public\n */\nEventEmitter.prototype.listenerCount = function listenerCount(event) {\n var evt = prefix ? prefix + event : event\n , listeners = this._events[evt];\n\n if (!listeners) return 0;\n if (listeners.fn) return 1;\n return listeners.length;\n};\n\n/**\n * Calls each of the listeners registered for a given event.\n *\n * @param {(String|Symbol)} event The event name.\n * @returns {Boolean} `true` if the event had listeners, else `false`.\n * @public\n */\nEventEmitter.prototype.emit = function emit(event, a1, a2, a3, a4, a5) {\n var evt = prefix ? prefix + event : event;\n\n if (!this._events[evt]) return false;\n\n var listeners = this._events[evt]\n , len = arguments.length\n , args\n , i;\n\n if (listeners.fn) {\n if (listeners.once) this.removeListener(event, listeners.fn, undefined, true);\n\n switch (len) {\n case 1: return listeners.fn.call(listeners.context), true;\n case 2: return listeners.fn.call(listeners.context, a1), true;\n case 3: return listeners.fn.call(listeners.context, a1, a2), true;\n case 4: return listeners.fn.call(listeners.context, a1, a2, a3), true;\n case 5: return listeners.fn.call(listeners.context, a1, a2, a3, a4), true;\n case 6: return listeners.fn.call(listeners.context, a1, a2, a3, a4, a5), true;\n }\n\n for (i = 1, args = new Array(len -1); i < len; i++) {\n args[i - 1] = arguments[i];\n }\n\n listeners.fn.apply(listeners.context, args);\n } else {\n var length = listeners.length\n , j;\n\n for (i = 0; i < length; i++) {\n if (listeners[i].once) this.removeListener(event, listeners[i].fn, undefined, true);\n\n switch (len) {\n case 1: listeners[i].fn.call(listeners[i].context); break;\n case 2: listeners[i].fn.call(listeners[i].context, a1); break;\n case 3: listeners[i].fn.call(listeners[i].context, a1, a2); break;\n case 4: listeners[i].fn.call(listeners[i].context, a1, a2, a3); break;\n default:\n if (!args) for (j = 1, args = new Array(len -1); j < len; j++) {\n args[j - 1] = arguments[j];\n }\n\n listeners[i].fn.apply(listeners[i].context, args);\n }\n }\n }\n\n return true;\n};\n\n/**\n * Add a listener for a given event.\n *\n * @param {(String|Symbol)} event The event name.\n * @param {Function} fn The listener function.\n * @param {*} [context=this] The context to invoke the listener with.\n * @returns {EventEmitter} `this`.\n * @public\n */\nEventEmitter.prototype.on = function on(event, fn, context) {\n return addListener(this, event, fn, context, false);\n};\n\n/**\n * Add a one-time listener for a given event.\n *\n * @param {(String|Symbol)} event The event name.\n * @param {Function} fn The listener function.\n * @param {*} [context=this] The context to invoke the listener with.\n * @returns {EventEmitter} `this`.\n * @public\n */\nEventEmitter.prototype.once = function once(event, fn, context) {\n return addListener(this, event, fn, context, true);\n};\n\n/**\n * Remove the listeners of a given event.\n *\n * @param {(String|Symbol)} event The event name.\n * @param {Function} fn Only remove the listeners that match this function.\n * @param {*} context Only remove the listeners that have this context.\n * @param {Boolean} once Only remove one-time listeners.\n * @returns {EventEmitter} `this`.\n * @public\n */\nEventEmitter.prototype.removeListener = function removeListener(event, fn, context, once) {\n var evt = prefix ? prefix + event : event;\n\n if (!this._events[evt]) return this;\n if (!fn) {\n clearEvent(this, evt);\n return this;\n }\n\n var listeners = this._events[evt];\n\n if (listeners.fn) {\n if (\n listeners.fn === fn &&\n (!once || listeners.once) &&\n (!context || listeners.context === context)\n ) {\n clearEvent(this, evt);\n }\n } else {\n for (var i = 0, events = [], length = listeners.length; i < length; i++) {\n if (\n listeners[i].fn !== fn ||\n (once && !listeners[i].once) ||\n (context && listeners[i].context !== context)\n ) {\n events.push(listeners[i]);\n }\n }\n\n //\n // Reset the array, or remove it completely if we have no more listeners.\n //\n if (events.length) this._events[evt] = events.length === 1 ? events[0] : events;\n else clearEvent(this, evt);\n }\n\n return this;\n};\n\n/**\n * Remove all listeners, or those of the specified event.\n *\n * @param {(String|Symbol)} [event] The event name.\n * @returns {EventEmitter} `this`.\n * @public\n */\nEventEmitter.prototype.removeAllListeners = function removeAllListeners(event) {\n var evt;\n\n if (event) {\n evt = prefix ? prefix + event : event;\n if (this._events[evt]) clearEvent(this, evt);\n } else {\n this._events = new Events();\n this._eventsCount = 0;\n }\n\n return this;\n};\n\n//\n// Alias methods names because people roll like that.\n//\nEventEmitter.prototype.off = EventEmitter.prototype.removeListener;\nEventEmitter.prototype.addListener = EventEmitter.prototype.on;\n\n//\n// Expose the prefix.\n//\nEventEmitter.prefixed = prefix;\n\n//\n// Allow `EventEmitter` to be imported as module namespace.\n//\nEventEmitter.EventEmitter = EventEmitter;\n\n//\n// Expose the module.\n//\nif ('undefined' !== typeof module) {\n module.exports = EventEmitter;\n}\n","import EventEmitter from './index.js'\n\nexport { EventEmitter }\nexport default EventEmitter\n","import { EventEmitter } from 'eventemitter3';\nimport type BaseWorld from '../world';\nimport type { ComponentDefinitionMap, ComponentMap } from '../component-definition';\n\n// Base system: runs on an optional fixed timestep (deltaBetweenRuns), driven by BaseWorld#update.\nexport default abstract class System<C extends ComponentMap = ComponentMap> extends EventEmitter {\n\tworld: BaseWorld<ComponentDefinitionMap, C>;\n\tname: string;\n\tcurrentDelta: number = 0;\n\tdeltaBetweenRuns: number;\n\tfirstRun: boolean;\n\n\tconstructor(world: BaseWorld<ComponentDefinitionMap, C>, options: SystemConfig = { name: 'System' }) {\n\t\tsuper();\n\n\t\tthis.name = options.name;\n\t\tthis.world = world;\n\n\t\tthis.deltaBetweenRuns = options.deltaBetweenRuns ?? 0;\n\t\tthis.firstRun = options.firstRun !== undefined ? options.firstRun : false;\n\t}\n\n\tinit(): void | Promise<void> {}\n\n\tclear() {\n\t\tthis.currentDelta = 0;\n\t}\n\t// Called once the world's entities all exist: the point a system hands its startup data off (see EntityWorkerSystem).\n\tfinishLoading(): void | Promise<void> {}\n\n\tupdate(elapsedTime: number): boolean {\n\t\tthis.currentDelta += elapsedTime;\n\n\t\tif(this.currentDelta >= this.deltaBetweenRuns || this.firstRun) {\n\t\t\tlet leftOverDelta = 0;\n\t\t\tif(this.deltaBetweenRuns > 0) {\n\t\t\t\t// Carry the remainder so a run that overshoots its timestep doesn't drift the next one later.\n\t\t\t\tleftOverDelta = this.currentDelta % this.deltaBetweenRuns;\n\t\t\t}\n\n\t\t\tthis.run(this.currentDelta - leftOverDelta);\n\t\t\tthis.currentDelta = leftOverDelta;\n\t\t\tthis.firstRun = false;\n\t\t\tthis.onRunFinished();\n\n\t\t\treturn true;\n\t\t} else {\n\t\t\treturn false;\n\t\t}\n\t}\n\tabstract run(elapsedTime: number): void;\n\n\t// Logs and surfaces an error thrown by user code (an update body, preRun, etc.) on the main thread: a\n\t// `system-error` event carrying the system name, so a run keeps going past one failure instead of aborting.\n\tprotected onError(error: Error, context: { entityId?: number, phase?: SystemErrorPhase } = {}) {\n\t\tconst where = context.entityId !== undefined ? ` (entity ${context.entityId})` : '';\n\t\tconsole.error(`Error in system ${this.name}${where}: ${error.message}`, error);\n\t\tconst payload: SystemError = { system: this.name, error, entityId: context.entityId, phase: context.phase };\n\t\tthis.world.emit('system-error', payload);\n\t}\n\n\t// Marks one run as fully applied. Synchronous systems finish inside update(); subclasses whose work is\n\t// deferred (spread across frames, or off-thread) override this and call it at their real completion point.\n\tprotected onRunFinished() {\n\t\tthis.world.notifySystemRunCompleted(this);\n\t}\n\t// True while a run is still in progress between update() calls (a worker round-trip, or an iteration spread\n\t// across frames). Used by the world to keep waiting on a system that is mid-run over memory it may free.\n\tisCurrentlyRunning(): boolean {\n\t\treturn false;\n\t}\n\t// Resolves once any in-flight run has finished, so the world's clear() knows nothing is still reading memory\n\twaitForRunToComplete(): void | Promise<void> {}\n\n\tshouldRun(): boolean {\n\t\treturn true;\n\t}\n\n\tdestroy() {\n\t\tthis.removeAllListeners();\n\t}\n}\n\nexport interface SystemConfig {\n\tname: string\n\tdeltaBetweenRuns?: number\n\tfirstRun?: boolean\n}\n\n// Which part of a run threw, for the `system-error` event.\nexport type SystemErrorPhase = 'queryChanged' | 'preRun' | 'update' | 'entityRemoved' | 'run' | 'died';\nexport interface SystemError {\n\tsystem: string\n\terror: Error\n\tentityId?: number\n\tphase?: SystemErrorPhase\n}\n","import type BaseWorld from '../world';\nimport type { ComponentDefinitionMap, ComponentMap } from '../component-definition';\nimport System, { type SystemConfig } from './system';\n\nexport default abstract class IterableSystem<C extends ComponentMap, T> extends System<C> {\n\tremainingInstancesToRun: Array<T> = [];\n\tremainingInstancesStartTime: number | null = null;\n\titerationsPerCheck: number;\n\tmaxMsPerFrame: number;\n\n\tconstructor(world: BaseWorld<ComponentDefinitionMap, C>, options: IterableSystemConfig) {\n\t\tsuper(world, options);\n\n\t\tthis.iterationsPerCheck = options.iterationsPerCheck ?? 1;\n\t\tthis.maxMsPerFrame = options.maxMsPerFrame ?? 10;\n\t}\n\n\tclear() {\n\t\tsuper.clear();\n\n\t\tthis.remainingInstancesToRun = [];\n\t\tthis.remainingInstancesStartTime = null;\n\t}\n\n\tupdate(elapsedTime: number): boolean {\n\t\tif(this.remainingInstancesToRun.length) {\n\t\t\tthis.runIterables(this.remainingInstancesToRun, this.remainingInstancesStartTime ?? 0);\n\t\t\tthis.currentDelta += elapsedTime;\n\t\t\tif(!this.remainingInstancesToRun.length) {\n\t\t\t\tthis.onRunFinished();\n\t\t\t}\n\n\t\t\treturn true;\n\t\t} else {\n\t\t\treturn super.update(elapsedTime);\n\t\t}\n\t}\n\trun(elapsedTime: number): void {\n\t\tlet iterables = this.getIterables();\n\t\tthis.runIterables(iterables, elapsedTime);\n\t}\n\t// A run that overflowed onto a later frame isn't finished yet; only count it once the queue drains (handled\n\t// by update() when it empties remainingInstancesToRun).\n\tprotected onRunFinished() {\n\t\tif(this.remainingInstancesToRun.length) {\n\t\t\treturn;\n\t\t}\n\n\t\tsuper.onRunFinished();\n\t}\n\tisCurrentlyRunning(): boolean {\n\t\treturn this.remainingInstancesToRun.length > 0;\n\t}\n\n\trunIterables(iterables: Array<T>, elapsedTime: number) {\n\t\tlet started = performance.now();\n\t\ttry {\n\t\t\tthis.beforeRunIterables();\n\t\t} catch(e) {\n\t\t\t// preRun failed: skip the iteration this frame rather than run over half-prepared state.\n\t\t\tthis.onError(e as Error, { phase: 'preRun' });\n\t\t\tthis.remainingInstancesToRun = [];\n\t\t\tthis.remainingInstancesStartTime = null;\n\t\t\treturn;\n\t\t}\n\t\tfor(let i = 0; i < iterables.length; i++) {\n\t\t\ttry {\n\t\t\t\tthis.updateIterable(iterables[i], elapsedTime);\n\t\t\t} catch(e) {\n\t\t\t\t// One iterable failing must not stop the rest of the run.\n\t\t\t\tthis.onError(e as Error, { phase: 'update', entityId: this.getIterableEntityId(iterables[i]) });\n\t\t\t}\n\n\t\t\tif(i % this.iterationsPerCheck === 0) {\n\t\t\t\tlet now = performance.now();\n\t\t\t\tif(now - started >= this.maxMsPerFrame) {\n\t\t\t\t\tthis.remainingInstancesToRun = iterables.slice(i + 1);\n\t\t\t\t\tthis.remainingInstancesStartTime = elapsedTime;\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tthis.remainingInstancesToRun = [];\n\t\tthis.remainingInstancesStartTime = null;\n\t}\n\tbeforeRunIterables() {}\n\t// Best-effort eid for a failed iterable, so `system-error` can name it. Subclasses whose T carries an eid override.\n\tprotected getIterableEntityId(_iterable: T): number | undefined {\n\t\treturn undefined;\n\t}\n\n\tabstract getIterables(): Array<T>;\n\tabstract updateIterable(iterable: T, elapsedTime: number): void;\n}\n\nexport interface IterableSystemConfig extends SystemConfig {\n\titerationsPerCheck?: number\n\tmaxMsPerFrame?: number\n}\n","import type BaseWorld from '../world';\nimport type BaseEntity from '../entity';\nimport type { ComponentDefinitionMap, ComponentMap } from '../component-definition';\nimport IterableSystem, { type IterableSystemConfig } from './iterable-system';\n\n// Iterates the entities owning a given set of components on the main thread; membership tracks world events.\nexport default abstract class EntitySystem<C extends ComponentMap, T extends BaseEntity<C> = BaseEntity<C>> extends IterableSystem<C, T> {\n\tentities: Map<number, T> = new Map();\n\toptions: EntitySystemConfig<C>;\n\n\tconstructor(world: BaseWorld<ComponentDefinitionMap, C>, options: EntitySystemConfig<C> = { name: 'EntitySystem' }) {\n\t\tif(!options.iterationsPerCheck) {\n\t\t\toptions.iterationsPerCheck = 10;\n\t\t}\n\t\tif(!options.maxMsPerFrame) {\n\t\t\toptions.maxMsPerFrame = 4;\n\t\t}\n\n\t\tsuper(world, options);\n\t\tthis.options = options;\n\n\t\tworld.on('entity-added', (entity: BaseEntity<C>) => {\n\t\t\tif(this.checkAddEntity(entity) && this.options.updateEntityOnAdd) {\n\t\t\t\tthis.updateEntity(entity as T, 0);\n\t\t\t}\n\t\t});\n\t\tworld.on('entity-removed', (entity: BaseEntity<C>) => {\n\t\t\tthis.removeEntity(entity);\n\t\t});\n\n\t\tworld.entities.forEach(entity => {\n\t\t\tthis.checkAddEntity(entity);\n\t\t});\n\t}\n\n\tgetIterables(): Array<T> {\n\t\tconst iterables: Array<T> = [];\n\t\tthis.entities.forEach(entity => {\n\t\t\tif(!entity.components.entity.dead) {\n\t\t\t\titerables.push(entity);\n\t\t\t}\n\t\t});\n\n\t\treturn iterables;\n\t}\n\tupdateIterable(entity: T, elapsedTime: number): void {\n\t\t// A multi-frame snapshot can outlive query membership. Revalidate the exact instance before touching it.\n\t\tif(entity.components.entity.dead || this.entities.get(entity.eid) !== entity) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.updateEntity(entity, elapsedTime);\n\t}\n\tfilterEntity(entity: BaseEntity<C>): boolean {\n\t\treturn !entity.components.entity.isStatic;\n\t}\n\tprotected getIterableEntityId(entity: T): number {\n\t\treturn entity.eid;\n\t}\n\tisEntityInSystem(entity: BaseEntity<C>) {\n\t\treturn this.entities.has(entity.eid);\n\t}\n\tabstract updateEntity(entity: T, elapsedTime: number): void;\n\n\tcheckAddEntity(entity: BaseEntity<C>): boolean {\n\t\tif(this.options.components && this.options.components.filter(component => !!entity.components[component]).length !== this.options.components.length) {\n\t\t\treturn false;\n\t\t}\n\n\t\tif(this.filterEntity(entity)) {\n\t\t\tthis.entities.set(entity.eid, entity as T);\n\t\t\treturn true;\n\t\t} else {\n\t\t\treturn false;\n\t\t}\n\t}\n\tremoveEntity(entity: BaseEntity<C>) {\n\t\tthis.entities.delete(entity.eid);\n\t}\n\n\tshouldRun(): boolean {\n\t\t// A continuation must drain even if every live member left since the previous frame.\n\t\treturn this.isCurrentlyRunning() || this.entities.size > 0;\n\t}\n}\n\nexport interface EntitySystemConfig<C extends ComponentMap> extends IterableSystemConfig {\n\tcomponents?: Array<keyof C>\n\tupdateEntityOnAdd?: boolean\n}\n","// Minimal Worker-like base for the main-thread fallback. Loose params: this mirrors the DOM Worker boundary.\nexport default abstract class WebWorker {\n\tabstract postMessage(message: any): void | Promise<void>;\n\tonmessage(message: any, transferrables: Array<any> = []): void {\n\n\t}\n}\n","import WebWorker from './web-worker';\nimport { applyQueryDelta } from './apply-query-delta';\nimport type EntitySystemWorkerMessage from './entity-system-worker-message';\nimport type { EntityEvent, SystemEvents, WorkerRunError } from './entity-system-worker-message';\nimport type BaseWorld from '../../world';\nimport type { ComponentDefinitionMap, ComponentMap, RegisteredComponentRegistry } from '../../component-definition';\nimport type {\n\tEntityWorkerSystemCallbacks, EntityWorkerSystemWorld, EntityQueryComponents, EntityUpdateComponents,\n\tEntityUpdateFunction, QueryDelta, UpdateEntityConfigObject, WorkerAllocator, WorkerComponentChange, WorkerCreatedEntity,\n} from '../entity-worker-system';\nimport { buildWorkerComponent, buildWorkerEntity, type WorkerCreateRegistry } from '../../actions/build-worker-entity';\n\n// Main-thread fallback that runs the update function synchronously, mirroring the real worker's behavior.\nexport default class EntitySystemWebWorker<C extends ComponentMap, T extends EntityUpdateComponents<C>, W extends EntityWorkerSystemWorld = EntityWorkerSystemWorld, D = unknown> extends WebWorker {\n\tprivate updateFunction: EntityUpdateFunction<C, T, W, D>;\n\tprivate entities: Array<UpdateEntityConfigObject<T>> = [];\n\tprivate queryEntities: { [key: string]: Array<UpdateEntityConfigObject<T>> } = {};\n\t// Mirrors createEntitySystemWorker: updateFunction.init's result, merged onto `world` each run.\n\tprivate worldExtension: Partial<W> | undefined;\n\t// Running on the main thread, this shares the world (its string cache, registry pools, eid counter) directly.\n\tprivate world: BaseWorld<ComponentDefinitionMap, C>;\n\tprivate allocator: WorkerAllocator;\n\tprivate createsEntities: boolean;\n\tprivate addsComponents: boolean;\n\n\tconstructor(\n\t\tupdateFunction: EntityUpdateFunction<C, T, W, D>,\n\t\tworld: BaseWorld<ComponentDefinitionMap, C>,\n\t\tcreatesEntities = false,\n\t\taddsComponents = false,\n\t) {\n\t\tsuper();\n\t\tthis.updateFunction = updateFunction;\n\t\tthis.world = world;\n\t\tthis.createsEntities = createsEntities;\n\t\tthis.addsComponents = addsComponents;\n\t\tconst registry = world.registry as RegisteredComponentRegistry<C>;\n\t\tthis.allocator = {\n\t\t\tallocateEid: () => world.allocateEid(),\n\t\t\tallocateComponentBlock: (name, values) => registry[name as keyof C].memoryComponent.create(values),\n\t\t};\n\t}\n\n\tpostMessage(message: EntitySystemWorkerMessage<W, D>): void {\n\t\tif(message.type === 'init') {\n\t\t\tthis.onMessageTyped({\n\t\t\t\ttype: 'init-complete',\n\t\t\t});\n\t\t} else if(message.type === 'load') {\n\t\t\tthis.worldExtension = this.updateFunction.init?.(message.data) ?? undefined;\n\t\t\tthis.onMessageTyped({\n\t\t\t\ttype: 'loaded',\n\t\t\t});\n\t\t} else if(message.type === 'reset') {\n\t\t\t// Drop the persistent lists so a reused world starts empty; worldExtension is refreshed by the next load.\n\t\t\tthis.entities = [];\n\t\t\tthis.queryEntities = {};\n\t\t} else if(message.type === 'run') {\n\t\t\tif(this.worldExtension) {\n\t\t\t\tObject.assign(message.world, this.worldExtension);\n\t\t\t}\n\t\t\tmessage.world.getString = (pointer: number) => this.world.constantStrings.getString(pointer) ?? '';\n\t\t\tmessage.world.heap = this.world.heap;\n\t\t\tmessage.world.allocate = this.allocator;\n\t\t\tif(this.createsEntities) {\n\t\t\t\tconst registry: WorkerCreateRegistry = this.world.registry;\n\t\t\t\tmessage.world.buildEntityDescriptor = config => buildWorkerEntity(\n\t\t\t\t\tconfig,\n\t\t\t\t\tthis.world.factory.configs,\n\t\t\t\t\tregistry,\n\t\t\t\t\tthis.allocator,\n\t\t\t\t\tthis.world.factory.getWorkerClasses(),\n\t\t\t\t);\n\t\t\t}\n\t\t\tif(this.addsComponents) {\n\t\t\t\tconst registry: WorkerCreateRegistry = this.world.registry;\n\t\t\t\tmessage.world.buildComponentDescriptor = (name, config) => buildWorkerComponent(name, config, registry, this.allocator);\n\t\t\t}\n\t\t\t// Timed like the real worker so a forceMainThread system reports a real run cost, not zero.\n\t\t\tconst start = performance.now();\n\t\t\tlet entityEvents: Array<EntityEvent> = [];\n\t\t\tlet systemEvents: SystemEvents = {};\n\t\t\tlet createdEntities: Array<WorkerCreatedEntity> = [];\n\t\t\tlet componentChanges: Array<WorkerComponentChange> = [];\n\t\t\tlet errors: Array<WorkerRunError> = [];\n\n\t\t\tthis.entities = applyQueryDelta(this.entities, message.entities as QueryDelta<T>);\n\n\t\t\tlet queries: EntityQueryComponents<C> = {};\n\t\t\tObject.entries(message.queries).forEach(([queryKey, delta]) => {\n\t\t\t\tconst list = applyQueryDelta(this.queryEntities[queryKey] ?? [], delta as QueryDelta<T>);\n\t\t\t\tthis.queryEntities[queryKey] = list;\n\t\t\t\tqueries[queryKey] = list;\n\t\t\t});\n\n\t\t\tlet callbacks: EntityWorkerSystemCallbacks<C> = {\n\t\t\t\tentityComponentChanged<K extends keyof C, P extends keyof C[K]>(entityId: number, componentName: K, prop: P, value: C[K][P]) {\n\t\t\t\t\tentityEvents.push({\n\t\t\t\t\t\tentityId,\n\t\t\t\t\t\tevent: 'component-property-updated',\n\t\t\t\t\t\targs: [componentName, prop, value],\n\t\t\t\t\t});\n\t\t\t\t},\n\t\t\t\temitEntityEvent(entityId: number, event: string, ...args: Array<unknown>) {\n\t\t\t\t\tentityEvents.push({\n\t\t\t\t\t\tentityId,\n\t\t\t\t\t\tevent,\n\t\t\t\t\t\targs,\n\t\t\t\t\t});\n\t\t\t\t},\n\t\t\t\temitSystemEvent(event: string, entityId: number) {\n\t\t\t\t\t(systemEvents[event] ?? (systemEvents[event] = [])).push(entityId);\n\t\t\t\t},\n\t\t\t\tentityDied(entityId: number) {\n\t\t\t\t\tentityEvents.push({\n\t\t\t\t\t\tentityId,\n\t\t\t\t\t\tevent: 'death',\n\t\t\t\t\t\targs: [],\n\t\t\t\t\t});\n\t\t\t\t},\n\t\t\t\tcreateEntity(entity: WorkerCreatedEntity) {\n\t\t\t\t\tcreatedEntities.push(entity);\n\t\t\t\t},\n\t\t\t\taddComponent(entityId, component) {\n\t\t\t\t\tcomponentChanges.push({ type: 'add', entityId, component });\n\t\t\t\t},\n\t\t\t\tremoveComponent(entityId, componentName) {\n\t\t\t\t\tcomponentChanges.push({ type: 'remove', entityId, componentName: String(componentName) });\n\t\t\t\t},\n\t\t\t};\n\t\t\tif(this.updateFunction.queryChanged) {\n\t\t\t\tfor(const [queryName, delta] of Object.entries(message.queries)) {\n\t\t\t\t\tif(!delta.added.length && !delta.removed.length) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\ttry {\n\t\t\t\t\t\tthis.updateFunction.queryChanged(message.world, queryName, delta, callbacks);\n\t\t\t\t\t} catch(e) {\n\t\t\t\t\t\terrors.push({ error: e as Error, phase: 'queryChanged' });\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tlet preRunFailed = false;\n\t\t\tif(this.updateFunction.preRun) {\n\t\t\t\ttry {\n\t\t\t\t\tthis.updateFunction.preRun(message.world, this.entities, queries, callbacks);\n\t\t\t\t} catch(e) {\n\t\t\t\t\tpreRunFailed = true;\n\t\t\t\t\terrors.push({ error: e as Error, phase: 'preRun' });\n\t\t\t\t}\n\t\t\t}\n\t\t\t// preRun sets up the run's state; if it threw, skip the entity loop rather than run over half-prepared data.\n\t\t\tif(!preRunFailed) {\n\t\t\t\tthis.entities.forEach(entity => {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tthis.updateFunction(message.world, entity.entityId, entity.components, queries, callbacks);\n\t\t\t\t\t} catch(e) {\n\t\t\t\t\t\t// One entity failing must not stop the rest of the run.\n\t\t\t\t\t\terrors.push({ error: e as Error, phase: 'update', entityId: entity.entityId });\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tif(this.updateFunction.entityRemoved) {\n\t\t\t\tfor(let entityId of message.entities.removed) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tthis.updateFunction.entityRemoved(message.world, entityId, callbacks);\n\t\t\t\t\t} catch(e) {\n\t\t\t\t\t\terrors.push({ error: e as Error, phase: 'entityRemoved', entityId });\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst runTime = performance.now() - start;\n\n\t\t\tthis.onMessageTyped({\n\t\t\t\ttype: 'run-complete',\n\t\t\t\tgeneration: message.generation,\n\t\t\t\trunTime,\n\t\t\t\tevents: entityEvents,\n\t\t\t\tsystemEvents,\n\t\t\t\tcreated: createdEntities,\n\t\t\t\tcomponentChanges,\n\t\t\t\terrors,\n\t\t\t});\n\t\t}\n\t}\n\n\tonMessageTyped(message: EntitySystemWorkerMessage<W, D>) {\n\t\tthis.onmessage({\n\t\t\tdata: message,\n\t\t});\n\t}\n}\n","import type MemoryHeap from '@daneren2005/shared-memory-objects/memory-heap';\nimport type { GrowBufferData } from '@daneren2005/shared-memory-objects/memory-heap';\nimport type BaseWorld from '../world';\nimport type BaseEntity from '../entity';\nimport type { BaseComponent, ComponentDefinitionMap, ComponentMap } from '../component-definition';\nimport type { ComponentTypedArray } from '../memory-component';\nimport System, { type SystemConfig } from './system';\nimport type EntitySystemWorkerMessage from './workers/entity-system-worker-message';\nimport EntitySystemWebWorker from './workers/entity-system-web-worker';\n\nconst MAIN_QUERY_NAME = '___main';\n\n// Runs an update function over the raw shared-memory blocks of its matched entities. Uses getWorker() when\n// Web Workers + SharedArrayBuffer exist, else falls back to EntitySystemWebWorker on the main thread. No game\n// concepts; games inject per-run data via addDataToWorld.\nexport default abstract class EntityWorkerSystem<\n\tC extends ComponentMap,\n\tT extends EntityUpdateComponents<C>,\n\tW extends EntityWorkerSystemWorld = EntityWorkerSystemWorld,\n\tD = unknown,\n> extends System<C> {\n\tentities: Map<number, BaseEntity<C>> = new Map();\n\toptions: EntityWorkerSystemConfig<C, T, W, D>;\n\n\tworker: Worker | EntitySystemWebWorker<C, T, W, D>;\n\tisWorkerThread: boolean;\n\n\tprivate initialized = false;\n\tprivate initPromise: Resolvable | null = null;\n\tprivate loadingPromise: Resolvable | null = null;\n\tprivate runCompletePromise: Resolvable | null = null;\n\tprivate isRunning = false;\n\t// Bumped by clear(); checked on each event to make certain we are dealing with the correct world\n\tprivate generation = 0;\n\tprotected queryEntities: { [key: string]: Map<number, BaseEntity<C>> } = {};\n\t// Membership changes since the last run(), flushed each run as a delta so a steady-state run sends empty\n\t// arrays rather than re-transmitting every eid. The worker applies these to its own list (see applyQueryDelta).\n\tprivate queryDeltas: { [key: string]: MembershipDelta<C> } = {};\n\n\taddDataToWorld?(world: W): void;\n\n\tconstructor(world: BaseWorld<ComponentDefinitionMap, C>, options: EntityWorkerSystemConfig<C, T, W, D>) {\n\t\tsuper(world, options);\n\t\tthis.options = options;\n\t\tObject.keys(this.options.queries ?? {}).forEach(queryName => {\n\t\t\tthis.queryEntities[queryName] = new Map();\n\t\t});\n\n\t\tworld.on('entity-added', (entity: BaseEntity<C>) => {\n\t\t\tthis.checkAddEntity(entity);\n\t\t});\n\t\tworld.on('entity-removed', (entity: BaseEntity<C>) => {\n\t\t\tthis.removeEntity(entity);\n\t\t});\n\n\t\tworld.entities.forEach(entity => {\n\t\t\tthis.checkAddEntity(entity);\n\t\t});\n\n\t\tif(!options.forceMainThread && typeof globalThis.Worker !== 'undefined' && typeof globalThis.SharedArrayBuffer !== 'undefined') {\n\t\t\tthis.worker = options.getWorker();\n\t\t\tthis.isWorkerThread = true;\n\t\t\t// Forward heap growth so the worker's reconstructed heap can resolve pointers into new buffers.\n\t\t\tworld.on('grow-buffer', (buffer: GrowBufferData) => {\n\t\t\t\tthis.worker.postMessage({ type: 'grow-buffer', buffer });\n\t\t\t});\n\t\t} else {\n\t\t\tthis.worker = new EntitySystemWebWorker(options.updateFunction, world, !!options.createsEntities, !!options.addsComponents);\n\t\t\tthis.isWorkerThread = false;\n\t\t}\n\n\t\tthis.initWorker();\n\t}\n\n\tprivate initWorker() {\n\t\tthis.worker.onmessage = (e: MessageEvent) => {\n\t\t\tlet message = e.data as EntitySystemWorkerMessage;\n\t\t\tif(message.type === 'init-complete') {\n\t\t\t\tthis.initialized = true;\n\t\t\t\tif(this.initPromise) {\n\t\t\t\t\tthis.initPromise.resolve();\n\t\t\t\t\tthis.initPromise = null;\n\t\t\t\t}\n\t\t\t} else if(message.type === 'loaded') {\n\t\t\t\tif(this.loadingPromise) {\n\t\t\t\t\tthis.loadingPromise.resolve();\n\t\t\t\t\tthis.loadingPromise = null;\n\t\t\t\t}\n\t\t\t} else if(message.type === 'grow-buffer-from-worker') {\n\t\t\t\t// A buffer this worker grew while allocating: adopt into the main heap and fan out to sibling workers.\n\t\t\t\tthis.world.addGrownBuffer(message.buffer);\n\t\t\t} else if(message.type === 'run-complete') {\n\t\t\t\t// A reply from a run that started before a clear(): the world it ran over is gone, so drop it whole.\n\t\t\t\tif(message.generation !== this.generation) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tthis.isRunning = false;\n\t\t\t\tthis.world.emit(`system-${this.name}-worker-finished`, message.runTime);\n\n\t\t\t\t// User-code errors caught inside the run: log + emit on the main thread, one per failure.\n\t\t\t\tmessage.errors.forEach(({ error, entityId, phase }) => {\n\t\t\t\t\tthis.onError(error, { entityId, phase });\n\t\t\t\t});\n\n\t\t\t\t// Structural changes are applied only after the worker has finished iterating its snapshot. Attaching emits\n\t\t\t\t// the same entity events as a main-thread mutation, which rechecks every affected system/query and queues\n\t\t\t\t// refreshed component bundles for their next run.\n\t\t\t\t(message.componentChanges ?? []).forEach(change => {\n\t\t\t\t\tconst entity = this.world.getEntityByEid(change.entityId);\n\t\t\t\t\tif(change.type === 'add') {\n\t\t\t\t\t\tconst definition = this.world.registry[change.component.name as keyof C];\n\t\t\t\t\t\tif(!entity || !definition || change.component.name === 'entity') {\n\t\t\t\t\t\t\tdefinition?.memoryComponent.delete(change.component.index);\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tconst componentName = change.component.name as keyof C;\n\t\t\t\t\t\tentity.removeComponent(componentName);\n\t\t\t\t\t\tentity.attachComponent(componentName, change.component.index, true);\n\t\t\t\t\t} else if(entity && change.componentName !== 'entity') {\n\t\t\t\t\t\tentity.removeComponent(change.componentName);\n\t\t\t\t\t}\n\t\t\t\t});\n\n\t\t\t\t// Before the per-entity events: an entity killed this run is still in the world here, since `death`\n\t\t\t\t// is dispatched below and removes it.\n\t\t\t\tfor(const event of Object.keys(message.systemEvents)) {\n\t\t\t\t\tthis.emit(event, message.systemEvents[event]);\n\t\t\t\t}\n\n\t\t\t\tmessage.events.forEach(event => {\n\t\t\t\t\t// Look up on the world, not the query cache, so events for sub-query-only entities still route.\n\t\t\t\t\tconst entity = this.world.getEntityByEid(event.entityId);\n\t\t\t\t\tif(!entity) {\n\t\t\t\t\t\tconsole.warn(`${this.name}-event ${event.event}: Could not find entity with id ${event.entityId}`);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tentity.emit(event.event, ...event.args);\n\t\t\t\t});\n\n\t\t\t\t// After deaths, so an entity created this run isn't immediately removed. Adopts the blocks the worker\n\t\t\t\t// already allocated + wrote, rather than re-creating them.\n\t\t\t\tmessage.created.forEach(descriptor => {\n\t\t\t\t\tthis.world.adoptEntity(descriptor);\n\t\t\t\t});\n\n\t\t\t\tthis.world.emit(`system-${this.name}-worker-events-finished`, message.runTime);\n\t\t\t\tthis.world.notifySystemRunCompleted(this);\n\n\t\t\t\tif(this.runCompletePromise) {\n\t\t\t\t\tthis.runCompletePromise.resolve();\n\t\t\t\t\tthis.runCompletePromise = null;\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\n\t\tconst message: EntitySystemWorkerMessage<W, D> = {\n\t\t\ttype: 'init',\n\t\t};\n\n\t\tthis.worker.postMessage(message);\n\t}\n\n\tinit(): Promise<void> | void {\n\t\tif(this.initialized) {\n\t\t\treturn;\n\t\t} else if(this.initPromise) {\n\t\t\treturn this.initPromise.promise;\n\t\t}\n\n\t\tlet { promise, resolve } = Promise.withResolvers<void>();\n\t\tthis.initPromise = {\n\t\t\tpromise,\n\t\t\tresolve,\n\t\t};\n\t\treturn promise;\n\t}\n\n\t// Sends the init data over and runs the update function's own init in the worker\n\tfinishLoading(): Promise<void> {\n\t\tlet { promise, resolve } = Promise.withResolvers<void>();\n\t\t// Assigned before posting: the main-thread fallback replies synchronously from inside postMessage.\n\t\tthis.loadingPromise = {\n\t\t\tpromise,\n\t\t\tresolve,\n\t\t};\n\n\t\tconst message: EntitySystemWorkerMessage<W, D> = {\n\t\t\ttype: 'load',\n\t\t\tdata: this.options.getInitData?.(),\n\t\t\t// Only a real worker needs the buffers to rebuild a heap, plus the pools + eid counter to allocate off-thread.\n\t\t\theap: this.isWorkerThread ? this.world.heap.getSharedMemory() : undefined,\n\t\t\tsharedMemory: this.isWorkerThread ? this.world.getSharedComponentMemory() : undefined,\n\t\t\t// Factory templates only go to workers that create entities.\n\t\t\tfactoryConfigs: this.isWorkerThread && this.options.createsEntities ? this.world.factory.configs : undefined,\n\t\t\tfactoryClasses: this.isWorkerThread && this.options.createsEntities ? this.world.factory.getWorkerClasses() : undefined,\n\t\t\taddsComponents: !!this.options.addsComponents,\n\t\t};\n\t\tthis.worker.postMessage(message);\n\n\t\treturn promise;\n\t}\n\n\t// Un-initializes the system so its world can be reused\n\tclear() {\n\t\tsuper.clear();\n\n\t\tif(this.isRunning) {\n\t\t\tif(!this.runCompletePromise) {\n\t\t\t\tconst { promise, resolve } = Promise.withResolvers<void>();\n\t\t\t\tthis.runCompletePromise = { promise, resolve };\n\t\t\t}\n\t\t}\n\t\tthis.isRunning = false;\n\t\tthis.generation++;\n\n\t\tthis.entities.clear();\n\t\tObject.values(this.queryEntities).forEach(list => list.clear());\n\t\tthis.queryDeltas = {};\n\n\t\tconst message: EntitySystemWorkerMessage = { type: 'reset' };\n\t\tthis.worker.postMessage(message);\n\t}\n\n\tupdate(elapsedTime: number): boolean {\n\t\tif(this.isRunning) {\n\t\t\tthis.currentDelta += elapsedTime;\n\n\t\t\treturn false;\n\t\t} else {\n\t\t\treturn super.update(elapsedTime);\n\t\t}\n\t}\n\t// A run finishes off-thread, not when update() returns; completedRuns is bumped on the worker's run-complete.\n\tprotected onRunFinished() {}\n\tisCurrentlyRunning(): boolean {\n\t\treturn this.isRunning;\n\t}\n\twaitForRunToComplete(): void | Promise<void> {\n\t\tif(!this.isRunning) {\n\t\t\treturn;\n\t\t}\n\t\tif(!this.runCompletePromise) {\n\t\t\tconst { promise, resolve } = Promise.withResolvers<void>();\n\t\t\tthis.runCompletePromise = { promise, resolve };\n\t\t}\n\t\treturn this.runCompletePromise.promise;\n\t}\n\trun(elapsedTime: number): void {\n\t\tconst world = {\n\t\t\tgameTime: this.world.gameTime,\n\t\t\telapsedTime,\n\t\t} as W;\n\t\tthis.addDataToWorld?.(world);\n\n\t\tthis.isRunning = true;\n\t\tlet entities = this.buildQueryDelta(MAIN_QUERY_NAME, this.options);\n\t\tlet queries: { [key: string]: QueryDelta<T> } = {};\n\t\tObject.entries(this.options.queries ?? {}).forEach(([queryKey, query]) => {\n\t\t\tqueries[queryKey] = this.buildQueryDelta(queryKey, query);\n\t\t});\n\t\tlet message: EntitySystemWorkerMessage<W> = {\n\t\t\ttype: 'run',\n\t\t\tgeneration: this.generation,\n\t\t\tworld,\n\t\t\tentities,\n\t\t\tqueries,\n\t\t};\n\t\tthis.worker.postMessage(message);\n\t}\n\n\tprivate buildQueryDelta(queryName: string, query: EntityWorkerSystemQuery<C>): QueryDelta<T> {\n\t\tconst delta = this.getQueryDelta(queryName);\n\t\tconst added: Array<UpdateEntityConfigObject<T>> = [];\n\t\tdelta.added.forEach(entity => {\n\t\t\tadded.push({\n\t\t\t\tentityId: entity.eid,\n\t\t\t\tcomponents: this.buildComponents(entity, query),\n\t\t\t});\n\t\t});\n\t\tconst removed = Array.from(delta.removed);\n\t\tthis.queryDeltas[queryName] = { added: new Set(), removed: new Set() };\n\n\t\treturn { added, removed };\n\t}\n\tprivate buildComponents(entity: BaseEntity<C>, query: EntityWorkerSystemQuery<C>): T {\n\t\tconst components = {} as T;\n\t\t[\n\t\t\t...query.required,\n\t\t\t...query.optional ?? [],\n\t\t].forEach(componentName => {\n\t\t\t// Reuse the view cached on the accessor at attach: getBlock allocates a fresh subarray every call and an\n\t\t\t// entity joins many systems, so re-looking it up here per system was a measurable spawn-time cost.\n\t\t\tconst block = entity.components[componentName]?.block;\n\t\t\tif(block) {\n\t\t\t\tcomponents[componentName] = block as T[typeof componentName];\n\t\t\t}\n\t\t});\n\n\t\treturn components;\n\t}\n\n\tisEntityInSystem(entity: BaseEntity<C>) {\n\t\treturn this.entities.has(entity.eid);\n\t}\n\tprotected matchesQuery(entity: BaseEntity<C>, query: EntityWorkerSystemQuery<C>): boolean {\n\t\tif(entity.components.entity.dead) {\n\t\t\treturn false;\n\t\t}\n\n\t\tif(query.required.find(component => !entity.components[component])) {\n\t\t\treturn false;\n\t\t}\n\t\tif(query.not?.find(component => !!entity.components[component])) {\n\t\t\treturn false;\n\t\t}\n\t\tif(query.filter && !query.filter(entity)) {\n\t\t\treturn false;\n\t\t}\n\n\t\treturn true;\n\t}\n\tprivate getQueryDelta(queryName: string): MembershipDelta<C> {\n\t\tlet delta = this.queryDeltas[queryName];\n\t\tif(!delta) {\n\t\t\tdelta = this.queryDeltas[queryName] = { added: new Set(), removed: new Set() };\n\t\t}\n\n\t\treturn delta;\n\t}\n\t// A pending removal this same frame is cancelled, so the net effect is a re-send rather than remove+add churn.\n\tprivate markAdded(delta: MembershipDelta<C>, entity: BaseEntity<C>) {\n\t\tdelta.removed.delete(entity.eid);\n\t\tdelta.added.add(entity);\n\t}\n\tprivate markRemoved(delta: MembershipDelta<C>, entity: BaseEntity<C>) {\n\t\tif(delta.added.delete(entity)) {\n\t\t\treturn;\n\t\t}\n\n\t\tdelta.removed.add(entity.eid);\n\t}\n\tprotected updateEntityList(queryName: string, list: Map<number, BaseEntity<C>>, entity: BaseEntity<C>, shouldInclude: boolean) {\n\t\tconst delta = this.getQueryDelta(queryName);\n\t\tif(shouldInclude) {\n\t\t\tlist.set(entity.eid, entity);\n\t\t\tthis.markAdded(delta, entity);\n\t\t} else if(list.delete(entity.eid)) {\n\t\t\tthis.markRemoved(delta, entity);\n\t\t}\n\t}\n\n\tcheckAddEntity(entity: BaseEntity<C>): boolean {\n\t\tconst shouldAddToMain = this.matchesQuery(entity, this.options);\n\t\tthis.updateEntityList(MAIN_QUERY_NAME, this.entities, entity, shouldAddToMain);\n\n\t\tObject.entries(this.options.queries ?? {}).forEach(([queryName, query]) => {\n\t\t\tconst queryList = this.queryEntities[queryName] ?? (this.queryEntities[queryName] = new Map());\n\t\t\tthis.updateEntityList(queryName, queryList, entity, this.matchesQuery(entity, query));\n\t\t});\n\n\t\treturn shouldAddToMain;\n\t}\n\tremoveEntity(entity: BaseEntity<C>) {\n\t\tthis.updateEntityList(MAIN_QUERY_NAME, this.entities, entity, false);\n\t\tObject.entries(this.queryEntities).forEach(([queryName, list]) => {\n\t\t\tthis.updateEntityList(queryName, list, entity, false);\n\t\t});\n\t}\n\n\t// Re-evaluates every entity's membership against the current queries. Needed when a `filter` closes over mutable\n\t// state (e.g. a scope keyed on which group is active) and that state changes with no entity event to react to\n\trecheckMembership() {\n\t\tthis.world.entities.forEach(entity => {\n\t\t\tthis.checkAddEntity(entity);\n\t\t});\n\t}\n\n\tshouldRun(): boolean {\n\t\treturn this.entities.size > 0;\n\t}\n\n\tdestroy() {\n\t\tsuper.destroy();\n\n\t\tif('terminate' in this.worker) {\n\t\t\tthis.worker.terminate();\n\t\t}\n\t}\n}\n\ninterface Resolvable {\n\tpromise: Promise<void>\n\tresolve: (value: void | PromiseLike<void>) => void\n}\n\nexport type EntityUpdateComponents<C extends ComponentMap = ComponentMap> = { [K in keyof C]?: ComponentTypedArray };\nexport type EntityQueryComponents<C extends ComponentMap = ComponentMap> = { [key: string]: Array<{ entityId: number, components: EntityUpdateComponents<C> }> };\ntype EntityUpdateFunctionImpl<C extends ComponentMap, T extends EntityUpdateComponents<C>, W extends EntityWorkerSystemWorld = EntityWorkerSystemWorld> = (\n\tworld: W,\n\tentityId: number,\n\tcomponents: T,\n\tqueries: EntityQueryComponents<C>,\n\tcallbacks: EntityWorkerSystemCallbacks<C>,\n) => void;\nexport type EntityUpdateFunction<\n\tC extends ComponentMap,\n\tT extends EntityUpdateComponents<C>,\n\tW extends EntityWorkerSystemWorld = EntityWorkerSystemWorld,\n\tD = unknown,\n> = EntityUpdateFunctionImpl<C, T, W> & {\n\tqueryChanged?: EntityQueryChangedFunction<C, W>\n\tpreRun?: EntityUpdatePreRunFunction<C, T, W>\n\tentityRemoved?: EntityRemovedFunction<C, W>\n\tinit?: EntityUpdateInitFunction<W, D>\n};\nexport type EntityUpdateInitFunction<W extends EntityWorkerSystemWorld = EntityWorkerSystemWorld, D = unknown> = (data: D | undefined) => Partial<W> | void;\nexport type EntityUpdatePreRunFunction<C extends ComponentMap, T extends EntityUpdateComponents<C>, W extends EntityWorkerSystemWorld = EntityWorkerSystemWorld> = (\n\tworld: W,\n\tentities: Array<UpdateEntityConfigObject<T>>,\n\tqueries: EntityQueryComponents<C>,\n\tcallbacks: EntityWorkerSystemCallbacks<C>,\n) => void;\n// Called once per sub-query whose membership changed this run, before preRun. `added` can repeat an entity already\n// in the query (its component bundle was refreshed), so treat it as an upsert.\nexport type EntityQueryChangedFunction<C extends ComponentMap = ComponentMap, W extends EntityWorkerSystemWorld = EntityWorkerSystemWorld> = (\n\tworld: W,\n\tqueryName: string,\n\tdelta: QueryDelta<EntityUpdateComponents<C>>,\n\tcallbacks: EntityWorkerSystemCallbacks<C>,\n) => void;\nexport type EntityRemovedFunction<C extends ComponentMap = ComponentMap, W extends EntityWorkerSystemWorld = EntityWorkerSystemWorld> = (\n\tworld: W,\n\tentityId: number,\n\tcallbacks: EntityWorkerSystemCallbacks<C>,\n) => void;\nexport type UpdateEntityConfig<T extends EntityUpdateComponents = EntityUpdateComponents> = number | UpdateEntityConfigObject<T>;\nexport type UpdateEntityConfigObject<T extends EntityUpdateComponents> = {\n\tentityId: number\n\tcomponents: T\n};\n\nexport interface QueryDelta<T extends EntityUpdateComponents = EntityUpdateComponents> {\n\tadded: Array<UpdateEntityConfigObject<T>>\n\tremoved: Array<number>\n}\n// Sets so queuing can check for an already-queued or opposite change without scanning a growing array.\ninterface MembershipDelta<C extends ComponentMap> {\n\tadded: Set<BaseEntity<C>>\n\tremoved: Set<number>\n}\n\n// Low-level off-thread allocation primitives, injected onto the worker `world` each run. `allocateEid` mints a\n// heap-unique id; `allocateComponentBlock` pushes a block into a component's shared pool and returns its index.\n// These are the foundation a future worker-side createEntity builds on (allocate + write blocks, then report the\n// eid/indexes back for the main thread to adopt).\nexport interface WorkerAllocator {\n\tallocateEid(): number\n\tallocateComponentBlock(name: string, values: Array<number>): number\n}\n\nexport interface EntityWorkerSystemWorld {\n\tgameTime: number\n\telapsedTime: number\n\tgetString(pointer: number): string\n\t// The reconstructed heap (real worker) or the shared main-thread heap (fallback), injected each run so an\n\t// update function can rebuild heap-backed structures (a SharedMap/SharedList) from a pointer in a component\n\t// block. Undefined only before the first run.\n\theap?: MemoryHeap\n\tallocate?: WorkerAllocator\n\t// Injected each run on a system registered with createsEntities: builds a WorkerCreatedEntity descriptor from a\n\t// factory config (merges the type's template, allocates + writes each component's block). Drives createEntityWorker.\n\tbuildEntityDescriptor?(config: WorkerCreateEntityConfig): WorkerCreatedEntity\n\t// Injected for systems with addsComponents. Allocates/writes a block off-thread; the main thread attaches it\n\t// after run completion so no running update observes a changing component set.\n\tbuildComponentDescriptor?(name: string, config: Record<string, unknown>): WorkerCreatedComponent\n}\n// What a game passes to createEntityWorker: a factory-style config - the entity `type` plus any overrides layered\n// over that type's factory template. The worker merges template + overrides, then allocates + writes each triggered\n// component's block off-thread via the component's toBlock(config). The \"entity\" component is built on the main\n// thread when the descriptor is adopted, since interning the type is main-thread-only.\nexport type WorkerCreateEntityConfig = { type: string, class?: never } & { [key: string]: unknown };\n// The result reported back on run-complete: the minted id plus, per game component, the pool index the worker\n// allocated. world.adoptEntity turns this into a real BaseEntity.\nexport interface WorkerCreatedEntity {\n\teid: number\n\ttype: string\n\tclass?: string\n\tisStatic?: boolean\n\tcomponents: { [name: string]: number }\n}\n\nexport interface WorkerCreatedComponent {\n\tname: string\n\tindex: number\n}\n\nexport type WorkerComponentChange =\n\t| { type: 'add', entityId: number, component: WorkerCreatedComponent }\n\t| { type: 'remove', entityId: number, componentName: string };\n\nexport interface EntityWorkerSystemCallbacks<C extends ComponentMap = ComponentMap> {\n\tentityComponentChanged<K extends keyof C, P extends keyof C[K]>(entityId: number, componentName: K, prop: P, value: C[K][P]): void\n\t// Args are structured-cloned, so plain values only.\n\temitEntityEvent(entityId: number, event: string, ...args: Array<unknown>): void\n\t// Emitted **on the system** with all its ids in one array. The allocation-free path for something that\n\t// happens to most entities every run; carries no args (values are already in shared memory).\n\temitSystemEvent(event: string, entityId: number): void\n\tentityDied(entityId: number): void\n\tcreateEntity(entity: WorkerCreatedEntity): void\n\taddComponent(entityId: number, component: WorkerCreatedComponent): void\n\tremoveComponent<K extends keyof C>(entityId: number, componentName: K): void\n}\n\nexport interface EntityWorkerSystemQuery<C extends ComponentMap = ComponentMap> {\n\trequired: Array<keyof C>\n\toptional?: Array<keyof C>\n\tnot?: Array<keyof C>\n\tfilter?: (entity: BaseEntity<C>) => boolean\n}\n\nexport interface EntityWorkerSystemConfig<\n\tC extends ComponentMap,\n\tT extends EntityUpdateComponents<C>,\n\tW extends EntityWorkerSystemWorld = EntityWorkerSystemWorld,\n\tD = unknown,\n> extends SystemConfig, EntityWorkerSystemQuery<C> {\n\tupdateFunction: EntityUpdateFunction<C, T, W, D>\n\tgetWorker: () => Worker\n\tforceMainThread?: boolean\n\tgetInitData?: () => D\n\t// Opt in to worker-side entity creation (createEntityWorker). When set, factory templates and serializable class\n\t// allowlists are shipped to this system's worker; the worker entry must also pass the component registry to\n\t// createEntitySystemWorker so it has each component's toBlock(). Only systems that create entities need either.\n\tcreatesEntities?: boolean\n\t// Opt in to worker-side component allocation through addComponentWorker. The worker entry must also pass the\n\t// component registry to createEntitySystemWorker so the worker has each component's toBlock().\n\taddsComponents?: boolean\n\n\tqueries?: { [key: string]: EntityWorkerSystemQuery<C> }\n}\n\nexport type { BaseComponent };\n","import { EventEmitter } from 'eventemitter3';\nimport type BaseWorld from './world';\nimport type { BaseComponent, ComponentDefinitionMap, ComponentMap, RegisteredComponentRegistry } from './component-definition';\nimport type { EntityComponent } from './entity-component';\n\nexport default class BaseEntity<C extends ComponentMap = ComponentMap, Cfg = any> extends EventEmitter {\n\treadonly eid: number;\n\tconfig?: Cfg;\n\n\tworld: BaseWorld<ComponentDefinitionMap, C, Cfg>;\n\tprivate componentMemoryDeletionScheduled = false;\n\tprivate allowedComponents?: ReadonlySet<string>;\n\t// entity is always present; game components are partial.\n\tcomponents: Partial<C> & { entity: EntityComponent } = {} as Partial<C> & { entity: EntityComponent };\n\n\t// `adoptEid`: build an empty shell around a pre-minted id (an entity a worker created off-thread), skipping the\n\t// automatic entity-component load - the caller (world.adoptEntity) loads the entity component and attaches the\n\t// worker-allocated blocks itself.\n\tconstructor(\n\t\tworld: BaseWorld<ComponentDefinitionMap, C, Cfg>,\n\t\tconfig?: Cfg,\n\t\tadoptEid?: number,\n\t\tallowedComponents?: ReadonlySet<string>,\n\t) {\n\t\tsuper();\n\n\t\tthis.world = world;\n\t\tthis.eid = adoptEid ?? world.allocateEid();\n\t\tthis.allowedComponents = allowedComponents ?? world.factory.getAllowedComponentsForConfig(config);\n\t\tif(adoptEid !== undefined) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.loadComponent('entity', config ?? {}, false);\n\t\tif(config) {\n\t\t\tthis.load(config);\n\t\t}\n\t}\n\tget id(): number {\n\t\treturn this.eid;\n\t}\n\tget dead(): boolean {\n\t\treturn this.components.entity.dead;\n\t}\n\tget type(): string {\n\t\treturn this.components.entity.type;\n\t}\n\n\tloadComponent<K extends keyof C>(name: K, config: any, emitAdded = true): C[K] {\n\t\tthis.assertComponentAllowed(name);\n\t\tconst definition = (this.world.registry as RegisteredComponentRegistry<C>)[name];\n\t\tconst memoryComponent = definition.memoryComponent;\n\t\tconst index = memoryComponent.create(definition.toBlock(config, this));\n\t\tconst component = definition.attach(this, memoryComponent, index, config);\n\t\t// A Component subclass already holds its block; only fetch one for a plain-object accessor that didn't.\n\t\t(component as BaseComponent).block ??= memoryComponent.getBlock(index);\n\t\t(this.components as Partial<C>)[name] = component;\n\t\tif(emitAdded) {\n\t\t\tthis.emit('component-added', name, component);\n\t\t}\n\n\t\treturn component;\n\t}\n\t// Builds an accessor over an existing block (allocated + written by a worker) instead of creating a new one - the\n\t// adopt half of loadComponent, without the create.\n\tattachComponent<K extends keyof C>(name: K, index: number, emitAdded = false): C[K] {\n\t\tthis.assertComponentAllowed(name);\n\t\tconst definition = (this.world.registry as RegisteredComponentRegistry<C>)[name];\n\t\tconst component = definition.attach(this, definition.memoryComponent, index);\n\t\t(component as BaseComponent).block ??= definition.memoryComponent.getBlock(index);\n\t\t(this.components as Partial<C>)[name] = component;\n\t\tif(emitAdded) {\n\t\t\tthis.emit('component-added', name, component);\n\t\t}\n\t\treturn component;\n\t}\n\tremoveComponent<K extends keyof C>(name: K) {\n\t\tif(this.componentMemoryDeletionScheduled) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst component = (this.components as Partial<C>)[name];\n\t\tif(component) {\n\t\t\tconst definition = (this.world.registry as RegisteredComponentRegistry<C>)[name];\n\t\t\tthis.world.deferComponentMemoryFree(definition.memoryComponent, component.index, definition.free ? () => definition.free!(component) : undefined);\n\t\t\tdelete this.components[name];\n\t\t\tthis.emit('component-removed', name);\n\t\t}\n\t}\n\tsetComponent<K extends keyof C, P extends keyof C[K]>(componentName: K, prop: P, value: C[K][P]) {\n\t\tthis.assertComponentPropertyMutable(componentName, prop);\n\t\tconst component = this.components[componentName];\n\t\tif(!component) {\n\t\t\treturn;\n\t\t}\n\n\t\t(component as unknown as Record<P, C[K][P]>)[prop] = value;\n\t\tthis.emit('component-property-updated', componentName, prop, value);\n\t}\n\t/**\n\t * NOTE: Does not emit component-property-updated!\n\t */\n\tsetComponentBulk<K extends keyof C>(componentName: K, values: Partial<C[K]>) {\n\t\tfor(const prop of Object.keys(values)) {\n\t\t\tthis.assertComponentPropertyMutable(componentName, prop);\n\t\t}\n\t\tconst component = this.components[componentName];\n\t\tif(!component) {\n\t\t\treturn;\n\t\t}\n\n\t\tObject.assign(component, values);\n\t}\n\tdeleteComponent<K extends keyof C>(componentName: K, prop: keyof C[K]) {\n\t\tthis.assertComponentPropertyMutable(componentName, prop);\n\t\tconst component = this.components[componentName];\n\t\tif(!component) {\n\t\t\treturn;\n\t\t}\n\n\t\tdelete (component as Partial<C[K]>)[prop];\n\t\tthis.emit('component-property-deleted', componentName, prop);\n\t}\n\n\tdeleteAllComponentMemory() {\n\t\tif(this.componentMemoryDeletionScheduled) {\n\t\t\treturn;\n\t\t}\n\t\tthis.componentMemoryDeletionScheduled = true;\n\n\t\tconst registry = this.world.registry as RegisteredComponentRegistry<C>;\n\t\tconst components = this.components as Partial<C>;\n\t\tfor(let name of Object.keys(components) as Array<keyof C>) {\n\t\t\tconst definition = registry[name];\n\t\t\tconst component = components[name];\n\t\t\tif(component) {\n\t\t\t\tthis.world.deferComponentMemoryFree(definition.memoryComponent, component.index, definition.free ? () => definition.free!(component) : undefined);\n\t\t\t}\n\t\t}\n\t}\n\n\tload(config: Cfg) {\n\t\tconst props = config as Record<string, unknown>;\n\t\tconst registry = this.world.registry as RegisteredComponentRegistry<C>;\n\t\tfor(let name of Object.keys(registry) as Array<keyof C>) {\n\t\t\tif(name === 'entity') {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif(!this.isComponentAllowed(name)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst definition = registry[name];\n\t\t\tif(definition.loadInFinishLoading) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif(definition.loadProperties.some(prop => prop in props)) {\n\t\t\t\tthis.loadComponent(name, config, false);\n\t\t\t}\n\t\t}\n\n\t\tthis.config = config;\n\t}\n\tsave(): Cfg {\n\t\tconst config: { [key: string]: any } = {};\n\n\t\tconst registry = this.world.registry as RegisteredComponentRegistry<C>;\n\t\tconst components = this.components as Partial<C>;\n\t\tfor(let name of Object.keys(components) as Array<keyof C>) {\n\t\t\tconst definition = registry[name];\n\t\t\tconst component = components[name];\n\t\t\tif(definition.save && component) {\n\t\t\t\tObject.assign(config, definition.save(component));\n\t\t\t}\n\t\t}\n\n\t\treturn config as Cfg;\n\t}\n\t// Second pass once every entity in a load batch exists; loads the deferred (loadInFinishLoading)\n\t// components load skipped. Overrides should call super.\n\tfinishLoading() {\n\t\tconst config = this.config;\n\t\tif(!config) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst props = config as Record<string, unknown>;\n\t\tconst registry = this.world.registry as RegisteredComponentRegistry<C>;\n\t\tfor(let name of Object.keys(registry) as Array<keyof C>) {\n\t\t\tif(name === 'entity') {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif(!this.isComponentAllowed(name)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst definition = registry[name];\n\t\t\tif(definition.loadInFinishLoading && definition.loadProperties.some(prop => prop in props)) {\n\t\t\t\tthis.loadComponent(name, config, false);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate isComponentAllowed(name: keyof C): boolean {\n\t\treturn name === 'entity' || !this.allowedComponents || this.allowedComponents.has(String(name));\n\t}\n\tsetAllowedComponents(allowedComponents: ReadonlySet<string> | undefined): void {\n\t\tif(this.allowedComponents && this.allowedComponents !== allowedComponents) {\n\t\t\tthrow new Error('Entity component allowlist is immutable');\n\t\t}\n\t\tthis.allowedComponents = allowedComponents;\n\t}\n\tprivate assertComponentAllowed(name: keyof C): void {\n\t\tif(!this.isComponentAllowed(name)) {\n\t\t\tthrow new Error(`Component ${String(name)} is not allowed for entity type ${this.type}`);\n\t\t}\n\t}\n\tprivate assertComponentPropertyMutable(componentName: keyof C, prop: PropertyKey): void {\n\t\tif(componentName === 'entity' && (prop === 'type' || prop === 'class')) {\n\t\t\tthrow new Error(`Entity ${prop} is immutable`);\n\t\t}\n\t}\n}\n","import BaseEntity from './entity';\nimport type BaseWorld from './world';\nimport type { ComponentDefinitionMap, ComponentMap } from './component-definition';\nimport type { EntityClassDefinition, EntityClassRegistry, WorkerEntityClassRegistry } from './entity-class';\n\n// Maps type to a template and optionally maps the template's class to a wrapper + component allowlist.\nexport default class EntityFactory<\n\tC extends ComponentMap = ComponentMap,\n\tCfg = any,\n\tE extends BaseEntity<C, Cfg> = BaseEntity<C, Cfg>,\n> {\n\tworld!: BaseWorld<ComponentDefinitionMap, C, Cfg, E>;\n\tconfigs: { [type: string]: Cfg };\n\tclasses: EntityClassRegistry;\n\tprivate allowedComponents = new Map<string, ReadonlySet<string>>();\n\n\tconstructor(configs: { [type: string]: Cfg } = {}, classes: EntityClassRegistry = {}) {\n\t\tthis.configs = configs;\n\t\tthis.classes = classes;\n\t\tfor(const name of Object.keys(classes)) {\n\t\t\tthis.allowedComponents.set(name, new Set(classes[name].components));\n\t\t}\n\t}\n\n\tregister(type: string, config: Cfg) {\n\t\tif(this.world) {\n\t\t\tthis.validateTemplate(type, config);\n\t\t}\n\t\tthis.configs[type] = config;\n\t}\n\n\tsetWorld(world: BaseWorld<ComponentDefinitionMap, C, Cfg, E>): void {\n\t\tthis.world = world;\n\t\tfor(const name of Object.keys(this.classes)) {\n\t\t\tconst constructor = this.classes[name].entity;\n\t\t\tif(constructor !== BaseEntity && !(constructor.prototype instanceof BaseEntity)) {\n\t\t\t\tthrow new Error(`Entity class ${name} must extend BaseEntity`);\n\t\t\t}\n\t\t\tfor(const component of this.classes[name].components) {\n\t\t\t\tif(component === 'entity' || !(component in world.registry)) {\n\t\t\t\t\tthrow new Error(`Entity class ${name} contains unknown or reserved component ${component}`);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tfor(const type of Object.keys(this.configs)) {\n\t\t\tthis.validateTemplate(type, this.configs[type]);\n\t\t}\n\t}\n\n\tgetConfig(config: Cfg): Cfg {\n\t\tconst input = config as { type?: string, class?: unknown } | undefined;\n\t\tconst type = input?.type;\n\t\tconst base = type ? this.configs[type] : undefined;\n\t\tif(this.hasClasses) {\n\t\t\tif(!type || !base) {\n\t\t\t\tthrow new Error(`Unknown entity type: ${type ?? ''}`);\n\t\t\t}\n\t\t\tif(Object.prototype.hasOwnProperty.call(input, 'class')) {\n\t\t\t\tthrow new Error('Entity class comes from its type template and cannot be supplied by an instance config');\n\t\t\t}\n\t\t}\n\t\tconst merged = base ? { ...base, ...config } : config;\n\t\tif(this.hasClasses && type) {\n\t\t\tthis.validateResolvedConfig(type, merged);\n\t\t}\n\t\treturn merged;\n\t}\n\n\tloadEntity(config: Cfg, created = true): E {\n\t\tconst requestedType = (config as { type?: string }).type;\n\t\tconst merged = this.getConfig(config);\n\t\tif(this.hasClasses && requestedType) {\n\t\t\tthis.validateResolvedConfig(requestedType, merged);\n\t\t}\n\t\tconst definition = this.getClassDefinition(merged);\n\t\tconst entity = definition\n\t\t\t? this.constructEntity(definition, merged)\n\t\t\t: this.createEntity(merged);\n\t\treturn this.world.addEntity(entity, created);\n\t}\n\n\tcreateAdoptedEntity(type: string, entityClass: string | undefined, eid: number): E {\n\t\tif(!entityClass) {\n\t\t\tif(this.hasClasses) {\n\t\t\t\tthrow new Error(`Entity type ${type} has no class`);\n\t\t\t}\n\t\t\treturn new BaseEntity<C, Cfg>(this.world, undefined, eid) as E;\n\t\t}\n\t\tconst definition = this.classes[entityClass];\n\t\tif(!definition) {\n\t\t\tthrow new Error(`Unknown entity class: ${entityClass}`);\n\t\t}\n\t\tthis.validateTypeClass(type, entityClass);\n\t\tconst entity = Reflect.construct(definition.entity, [this.world, undefined, eid, this.allowedComponents.get(entityClass)]) as E;\n\t\tentity.setAllowedComponents(this.allowedComponents.get(entityClass));\n\t\treturn entity;\n\t}\n\n\tisComponentAllowed(entityClass: string | undefined, component: string): boolean {\n\t\treturn !entityClass || !this.hasClasses || this.allowedComponents.get(entityClass)?.has(component) === true;\n\t}\n\n\tgetWorkerClasses(): WorkerEntityClassRegistry | undefined {\n\t\tif(!this.hasClasses) {\n\t\t\treturn undefined;\n\t\t}\n\t\tconst classes: WorkerEntityClassRegistry = {};\n\t\tfor(const name of Object.keys(this.classes)) {\n\t\t\tclasses[name] = { components: [...this.classes[name].components] };\n\t\t}\n\t\treturn classes;\n\t}\n\n\tgetAllowedComponentsForConfig(config: Cfg | undefined): ReadonlySet<string> | undefined {\n\t\treturn config ? this.getAllowedComponents(config) : undefined;\n\t}\n\n\tprotected createEntity(config: Cfg): E {\n\t\treturn new BaseEntity<C, Cfg>(this.world, config) as E;\n\t}\n\n\tprivate get hasClasses(): boolean {\n\t\treturn this.allowedComponents.size > 0;\n\t}\n\tprivate getClassDefinition(config: Cfg): EntityClassDefinition | undefined {\n\t\tconst entityClass = (config as { class?: string }).class;\n\t\treturn entityClass ? this.classes[entityClass] : undefined;\n\t}\n\tprivate getAllowedComponents(config: Cfg): ReadonlySet<string> | undefined {\n\t\tconst entityClass = (config as { class?: string }).class;\n\t\treturn entityClass ? this.allowedComponents.get(entityClass) : undefined;\n\t}\n\tprivate constructEntity(definition: EntityClassDefinition, config: Cfg): E {\n\t\tconst entityClass = (config as { class?: string }).class;\n\t\treturn Reflect.construct(definition.entity, [this.world, config, undefined, this.allowedComponents.get(entityClass ?? '')]) as E;\n\t}\n\tprivate validateTemplate(type: string, config: Cfg): void {\n\t\tif(!this.hasClasses) {\n\t\t\treturn;\n\t\t}\n\t\tconst identity = config as { type?: string, class?: string };\n\t\tif(identity.type !== type) {\n\t\t\tthrow new Error(`Entity template ${type} must declare the same type`);\n\t\t}\n\t\tif(!identity.class || !this.classes[identity.class]) {\n\t\t\tthrow new Error(`Entity template ${type} has unknown class ${identity.class ?? ''}`);\n\t\t}\n\t\tthis.validateComponentTriggers(type, identity.class, config);\n\t}\n\tprivate validateResolvedConfig(type: string, config: Cfg): void {\n\t\tconst identity = config as { type?: string, class?: string };\n\t\tif(identity.type !== type) {\n\t\t\tthrow new Error(`Entity type ${type} is immutable`);\n\t\t}\n\t\tif(!identity.class || !this.classes[identity.class]) {\n\t\t\tthrow new Error(`Entity type ${type} has unknown class ${identity.class ?? ''}`);\n\t\t}\n\t\tthis.validateTypeClass(type, identity.class);\n\t\tthis.validateComponentTriggers(type, identity.class, config);\n\t}\n\tprivate validateTypeClass(type: string, entityClass: string): void {\n\t\tconst template = this.configs[type] as { class?: string } | undefined;\n\t\tif(!template || template.class !== entityClass) {\n\t\t\tthrow new Error(`Entity type ${type} does not belong to class ${entityClass}`);\n\t\t}\n\t}\n\tprivate validateComponentTriggers(type: string, entityClass: string, config: Cfg): void {\n\t\tconst allowed = this.allowedComponents.get(entityClass)!;\n\t\tconst allowedProperties = new Set<string>();\n\t\tfor(const component of allowed) {\n\t\t\tfor(const prop of this.world.registry[component as keyof C].loadProperties) {\n\t\t\t\tallowedProperties.add(prop);\n\t\t\t}\n\t\t}\n\t\tconst props = config as Record<string, unknown>;\n\t\tfor(const name of Object.keys(this.world.registry)) {\n\t\t\tif(name === 'entity' || allowed.has(name)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tconst definition = this.world.registry[name as keyof C];\n\t\t\tconst forbidden = definition.loadProperties.find(prop => prop in props && !allowedProperties.has(prop));\n\t\t\tif(forbidden) {\n\t\t\t\tthrow new Error(`Entity type ${type} class ${entityClass} cannot load component ${name} from property ${forbidden}`);\n\t\t\t}\n\t\t}\n\t}\n}\n","import { EventEmitter } from 'eventemitter3';\nimport MemoryHeap from '@daneren2005/shared-memory-objects/memory-heap';\nimport type { GrowBufferData } from '@daneren2005/shared-memory-objects/memory-heap';\nimport type AllocatedMemory from '@daneren2005/shared-memory-objects/allocated-memory';\nimport type { SharedAllocatedMemory } from '@daneren2005/shared-memory-objects/allocated-memory';\nimport type { SharedPoolMemory } from '@daneren2005/shared-memory-objects/shared-pool';\nimport { MAX_BYTE_OFFSET_LENGTH } from '@daneren2005/shared-memory-objects/utils/pointer';\nimport MemoryComponent from './memory-component';\nimport ConstantStringCache from './constant-string-cache';\nimport type BaseEntity from './entity';\nimport type System from './systems/system';\nimport EntitySystem from './systems/entity-system';\nimport EntityWorkerSystem from './systems/entity-worker-system';\nimport type { WorkerCreatedEntity } from './systems/entity-worker-system';\nimport type {\n\tBaseComponent, ComponentDefinitionMap, ComponentMap, ComponentRegistry, ComponentsOf,\n\tEntityConfigOf, RegisteredComponentDefinition, RegisteredComponentRegistry,\n} from './component-definition';\nimport { entityDefinition, type EntityComponent } from './entity-component';\nimport EntityFactory from './entity-factory';\n\nconst DEFAULT_HEAP_SIZE = MAX_BYTE_OFFSET_LENGTH;\nconst FREE_BUFFER_STUCK_MS = 10000;\n\ninterface DeferredComponentFree {\n\tmemoryComponent: MemoryComponent\n\tindex: number\n\t// The definition's free hook, deferred to fire alongside the block free rather than the instant the entity dies.\n\tfree?: () => void\n}\n// A batch of component blocks queued to be freed, plus the systems that must each finish a run before it is safe to free them\ninterface ComponentFreeBuffer<C extends ComponentMap> {\n\tfrees: Array<DeferredComponentFree>\n\twaitingSystems: Set<System<C>>\n\twaitElapsed: number\n}\n\nexport interface WorldOptions<\n\tC extends ComponentMap = ComponentMap,\n\tCfg = any,\n\tE extends BaseEntity<C, Cfg> = BaseEntity<C, Cfg>,\n> {\n\theapSize?: number\n\tfactory?: EntityFactory<C, Cfg, E>\n}\n\nexport interface WorldConfig<Cfg = any> {\n\tentities: Array<Cfg>\n\tgameTime?: number\n\tplayerTime?: number\n\ttimeScale?: number\n}\n\n// Shipped to a worker so it can reconstruct handles over this world's shared state (see getSharedComponentMemory).\nexport interface WorldSharedMemory {\n\tcomponents: { [name: string]: SharedPoolMemory }\n\teidCounter: SharedAllocatedMemory\n}\n\nexport default class BaseWorld<\n\tR extends ComponentDefinitionMap = ComponentDefinitionMap,\n\tC extends ComponentMap = ComponentsOf<R>,\n\tCfg = EntityConfigOf<R>,\n\tE extends BaseEntity<C, Cfg> = BaseEntity<C, Cfg>,\n> extends EventEmitter {\n\theap: MemoryHeap;\n\t// Interns entity type names (and any other constant strings) in the heap\n\tconstantStrings: ConstantStringCache;\n\t// Single heap-backed counter every thread bumps atomically, so eids stay unique whether an entity is created on\n\t// the main thread or inside a worker.\n\tprivate eidCounter: AllocatedMemory;\n\tregistry: RegisteredComponentRegistry<C> & { entity: RegisteredComponentDefinition<EntityComponent> };\n\tfactory: EntityFactory<C, Cfg, E>;\n\n\t// Keyed by eid: entities leave from the middle one at a time (every death), so a Map deletes in constant\n\t// time while still iterating in insertion order, preserving load/save order.\n\tentities: Map<number, E> = new Map();\n\tsystems: Array<System<C>> = [];\n\n\tgameTime = 0;\n\t// Keeps advancing while paused and is never scaled by timeScale (unlike gameTime).\n\tplayerTime = 0;\n\ttimeScale = 1;\n\tpaused = false;\n\tdestroyed = false;\n\t// True while the world has never been loaded into\n\tpristine = true;\n\n\t// Two rolling buffers of component blocks awaiting a safe free. New deferrals land in `next`; `active` is the\n\t// one currently waiting for its systems to each finish a run before its blocks can be reused\n\tprivate activeFreeBuffer: ComponentFreeBuffer<C> = { frees: [], waitingSystems: new Set(), waitElapsed: 0 };\n\tprivate nextFreeBuffer: ComponentFreeBuffer<C> = { frees: [], waitingSystems: new Set(), waitElapsed: 0 };\n\n\t// The entity component is added automatically, so it must not be part of the passed registry.\n\tconstructor(registry: R, options: WorldOptions<C, Cfg, E> = {}) {\n\t\tsuper();\n\n\t\tthis.heap = new MemoryHeap({ bufferSize: options.heapSize ?? DEFAULT_HEAP_SIZE });\n\t\tthis.constantStrings = new ConstantStringCache(this.heap);\n\t\tthis.eidCounter = this.heap.allocUI32(1);\n\t\t// A grown buffer must reach every worker's reconstructed heap so pointers into it still resolve.\n\t\tthis.heap.addOnGrowBufferHandlers((data: GrowBufferData) => this.emit('grow-buffer', data));\n\n\t\tconst inputRegistry = { ...registry, entity: entityDefinition } as ComponentRegistry<C> & { entity: typeof entityDefinition };\n\t\tconst registry_: Record<string, RegisteredComponentDefinition<BaseComponent>> = {};\n\t\tfor(let name of Object.keys(inputRegistry)) {\n\t\t\tconst definition = inputRegistry[name as keyof typeof inputRegistry];\n\t\t\tregistry_[name] = {\n\t\t\t\t...definition,\n\t\t\t\tmemoryComponent: new MemoryComponent(this.heap, definition.type, definition.size),\n\t\t\t};\n\t\t}\n\t\tthis.registry = registry_ as RegisteredComponentRegistry<C> & { entity: RegisteredComponentDefinition<EntityComponent> };\n\n\t\tthis.factory = options.factory ?? new EntityFactory<C, Cfg, E>();\n\t\tthis.factory.setWorld(this);\n\t}\n\n\t// Returns a fresh, unique entity id. Backed by a heap atomic so a worker allocating an entity gets an id that can\n\t// never collide with one the main thread (or another worker) hands out. First id is 1, matching the old counter.\n\tallocateEid(): number {\n\t\treturn Atomics.add(this.eidCounter.data, 0, 1) + 1;\n\t}\n\t// Everything a worker needs to reconstruct handles over this world's shared state: one SharedPoolMemory per\n\t// registered component (so it can allocate/read blocks) plus the eid counter (so it can mint unique ids).\n\tgetSharedComponentMemory(): WorldSharedMemory {\n\t\tconst components: { [name: string]: SharedPoolMemory } = {};\n\t\tfor(let name of Object.keys(this.registry)) {\n\t\t\tcomponents[name] = this.registry[name as keyof typeof this.registry].memoryComponent.getSharedMemory();\n\t\t}\n\t\treturn {\n\t\t\tcomponents,\n\t\t\teidCounter: this.eidCounter.getSharedMemory(),\n\t\t};\n\t}\n\t// A buffer that was grown inside a worker: adopt it into the main heap (if not already present) and fan it out to\n\t// every other worker so their heaps can resolve pointers into it. The heap's BUFFER_COUNT is authoritative, so\n\t// re-adding an already-known position is a harmless overwrite of the same SharedArrayBuffer.\n\taddGrownBuffer(data: GrowBufferData) {\n\t\tif(this.heap.buffers[data.bufferPosition] === undefined) {\n\t\t\tthis.heap.addSharedBuffer(data);\n\t\t}\n\t\tthis.emit('grow-buffer', data);\n\t}\n\n\t// Only an off-thread EntityWorkerSystem that creates entities or adds components allocates in a worker, so only\n\t// then is a pre-fanned-out spare buffer worth keeping. The main-thread fallback allocates on the main thread, where\n\t// growth fans out inline, so it never needs one.\n\tprivate get needsSpareBuffer(): boolean {\n\t\treturn this.systems.some(system => system instanceof EntityWorkerSystem\n\t\t\t&& system.isWorkerThread\n\t\t\t&& (!!system.options.createsEntities || !!system.options.addsComponents));\n\t}\n\n\tasync init() {\n\t\tawait Promise.all(this.systems.map(system => system.init()).filter(promise => promise instanceof Promise));\n\t}\n\tprivate finishLoadingSystems() {\n\t\treturn Promise.all(this.systems.map(system => system.finishLoading()).filter(promise => promise instanceof Promise));\n\t}\n\n\taddEntity(entity: E, created = true): E {\n\t\tthis.entities.set(entity.eid, entity);\n\t\tentity.world = this;\n\t\t// Any entity in the world means there is state to tear down on the next load/clear.\n\t\tthis.pristine = false;\n\n\t\tentity.on('component-added', (name: keyof C) => {\n\t\t\tthis.addEntityToEntityWorkerSystem(entity, name);\n\t\t});\n\t\tentity.on('component-removed', (name: keyof C) => {\n\t\t\tthis.removeEntityFromEntityWorkerSystem(entity, name);\n\t\t});\n\n\t\tif(created) {\n\t\t\tentity.finishLoading();\n\t\t\tthis.emit('entity-added', entity);\n\t\t\tentity.on('death', () => {\n\t\t\t\tthis.onEntityDied(entity);\n\t\t\t});\n\t\t}\n\n\t\treturn entity;\n\t}\n\tloadEntity(config: Cfg, created = true): E {\n\t\treturn this.factory.loadEntity(config, created);\n\t}\n\t// Materializes an entity a worker created off-thread (see createEntityWorker): the worker already minted the id and\n\t// allocated + wrote every game-component block, so this only builds the `entity` component on the main thread\n\t// (interning its type) and adopts each worker-allocated block by index, then wires it into the world like any new\n\t// entity. The factory selects the same class wrapper a main-thread load would use.\n\tadoptEntity(descriptor: WorkerCreatedEntity): E {\n\t\tlet entity: E | undefined;\n\t\tconst attached = new Set<string>();\n\t\ttry {\n\t\t\tfor(const name of Object.keys(descriptor.components)) {\n\t\t\t\tif(!(name in this.registry)) {\n\t\t\t\t\tthrow new Error(`Worker-created entity contains unknown component ${name}`);\n\t\t\t\t}\n\t\t\t\tif(!this.factory.isComponentAllowed(descriptor.class, name)) {\n\t\t\t\t\tthrow new Error(`Component ${name} is not allowed for entity class ${descriptor.class ?? ''}`);\n\t\t\t\t}\n\t\t\t}\n\t\t\tentity = this.factory.createAdoptedEntity(descriptor.type, descriptor.class, descriptor.eid);\n\t\t\tentity.loadComponent('entity', { type: descriptor.type, class: descriptor.class, isStatic: descriptor.isStatic }, false);\n\t\t\tfor(let name of Object.keys(descriptor.components)) {\n\t\t\t\tentity.attachComponent(name, descriptor.components[name]);\n\t\t\t\tattached.add(name);\n\t\t\t}\n\t\t\treturn this.addEntity(entity, true);\n\t\t} catch(error) {\n\t\t\tentity?.deleteAllComponentMemory();\n\t\t\tfor(const name of Object.keys(descriptor.components)) {\n\t\t\t\tif(!attached.has(name) && name in this.registry) {\n\t\t\t\t\tthis.deferComponentMemoryFree(this.registry[name as keyof C].memoryComponent, descriptor.components[name]);\n\t\t\t\t}\n\t\t\t}\n\t\t\tthrow error;\n\t\t}\n\t}\n\t// Replaces the world's contents. Entities load with created = false so no finishLoading runs mid-batch;\n\t// finishLoading is called on each once the whole batch exists, so cross-entity dependencies can resolve.\n\tload(config: WorldConfig<Cfg>) {\n\t\t// A pristine world (fresh or just cleared) has nothing to tear down, so skip the per-system clear.\n\t\tif(!this.pristine) {\n\t\t\t// Iterate over a copy since removeEntity mutates `this.entities`.\n\t\t\tfor(let entity of Array.from(this.entities.values())) {\n\t\t\t\tthis.removeEntity(entity);\n\t\t\t}\n\t\t\tthis.systems.forEach(system => system.clear());\n\t\t\tthis.consolidateFreeBuffersForReload();\n\t\t}\n\n\t\t// Intern a constant string for every type the factory knows, so a worker can resolve any type - even one no\n\t\t// currently-loaded entity uses. Deduped, so the types actually loaded below cost nothing extra.\n\t\tfor(let type of Object.keys(this.factory.configs)) {\n\t\t\tthis.constantStrings.getOrCreate(type);\n\t\t}\n\t\tfor(let entityClass of Object.keys(this.factory.classes)) {\n\t\t\tthis.constantStrings.getOrCreate(entityClass);\n\t\t}\n\n\t\tconst entities = config.entities.map(entityConfig => this.loadEntity(entityConfig, false));\n\t\tfor(let entity of entities) {\n\t\t\tentity.finishLoading();\n\t\t\tthis.emit('entity-added', entity);\n\t\t\tentity.on('death', () => {\n\t\t\t\tthis.onEntityDied(entity);\n\t\t\t});\n\t\t}\n\n\t\tthis.gameTime = config.gameTime ?? 0;\n\t\tthis.playerTime = config.playerTime ?? 0;\n\t\tthis.timeScale = config.timeScale ?? 1;\n\n\t\t// EntityWorkerSystem re-sends its init data here.\n\t\tvoid this.finishLoadingSystems();\n\t}\n\tasync clear(): Promise<void> {\n\t\tif(this.pristine) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Capture and await active runs before clear() resets their state. Component blocks cannot be released while a\n\t\t// worker still holds views over them, since the pool may immediately reuse those indexes after clear resolves.\n\t\tawait Promise.all(\n\t\t\tthis.systems\n\t\t\t\t.map(system => system.waitForRunToComplete())\n\t\t\t\t.filter(promise => promise instanceof Promise),\n\t\t);\n\t\tfor(let entity of Array.from(this.entities.values())) {\n\t\t\tthis.removeEntity(entity);\n\t\t}\n\t\tthis.systems.forEach(system => system.clear());\n\t\tthis.freeAllPendingBuffers();\n\n\t\tthis.pristine = true;\n\t}\n\tremoveEntity(entity: E) {\n\t\t// Match the instance as well as the eid: a stale entity must not remove a newer entity that owns the same key.\n\t\tif(this.entities.get(entity.eid) !== entity) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.entities.delete(entity.eid);\n\t\tthis.emit('entity-removed', entity);\n\t\tentity.deleteAllComponentMemory();\n\t}\n\t// Fires the death hooks then removes the entity\n\tonEntityDied(entity: E) {\n\t\tif(this.entities.get(entity.eid) !== entity) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst registry = this.registry as RegisteredComponentRegistry<C>;\n\t\tconst components = entity.components as Partial<C>;\n\t\tfor(let name of Object.keys(components) as Array<keyof C>) {\n\t\t\tconst definition = registry[name];\n\t\t\tconst component = components[name];\n\t\t\tif(definition?.died && component) {\n\t\t\t\t// A bad hook must not abort the death; mirror the update-loop convention and surface a system-error.\n\t\t\t\ttry {\n\t\t\t\t\tdefinition.died(component, entity, this as unknown as BaseWorld);\n\t\t\t\t} catch(e) {\n\t\t\t\t\tconst error = e as Error;\n\t\t\t\t\tconsole.error(`Error in died hook for component ${String(name)} (entity ${entity.eid}): ${error.message}`, error);\n\t\t\t\t\tthis.emit('system-error', { system: String(name), error, entityId: entity.eid, phase: 'died' });\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tthis.emit('entity-died', entity);\n\t\tthis.removeEntity(entity);\n\t}\n\tgetEntityByEid(eid: number): E | undefined {\n\t\treturn this.entities.get(eid);\n\t}\n\n\t// Queues a component block to be freed when all systems done using it, running the definition's free hook (if any)\n\t// at that same deferred point so a system still mid-run can't observe the resource being torn down early.\n\tdeferComponentMemoryFree(memoryComponent: MemoryComponent, index: number, free?: () => void) {\n\t\tthis.nextFreeBuffer.frees.push({ memoryComponent, index, free });\n\t}\n\t// A system finished a run; if the active buffer was waiting on it, drop it and, once nothing is left to wait\n\t// for, free the buffer. One completion is enough: the system is now done touching the block for that run, and\n\t// every later run applies the pending removed-delta before its update loop, so it can never process the freed\n\t// entity again.\n\tnotifySystemRunCompleted(system: System<C>) {\n\t\tif(this.activeFreeBuffer.waitingSystems.delete(system) && this.activeFreeBuffer.waitingSystems.size === 0) {\n\t\t\tthis.processFreeBuffers();\n\t\t}\n\t}\n\tprivate processFreeBuffers() {\n\t\t// Loop so a promoted buffer with no systems to wait for is freed the same tick rather than a frame later.\n\t\twhile(this.activeFreeBuffer.waitingSystems.size === 0) {\n\t\t\tif(this.activeFreeBuffer.frees.length > 0) {\n\t\t\t\tthis.performFrees(this.activeFreeBuffer);\n\t\t\t}\n\t\t\tif(this.nextFreeBuffer.frees.length === 0) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tthis.promoteNextFreeBuffer();\n\t\t}\n\t}\n\tprivate promoteNextFreeBuffer() {\n\t\t// active is now empty (its frees were performed); swap roles and reuse it as the new next buffer.\n\t\tconst emptied = this.activeFreeBuffer;\n\t\tthis.activeFreeBuffer = this.nextFreeBuffer;\n\t\tthis.nextFreeBuffer = emptied;\n\n\t\tconst active = this.activeFreeBuffer;\n\t\tactive.waitElapsed = 0;\n\t\tactive.waitingSystems.clear();\n\t\tfor(let system of this.systems) {\n\t\t\t// Wait on a system if it will run (and so might pick up this block) or is already mid-run over memory we\n\t\t\t// may free. A system that is neither can't touch these blocks, so there's nothing to wait for.\n\t\t\tif(system.shouldRun() || system.isCurrentlyRunning()) {\n\t\t\t\tactive.waitingSystems.add(system);\n\t\t\t}\n\t\t}\n\t}\n\t// On reload every system was just cleared (its completedRuns reset and worker told to drop its lists), so the\n\t// old targets no longer apply. Collapse whatever was pending into `next` with a fresh (empty) active buffer\n\tprivate consolidateFreeBuffersForReload() {\n\t\tif(this.activeFreeBuffer.frees.length > 0) {\n\t\t\tthis.nextFreeBuffer.frees.push(...this.activeFreeBuffer.frees);\n\t\t\tthis.activeFreeBuffer.frees.length = 0;\n\t\t}\n\t\tthis.activeFreeBuffer.waitingSystems.clear();\n\t\tthis.activeFreeBuffer.waitElapsed = 0;\n\t}\n\t// Frees both buffers outright. Only safe once every system's in-flight run has finished (see clear()), since it\n\t// skips the per-system wait the update loop normally enforces.\n\tprivate freeAllPendingBuffers() {\n\t\tthis.performFrees(this.activeFreeBuffer);\n\t\tthis.performFrees(this.nextFreeBuffer);\n\t\tthis.activeFreeBuffer.waitingSystems.clear();\n\t\tthis.activeFreeBuffer.waitElapsed = 0;\n\t\tthis.nextFreeBuffer.waitingSystems.clear();\n\t\tthis.nextFreeBuffer.waitElapsed = 0;\n\t}\n\tprivate performFrees(buffer: ComponentFreeBuffer<C>) {\n\t\tfor(let deferred of buffer.frees) {\n\t\t\tdeferred.free?.();\n\t\t\tdeferred.memoryComponent.delete(deferred.index);\n\t\t}\n\t\tbuffer.frees.length = 0;\n\t}\n\tprivate checkFreeBufferTimeout(elapsedTime: number) {\n\t\tconst active = this.activeFreeBuffer;\n\t\tif(active.waitingSystems.size === 0) {\n\t\t\treturn;\n\t\t}\n\n\t\tactive.waitElapsed += elapsedTime;\n\t\tif(active.waitElapsed >= FREE_BUFFER_STUCK_MS) {\n\t\t\tconst stuck = Array.from(active.waitingSystems).map(system => system.name).join(', ');\n\t\t\tconsole.warn(`shared-memory-ecs: deferred component free waited over ${FREE_BUFFER_STUCK_MS}ms on system(s): ${stuck}; freeing anyway`);\n\t\t\tactive.waitingSystems.clear();\n\t\t\tthis.processFreeBuffers();\n\t\t}\n\t}\n\n\taddSystem<T extends System<C>>(system: T): T {\n\t\tthis.systems.push(system);\n\t\tthis.emit('system-added', system);\n\t\treturn system;\n\t}\n\taddSystemIfNotExists(system: System<C>) {\n\t\tlet index = this.systems.findIndex(otherSystem => system.name === otherSystem.name);\n\t\tif(index === -1) {\n\t\t\tthis.systems.push(system);\n\t\t\tthis.emit('system-added', system);\n\t\t}\n\t}\n\tremoveSystem(name: string) {\n\t\tlet index = this.systems.findIndex(system => system.name === name);\n\t\tif(index !== -1) {\n\t\t\tconst [system] = this.systems.splice(index, 1);\n\t\t\tthis.emit('system-removed', system);\n\t\t}\n\t}\n\n\tupdate(elapsedTime: number): { lastSystemError?: Error | null } {\n\t\tthis.emit('update-started', elapsedTime);\n\t\tconst result = this.runUpdate(elapsedTime);\n\t\tthis.emit('update-finished', elapsedTime);\n\n\t\treturn result;\n\t}\n\tprivate runUpdate(elapsedTime: number): { lastSystemError?: Error | null } {\n\t\tthis.playerTime += elapsedTime;\n\t\tif(this.paused) {\n\t\t\treturn {};\n\t\t}\n\t\tconst unscaledElapsedTime = elapsedTime;\n\t\telapsedTime = this.timeScale * elapsedTime;\n\n\t\tthis.gameTime += elapsedTime;\n\n\t\t// Promote before running: a run this same update then counts toward the wait, instead of after it.\n\t\tthis.processFreeBuffers();\n\n\t\t// Keep an empty heap buffer fanned out ahead of any worker that allocates off-thread, so its allocations land in\n\t\t// a buffer every thread already holds. Done here (before dispatching runs) so the resulting grow-buffer message\n\t\t// is queued to each worker before its run message - postMessage is FIFO, so the worker has the buffer first.\n\t\tif(this.needsSpareBuffer) {\n\t\t\tthis.heap.ensureSpareBuffer();\n\t\t}\n\n\t\tlet lastSystemError: Error | null = null;\n\t\tthis.systems.forEach(system => {\n\t\t\tlet shouldRun = true;\n\t\t\tlet ran = false;\n\t\t\tlet failed = false;\n\t\t\tthis.emit(`system-${system.name}-started`);\n\t\t\ttry {\n\t\t\t\tshouldRun = system.shouldRun();\n\t\t\t\tif(shouldRun) {\n\t\t\t\t\tran = system.update(elapsedTime);\n\t\t\t\t}\n\t\t\t} catch(e) {\n\t\t\t\tconst error = e as Error;\n\t\t\t\tconsole.error(error.message, error);\n\t\t\t\tfailed = true;\n\t\t\t\tlastSystemError = error;\n\t\t\t\tthis.emit('system-error', { system: system.name, error, phase: 'run' });\n\t\t\t}\n\t\t\tthis.emit(`system-${system.name}-finished`, {\n\t\t\t\tran,\n\t\t\t\tshouldRun,\n\t\t\t\tfailed,\n\t\t\t});\n\t\t});\n\n\t\tthis.checkFreeBufferTimeout(unscaledElapsedTime);\n\n\t\treturn {\n\t\t\tlastSystemError,\n\t\t};\n\t}\n\tpause() {\n\t\tthis.paused = true;\n\t}\n\tresume() {\n\t\tthis.paused = false;\n\t}\n\n\taddEntityToEntityWorkerSystem(entity: BaseEntity<C>, component: keyof C) {\n\t\tthis.systems.forEach(system => {\n\t\t\tif(system instanceof EntitySystem && system.options.components?.includes(component)) {\n\t\t\t\tsystem.checkAddEntity(entity);\n\t\t\t} else if(system instanceof EntityWorkerSystem) {\n\t\t\t\tif(this.componentAffectsEntityWorkerSystem(system, component)) {\n\t\t\t\t\tsystem.checkAddEntity(entity);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t}\n\tremoveEntityFromEntityWorkerSystem(entity: BaseEntity<C>, component: keyof C) {\n\t\tthis.systems.forEach(system => {\n\t\t\tif(system instanceof EntitySystem && system.options.components?.includes(component)) {\n\t\t\t\tsystem.removeEntity(entity);\n\t\t\t} else if(system instanceof EntityWorkerSystem) {\n\t\t\t\tif(this.componentAffectsEntityWorkerSystem(system, component)) {\n\t\t\t\t\tsystem.checkAddEntity(entity);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t}\n\tprivate componentAffectsEntityWorkerSystem(system: EntityWorkerSystem<C, any>, component: keyof C): boolean {\n\t\tconst affectsMainQuery = system.options.required.includes(component)\n\t\t\t|| !!system.options.not?.includes(component)\n\t\t\t|| !!system.options.optional?.includes(component);\n\t\tconst affectsSubQuery = Object.values(system.options.queries ?? {}).some(query => {\n\t\t\treturn query.required.includes(component)\n\t\t\t\t|| !!query.not?.includes(component)\n\t\t\t\t|| !!query.optional?.includes(component);\n\t\t});\n\n\t\treturn affectsMainQuery || affectsSubQuery;\n\t}\n\n\tdestroy() {\n\t\tif(this.destroyed) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.systems.forEach(system => {\n\t\t\tsystem.destroy();\n\t\t});\n\t\tthis.destroyed = true;\n\t}\n}\n","import type { ComponentDefinitionMap, EntityConfigOf } from './component-definition';\n\nexport type EntityClassConstructor = abstract new (...args: never[]) => { readonly eid: number };\n\nexport interface EntityClassDefinition {\n\tentity: EntityClassConstructor\n\tcomponents: ReadonlyArray<string>\n}\n\nexport type EntityClassRegistry = Record<string, EntityClassDefinition>;\n\ndeclare const ENTITY_CLASSES_TYPE: unique symbol;\n\nexport type DefinedEntityClasses<\n\tR extends ComponentDefinitionMap,\n\tClasses extends EntityClassRegistry,\n> = Classes & { readonly [ENTITY_CLASSES_TYPE]: R };\n\nexport type EntityInstancesOf<Classes extends EntityClassRegistry> = InstanceType<Classes[keyof Classes & string]['entity']>;\n\ntype RegistryOf<Classes extends EntityClassRegistry> = Classes extends DefinedEntityClasses<infer R, EntityClassRegistry> ? R : never;\ntype ComponentKeysOf<Definition> = Definition extends { components: ReadonlyArray<infer K> } ? K : never;\n\nexport type EntityClassTemplateConfig<\n\tClasses extends EntityClassRegistry,\n\tClassName extends keyof Classes & string,\n\tR extends ComponentDefinitionMap = RegistryOf<Classes>,\n> = EntityConfigOf<Pick<R, Extract<ComponentKeysOf<Classes[ClassName]>, keyof R>>> & {\n\ttype: string\n\tclass: ClassName\n};\n\nexport type EntityTemplateConfigOf<Classes extends EntityClassRegistry> = {\n\t[ClassName in keyof Classes & string]: EntityClassTemplateConfig<Classes, ClassName>\n}[keyof Classes & string];\n\nexport type EntityInstanceConfigOf<Classes extends EntityClassRegistry> = EntityTemplateConfigOf<Classes> extends infer Config\n\t? Config extends object ? Omit<Config, 'class'> & { class?: never } : never\n\t: never;\n\ntype EntityClassInput<R extends ComponentDefinitionMap> = Record<string, {\n\tentity: EntityClassConstructor\n\tcomponents: ReadonlyArray<keyof R & string>\n}>;\n\ntype ExactEntityConfig<Classes extends EntityClassRegistry, ClassName extends keyof Classes & string, Type, Config> = Config\n\t& EntityClassTemplateConfig<Classes, ClassName>\n\t& { type: Type }\n\t& Record<Exclude<keyof Config, keyof EntityClassTemplateConfig<Classes, ClassName>>, never>;\n\ntype CheckedEntityConfig<Classes extends EntityClassRegistry, Type, Config> =\n\tConfig extends { class: infer ClassName }\n\t\t? ClassName extends keyof Classes & string\n\t\t\t? ExactEntityConfig<Classes, ClassName, Type, Config>\n\t\t\t: never\n\t\t: never;\n\ntype CheckedEntityConfigs<Classes extends EntityClassRegistry, Configs> = {\n\t[K in keyof Configs]: CheckedEntityConfig<Classes, K, Configs[K]>\n};\n\nexport function defineEntityClasses<\n\tR extends ComponentDefinitionMap,\n\tconst Classes extends EntityClassInput<R>,\n>(_registry: R, classes: Classes): DefinedEntityClasses<R, Classes> {\n\treturn classes as DefinedEntityClasses<R, Classes>;\n}\n\nexport function defineEntityConfigs<\n\tClasses extends EntityClassRegistry,\n\tconst Configs extends Record<string, { type: string, class: keyof Classes & string }>,\n>(_classes: Classes, configs: Configs & CheckedEntityConfigs<Classes, Configs>): Configs {\n\treturn configs;\n}\n\nexport interface WorkerEntityClassDefinition {\n\tcomponents: Array<string>\n}\n\nexport type WorkerEntityClassRegistry = Record<string, WorkerEntityClassDefinition>;\n","import type BaseEntity from '../entity';\n\n// Flags the entity dead in shared memory and emits `death`; BaseWorld listens for it to remove the entity.\nexport default function killEntity(entity: BaseEntity): void {\n\tentity.components.entity.dead = true;\n\tentity.emit('death');\n}\n","import { EventEmitter } from 'eventemitter3';\nimport type BaseWorld from './world';\nimport type { ComponentDefinitionMap, ComponentMap } from './component-definition';\nimport type System from './systems/system';\n\nexport const DEFAULT_TICKS_BETWEEN_UPDATES = 1_000;\n\nexport interface TimingStats {\n\tavg: number\n\tmin: number\n\tmax: number\n\tsamples: number\n}\n\nexport interface SystemTimingStats {\n\tname: string\n\trun: TimingStats\n\tevents: TimingStats\n}\n\nexport interface PerformanceStats {\n\tupdate: TimingStats\n\tsystems: Array<SystemTimingStats>\n\tevents: TimingStats\n}\n\nexport interface PerformanceTimingOptions {\n\tticksBetweenUpdates?: number\n}\n\ninterface SystemTiming {\n\trun: Array<number>\n\tevents: Array<number>\n\t// -1 when no run is being dispatched.\n\teventStart: number\n\tonRunFinished: (runTime: number) => void\n\tonEventsFinished: () => void\n}\n\nconst EMPTY_TIMING: TimingStats = { avg: 0, min: 0, max: 0, samples: 0 };\n\n// An empty window reads as zeroes (not an infinite min) so a snapshot is always safe to render.\nfunction summarize(samples: Array<number>): TimingStats {\n\tif(!samples.length) {\n\t\treturn { ...EMPTY_TIMING };\n\t}\n\n\tlet total = 0;\n\tlet min = Infinity;\n\tlet max = 0;\n\tfor(let sample of samples) {\n\t\ttotal += sample;\n\t\tif(sample < min) {\n\t\t\tmin = sample;\n\t\t}\n\t\tif(sample > max) {\n\t\t\tmax = sample;\n\t\t}\n\t}\n\n\treturn {\n\t\tavg: total / samples.length,\n\t\tmin,\n\t\tmax,\n\t\tsamples: samples.length,\n\t};\n}\n\n// Watches a world and reports what it costs to run, driven off events the world emits. Emits `stats-updated`\n// every `ticksBetweenUpdates`; paused frames are skipped.\nexport default class PerformanceTiming<C extends ComponentMap = ComponentMap> extends EventEmitter {\n\tworld: BaseWorld<ComponentDefinitionMap, C>;\n\tticksBetweenUpdates: number;\n\tstats: PerformanceStats = {\n\t\tupdate: { ...EMPTY_TIMING },\n\t\tsystems: [],\n\t\tevents: { ...EMPTY_TIMING },\n\t};\n\n\tprivate ticks = 0;\n\tprivate updateStart = 0;\n\tprivate updateTimes: Array<number> = [];\n\tprivate systemTimings = new Map<string, SystemTiming>();\n\tprivate destroyed = false;\n\n\tconstructor(world: BaseWorld<ComponentDefinitionMap, C>, options: PerformanceTimingOptions = {}) {\n\t\tsuper();\n\n\t\tthis.world = world;\n\t\tthis.ticksBetweenUpdates = options.ticksBetweenUpdates ?? DEFAULT_TICKS_BETWEEN_UPDATES;\n\n\t\tworld.on('update-started', this.onUpdateStarted);\n\t\tworld.on('update-finished', this.onUpdateFinished);\n\t\tworld.on('system-added', this.onSystemAdded);\n\t\tworld.on('system-removed', this.onSystemRemoved);\n\t\tworld.systems.forEach(system => this.trackSystem(system));\n\t}\n\n\tgetSystemStats(name: string): SystemTimingStats | undefined {\n\t\treturn this.stats.systems.find(system => system.name === name);\n\t}\n\n\treset() {\n\t\tthis.ticks = 0;\n\t\tthis.updateTimes = [];\n\t\tthis.systemTimings.forEach(timing => {\n\t\t\ttiming.run = [];\n\t\t\ttiming.events = [];\n\t\t\ttiming.eventStart = -1;\n\t\t});\n\t\tthis.stats = {\n\t\t\tupdate: { ...EMPTY_TIMING },\n\t\t\tsystems: [],\n\t\t\tevents: { ...EMPTY_TIMING },\n\t\t};\n\t}\n\n\tdestroy() {\n\t\tif(this.destroyed) {\n\t\t\treturn;\n\t\t}\n\t\tthis.destroyed = true;\n\n\t\tthis.world.off('update-started', this.onUpdateStarted);\n\t\tthis.world.off('update-finished', this.onUpdateFinished);\n\t\tthis.world.off('system-added', this.onSystemAdded);\n\t\tthis.world.off('system-removed', this.onSystemRemoved);\n\t\tArray.from(this.systemTimings.keys()).forEach(name => this.untrackSystem(name));\n\t\tthis.removeAllListeners();\n\t}\n\n\tprivate onUpdateStarted = () => {\n\t\tthis.updateStart = performance.now();\n\t};\n\n\tprivate onUpdateFinished = (elapsedTime: number) => {\n\t\tif(this.world.paused) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.updateTimes.push(performance.now() - this.updateStart);\n\n\t\tthis.ticks += elapsedTime;\n\t\tif(this.ticks >= this.ticksBetweenUpdates) {\n\t\t\tthis.recalculate();\n\t\t}\n\t};\n\n\tprivate onSystemAdded = (system: System<C>) => {\n\t\tthis.trackSystem(system);\n\t};\n\n\tprivate onSystemRemoved = (system: System<C>) => {\n\t\tthis.untrackSystem(system.name);\n\t};\n\n\t// The gap between `-worker-finished` (before events dispatch) and `-worker-events-finished` (after) is what\n\t// that run cost this thread. Both fire for the main-thread fallback too.\n\tprivate trackSystem(system: System<C>) {\n\t\tif(this.systemTimings.has(system.name)) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst timing: SystemTiming = {\n\t\t\trun: [],\n\t\t\tevents: [],\n\t\t\teventStart: -1,\n\t\t\tonRunFinished: (runTime: number) => {\n\t\t\t\ttiming.run.push(runTime);\n\t\t\t\ttiming.eventStart = performance.now();\n\t\t\t},\n\t\t\tonEventsFinished: () => {\n\t\t\t\tif(timing.eventStart < 0) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\ttiming.events.push(performance.now() - timing.eventStart);\n\t\t\t\ttiming.eventStart = -1;\n\t\t\t},\n\t\t};\n\n\t\tthis.world.on(`system-${system.name}-worker-finished`, timing.onRunFinished);\n\t\tthis.world.on(`system-${system.name}-worker-events-finished`, timing.onEventsFinished);\n\t\tthis.systemTimings.set(system.name, timing);\n\t}\n\n\tprivate untrackSystem(name: string) {\n\t\tconst timing = this.systemTimings.get(name);\n\t\tif(!timing) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.world.off(`system-${name}-worker-finished`, timing.onRunFinished);\n\t\tthis.world.off(`system-${name}-worker-events-finished`, timing.onEventsFinished);\n\t\tthis.systemTimings.delete(name);\n\t}\n\n\tprivate recalculate() {\n\t\tconst systems = this.world.systems.map(system => {\n\t\t\tconst timing = this.systemTimings.get(system.name);\n\t\t\treturn {\n\t\t\t\tname: system.name,\n\t\t\t\trun: summarize(timing?.run ?? []),\n\t\t\t\tevents: summarize(timing?.events ?? []),\n\t\t\t};\n\t\t});\n\n\t\tconst events: TimingStats = { ...EMPTY_TIMING };\n\t\tsystems.forEach(system => {\n\t\t\tevents.avg += system.events.avg;\n\t\t\tevents.min += system.events.min;\n\t\t\tevents.max += system.events.max;\n\t\t\tevents.samples += system.events.samples;\n\t\t});\n\n\t\tthis.stats = {\n\t\t\tupdate: summarize(this.updateTimes),\n\t\t\tsystems,\n\t\t\tevents,\n\t\t};\n\n\t\tthis.ticks = 0;\n\t\tthis.updateTimes = [];\n\t\tthis.systemTimings.forEach(timing => {\n\t\t\ttiming.run = [];\n\t\t\ttiming.events = [];\n\t\t});\n\n\t\tthis.emit('stats-updated', this.stats);\n\t}\n}\n","import type BaseWorld from '../world';\nimport type BaseEntity from '../entity';\nimport type { ComponentDefinitionMap, ComponentMap } from '../component-definition';\nimport type { SystemConfig } from './system';\nimport EntityWorkerSystem, {\n\ttype EntityWorkerSystemQuery, type EntityWorkerSystemWorld, type EntityUpdateComponents,\n} from './entity-worker-system';\nimport { toEntityUpdateFunction, type WorkerSystemRunFunction } from './workers/create-system-worker';\n\n// An EntityWorkerSystem that runs its update function once per tick instead of once per entity. It accepts the same\n// named `queries` (so it can count/scan other entities), runs on its own worker, can create entities off-thread, and\n// receives fresh per-run data via addDataToWorld — all reusing the EntityWorkerSystem machinery. It has no main query:\n// all work happens in the single run function over the named sub-queries.\nexport default class WorkerSystem<\n\tC extends ComponentMap,\n\tW extends EntityWorkerSystemWorld = EntityWorkerSystemWorld,\n\tD = unknown,\n> extends EntityWorkerSystem<C, EntityUpdateComponents<C>, W, D> {\n\tconstructor(world: BaseWorld<ComponentDefinitionMap, C>, options: WorkerSystemConfig<C, W, D>) {\n\t\tsuper(world, {\n\t\t\t...options,\n\t\t\t// No main query: the run function works entirely over the named sub-queries.\n\t\t\trequired: [],\n\t\t\tupdateFunction: toEntityUpdateFunction(options.updateFunction),\n\t\t});\n\t}\n\n\t// Never populate the main query — an empty `required` would otherwise match every entity. Sub-query membership\n\t// is maintained as usual so the run function still sees it.\n\tcheckAddEntity(entity: BaseEntity<C>): boolean {\n\t\tObject.entries(this.options.queries ?? {}).forEach(([queryName, query]) => {\n\t\t\tconst queryList = this.queryEntities[queryName] ?? (this.queryEntities[queryName] = new Map());\n\t\t\tthis.updateEntityList(queryName, queryList, entity, this.matchesQuery(entity, query));\n\t\t});\n\n\t\treturn false;\n\t}\n\n\t// Runs every interval regardless of membership, since its work is the single run function over sub-queries.\n\tshouldRun(): boolean {\n\t\treturn true;\n\t}\n}\n\nexport interface WorkerSystemConfig<\n\tC extends ComponentMap,\n\tW extends EntityWorkerSystemWorld = EntityWorkerSystemWorld,\n\tD = unknown,\n> extends SystemConfig {\n\tupdateFunction: WorkerSystemRunFunction<C, W, D>\n\tgetWorker: () => Worker\n\tforceMainThread?: boolean\n\tgetInitData?: () => D\n\tcreatesEntities?: boolean\n\tqueries?: { [key: string]: EntityWorkerSystemQuery<C> }\n}\n\nexport type { WorkerSystemRunFunction };\n"],"x_google_ignoreList":[0,1],"mappings":"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"}
@@ -56,12 +56,14 @@ export type EntityQueryComponents<C extends ComponentMap = ComponentMap> = {
56
56
  };
57
57
  type EntityUpdateFunctionImpl<C extends ComponentMap, T extends EntityUpdateComponents<C>, W extends EntityWorkerSystemWorld = EntityWorkerSystemWorld> = (world: W, entityId: number, components: T, queries: EntityQueryComponents<C>, callbacks: EntityWorkerSystemCallbacks<C>) => void;
58
58
  export type EntityUpdateFunction<C extends ComponentMap, T extends EntityUpdateComponents<C>, W extends EntityWorkerSystemWorld = EntityWorkerSystemWorld, D = unknown> = EntityUpdateFunctionImpl<C, T, W> & {
59
+ queryChanged?: EntityQueryChangedFunction<C, W>;
59
60
  preRun?: EntityUpdatePreRunFunction<C, T, W>;
60
61
  entityRemoved?: EntityRemovedFunction<C, W>;
61
62
  init?: EntityUpdateInitFunction<W, D>;
62
63
  };
63
64
  export type EntityUpdateInitFunction<W extends EntityWorkerSystemWorld = EntityWorkerSystemWorld, D = unknown> = (data: D | undefined) => Partial<W> | void;
64
65
  export type EntityUpdatePreRunFunction<C extends ComponentMap, T extends EntityUpdateComponents<C>, W extends EntityWorkerSystemWorld = EntityWorkerSystemWorld> = (world: W, entities: Array<UpdateEntityConfigObject<T>>, queries: EntityQueryComponents<C>, callbacks: EntityWorkerSystemCallbacks<C>) => void;
66
+ export type EntityQueryChangedFunction<C extends ComponentMap = ComponentMap, W extends EntityWorkerSystemWorld = EntityWorkerSystemWorld> = (world: W, queryName: string, delta: QueryDelta<EntityUpdateComponents<C>>, callbacks: EntityWorkerSystemCallbacks<C>) => void;
65
67
  export type EntityRemovedFunction<C extends ComponentMap = ComponentMap, W extends EntityWorkerSystemWorld = EntityWorkerSystemWorld> = (world: W, entityId: number, callbacks: EntityWorkerSystemCallbacks<C>) => void;
66
68
  export type UpdateEntityConfig<T extends EntityUpdateComponents = EntityUpdateComponents> = number | UpdateEntityConfigObject<T>;
67
69
  export type UpdateEntityConfigObject<T extends EntityUpdateComponents> = {
@@ -28,7 +28,7 @@ export interface SystemConfig {
28
28
  deltaBetweenRuns?: number;
29
29
  firstRun?: boolean;
30
30
  }
31
- export type SystemErrorPhase = 'preRun' | 'update' | 'entityRemoved' | 'run' | 'died';
31
+ export type SystemErrorPhase = 'queryChanged' | 'preRun' | 'update' | 'entityRemoved' | 'run' | 'died';
32
32
  export interface SystemError {
33
33
  system: string;
34
34
  error: Error;
@@ -1,8 +1,9 @@
1
1
  import { type EntitySystemWorkerScope } from './create-entity-system-worker';
2
2
  import type { ComponentDefinitionMap, ComponentMap } from '../../component-definition';
3
- import type { EntityWorkerSystemCallbacks, EntityWorkerSystemWorld, EntityQueryComponents, EntityUpdateComponents, EntityUpdateFunction, EntityUpdateInitFunction, EntityRemovedFunction } from '../entity-worker-system';
3
+ import type { EntityWorkerSystemCallbacks, EntityWorkerSystemWorld, EntityQueryComponents, EntityUpdateComponents, EntityUpdateFunction, EntityUpdateInitFunction, EntityRemovedFunction, EntityQueryChangedFunction } from '../entity-worker-system';
4
4
  export type WorkerSystemRunFunction<C extends ComponentMap, W extends EntityWorkerSystemWorld = EntityWorkerSystemWorld, D = unknown> = ((world: W, queries: EntityQueryComponents<C>, callbacks: EntityWorkerSystemCallbacks<C>) => void) & {
5
5
  init?: EntityUpdateInitFunction<W, D>;
6
+ queryChanged?: EntityQueryChangedFunction<C, W>;
6
7
  entityRemoved?: EntityRemovedFunction<C, W>;
7
8
  };
8
9
  export declare function toEntityUpdateFunction<C extends ComponentMap, W extends EntityWorkerSystemWorld = EntityWorkerSystemWorld, D = unknown>(run: WorkerSystemRunFunction<C, W, D>): EntityUpdateFunction<C, EntityUpdateComponents<C>, W, D>;
@@ -49,7 +49,7 @@ export interface EntityEvent {
49
49
  }
50
50
  export interface WorkerRunError {
51
51
  error: Error;
52
- phase: 'preRun' | 'update' | 'entityRemoved';
52
+ phase: 'queryChanged' | 'preRun' | 'update' | 'entityRemoved';
53
53
  entityId?: number;
54
54
  }
55
55
  export type SystemEvents = {
package/dist/worker.d.ts CHANGED
@@ -9,4 +9,4 @@ export { default as killEntityWorker } from './actions/kill-entity-worker';
9
9
  export { CLASS_INDEX, DEAD_INDEX, TYPE_INDEX } from './entity-component';
10
10
  export type { default as EntitySystemWorkerMessage } from './systems/workers/entity-system-worker-message';
11
11
  export type { EntityEvent, SystemEvents } from './systems/workers/entity-system-worker-message';
12
- export type { EntityWorkerSystemWorld, EntityWorkerSystemCallbacks, WorkerAllocator, WorkerCreateEntityConfig, WorkerCreatedEntity, WorkerCreatedComponent, WorkerComponentChange, EntityUpdateComponents, EntityQueryComponents, EntityUpdateFunction, EntityUpdateInitFunction, EntityUpdatePreRunFunction, EntityRemovedFunction, UpdateEntityConfigObject, } from './systems/entity-worker-system';
12
+ export type { EntityWorkerSystemWorld, EntityWorkerSystemCallbacks, WorkerAllocator, WorkerCreateEntityConfig, WorkerCreatedEntity, WorkerCreatedComponent, WorkerComponentChange, EntityUpdateComponents, EntityQueryComponents, EntityUpdateFunction, EntityUpdateInitFunction, EntityUpdatePreRunFunction, EntityQueryChangedFunction, QueryDelta, EntityRemovedFunction, UpdateEntityConfigObject, } from './systems/entity-worker-system';
package/dist/worker.js CHANGED
@@ -1,2 +1,2 @@
1
- import { a as e, c as t, d as n, i as r, l as i, o as a, r as o, s, t as c } from "./create-system-worker-CDQmmww7.js";
1
+ import { a as e, c as t, d as n, i as r, l as i, o as a, r as o, s, t as c } from "./create-system-worker-C4aS3-3R.js";
2
2
  export { t as CLASS_INDEX, i as DEAD_INDEX, n as TYPE_INDEX, e as addComponentWorker, o as createEntitySystemWorker, a as createEntityWorker, c as createSystemWorker, s as killEntityWorker, r as removeComponentWorker };
package/package.json CHANGED
@@ -2,9 +2,10 @@
2
2
  "name": "@daneren2005/shared-memory-ecs",
3
3
  "description": "A small, reusable Entity/Component/System core backed by shared memory.",
4
4
  "author": "Scott Jackson",
5
- "version": "1.7.2",
5
+ "version": "1.8.0",
6
6
  "type": "module",
7
7
  "sideEffects": false,
8
+ "license": "MIT",
8
9
  "repository": {
9
10
  "type": "git",
10
11
  "url": "git+https://github.com/daneren2005/shared-memory-ecs.git"
@@ -61,17 +62,17 @@
61
62
  "devDependencies": {
62
63
  "@semantic-release/git": "^10.0.1",
63
64
  "@stylistic/eslint-plugin": "^5.10.0",
64
- "@types/node": "^26.1.1",
65
- "@vitest/web-worker": "^4.1.10",
65
+ "@types/node": "^26.6.1",
66
+ "@vitest/web-worker": "^5.0.1",
66
67
  "cross-env": "^10.1.0",
67
68
  "husky": "^9.1.7",
68
- "lint-staged": "^17.0.8",
69
- "oxlint": "^1.73.0",
70
- "oxlint-tsgolint": "^0.24.0",
71
- "semantic-release": "^25.0.6",
69
+ "lint-staged": "^17.5.1",
70
+ "oxlint": "^1.83.0",
71
+ "oxlint-tsgolint": "^7.0.2001",
72
+ "semantic-release": "^25.0.9",
72
73
  "typescript": "^7.0.2",
73
- "vite": "^8.1.4",
74
- "vitest": "^4.1.10"
74
+ "vite": "^8.3.0",
75
+ "vitest": "^5.0.1"
75
76
  },
76
77
  "peerDependencies": {
77
78
  "@daneren2005/shared-memory-objects": "^1.5.2"