@woosh/meep-engine 2.128.1 → 2.128.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -13,11 +13,33 @@ To help get you started, various samples are provided under `/samples` folder. F
13
13
 
14
14
  ## Quality
15
15
 
16
- Meep is covered by 2,790 handwritten unit tests
16
+ ### Testing
17
+ Meep is covered by 2,801 handwritten unit tests, reaching 90%+ coverage in `core` and 40%+ coverage total.
17
18
 
18
19
  The aim is to [ensure quality](https://about.codecov.io/blog/the-case-against-100-code-coverage/). As a result, the tests are written to cover complex code first and to exhaustively validate critical algorithms.
19
20
  Most of the test code is significantly larger than the code that is being tested.
20
21
 
22
+ ### Assertions
23
+ Meep is covered by 3,162 asserts. [Assertions](https://en.wikipedia.org/wiki/Assertion_(software_development)) provide very extensive pre- and post-condition checks throughout the engine.
24
+ Asserts are intended primarily for development builds.
25
+ To remove asserts in Vite builds, you can use `@rollup/plugin-strip` package like so:
26
+
27
+ ```js
28
+ import strip from '@rollup/plugin-strip';
29
+ import { defineConfig } from 'vite';
30
+
31
+ export default defineConfig({
32
+ plugins: [{
33
+ // this will remove all assert statements from the production build
34
+ ...strip(),
35
+ apply: 'build'
36
+ }],
37
+ // ... the rest of the config ...
38
+ });
39
+ ```
40
+
41
+ Assertion package can be found under `/src/core/assert.js`.
42
+
21
43
  ## Package Size
22
44
 
23
45
  Meep is infinitely tree-shakable, you only package what you use.
package/package.json CHANGED
@@ -5,7 +5,7 @@
5
5
  "description": "Pure JavaScript game engine. Fully featured and production ready.",
6
6
  "type": "module",
7
7
  "author": "Alexander Goldring",
8
- "version": "2.128.1",
8
+ "version": "2.128.3",
9
9
  "main": "build/meep.module.js",
10
10
  "module": "build/meep.module.js",
11
11
  "exports": {
@@ -120,8 +120,8 @@ export namespace assert {
120
120
  */
121
121
  export function notNaN(value: number, name?: string): void;
122
122
  /**
123
- * Is given number finite?
124
- * Will trigger if number is infinite, i.e. fails the `Number.isFinite` test
123
+ * Is the given number finite?
124
+ * Will trigger if the number is infinite, i.e. fails the `Number.isFinite` test
125
125
  * @param {number} value
126
126
  * @param {string} [name] optional name for the value being checked
127
127
  */
@@ -447,8 +447,8 @@ assert.notNaN = function (value, name = "value") {
447
447
  };
448
448
 
449
449
  /**
450
- * Is given number finite?
451
- * Will trigger if number is infinite, i.e. fails the `Number.isFinite` test
450
+ * Is the given number finite?
451
+ * Will trigger if the number is infinite, i.e. fails the `Number.isFinite` test
452
452
  * @param {number} value
453
453
  * @param {string} [name] optional name for the value being checked
454
454
  */
@@ -81,8 +81,17 @@ export class OffsetAllocator {
81
81
  */
82
82
  allocate(size: number): Allocation;
83
83
  /**
84
+ * Direct method of releasing an allocation.
85
+ * Allows the user to skip holding an object reference in memory.
86
+ * {@link node_index} can be read from {@link Allocation.metadata}
84
87
  *
88
+ * @param {number} node_index
89
+ * @see free
90
+ */
91
+ free_node(node_index: number): void;
92
+ /**
85
93
  * @param {Allocation} allocation
94
+ * @see free_node
86
95
  */
87
96
  free(allocation: Allocation): void;
88
97
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"OffsetAllocator.d.ts","sourceRoot":"","sources":["../../../../../src/core/binary/allocator/OffsetAllocator.js"],"names":[],"mappings":"AAaA,4CAA6C;AAmF7C;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH;IAwDI;;;;OAIG;IACH,kBAHW,MAAM,cACN,MAAM,EAYhB;IAtED;;;;OAIG;IACH,MAFU,MAAM,CAEP;IAET;;;;OAIG;IACH,WAFU,MAAM,CAEF;IAEd;;;OAGG;IACH,aAFU,MAAM,CAEA;IAEhB;;;OAGG;IACH,aAFU,MAAM,CAEA;IAEhB;;;OAGG;IACH,UAFU,UAAU,CAEoB;IAExC;;;OAGG;IACH,YAFU,WAAW,CAEuB;IAE5C;;;OAGG;IACH,OAFU,aAAa,CAEmB;IAE1C;;OAEG;IACH,WAFU,WAAW,CAEX;IAEV;;;OAGG;IACH,YAFU,MAAM,CAED;IAmBf;;;;OAIG;IACH,eAHW,MAAM,GACJ,UAAU,CAkGtB;IAED;;;OAGG;IACH,iBAFW,UAAU,QAsFpB;IAqID;;OAEG;IACH,cA4BC;IAED;;;OAGG;IACH,iBAFY,aAAa,CA2BxB;;CACJ;8BAjkB6B,yCAAyC;AAgDvE;IAII;;;;;OAKG;IACH,oBAJW,MAAM,YACN,MAAM,GACL,UAAU,CASrB;IAhBD,eAA4B;IAC5B,iBAA8B;CAgBjC;AAoBD;IACI,uBAAkB;IAClB,0BAAqB;CACxB"}
1
+ {"version":3,"file":"OffsetAllocator.d.ts","sourceRoot":"","sources":["../../../../../src/core/binary/allocator/OffsetAllocator.js"],"names":[],"mappings":"AAaA,4CAA6C;AAmF7C;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH;IAwDI;;;;OAIG;IACH,kBAHW,MAAM,cACN,MAAM,EAYhB;IAtED;;;;OAIG;IACH,MAFU,MAAM,CAEP;IAET;;;;OAIG;IACH,WAFU,MAAM,CAEF;IAEd;;;OAGG;IACH,aAFU,MAAM,CAEA;IAEhB;;;OAGG;IACH,aAFU,MAAM,CAEA;IAEhB;;;OAGG;IACH,UAFU,UAAU,CAEoB;IAExC;;;OAGG;IACH,YAFU,WAAW,CAEuB;IAE5C;;;OAGG;IACH,OAFU,aAAa,CAEmB;IAE1C;;OAEG;IACH,WAFU,WAAW,CAEX;IAEV;;;OAGG;IACH,YAFU,MAAM,CAED;IAmBf;;;;OAIG;IACH,eAHW,MAAM,GACJ,UAAU,CAkGtB;IAED;;;;;;;OAOG;IACH,sBAHW,MAAM,QAqFhB;IAED;;;OAGG;IACH,iBAHW,UAAU,QAUpB;IAqID;;OAEG;IACH,cA4BC;IAED;;;OAGG;IACH,iBAFY,aAAa,CA2BxB;;CACJ;8BAhlB6B,yCAAyC;AAgDvE;IAII;;;;;OAKG;IACH,oBAJW,MAAM,YACN,MAAM,GACL,UAAU,CASrB;IAhBD,eAA4B;IAC5B,iBAA8B;CAgBjC;AAoBD;IACI,uBAAkB;IAClB,0BAAqB;CACxB"}
@@ -293,14 +293,16 @@ export class OffsetAllocator {
293
293
  }
294
294
 
295
295
  /**
296
+ * Direct method of releasing an allocation.
297
+ * Allows the user to skip holding an object reference in memory.
298
+ * {@link node_index} can be read from {@link Allocation.metadata}
296
299
  *
297
- * @param {Allocation} allocation
300
+ * @param {number} node_index
301
+ * @see free
298
302
  */
299
- free(allocation) {
300
- assert.notEqual(allocation.metadata, ALLOCATOR_NO_SPACE, 'Invalid allocation');
301
- // if (!m_nodes) return;
302
-
303
- const node_index = allocation.metadata;
303
+ free_node(node_index) {
304
+ assert.isNonNegativeInteger(node_index, 'node_index');
305
+ assert.notEqual(node_index, ALLOCATOR_NO_SPACE, 'Invalid allocation');
304
306
 
305
307
  const nodes = this.nodes;
306
308
  const node_flags = nodes.readCellValue(node_index, NODE_FIELD_FLAGS);
@@ -382,6 +384,19 @@ export class OffsetAllocator {
382
384
  }
383
385
  }
384
386
 
387
+ /**
388
+ * @param {Allocation} allocation
389
+ * @see free_node
390
+ */
391
+ free(allocation) {
392
+ assert.notEqual(allocation.metadata, ALLOCATOR_NO_SPACE, 'Invalid allocation');
393
+ // if (!m_nodes) return;
394
+
395
+ const node_index = allocation.metadata;
396
+
397
+ this.free_node(node_index);
398
+ }
399
+
385
400
  /**
386
401
  *
387
402
  * @param {number} size
@@ -1,12 +1,12 @@
1
1
  export class BVHQueryIntersectsSphere extends BVHQuery {
2
2
  /**
3
3
  *
4
- * @param {number[]|ArrayLike<number>} sphere
4
+ * @param {number[]|ArrayLike<number>} sphere (x,y,z,radius)
5
5
  * @returns {BVHQueryIntersectsRay}
6
6
  */
7
7
  static from(sphere: number[] | ArrayLike<number>): BVHQueryIntersectsRay;
8
8
  /**
9
- *
9
+ * [x,y,z,radius]
10
10
  * @type {number[]}
11
11
  */
12
12
  sphere: number[];
@@ -1 +1 @@
1
- {"version":3,"file":"BVHQueryIntersectsSphere.d.ts","sourceRoot":"","sources":["../../../../../../src/core/bvh2/bvh3/query/BVHQueryIntersectsSphere.js"],"names":[],"mappings":"AAKA;IAQI;;;;OAIG;IACH,oBAHW,MAAM,EAAE,GAAC,UAAU,MAAM,CAAC,yBASpC;IAjBD;;;OAGG;IACH,QAFU,MAAM,EAAE,CAEN;IAeZ,wCASC;CACJ;yBAnCwB,eAAe"}
1
+ {"version":3,"file":"BVHQueryIntersectsSphere.d.ts","sourceRoot":"","sources":["../../../../../../src/core/bvh2/bvh3/query/BVHQueryIntersectsSphere.js"],"names":[],"mappings":"AAUA;IAQI;;;;OAIG;IACH,oBAHW,MAAM,EAAE,GAAC,UAAU,MAAM,CAAC,yBAWpC;IAnBD;;;OAGG;IACH,QAFU,MAAM,EAAE,CAEC;IAiBnB,wCASC;CACJ;yBAzCwB,eAAe"}
@@ -1,22 +1,29 @@
1
+ import { assert } from "../../../assert.js";
1
2
  import { aabb3_array_intersects_sphere_array } from "../../../geom/3d/aabb/aabb3_array_intersects_sphere_array.js";
2
3
  import { BVHQuery } from "./BVHQuery.js";
3
4
 
4
- const scratch_aabb = [];
5
+ /**
6
+ * We read node bounds here
7
+ * @type {Float32Array}
8
+ */
9
+ const scratch_aabb = new Float32Array(6);
5
10
 
6
11
  export class BVHQueryIntersectsSphere extends BVHQuery {
7
12
 
8
13
  /**
9
- *
14
+ * [x,y,z,radius]
10
15
  * @type {number[]}
11
16
  */
12
- sphere = [];
17
+ sphere = [0,0,0,0];
13
18
 
14
19
  /**
15
20
  *
16
- * @param {number[]|ArrayLike<number>} sphere
21
+ * @param {number[]|ArrayLike<number>} sphere (x,y,z,radius)
17
22
  * @returns {BVHQueryIntersectsRay}
18
23
  */
19
24
  static from(sphere) {
25
+ assert.isArrayLike(sphere, 'sphere');
26
+
20
27
  const r = new BVHQueryIntersectsSphere();
21
28
 
22
29
  r.sphere = sphere;
@@ -9,7 +9,29 @@ export namespace EntityManagerState {
9
9
  }
10
10
  /**
11
11
  * Brings together {@link System}s and an {@link EntityComponentDataset}
12
- * Main entry point into the simulation process
12
+ * Main entry point into the simulation process.
13
+ *
14
+ * @example
15
+ * const em = new EntityManager()
16
+ *
17
+ * em.addSystem(new MySystem())
18
+ * em.addSystem(new MyOtherSystem())
19
+ *
20
+ * em.attachDataset(new EntityComponentDataset())
21
+ *
22
+ * em.startup();
23
+ *
24
+ * // ..
25
+ *
26
+ * em.simulate(0.016); // advance simulation forward by 16ms
27
+ *
28
+ * // ..
29
+ *
30
+ * em.shutdown();
31
+ *
32
+ * // ..
33
+ *
34
+ * em.detachDataset();
13
35
  *
14
36
  * @author Alex Goldring
15
37
  * @copyright Company Named Limited (c) 2025
@@ -179,11 +201,11 @@ export class EntityManager {
179
201
  */
180
202
  promiseSystem(systemClass: Class): Promise<System<any, any, any, any, any>>;
181
203
  /**
182
- * @param {Class} systemClass
204
+ * @param {Class} SystemClass
183
205
  * @param {SystemState} state
184
206
  * @returns {Promise.<System>}
185
207
  */
186
- promiseSystemInState(systemClass: Class, state: SystemState): Promise<System<any, any, any, any, any>>;
208
+ promiseSystemInState(SystemClass: Class, state: SystemState): Promise<System<any, any, any, any, any>>;
187
209
  /**
188
210
  * This method is asynchronous by nature, it will not be done until each system has finished its shutdown
189
211
  * Make sure to use callback to be notified when the shutdown has completed
@@ -1 +1 @@
1
- {"version":3,"file":"EntityManager.d.ts","sourceRoot":"","sources":["../../../../src/engine/ecs/EntityManager.js"],"names":[],"mappings":"iCAgBU,MAAM;;;;;;;;;AAiBhB;;;;;;GAMG;AACH;IAEI;;;;OAIG;IACH,kBAFU,iCAAQ,CAEL;IAEb;;;;;;OAMG;IACH,uCAA2B;IAE3B;;;;;OAKG;IACH,iCAA4B;IAE5B;;OAEG;IACH;;;QAGI;;WAEG;qBADO,uCAAc;;MAI1B;IAEF;;;OAGG;IACH,OAFU,kBAAkB,CAEO;IAEnC;;;;;;OAMG;IACH,gDAA2C;IAE3C;;;;;;;;;OASG;IACH,qBAFU,MAAM,CAEqB;IAErC;;;;;OAKG;IACH,wCAFU,MAAM,CAE4B;IAE5C;;;;OAIG;IACH,SAFU,sBAAsB,CAEjB;IAEf;;;;;OAKG;IACH,uCAAsC;IAEtC;;;OAGG;IACH,6BAmFC;IAED;;;OAGG;IACH,uBAFa,OAAO,CAuBnB;IAED;;;;;OAKG;IACH,uBAJW,sBAAsB,QA4ChC;IAGD;;;OAGG;IACH,sBA2BC;IAED;;;;OAIG;IACH,qCAFa,OAAO,CAInB;IAED;;;;OAIG;IACH,6CAgBC;IAED;;;;;OAKG;IACH,wCAHW,MAAM,GACJ,IAAI,aAAS,CAiBzB;IAGD;;;OAGG;IACH,oBAFW,MAAM,QAoEhB;IAED;;;;;OAKG;IACH,iEA6DC;IAED;;;;OAIG;IACH,uDAFa,QAAQ,OAAO,CAAC,CA2C5B;IAED;;;;;OAKG;IACH,mBAmCC;IAED;;;;;OAKG;IACH,oBAqFC;IAED;;;;;OAKG;IACH,kEAyEC;IAED;;;;OAIG;IACH,mCAFa,wCAAgB,CA0B5B;IAED;;;;OAIG;IACH,8DAFa,wCAAgB,CAsB5B;IAED;;;;;OAKG;IACH,mEAoFC;IAGL;;OAEG;IACH,yBAxrBe,sBAAsB,UAwrBA;IACrC;;OAEG;IACH,0BAAqC;CATpC;uBAh6BmC,aAAa;mBAR9B,oCAAoC;uCAMhB,6BAA6B"}
1
+ {"version":3,"file":"EntityManager.d.ts","sourceRoot":"","sources":["../../../../src/engine/ecs/EntityManager.js"],"names":[],"mappings":"iCAgBU,MAAM;;;;;;;;;AAiBhB;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH;IAEI;;;;OAIG;IACH,kBAFU,iCAAQ,CAEL;IAEb;;;;;;OAMG;IACH,uCAA2B;IAE3B;;;;;OAKG;IACH,iCAA4B;IAE5B;;OAEG;IACH;;;QAGI;;WAEG;qBADO,uCAAc;;MAI1B;IAEF;;;OAGG;IACH,OAFU,kBAAkB,CAEO;IAEnC;;;;;;OAMG;IACH,gDAA2C;IAE3C;;;;;;;;;OASG;IACH,qBAFU,MAAM,CAEqB;IAErC;;;;;OAKG;IACH,wCAFU,MAAM,CAE4B;IAE5C;;;;OAIG;IACH,SAFU,sBAAsB,CAEjB;IAEf;;;;;OAKG;IACH,uCAAsC;IAEtC;;;OAGG;IACH,6BAmFC;IAED;;;OAGG;IACH,uBAFa,OAAO,CAuBnB;IAED;;;;;OAKG;IACH,uBAJW,sBAAsB,QA4ChC;IAGD;;;OAGG;IACH,sBA2BC;IAED;;;;OAIG;IACH,qCAFa,OAAO,CAInB;IAED;;;;OAIG;IACH,6CAgBC;IAED;;;;;OAKG;IACH,wCAHW,MAAM,GACJ,IAAI,aAAS,CAiBzB;IAGD;;;OAGG;IACH,oBAFW,MAAM,QAoEhB;IAED;;;;;OAKG;IACH,iEA6DC;IAED;;;;OAIG;IACH,uDAFa,QAAQ,OAAO,CAAC,CA2C5B;IAED;;;;;OAKG;IACH,mBAmCC;IAED;;;;;OAKG;IACH,oBAqFC;IAED;;;;;OAKG;IACH,kEAyEC;IAED;;;;OAIG;IACH,mCAFa,wCAAgB,CA0B5B;IAED;;;;OAIG;IACH,8DAFa,wCAAgB,CA0B5B;IAED;;;;;OAKG;IACH,mEAoFC;IAGL;;OAEG;IACH,yBA5rBe,sBAAsB,UA4rBA;IACrC;;OAEG;IACH,0BAAqC;CATpC;uBA17BmC,aAAa;mBAR9B,oCAAoC;uCAMhB,6BAA6B"}
@@ -33,7 +33,29 @@ const DEFAULT_SYSTEM_STARTUP_TIMEOUT_CHECK = 5;
33
33
 
34
34
  /**
35
35
  * Brings together {@link System}s and an {@link EntityComponentDataset}
36
- * Main entry point into the simulation process
36
+ * Main entry point into the simulation process.
37
+ *
38
+ * @example
39
+ * const em = new EntityManager()
40
+ *
41
+ * em.addSystem(new MySystem())
42
+ * em.addSystem(new MyOtherSystem())
43
+ *
44
+ * em.attachDataset(new EntityComponentDataset())
45
+ *
46
+ * em.startup();
47
+ *
48
+ * // ..
49
+ *
50
+ * em.simulate(0.016); // advance simulation forward by 16ms
51
+ *
52
+ * // ..
53
+ *
54
+ * em.shutdown();
55
+ *
56
+ * // ..
57
+ *
58
+ * em.detachDataset();
37
59
  *
38
60
  * @author Alex Goldring
39
61
  * @copyright Company Named Limited (c) 2025
@@ -819,16 +841,20 @@ export class EntityManager {
819
841
  }
820
842
 
821
843
  /**
822
- * @param {Class} systemClass
844
+ * @param {Class} SystemClass
823
845
  * @param {SystemState} state
824
846
  * @returns {Promise.<System>}
825
847
  */
826
- promiseSystemInState(systemClass, state) {
848
+ promiseSystemInState(SystemClass, state) {
849
+
850
+ assert.defined(SystemClass, 'SystemClass');
851
+ assert.enum(state, SystemState, 'state');
852
+
827
853
  const em = this;
828
854
 
829
855
  return new Promise(function (resolve, reject) {
830
856
 
831
- const pSystem = em.promiseSystem(systemClass);
857
+ const pSystem = em.promiseSystem(SystemClass);
832
858
 
833
859
  pSystem.then(function (system) {
834
860
  function tryProcessSystem() {