aiecsjs 0.5.9 → 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 +114 -18
- package/llms.txt +1 -0
- package/package.json +57 -22
- package/dist/chunk-JDV5JZP2.cjs +0 -2
- package/dist/chunk-JDV5JZP2.cjs.map +0 -1
- package/dist/chunk-OBMQME2P.js +0 -2
- package/dist/chunk-OBMQME2P.js.map +0 -1
- package/dist/chunk-Q2XLL6YG.cjs +0 -2
- package/dist/chunk-Q2XLL6YG.cjs.map +0 -1
- package/dist/chunk-USHKPJQG.cjs +0 -2
- package/dist/chunk-USHKPJQG.cjs.map +0 -1
- package/dist/chunk-XKN3ULCC.js +0 -2
- package/dist/chunk-XKN3ULCC.js.map +0 -1
- package/dist/chunk-ZZBNE7C5.js +0 -2
- package/dist/chunk-ZZBNE7C5.js.map +0 -1
package/api.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://islumina.github.io/aiecsjs/api-schema.json",
|
|
3
3
|
"name": "aiecsjs",
|
|
4
|
-
"version": "0.
|
|
5
|
-
"generated": "2026-
|
|
4
|
+
"version": "0.6.0",
|
|
5
|
+
"generated": "2026-09-29",
|
|
6
6
|
"stability": "experimental",
|
|
7
7
|
"license": "MIT",
|
|
8
8
|
"repository": "https://github.com/islumina/aiecsjs",
|
|
@@ -119,6 +119,12 @@
|
|
|
119
119
|
"type": "World",
|
|
120
120
|
"description": "Opaque world handle passed to all other API calls."
|
|
121
121
|
},
|
|
122
|
+
"throws": [
|
|
123
|
+
{
|
|
124
|
+
"type": "EcsError",
|
|
125
|
+
"when": "initialCapacity, maxEntities, indexBits or generationBits is not an integer (checked first), indexBits is outside [1, 24], generationBits is outside [0, 16], or their sum exceeds 32."
|
|
126
|
+
}
|
|
127
|
+
],
|
|
122
128
|
"examples": [
|
|
123
129
|
{ "title": "Minimal world", "code": "const world = createWorld()" },
|
|
124
130
|
{
|
|
@@ -179,11 +185,12 @@
|
|
|
179
185
|
"stability": "stable",
|
|
180
186
|
"deprecated": false,
|
|
181
187
|
"signature": "function resetWorld(world: World): void",
|
|
182
|
-
"summary": "Wipe entities and
|
|
188
|
+
"summary": "Wipe entities, components and relation edges but keep the world allocated (capacity and registered components). Useful for hot module reload.",
|
|
183
189
|
"params": [
|
|
184
190
|
{ "name": "world", "type": "World", "optional": false, "description": "World to reset." }
|
|
185
191
|
],
|
|
186
192
|
"returns": { "type": "void", "description": "" },
|
|
193
|
+
"throws": [{ "type": "EcsError", "when": "world is read-only (worker-attached, since 0.6.0)." }],
|
|
187
194
|
"examples": [
|
|
188
195
|
{
|
|
189
196
|
"title": "Reset for HMR",
|
|
@@ -242,7 +249,9 @@
|
|
|
242
249
|
"type": "EntityId",
|
|
243
250
|
"description": "Branded number containing index + generation."
|
|
244
251
|
},
|
|
245
|
-
"throws": [
|
|
252
|
+
"throws": [
|
|
253
|
+
{ "type": "EcsError", "when": "world has reached its maxEntities cap, or is read-only." }
|
|
254
|
+
],
|
|
246
255
|
"examples": [{ "title": "Spawn one entity", "code": "const e = createEntity(world)" }],
|
|
247
256
|
"seeAlso": ["destroyEntity", "entityExists", "packEntity"]
|
|
248
257
|
},
|
|
@@ -254,7 +263,7 @@
|
|
|
254
263
|
"stability": "stable",
|
|
255
264
|
"deprecated": false,
|
|
256
265
|
"signature": "function destroyEntity(world: World, eid: EntityId): void",
|
|
257
|
-
"summary": "Remove all components, bump generation, free slot.",
|
|
266
|
+
"summary": "Remove all components and relation edges, bump generation, free slot. No-op for a dead entity.",
|
|
258
267
|
"params": [
|
|
259
268
|
{ "name": "world", "type": "World", "optional": false, "description": "Target world." },
|
|
260
269
|
{
|
|
@@ -265,6 +274,7 @@
|
|
|
265
274
|
}
|
|
266
275
|
],
|
|
267
276
|
"returns": { "type": "void", "description": "" },
|
|
277
|
+
"throws": [{ "type": "EcsError", "when": "world is read-only." }],
|
|
268
278
|
"examples": [
|
|
269
279
|
{
|
|
270
280
|
"title": "Cleanup dead entity",
|
|
@@ -364,20 +374,30 @@
|
|
|
364
374
|
"since": "0.1.0",
|
|
365
375
|
"stability": "stable",
|
|
366
376
|
"deprecated": false,
|
|
367
|
-
"signature": "function defineComponent<S extends SoASchema>(schema: S): SoAComponent<S>",
|
|
368
|
-
"summary": "Declare a Structure-of-Arrays component. Each field becomes a TypedArray column indexed by entity
|
|
377
|
+
"signature": "function defineComponent<S extends SoASchema>(schema: S, options?: { key?: string }): SoAComponent<S>",
|
|
378
|
+
"summary": "Declare a Structure-of-Arrays component. Each field becomes a TypedArray column indexed by entity slot index. `options.key` (since 0.6.0) is the stable identity snapshots use to match data to this component.",
|
|
369
379
|
"params": [
|
|
370
380
|
{
|
|
371
381
|
"name": "schema",
|
|
372
382
|
"type": "SoASchema",
|
|
373
383
|
"optional": false,
|
|
374
384
|
"description": "Map of field name → field type. Field type is a member of Types, or [type, vectorLength] for fixed-size vectors."
|
|
385
|
+
},
|
|
386
|
+
{
|
|
387
|
+
"name": "options",
|
|
388
|
+
"type": "{ key?: string }",
|
|
389
|
+
"optional": true,
|
|
390
|
+
"description": "Stable serialization key: a non-empty string, unique in the process. Snapshot loaders resolve keyed components by key, keyless ones by creation-order id."
|
|
375
391
|
}
|
|
376
392
|
],
|
|
377
393
|
"returns": {
|
|
378
394
|
"type": "SoAComponent<S>",
|
|
379
395
|
"description": "Component handle used in addComponent/getComponent/etc."
|
|
380
396
|
},
|
|
397
|
+
"throws": [
|
|
398
|
+
{ "type": "TypeError", "when": "a field declaration or field type is invalid." },
|
|
399
|
+
{ "type": "EcsError", "when": "options.key is empty, not a string, or already defined." }
|
|
400
|
+
],
|
|
381
401
|
"examples": [
|
|
382
402
|
{
|
|
383
403
|
"title": "Position with two scalars",
|
|
@@ -386,6 +406,10 @@
|
|
|
386
406
|
{
|
|
387
407
|
"title": "Transform with vector field",
|
|
388
408
|
"code": "const Transform = defineComponent({ pos: [Types.f32, 3], scale: Types.f32 })"
|
|
409
|
+
},
|
|
410
|
+
{
|
|
411
|
+
"title": "Keyed for snapshots",
|
|
412
|
+
"code": "const Position = defineComponent({ x: Types.f32, y: Types.f32 }, { key: 'position' })"
|
|
389
413
|
}
|
|
390
414
|
],
|
|
391
415
|
"seeAlso": ["defineTag", "defineObjectComponent", "Types", "addComponent"]
|
|
@@ -397,9 +421,16 @@
|
|
|
397
421
|
"since": "0.1.0",
|
|
398
422
|
"stability": "stable",
|
|
399
423
|
"deprecated": false,
|
|
400
|
-
"signature": "function defineTag(): TagComponent",
|
|
401
|
-
"summary": "Declare a zero-byte tag component. No fields.",
|
|
402
|
-
"params": [
|
|
424
|
+
"signature": "function defineTag(options?: { key?: string }): TagComponent",
|
|
425
|
+
"summary": "Declare a zero-byte tag component. No fields. `options.key` (since 0.6.0): see defineComponent.",
|
|
426
|
+
"params": [
|
|
427
|
+
{
|
|
428
|
+
"name": "options",
|
|
429
|
+
"type": "{ key?: string }",
|
|
430
|
+
"optional": true,
|
|
431
|
+
"description": "Stable serialization key; see defineComponent."
|
|
432
|
+
}
|
|
433
|
+
],
|
|
403
434
|
"returns": { "type": "TagComponent", "description": "Tag component handle." },
|
|
404
435
|
"examples": [{ "title": "Player tag", "code": "const Player = defineTag()" }],
|
|
405
436
|
"seeAlso": ["defineComponent"]
|
|
@@ -411,17 +442,29 @@
|
|
|
411
442
|
"since": "0.1.0",
|
|
412
443
|
"stability": "stable",
|
|
413
444
|
"deprecated": false,
|
|
414
|
-
"signature": "function defineObjectComponent<T>(factory?: () => T): AoSComponent<T>",
|
|
445
|
+
"signature": "function defineObjectComponent<T>(factory?: () => T, options?: { key?: string }): AoSComponent<T>",
|
|
415
446
|
"summary": "Declare an Array-of-Structures component. Each entity stores a separate JS object. Main-thread only.",
|
|
416
447
|
"params": [
|
|
417
448
|
{
|
|
418
449
|
"name": "factory",
|
|
419
450
|
"type": "() => T",
|
|
420
451
|
"optional": true,
|
|
421
|
-
"description": "
|
|
452
|
+
"description": "Called once per entity, when the component is first added, to create that entity's instance (default `() => ({})`). Must return a value other than null or undefined. Initial data is copied onto the instance."
|
|
453
|
+
},
|
|
454
|
+
{
|
|
455
|
+
"name": "options",
|
|
456
|
+
"type": "{ key?: string }",
|
|
457
|
+
"optional": true,
|
|
458
|
+
"description": "Stable serialization key; see defineComponent."
|
|
422
459
|
}
|
|
423
460
|
],
|
|
424
461
|
"returns": { "type": "AoSComponent<T>", "description": "AoS component handle." },
|
|
462
|
+
"throws": [
|
|
463
|
+
{
|
|
464
|
+
"type": "EcsError",
|
|
465
|
+
"when": "factory is given but not a function, or options.key is invalid or already defined."
|
|
466
|
+
}
|
|
467
|
+
],
|
|
425
468
|
"examples": [
|
|
426
469
|
{
|
|
427
470
|
"title": "Reference to a Three.js mesh",
|
|
@@ -462,8 +505,10 @@
|
|
|
462
505
|
],
|
|
463
506
|
"returns": { "type": "void", "description": "" },
|
|
464
507
|
"throws": [
|
|
465
|
-
{
|
|
466
|
-
|
|
508
|
+
{
|
|
509
|
+
"type": "EcsError",
|
|
510
|
+
"when": "eid is not alive, the component is not registered, the world is read-only, or an AoS factory returns null/undefined (before the entity changes)."
|
|
511
|
+
}
|
|
467
512
|
],
|
|
468
513
|
"examples": [
|
|
469
514
|
{
|
|
@@ -577,6 +622,12 @@
|
|
|
577
622
|
{ "name": "value", "type": "V", "optional": false, "description": "New values." }
|
|
578
623
|
],
|
|
579
624
|
"returns": { "type": "void", "description": "" },
|
|
625
|
+
"throws": [
|
|
626
|
+
{
|
|
627
|
+
"type": "EcsError",
|
|
628
|
+
"when": "eid is not alive, the component is not registered, or the world is read-only."
|
|
629
|
+
}
|
|
630
|
+
],
|
|
580
631
|
"examples": [
|
|
581
632
|
{ "title": "Set SoA", "code": "setComponent(world, e, Position, { x: 5, y: 10 })" }
|
|
582
633
|
],
|
|
@@ -623,7 +674,8 @@
|
|
|
623
674
|
{ "name": "world", "type": "World", "optional": false, "description": "Target world." },
|
|
624
675
|
{ "name": "query", "type": "Query", "optional": false, "description": "Query handle." }
|
|
625
676
|
],
|
|
626
|
-
"returns": { "type": "
|
|
677
|
+
"returns": { "type": "Query", "description": "Cached query handle." },
|
|
678
|
+
"throws": [{ "type": "TypeError", "when": "a member is not a component handle." }],
|
|
627
679
|
"examples": [],
|
|
628
680
|
"seeAlso": ["forEachEntity", "iterQuery"]
|
|
629
681
|
},
|
|
@@ -653,6 +705,10 @@
|
|
|
653
705
|
"code": "forEachEntity(world, movers, (e, pos, vel) => { const i = getEntityIndex(e); pos.x[i] += vel.x[i]; pos.y[i] += vel.y[i] })"
|
|
654
706
|
}
|
|
655
707
|
],
|
|
708
|
+
"throws": [
|
|
709
|
+
{ "type": "TypeError", "when": "query is neither a Query nor a component array." },
|
|
710
|
+
{ "type": "EcsError", "when": "fn is not a function (checked before a reactive buffer is drained)." }
|
|
711
|
+
],
|
|
656
712
|
"seeAlso": ["defineQuery", "runQuery", "forEachEntityIndexed", "iterQuery"]
|
|
657
713
|
},
|
|
658
714
|
{
|
|
@@ -681,6 +737,10 @@
|
|
|
681
737
|
"code": "forEachEntityIndexed(world, movers, (e, i, pos, vel) => { pos.x[i] += vel.x[i]; pos.y[i] += vel.y[i] })"
|
|
682
738
|
}
|
|
683
739
|
],
|
|
740
|
+
"throws": [
|
|
741
|
+
{ "type": "TypeError", "when": "query is neither a Query nor a component array." },
|
|
742
|
+
{ "type": "EcsError", "when": "fn is not a function (checked before a reactive buffer is drained)." }
|
|
743
|
+
],
|
|
684
744
|
"seeAlso": ["forEachEntity", "defineQuery", "runQuery", "iterQuery"]
|
|
685
745
|
},
|
|
686
746
|
{
|
|
@@ -710,11 +770,17 @@
|
|
|
710
770
|
"stability": "stable",
|
|
711
771
|
"deprecated": false,
|
|
712
772
|
"signature": "function enterQuery(query: Query): Query",
|
|
713
|
-
"summary": "Reactive query that yields only entities newly matching
|
|
773
|
+
"summary": "Reactive query that yields only entities newly matching since the last read. The buffer is unbounded until drained.",
|
|
714
774
|
"params": [
|
|
715
|
-
{
|
|
775
|
+
{
|
|
776
|
+
"name": "query",
|
|
777
|
+
"type": "Query",
|
|
778
|
+
"optional": false,
|
|
779
|
+
"description": "Source query (a raw component array is accepted, as for runQuery)."
|
|
780
|
+
}
|
|
716
781
|
],
|
|
717
782
|
"returns": { "type": "Query", "description": "Reactive query handle." },
|
|
783
|
+
"throws": [{ "type": "TypeError", "when": "query is neither a Query nor a component array." }],
|
|
718
784
|
"examples": [
|
|
719
785
|
{ "title": "Mount-on-enter", "code": "const becameVisible = enterQuery(visibleQ)" }
|
|
720
786
|
],
|
|
@@ -728,11 +794,17 @@
|
|
|
728
794
|
"stability": "stable",
|
|
729
795
|
"deprecated": false,
|
|
730
796
|
"signature": "function exitQuery(query: Query): Query",
|
|
731
|
-
"summary": "Reactive query that yields only entities that left the match
|
|
797
|
+
"summary": "Reactive query that yields only entities that left the match since the last read. The buffer is unbounded until drained.",
|
|
732
798
|
"params": [
|
|
733
|
-
{
|
|
799
|
+
{
|
|
800
|
+
"name": "query",
|
|
801
|
+
"type": "Query",
|
|
802
|
+
"optional": false,
|
|
803
|
+
"description": "Source query (a raw component array is accepted, as for runQuery)."
|
|
804
|
+
}
|
|
734
805
|
],
|
|
735
806
|
"returns": { "type": "Query", "description": "Reactive query handle." },
|
|
807
|
+
"throws": [{ "type": "TypeError", "when": "query is neither a Query nor a component array." }],
|
|
736
808
|
"examples": [],
|
|
737
809
|
"seeAlso": ["enterQuery", "defineQuery"]
|
|
738
810
|
},
|
|
@@ -776,6 +848,7 @@
|
|
|
776
848
|
}
|
|
777
849
|
],
|
|
778
850
|
"returns": { "type": "System<W, Ctx>", "description": "Composed system." },
|
|
851
|
+
"throws": [{ "type": "EcsError", "when": "a system is not a function (checked at composition)." }],
|
|
779
852
|
"examples": [
|
|
780
853
|
{
|
|
781
854
|
"title": "Frame tick",
|
|
@@ -802,6 +875,16 @@
|
|
|
802
875
|
}
|
|
803
876
|
],
|
|
804
877
|
"returns": { "type": "{ start(), stop() }", "description": "Loop control handle." },
|
|
878
|
+
"throws": [
|
|
879
|
+
{
|
|
880
|
+
"type": "TypeError",
|
|
881
|
+
"when": "options is not an object, onUpdate is not a function, or onRender is set but not a function."
|
|
882
|
+
},
|
|
883
|
+
{
|
|
884
|
+
"type": "RangeError",
|
|
885
|
+
"when": "fixed is not a finite number > 0, or maxSubSteps is not a finite number >= 1."
|
|
886
|
+
}
|
|
887
|
+
],
|
|
805
888
|
"examples": [
|
|
806
889
|
{
|
|
807
890
|
"title": "60Hz loop",
|
|
@@ -869,6 +952,7 @@
|
|
|
869
952
|
}
|
|
870
953
|
],
|
|
871
954
|
"returns": { "type": "R", "description": "Whatever the callback returned." },
|
|
955
|
+
"throws": [{ "type": "EcsError", "when": "fn is not a function." }],
|
|
872
956
|
"examples": [
|
|
873
957
|
{
|
|
874
958
|
"title": "Safe destroy in iter",
|
|
@@ -885,7 +969,7 @@
|
|
|
885
969
|
"stability": "stable",
|
|
886
970
|
"deprecated": false,
|
|
887
971
|
"signature": "function observe(world: World, query: Query, event: 'add' | 'remove' | 'set', handler: (eid: EntityId) => void, opts?: ObserverOptions): () => void",
|
|
888
|
-
"summary": "General-purpose query observer. Returns a disposer. `opts.signal` (since 0.2.0) auto-unsubscribes when aborted.",
|
|
972
|
+
"summary": "General-purpose query observer: 'add' when an entity starts matching, 'remove' when it stops (including destroy), 'set' after setComponent writes an all/any component of a matching entity. Accepts a raw component array. Returns a disposer. `opts.signal` (since 0.2.0) auto-unsubscribes when aborted.",
|
|
889
973
|
"params": [
|
|
890
974
|
{ "name": "world", "type": "World", "optional": false, "description": "Target world." },
|
|
891
975
|
{ "name": "query", "type": "Query", "optional": false, "description": "Query handle." },
|
|
@@ -909,6 +993,7 @@
|
|
|
909
993
|
}
|
|
910
994
|
],
|
|
911
995
|
"returns": { "type": "() => void", "description": "Disposer." },
|
|
996
|
+
"throws": [{ "type": "EcsError", "when": "handler is not a function." }],
|
|
912
997
|
"examples": [],
|
|
913
998
|
"seeAlso": ["onAdd", "onRemove", "onSet"]
|
|
914
999
|
},
|
|
@@ -943,6 +1028,7 @@
|
|
|
943
1028
|
}
|
|
944
1029
|
],
|
|
945
1030
|
"returns": { "type": "() => void", "description": "Disposer." },
|
|
1031
|
+
"throws": [{ "type": "EcsError", "when": "handler is not a function." }],
|
|
946
1032
|
"examples": [],
|
|
947
1033
|
"seeAlso": ["onRemove", "onSet", "observe"]
|
|
948
1034
|
},
|
|
@@ -977,6 +1063,7 @@
|
|
|
977
1063
|
}
|
|
978
1064
|
],
|
|
979
1065
|
"returns": { "type": "() => void", "description": "Disposer." },
|
|
1066
|
+
"throws": [{ "type": "EcsError", "when": "handler is not a function." }],
|
|
980
1067
|
"examples": [],
|
|
981
1068
|
"seeAlso": ["onAdd", "onSet"]
|
|
982
1069
|
},
|
|
@@ -1006,6 +1093,7 @@
|
|
|
1006
1093
|
}
|
|
1007
1094
|
],
|
|
1008
1095
|
"returns": { "type": "() => void", "description": "Disposer." },
|
|
1096
|
+
"throws": [{ "type": "EcsError", "when": "handler is not a function." }],
|
|
1009
1097
|
"examples": [],
|
|
1010
1098
|
"seeAlso": ["onAdd", "onRemove"]
|
|
1011
1099
|
},
|
|
@@ -1017,7 +1105,7 @@
|
|
|
1017
1105
|
"stability": "stable",
|
|
1018
1106
|
"deprecated": false,
|
|
1019
1107
|
"signature": "function serializeWorld(world: World, options?: SerializeOptions): Uint8Array",
|
|
1020
|
-
"summary": "Produce a versioned binary snapshot of the world.",
|
|
1108
|
+
"summary": "Produce a versioned binary snapshot of the world (format 2: magic, format version, VERSION, JSON body with the component table).",
|
|
1021
1109
|
"params": [
|
|
1022
1110
|
{ "name": "world", "type": "World", "optional": false, "description": "Target world." },
|
|
1023
1111
|
{
|
|
@@ -1051,11 +1139,16 @@
|
|
|
1051
1139
|
"name": "options",
|
|
1052
1140
|
"type": "DeserializeOptions",
|
|
1053
1141
|
"optional": true,
|
|
1054
|
-
"description": "
|
|
1142
|
+
"description": "Same as fromJSON: components allowlist, onUnknownVersion (also checked against the binary header), onUnknownComponent."
|
|
1055
1143
|
}
|
|
1056
1144
|
],
|
|
1057
1145
|
"returns": { "type": "World", "description": "Restored world." },
|
|
1058
|
-
"throws": [
|
|
1146
|
+
"throws": [
|
|
1147
|
+
{
|
|
1148
|
+
"type": "EcsError",
|
|
1149
|
+
"when": "the bytes are malformed, the format version is not 2 and onUnknownVersion is not 'best-effort', a component is undefined here and onUnknownComponent is not 'skip', or a component kind/SoA fields mismatch."
|
|
1150
|
+
}
|
|
1151
|
+
],
|
|
1059
1152
|
"examples": [],
|
|
1060
1153
|
"seeAlso": ["serializeWorld"]
|
|
1061
1154
|
},
|
|
@@ -1067,7 +1160,7 @@
|
|
|
1067
1160
|
"stability": "stable",
|
|
1068
1161
|
"deprecated": false,
|
|
1069
1162
|
"signature": "function toJSON(world: World): WorldSnapshot",
|
|
1070
|
-
"summary": "Produce a human-readable JSON snapshot. Slower than serializeWorld; inspectable in DevTools.",
|
|
1163
|
+
"summary": "Produce a human-readable JSON snapshot (format 2: `formatVersion: 2`, a `components` table with id/key/kind/fields, and per-entity data). AoS data is deep-copied. Slower than serializeWorld; inspectable in DevTools.",
|
|
1071
1164
|
"params": [
|
|
1072
1165
|
{ "name": "world", "type": "World", "optional": false, "description": "Target world." }
|
|
1073
1166
|
],
|
|
@@ -1082,17 +1175,29 @@
|
|
|
1082
1175
|
"since": "0.1.0",
|
|
1083
1176
|
"stability": "stable",
|
|
1084
1177
|
"deprecated": false,
|
|
1085
|
-
"signature": "function fromJSON(snapshot: WorldSnapshot): World",
|
|
1086
|
-
"summary": "Restore from a JSON snapshot.",
|
|
1178
|
+
"signature": "function fromJSON(snapshot: WorldSnapshot, options?: DeserializeOptions): World",
|
|
1179
|
+
"summary": "Restore from a JSON snapshot. Every component is resolved (by key, by creation-order id when keyless) and checked for kind/SoA fields before the world is created. Entities get fresh ids in snapshot order.",
|
|
1087
1180
|
"params": [
|
|
1088
1181
|
{
|
|
1089
1182
|
"name": "snapshot",
|
|
1090
1183
|
"type": "WorldSnapshot",
|
|
1091
1184
|
"optional": false,
|
|
1092
1185
|
"description": "Snapshot from toJSON."
|
|
1186
|
+
},
|
|
1187
|
+
{
|
|
1188
|
+
"name": "options",
|
|
1189
|
+
"type": "DeserializeOptions",
|
|
1190
|
+
"optional": true,
|
|
1191
|
+
"description": "components allowlist, onUnknownVersion ('throw' | 'best-effort'), onUnknownComponent ('throw' | 'skip'). Since 0.6.0."
|
|
1093
1192
|
}
|
|
1094
1193
|
],
|
|
1095
1194
|
"returns": { "type": "World", "description": "Restored world." },
|
|
1195
|
+
"throws": [
|
|
1196
|
+
{
|
|
1197
|
+
"type": "EcsError",
|
|
1198
|
+
"when": "snapshot is not an object with an entities array, formatVersion is not 2 and onUnknownVersion is not 'best-effort', a component is undefined here and onUnknownComponent is not 'skip', or a component kind/SoA fields mismatch."
|
|
1199
|
+
}
|
|
1200
|
+
],
|
|
1096
1201
|
"examples": [],
|
|
1097
1202
|
"seeAlso": ["toJSON"]
|
|
1098
1203
|
},
|
|
@@ -1104,7 +1209,7 @@
|
|
|
1104
1209
|
"stability": "experimental",
|
|
1105
1210
|
"deprecated": false,
|
|
1106
1211
|
"signature": "function createDeltaSerializer(world: World, options?: SerializeOptions): DeltaSerializer",
|
|
1107
|
-
"summary": "Capture only changes since the previous capture. For network replication. Wire format may change before 1.0.",
|
|
1212
|
+
"summary": "Capture only changes since the previous capture. For network replication. Each capture carries formatVersion 2 and the component table; apply() resolves it like fromJSON (unknown components throw) before touching the target, and keeps slot indices. Wire format may change before 1.0.",
|
|
1108
1213
|
"params": [
|
|
1109
1214
|
{ "name": "world", "type": "World", "optional": false, "description": "Target world." },
|
|
1110
1215
|
{
|
|
@@ -1151,14 +1256,20 @@
|
|
|
1151
1256
|
"since": "0.1.0",
|
|
1152
1257
|
"stability": "experimental",
|
|
1153
1258
|
"deprecated": false,
|
|
1154
|
-
"signature": "function adoptSnapshot(snap:
|
|
1155
|
-
"summary": "On the Worker side, materialise a world from a snapshot sent over postMessage.",
|
|
1259
|
+
"signature": "function adoptSnapshot(snap: TransferableSnapshot, options?: DeserializeOptions): World",
|
|
1260
|
+
"summary": "On the Worker side, materialise a world from a snapshot sent over postMessage. Validates the meta (magic, format version 2 unless onUnknownVersion is 'best-effort') and resolves components like deserializeWorld.",
|
|
1156
1261
|
"params": [
|
|
1157
1262
|
{
|
|
1158
1263
|
"name": "snap",
|
|
1159
1264
|
"type": "TransferableSnapshot",
|
|
1160
1265
|
"optional": false,
|
|
1161
1266
|
"description": "Snapshot received via onmessage."
|
|
1267
|
+
},
|
|
1268
|
+
{
|
|
1269
|
+
"name": "options",
|
|
1270
|
+
"type": "DeserializeOptions",
|
|
1271
|
+
"optional": true,
|
|
1272
|
+
"description": "Same as deserializeWorld. Since 0.6.0."
|
|
1162
1273
|
}
|
|
1163
1274
|
],
|
|
1164
1275
|
"returns": {
|
|
@@ -1175,8 +1286,8 @@
|
|
|
1175
1286
|
"since": "0.1.0",
|
|
1176
1287
|
"stability": "experimental",
|
|
1177
1288
|
"deprecated": false,
|
|
1178
|
-
"signature": "function attachWorld(buffer: SharedArrayBuffer, options?: { readOnly?: boolean }): World",
|
|
1179
|
-
"summary": "Attach to a SAB that was set up by another thread. Use readOnly when this thread should only read.",
|
|
1289
|
+
"signature": "function attachWorld(buffer: SharedArrayBuffer | ArrayBuffer, options?: DeserializeOptions & { readOnly?: boolean }): World",
|
|
1290
|
+
"summary": "Attach to a SAB that was set up by another thread. Use readOnly when this thread should only read: every mutator, resetWorld included, then throws EcsError.",
|
|
1180
1291
|
"params": [
|
|
1181
1292
|
{
|
|
1182
1293
|
"name": "buffer",
|
|
@@ -1186,9 +1297,9 @@
|
|
|
1186
1297
|
},
|
|
1187
1298
|
{
|
|
1188
1299
|
"name": "options",
|
|
1189
|
-
"type": "{ readOnly?: boolean }",
|
|
1300
|
+
"type": "DeserializeOptions & { readOnly?: boolean }",
|
|
1190
1301
|
"optional": true,
|
|
1191
|
-
"description": "
|
|
1302
|
+
"description": "readOnly flag plus the deserializeWorld options (onUnknownVersion, onUnknownComponent, components)."
|
|
1192
1303
|
}
|
|
1193
1304
|
],
|
|
1194
1305
|
"returns": { "type": "World", "description": "Attached world view." },
|
|
@@ -1245,9 +1356,21 @@
|
|
|
1245
1356
|
"stability": "stable",
|
|
1246
1357
|
"deprecated": false,
|
|
1247
1358
|
"signature": "function addRelation<T>(world: World, source: EntityId, rel: Relation<T>, target: EntityId, data?: T): void",
|
|
1248
|
-
"summary": "Add a relation edge from source to target.",
|
|
1249
|
-
"params": [
|
|
1359
|
+
"summary": "Add a relation edge from source to target (replacing the current target of an exclusive relation), optionally with a data payload.",
|
|
1360
|
+
"params": [
|
|
1361
|
+
{ "name": "world", "type": "World", "optional": false, "description": "Target world." },
|
|
1362
|
+
{ "name": "source", "type": "EntityId", "optional": false, "description": "Live source entity." },
|
|
1363
|
+
{ "name": "rel", "type": "Relation<T>", "optional": false, "description": "Relation handle." },
|
|
1364
|
+
{ "name": "target", "type": "EntityId", "optional": false, "description": "Live target entity." },
|
|
1365
|
+
{ "name": "data", "type": "T", "optional": true, "description": "Edge payload for getRelationData." }
|
|
1366
|
+
],
|
|
1250
1367
|
"returns": { "type": "void", "description": "" },
|
|
1368
|
+
"throws": [
|
|
1369
|
+
{
|
|
1370
|
+
"type": "EcsError",
|
|
1371
|
+
"when": "source or target is not alive (since 0.6.0), rel is not a relation handle, or the world is read-only."
|
|
1372
|
+
}
|
|
1373
|
+
],
|
|
1251
1374
|
"examples": [
|
|
1252
1375
|
{
|
|
1253
1376
|
"title": "Mark Alice as child of Parent",
|
|
@@ -1292,7 +1415,7 @@
|
|
|
1292
1415
|
"stability": "stable",
|
|
1293
1416
|
"deprecated": false,
|
|
1294
1417
|
"signature": "function getRelationData<T>(world: World, source: EntityId, rel: Relation<T>, target: EntityId): T | undefined",
|
|
1295
|
-
"summary": "Read the data payload attached to a relation edge. Returns the value passed as `data` to `addRelation`, or `undefined` if no such edge exists or no data was stored.
|
|
1418
|
+
"summary": "Read the data payload attached to a relation edge. Returns the value passed as `data` to `addRelation`, or `undefined` if no such edge exists or no data was stored. Edges are keyed by slot index; storage never holds an edge for a dead entity, but a stale EntityId addresses its slot's current occupant, so validate cached ids with `entityExists`.",
|
|
1296
1419
|
"params": [
|
|
1297
1420
|
{ "name": "world", "type": "World", "optional": false, "description": "Target world." },
|
|
1298
1421
|
{ "name": "source", "type": "EntityId", "optional": false, "description": "Source entity." },
|
|
@@ -1374,7 +1497,7 @@
|
|
|
1374
1497
|
"stability": "stable",
|
|
1375
1498
|
"deprecated": false,
|
|
1376
1499
|
"signature": "function deref<T = unknown>(world: World, ref: EntityRef<T>): EntityId | null",
|
|
1377
|
-
"summary": "Resolve a ref to its live EntityId, or null if stale / cross-world / OOB. Never throws.",
|
|
1500
|
+
"summary": "Resolve a ref to its live EntityId, or null if stale / cross-world / OOB. Never throws for a live world; throws EcsError if world was already disposed.",
|
|
1378
1501
|
"params": [
|
|
1379
1502
|
{ "name": "world", "type": "World", "optional": false, "description": "Target world." },
|
|
1380
1503
|
{
|
|
@@ -1401,7 +1524,7 @@
|
|
|
1401
1524
|
"stability": "stable",
|
|
1402
1525
|
"deprecated": false,
|
|
1403
1526
|
"signature": "function aliveRef<T = unknown>(world: World, ref: EntityRef<T>): boolean",
|
|
1404
|
-
"summary": "Boolean guard form of deref. Returns true if ref is alive, false otherwise. Never throws.",
|
|
1527
|
+
"summary": "Boolean guard form of deref. Returns true if ref is alive, false otherwise. Never throws for a live world; see deref for the disposed-world case.",
|
|
1405
1528
|
"params": [
|
|
1406
1529
|
{ "name": "world", "type": "World", "optional": false, "description": "Target world." },
|
|
1407
1530
|
{ "name": "ref", "type": "EntityRef<T>", "optional": false, "description": "Ref to check." }
|
|
@@ -1419,8 +1542,8 @@
|
|
|
1419
1542
|
"since": "0.5.6",
|
|
1420
1543
|
"stability": "stable",
|
|
1421
1544
|
"deprecated": false,
|
|
1422
|
-
"signature": "class EcsError extends Error {}",
|
|
1423
|
-
"summary": "Thrown by
|
|
1545
|
+
"signature": "class EcsError extends Error { constructor(message: string, options?: { cause?: unknown }) }",
|
|
1546
|
+
"summary": "Thrown by aiecsjs for invariant violations and misuse, before any change is made: bad or non-integer world options, a destroyed/unknown world, dead entities, unregistered components, invalid component keys, non-function callbacks or factories, dead relation endpoints, read-only world mutations, command-buffer errors and snapshot errors (malformed bytes, unsupported format version, unknown or mismatched components). Carries the aiecsjs:-prefixed message.",
|
|
1424
1547
|
"params": [],
|
|
1425
1548
|
"returns": {
|
|
1426
1549
|
"type": "EcsError",
|
|
@@ -1442,7 +1565,7 @@
|
|
|
1442
1565
|
"stability": "stable",
|
|
1443
1566
|
"deprecated": false,
|
|
1444
1567
|
"signature": "class EntityNotAliveError extends Error { readonly eid: number }",
|
|
1445
|
-
"summary": "Thrown by refOf when the entity is not alive. deref and aliveRef never throw.",
|
|
1568
|
+
"summary": "Thrown by refOf when the entity is not alive. deref and aliveRef never throw for a live world (they throw EcsError only if world was already disposed).",
|
|
1446
1569
|
"params": [],
|
|
1447
1570
|
"returns": {
|
|
1448
1571
|
"type": "EntityNotAliveError",
|
|
@@ -1472,7 +1595,7 @@
|
|
|
1472
1595
|
"module": "aiecsjs",
|
|
1473
1596
|
"since": "0.1.0",
|
|
1474
1597
|
"stability": "stable",
|
|
1475
|
-
"definition": "type WorldOptions = { initialCapacity?: number; maxEntities?: number; indexBits?:
|
|
1598
|
+
"definition": "type WorldOptions = { initialCapacity?: number; maxEntities?: number; indexBits?: number; generationBits?: number; buffer?: SharedArrayBuffer; bufferByteOffset?: number } // numeric options must be integers; indexBits 1-24, generationBits 0-16, sum <= 32; buffer/bufferByteOffset reserved (no effect)"
|
|
1476
1599
|
},
|
|
1477
1600
|
{
|
|
1478
1601
|
"name": "World",
|
|
@@ -1504,7 +1627,7 @@
|
|
|
1504
1627
|
"module": "aiecsjs",
|
|
1505
1628
|
"since": "0.1.0",
|
|
1506
1629
|
"stability": "stable",
|
|
1507
|
-
"definition": "interface SoAComponent<S extends SoASchema> { readonly
|
|
1630
|
+
"definition": "interface SoAComponent<S extends SoASchema = SoASchema> { readonly __kind: 'soa'; readonly __id: number; readonly __schema: S }"
|
|
1508
1631
|
},
|
|
1509
1632
|
{
|
|
1510
1633
|
"name": "AoSComponent",
|
|
@@ -1512,7 +1635,7 @@
|
|
|
1512
1635
|
"module": "aiecsjs",
|
|
1513
1636
|
"since": "0.1.0",
|
|
1514
1637
|
"stability": "stable",
|
|
1515
|
-
"definition": "interface AoSComponent<T> { readonly
|
|
1638
|
+
"definition": "interface AoSComponent<T = unknown> { readonly __kind: 'aos'; readonly __id: number; readonly __factory: () => T }"
|
|
1516
1639
|
},
|
|
1517
1640
|
{
|
|
1518
1641
|
"name": "TagComponent",
|
|
@@ -1520,7 +1643,7 @@
|
|
|
1520
1643
|
"module": "aiecsjs",
|
|
1521
1644
|
"since": "0.1.0",
|
|
1522
1645
|
"stability": "stable",
|
|
1523
|
-
"definition": "interface TagComponent { readonly
|
|
1646
|
+
"definition": "interface TagComponent { readonly __kind: 'tag'; readonly __id: number }"
|
|
1524
1647
|
},
|
|
1525
1648
|
{
|
|
1526
1649
|
"name": "ComponentLike",
|
|
@@ -1584,7 +1707,7 @@
|
|
|
1584
1707
|
"module": "aiecsjs/serialize",
|
|
1585
1708
|
"since": "0.1.0",
|
|
1586
1709
|
"stability": "stable",
|
|
1587
|
-
"definition": "type DeserializeOptions = { onUnknownVersion?: 'throw' | 'best-effort' }"
|
|
1710
|
+
"definition": "type DeserializeOptions = { components?: ComponentLike[]; onUnknownVersion?: 'throw' | 'best-effort'; onUnknownComponent?: 'throw' | 'skip' }"
|
|
1588
1711
|
},
|
|
1589
1712
|
{
|
|
1590
1713
|
"name": "WorldSnapshot",
|
|
@@ -1592,7 +1715,7 @@
|
|
|
1592
1715
|
"module": "aiecsjs/serialize",
|
|
1593
1716
|
"since": "0.1.0",
|
|
1594
1717
|
"stability": "stable",
|
|
1595
|
-
"definition": "interface WorldSnapshot {
|
|
1718
|
+
"definition": "interface WorldSnapshot { formatVersion: 2; version: string; capacity: number; maxEntities?: number; indexBits?: number; generationBits?: number; components: Array<{ id: number; key: string | null; kind: 'soa' | 'aos' | 'tag'; fields: Array<{ name: string; type: SoAFieldType; vectorLen: number }> | null }>; entities: Array<{ eid: number; components: Array<{ kind: 'soa' | 'aos' | 'tag'; id: number; data: unknown }> }> }"
|
|
1596
1719
|
},
|
|
1597
1720
|
{
|
|
1598
1721
|
"name": "DeltaSerializer",
|
|
@@ -1616,7 +1739,7 @@
|
|
|
1616
1739
|
"module": "aiecsjs/relations",
|
|
1617
1740
|
"since": "0.2.0",
|
|
1618
1741
|
"stability": "experimental",
|
|
1619
|
-
"definition": "interface Relation<T = void> { readonly
|
|
1742
|
+
"definition": "interface Relation<T = void> { readonly __kind: 'relation'; readonly __id: number; readonly __exclusive: boolean; readonly __hasData: boolean }"
|
|
1620
1743
|
}
|
|
1621
1744
|
],
|
|
1622
1745
|
"constants": [
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
var C="0.6.0";function D(e){return new Uint32Array(e)}function q(e,n){let t=n>>>5;e[t]=(e[t]??0)|1<<(n&31);}function S(e,n){let t=n>>>5;e[t]=(e[t]??0)&~(1<<(n&31));}function h(e,n){let t=n>>>5;return ((e[t]??0)&1<<(n&31))!==0}function b(e){let n=new Uint32Array(e.length);for(let t=0;t<e.length;t++)n[t]=e[t]??0;return n}function N(e){let n=[];for(let t=0;t<e.length;t++)n.push((e[t]??0).toString(16));return n.join(",")}function U(e,n,t,o){for(let r=0;r<t;r++){let i=e[n+r]??0;for(;i!==0;){let s=(r<<5)+tn(i);o(s),i&=i-1;}}}function bn(e,n,t,o,r,i,s){let a=!s;for(let c=0;c<t;c++){let u=e[n+c]??0,p=o[c]??0,M=r[c]??0,g=i[c]??0;if((u&p)!==p||(u&g)!==0)return false;!a&&(u&M)!==0&&(a=true);}return a}function tn(e){return 31-Math.clz32(e&-e)}var d=class extends Error{constructor(n,t){super(n,t),this.name="EcsError";}};var v=globalThis,$=Symbol.for("aiecsjs.ids");v[$]??={component:1,query:1,world:1,relation:1};var E=v[$],z=Symbol.for(`aiecsjs.registry@${C}`);v[z]??={componentInfoById:new Map,componentInfoByKey:new Map,queryCache:new Map,reactiveBySource:new Map,reactiveSourcesByComponent:new Map,worlds:new Map,childOf:null,hooks:{observerDispatch:null,maskChange:null,destroyObservers:null,relationsCleanup:null}};var f=v[z];var w={initialCapacity:1024,maxEntities:1e6,indexBits:24,generationBits:8},on=256,k=f.worlds;function l(e){let n=e?.id,t=k.get(n);if(!t)throw new d(`aiecsjs: world ${n} is destroyed or unknown`);return t}function x(e){let n=l(e);if(n.readOnly)throw new d("aiecsjs: cannot mutate a read-only world");return n}function rn(e){k.set(e.id,e);}function sn(e){k.delete(e);}function vn(e){return k.has(e)}function an(e){let n=e??{};for(let c of Object.keys(w)){let u=n[c];if(u!==void 0&&!Number.isInteger(u))throw new d(`aiecsjs: ${c} must be an integer`)}let t=n.indexBits??w.indexBits,o=n.generationBits??w.generationBits,r=on;if(t<1||t>24)throw new d("aiecsjs: indexBits must be in [1, 24]");if(o<0||o>16)throw new d("aiecsjs: generationBits must be in [0, 16]");if(t+o>32)throw new d(`aiecsjs: indexBits (${t}) + generationBits (${o}) must be <= 32`);let i=1<<t,s=Math.max(1,Math.min(n.initialCapacity??w.initialCapacity,i)),a=Math.max(s,Math.min(n.maxEntities??w.maxEntities,i));return {initialCapacity:s,maxEntities:a,indexBits:t,generationBits:o,indexMask:(1<<t)-1,generationMask:o===0?0:(1<<o)-1,maxComponents:r,maskWordCount:Math.ceil(r/32),buffer:n.buffer??null,bufferByteOffset:n.bufferByteOffset??0}}function En(e){let n=an(e),t=E.world++,o=n.generationBits>8?Uint16Array:Uint8Array,r=new o(n.initialCapacity),i={id:t,capacity:n.initialCapacity,version:C,options:n,size:0,nextFreshIndex:1,freeList:[],generations:r,destroyed:false,destroying:new Set,removing:new Set,visitStamp:new Uint32Array(0),visitEpoch:0,componentBitFor:new Map,componentInfoByBit:new Array(n.maxComponents).fill(null),componentStorageByBit:new Array(n.maxComponents).fill(null),nextComponentBit:0,entityArchetype:new Uint32Array(n.initialCapacity),entityMask:new Uint32Array(n.initialCapacity*n.maskWordCount),archetypes:[],archetypeByMaskHash:new Map,queryVersion:0,queries:[],queryMasks:new Map,queryArchetypeCache:[],queryArchetypeStamp:[],bitToQueries:new Map,reactiveBuffers:new Map,observers:[],relationStorage:new Map,sab:n.buffer,readOnly:false};return R(i,D(n.maskWordCount)),rn(i),cn(i)}function cn(e){return {id:e.id,get capacity(){return e.capacity},version:e.version}}function Wn(e){let n=k.get(e?.id);!n||n.destroyed||(n.destroyed=true,n.archetypes=[],n.archetypeByMaskHash.clear(),n.componentInfoByBit=[],n.componentStorageByBit=[],n.queries=[],n.queryMasks.clear(),n.queryArchetypeCache=[],n.observers=[],n.relationStorage.clear(),n.reactiveBuffers.clear(),n.entityMask=new Uint32Array(0),n.entityArchetype=new Uint32Array(0),n.visitStamp=new Uint32Array(0),n.generations=new Uint8Array(0),n.freeList=[],n.destroying.clear(),n.componentBitFor.clear(),n.bitToQueries.clear(),n.queryArchetypeStamp=[],n.sab=null,sn(n.id));}function Bn(e){let n=x(e);n.size=0,n.nextFreshIndex=1,n.freeList=[],n.destroying.clear(),n.generations.fill(0),n.entityArchetype.fill(0),n.entityMask.fill(0);for(let t of n.archetypes)t.size=0,t.entityRow.clear();for(let t of n.componentStorageByBit)if(t)if(t.kind==="soa"&&t.soa)for(let o of Object.keys(t.soa))t.soa[o]?.fill(0);else t.kind==="aos"&&t.aos&&t.aos.fill(void 0);n.relationStorage.clear(),n.queryVersion++;for(let t of n.reactiveBuffers.values())t.entered.length=0,t.exited.length=0;}function Mn(e){return l(e).size}function Un(e){return l(e).capacity}function O(e,n){if(n<=e.capacity)return;if(n>e.options.maxEntities)throw new d(`aiecsjs: requested capacity ${n} exceeds maxEntities ${e.options.maxEntities}`);let t=e.capacity;for(;t<n;)t=Math.min(t*2,e.options.maxEntities);un(e,t);}function un(e,n){let t=e.generations.constructor,o=new t(n);o.set(e.generations),e.generations=o;let r=new Uint32Array(n);r.set(e.entityArchetype),e.entityArchetype=r;let i=e.options.maskWordCount,s=new Uint32Array(n*i);if(s.set(e.entityMask),e.entityMask=s,e.visitStamp.length>0){let a=new Uint32Array(n);a.set(e.visitStamp),e.visitStamp=a;}for(let a of e.componentStorageByBit)if(a)if(a.kind==="soa"&&a.soa){let c=e.componentInfoByBit[a.bit];c&&dn(a.soa,c.fields,n);}else a.kind==="aos"&&a.aos&&(a.aos.length=n);e.capacity=n;}function dn(e,n,t){for(let o of n){let r=e[o.name];if(!r)continue;let i=t*o.vectorLen;if(r.length>=i)continue;let s=new o.ctor(i);s.set(r),e[o.name]=s;}}function R(e,n){let t=N(n),o=e.archetypeByMaskHash.get(t);if(o!==void 0)return {archId:o,created:false};let r=e.archetypes.length,i={id:r,mask:b(n),size:0,capacity:16,entities:new Uint32Array(16),entityRow:new Map};return e.archetypes.push(i),e.archetypeByMaskHash.set(t,r),e.queryVersion++,{archId:r,created:true}}function W(e,n){if(e.size===e.capacity){e.capacity*=2;let t=new Uint32Array(e.capacity);t.set(e.entities),e.entities=t;}e.entities[e.size]=n,e.entityRow.set(n,e.size++);}function B(e,n){let t=e.entityRow.get(n);if(t===void 0)return;let o=--e.size,r=e.entities[o]??0;e.entities[t]=r,e.entityRow.set(r,t),e.entities[o]=0,e.entityRow.delete(n);}function P(e,n){let t=e.componentBitFor.get(n.id);if(t!==void 0)return t;if(e.nextComponentBit>=e.options.maxComponents)throw new d(`aiecsjs: world reached maxComponents=${e.options.maxComponents}`);let o=e.nextComponentBit++;e.componentBitFor.set(n.id,o),e.componentInfoByBit[o]=n;let r;if(n.kind==="soa"){let i={};for(let s of n.fields)i[s.name]=new s.ctor(e.capacity*s.vectorLen);r={kind:"soa",componentId:n.id,bit:o,soa:i};}else n.kind==="aos"?r={kind:"aos",componentId:n.id,bit:o,aos:new Array(e.capacity)}:r={kind:"tag",componentId:n.id,bit:o};return e.componentStorageByBit[o]=r,o}function m(e,n){let t=e.options.maskWordCount,o=new Uint32Array(t),i=(n&e.options.indexMask)*t;for(let s=0;s<t;s++)o[s]=e.entityMask[i+s]??0;return o}function G(e,n,t){let o=e.options.maskWordCount,i=(n&e.options.indexMask)*o;for(let s=0;s<o;s++)e.entityMask[i+s]=t[s]??0;}function A(e,n){return e.componentBitFor.get(n.id)}function On(e){if(!e||typeof e!="object")return false;let n=e;return typeof n.id!="number"||typeof n.version!="string"?false:k.has(n.id)}var fn={i8:Int8Array,u8:Uint8Array,i16:Int16Array,u16:Uint16Array,i32:Int32Array,u32:Uint32Array,f32:Float32Array,f64:Float64Array,eid:Uint32Array,bool:Uint8Array},j=f.componentInfoById,V=f.componentInfoByKey;function L(e,n,t=null,o=[],r=null){let i=e?.key;if(i!==void 0){if(typeof i!="string"||i==="")throw new d("aiecsjs: component key must be a non-empty string");let c=V.get(i);if(c){if(c.kind!==n||c.fields.length!==o.length||c.fields.some((u,p)=>u.name!==o[p].name||u.type!==o[p].type||u.vectorLen!==o[p].vectorLen))throw new d(`aiecsjs: component key "${i}" is already defined with a different layout`);return r&&(c.factory=r),c.id}}let s=E.component++,a={id:s,key:i??null,kind:n,schema:t,fields:o,factory:r};return j.set(s,a),i!==void 0&&V.set(i,a),s}function Dn(e,n){let t=[];for(let[o,r]of Object.entries(e)){let i,s=1;if(typeof r=="string")i=r;else if(Array.isArray(r)){let[c,u]=r;i=c,s=u;}else throw new TypeError(`aiecsjs: invalid field declaration for "${o}"`);let a=fn[i];if(!a)throw new TypeError(`aiecsjs: unknown field type "${i}" for field "${o}"`);t.push({name:o,type:i,vectorLen:s,ctor:a});}return {__kind:"soa",__id:L(n,"soa",e,t),__schema:e}}function qn(e){return {__kind:"tag",__id:L(e,"tag")}}function Nn(e,n){if(e!==void 0&&typeof e!="function")throw new d("aiecsjs: factory must be a function");let t=e??(()=>({}));return {__kind:"aos",__id:L(n,"aos",null,[],t),__factory:t}}function I(e){let n=j.get(e?.__id);if(!n)throw new d("aiecsjs: component is not registered (call defineComponent/defineTag/defineObjectComponent)");return n}function pn(e,n,t,o){let r=x(e);if(!y(r,n))throw new d(`aiecsjs: addComponent on dead entity ${n}`);let i=I(t),s=P(r,i),a=n&r.options.indexMask,c=m(r,n);if(h(c,s)){o!==void 0&&_(r,a,i,s,o);return}let u=b(c);q(u,s),i.kind==="aos"&&H(r,a,i,s),Y(r,n,u),_(r,a,i,s,o),f.hooks.observerDispatch?.fireAdd(r,n,s,c,u),F(r,n,s,c,u);}function $n(e,n,t){let o=x(e);if(!y(o,n))return;let r=I(t),i=A(o,r);if(i===void 0||!h(m(o,n),i))return;let s=(n&o.options.indexMask)*o.options.maxComponents+i;if(o.removing.has(s))return;o.removing.add(s);try{f.hooks.observerDispatch?.fireRemove(o,n,i);}finally{o.removing.delete(s);}if(!y(o,n))return;let a=m(o,n);if(!h(a,i))return;let c=b(a);S(c,i),Y(o,n,c),f.hooks.observerDispatch?.fireRemoveQuery(o,n,a,c);let u=n&o.options.indexMask,p=o.componentStorageByBit[i];p?.kind==="soa"&&p.soa?K(p.soa,r.fields,u):p?.kind==="aos"&&p.aos&&(p.aos[u]=void 0),F(o,n,i,a,c);}function zn(e,n,t){let o=l(e);if(!y(o,n))return false;let r=I(t),i=A(o,r);if(i===void 0)return false;let s=m(o,n);return h(s,i)}function Pn(e,n,t){let o=l(e);if(!y(o,n))return;let r=I(t),i=A(o,r);if(i===void 0)return;let s=m(o,n);if(!h(s,i))return;let a=o.componentStorageByBit[i];if(a){if(a.kind==="soa")return a.soa;if(a.kind==="aos"){let c=n&o.options.indexMask;return a.aos?.[c]}return true}}function Gn(e,n,t,o){let r=x(e);if(!y(r,n))throw new d(`aiecsjs: setComponent on dead entity ${n}`);let i=I(t),s=A(r,i);if(s===void 0||!h(m(r,n),s)){pn(e,n,t,o);return}_(r,n&r.options.indexMask,i,s,o),f.hooks.observerDispatch?.fireSet(r,n,s,o);}function _(e,n,t,o,r){let i=e.componentStorageByBit[o];if(t.kind==="soa"&&i?.soa){if(r==null)return;let s=r;for(let a of t.fields){if(!(a.name in s))continue;let c=i.soa[a.name];if(!c)continue;let u=s[a.name];if(a.vectorLen===1)c[n]=typeof u=="boolean"?u?1:0:Number(u);else if(Array.isArray(u)||ArrayBuffer.isView(u)){let p=n*a.vectorLen,M=u;for(let g=0;g<a.vectorLen;g++)c[p+g]=Number(M[g]??0);}}}else if(t.kind==="aos"){let s=H(e,n,t,o);if(r&&typeof r=="object"){let a=r,c=s;for(let u of Object.keys(a))u==="__proto__"||u==="constructor"||u==="prototype"||(c[u]=a[u]);}}}function H(e,n,t,o){let r=e.componentStorageByBit[o].aos;if(r[n]===void 0){let i=t.factory();if(i==null)throw new d("aiecsjs: factory result must not be null or undefined");r[n]=i;}return r[n]}function K(e,n,t){for(let o of n){let r=e[o.name];if(r)if(o.vectorLen===1)r[t]=0;else {let i=t*o.vectorLen;for(let s=0;s<o.vectorLen;s++)r[i+s]=0;}}}function Q(e,n){let t=e.options.maskWordCount,o=n&e.options.indexMask,r=o*t;U(e.entityMask,r,t,i=>{let s=e.componentStorageByBit[i],a=e.componentInfoByBit[i];s?.kind==="soa"&&s.soa&&a?K(s.soa,a.fields,o):s?.kind==="aos"&&s.aos&&(s.aos[o]=void 0);});}function Y(e,n,t){let o=n&e.options.indexMask,r=e.entityArchetype[o]??0,i=e.archetypes[r];if(!i)return;let a=R(e,t).archId,c=e.archetypes[a];c&&(a!==r&&(B(i,n),W(c,n),e.entityArchetype[o]=a),G(e,n,t));}function Vn(e){f.hooks.maskChange=e;}function F(e,n,t,o,r){f.hooks.maskChange?.(e,n,t,o,r);}function X(e,n,t){let o=e.options.maskWordCount,r=b(t),i=b(t);U(t,0,o,s=>{S(i,s),F(e,n,s,r,i),S(r,s);});}function Hn(e){f.hooks.observerDispatch=e;}function Kn(e){return j.get(e)}var T=24,yn=8,Z=(1<<T)-1,J=(1<<yn)-1;function nn(e,n,t){return ((n&t.generationMask)<<t.indexBits|e&t.indexMask)>>>0}function ne(e,n){return e&n.indexMask}function ee(e,n){return e>>>n.indexBits&n.generationMask}function te(e){let n=l(e);if(n.readOnly)throw new d("aiecsjs: cannot createEntity on a read-only world (worker-attached)");let t;if(n.freeList.length>0)t=n.freeList.pop();else {if(n.nextFreshIndex>=n.options.maxEntities)throw new d(`aiecsjs: reached maxEntities ${n.options.maxEntities}`);n.nextFreshIndex>=n.capacity&&O(n,n.nextFreshIndex+1),t=n.nextFreshIndex++;}return en(n,t)}function en(e,n){let t=nn(n,e.generations[n]??0,e.options),o=e.archetypes[0];if(!o)throw new d("aiecsjs: missing empty archetype");return W(o,t),e.entityArchetype[n]=0,e.entityMask.fill(0,n*e.options.maskWordCount,(n+1)*e.options.maskWordCount),e.size++,t}function oe(e,n){if(e.readOnly)throw new d("aiecsjs: cannot create entities on a read-only world (worker-attached)");if(n<=0||n>=e.options.maxEntities)throw new d(`aiecsjs: slot index ${n} out of range`);n>=e.capacity&&O(e,n+1);let t=e.generations[n]??0,o=nn(n,t,e.options);if(y(e,o))return o;if(n>=e.nextFreshIndex){for(let r=e.nextFreshIndex;r<n;r++)e.freeList.push(r);e.nextFreshIndex=n+1;}else {let r=e.freeList.lastIndexOf(n);if(r!==-1){let i=e.freeList.length-1;e.freeList[r]=e.freeList[i],e.freeList.pop();}}return en(e,n)}function re(e,n){let t=l(e);if(t.readOnly)throw new d("aiecsjs: cannot destroyEntity on a read-only world");if(!y(t,n)||t.destroying.has(n))return;let o=n&t.options.indexMask;t.destroying.add(n);let r;try{f.hooks.destroyObservers?.dispatchDestroyObservers(t,n),mn(t,n);}finally{r=t.destroying.delete(n);}if(!r||t.destroyed||!y(t,n))return;let i=m(t,n);Q(t,n),B(t.archetypes[t.entityArchetype[o]??0],n),X(t,n,i),t.entityArchetype[o]=0,t.entityMask.fill(0,o*t.options.maskWordCount,(o+1)*t.options.maskWordCount),t.generations[o]=(t.generations[o]??0)+1&t.options.generationMask,t.freeList.push(o),t.size--;}function ln(e,n){let t=l(e);return y(t,n)}function y(e,n){let t=n&e.options.indexMask;if(t<=0||t>=e.capacity)return false;let o=e.entityArchetype[t]??0,r=e.archetypes[o];if(!r||!r.entityRow.has(n))return false;let i=e.generations[t]??0,s=n>>>e.options.indexBits&e.options.generationMask;return i===s}function ie(e){return e&Z}function se(e){return e>>>T&J}function ae(e,n){return ((n&J)<<T|e&Z)>>>0}function ce(e,n){return typeof n!="number"?false:ln(e,n)}function ue(e){f.hooks.destroyObservers=e;}function de(e){f.hooks.relationsCleanup=e;}function mn(e,n){f.hooks.relationsCleanup?.(e,n);}export{ie as A,se as B,ae as C,ce as D,ue as E,de as F,Dn as G,qn as H,Nn as I,I as J,pn as K,$n as L,zn as M,Pn as N,Gn as O,Vn as P,Hn as Q,Kn as R,C as a,D as b,q as c,U as d,bn as e,d as f,E as g,f as h,l as i,x as j,vn as k,En as l,Wn as m,Bn as n,Mn as o,Un as p,P as q,On as r,nn as s,ne as t,ee as u,te as v,oe as w,re as x,ln as y,y as z};//# sourceMappingURL=chunk-27JX7WHY.js.map
|
|
2
|
+
//# sourceMappingURL=chunk-27JX7WHY.js.map
|