@antha/entity-2d 0.19.0 → 0.20.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/dist/entity.d.ts CHANGED
@@ -182,6 +182,19 @@ export declare class EntityStore2d<State extends AnyObject = any> {
182
182
  * and then deserializing and passing the given `serializedParams` to that constructor.
183
183
  */
184
184
  deserializeEntity(entityKey: string, serializedParams: string | undefined): Promise<BaseEntity2d>;
185
+ /**
186
+ * Serializes every current entity, in update order, for {@link EntityStore2d.loadSnapshot}.
187
+ * Entities that are marked destroyed but not yet removed are skipped.
188
+ */
189
+ createSnapshot(): SerializedEntity2d[];
190
+ /**
191
+ * Immediately destroys every current entity and recreates the entities from a snapshot made by
192
+ * {@link EntityStore2d.createSnapshot}, in the same order. Only entity params are restored: any
193
+ * state an entity keeps outside of its params is lost, so lock-step peers must all load the
194
+ * snapshot on the same frame to stay in sync. Every entity class in the snapshot must be
195
+ * registered in this store (see `preregisteredEntities`).
196
+ */
197
+ loadSnapshot(snapshot: ReadonlyArray<Readonly<SerializedEntity2d>>): Promise<BaseEntity2d<any, any, any>[]>;
185
198
  /** Create a new instance of the given entity class and add it to this entity store. */
186
199
  addEntity<const NewEntityConstructor extends Entity2dConstructor>(entityClass: NewEntityConstructor, ...params: AddEntity2dParams<NoInfer<NewEntityConstructor>>): Promise<InstanceType<NewEntityConstructor>>;
187
200
  /** Immediately destroys every current entity while leaving the entity store usable. */
@@ -189,6 +202,21 @@ export declare class EntityStore2d<State extends AnyObject = any> {
189
202
  /** Destroys the entity store and all entities contained inside it. */
190
203
  destroy(): void;
191
204
  }
205
+ /**
206
+ * Shape definition for {@link SerializedEntity2d}.
207
+ *
208
+ * @category Internal
209
+ */
210
+ export declare const serializedEntity2dShape: Shape<{
211
+ entityKey: string;
212
+ serializedParams: Shape<import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TUndefined, import("@sinclair/typebox").TString]>>>;
213
+ }>;
214
+ /**
215
+ * One entity in a snapshot from {@link EntityStore2d.createSnapshot}.
216
+ *
217
+ * @category Internal
218
+ */
219
+ export type SerializedEntity2d = typeof serializedEntity2dShape.runtimeType;
192
220
  /**
193
221
  * Shape definition for {@link EntityPositionParams}.
194
222
  *
package/dist/entity.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { assert, check } from '@augment-vir/assert';
2
- import { ConstructorInstanceMap, getObjectTypedEntries, getOrSet, makeWritable, mapObjectValues, } from '@augment-vir/common';
2
+ import { awaitedBlockingMap, ConstructorInstanceMap, getObjectTypedEntries, getOrSet, makeWritable, mapObjectValues, } from '@augment-vir/common';
3
3
  import { System as HitboxSystem, Response, } from 'detect-collisions';
4
- import { assertValidShape, defineShape } from 'object-shape-tester';
4
+ import { assertValidShape, defineShape, optionalShape } from 'object-shape-tester';
5
5
  import { ParticleContainer } from 'pixi.js';
6
6
  import { defineTypedCustomEvent, GenericListenTarget } from 'typed-event-target';
7
7
  export { System as HitboxSystem } from 'detect-collisions';
@@ -272,6 +272,40 @@ export class EntityStore2d {
272
272
  }
273
273
  return await this.addEntity(entityConstructor, entityConstructor.deserialize(serializedParams));
274
274
  }
275
+ /**
276
+ * Serializes every current entity, in update order, for {@link EntityStore2d.loadSnapshot}.
277
+ * Entities that are marked destroyed but not yet removed are skipped.
278
+ */
279
+ createSnapshot() {
280
+ if (this.isDestroyed) {
281
+ throw new Error('Cannot operate on a destroyed entity store.');
282
+ }
283
+ return [...this.currentEntityInstances]
284
+ .filter((entity) => !entity.isDestroyed)
285
+ .map((entity) => {
286
+ return {
287
+ entityKey: entity.entityDefinition.entityKey,
288
+ serializedParams: entity.serialize(),
289
+ };
290
+ });
291
+ }
292
+ /**
293
+ * Immediately destroys every current entity and recreates the entities from a snapshot made by
294
+ * {@link EntityStore2d.createSnapshot}, in the same order. Only entity params are restored: any
295
+ * state an entity keeps outside of its params is lost, so lock-step peers must all load the
296
+ * snapshot on the same frame to stay in sync. Every entity class in the snapshot must be
297
+ * registered in this store (see `preregisteredEntities`).
298
+ */
299
+ async loadSnapshot(snapshot) {
300
+ this.destroyAllEntities();
301
+ /**
302
+ * `addEntity` inserts each entity only after its async init finishes, so creating them in
303
+ * parallel could order the store differently on each peer.
304
+ */
305
+ return await awaitedBlockingMap(snapshot, async (serializedEntity) => {
306
+ return await this.deserializeEntity(serializedEntity.entityKey, serializedEntity.serializedParams);
307
+ });
308
+ }
275
309
  /** Create a new instance of the given entity class and add it to this entity store. */
276
310
  async addEntity(entityClass, ...params) {
277
311
  if (this.isDestroyed) {
@@ -314,6 +348,17 @@ export class EntityStore2d {
314
348
  delete this.listenTarget;
315
349
  }
316
350
  }
351
+ /**
352
+ * Shape definition for {@link SerializedEntity2d}.
353
+ *
354
+ * @category Internal
355
+ */
356
+ export const serializedEntity2dShape = defineShape({
357
+ entityKey: '',
358
+ serializedParams: optionalShape('', {
359
+ alsoUndefined: true,
360
+ }),
361
+ });
317
362
  /**
318
363
  * Shape definition for {@link EntityPositionParams}.
319
364
  *
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@antha/entity-2d",
3
- "version": "0.19.0",
3
+ "version": "0.20.0",
4
4
  "description": "An Antha mod for handling 2D entities.",
5
5
  "keywords": [
6
6
  "vir",
@@ -39,11 +39,11 @@
39
39
  "@augment-vir/common": "^32.3.0"
40
40
  },
41
41
  "devDependencies": {
42
- "@antha/asset": "^0.19.0",
43
- "@antha/audio": "^0.19.0",
44
- "@antha/engine": "^0.19.0",
45
- "@antha/graphics-2d": "^0.19.0",
46
- "@antha/web-test-runner-plugin-pixi": "^0.19.0",
42
+ "@antha/asset": "^0.20.0",
43
+ "@antha/audio": "^0.20.0",
44
+ "@antha/engine": "^0.20.0",
45
+ "@antha/graphics-2d": "^0.20.0",
46
+ "@antha/web-test-runner-plugin-pixi": "^0.20.0",
47
47
  "@augment-vir/test": "^32.3.0",
48
48
  "@web/dev-server-esbuild": "^2.0.0",
49
49
  "@web/test-runner": "^1.0.0",
@@ -55,10 +55,10 @@
55
55
  "typed-event-target": "^4.3.3"
56
56
  },
57
57
  "peerDependencies": {
58
- "@antha/asset": "^0.19.0",
59
- "@antha/audio": "^0.19.0",
60
- "@antha/engine": "^0.19.0",
61
- "@antha/graphics-2d": "^0.19.0",
58
+ "@antha/asset": "^0.20.0",
59
+ "@antha/audio": "^0.20.0",
60
+ "@antha/engine": "^0.20.0",
61
+ "@antha/graphics-2d": "^0.20.0",
62
62
  "detect-collisions": "^10",
63
63
  "element-vir": "^27",
64
64
  "object-shape-tester": "^6",