@m2c2kit/core 0.3.10 → 0.3.11

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2023 Scott T. Yabiku
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -19,4 +19,4 @@ This package implements the m2c2kit core functionality.
19
19
  - [Website](https://m2c2-project.github.io/m2c2kit/)
20
20
  - [Live Examples](https://m2c2-project.github.io/m2c2kit/docs/category/examples)
21
21
  - [Getting Started](https://m2c2-project.github.io/m2c2kit/docs/getting-started)
22
- - [Interactive Tutorial](https://m2c2-project.github.io/m2c2kit/docs/tutorial-fundamentals/fundamentals)
22
+ - [Interactive Tutorials](https://m2c2-project.github.io/m2c2kit/docs/category/tutorials)
package/dist/index.d.ts CHANGED
@@ -720,6 +720,15 @@ interface CallbackOptions {
720
720
  key?: string;
721
721
  }
722
722
 
723
+ /**
724
+ * Notifies when events in the Frame cycle occur on a Game.
725
+ */
726
+ interface FrameCycleEvent extends EventBase {
727
+ target: Game;
728
+ /** difference in milliseconds since the last Frame lifecycle began */
729
+ deltaTime: number;
730
+ }
731
+
723
732
  interface TrialData {
724
733
  [key: string]: string | number | boolean | object | undefined | null;
725
734
  }
@@ -742,7 +751,7 @@ declare class Game implements Activity {
742
751
  i18n?: I18n;
743
752
  private warmupFunctionQueue;
744
753
  private loaderElementsRemoved;
745
- private _dataStore?;
754
+ private _dataStores?;
746
755
  additionalParameters?: unknown;
747
756
  staticTrialSchema: {
748
757
  [key: string]: JsonSchemaDataTypeScriptTypes;
@@ -760,12 +769,13 @@ declare class Game implements Activity {
760
769
  * Saves an item to the activity's key-value store.
761
770
  *
762
771
  * @remarks The underlying persistence provider of the key-value store must
763
- * be previously set in the activity's `Session` before use:
764
- * ```
765
- * const db: IDataStore = new LocalDatabase();
766
- * session.dataStore = db;
767
- * session.initialize();
768
- * ```
772
+ * have been previously provided in `SessionOptions`.
773
+ * @example
774
+ * import { LocalDatabase } from "@m2c2kit/db";
775
+ * const session = new Session({
776
+ * dataStores: [new LocalDatabase()]
777
+ * ...
778
+ * });
769
779
  * @param key - item key
770
780
  * @param value - item value
771
781
  * @param globalStore - if true, treat the item as "global" and not
@@ -778,12 +788,13 @@ declare class Game implements Activity {
778
788
  * Gets an item value from the activity's key-value store.
779
789
  *
780
790
  * @remarks The underlying persistence provider of the key-value store must
781
- * be previously set in the activity's `Session` before use:
782
- * ```
783
- * const db: IDataStore = new LocalDatabase();
784
- * session.dataStore = db;
785
- * session.initialize();
786
- * ```
791
+ * have been previously provided in `SessionOptions`.
792
+ * @example
793
+ * import { LocalDatabase } from "@m2c2kit/db";
794
+ * const session = new Session({
795
+ * dataStores: [new LocalDatabase()]
796
+ * ...
797
+ * });
787
798
  * @param key - item key
788
799
  * @param globalStore - if true, treat the item as "global" and not
789
800
  * associated with a specific activity; global items can be accessed
@@ -795,12 +806,13 @@ declare class Game implements Activity {
795
806
  * Deletes an item value from the activity's key-value store.
796
807
  *
797
808
  * @remarks The underlying persistence provider of the key-value store must
798
- * be previously set in the activity's `Session` before use:
799
- * ```
800
- * const db: IDataStore = new LocalDatabase();
801
- * session.dataStore = db;
802
- * session.initialize();
803
- * ```
809
+ * have been previously provided in `SessionOptions`.
810
+ * @example
811
+ * import { LocalDatabase } from "@m2c2kit/db";
812
+ * const session = new Session({
813
+ * dataStores: [new LocalDatabase()]
814
+ * ...
815
+ * });
804
816
  * @param key - item key
805
817
  * @param globalStore - if true, treat the item as "global" and not
806
818
  * associated with a specific activity; global items can be accessed
@@ -811,24 +823,26 @@ declare class Game implements Activity {
811
823
  * Deletes all items from the activity's key-value store.
812
824
  *
813
825
  * @remarks The underlying persistence provider of the key-value store must
814
- * be previously set in the activity's `Session` before use:
815
- * ```
816
- * const db: IDataStore = new LocalDatabase();
817
- * session.dataStore = db;
818
- * session.initialize();
819
- * ```
826
+ * have been previously provided in `SessionOptions`.
827
+ * @example
828
+ * import { LocalDatabase } from "@m2c2kit/db";
829
+ * const session = new Session({
830
+ * dataStores: [new LocalDatabase()]
831
+ * ...
832
+ * });
820
833
  */
821
834
  storeClearItems(): Promise<void>;
822
835
  /**
823
836
  * Returns keys of all items in the activity's key-value store.
824
837
  *
825
838
  * @remarks The underlying persistence provider of the key-value store must
826
- * be previously set in the activity's `Session` before use:
827
- * ```
828
- * const db: IDataStore = new LocalDatabase();
829
- * session.dataStore = db;
830
- * session.initialize();
831
- * ```
839
+ * have been previously provided in `SessionOptions`.
840
+ * @example
841
+ * import { LocalDatabase } from "@m2c2kit/db";
842
+ * const session = new Session({
843
+ * dataStores: [new LocalDatabase()]
844
+ * ...
845
+ * });
832
846
  * @param globalStore - if true, treat the item as "global" and not
833
847
  * associated with a specific activity; global items can be accessed
834
848
  * by any activity. Default is false.
@@ -838,12 +852,13 @@ declare class Game implements Activity {
838
852
  * Determines if a key exists in the activity's key-value store.
839
853
  *
840
854
  * @remarks The underlying persistence provider of the key-value store must
841
- * be previously set in the activity's `Session` before use:
842
- * ```
843
- * const db: IDataStore = new LocalDatabase();
844
- * session.dataStore = db;
845
- * session.initialize();
846
- * ```
855
+ * have been previously provided in `SessionOptions`.
856
+ * @example
857
+ * import { LocalDatabase } from "@m2c2kit/db";
858
+ * const session = new Session({
859
+ * dataStores: [new LocalDatabase()]
860
+ * ...
861
+ * });
847
862
  * @param key - item key
848
863
  * @param globalStore - if true, treat the item as "global" and not
849
864
  * associated with a specific activity; global items can be accessed
@@ -851,8 +866,8 @@ declare class Game implements Activity {
851
866
  * @returns true if the key exists, false otherwise
852
867
  */
853
868
  storeItemExists(key: string, globalStore?: boolean): Promise<boolean>;
854
- get dataStore(): IDataStore;
855
- set dataStore(dataStore: IDataStore);
869
+ get dataStores(): IDataStore[];
870
+ set dataStores(dataStores: IDataStore[]);
856
871
  private getLocalizationOptionsFromGameParameters;
857
872
  private isLocalizationRequested;
858
873
  setParameters(additionalParameters: unknown): void;
@@ -1150,6 +1165,13 @@ declare class Game implements Activity {
1150
1165
  * @returns - the scene with the screen shot
1151
1166
  */
1152
1167
  private createOutgoingScene;
1168
+ /**
1169
+ * Executes a callback when the frame has finished simulating physics.
1170
+ *
1171
+ * @param callback - function to execute.
1172
+ * @param options - options for the callback.
1173
+ */
1174
+ onFrameDidSimulatePhysics(callback: (frameCycleEvent: FrameCycleEvent) => void, options?: CallbackOptions): void;
1153
1175
  private update;
1154
1176
  private draw;
1155
1177
  private calculateFps;
@@ -1373,6 +1395,8 @@ interface SessionOptions {
1373
1395
  sessionUuid?: string;
1374
1396
  /** URL of session assets folder (which contains wasm binary), if not the default location of "assets" */
1375
1397
  assetsUrl?: string;
1398
+ /** Array of one or more optional databases that implement the IDataStore interface for persisting data. For store item operations, the first data store will be used. */
1399
+ dataStores?: IDataStore[];
1376
1400
  /** After the session initializes, should the session automatically start? Default is true */
1377
1401
  autoStartAfterInit?: boolean;
1378
1402
  /** When an activity ends or is canceled, should the session automatically go to the next activity? Default is true */
@@ -1389,7 +1413,7 @@ declare class Session {
1389
1413
  imageManager: ImageManager;
1390
1414
  currentActivity?: Activity;
1391
1415
  uuid: string;
1392
- dataStore?: IDataStore;
1416
+ dataStores?: IDataStore[];
1393
1417
  private eventListeners;
1394
1418
  private sessionDictionary;
1395
1419
  private canvasKit?;
@@ -1645,8 +1669,8 @@ interface Activity {
1645
1669
  setParameters(additionalParameters: unknown): void;
1646
1670
  /** Additional activity parameters that were set. */
1647
1671
  readonly additionalParameters?: unknown;
1648
- /** Optional store to use for saving data. The implementation of the store is not provided by the \@m2c2kit/core library. */
1649
- dataStore?: IDataStore;
1672
+ /** Optional stores to use for saving data. The implementation of the store is not provided by the \@m2c2kit/core library. */
1673
+ dataStores?: IDataStore[];
1650
1674
  }
1651
1675
 
1652
1676
  /**
@@ -1684,7 +1708,8 @@ declare enum EventType {
1684
1708
  Drag = "Drag",
1685
1709
  DragStart = "DragStart",
1686
1710
  DragEnd = "DragEnd",
1687
- CompositeCustom = "CompositeCustom"
1711
+ CompositeCustom = "CompositeCustom",
1712
+ FrameDidSimulatePhysics = "FrameDidSimulatePhysics"
1688
1713
  }
1689
1714
 
1690
1715
  interface EntityEventListener {
@@ -1807,6 +1832,12 @@ declare abstract class Entity implements EntityOptions {
1807
1832
  * @remarks Throws error if entity is not part of the game object.
1808
1833
  */
1809
1834
  get game(): Game;
1835
+ /**
1836
+ * Determines if the entity has been added to the game object.
1837
+ *
1838
+ * @returns true if entity has been added
1839
+ */
1840
+ private isPartOfGame;
1810
1841
  /**
1811
1842
  * Overrides toString() and returns a human-friendly description of the entity.
1812
1843
  *
@@ -1815,7 +1846,8 @@ declare abstract class Entity implements EntityOptions {
1815
1846
  toString: () => string;
1816
1847
  /**
1817
1848
  * Adds a child to this parent entity. Throws exception if the child's name
1818
- * is not unique with respect to other children of this parent.
1849
+ * is not unique with respect to other children of this parent, or if the
1850
+ * child has already been added to another parent.
1819
1851
  *
1820
1852
  * @param child - The child entity to add
1821
1853
  */
package/dist/index.js CHANGED
@@ -768,6 +768,7 @@ var EventType = /* @__PURE__ */ ((EventType2) => {
768
768
  EventType2["DragStart"] = "DragStart";
769
769
  EventType2["DragEnd"] = "DragEnd";
770
770
  EventType2["CompositeCustom"] = "CompositeCustom";
771
+ EventType2["FrameDidSimulatePhysics"] = "FrameDidSimulatePhysics";
771
772
  return EventType2;
772
773
  })(EventType || {});
773
774
 
@@ -870,9 +871,9 @@ class Entity {
870
871
  type = this.compositeType;
871
872
  }
872
873
  if (this.name !== this.uuid) {
873
- return `"${this.name}" (${type}, ${this.uuid})`;
874
+ return `${this.name} (${type}, ${this.uuid})`;
874
875
  } else {
875
- return `"${type} (${this.uuid})`;
876
+ return `${type} (${this.uuid})`;
876
877
  }
877
878
  });
878
879
  if (options.name === void 0) {
@@ -920,32 +921,91 @@ class Entity {
920
921
  };
921
922
  return findParentScene(this).game;
922
923
  }
924
+ /**
925
+ * Determines if the entity has been added to the game object.
926
+ *
927
+ * @returns true if entity has been added
928
+ */
929
+ isPartOfGame() {
930
+ var _a;
931
+ if (this.type === EntityType.Scene && this._game === void 0) {
932
+ return false;
933
+ }
934
+ if (this.type === EntityType.Scene && this._game !== void 0) {
935
+ return true;
936
+ }
937
+ const findParentScene = (entity) => {
938
+ if (!entity.parent) {
939
+ return void 0;
940
+ } else if (entity.parent.type === EntityType.Scene) {
941
+ return entity.parent;
942
+ } else {
943
+ return findParentScene(entity.parent);
944
+ }
945
+ };
946
+ return ((_a = findParentScene(this)) == null ? void 0 : _a._game) !== void 0;
947
+ }
923
948
  /**
924
949
  * Adds a child to this parent entity. Throws exception if the child's name
925
- * is not unique with respect to other children of this parent.
950
+ * is not unique with respect to other children of this parent, or if the
951
+ * child has already been added to another parent.
926
952
  *
927
953
  * @param child - The child entity to add
928
954
  */
929
955
  addChild(child) {
956
+ if (child === this) {
957
+ throw new Error(
958
+ `Cannot add entity ${child.toString()} as a child to itself.`
959
+ );
960
+ }
930
961
  if (child.type == EntityType.Scene) {
931
962
  throw new Error(
932
- "A scene cannot be the child of an entity. A scene can only be added to a game object"
963
+ `Cannot add scene ${child.toString()} as a child to entity ${this.toString()}. A scene cannot be the child of an entity. A scene can only be added to a game object.`
964
+ );
965
+ }
966
+ if (this.children.filter((c) => c !== child).map((c) => c.name).includes(child.name)) {
967
+ throw new Error(
968
+ `Cannot add child entity ${child.toString()} to parent entity ${this.toString()}. A child with name "${child.name}" already exists on this parent.`
969
+ );
970
+ }
971
+ let otherParents = new Array();
972
+ if (this.isPartOfGame()) {
973
+ otherParents = this.game.entities.filter(
974
+ (e) => e.children.includes(child)
933
975
  );
976
+ } else {
977
+ const descendants = this.descendants;
978
+ if (descendants.includes(child)) {
979
+ otherParents = descendants.filter((d) => d.children.includes(child)).map((d) => {
980
+ var _a;
981
+ return (_a = d.parent) != null ? _a : void 0;
982
+ });
983
+ }
984
+ }
985
+ if (otherParents.length === 0) {
986
+ child.parent = this;
987
+ this.children.push(child);
988
+ return;
934
989
  }
935
- child.parent = this;
936
- if (this.children.map((c) => c.name).includes(child.name)) {
990
+ const firstOtherParent = otherParents.find(Boolean);
991
+ if (firstOtherParent === this) {
937
992
  throw new Error(
938
- `Cannot add child entity ${child.toString()} to parent entity ${this.toString()}. A child with name "${child.name}" already exists on parent.`
993
+ `Cannot add child entity ${child.toString()} to parent entity ${this.toString()}. This child already exists on this parent. The child cannot be added again.`
939
994
  );
940
995
  }
941
- this.children.push(child);
996
+ throw new Error(
997
+ `Cannot add child entity ${child.toString()} to parent entity ${this.toString()}. This child already exists on other parent entity: ${firstOtherParent == null ? void 0 : firstOtherParent.toString()}}. Remove the child from the other parent first.`
998
+ );
942
999
  }
943
1000
  /**
944
1001
  * Removes all children from the entity.
945
1002
  */
946
1003
  removeAllChildren() {
947
1004
  while (this.children.length) {
948
- this.children.pop();
1005
+ const child = this.children.pop();
1006
+ if (child) {
1007
+ child.parent = void 0;
1008
+ }
949
1009
  }
950
1010
  }
951
1011
  /**
@@ -956,6 +1016,7 @@ class Entity {
956
1016
  */
957
1017
  removeChild(child) {
958
1018
  if (this.children.includes(child)) {
1019
+ child.parent = void 0;
959
1020
  this.children = this.children.filter((c) => c !== child);
960
1021
  } else {
961
1022
  throw new Error(
@@ -976,6 +1037,7 @@ class Entity {
976
1037
  `cannot remove entity ${child} from parent ${this} because the entity is not currently a child of the parent`
977
1038
  );
978
1039
  }
1040
+ child.parent = void 0;
979
1041
  });
980
1042
  this.children = this.children.filter((child) => !children.includes(child));
981
1043
  }
@@ -3243,7 +3305,7 @@ class Game {
3243
3305
  __publicField$6(this, "i18n");
3244
3306
  __publicField$6(this, "warmupFunctionQueue", new Array());
3245
3307
  __publicField$6(this, "loaderElementsRemoved", false);
3246
- __publicField$6(this, "_dataStore");
3308
+ __publicField$6(this, "_dataStores");
3247
3309
  __publicField$6(this, "additionalParameters");
3248
3310
  __publicField$6(this, "staticTrialSchema", {});
3249
3311
  /** The scene, or its name as a string, to be presented when the game is started. If this is undefined, the game will start with the first scene that has been added */
@@ -3359,12 +3421,13 @@ class Game {
3359
3421
  * Saves an item to the activity's key-value store.
3360
3422
  *
3361
3423
  * @remarks The underlying persistence provider of the key-value store must
3362
- * be previously set in the activity's `Session` before use:
3363
- * ```
3364
- * const db: IDataStore = new LocalDatabase();
3365
- * session.dataStore = db;
3366
- * session.initialize();
3367
- * ```
3424
+ * have been previously provided in `SessionOptions`.
3425
+ * @example
3426
+ * import { LocalDatabase } from "@m2c2kit/db";
3427
+ * const session = new Session({
3428
+ * dataStores: [new LocalDatabase()]
3429
+ * ...
3430
+ * });
3368
3431
  * @param key - item key
3369
3432
  * @param value - item value
3370
3433
  * @param globalStore - if true, treat the item as "global" and not
@@ -3375,18 +3438,19 @@ class Game {
3375
3438
  storeSetItem(key, value, globalStore = false) {
3376
3439
  const k = globalStore ? key : this.id.concat(":", key);
3377
3440
  const activityId = globalStore ? "" : this.id;
3378
- return this.dataStore.setItem(k, value, activityId);
3441
+ return this.dataStores[0].setItem(k, value, activityId);
3379
3442
  }
3380
3443
  /**
3381
3444
  * Gets an item value from the activity's key-value store.
3382
3445
  *
3383
3446
  * @remarks The underlying persistence provider of the key-value store must
3384
- * be previously set in the activity's `Session` before use:
3385
- * ```
3386
- * const db: IDataStore = new LocalDatabase();
3387
- * session.dataStore = db;
3388
- * session.initialize();
3389
- * ```
3447
+ * have been previously provided in `SessionOptions`.
3448
+ * @example
3449
+ * import { LocalDatabase } from "@m2c2kit/db";
3450
+ * const session = new Session({
3451
+ * dataStores: [new LocalDatabase()]
3452
+ * ...
3453
+ * });
3390
3454
  * @param key - item key
3391
3455
  * @param globalStore - if true, treat the item as "global" and not
3392
3456
  * associated with a specific activity; global items can be accessed
@@ -3395,18 +3459,19 @@ class Game {
3395
3459
  */
3396
3460
  storeGetItem(key, globalStore = false) {
3397
3461
  const k = globalStore ? key : this.id.concat(":", key);
3398
- return this.dataStore.getItem(k);
3462
+ return this.dataStores[0].getItem(k);
3399
3463
  }
3400
3464
  /**
3401
3465
  * Deletes an item value from the activity's key-value store.
3402
3466
  *
3403
3467
  * @remarks The underlying persistence provider of the key-value store must
3404
- * be previously set in the activity's `Session` before use:
3405
- * ```
3406
- * const db: IDataStore = new LocalDatabase();
3407
- * session.dataStore = db;
3408
- * session.initialize();
3409
- * ```
3468
+ * have been previously provided in `SessionOptions`.
3469
+ * @example
3470
+ * import { LocalDatabase } from "@m2c2kit/db";
3471
+ * const session = new Session({
3472
+ * dataStores: [new LocalDatabase()]
3473
+ * ...
3474
+ * });
3410
3475
  * @param key - item key
3411
3476
  * @param globalStore - if true, treat the item as "global" and not
3412
3477
  * associated with a specific activity; global items can be accessed
@@ -3414,49 +3479,52 @@ class Game {
3414
3479
  */
3415
3480
  storeDeleteItem(key, globalStore = false) {
3416
3481
  const k = globalStore ? key : this.id.concat(":", key);
3417
- return this.dataStore.deleteItem(k);
3482
+ return this.dataStores[0].deleteItem(k);
3418
3483
  }
3419
3484
  /**
3420
3485
  * Deletes all items from the activity's key-value store.
3421
3486
  *
3422
3487
  * @remarks The underlying persistence provider of the key-value store must
3423
- * be previously set in the activity's `Session` before use:
3424
- * ```
3425
- * const db: IDataStore = new LocalDatabase();
3426
- * session.dataStore = db;
3427
- * session.initialize();
3428
- * ```
3488
+ * have been previously provided in `SessionOptions`.
3489
+ * @example
3490
+ * import { LocalDatabase } from "@m2c2kit/db";
3491
+ * const session = new Session({
3492
+ * dataStores: [new LocalDatabase()]
3493
+ * ...
3494
+ * });
3429
3495
  */
3430
3496
  storeClearItems() {
3431
- return this.dataStore.clearItemsByActivityId(this.id);
3497
+ return this.dataStores[0].clearItemsByActivityId(this.id);
3432
3498
  }
3433
3499
  /**
3434
3500
  * Returns keys of all items in the activity's key-value store.
3435
3501
  *
3436
3502
  * @remarks The underlying persistence provider of the key-value store must
3437
- * be previously set in the activity's `Session` before use:
3438
- * ```
3439
- * const db: IDataStore = new LocalDatabase();
3440
- * session.dataStore = db;
3441
- * session.initialize();
3442
- * ```
3503
+ * have been previously provided in `SessionOptions`.
3504
+ * @example
3505
+ * import { LocalDatabase } from "@m2c2kit/db";
3506
+ * const session = new Session({
3507
+ * dataStores: [new LocalDatabase()]
3508
+ * ...
3509
+ * });
3443
3510
  * @param globalStore - if true, treat the item as "global" and not
3444
3511
  * associated with a specific activity; global items can be accessed
3445
3512
  * by any activity. Default is false.
3446
3513
  */
3447
3514
  storeItemsKeys(globalStore = false) {
3448
- return this.dataStore.itemsKeysByActivityId(globalStore ? "" : this.id);
3515
+ return this.dataStores[0].itemsKeysByActivityId(globalStore ? "" : this.id);
3449
3516
  }
3450
3517
  /**
3451
3518
  * Determines if a key exists in the activity's key-value store.
3452
3519
  *
3453
3520
  * @remarks The underlying persistence provider of the key-value store must
3454
- * be previously set in the activity's `Session` before use:
3455
- * ```
3456
- * const db: IDataStore = new LocalDatabase();
3457
- * session.dataStore = db;
3458
- * session.initialize();
3459
- * ```
3521
+ * have been previously provided in `SessionOptions`.
3522
+ * @example
3523
+ * import { LocalDatabase } from "@m2c2kit/db";
3524
+ * const session = new Session({
3525
+ * dataStores: [new LocalDatabase()]
3526
+ * ...
3527
+ * });
3460
3528
  * @param key - item key
3461
3529
  * @param globalStore - if true, treat the item as "global" and not
3462
3530
  * associated with a specific activity; global items can be accessed
@@ -3465,16 +3533,16 @@ class Game {
3465
3533
  */
3466
3534
  storeItemExists(key, globalStore = false) {
3467
3535
  const k = globalStore ? key : this.id.concat(":", key);
3468
- return this.dataStore.itemExists(k);
3536
+ return this.dataStores[0].itemExists(k);
3469
3537
  }
3470
- get dataStore() {
3471
- if (!this._dataStore) {
3472
- throw new Error("dataStore is undefined");
3538
+ get dataStores() {
3539
+ if (!this._dataStores) {
3540
+ throw new Error("dataStores is undefined");
3473
3541
  }
3474
- return this._dataStore;
3542
+ return this._dataStores;
3475
3543
  }
3476
- set dataStore(dataStore) {
3477
- this._dataStore = dataStore;
3544
+ set dataStores(dataStores) {
3545
+ this._dataStores = dataStores;
3478
3546
  }
3479
3547
  getLocalizationOptionsFromGameParameters() {
3480
3548
  const locale = this.getParameter("locale");
@@ -4688,9 +4756,28 @@ class Game {
4688
4756
  outgoingScene.addChild(spr);
4689
4757
  return outgoingScene;
4690
4758
  }
4759
+ /**
4760
+ * Executes a callback when the frame has finished simulating physics.
4761
+ *
4762
+ * @param callback - function to execute.
4763
+ * @param options - options for the callback.
4764
+ */
4765
+ onFrameDidSimulatePhysics(callback, options) {
4766
+ this.addEventListener(
4767
+ EventType.FrameDidSimulatePhysics,
4768
+ callback,
4769
+ options
4770
+ );
4771
+ }
4691
4772
  update() {
4692
4773
  this.scenes.filter((scene) => scene._active).forEach((scene) => scene.update());
4693
4774
  this.freeEntitiesScene.update();
4775
+ const frameDidSimulatePhysicsEvent = {
4776
+ target: this,
4777
+ type: EventType.FrameDidSimulatePhysics,
4778
+ deltaTime: Globals.deltaTime
4779
+ };
4780
+ this.raiseActivityEventOnListeners(frameDidSimulatePhysicsEvent);
4694
4781
  }
4695
4782
  draw(canvas) {
4696
4783
  this.scenes.filter((scene) => scene._active).forEach((scene) => scene.draw(canvas));
@@ -7012,12 +7099,12 @@ class Session {
7012
7099
  __publicField$2(this, "imageManager");
7013
7100
  __publicField$2(this, "currentActivity");
7014
7101
  __publicField$2(this, "uuid");
7015
- __publicField$2(this, "dataStore");
7102
+ __publicField$2(this, "dataStores");
7016
7103
  __publicField$2(this, "eventListeners", new Array());
7017
7104
  __publicField$2(this, "sessionDictionary", /* @__PURE__ */ new Map());
7018
7105
  __publicField$2(this, "canvasKit");
7019
7106
  __publicField$2(this, "initialized", false);
7020
- __publicField$2(this, "version", "0.3.10 (b15b374e)");
7107
+ __publicField$2(this, "version", "0.3.11 (25099410)");
7021
7108
  this.options = options;
7022
7109
  for (const activity of this.options.activities) {
7023
7110
  if (this.options.activities.filter((a) => a === activity).length > 1) {
@@ -7184,6 +7271,7 @@ class Session {
7184
7271
  * Asynchronously initializes the m2c2kit engine and loads assets
7185
7272
  */
7186
7273
  async initialize() {
7274
+ var _a;
7187
7275
  console.log(`\u26AA @m2c2kit/core version ${this.version}`);
7188
7276
  Timer.start("sessionInitialize");
7189
7277
  const sessionInitializeEvent = {
@@ -7194,9 +7282,15 @@ class Session {
7194
7282
  DomHelpers.addLoadingElements();
7195
7283
  DomHelpers.setSpinnerVisibility(true);
7196
7284
  DomHelpers.setCanvasOverlayVisibility(true);
7285
+ this.dataStores = this.options.dataStores;
7286
+ if (((_a = this.dataStores) == null ? void 0 : _a.length) === 0) {
7287
+ throw new Error(
7288
+ "Session.initialize(): dataStores must be undefined or a non-zero array of datastores."
7289
+ );
7290
+ }
7197
7291
  await Promise.all(
7198
7292
  this.options.activities.map((activity) => {
7199
- activity.dataStore = this.dataStore;
7293
+ activity.dataStores = this.dataStores;
7200
7294
  activity.onStart(this.sessionActivityLifecycleHandler.bind(this));
7201
7295
  activity.onCancel(this.sessionActivityLifecycleHandler.bind(this));
7202
7296
  activity.onEnd(this.sessionActivityLifecycleHandler.bind(this));
@@ -7322,7 +7416,7 @@ class Session {
7322
7416
  this.options.activities[indexOfCurrentActivity] = this.currentActivity;
7323
7417
  DomHelpers.configureDomForActivity(this.currentActivity);
7324
7418
  this.currentActivity.session = this;
7325
- this.currentActivity.dataStore = this.dataStore;
7419
+ this.currentActivity.dataStores = this.dataStores;
7326
7420
  if (this.currentActivity.type === ActivityType.Game && this.canvasKit) {
7327
7421
  this.currentActivity.canvasKit = this.canvasKit;
7328
7422
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@m2c2kit/core",
3
- "version": "0.3.10",
3
+ "version": "0.3.11",
4
4
  "description": "The m2c2kit core functionality",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.js",
@@ -22,6 +22,16 @@
22
22
  "test": "cd ../.. && npx env-cmd -f .env.jest jest --selectProjects @m2c2kit/core"
23
23
  },
24
24
  "license": "MIT",
25
+ "author": {
26
+ "name": "Scott T. Yabiku",
27
+ "email": "syabiku@gmail.com"
28
+ },
29
+ "repository": {
30
+ "type": "git",
31
+ "url": "https://github.com/m2c2-project/m2c2kit.git",
32
+ "directory": "packages/core"
33
+ },
34
+ "homepage": "https://m2c2-project.github.io/m2c2kit",
25
35
  "devDependencies": {
26
36
  "@rollup/plugin-commonjs": "25.0.2",
27
37
  "@rollup/plugin-node-resolve": "15.1.0",
@@ -37,12 +47,15 @@
37
47
  "jest-environment-jsdom": "29.5.0",
38
48
  "jsdom": "22.1.0",
39
49
  "rimraf": "5.0.1",
40
- "rollup": "3.25.1",
50
+ "rollup": "3.25.3",
41
51
  "rollup-plugin-copy": "3.4.0",
42
52
  "rollup-plugin-dts": "5.3.0",
43
53
  "rollup-plugin-esbuild": "5.0.0",
44
54
  "rollup-plugin-polyfill-node": "0.12.0",
45
55
  "ts-jest": "29.1.0",
46
- "typescript": "5.1.3"
56
+ "typescript": "5.1.6"
57
+ },
58
+ "engines": {
59
+ "node": ">=18"
47
60
  }
48
61
  }