@daneren2005/shared-memory-ecs 1.3.0 → 1.5.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.
@@ -1,4 +1,6 @@
1
- import type { ComponentSystemWorld, QueryDelta } from '../component-system';
1
+ import type { MemoryHeapMemory, GrowBufferData } from '@daneren2005/shared-memory-objects/memory-heap';
2
+ import type { WorldSharedMemory } from '../../world';
3
+ import type { ComponentSystemWorld, QueryDelta, WorkerCreatedEntity } from '../component-system';
2
4
  interface InitMessage {
3
5
  type: 'init';
4
6
  }
@@ -8,6 +10,19 @@ interface InitCompleteMessage {
8
10
  interface LoadMessage<D = unknown> {
9
11
  type: 'load';
10
12
  data?: D;
13
+ heap?: MemoryHeapMemory;
14
+ sharedMemory?: WorldSharedMemory;
15
+ factoryConfigs?: {
16
+ [type: string]: Record<string, unknown>;
17
+ };
18
+ }
19
+ interface GrowBufferMessage {
20
+ type: 'grow-buffer';
21
+ buffer: GrowBufferData;
22
+ }
23
+ interface GrowBufferFromWorkerMessage {
24
+ type: 'grow-buffer-from-worker';
25
+ buffer: GrowBufferData;
11
26
  }
12
27
  interface LoadedMessage {
13
28
  type: 'loaded';
@@ -38,7 +53,7 @@ interface EntityEventsMessage {
38
53
  runTime: number;
39
54
  events: Array<EntityEvent>;
40
55
  systemEvents: SystemEvents;
41
- created: Array<Record<string, unknown>>;
56
+ created: Array<WorkerCreatedEntity>;
42
57
  }
43
- type ComponentWorkerMessage<W extends ComponentSystemWorld = ComponentSystemWorld, D = unknown> = InitMessage | InitCompleteMessage | LoadMessage<D> | LoadedMessage | ResetMessage | RunUpdateMessage<W> | EntityEventsMessage;
58
+ type ComponentWorkerMessage<W extends ComponentSystemWorld = ComponentSystemWorld, D = unknown> = InitMessage | InitCompleteMessage | LoadMessage<D> | LoadedMessage | ResetMessage | GrowBufferMessage | GrowBufferFromWorkerMessage | RunUpdateMessage<W> | EntityEventsMessage;
44
59
  export default ComponentWorkerMessage;
@@ -1,8 +1,8 @@
1
1
  import type ComponentWorkerMessage from './component-worker-message';
2
- import type { ComponentMap } from '../../component-definition';
2
+ import type { ComponentDefinitionMap, ComponentMap } from '../../component-definition';
3
3
  import type { ComponentSystemWorld, EntityUpdateComponents, EntityUpdateFunction } from '../component-system';
4
4
  export interface ComponentWorkerScope {
5
5
  onmessage: ((e: MessageEvent) => void) | null;
6
6
  postMessage(message: ComponentWorkerMessage): void;
7
7
  }
8
- export default function createComponentWorker<C extends ComponentMap, T extends EntityUpdateComponents<C>, W extends ComponentSystemWorld = ComponentSystemWorld, D = unknown>(scope: ComponentWorkerScope, updateFunction: EntityUpdateFunction<C, T, W, D>): void;
8
+ export default function createComponentWorker<C extends ComponentMap, T extends EntityUpdateComponents<C>, W extends ComponentSystemWorld = ComponentSystemWorld, D = unknown>(scope: ComponentWorkerScope, updateFunction: EntityUpdateFunction<C, T, W, D>, definitions?: ComponentDefinitionMap): void;
package/dist/worker.d.ts CHANGED
@@ -2,7 +2,7 @@ export { default as createComponentWorker } from './systems/workers/create-compo
2
2
  export type { ComponentWorkerScope } from './systems/workers/create-component-worker';
3
3
  export { default as createEntityWorker } from './actions/create-entity-worker';
4
4
  export { default as killEntityWorker } from './actions/kill-entity-worker';
5
- export { DEAD_INDEX } from './entity-component';
5
+ export { DEAD_INDEX, TYPE_INDEX } from './entity-component';
6
6
  export type { default as ComponentWorkerMessage } from './systems/workers/component-worker-message';
7
7
  export type { EntityEvent, SystemEvents } from './systems/workers/component-worker-message';
8
- export type { ComponentSystemWorld, ComponentSystemCallbacks, CreateEntityConfig, EntityUpdateComponents, EntityQueryComponents, EntityUpdateFunction, EntityUpdateInitFunction, EntityUpdatePreRunFunction, EntityRemovedFunction, UpdateEntityConfigObject, } from './systems/component-system';
8
+ export type { ComponentSystemWorld, ComponentSystemCallbacks, WorkerAllocator, WorkerCreateEntityConfig, WorkerCreatedEntity, EntityUpdateComponents, EntityQueryComponents, EntityUpdateFunction, EntityUpdateInitFunction, EntityUpdatePreRunFunction, EntityRemovedFunction, UpdateEntityConfigObject, } from './systems/component-system';
package/dist/worker.js CHANGED
@@ -1,2 +1,2 @@
1
- import { i as e, n as t, r as n, t as r } from "./create-component-worker-vbX3vEia.js";
2
- export { e as DEAD_INDEX, r as createComponentWorker, t as createEntityWorker, n as killEntityWorker };
1
+ import { i as e, n as t, o as n, r, t as i } from "./create-component-worker-CaB32Dgn.js";
2
+ export { e as DEAD_INDEX, n as TYPE_INDEX, i as createComponentWorker, t as createEntityWorker, r as killEntityWorker };
package/dist/world.d.ts CHANGED
@@ -1,7 +1,13 @@
1
1
  import { EventEmitter } from 'eventemitter3';
2
2
  import MemoryHeap from '@daneren2005/shared-memory-objects/memory-heap';
3
- import type BaseEntity from './entity';
3
+ import type { GrowBufferData } from '@daneren2005/shared-memory-objects/memory-heap';
4
+ import type { SharedAllocatedMemory } from '@daneren2005/shared-memory-objects/allocated-memory';
5
+ import type { SharedPoolMemory } from '@daneren2005/shared-memory-objects/shared-pool';
6
+ import MemoryComponent from './memory-component';
7
+ import ConstantStringCache from './constant-string-cache';
8
+ import BaseEntity from './entity';
4
9
  import type System from './systems/system';
10
+ import type { WorkerCreatedEntity } from './systems/component-system';
5
11
  import type { ComponentDefinitionMap, ComponentMap, ComponentsOf, EntityConfigOf, RegisteredComponentDefinition, RegisteredComponentRegistry } from './component-definition';
6
12
  import { type EntityComponent } from './entity-component';
7
13
  import EntityFactory from './entity-factory';
@@ -15,8 +21,16 @@ export interface WorldConfig<Cfg = any> {
15
21
  playerTime?: number;
16
22
  timeScale?: number;
17
23
  }
24
+ export interface WorldSharedMemory {
25
+ components: {
26
+ [name: string]: SharedPoolMemory;
27
+ };
28
+ eidCounter: SharedAllocatedMemory;
29
+ }
18
30
  export default class BaseWorld<R extends ComponentDefinitionMap = ComponentDefinitionMap, C extends ComponentMap = ComponentsOf<R>, Cfg = EntityConfigOf<R>> extends EventEmitter {
19
31
  heap: MemoryHeap;
32
+ constantStrings: ConstantStringCache;
33
+ private eidCounter;
20
34
  registry: RegisteredComponentRegistry<C> & {
21
35
  entity: RegisteredComponentDefinition<EntityComponent>;
22
36
  };
@@ -28,15 +42,31 @@ export default class BaseWorld<R extends ComponentDefinitionMap = ComponentDefin
28
42
  timeScale: number;
29
43
  paused: boolean;
30
44
  destroyed: boolean;
45
+ pristine: boolean;
46
+ private activeFreeBuffer;
47
+ private nextFreeBuffer;
31
48
  constructor(registry: R, options?: WorldOptions<C, Cfg>);
49
+ allocateEid(): number;
50
+ getSharedComponentMemory(): WorldSharedMemory;
51
+ addGrownBuffer(data: GrowBufferData): void;
32
52
  init(): Promise<void>;
33
53
  private finishLoadingSystems;
34
54
  addEntity(entity: BaseEntity<C, Cfg>, created?: boolean): BaseEntity<C, Cfg>;
35
55
  loadEntity(config: Cfg, created?: boolean): BaseEntity<C, Cfg>;
56
+ adoptEntity(descriptor: WorkerCreatedEntity): BaseEntity<C, Cfg>;
36
57
  load(config: WorldConfig<Cfg>): void;
58
+ clear(): Promise<void>;
37
59
  removeEntity(entity: BaseEntity<C, Cfg>): void;
38
60
  onEntityDied(entity: BaseEntity<C, Cfg>): void;
39
61
  getEntityByEid(eid: number): BaseEntity<C, Cfg> | undefined;
62
+ deferComponentMemoryFree(memoryComponent: MemoryComponent, index: number, free?: () => void): void;
63
+ notifySystemRunCompleted(system: System<C>): void;
64
+ private processFreeBuffers;
65
+ private promoteNextFreeBuffer;
66
+ private consolidateFreeBuffersForReload;
67
+ private freeAllPendingBuffers;
68
+ private performFrees;
69
+ private checkFreeBufferTimeout;
40
70
  addSystem<T extends System<C>>(system: T): T;
41
71
  addSystemIfNotExists(system: System<C>): void;
42
72
  removeSystem(name: string): void;
package/package.json CHANGED
@@ -2,7 +2,7 @@
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.3.0",
5
+ "version": "1.5.0",
6
6
  "type": "module",
7
7
  "sideEffects": false,
8
8
  "repository": {
@@ -61,6 +61,6 @@
61
61
  "vitest": "^4.1.10"
62
62
  },
63
63
  "peerDependencies": {
64
- "@daneren2005/shared-memory-objects": "^1.1.0"
64
+ "@daneren2005/shared-memory-objects": "^1.2.0"
65
65
  }
66
66
  }
@@ -1,135 +0,0 @@
1
- //#region src/systems/workers/apply-query-delta.ts
2
- function e(e, t) {
3
- if (t.removed.length) {
4
- let n = new Set(t.removed);
5
- e = e.filter((e) => !n.has(e.entityId));
6
- }
7
- if (t.added.length) {
8
- let n = /* @__PURE__ */ new Map();
9
- e.forEach((e, t) => n.set(e.entityId, t));
10
- for (let r of t.added) {
11
- let t = n.get(r.entityId);
12
- t === void 0 ? (n.set(r.entityId, e.length), e.push(r)) : e[t] = r;
13
- }
14
- }
15
- return e;
16
- }
17
- //#endregion
18
- //#region src/entity-component.ts
19
- var t = 0, n = 1, r = {
20
- type: Uint32Array,
21
- size: 2,
22
- loadProperties: ["type", "isStatic"],
23
- load(e, t, n) {
24
- let r = t.create([+!!n.dead, +!!n.isStatic]), i = t.getBlock(r);
25
- return {
26
- index: r,
27
- type: n.type,
28
- get dead() {
29
- return i[0] === 1;
30
- },
31
- set dead(e) {
32
- i[0] = +!!e;
33
- },
34
- get isStatic() {
35
- return i[1] === 1;
36
- },
37
- set isStatic(e) {
38
- i[1] = +!!e;
39
- }
40
- };
41
- },
42
- save(e) {
43
- let t = {};
44
- return e.type && (t.type = e.type), e.dead && (t.dead = !0), t;
45
- }
46
- };
47
- //#endregion
48
- //#region src/actions/kill-entity-worker.ts
49
- function i(e, t, n) {
50
- let r = t.entity;
51
- r && (r[0] = 1), n.entityDied(e);
52
- }
53
- //#endregion
54
- //#region src/actions/create-entity-worker.ts
55
- function a(e, t) {
56
- t.createEntity(e);
57
- }
58
- //#endregion
59
- //#region src/systems/workers/create-component-worker.ts
60
- function o(t, n) {
61
- let r = [], i = {}, a;
62
- t.onmessage = function(o) {
63
- let c = o.data;
64
- if (c.type === "init") s(t, { type: "init-complete" });
65
- else if (c.type === "load") a = n.init?.(c.data) ?? void 0, s(t, { type: "loaded" });
66
- else if (c.type === "reset") {
67
- r = [];
68
- for (let e of Object.keys(i)) delete i[e];
69
- a = void 0;
70
- } else if (c.type === "run") {
71
- a && Object.assign(c.world, a);
72
- let o = performance.now(), l = [], u = {}, d = [];
73
- r = e(r, c.entities);
74
- let f = {};
75
- Object.entries(c.queries).forEach(([t, n]) => {
76
- let r = e(i[t] ?? [], n);
77
- i[t] = r, f[t] = r;
78
- });
79
- let p = {
80
- entityComponentChanged(e, t, n, r) {
81
- l.push({
82
- entityId: e,
83
- event: "component-property-updated",
84
- args: [
85
- t,
86
- n,
87
- r
88
- ]
89
- });
90
- },
91
- emitEntityEvent(e, t, ...n) {
92
- l.push({
93
- entityId: e,
94
- event: t,
95
- args: n
96
- });
97
- },
98
- emitSystemEvent(e, t) {
99
- (u[e] ?? (u[e] = [])).push(t);
100
- },
101
- entityDied(e) {
102
- l.push({
103
- entityId: e,
104
- event: "death",
105
- args: []
106
- });
107
- },
108
- createEntity(e) {
109
- d.push(e);
110
- }
111
- };
112
- n.preRun && n.preRun(c.world, r, f, p), r.forEach((e) => {
113
- n(c.world, e.entityId, e.components, f, p);
114
- }), n.entityRemoved && c.entities.removed.forEach((e) => {
115
- n.entityRemoved(c.world, e, p);
116
- });
117
- let m = performance.now() - o;
118
- s(t, {
119
- type: "run-complete",
120
- generation: c.generation,
121
- runTime: m,
122
- events: l,
123
- systemEvents: u,
124
- created: d
125
- });
126
- }
127
- };
128
- }
129
- function s(e, t) {
130
- e.postMessage(t);
131
- }
132
- //#endregion
133
- export { n as a, t as i, a as n, r as o, i as r, e as s, o as t };
134
-
135
- //# sourceMappingURL=create-component-worker-vbX3vEia.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"create-component-worker-vbX3vEia.js","names":[],"sources":["../src/systems/workers/apply-query-delta.ts","../src/entity-component.ts","../src/actions/kill-entity-worker.ts","../src/actions/create-entity-worker.ts","../src/systems/workers/create-component-worker.ts"],"sourcesContent":["import type { EntityUpdateComponents, QueryDelta, UpdateEntityConfigObject } from '../component-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 { ComponentDefinition } from './component-definition';\n\n// dead/isStatic live in the shared block (worker-visible); type is main-thread only.\nexport interface EntityComponent {\n\tindex: number\n\ttype: string\n\tdead: boolean\n\tisStatic: boolean\n}\n\nexport interface EntityComponentConfig {\n\ttype: string\n\tisStatic?: boolean\n}\n\nexport interface EntityComponentSerialization {\n\ttype?: string\n\tdead?: boolean\n}\n\nexport const DEAD_INDEX = 0;\nexport const STATIC_INDEX = 1;\n\nexport const entityDefinition: ComponentDefinition<EntityComponent, Uint32Array, EntityComponentConfig, EntityComponentSerialization> = {\n\ttype: Uint32Array,\n\tsize: 2,\n\tloadProperties: ['type', 'isStatic'],\n\tload(entity, memory, config) {\n\t\tconst index = memory.create([config.dead ? 1 : 0, config.isStatic ? 1 : 0]);\n\t\tconst block = memory.getBlock(index);\n\n\t\treturn {\n\t\t\tindex,\n\t\t\ttype: config.type,\n\t\t\tget dead() {\n\t\t\t\treturn block[DEAD_INDEX] === 1;\n\t\t\t},\n\t\t\tset dead(value: boolean) {\n\t\t\t\tblock[DEAD_INDEX] = value ? 1 : 0;\n\t\t\t},\n\t\t\tget isStatic() {\n\t\t\t\treturn block[STATIC_INDEX] === 1;\n\t\t\t},\n\t\t\tset isStatic(value: boolean) {\n\t\t\t\tblock[STATIC_INDEX] = value ? 1 : 0;\n\t\t\t},\n\t\t};\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 { ComponentSystemCallbacks, EntityUpdateComponents } from '../systems/component-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: ComponentSystemCallbacks): 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 { ComponentSystemCallbacks, CreateEntityConfig } from '../systems/component-system';\n\n// Worker-side loadEntity: buffers the config through callbacks. The main thread builds it via world.loadEntity\n// once the run completes, so it first exists on the following frame.\nexport default function createEntityWorker(config: CreateEntityConfig, callbacks: ComponentSystemCallbacks): void {\n\tcallbacks.createEntity(config);\n}\n","import type ComponentWorkerMessage from './component-worker-message';\nimport type { EntityEvent, SystemEvents } from './component-worker-message';\nimport type { ComponentMap } from '../../component-definition';\nimport type { ComponentSystemCallbacks, ComponentSystemWorld, EntityQueryComponents, EntityUpdateComponents, EntityUpdateFunction, QueryDelta, UpdateEntityConfigObject } from '../component-system';\nimport { applyQueryDelta } from './apply-query-delta';\n\n// The slice of the worker global scope createComponentWorker 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 ComponentWorkerScope {\n\tonmessage: ((e: MessageEvent) => void) | null\n\tpostMessage(message: ComponentWorkerMessage): void\n}\n\nexport default function createComponentWorker<\n\tC extends ComponentMap,\n\tT extends EntityUpdateComponents<C>,\n\tW extends ComponentSystemWorld = ComponentSystemWorld,\n\tD = unknown,\n>(scope: ComponentWorkerScope, updateFunction: EntityUpdateFunction<C, T, W, D>) {\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\n\tscope.onmessage = function(e) {\n\t\tconst message = e.data as ComponentWorkerMessage<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\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 === '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\tconst start = performance.now();\n\t\t\tlet entityEvents: Array<EntityEvent> = [];\n\t\t\tlet systemEvents: SystemEvents = {};\n\t\t\tlet createdEntities: Array<Record<string, unknown>> = [];\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: ComponentSystemCallbacks<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(config: Record<string, unknown>) {\n\t\t\t\t\tcreatedEntities.push(config);\n\t\t\t\t},\n\t\t\t};\n\t\t\tif(updateFunction.preRun) {\n\t\t\t\tupdateFunction.preRun(message.world, entities, queries, callbacks);\n\t\t\t}\n\n\t\t\tentities.forEach(entity => {\n\t\t\t\tupdateFunction(message.world, entity.entityId, entity.components, queries, callbacks);\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\tupdateFunction.entityRemoved!(message.world, entityId, callbacks);\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});\n\t\t}\n\t};\n}\n\nfunction postMessageTyped(scope: ComponentWorkerScope, message: ComponentWorkerMessage) {\n\tscope.postMessage(message);\n}\n"],"mappings":";AAKA,SAAgB,EACf,GACA,GACqC;CACrC,IAAG,EAAM,QAAQ,QAAQ;EACxB,IAAM,IAAa,IAAI,IAAI,EAAM,OAAO;EACxC,IAAO,EAAK,QAAO,MAAS,CAAC,EAAW,IAAI,EAAM,QAAQ,CAAC;CAC5D;CAEA,IAAG,EAAM,MAAM,QAAQ;EAEtB,IAAM,oBAAa,IAAI,IAAoB;EAC3C,EAAK,SAAS,GAAO,MAAU,EAAW,IAAI,EAAM,UAAU,CAAK,CAAC;EAEpE,KAAI,IAAI,KAAU,EAAM,OAAO;GAC9B,IAAM,IAAW,EAAW,IAAI,EAAO,QAAQ;GAC/C,AAAG,MAAa,KAAA,KAGf,EAAW,IAAI,EAAO,UAAU,EAAK,MAAM,GAC3C,EAAK,KAAK,CAAM,KAHhB,EAAK,KAAY;EAKnB;CACD;CAEA,OAAO;AACR;;;ACXA,IAAa,IAAa,GACb,IAAe,GAEf,IAA2H;CACvI,MAAM;CACN,MAAM;CACN,gBAAgB,CAAC,QAAQ,UAAU;CACnC,KAAK,GAAQ,GAAQ,GAAQ;EAC5B,IAAM,IAAQ,EAAO,OAAO,CAAC,KAAO,MAAc,KAAO,QAAgB,CAAC,GACpE,IAAQ,EAAO,SAAS,CAAK;EAEnC,OAAO;GACN;GACA,MAAM,EAAO;GACb,IAAI,OAAO;IACV,OAAO,EAAA,OAAsB;GAC9B;GACA,IAAI,KAAK,GAAgB;IACxB,EAAA,KAAoB;GACrB;GACA,IAAI,WAAW;IACd,OAAO,EAAA,OAAwB;GAChC;GACA,IAAI,SAAS,GAAgB;IAC5B,EAAA,KAAsB;GACvB;EACD;CACD;CACA,KAAK,GAAW;EACf,IAAM,IAAuC,CAAC;EAQ9C,OAPG,EAAU,SACZ,EAAO,OAAO,EAAU,OAEtB,EAAU,SACZ,EAAO,OAAO,KAGR;CACR;AACD;;;ACrDA,SAAwB,EAAiB,GAAkB,GAAoC,GAA2C;CACzI,IAAM,IAAS,EAAgD;CAK/D,AAJG,MACF,EAAA,KAAoB,IAGrB,EAAU,WAAW,CAAQ;AAC9B;;;ACTA,SAAwB,EAAmB,GAA4B,GAA2C;CACjH,EAAU,aAAa,CAAM;AAC9B;;;ACOA,SAAwB,EAKtB,GAA6B,GAAkD;CAEhF,IAAI,IAA+C,CAAC,GAC9C,IAAuE,CAAC,GAE1E;CAEJ,EAAM,YAAY,SAAS,GAAG;EAC7B,IAAM,IAAU,EAAE;EAElB,IAAG,EAAQ,SAAS,QACnB,EAAiB,GAAO,EACvB,MAAM,gBACP,CAAC;OACK,IAAG,EAAQ,SAAS,QAE1B,AADA,IAAiB,EAAe,OAAO,EAAQ,IAAI,KAAK,KAAA,GACxD,EAAiB,GAAO,EACvB,MAAM,SACP,CAAC;OACK,IAAG,EAAQ,SAAS,SAAS;GAEnC,IAAW,CAAC;GACZ,KAAI,IAAM,KAAO,OAAO,KAAK,CAAa,GACzC,OAAO,EAAc;GAEtB,IAAiB,KAAA;EAClB,OAAO,IAAG,EAAQ,SAAS,OAAO;GACjC,AAAG,KACF,OAAO,OAAO,EAAQ,OAAO,CAAc;GAE5C,IAAM,IAAQ,YAAY,IAAI,GAC1B,IAAmC,CAAC,GACpC,IAA6B,CAAC,GAC9B,IAAkD,CAAC;GAEvD,IAAW,EAAgB,GAAU,EAAQ,QAAyB;GAEtE,IAAI,IAAoC,CAAC;GACzC,OAAO,QAAQ,EAAQ,OAAO,CAAC,CAAC,SAAS,CAAC,GAAU,OAAW;IAC9D,IAAM,IAAO,EAAgB,EAAc,MAAa,CAAC,GAAG,CAAsB;IAElF,AADA,EAAc,KAAY,GAC1B,EAAQ,KAAY;GACrB,CAAC;GAED,IAAI,IAAyC;IAC5C,uBAAgE,GAAkB,GAAkB,GAAS,GAAgB;KAC5H,EAAa,KAAK;MACjB;MACA,OAAO;MACP,MAAM;OAAC;OAAe;OAAM;MAAK;KAClC,CAAC;IACF;IACA,gBAAgB,GAAkB,GAAe,GAAG,GAAsB;KACzE,EAAa,KAAK;MACjB;MACA;MACA;KACD,CAAC;IACF;IACA,gBAAgB,GAAe,GAAkB;KAChD,CAAC,EAAa,OAAW,EAAa,KAAS,CAAC,GAAA,CAAI,KAAK,CAAQ;IAClE;IACA,WAAW,GAAkB;KAC5B,EAAa,KAAK;MACjB;MACA,OAAO;MACP,MAAM,CAAC;KACR,CAAC;IACF;IACA,aAAa,GAAiC;KAC7C,EAAgB,KAAK,CAAM;IAC5B;GACD;GASA,AARG,EAAe,UACjB,EAAe,OAAO,EAAQ,OAAO,GAAU,GAAS,CAAS,GAGlE,EAAS,SAAQ,MAAU;IAC1B,EAAe,EAAQ,OAAO,EAAO,UAAU,EAAO,YAAY,GAAS,CAAS;GACrF,CAAC,GAEE,EAAe,iBACjB,EAAQ,SAAS,QAAQ,SAAQ,MAAY;IAC5C,EAAe,cAAe,EAAQ,OAAO,GAAU,CAAS;GACjE,CAAC;GAEF,IAAM,IAAU,YAAY,IAAI,IAAI;GAEpC,EAAiB,GAAO;IACvB,MAAM;IACN,YAAY,EAAQ;IACpB;IACA,QAAQ;IACR;IACA,SAAS;GACV,CAAC;EACF;CACD;AACD;AAEA,SAAS,EAAiB,GAA6B,GAAiC;CACvF,EAAM,YAAY,CAAO;AAC1B"}