aiecsjs 0.5.8 → 0.6.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 +46 -12
- package/README_ZHTW.md +46 -12
- package/api.json +171 -48
- package/dist/chunk-27JX7WHY.js +2 -0
- package/dist/chunk-27JX7WHY.js.map +1 -0
- package/dist/chunk-GJ6U2TIU.js +2 -0
- package/dist/chunk-GJ6U2TIU.js.map +1 -0
- package/dist/chunk-LNZZ4WWC.js +2 -0
- package/dist/chunk-LNZZ4WWC.js.map +1 -0
- package/dist/chunk-MVBFYRHY.cjs +2 -0
- package/dist/chunk-MVBFYRHY.cjs.map +1 -0
- package/dist/chunk-NPNWRCB5.cjs +2 -0
- package/dist/chunk-NPNWRCB5.cjs.map +1 -0
- package/dist/chunk-O4UVAWFU.cjs +2 -0
- package/dist/chunk-O4UVAWFU.cjs.map +1 -0
- package/dist/commands.cjs +1 -1
- package/dist/commands.cjs.map +1 -1
- package/dist/commands.d.cts +1 -1
- package/dist/commands.d.ts +1 -1
- package/dist/commands.js +1 -1
- package/dist/commands.js.map +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +79 -13
- package/dist/index.d.ts +79 -13
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/loop.cjs +1 -1
- package/dist/loop.cjs.map +1 -1
- package/dist/loop.d.cts +12 -0
- package/dist/loop.d.ts +12 -0
- package/dist/loop.js +1 -1
- package/dist/loop.js.map +1 -1
- package/dist/observers.cjs +1 -1
- package/dist/observers.cjs.map +1 -1
- package/dist/observers.d.cts +7 -1
- package/dist/observers.d.ts +7 -1
- package/dist/observers.js +1 -1
- package/dist/observers.js.map +1 -1
- package/dist/relations.cjs +1 -1
- package/dist/relations.cjs.map +1 -1
- package/dist/relations.d.cts +18 -9
- package/dist/relations.d.ts +18 -9
- package/dist/relations.js +1 -1
- package/dist/relations.js.map +1 -1
- package/dist/serialize.cjs +1 -1
- package/dist/serialize.d.cts +30 -5
- package/dist/serialize.d.ts +30 -5
- package/dist/serialize.js +1 -1
- package/dist/{types-BeVLA7xG.d.cts → types-C6TkQ7HW.d.cts} +33 -0
- package/dist/{types-BeVLA7xG.d.ts → types-C6TkQ7HW.d.ts} +33 -0
- package/dist/worker.cjs +1 -1
- package/dist/worker.cjs.map +1 -1
- package/dist/worker.d.cts +10 -3
- package/dist/worker.d.ts +10 -3
- package/dist/worker.js +1 -1
- package/dist/worker.js.map +1 -1
- package/llms-full.txt +120 -18
- package/llms.txt +1 -0
- package/package.json +57 -22
- package/dist/chunk-3FV6UMUS.cjs +0 -2
- package/dist/chunk-3FV6UMUS.cjs.map +0 -1
- package/dist/chunk-3ZLNR4JX.cjs +0 -2
- package/dist/chunk-3ZLNR4JX.cjs.map +0 -1
- package/dist/chunk-N5OETPTK.js +0 -2
- package/dist/chunk-N5OETPTK.js.map +0 -1
- package/dist/chunk-TNZMD7E5.js +0 -2
- package/dist/chunk-TNZMD7E5.js.map +0 -1
- package/dist/chunk-YFTCD2UG.js +0 -2
- package/dist/chunk-YFTCD2UG.js.map +0 -1
- package/dist/chunk-ZIZSWIHW.cjs +0 -2
- package/dist/chunk-ZIZSWIHW.cjs.map +0 -1
package/llms-full.txt
CHANGED
|
@@ -14,7 +14,7 @@ The short index lives at `llms.txt` (see https://llmstxt.org/).
|
|
|
14
14
|
|
|
15
15
|
TypeScript-first archetype ECS with TypedArray SoA components, command buffers, relations, serialization, and SAB-ready snapshot transport.
|
|
16
16
|
|
|
17
|
-
> **Status: 0.
|
|
17
|
+
> **Status: 0.6.0 - stable 1.0-track core.** Root ECS APIs are stable; worker transport remains adapter-shaped and environment-dependent. 0.6.0 has breaking changes (snapshot format 2, stricter validation): see the [CHANGELOG](CHANGELOG.md).
|
|
18
18
|
|
|
19
19
|
## Install
|
|
20
20
|
|
|
@@ -29,8 +29,8 @@ import {
|
|
|
29
29
|
createEntity,
|
|
30
30
|
createWorld,
|
|
31
31
|
defineComponent,
|
|
32
|
-
|
|
33
|
-
|
|
32
|
+
defineQuery,
|
|
33
|
+
forEachEntityIndexed,
|
|
34
34
|
} from "aiecsjs";
|
|
35
35
|
```
|
|
36
36
|
|
|
@@ -45,15 +45,15 @@ const e = createEntity(world);
|
|
|
45
45
|
addComponent(world, e, Position, { x: 0, y: 0 });
|
|
46
46
|
addComponent(world, e, Velocity, { x: 1, y: 0 });
|
|
47
47
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
pos.x += vel.x;
|
|
52
|
-
pos.y += vel.y;
|
|
48
|
+
// SoA columns are TypedArrays; index them with `i`, the entity's slot index.
|
|
49
|
+
const movers = defineQuery([Position, Velocity]);
|
|
50
|
+
forEachEntityIndexed(world, movers, (entity, i, pos, vel) => {
|
|
51
|
+
pos.x[i] += vel.x[i];
|
|
52
|
+
pos.y[i] += vel.y[i];
|
|
53
53
|
});
|
|
54
54
|
```
|
|
55
55
|
|
|
56
|
-
Use `defineTag()` for marker components and `defineObjectComponent()` when you need object references instead of TypedArray storage.
|
|
56
|
+
Use `defineTag()` for marker components and `defineObjectComponent()` when you need object references instead of TypedArray storage. Do not index columns with the packed `entity` id: it stops matching the slot once a slot is recycled.
|
|
57
57
|
|
|
58
58
|
## Public Surface
|
|
59
59
|
|
|
@@ -67,15 +67,49 @@ Use `defineTag()` for marker components and `defineObjectComponent()` when you n
|
|
|
67
67
|
| `aiecsjs/worker` | Transfer/adopt/attach helpers for worker snapshots. |
|
|
68
68
|
| `aiecsjs/relations` | `defineRelation`, `ChildOf`, relation add/remove/read helpers. |
|
|
69
69
|
|
|
70
|
+
## Snapshots
|
|
71
|
+
|
|
72
|
+
`toJSON` / `serializeWorld` write snapshot format 2: entity data plus a table of the components it uses (stable key, kind, SoA fields). Give every component you save a `key`, so a loading session can define its components in any order:
|
|
73
|
+
|
|
74
|
+
```ts
|
|
75
|
+
const Position = defineComponent({ x: Types.f32, y: Types.f32 }, { key: "position" });
|
|
76
|
+
const Player = defineTag({ key: "player" });
|
|
77
|
+
|
|
78
|
+
const bytes = serializeWorld(world); // aiecsjs/serialize
|
|
79
|
+
const restored = deserializeWorld(bytes); // or fromJSON(toJSON(world))
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
- Loading resolves every component before it creates the world: by key, or by creation-order id for keyless components. It throws `EcsError` when a component is not defined in this process (pass `onUnknownComponent: "skip"` to drop its data) or when its kind or SoA fields differ.
|
|
83
|
+
- 0.5.x snapshots are rejected with `EcsError` by default; `{ onUnknownVersion: "best-effort" }` loads them by id with a kind check. See [0.5.x -> 0.6.0 snapshots](docs/MIGRATION.md#05x---060-snapshots).
|
|
84
|
+
- Restored entities get fresh ids in snapshot order (holes in the slot range close up), so EntityIds stored inside component data are not remapped. Delta `apply()` keeps slot indices.
|
|
85
|
+
|
|
86
|
+
## Relations
|
|
87
|
+
|
|
88
|
+
```ts
|
|
89
|
+
import { ChildOf, addRelation, getRelationTargets } from "aiecsjs/relations";
|
|
90
|
+
|
|
91
|
+
addRelation(world, child, ChildOf, parent);
|
|
92
|
+
getRelationTargets(world, child, ChildOf); // [parent]
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
- `addRelation` throws `EcsError` for a dead source or target, mirroring `addComponent`. Check `entityExists` first when an endpoint may be stale.
|
|
96
|
+
- `destroyEntity` and `resetWorld` drop every edge of the entities they remove; `removeRelation` is a no-op for dead endpoints.
|
|
97
|
+
|
|
98
|
+
## Errors
|
|
99
|
+
|
|
100
|
+
- Misuse and invariant failures throw `EcsError` (message `aiecsjs: ...`) before any change is made: non-integer world options, dead entities, unknown components, invalid component keys, non-function callbacks (observer handlers, `forEachEntity`, `withCommandBuffer`, `pipe` systems, AoS factories) and snapshot errors.
|
|
101
|
+
- A world from `attachWorld(buffer, { readOnly: true })` rejects every mutator with `EcsError`: `createEntity`, `destroyEntity`, `addComponent`, `removeComponent`, `setComponent`, `resetWorld`, `addRelation`, `removeRelation` and delta `apply()`.
|
|
102
|
+
- `defineComponent` field-declaration errors and non-Query input to query functions throw `TypeError`. `createLoop` (`aiecsjs/loop` has no error class) throws `TypeError` / `RangeError`.
|
|
103
|
+
|
|
70
104
|
## Sharp Edges
|
|
71
105
|
|
|
72
106
|
- Structural mutation during a query loop is allowed by the library, but app systems should prefer `withCommandBuffer()` when adding/removing/destroying entities from inside iteration.
|
|
73
107
|
- Reactive query buffers are unbounded until drained. Poll and clear them every frame or event tick.
|
|
74
|
-
-
|
|
75
|
-
- Exclusive relation cleanup
|
|
108
|
+
- Queries are cached process-wide, and a structural change visits every reactive (enter/exit) source query that references the changed component, whichever world registered it.
|
|
109
|
+
- Exclusive relation cleanup is `O(incoming)` on destroy for the exclusive-slot reverse index, but every destroy also walks all relation `data` payload sources and all `outgoing` (non-exclusive) edge lists — cost is `O(incoming + data sources + outgoing sources)` across all relations, even for entities with no relations at all.
|
|
76
110
|
- Serialization restores capacity with safety clamps, but snapshots from untrusted sources should still be treated as hostile input.
|
|
77
111
|
- Worker/SAB helpers depend on the runtime environment. Feature-detect `SharedArrayBuffer` and cross-origin isolation in browsers.
|
|
78
|
-
- `pnpm lint`
|
|
112
|
+
- `pnpm lint` reports 84 `noExplicitAny` warnings, mostly casts in tests plus the public query callback types. They are not release-blocking.
|
|
79
113
|
|
|
80
114
|
## AI Context
|
|
81
115
|
|
|
@@ -98,7 +132,64 @@ MIT
|
|
|
98
132
|
|
|
99
133
|
All notable changes to aiecsjs are summarized here. Detailed historical review notes live in Git history; this file keeps current release context compact.
|
|
100
134
|
|
|
101
|
-
## [
|
|
135
|
+
## [0.6.0] - 2026-09-29
|
|
136
|
+
|
|
137
|
+
### Breaking
|
|
138
|
+
|
|
139
|
+
- `toJSON` / `serializeWorld` / `createDeltaSerializer` / `fromJSON` / `deserializeWorld` / `adoptSnapshot` / `attachWorld`: snapshots are now format 2 with a component table, and every loader resolves each component by its stable key (by creation-order id when keyless) and throws `EcsError` for a component the process has not defined or a kind / SoA-field mismatch, because 0.5.x id-only matching silently put data into the wrong components when definition order differed; 0.5.x snapshots (no `formatVersion`, binary or worker meta format 1) are rejected with `EcsError: aiecsjs: format version 1 not supported`. Migration: give every serialized component a key (`defineComponent(schema, { key })`, `defineTag({ key })`, `defineObjectComponent(factory, { key })`), re-export existing 0.5.x snapshots with 0.6.0 or load them once with `{ onUnknownVersion: 'best-effort' }` and save again, pass `{ onUnknownComponent: 'skip' }` where dropping unknown components is intended, and add `formatVersion: 2` plus a `components` table to hand-built snapshots (see docs/MIGRATION.md).
|
|
140
|
+
- `addRelation`: a dead source or target now throws `EcsError` (mirroring `addComponent`), because edges are stored by slot and an edge to a dead entity was inherited by whatever entity was later recycled into that slot. Migration: check `entityExists` before `addRelation` when an endpoint may be stale.
|
|
141
|
+
- `createWorld`: a non-integer `initialCapacity`, `maxEntities`, `indexBits` or `generationBits` (such as `1.5`, `NaN`, `Infinity` or `'8'`) now throws `EcsError` before the range checks and clamps, because fractional and `NaN` values silently truncated typed arrays and dropped entities. Migration: pass integers for these options (for example `Math.floor(n)`).
|
|
142
|
+
- `resetWorld`: a read-only (worker-attached) world now throws `EcsError`, as every other mutator already did, instead of being wiped. Migration: reset a writable world instead (`adoptSnapshot`, or `attachWorld` without `readOnly`).
|
|
143
|
+
- `onAdd` / `onRemove` / `onSet` / `observe`, `forEachEntity` / `forEachEntityIndexed`, `withCommandBuffer`, `pipe`, `defineObjectComponent` and the relation helpers: a non-function handler, callback, system or factory, an AoS factory that returns `null` or `undefined`, or a relation argument that is not a `defineRelation` handle now throws `EcsError` at the call, instead of being accepted and failing later (for observers, after the structural change was already committed) or doing nothing. Migration: pass functions, a factory that returns a value and real relation handles; catch `EcsError` where these come from dynamic input.
|
|
144
|
+
- `createLoop` (`aiecsjs/loop`): a missing options object or a non-function `onUpdate` / `onRender` now throws `TypeError`, and a `fixed` that is not a finite number > 0 or a `maxSubSteps` that is not a finite number >= 1 throws `RangeError`, instead of failing in the first tick or silently stalling. Migration: pass an options object with a function `onUpdate`, and a positive finite `fixed` and a `maxSubSteps` of at least 1 when you set them.
|
|
145
|
+
|
|
146
|
+
### Changes
|
|
147
|
+
|
|
148
|
+
- Added: stable component keys: `defineComponent(schema, { key })`, `defineTag({ key })` and `defineObjectComponent(factory, { key })`; a key must be a non-empty string (`EcsError` otherwise); defining a key again with the same kind and field layout (HMR, editor script reload) returns the existing component, and a different layout throws `EcsError`.
|
|
149
|
+
- Added: `DeserializeOptions.onUnknownComponent` (`'throw'` by default, or `'skip'`); `fromJSON(snapshot, options?)` takes `DeserializeOptions` (including the `components` allowlist), and `adoptSnapshot(snap, options?)` and `attachWorld(buffer, { readOnly?, ...DeserializeOptions })` pass them through.
|
|
150
|
+
- Added: the `EcsError` constructor accepts an optional `{ cause }`.
|
|
151
|
+
- Changed: every plain `Error` misuse throw (read-only guards, the dead-entity guards of `addComponent` / `setComponent`, unregistered components, the missing empty archetype guard, binary snapshot header and body errors, worker meta errors, command-buffer errors) is now `EcsError` with the same message, so callers can branch on the class; `instanceof Error` checks and message matches keep working.
|
|
152
|
+
- Changed: `noExplicitAny` lint warnings are down from 133 to 84 (`src` 11 to 4, tests 122 to 80), with the emitted public `.d.ts` signatures unchanged; the 4 left in `src` are the public query callback and `ComponentLike` types.
|
|
153
|
+
- Changed: internal refactors keep every entry inside its existing size budget: shared archetype-row and slot-placement helpers, one loop for `forEachEntity` / `forEachEntityIndexed`, one reactive-buffer drain, one mask matcher, and removal of the never-read per-archetype edge tables (two `Int32Array(256)` per archetype) and of unreachable fallback factories; the coverage `functions` threshold is raised to 100.
|
|
154
|
+
- Fixed: `destroyEntity` no longer recurses (or corrupts world size/freeList/exit-query state) when an onRemove/observe handler destroys, resets, or otherwise re-enters teardown for the same entity.
|
|
155
|
+
- Fixed: the package's `sideEffects: false` no longer lets bundlers drop `dist/index.js`'s component-lookup and mask-change registration, which broke queries (and left reactive enter/exit queries empty) for consumers who imported only chunk-owned bindings.
|
|
156
|
+
- Fixed: query observers (`observe(world, query, 'add'|'remove')`) now track match transitions, so queries with `none` terms fire enter/exit correctly and `'remove'` no longer fires for entities that never matched.
|
|
157
|
+
- Fixed: the delta serializer now replicates AoS (`defineObjectComponent`) changes; `capture()` previously aliased the live component instance and always diffed it against itself, silently dropping AoS updates.
|
|
158
|
+
- Fixed: `toJSON`/delta capture no longer drop component-less live entities (archetype 0) from snapshots.
|
|
159
|
+
- Fixed: `flush()` detaches the command-buffer queue before applying it, so a flush that throws partway through no longer replays Phase 1 and duplicates entities on retry.
|
|
160
|
+
- Fixed: command-buffer ops enqueued during `flush()` (e.g. from an onAdd/onRemove handler) are now processed in further rounds instead of throwing an unresolved-placeholder error or being silently dropped.
|
|
161
|
+
- Fixed: component-level `onRemove` handlers can now read the outgoing component's value via `getComponent` on the `removeComponent` path, matching the existing `destroyEntity` path.
|
|
162
|
+
- Fixed: `forEachEntity`/`forEachEntityIndexed`/`iterQuery`/`runQuery` accept a raw component array (routed through `defineQuery`) and throw a `TypeError` for other non-Query input, instead of silently iterating zero entities.
|
|
163
|
+
- Fixed: an in-loop `addComponent`/`removeComponent` that moves the currently visited entity into an archetype already covered by the same `forEachEntity`/`forEachEntityIndexed` pass no longer visits it twice or skips another entity.
|
|
164
|
+
- Fixed: `observe(world, query, 'set')` now fires only for entities that actually match the query (not merely any entity carrying a component in `query.all`), and fires for `any`-only components too.
|
|
165
|
+
- Fixed: `toJSON` deep-copies AoS component data instead of handing out the live instance, so `fromJSON(toJSON(w))` and a mutated snapshot no longer alias/mutate the source world.
|
|
166
|
+
- Fixed: the delta serializer's `capture()`/`apply()` and `deserializeWorld` now honour the documented `components` allowlist option instead of silently ignoring it.
|
|
167
|
+
- Fixed: component/query/world registries are now shared across duplicate ESM+CJS copies of the package (via a `globalThis` key) instead of colliding on the same auto-incrementing ids.
|
|
168
|
+
- Fixed: `fromJSON`/`deserializeWorld` restore `maxEntities`, `indexBits`, and `generationBits` from the snapshot instead of falling back to defaults, so a large or non-default-layout world round-trips without hitting a bogus `maxEntities` cap.
|
|
169
|
+
- Fixed: the fixed-timestep loop now ends a tick chain as soon as it is stopped or restarted — even from inside `onUpdate`/`onRender` — so it no longer keeps stepping, renders after `stop()`, or runs two chains concurrently.
|
|
170
|
+
- Fixed: reactive (enter/exit) queries are now indexed per world instead of scanning a module-level cache on every structural change, which previously registered foreign components (and could exhaust `maxComponents`) in unrelated worlds.
|
|
171
|
+
- Fixed: `observe()` on an `enterQuery`/`exitQuery` now registers the query directly instead of forcing registration via `runQuery`, which drained the (not-yet-registered) reactive buffer as a no-op and left the observer permanently inert.
|
|
172
|
+
- Fixed: `iterQuery`/`forEachEntity`/`forEachEntityIndexed` now drain their reactive buffer up front, so breaking out of the loop early or a callback throwing partway through no longer re-delivers already-seen entities on the next read.
|
|
173
|
+
- Fixed: the delta serializer's `apply()` rejects a non-integer `eid` instead of corrupting entity-slot allocation (a live slot pushed onto the freeList, a non-integer allocation frontier).
|
|
174
|
+
- Fixed: the fixed-timestep loop clamps `dtMs` to non-negative, so a first tick timestamp earlier than `start()`'s sample can no longer drive the accumulator (and `onRender`'s alpha) negative.
|
|
175
|
+
- Fixed: `createEntity`'s `maxEntities` guard now throws `EcsError` (matching the documented behaviour) instead of a plain `Error`.
|
|
176
|
+
- Fixed: `enterQuery` / `exitQuery` / `observe` now check their query argument like `runQuery`: a raw component array works, and other non-Query input throws the documented `TypeError` instead of an internal `TypeError` (`enterQuery` / `exitQuery` also cached a broken reactive query that later calls returned silently).
|
|
177
|
+
- Fixed: `addComponent` builds a new AoS instance before it moves the entity to its new archetype, so a factory that throws leaves the entity unchanged instead of half-added (moved, but never announced to observers or reactive queries).
|
|
178
|
+
- Fixed: a missing world handle, component handle, snapshot, worker meta or delta byte array now throws `EcsError` instead of a bare `TypeError` from property access.
|
|
179
|
+
- Fixed: `deserializeWorld` applied the `components` allowlist to the snapshot's source-process component ids; `fromJSON` / `deserializeWorld` now apply it to the resolved local components.
|
|
180
|
+
- Fixed: package.json `exports` now nest `types` under `import` and `require` for every subpath, with `require.types` pointing at the `.d.cts` file, so CommonJS consumers on `node16`/`nodenext` module resolution get the CommonJS declarations; `verify-exports` walks nested conditions.
|
|
181
|
+
- Docs: relation-destroy cost is documented as `O(incoming + data sources + outgoing sources)` (was understated as `O(incoming)` alone).
|
|
182
|
+
- Docs: `deref`/`aliveRef` are documented as "never throws for a live world" (was an unqualified "never throws") — both throw `EcsError` once the world has been disposed.
|
|
183
|
+
- Docs: the README / README_ZHTW Quick Start no longer corrupts the world: it did `pos.x += vel.x` on the column objects returned by `getComponent`, which replaced the `Position.x` column with a string; it now indexes the columns with `forEachEntityIndexed`'s `i` over a `defineQuery` query (the TypeScript signature does not accept a raw array).
|
|
184
|
+
- Docs: README / README_ZHTW gain Snapshots, Relations and Errors sections; STABILITY gains a Behavioral Contract section (the ai*js re-entrancy clause for observer dispatch, argument validation, read-only mutators, relation liveness, snapshot format 2); `docs/MIGRATION.md` / `MIGRATION_ZHTW.md` gain "0.5.x -> 0.6.0 snapshots".
|
|
185
|
+
- Docs: README / STABILITY no longer describe reactive-query tracking as a module-level cache scan; it is a per-component index.
|
|
186
|
+
- Docs: `api.json` is updated for 0.6.0 signatures and throws, documents that the `defineObjectComponent` factory runs once per entity on first add (not once at definition), and lists `DeserializeOptions.components`.
|
|
187
|
+
|
|
188
|
+
## [0.5.9] - 2026-06-29
|
|
189
|
+
|
|
190
|
+
- Fixed: `forEachEntity` / `forEachEntityIndexed` no longer cache the archetype's entity array, so an in-loop `createEntity`/`addComponent` that reallocates the iterated archetype can no longer yield `undefined` EntityIds or a bogus index `0`.
|
|
191
|
+
- Fixed: `resetWorld` now clears relation storage, so recycled entity slots no longer inherit stale relation edges/data.
|
|
192
|
+
- Docs: relation destroy is documented as `O(incoming)` (was stale `O(capacity)`).
|
|
102
193
|
|
|
103
194
|
## [0.5.8] - 2026-06-14
|
|
104
195
|
|
|
@@ -138,25 +229,36 @@ aiecsjs keeps the root ECS surface stable and treats subpaths as explicit public
|
|
|
138
229
|
| `aiecsjs/loop` | Stable utility | Loop helper only; scheduler policy remains app-owned. |
|
|
139
230
|
| `aiecsjs/commands` | Stable utility | Command buffers for deferred structural mutations. |
|
|
140
231
|
| `aiecsjs/observers` | Stable utility | Add/remove/set observer helpers. |
|
|
141
|
-
| `aiecsjs/serialize` | Stable utility | Binary and JSON snapshots with capacity clamps. |
|
|
232
|
+
| `aiecsjs/serialize` | Stable utility | Binary and JSON snapshots with capacity clamps; format 2; keyed components; mismatch rejected. |
|
|
142
233
|
| `aiecsjs/worker` | Experimental adapter | Environment-dependent SAB/transfer helpers. |
|
|
143
|
-
| `aiecsjs/relations` | Stable | Relations and `ChildOf`; destroy cleanup cost remains documented. |
|
|
234
|
+
| `aiecsjs/relations` | Stable | Relations and `ChildOf`; `addRelation` throws `EcsError` for a dead source or target, mirroring `addComponent`; destroy cleanup cost remains documented. |
|
|
144
235
|
| `aiecsjs/internal/*` | Private | No compatibility guarantee. |
|
|
145
236
|
|
|
237
|
+
## Behavioral Contract
|
|
238
|
+
|
|
239
|
+
- Re-entrancy (ai*js rule for pure fan-out emitters): observer dispatch (`onAdd`, `onRemove`, `onSet`, `observe`) is synchronous and depth-first. A structural change made inside a handler, with its own notifications, runs to completion before the outer dispatch resumes; the outer dispatch keeps iterating its pre-taken snapshot and skips observers removed meanwhile; nested dispatch is never rejected or queued. aiecsjs has no `once` observers.
|
|
240
|
+
- Structural changes are applied at once, never queued. A handler that destroys the entity being destroyed, or removes the component being removed, makes the nested call a no-op and the outer call finishes. `flush()` on a buffer that is already flushing returns immediately; ops queued during a flush run in later rounds of that flush, in queue order.
|
|
241
|
+
- Misuse throws `EcsError` (message `aiecsjs: <subject> must be <constraint>` or `aiecsjs: <operation> on dead entity <eid>`) before any change is made: a non-integer `initialCapacity` / `maxEntities` / `indexBits` / `generationBits`; an empty, non-string or duplicate component `key`; a non-function observer handler, `forEachEntity` / `forEachEntityIndexed` / `withCommandBuffer` callback, `pipe` system or AoS factory; an AoS factory that returns `null` / `undefined`; a value that is not a relation handle; a missing world or component handle.
|
|
242
|
+
- `defineComponent` field-declaration errors and non-Query input to the query functions throw `TypeError`. `aiecsjs/loop` exports no error class: `createLoop` throws `TypeError` for a missing options object or a non-function `onUpdate` / `onRender` and `RangeError` for a `fixed` that is not a finite number > 0 or a `maxSubSteps` that is not a finite number >= 1.
|
|
243
|
+
- A read-only world (`attachWorld(buffer, { readOnly: true })`) rejects every mutator with `EcsError`: `createEntity`, `destroyEntity`, `addComponent`, `removeComponent`, `setComponent`, `resetWorld`, `addRelation`, `removeRelation` and delta `apply()`.
|
|
244
|
+
- `addRelation` throws `EcsError` for a dead source or target; `removeRelation` is lenient. `destroyEntity` and `resetWorld` drop the edges of the entities they remove, so relation storage never holds an edge for a dead entity.
|
|
245
|
+
- Snapshots are format 2: `toJSON`, `serializeWorld` and delta `capture()` write `formatVersion: 2` and a table of every referenced component (`id`, `key`, `kind`, SoA `fields`). `fromJSON`, `deserializeWorld`, delta `apply()`, `adoptSnapshot` and `attachWorld` resolve every component (by `key`, by `id` when keyless) before they create or write anything. An undefined component throws `EcsError` unless `onUnknownComponent: 'skip'`; a kind or SoA-field mismatch always throws. A snapshot of another format version (every 0.5.x snapshot) throws unless `onUnknownVersion: 'best-effort'`, which resolves by `id` with a kind check only.
|
|
246
|
+
|
|
146
247
|
## Behavioral Boundaries
|
|
147
248
|
|
|
148
249
|
- Entity ids are generational numeric ids. Use refs (`refOf`, `deref`, `aliveRef`) when storing ids across time.
|
|
149
250
|
- Query iteration is synchronous and direct. Use command buffers for structural changes inside systems.
|
|
150
251
|
- Reactive query buffers must be drained by the caller.
|
|
151
252
|
- Serialization accepts trusted snapshots; hostile input is bounded but not a sandbox.
|
|
253
|
+
- `fromJSON` / `deserializeWorld` re-create entities in snapshot order with fresh ids; EntityIds stored inside component data are not remapped.
|
|
152
254
|
- No build-mode-gated runtime validation policy is promised.
|
|
153
255
|
- Worker support depends on `SharedArrayBuffer`, transfer support, and browser isolation policy.
|
|
154
256
|
|
|
155
257
|
## Current Caveats
|
|
156
258
|
|
|
157
|
-
-
|
|
158
|
-
- Exclusive relation cleanup
|
|
159
|
-
- Lint
|
|
259
|
+
- Queries are cached process-wide, and reactive (enter/exit) source queries are indexed process-wide by component: a structural change visits every such source that references the changed component, whichever world registered it.
|
|
260
|
+
- Exclusive relation cleanup avoids a full relation-capacity scan (via a reverse index it touches only `O(incoming)` exclusive edges), but it still walks every relation's `data` payload sources and `outgoing` (non-exclusive) edge lists on every destroy: `O(incoming + data sources + outgoing sources)` across all relations, even for entities with no relations.
|
|
261
|
+
- Lint reports `noExplicitAny` warnings, mostly test casts plus the public query callback types (typed per arity only in a future design).
|
|
160
262
|
|
|
161
263
|
---
|
|
162
264
|
|
package/llms.txt
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "aiecsjs",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "TypeScript-first archetype ECS with TypedArray SoA, SAB-ready snapshot transport, and AI-readable docs.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
@@ -8,39 +8,74 @@
|
|
|
8
8
|
"types": "./dist/index.d.ts",
|
|
9
9
|
"exports": {
|
|
10
10
|
".": {
|
|
11
|
-
"
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
"import": {
|
|
12
|
+
"types": "./dist/index.d.ts",
|
|
13
|
+
"default": "./dist/index.js"
|
|
14
|
+
},
|
|
15
|
+
"require": {
|
|
16
|
+
"types": "./dist/index.d.cts",
|
|
17
|
+
"default": "./dist/index.cjs"
|
|
18
|
+
}
|
|
14
19
|
},
|
|
15
20
|
"./loop": {
|
|
16
|
-
"
|
|
17
|
-
|
|
18
|
-
|
|
21
|
+
"import": {
|
|
22
|
+
"types": "./dist/loop.d.ts",
|
|
23
|
+
"default": "./dist/loop.js"
|
|
24
|
+
},
|
|
25
|
+
"require": {
|
|
26
|
+
"types": "./dist/loop.d.cts",
|
|
27
|
+
"default": "./dist/loop.cjs"
|
|
28
|
+
}
|
|
19
29
|
},
|
|
20
30
|
"./commands": {
|
|
21
|
-
"
|
|
22
|
-
|
|
23
|
-
|
|
31
|
+
"import": {
|
|
32
|
+
"types": "./dist/commands.d.ts",
|
|
33
|
+
"default": "./dist/commands.js"
|
|
34
|
+
},
|
|
35
|
+
"require": {
|
|
36
|
+
"types": "./dist/commands.d.cts",
|
|
37
|
+
"default": "./dist/commands.cjs"
|
|
38
|
+
}
|
|
24
39
|
},
|
|
25
40
|
"./observers": {
|
|
26
|
-
"
|
|
27
|
-
|
|
28
|
-
|
|
41
|
+
"import": {
|
|
42
|
+
"types": "./dist/observers.d.ts",
|
|
43
|
+
"default": "./dist/observers.js"
|
|
44
|
+
},
|
|
45
|
+
"require": {
|
|
46
|
+
"types": "./dist/observers.d.cts",
|
|
47
|
+
"default": "./dist/observers.cjs"
|
|
48
|
+
}
|
|
29
49
|
},
|
|
30
50
|
"./serialize": {
|
|
31
|
-
"
|
|
32
|
-
|
|
33
|
-
|
|
51
|
+
"import": {
|
|
52
|
+
"types": "./dist/serialize.d.ts",
|
|
53
|
+
"default": "./dist/serialize.js"
|
|
54
|
+
},
|
|
55
|
+
"require": {
|
|
56
|
+
"types": "./dist/serialize.d.cts",
|
|
57
|
+
"default": "./dist/serialize.cjs"
|
|
58
|
+
}
|
|
34
59
|
},
|
|
35
60
|
"./worker": {
|
|
36
|
-
"
|
|
37
|
-
|
|
38
|
-
|
|
61
|
+
"import": {
|
|
62
|
+
"types": "./dist/worker.d.ts",
|
|
63
|
+
"default": "./dist/worker.js"
|
|
64
|
+
},
|
|
65
|
+
"require": {
|
|
66
|
+
"types": "./dist/worker.d.cts",
|
|
67
|
+
"default": "./dist/worker.cjs"
|
|
68
|
+
}
|
|
39
69
|
},
|
|
40
70
|
"./relations": {
|
|
41
|
-
"
|
|
42
|
-
|
|
43
|
-
|
|
71
|
+
"import": {
|
|
72
|
+
"types": "./dist/relations.d.ts",
|
|
73
|
+
"default": "./dist/relations.js"
|
|
74
|
+
},
|
|
75
|
+
"require": {
|
|
76
|
+
"types": "./dist/relations.d.cts",
|
|
77
|
+
"default": "./dist/relations.cjs"
|
|
78
|
+
}
|
|
44
79
|
},
|
|
45
80
|
"./package.json": "./package.json"
|
|
46
81
|
},
|
package/dist/chunk-3FV6UMUS.cjs
DELETED
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
'use strict';var chunkZIZSWIHW_cjs=require('./chunk-ZIZSWIHW.cjs');var p="AIEC",b=1;function Q(n,o){let e=B(n);return o?.components&&(e.entities=e.entities.map(t=>({eid:t.eid,components:t.components.filter(i=>o.components.some(c=>c.__id===i.id))}))),D(e)}function Z(n,o){let e=x(n,o);return T(e)}function B(n){let o=chunkZIZSWIHW_cjs.j(n),e=[];for(let t=1;t<o.capacity;t++){let i=o.entityArchetype[t]??0;if(i===0)continue;let c=o.archetypes[i];if(!c)continue;let r=o.generations[t]??0,a=chunkZIZSWIHW_cjs.s(t,r,o.options);if(!c.entityRow.has(a))continue;let s=o.options.maskWordCount,f=t*s,l=[];for(let d=0;d<s;d++){let m=o.entityMask[f+d]??0;for(;m!==0;){let M=m&-m,_=(d<<5)+(31-Math.clz32(M)),h=o.componentInfoByBit[_];if(h){let S=o.componentStorageByBit[_],w=null;if(h.kind==="soa"&&S?.soa){let y={};for(let u of h.fields){let g=S.soa[u.name];if(g)if(u.vectorLen===1)y[u.name]=g[t];else {let v=[],N=t*u.vectorLen;for(let C=0;C<u.vectorLen;C++)v.push(g[N+C]??0);y[u.name]=v;}}w=y;}else h.kind==="aos"&&S?.aos?w=S.aos[t]??null:w=true;l.push({kind:h.kind,id:h.id,data:w});}m&=m-1;}}e.push({eid:t,components:l});}return {version:o.version,capacity:o.capacity,entities:e}}var R=1024;function J(n,o){let e=Math.max(R,o+1);return typeof n!="number"||!Number.isFinite(n)||n<=0?e:Math.min(Math.floor(n),e)}function T(n){let o=J(n.capacity,n.entities.length),e=chunkZIZSWIHW_cjs.l({initialCapacity:o}),t=new Map;for(let i of n.entities){let c=chunkZIZSWIHW_cjs.v(e);t.set(i.eid,c);}for(let i of n.entities){let c=t.get(i.eid);for(let r of i.components){let a=chunkZIZSWIHW_cjs.R(r.id);if(!a)continue;let s=A(a);s&&chunkZIZSWIHW_cjs.K(e,c,s,r.data);}}return e}function A(n){if(n.kind==="soa")return {__kind:"soa",__id:n.id,__schema:n.schema??{}};if(n.kind==="aos"){let o=n.factory??(()=>({}));return {__kind:"aos",__id:n.id,__factory:o}}return {__kind:"tag",__id:n.id}}function D(n){let o=JSON.stringify(n),e=new TextEncoder().encode(o),t=new TextEncoder().encode(chunkZIZSWIHW_cjs.a),c=12+t.length+4+e.length,r=new Uint8Array(c),a=new DataView(r.buffer),s=0;return r[s++]=p.charCodeAt(0),r[s++]=p.charCodeAt(1),r[s++]=p.charCodeAt(2),r[s++]=p.charCodeAt(3),a.setUint32(s,b,true),s+=4,a.setUint32(s,t.length,true),s+=4,r.set(t,s),s+=t.length,a.setUint32(s,e.length,true),s+=4,r.set(e,s),r}function x(n,o){if(n.length<12)throw new Error("aiecsjs: bytes too short to be a valid snapshot");let e=new DataView(n.buffer,n.byteOffset,n.byteLength);if(n[0]!==p.charCodeAt(0)||n[1]!==p.charCodeAt(1)||n[2]!==p.charCodeAt(2)||n[3]!==p.charCodeAt(3))throw new Error("aiecsjs: invalid magic bytes");let t=4,i=e.getUint32(t,true);t+=4;let c=o?.onUnknownVersion??"throw";if(i!==b&&c==="throw")throw new Error(`aiecsjs: format version ${i} not supported`);let r=64*1024*1024;if(t+4>n.length)throw new Error("aiecsjs: snapshot truncated before verLen");let a=e.getUint32(t,true);if(t+=4,a>r||t+a>n.length)throw new Error(`aiecsjs: snapshot verLen=${a} out of bounds`);if(t+=a,t+4>n.length)throw new Error("aiecsjs: snapshot truncated before jsonLen");let s=e.getUint32(t,true);if(t+=4,s>r||t+s>n.length)throw new Error(`aiecsjs: snapshot jsonLen=${s} out of bounds`);let f=n.subarray(t,t+s),l=new TextDecoder().decode(f);try{return JSON.parse(l)}catch(d){throw new Error("aiecsjs: snapshot body is not valid JSON",{cause:d})}}function tt(n,o){let e={world:n,components:o?.components??chunkZIZSWIHW_cjs.S().map(t=>A(t)).filter(Boolean),lastSnapshot:null};return {capture(){let t=B(e.world),i;return e.lastSnapshot?i=V(e.lastSnapshot,t):i=t,e.lastSnapshot=t,D(i)},apply(t,i){let c=x(i),r=chunkZIZSWIHW_cjs.j(t);for(let a of c.entities){if(a.eid<=0||a.eid>=r.options.maxEntities)continue;let s=chunkZIZSWIHW_cjs.w(r,a.eid);for(let f of a.components){let l=chunkZIZSWIHW_cjs.R(f.id);if(!l)continue;let d=A(l);d&&chunkZIZSWIHW_cjs.K(t,s,d,f.data);}}},reset(){e.lastSnapshot=null;}}}function V(n,o){let e=new Map(n.entities.map(i=>[i.eid,i])),t=[];for(let i of o.entities){let c=e.get(i.eid);if(!c){t.push(i);continue}let r=JSON.stringify(c.components),a=JSON.stringify(i.components);r!==a&&t.push(i);}return {version:o.version,capacity:o.capacity,entities:t}}exports.a=Q;exports.b=Z;exports.c=B;exports.d=T;exports.e=tt;//# sourceMappingURL=chunk-3FV6UMUS.cjs.map
|
|
2
|
-
//# sourceMappingURL=chunk-3FV6UMUS.cjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/serialize.ts"],"names":["MAGIC","FORMAT_VERSION","serializeWorld","world","options","snapshot","toJSON","e","c","comp","packBinary","deserializeWorld","bytes","unpackBinary","fromJSON","state","getWorldState","entities","idx","archId","arch","gen","packedEid","packEid","w","base","components","wi","word","lsb","bit","info","storage","data","obj","f","col","arr","baseI","i","RESTORE_CAPACITY_FLOOR","clampRestoreCapacity","rawCapacity","entityCount","needed","initialCapacity","createWorld","eidMap","eid","createEntity","getComponentByInternalId","handle","getComponentHandle","addComponent","factory","json","jsonBytes","versionBytes","VERSION","total","out","view","off","formatVersion","onUnknown","MAX_FIELD_LEN","verLen","jsonLen","cause","createDeltaSerializer","listAllComponents","current","delta","computeDelta","targetWorld","deltaBytes","targetState","ensureEntityAtSlot","prev","curr","prevByEid","changed","prevE","prevSig","currSig"],"mappings":"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","file":"chunk-3FV6UMUS.cjs","sourcesContent":["// aiecsjs/serialize — binary, JSON, and delta serializers.\n\nimport { testBit } from './internal/bitmask.js'\nimport {\n addComponent,\n defineComponent,\n defineObjectComponent,\n defineTag,\n getComponentByInternalId,\n getComponentInfo,\n listAllComponents,\n} from './internal/component.js'\nimport { createEntity, destroyEntity, ensureEntityAtSlot, packEid } from './internal/entity.js'\nimport type {\n ComponentInfo,\n ComponentInit,\n ComponentLike,\n DeltaSerializer,\n DeserializeOptions,\n EntityId,\n SerializeOptions,\n World,\n WorldSnapshot,\n} from './internal/types.js'\nimport { createWorld, getWorldState } from './internal/world.js'\nimport { VERSION } from './version.js'\n\nconst MAGIC = 'AIEC'\nconst FORMAT_VERSION = 1\n\nexport function serializeWorld(world: World, options?: SerializeOptions): Uint8Array {\n const snapshot = toJSON(world)\n if (options?.components) {\n snapshot.entities = snapshot.entities.map((e) => ({\n eid: e.eid,\n components: e.components.filter((c) =>\n options.components!.some((comp) => comp.__id === c.id),\n ),\n }))\n }\n return packBinary(snapshot)\n}\n\nexport function deserializeWorld(bytes: Uint8Array, options?: DeserializeOptions): World {\n const snapshot = unpackBinary(bytes, options)\n return fromJSON(snapshot)\n}\n\n/**\n * Serialize a world snapshot to a plain JSON-compatible object.\n *\n * Note: `EntityRef` is in-memory only — not preserved across serialize/deserialize.\n * Generation counters reset on world load. Stale refs from before serialization\n * will deref to null after loading the snapshot into a new world.\n */\nexport function toJSON(world: World): WorldSnapshot {\n const state = getWorldState(world)\n const entities: WorldSnapshot['entities'] = []\n // Iterate by raw slot index; snapshot stores raw idx in the `eid` field\n // (wire format unchanged — idx is used for load-side entity re-creation).\n for (let idx = 1; idx < state.capacity; idx++) {\n const archId = state.entityArchetype[idx] ?? 0\n if (archId === 0) continue // slot unused\n\n const arch = state.archetypes[archId]\n if (!arch) continue\n\n // Build the packed eid from idx + current generation to do alive check\n const gen = state.generations[idx] ?? 0\n const packedEid = packEid(idx, gen, state.options)\n if (!arch.entityRow.has(packedEid)) continue\n\n const w = state.options.maskWordCount\n const base = idx * w\n const components: WorldSnapshot['entities'][0]['components'] = []\n for (let wi = 0; wi < w; wi++) {\n let word = state.entityMask[base + wi] ?? 0\n while (word !== 0) {\n const lsb = word & -word\n const bit = (wi << 5) + (31 - Math.clz32(lsb))\n const info = state.componentInfoByBit[bit]\n if (info) {\n const storage = state.componentStorageByBit[bit]\n let data: unknown = null\n if (info.kind === 'soa' && storage?.soa) {\n const obj: Record<string, unknown> = {}\n for (const f of info.fields) {\n const col = storage.soa[f.name]\n if (!col) continue\n if (f.vectorLen === 1) {\n obj[f.name] = col[idx]\n } else {\n const arr: number[] = []\n const baseI = idx * f.vectorLen\n for (let i = 0; i < f.vectorLen; i++) arr.push(col[baseI + i] ?? 0)\n obj[f.name] = arr\n }\n }\n data = obj\n } else if (info.kind === 'aos' && storage?.aos) {\n data = storage.aos[idx] ?? null\n } else {\n data = true\n }\n components.push({ kind: info.kind, id: info.id, data })\n }\n word &= word - 1\n }\n }\n // Wire format stores raw idx (not packed) for cross-session portability\n entities.push({ eid: idx, components })\n }\n return {\n version: state.version,\n capacity: state.capacity,\n entities,\n }\n}\n\n// Default initial-capacity floor for a restored world (matches createWorld's\n// own default). Keeps the common round-trip from needlessly shrinking while\n// staying a trivial allocation (~36 KB of index arrays at 1024 slots).\nconst RESTORE_CAPACITY_FLOOR = 1024\n\n// SECURITY (ECS-S-01): the snapshot `capacity` field is attacker-controlled on\n// any untrusted-load path (localStorage, network — both documented flows for the\n// stable deserializeWorld). createWorld only clamps to 1<<indexBits (16,777,216),\n// so an inflated value forces a near-600 MB TypedArray allocation from a tiny\n// payload — a browser-tab OOM DoS. Clamp the *starting* capacity to the real\n// entity count (fromJSON re-creates entities via createEntity, which grows the\n// world on demand, so a tight initial hint never loses data). A garbage/missing\n// value falls back to the count too.\nfunction clampRestoreCapacity(rawCapacity: unknown, entityCount: number): number {\n const needed = Math.max(RESTORE_CAPACITY_FLOOR, entityCount + 1)\n if (typeof rawCapacity !== 'number' || !Number.isFinite(rawCapacity) || rawCapacity <= 0) {\n return needed\n }\n return Math.min(Math.floor(rawCapacity), needed)\n}\n\nexport function fromJSON(snapshot: WorldSnapshot): World {\n const initialCapacity = clampRestoreCapacity(snapshot.capacity, snapshot.entities.length)\n const world = createWorld({ initialCapacity })\n const eidMap = new Map<number, EntityId>()\n for (const e of snapshot.entities) {\n const eid = createEntity(world)\n eidMap.set(e.eid, eid)\n }\n for (const e of snapshot.entities) {\n const eid = eidMap.get(e.eid)!\n for (const comp of e.components) {\n const info = getComponentByInternalId(comp.id)\n if (!info) {\n // Component missing — silently skip; future version may throw based on options\n continue\n }\n const handle = getComponentHandle(info)\n if (handle) {\n addComponent(world, eid, handle, comp.data as ComponentInit<ComponentLike>)\n }\n }\n }\n return world\n}\n\n// Reconstruct a component handle from its ComponentInfo. Since defineComponent\n// returns plain handles { __kind, __id, __schema }, we can synthesize them.\nfunction getComponentHandle(info: ComponentInfo): ComponentLike | null {\n if (info.kind === 'soa') {\n return { __kind: 'soa', __id: info.id, __schema: info.schema ?? {} } as ComponentLike\n }\n if (info.kind === 'aos') {\n const factory = info.factory ?? (() => ({}))\n return { __kind: 'aos', __id: info.id, __factory: factory } as ComponentLike\n }\n return { __kind: 'tag', __id: info.id } as ComponentLike\n}\n\n// --- Binary packing (wrapped JSON for 0.1) ---\n\nfunction packBinary(snapshot: WorldSnapshot): Uint8Array {\n const json = JSON.stringify(snapshot)\n const jsonBytes = new TextEncoder().encode(json)\n const versionBytes = new TextEncoder().encode(VERSION)\n const headerSize = 4 + 4 + 4 + versionBytes.length + 4\n const total = headerSize + jsonBytes.length\n const out = new Uint8Array(total)\n const view = new DataView(out.buffer)\n let off = 0\n out[off++] = MAGIC.charCodeAt(0)\n out[off++] = MAGIC.charCodeAt(1)\n out[off++] = MAGIC.charCodeAt(2)\n out[off++] = MAGIC.charCodeAt(3)\n view.setUint32(off, FORMAT_VERSION, true)\n off += 4\n view.setUint32(off, versionBytes.length, true)\n off += 4\n out.set(versionBytes, off)\n off += versionBytes.length\n view.setUint32(off, jsonBytes.length, true)\n off += 4\n out.set(jsonBytes, off)\n return out\n}\n\nfunction unpackBinary(bytes: Uint8Array, options?: DeserializeOptions): WorldSnapshot {\n if (bytes.length < 12) throw new Error('aiecsjs: bytes too short to be a valid snapshot')\n const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength)\n if (\n bytes[0] !== MAGIC.charCodeAt(0) ||\n bytes[1] !== MAGIC.charCodeAt(1) ||\n bytes[2] !== MAGIC.charCodeAt(2) ||\n bytes[3] !== MAGIC.charCodeAt(3)\n ) {\n throw new Error('aiecsjs: invalid magic bytes')\n }\n let off = 4\n const formatVersion = view.getUint32(off, true)\n off += 4\n const onUnknown = options?.onUnknownVersion ?? 'throw'\n if (formatVersion !== FORMAT_VERSION && onUnknown === 'throw') {\n throw new Error(`aiecsjs: format version ${formatVersion} not supported`)\n }\n\n // SECURITY: explicit bounds checks on every length field. DataView itself\n // throws on out-of-range reads, but an attacker who controls the bytes can\n // still craft a `verLen` that skips past data of their choosing — we make\n // each step's invariant explicit and impose a sane cap to short-circuit\n // pathological payloads early.\n const MAX_FIELD_LEN = 64 * 1024 * 1024 // 64 MiB\n if (off + 4 > bytes.length) {\n throw new Error('aiecsjs: snapshot truncated before verLen')\n }\n const verLen = view.getUint32(off, true)\n off += 4\n if (verLen > MAX_FIELD_LEN || off + verLen > bytes.length) {\n throw new Error(`aiecsjs: snapshot verLen=${verLen} out of bounds`)\n }\n off += verLen // skip the aiecsjs version string\n\n if (off + 4 > bytes.length) {\n throw new Error('aiecsjs: snapshot truncated before jsonLen')\n }\n const jsonLen = view.getUint32(off, true)\n off += 4\n if (jsonLen > MAX_FIELD_LEN || off + jsonLen > bytes.length) {\n throw new Error(`aiecsjs: snapshot jsonLen=${jsonLen} out of bounds`)\n }\n const jsonBytes = bytes.subarray(off, off + jsonLen)\n const json = new TextDecoder().decode(jsonBytes)\n // Wrap the parse so a malformed body (e.g. a truncated/garbled payload reached\n // under onUnknownVersion:'best-effort') surfaces a namespaced `aiecsjs:` error\n // instead of leaking a raw SyntaxError — consistent with the rest of the module.\n // Bounds checks above already guarantee `json` covers exactly the declared body.\n try {\n return JSON.parse(json) as WorldSnapshot\n } catch (cause) {\n throw new Error('aiecsjs: snapshot body is not valid JSON', { cause })\n }\n}\n\n// --- Delta serializer ---\n\ninterface DeltaState {\n world: World\n components: ComponentLike[]\n lastSnapshot: WorldSnapshot | null\n}\n\nexport function createDeltaSerializer(world: World, options?: SerializeOptions): DeltaSerializer {\n const state: DeltaState = {\n world,\n components:\n options?.components ??\n listAllComponents()\n .map((i) => getComponentHandle(i)!)\n .filter(Boolean),\n lastSnapshot: null,\n }\n return {\n capture(): Uint8Array {\n const current = toJSON(state.world)\n let delta: WorldSnapshot\n if (!state.lastSnapshot) {\n delta = current\n } else {\n // Compute simple delta: entities with changed components\n delta = computeDelta(state.lastSnapshot, current)\n }\n state.lastSnapshot = current\n return packBinary(delta)\n },\n apply(targetWorld: World, deltaBytes: Uint8Array): void {\n const snapshot = unpackBinary(deltaBytes)\n // Materialise each snapshot entity at the SAME slot index the source used\n // (the wire stores raw slot indices in `eid`). ensureEntityAtSlot reuses a\n // live slot, reclaims a freed one, or advances the frontier — so apply() is\n // sound on a non-pristine / independently-churned replica (it uses the\n // slot's CURRENT generation, never gen=0) and never spawns phantom padding\n // entities for holes in the source's slot range.\n //\n // CAVEAT: deltas carry added/changed entities only (see computeDelta) —\n // entity REMOVALS are not represented, so a replica is not pruned when the\n // source destroys an entity, and a component removed on the source is not\n // removed on the replica. apply() is additive/updating.\n const targetState = getWorldState(targetWorld)\n for (const e of snapshot.entities) {\n if (e.eid <= 0 || e.eid >= targetState.options.maxEntities) continue\n const eid = ensureEntityAtSlot(targetState, e.eid)\n for (const comp of e.components) {\n const info = getComponentByInternalId(comp.id)\n if (!info) continue\n const handle = getComponentHandle(info)\n if (handle)\n addComponent(targetWorld, eid, handle, comp.data as ComponentInit<ComponentLike>)\n }\n }\n },\n reset(): void {\n state.lastSnapshot = null\n },\n }\n}\n\nfunction computeDelta(prev: WorldSnapshot, curr: WorldSnapshot): WorldSnapshot {\n const prevByEid = new Map(prev.entities.map((e) => [e.eid, e]))\n const changed: WorldSnapshot['entities'] = []\n for (const e of curr.entities) {\n const prevE = prevByEid.get(e.eid)\n if (!prevE) {\n changed.push(e)\n continue\n }\n const prevSig = JSON.stringify(prevE.components)\n const currSig = JSON.stringify(e.components)\n if (prevSig !== currSig) changed.push(e)\n }\n return { version: curr.version, capacity: curr.capacity, entities: changed }\n}\n"]}
|
package/dist/chunk-3ZLNR4JX.cjs
DELETED
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
'use strict';var chunkZIZSWIHW_cjs=require('./chunk-ZIZSWIHW.cjs');var E=1,f=new Map;function A(n){let e=(n.all??[]).map(o=>o.__id).sort((o,i)=>o-i).join("-"),t=(n.any??[]).map(o=>o.__id).sort((o,i)=>o-i).join("-"),r=(n.none??[]).map(o=>o.__id).sort((o,i)=>o-i).join("-");return `A${e}|Y${t}|N${r}`}function T(n){let e=Array.isArray(n)?{all:n}:n;for(let i of [...e.all??[],...e.any??[],...e.none??[]])if(!i||typeof i!="object"||typeof i.__id!="number")throw new TypeError("aiecsjs: defineQuery received a non-component value");let t=A(e),r=f.get(t);if(r)return r;let o={id:E++,mask:[],all:(e.all??[]).map(i=>i.__id),any:(e.any??[]).map(i=>i.__id),none:(e.none??[]).map(i=>i.__id),columnViewCache:[...e.all??[],...e.any??[]],reactiveKind:"normal",sourceQueryId:-1,sourceQuery:null};return f.set(t,o),o}function $(n){let e=n,t=`enter:${e.id}`,r=f.get(t);if(r)return r;let o={id:E++,mask:[],all:e.all,any:e.any,none:e.none,columnViewCache:e.columnViewCache,reactiveKind:"enter",sourceQueryId:e.id,sourceQuery:e};return f.set(t,o),o}function D(n){let e=n,t=`exit:${e.id}`,r=f.get(t);if(r)return r;let o={id:E++,mask:[],all:e.all,any:e.any,none:e.none,columnViewCache:e.columnViewCache,reactiveKind:"exit",sourceQueryId:e.id,sourceQuery:e};return f.set(t,o),o}function p(n,e){if(n.queries[e.id]===e&&n.queryMasks.has(e.id))return;let t=n.options.maskWordCount,r=chunkZIZSWIHW_cjs.b(t),o=chunkZIZSWIHW_cjs.b(t),i=chunkZIZSWIHW_cjs.b(t);for(let a of e.all){let u=C(a),d=chunkZIZSWIHW_cjs.q(n,u);chunkZIZSWIHW_cjs.c(r,d);}for(let a of e.any){let u=C(a),d=chunkZIZSWIHW_cjs.q(n,u);chunkZIZSWIHW_cjs.c(o,d);}for(let a of e.none){let u=C(a),d=chunkZIZSWIHW_cjs.q(n,u);chunkZIZSWIHW_cjs.c(i,d);}let c={withMask:r,anyMask:o,noneMask:i,anyHasBits:!chunkZIZSWIHW_cjs.d(o)};n.queryMasks.set(e.id,c),n.queries[e.id]=e,n.queryArchetypeCache[e.id]=null,n.queryArchetypeStamp[e.id]=-1;let s=[...chunkZIZSWIHW_cjs.f(r),...chunkZIZSWIHW_cjs.f(o),...chunkZIZSWIHW_cjs.f(i)];for(let a of s){let u=n.bitToQueries.get(a);u||(u=new Set,n.bitToQueries.set(a,u)),u.add(e.id);}e.reactiveKind!=="normal"&&(n.reactiveBuffers.has(e.id)||n.reactiveBuffers.set(e.id,{entered:[],exited:[]}),e.sourceQuery&&p(n,e.sourceQuery));}function m(n,e){if(p(n,e),n.queryArchetypeCache[e.id]&&n.queryArchetypeStamp[e.id]===n.queryVersion)return n.queryArchetypeCache[e.id];let t=n.queryMasks.get(e.id),r=n.options.maskWordCount,o=[];for(let i=0;i<n.archetypes.length;i++){let c=n.archetypes[i];chunkZIZSWIHW_cjs.e(c.mask,t.withMask,t.anyMask,t.noneMask,t.anyHasBits,r)&&o.push(i);}return n.queryArchetypeCache[e.id]=o,n.queryArchetypeStamp[e.id]=n.queryVersion,o}function H(n,e){let t=chunkZIZSWIHW_cjs.j(n),o=m(t,e),i=[];for(let c of o){let s=t.archetypes[c];i.push({id:s.id,mask:Array.from(s.mask),size:s.size});}return i}function L(n,e){let t=chunkZIZSWIHW_cjs.j(n),r=e,o=[];if(r.reactiveKind==="enter"){let c=t.reactiveBuffers.get(r.id);if(c){for(let s of c.entered)o.push(s);c.entered.length=0;}return o}if(r.reactiveKind==="exit"){let c=t.reactiveBuffers.get(r.id);if(c){for(let s of c.exited)o.push(s);c.exited.length=0;}return o}let i=m(t,r);for(let c of i){let s=t.archetypes[c];for(let a=0;a<s.size;a++)o.push(s.entities[a]);}return o}function*F(n,e){let t=chunkZIZSWIHW_cjs.j(n),r=e;if(r.reactiveKind!=="normal"){let i=t.reactiveBuffers.get(r.id);if(!i)return;let c=r.reactiveKind==="enter"?i.entered:i.exited;for(let s of c)yield s;c.length=0;return}let o=m(t,r);for(let i of o){let c=t.archetypes[i];for(let s=0;s<c.size;s++)yield c.entities[s];}}function O(n,e,t){let r=chunkZIZSWIHW_cjs.j(n),o=e;if(o.reactiveKind!=="normal"){let s=r.reactiveBuffers.get(o.id);if(!s)return;let a=o.reactiveKind==="enter"?s.entered:s.exited;if(a.length===0)return;let u=g(r,o);for(let d=0;d<a.length;d++){let y=a[d];w(t,y,u);}a.length=0;return}p(r,o);let i=m(r,o),c=g(r,o);for(let s of i){let a=r.archetypes[s],u=a.entities;for(let d=0;d<a.size;d++)w(t,u[d],c);}}function w(n,e,t){switch(t.length){case 0:n(e);break;case 1:n(e,t[0]);break;case 2:n(e,t[0],t[1]);break;case 3:n(e,t[0],t[1],t[2]);break;case 4:n(e,t[0],t[1],t[2],t[3]);break;case 5:n(e,t[0],t[1],t[2],t[3],t[4]);break;default:n(e,...t);}}function G(n,e,t){let r=chunkZIZSWIHW_cjs.j(n),o=e,i=r.options.indexMask;if(o.reactiveKind!=="normal"){let a=r.reactiveBuffers.get(o.id);if(!a)return;let u=o.reactiveKind==="enter"?a.entered:a.exited;if(u.length===0)return;let d=g(r,o);for(let y=0;y<u.length;y++){let h=u[y];W(t,h,h&i,d);}u.length=0;return}p(r,o);let c=m(r,o),s=g(r,o);for(let a of c){let u=r.archetypes[a],d=u.entities;for(let y=0;y<u.size;y++){let h=d[y];W(t,h,h&i,s);}}}function W(n,e,t,r){switch(r.length){case 0:n(e,t);break;case 1:n(e,t,r[0]);break;case 2:n(e,t,r[0],r[1]);break;case 3:n(e,t,r[0],r[1],r[2]);break;case 4:n(e,t,r[0],r[1],r[2],r[3]);break;case 5:n(e,t,r[0],r[1],r[2],r[3],r[4]);break;default:n(e,t,...r);}}function g(n,e){let t=[];for(let r of e.columnViewCache){let o=chunkZIZSWIHW_cjs.J(r),i=n.componentBitFor.get(o.id);if(i===void 0){t.push(void 0);continue}let c=n.componentStorageByBit[i];if(!c){t.push(void 0);continue}c.kind==="soa"?t.push(c.soa):c.kind==="aos"?t.push(c.aos):t.push(true);}return t}function N(n,e,t,r,o){for(let s of f.values())s.reactiveKind!=="normal"&&s.sourceQuery&&n.queries[s.sourceQuery.id]!==s.sourceQuery&&p(n,s.sourceQuery);let i=n.bitToQueries.get(t);if(!i)return;let c=n.options.maskWordCount;for(let s of i){let a=n.queries[s];if(!a||a.reactiveKind!=="normal")continue;let u=n.queryMasks.get(s);if(!u)continue;let d=chunkZIZSWIHW_cjs.e(r,u.withMask,u.anyMask,u.noneMask,u.anyHasBits,c),y=chunkZIZSWIHW_cjs.e(o,u.withMask,u.anyMask,u.noneMask,u.anyHasBits,c);!d&&y?_(n,s,"enter",e):d&&!y&&_(n,s,"exit",e);}}function _(n,e,t,r){for(let o of f.values()){if(o.sourceQueryId!==e||o.reactiveKind!==t)continue;p(n,o);let i=K(n,o.id);t==="enter"?i.entered.push(r):i.exited.push(r);}}function K(n,e){let t=n.reactiveBuffers.get(e);return t||(t={entered:[],exited:[]},n.reactiveBuffers.set(e,t)),t}function C(n){let e=S(n);if(!e)throw new Error(`aiecsjs: component id ${n} not registered`);return e}var x=null;function U(n){x=n;}function S(n){return x?x(n):void 0}exports.a=T;exports.b=$;exports.c=D;exports.d=H;exports.e=L;exports.f=F;exports.g=O;exports.h=G;exports.i=N;exports.j=U;//# sourceMappingURL=chunk-3ZLNR4JX.cjs.map
|
|
2
|
-
//# sourceMappingURL=chunk-3ZLNR4JX.cjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/internal/query.ts"],"names":["nextQueryId","moduleQueryCache","descKey","d","all","c","a","b","any","none","defineQuery","arg","desc","key","cached","q","enterQuery","query","reactive","exitQuery","ensureQueryRegistered","state","ww","withMask","createMask","anyMask","noneMask","compId","info","getComponentInfoById","bit","getOrRegisterComponentBit","setBit","bundle","isMaskZero","involvedBits","listBits","s","getQueryArchetypes","words","list","arch","matches","queryArchetypes","world","getWorldState","ids","out","id","runQuery","buf","e","archIds","r","iterQuery","src","forEachEntity","fn","cols","buildColumnViews","i","callWithCols","ents","eid","forEachEntityIndexed","indexMask","callWithColsIndexed","comp","getComponentInfo","storage","recordEntityMaskChange","changedBit","prevMask","nextMask","involved","qid","wasMatch","isMatch","pushReactive","queryId","kind","ensureReactiveBuffer","componentId","lazyGetComponentInfo","_getComponentInfoFn","registerComponentLookup"],"mappings":"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","file":"chunk-3ZLNR4JX.cjs","sourcesContent":["import { createMask, isMaskZero, listBits, matches, setBit } from './bitmask.js'\nimport { getComponentInfo } from './component.js'\nimport type {\n Archetype,\n ComponentInfo,\n ComponentLike,\n EntityId,\n Query,\n QueryDescriptor,\n QueryInternal,\n QueryMaskBundle,\n ReactiveBuffer,\n World,\n WorldState,\n} from './types.js'\nimport {\n getOrRegisterComponentBit,\n getWorldState,\n readEntityMask,\n tryGetComponentBit,\n} from './world.js'\n\nlet nextQueryId = 1\nconst moduleQueryCache = new Map<string, QueryInternal>()\n\nfunction descKey(d: QueryDescriptor): string {\n const all = (d.all ?? [])\n .map((c) => c.__id)\n .sort((a, b) => a - b)\n .join('-')\n const any = (d.any ?? [])\n .map((c) => c.__id)\n .sort((a, b) => a - b)\n .join('-')\n const none = (d.none ?? [])\n .map((c) => c.__id)\n .sort((a, b) => a - b)\n .join('-')\n return `A${all}|Y${any}|N${none}`\n}\n\nexport function defineQuery(arg: ComponentLike[] | QueryDescriptor): Query {\n const desc: QueryDescriptor = Array.isArray(arg) ? { all: arg } : arg\n\n // Validate all members are components\n for (const c of [...(desc.all ?? []), ...(desc.any ?? []), ...(desc.none ?? [])]) {\n if (!c || typeof c !== 'object' || typeof (c as any).__id !== 'number') {\n throw new TypeError('aiecsjs: defineQuery received a non-component value')\n }\n }\n\n const key = descKey(desc)\n const cached = moduleQueryCache.get(key)\n if (cached) return cached\n\n const q: QueryInternal = {\n id: nextQueryId++,\n mask: [],\n all: (desc.all ?? []).map((c) => c.__id),\n any: (desc.any ?? []).map((c) => c.__id),\n none: (desc.none ?? []).map((c) => c.__id),\n columnViewCache: [...(desc.all ?? []), ...(desc.any ?? [])],\n reactiveKind: 'normal',\n sourceQueryId: -1,\n sourceQuery: null,\n }\n moduleQueryCache.set(key, q)\n return q\n}\n\n/**\n * Reactive \"entered\" view of `query`: each read drains the entities that began\n * matching since the last read (via `runQuery` / `iterQuery` / `forEachEntity`).\n *\n * **MUST-DRAIN CONTRACT (unbounded buffer).** The enter buffer has **no cap**.\n * Every structural change that makes an entity newly match pushes one id; the\n * buffer only shrinks when you read the reactive view. A view that is created\n * but never read — e.g. a disabled system, or reading only the {@link exitQuery}\n * twin — accumulates one number per event **forever**, an unbounded memory leak\n * at churn rates (e.g. ~1k spawns/frame). Read every enter view you create, once\n * per frame. Dropping ids silently would corrupt enter/exit symmetry, so capping\n * is intentionally not done — draining is the caller's responsibility.\n */\nexport function enterQuery(query: Query): Query {\n const q = query as QueryInternal\n const key = `enter:${q.id}`\n const cached = moduleQueryCache.get(key)\n if (cached) return cached\n const reactive: QueryInternal = {\n id: nextQueryId++,\n mask: [],\n all: q.all,\n any: q.any,\n none: q.none,\n columnViewCache: q.columnViewCache,\n reactiveKind: 'enter',\n sourceQueryId: q.id,\n sourceQuery: q,\n }\n moduleQueryCache.set(key, reactive)\n return reactive\n}\n\n/**\n * Reactive \"exited\" view of `query`: each read drains the entities that stopped\n * matching since the last read (via `runQuery` / `iterQuery` / `forEachEntity`).\n *\n * **MUST-DRAIN CONTRACT (unbounded buffer).** The exit buffer has **no cap** —\n * same discipline as {@link enterQuery}. An unread exit view accumulates one id\n * per matching structural change (including every `destroyEntity` of a matching\n * entity) without bound. Read every exit view you create, once per frame. Capping\n * is intentionally not done because dropping ids would break enter/exit symmetry.\n */\nexport function exitQuery(query: Query): Query {\n const q = query as QueryInternal\n const key = `exit:${q.id}`\n const cached = moduleQueryCache.get(key)\n if (cached) return cached\n const reactive: QueryInternal = {\n id: nextQueryId++,\n mask: [],\n all: q.all,\n any: q.any,\n none: q.none,\n columnViewCache: q.columnViewCache,\n reactiveKind: 'exit',\n sourceQueryId: q.id,\n sourceQuery: q,\n }\n moduleQueryCache.set(key, reactive)\n return reactive\n}\n\n// --- Per-world query setup ---\n\nfunction ensureQueryRegistered(state: WorldState, q: QueryInternal): void {\n if (state.queries[q.id] === q && state.queryMasks.has(q.id)) return\n\n // Build per-world bitmasks (this may register new bits)\n const ww = state.options.maskWordCount\n const withMask = createMask(ww)\n const anyMask = createMask(ww)\n const noneMask = createMask(ww)\n for (const compId of q.all) {\n const info = getComponentInfoById(compId)\n const bit = getOrRegisterComponentBit(state, info)\n setBit(withMask, bit)\n }\n for (const compId of q.any) {\n const info = getComponentInfoById(compId)\n const bit = getOrRegisterComponentBit(state, info)\n setBit(anyMask, bit)\n }\n for (const compId of q.none) {\n const info = getComponentInfoById(compId)\n const bit = getOrRegisterComponentBit(state, info)\n setBit(noneMask, bit)\n }\n\n const bundle: QueryMaskBundle = {\n withMask,\n anyMask,\n noneMask,\n anyHasBits: !isMaskZero(anyMask),\n }\n state.queryMasks.set(q.id, bundle)\n\n state.queries[q.id] = q\n state.queryArchetypeCache[q.id] = null\n state.queryArchetypeStamp[q.id] = -1\n\n // Build bit → queries index for fast reactive lookup\n const involvedBits: number[] = [\n ...listBits(withMask),\n ...listBits(anyMask),\n ...listBits(noneMask),\n ]\n for (const b of involvedBits) {\n let s = state.bitToQueries.get(b)\n if (!s) {\n s = new Set<number>()\n state.bitToQueries.set(b, s)\n }\n s.add(q.id)\n }\n\n // Initialize reactive buffer for enter/exit queries\n if (q.reactiveKind !== 'normal') {\n if (!state.reactiveBuffers.has(q.id)) {\n state.reactiveBuffers.set(q.id, { entered: [], exited: [] })\n }\n // Also register the source query so recordEntityMaskChange will see it\n if (q.sourceQuery) ensureQueryRegistered(state, q.sourceQuery)\n }\n}\n\nfunction getQueryArchetypes(state: WorldState, q: QueryInternal): number[] {\n ensureQueryRegistered(state, q)\n if (state.queryArchetypeCache[q.id] && state.queryArchetypeStamp[q.id] === state.queryVersion) {\n return state.queryArchetypeCache[q.id]!\n }\n const bundle = state.queryMasks.get(q.id)!\n const words = state.options.maskWordCount\n const list: number[] = []\n for (let i = 0; i < state.archetypes.length; i++) {\n const arch = state.archetypes[i]!\n if (\n matches(arch.mask, bundle.withMask, bundle.anyMask, bundle.noneMask, bundle.anyHasBits, words)\n ) {\n list.push(i)\n }\n }\n state.queryArchetypeCache[q.id] = list\n state.queryArchetypeStamp[q.id] = state.queryVersion\n return list\n}\n\nexport function queryArchetypes(world: World, query: Query): readonly Archetype[] {\n const state = getWorldState(world)\n const q = query as QueryInternal\n const ids = getQueryArchetypes(state, q)\n const out: Archetype[] = []\n for (const id of ids) {\n const arch = state.archetypes[id]!\n out.push({ id: arch.id, mask: Array.from(arch.mask), size: arch.size })\n }\n return out\n}\n\nexport function runQuery(world: World, query: Query): readonly EntityId[] {\n const state = getWorldState(world)\n const q = query as QueryInternal\n const out: EntityId[] = []\n if (q.reactiveKind === 'enter') {\n const buf = state.reactiveBuffers.get(q.id)\n if (buf) {\n for (const e of buf.entered) out.push(e as EntityId)\n buf.entered.length = 0\n }\n return out\n }\n if (q.reactiveKind === 'exit') {\n const buf = state.reactiveBuffers.get(q.id)\n if (buf) {\n for (const e of buf.exited) out.push(e as EntityId)\n buf.exited.length = 0\n }\n return out\n }\n const archIds = getQueryArchetypes(state, q)\n for (const id of archIds) {\n const arch = state.archetypes[id]!\n for (let r = 0; r < arch.size; r++) {\n out.push(arch.entities[r] as EntityId)\n }\n }\n return out\n}\n\nexport function* iterQuery(world: World, query: Query): IterableIterator<EntityId> {\n const state = getWorldState(world)\n const q = query as QueryInternal\n if (q.reactiveKind !== 'normal') {\n const buf = state.reactiveBuffers.get(q.id)\n if (!buf) return\n const src = q.reactiveKind === 'enter' ? buf.entered : buf.exited\n for (const e of src) yield e as EntityId\n src.length = 0\n return\n }\n const archIds = getQueryArchetypes(state, q)\n for (const id of archIds) {\n const arch = state.archetypes[id]!\n for (let r = 0; r < arch.size; r++) {\n yield arch.entities[r] as EntityId\n }\n }\n}\n\n/**\n * Iterate every entity matching `query`, invoking `fn(e, ...cols)` once per row\n * with the packed {@link EntityId} and the query's SoA column views.\n *\n * **Caution — `e` is a packed EntityId, not a column subscript.** It carries the\n * generation in its high bits, so indexing a column view with it directly\n * (`pos.x[e]`) reads out of bounds once a slot has been recycled. Use `e` only\n * for identity operations (`destroyEntity` / `hasComponent` / `refOf`). To index\n * columns safely, prefer {@link forEachEntityIndexed} — which yields the masked\n * slot index `i` alongside `e` — or mask it yourself with {@link getEntityIndex}.\n *\n * @see {@link forEachEntityIndexed} — same iteration plus the safe column index `i`.\n * @see {@link getEntityIndex} — mask a packed EntityId to its raw slot index.\n */\nexport function forEachEntity(\n world: World,\n query: Query,\n fn: (eid: EntityId, ...cols: any[]) => void,\n): void {\n const state = getWorldState(world)\n const q = query as QueryInternal\n\n if (q.reactiveKind !== 'normal') {\n const buf = state.reactiveBuffers.get(q.id)\n if (!buf) return\n const src = q.reactiveKind === 'enter' ? buf.entered : buf.exited\n if (src.length === 0) return\n const cols = buildColumnViews(state, q)\n for (let i = 0; i < src.length; i++) {\n const e = src[i] as EntityId\n callWithCols(fn, e, cols)\n }\n src.length = 0\n return\n }\n\n ensureQueryRegistered(state, q)\n const archIds = getQueryArchetypes(state, q)\n const cols = buildColumnViews(state, q)\n for (const id of archIds) {\n const arch = state.archetypes[id]!\n const ents = arch.entities\n // Re-read `arch.size` each iteration (do NOT cache it as `n`): an in-loop\n // `destroyEntity` swap-pops the visited row, shrinks `arch.size`, and zeroes\n // the freed tail slot. A cached bound would keep walking into those zeroed\n // tail rows and hand the callback the reserved sentinel eid 0 (ECS-B-01).\n // The swapped-in survivor is intentionally skipped this pass (deferred to the\n // next). This is a scalar property read — no per-iteration allocation, so the\n // zero-allocation hot-path contract holds. Mirrors runQuery (:230) / iterQuery.\n for (let r = 0; r < arch.size; r++) {\n callWithCols(fn, ents[r] as EntityId, cols)\n }\n }\n}\n\nfunction callWithCols(\n fn: (eid: EntityId, ...cols: any[]) => void,\n eid: EntityId,\n cols: any[],\n): void {\n // Specialise for low arities to avoid spread allocation.\n switch (cols.length) {\n case 0:\n fn(eid)\n break\n case 1:\n fn(eid, cols[0])\n break\n case 2:\n fn(eid, cols[0], cols[1])\n break\n case 3:\n fn(eid, cols[0], cols[1], cols[2])\n break\n case 4:\n fn(eid, cols[0], cols[1], cols[2], cols[3])\n break\n case 5:\n fn(eid, cols[0], cols[1], cols[2], cols[3], cols[4])\n break\n default:\n fn(eid, ...cols)\n }\n}\n\n/**\n * Like {@link forEachEntity}, but yields the masked column index `i` alongside\n * the packed `EntityId`. The callback signature is `(e, i, ...cols)`:\n *\n * - `e` — the packed EntityId (carries the generation in its high bits). Use\n * it for in-loop `destroyEntity` / `hasComponent` / `refOf`, exactly as with\n * `forEachEntity`.\n * - `i` — `e & indexMask`, the raw slot index. This is the **correct subscript**\n * for SoA column views (`pos.x[i]`), and stays correct after a slot is\n * recycled — where indexing with the packed `e` would read out of bounds.\n * - `...cols` — the same column views `forEachEntity` passes.\n *\n * This closes the packed-EntityId footgun (A1): callers no longer need to call\n * `getEntityIndex(e)` (or hand-mask) themselves to index columns safely.\n */\nexport function forEachEntityIndexed(\n world: World,\n query: Query,\n fn: (e: EntityId, i: number, ...cols: any[]) => void,\n): void {\n const state = getWorldState(world)\n const q = query as QueryInternal\n const indexMask = state.options.indexMask\n\n if (q.reactiveKind !== 'normal') {\n const buf = state.reactiveBuffers.get(q.id)\n if (!buf) return\n const src = q.reactiveKind === 'enter' ? buf.entered : buf.exited\n if (src.length === 0) return\n const cols = buildColumnViews(state, q)\n for (let i = 0; i < src.length; i++) {\n const e = src[i] as EntityId\n callWithColsIndexed(fn, e, e & indexMask, cols)\n }\n src.length = 0\n return\n }\n\n ensureQueryRegistered(state, q)\n const archIds = getQueryArchetypes(state, q)\n const cols = buildColumnViews(state, q)\n for (const id of archIds) {\n const arch = state.archetypes[id]!\n const ents = arch.entities\n // Re-read `arch.size` each iteration — see forEachEntity for the rationale.\n // An in-loop `destroyEntity` swap-pops the row and zeroes the freed tail; a\n // cached bound would replay the sentinel eid 0 across the public boundary\n // (ECS-B-01). Scalar read only; the zero-allocation hot-path contract holds.\n for (let r = 0; r < arch.size; r++) {\n const e = ents[r] as EntityId\n callWithColsIndexed(fn, e, e & indexMask, cols)\n }\n }\n}\n\nfunction callWithColsIndexed(\n fn: (e: EntityId, i: number, ...cols: any[]) => void,\n e: EntityId,\n i: number,\n cols: any[],\n): void {\n // Specialise for low arities to avoid spread allocation.\n switch (cols.length) {\n case 0:\n fn(e, i)\n break\n case 1:\n fn(e, i, cols[0])\n break\n case 2:\n fn(e, i, cols[0], cols[1])\n break\n case 3:\n fn(e, i, cols[0], cols[1], cols[2])\n break\n case 4:\n fn(e, i, cols[0], cols[1], cols[2], cols[3])\n break\n case 5:\n fn(e, i, cols[0], cols[1], cols[2], cols[3], cols[4])\n break\n default:\n fn(e, i, ...cols)\n }\n}\n\nfunction buildColumnViews(state: WorldState, q: QueryInternal): any[] {\n const out: any[] = []\n for (const comp of q.columnViewCache) {\n const info = getComponentInfo(comp)\n const bit = state.componentBitFor.get(info.id)\n if (bit === undefined) {\n out.push(undefined)\n continue\n }\n const storage = state.componentStorageByBit[bit]\n if (!storage) {\n out.push(undefined)\n continue\n }\n if (storage.kind === 'soa') out.push(storage.soa)\n else if (storage.kind === 'aos') out.push(storage.aos)\n else out.push(true) // tag\n }\n return out\n}\n\n// --- Reactive query updates (called from migration code) ---\n\nexport function recordEntityMaskChange(\n state: WorldState,\n eid: EntityId,\n changedBit: number,\n prevMask: Uint32Array,\n nextMask: Uint32Array,\n): void {\n // Lazy-register any reactive queries (and their sources) so we can correctly\n // determine match transitions even if the user only ever called enterQuery/exitQuery.\n for (const q of moduleQueryCache.values()) {\n if (q.reactiveKind === 'normal') continue\n if (q.sourceQuery && state.queries[q.sourceQuery.id] !== q.sourceQuery) {\n ensureQueryRegistered(state, q.sourceQuery)\n }\n }\n\n const involved = state.bitToQueries.get(changedBit)\n if (!involved) return\n const words = state.options.maskWordCount\n for (const qid of involved) {\n const q = state.queries[qid]\n if (!q) continue\n if (q.reactiveKind !== 'normal') continue\n const bundle = state.queryMasks.get(qid)\n if (!bundle) continue\n const wasMatch = matches(\n prevMask,\n bundle.withMask,\n bundle.anyMask,\n bundle.noneMask,\n bundle.anyHasBits,\n words,\n )\n const isMatch = matches(\n nextMask,\n bundle.withMask,\n bundle.anyMask,\n bundle.noneMask,\n bundle.anyHasBits,\n words,\n )\n if (!wasMatch && isMatch) {\n pushReactive(state, qid, 'enter', eid)\n } else if (wasMatch && !isMatch) {\n pushReactive(state, qid, 'exit', eid)\n }\n }\n}\n\nfunction pushReactive(\n state: WorldState,\n queryId: number,\n kind: 'enter' | 'exit',\n eid: EntityId,\n): void {\n // Walk the module cache (not just state.queries) so reactive variants that\n // haven't been registered with this world yet still receive events.\n for (const r of moduleQueryCache.values()) {\n if (r.sourceQueryId !== queryId) continue\n if (r.reactiveKind !== kind) continue\n // Lazily register the reactive query in this world so subsequent reads can find it\n ensureQueryRegistered(state, r)\n const buf = ensureReactiveBuffer(state, r.id)\n if (kind === 'enter') buf.entered.push(eid as number)\n else buf.exited.push(eid as number)\n }\n}\n\nfunction ensureReactiveBuffer(state: WorldState, qid: number): ReactiveBuffer {\n let buf = state.reactiveBuffers.get(qid)\n if (!buf) {\n buf = { entered: [], exited: [] }\n state.reactiveBuffers.set(qid, buf)\n }\n return buf\n}\n\n// --- Helpers ---\n\nfunction getComponentInfoById(componentId: number): ComponentInfo {\n // We need access to the component registry's lookup by id. Re-import dynamically to avoid cycles.\n const info = lazyGetComponentInfo(componentId)\n if (!info) throw new Error(`aiecsjs: component id ${componentId} not registered`)\n return info\n}\n\nlet _getComponentInfoFn: ((id: number) => ComponentInfo | undefined) | null = null\nexport function registerComponentLookup(fn: (id: number) => ComponentInfo | undefined): void {\n _getComponentInfoFn = fn\n}\nfunction lazyGetComponentInfo(id: number): ComponentInfo | undefined {\n return _getComponentInfoFn ? _getComponentInfoFn(id) : undefined\n}\n\nexport function _resetQueryRegistry_FOR_TESTS_ONLY(): void {\n moduleQueryCache.clear()\n nextQueryId = 1\n}\n"]}
|
package/dist/chunk-N5OETPTK.js
DELETED
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import {j,J,e,b,q,c,d,f as f$1}from'./chunk-YFTCD2UG.js';var E=1,f=new Map;function A(n){let e=(n.all??[]).map(o=>o.__id).sort((o,i)=>o-i).join("-"),t=(n.any??[]).map(o=>o.__id).sort((o,i)=>o-i).join("-"),r=(n.none??[]).map(o=>o.__id).sort((o,i)=>o-i).join("-");return `A${e}|Y${t}|N${r}`}function T(n){let e=Array.isArray(n)?{all:n}:n;for(let i of [...e.all??[],...e.any??[],...e.none??[]])if(!i||typeof i!="object"||typeof i.__id!="number")throw new TypeError("aiecsjs: defineQuery received a non-component value");let t=A(e),r=f.get(t);if(r)return r;let o={id:E++,mask:[],all:(e.all??[]).map(i=>i.__id),any:(e.any??[]).map(i=>i.__id),none:(e.none??[]).map(i=>i.__id),columnViewCache:[...e.all??[],...e.any??[]],reactiveKind:"normal",sourceQueryId:-1,sourceQuery:null};return f.set(t,o),o}function $(n){let e=n,t=`enter:${e.id}`,r=f.get(t);if(r)return r;let o={id:E++,mask:[],all:e.all,any:e.any,none:e.none,columnViewCache:e.columnViewCache,reactiveKind:"enter",sourceQueryId:e.id,sourceQuery:e};return f.set(t,o),o}function D(n){let e=n,t=`exit:${e.id}`,r=f.get(t);if(r)return r;let o={id:E++,mask:[],all:e.all,any:e.any,none:e.none,columnViewCache:e.columnViewCache,reactiveKind:"exit",sourceQueryId:e.id,sourceQuery:e};return f.set(t,o),o}function p(n,e){if(n.queries[e.id]===e&&n.queryMasks.has(e.id))return;let t=n.options.maskWordCount,r=b(t),o=b(t),i=b(t);for(let a of e.all){let u=C(a),d=q(n,u);c(r,d);}for(let a of e.any){let u=C(a),d=q(n,u);c(o,d);}for(let a of e.none){let u=C(a),d=q(n,u);c(i,d);}let c$1={withMask:r,anyMask:o,noneMask:i,anyHasBits:!d(o)};n.queryMasks.set(e.id,c$1),n.queries[e.id]=e,n.queryArchetypeCache[e.id]=null,n.queryArchetypeStamp[e.id]=-1;let s=[...f$1(r),...f$1(o),...f$1(i)];for(let a of s){let u=n.bitToQueries.get(a);u||(u=new Set,n.bitToQueries.set(a,u)),u.add(e.id);}e.reactiveKind!=="normal"&&(n.reactiveBuffers.has(e.id)||n.reactiveBuffers.set(e.id,{entered:[],exited:[]}),e.sourceQuery&&p(n,e.sourceQuery));}function m(n,e$1){if(p(n,e$1),n.queryArchetypeCache[e$1.id]&&n.queryArchetypeStamp[e$1.id]===n.queryVersion)return n.queryArchetypeCache[e$1.id];let t=n.queryMasks.get(e$1.id),r=n.options.maskWordCount,o=[];for(let i=0;i<n.archetypes.length;i++){let c=n.archetypes[i];e(c.mask,t.withMask,t.anyMask,t.noneMask,t.anyHasBits,r)&&o.push(i);}return n.queryArchetypeCache[e$1.id]=o,n.queryArchetypeStamp[e$1.id]=n.queryVersion,o}function H(n,e){let t=j(n),o=m(t,e),i=[];for(let c of o){let s=t.archetypes[c];i.push({id:s.id,mask:Array.from(s.mask),size:s.size});}return i}function L(n,e){let t=j(n),r=e,o=[];if(r.reactiveKind==="enter"){let c=t.reactiveBuffers.get(r.id);if(c){for(let s of c.entered)o.push(s);c.entered.length=0;}return o}if(r.reactiveKind==="exit"){let c=t.reactiveBuffers.get(r.id);if(c){for(let s of c.exited)o.push(s);c.exited.length=0;}return o}let i=m(t,r);for(let c of i){let s=t.archetypes[c];for(let a=0;a<s.size;a++)o.push(s.entities[a]);}return o}function*F(n,e){let t=j(n),r=e;if(r.reactiveKind!=="normal"){let i=t.reactiveBuffers.get(r.id);if(!i)return;let c=r.reactiveKind==="enter"?i.entered:i.exited;for(let s of c)yield s;c.length=0;return}let o=m(t,r);for(let i of o){let c=t.archetypes[i];for(let s=0;s<c.size;s++)yield c.entities[s];}}function O(n,e,t){let r=j(n),o=e;if(o.reactiveKind!=="normal"){let s=r.reactiveBuffers.get(o.id);if(!s)return;let a=o.reactiveKind==="enter"?s.entered:s.exited;if(a.length===0)return;let u=g(r,o);for(let d=0;d<a.length;d++){let y=a[d];w(t,y,u);}a.length=0;return}p(r,o);let i=m(r,o),c=g(r,o);for(let s of i){let a=r.archetypes[s],u=a.entities;for(let d=0;d<a.size;d++)w(t,u[d],c);}}function w(n,e,t){switch(t.length){case 0:n(e);break;case 1:n(e,t[0]);break;case 2:n(e,t[0],t[1]);break;case 3:n(e,t[0],t[1],t[2]);break;case 4:n(e,t[0],t[1],t[2],t[3]);break;case 5:n(e,t[0],t[1],t[2],t[3],t[4]);break;default:n(e,...t);}}function G(n,e,t){let r=j(n),o=e,i=r.options.indexMask;if(o.reactiveKind!=="normal"){let a=r.reactiveBuffers.get(o.id);if(!a)return;let u=o.reactiveKind==="enter"?a.entered:a.exited;if(u.length===0)return;let d=g(r,o);for(let y=0;y<u.length;y++){let h=u[y];W(t,h,h&i,d);}u.length=0;return}p(r,o);let c=m(r,o),s=g(r,o);for(let a of c){let u=r.archetypes[a],d=u.entities;for(let y=0;y<u.size;y++){let h=d[y];W(t,h,h&i,s);}}}function W(n,e,t,r){switch(r.length){case 0:n(e,t);break;case 1:n(e,t,r[0]);break;case 2:n(e,t,r[0],r[1]);break;case 3:n(e,t,r[0],r[1],r[2]);break;case 4:n(e,t,r[0],r[1],r[2],r[3]);break;case 5:n(e,t,r[0],r[1],r[2],r[3],r[4]);break;default:n(e,t,...r);}}function g(n,e){let t=[];for(let r of e.columnViewCache){let o=J(r),i=n.componentBitFor.get(o.id);if(i===void 0){t.push(void 0);continue}let c=n.componentStorageByBit[i];if(!c){t.push(void 0);continue}c.kind==="soa"?t.push(c.soa):c.kind==="aos"?t.push(c.aos):t.push(true);}return t}function N(n,e$1,t,r,o){for(let s of f.values())s.reactiveKind!=="normal"&&s.sourceQuery&&n.queries[s.sourceQuery.id]!==s.sourceQuery&&p(n,s.sourceQuery);let i=n.bitToQueries.get(t);if(!i)return;let c=n.options.maskWordCount;for(let s of i){let a=n.queries[s];if(!a||a.reactiveKind!=="normal")continue;let u=n.queryMasks.get(s);if(!u)continue;let d=e(r,u.withMask,u.anyMask,u.noneMask,u.anyHasBits,c),y=e(o,u.withMask,u.anyMask,u.noneMask,u.anyHasBits,c);!d&&y?_(n,s,"enter",e$1):d&&!y&&_(n,s,"exit",e$1);}}function _(n,e,t,r){for(let o of f.values()){if(o.sourceQueryId!==e||o.reactiveKind!==t)continue;p(n,o);let i=K(n,o.id);t==="enter"?i.entered.push(r):i.exited.push(r);}}function K(n,e){let t=n.reactiveBuffers.get(e);return t||(t={entered:[],exited:[]},n.reactiveBuffers.set(e,t)),t}function C(n){let e=S(n);if(!e)throw new Error(`aiecsjs: component id ${n} not registered`);return e}var x=null;function U(n){x=n;}function S(n){return x?x(n):void 0}export{T as a,$ as b,D as c,H as d,L as e,F as f,O as g,G as h,N as i,U as j};//# sourceMappingURL=chunk-N5OETPTK.js.map
|
|
2
|
-
//# sourceMappingURL=chunk-N5OETPTK.js.map
|