@colyseus/schema 3.0.24 → 3.0.26

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.
@@ -960,6 +960,9 @@ const Metadata = {
960
960
  }
961
961
  };
962
962
 
963
+ function createChangeSet() {
964
+ return { indexes: {}, operations: [] };
965
+ }
963
966
  function setOperationAtIndex(changeSet, index) {
964
967
  const operationsIndex = changeSet.indexes[index];
965
968
  if (operationsIndex === undefined) {
@@ -977,7 +980,11 @@ function deleteOperationAtIndex(changeSet, index) {
977
980
  delete changeSet.indexes[index];
978
981
  }
979
982
  function enqueueChangeTree(root, changeTree, changeSet, queueRootIndex = changeTree[changeSet].queueRootIndex) {
980
- if (root && root[changeSet][queueRootIndex] !== changeTree) {
983
+ if (!root) {
984
+ // skip
985
+ return;
986
+ }
987
+ else if (root[changeSet][queueRootIndex] !== changeTree) {
981
988
  changeTree[changeSet].queueRootIndex = root[changeSet].push(changeTree) - 1;
982
989
  }
983
990
  }
@@ -1132,7 +1139,7 @@ class ChangeTree {
1132
1139
  const newIndexes = {};
1133
1140
  for (const index in this.indexedOperations) {
1134
1141
  newIndexedOperations[Number(index) + shiftIndex] = this.indexedOperations[index];
1135
- newIndexes[Number(index) + shiftIndex] = changeSet[index];
1142
+ newIndexes[Number(index) + shiftIndex] = changeSet.indexes[index];
1136
1143
  }
1137
1144
  this.indexedOperations = newIndexedOperations;
1138
1145
  changeSet.indexes = newIndexes;
@@ -1226,6 +1233,7 @@ class ChangeTree {
1226
1233
  : this.changes;
1227
1234
  this.indexedOperations[index] = operation ?? exports.OPERATION.DELETE;
1228
1235
  setOperationAtIndex(changeSet, index);
1236
+ deleteOperationAtIndex(this.allChanges, allChangesIndex);
1229
1237
  const previousValue = this.getValue(index);
1230
1238
  // remove `root` reference
1231
1239
  if (previousValue && previousValue[$changes]) {
@@ -1241,7 +1249,6 @@ class ChangeTree {
1241
1249
  //
1242
1250
  this.root?.remove(previousValue[$changes]);
1243
1251
  }
1244
- deleteOperationAtIndex(this.allChanges, allChangesIndex);
1245
1252
  //
1246
1253
  // FIXME: this is looking a ugly and repeated
1247
1254
  //
@@ -1254,11 +1261,12 @@ class ChangeTree {
1254
1261
  }
1255
1262
  return previousValue;
1256
1263
  }
1257
- endEncode() {
1264
+ endEncode(changeSetName) {
1258
1265
  this.indexedOperations = {};
1259
- // // clear changes
1260
- // this.changes.indexes = {};
1261
- // this.changes.operations.length = 0;
1266
+ // clear changeset
1267
+ this[changeSetName].indexes = {};
1268
+ this[changeSetName].operations.length = 0;
1269
+ this[changeSetName].queueRootIndex = undefined;
1262
1270
  // ArraySchema and MapSchema have a custom "encode end" method
1263
1271
  this.ref[$onEncodeEnd]?.();
1264
1272
  // Not a new instance anymore
@@ -1365,24 +1373,19 @@ class ChangeTree {
1365
1373
  || this.root.types.parentFiltered[key]
1366
1374
  || parentConstructor?.[Symbol.metadata]?.[$viewFieldIndexes]?.includes(parentIndex);
1367
1375
  //
1368
- // TODO: refactor this!
1369
- //
1370
- // swapping `changes` and `filteredChanges` is required here
1371
- // because "isFiltered" may not be imedialely available on `change()`
1372
- // (this happens when instance is detached from root or parent)
1376
+ // "isFiltered" may not be imedialely available during `change()` due to the instance not being attached to the root yet.
1377
+ // when it's available, we need to enqueue the "changes" changeset into the "filteredChanges" changeset.
1373
1378
  //
1374
1379
  if (this.isFiltered) {
1375
- this.filteredChanges = { indexes: {}, operations: [] };
1376
- this.allFilteredChanges = { indexes: {}, operations: [] };
1380
+ if (!this.filteredChanges) {
1381
+ this.filteredChanges = createChangeSet();
1382
+ this.allFilteredChanges = createChangeSet();
1383
+ }
1377
1384
  if (this.changes.operations.length > 0) {
1378
- // swap changes reference
1379
- const changes = this.changes;
1380
- this.changes = this.filteredChanges;
1381
- this.filteredChanges = changes;
1382
- // swap "all changes" reference
1383
- const allFilteredChanges = this.allFilteredChanges;
1384
- this.allFilteredChanges = this.allChanges;
1385
- this.allChanges = allFilteredChanges;
1385
+ this.changes.operations.forEach((index) => setOperationAtIndex(this.filteredChanges, index));
1386
+ this.allChanges.operations.forEach((index) => setOperationAtIndex(this.allFilteredChanges, index));
1387
+ this.changes = createChangeSet();
1388
+ this.allChanges = createChangeSet();
1386
1389
  }
1387
1390
  }
1388
1391
  }
@@ -2098,10 +2101,11 @@ class ArraySchema {
2098
2101
  return undefined;
2099
2102
  }
2100
2103
  // const index = Number(Object.keys(changeTree.indexes)[0]);
2101
- const index = this.tmpItems.findIndex((item, i) => item === this.items[0]);
2102
2104
  const changeTree = this[$changes];
2103
- changeTree.delete(index);
2104
- changeTree.shiftAllChangeIndexes(-1, index);
2105
+ const index = this.tmpItems.findIndex(item => item === this.items[0]);
2106
+ const allChangesIndex = this.items.findIndex(item => item === this.items[0]);
2107
+ changeTree.delete(index, exports.OPERATION.DELETE, allChangesIndex);
2108
+ changeTree.shiftAllChangeIndexes(-1, allChangesIndex);
2105
2109
  // this.deletedIndexes[index] = true;
2106
2110
  return this.items.shift();
2107
2111
  }
@@ -3662,19 +3666,6 @@ typeof SuppressedError === "function" ? SuppressedError : function (error, suppr
3662
3666
  return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
3663
3667
  };
3664
3668
 
3665
- function spliceOne(arr, index) {
3666
- // manually splice an array
3667
- if (index === -1 || index >= arr.length) {
3668
- return false;
3669
- }
3670
- const len = arr.length - 1;
3671
- for (let i = index; i < len; i++) {
3672
- arr[i] = arr[i + 1];
3673
- }
3674
- arr.length = len;
3675
- return true;
3676
- }
3677
-
3678
3669
  class Root {
3679
3670
  constructor(types) {
3680
3671
  this.types = types;
@@ -3755,11 +3746,16 @@ class Root {
3755
3746
  }
3756
3747
  removeChangeFromChangeSet(changeSetName, changeTree) {
3757
3748
  const changeSet = this[changeSetName];
3758
- if (spliceOne(changeSet, changeSet.indexOf(changeTree))) {
3749
+ const changeSetIndex = changeSet.indexOf(changeTree);
3750
+ if (changeSetIndex !== -1) {
3759
3751
  changeTree[changeSetName].queueRootIndex = -1;
3760
- // changeSet[index] = undefined;
3752
+ changeSet[changeSetIndex] = undefined;
3761
3753
  return true;
3762
3754
  }
3755
+ // if (spliceOne(changeSet, changeSet.indexOf(changeTree))) {
3756
+ // changeTree[changeSetName].queueRootIndex = -1;
3757
+ // return true;
3758
+ // }
3763
3759
  }
3764
3760
  clear() {
3765
3761
  this.changes.length = 0;
@@ -3792,10 +3788,12 @@ class Encoder {
3792
3788
  ) {
3793
3789
  const hasView = (view !== undefined);
3794
3790
  const rootChangeTree = this.state[$changes];
3795
- const shouldDiscardChanges = !isEncodeAll && !hasView;
3796
3791
  const changeTrees = this.root[changeSetName];
3797
3792
  for (let i = 0, numChangeTrees = changeTrees.length; i < numChangeTrees; i++) {
3798
3793
  const changeTree = changeTrees[i];
3794
+ if (!changeTree) {
3795
+ continue;
3796
+ }
3799
3797
  if (hasView) {
3800
3798
  if (!view.visible.has(changeTree)) {
3801
3799
  view.invisible.add(changeTree);
@@ -3843,10 +3841,6 @@ class Encoder {
3843
3841
  }
3844
3842
  encoder(this, buffer, changeTree, fieldIndex, operation, it, isEncodeAll, hasView, metadata);
3845
3843
  }
3846
- // if (shouldDiscardChanges) {
3847
- // changeTree.discard();
3848
- // changeTree.isNew = false; // Not a new instance anymore
3849
- // }
3850
3844
  }
3851
3845
  if (it.offset > buffer.byteLength) {
3852
3846
  // we can assume that n + 1 poolSize will suffice given that we are likely done with encoding at this point
@@ -3870,19 +3864,6 @@ class Encoder {
3870
3864
  return this.encode({ offset: initialOffset }, view, buffer, changeSetName, isEncodeAll);
3871
3865
  }
3872
3866
  else {
3873
- //
3874
- // only clear changes after making sure buffer resize is not required.
3875
- //
3876
- if (shouldDiscardChanges) {
3877
- //
3878
- // TODO: avoid iterating over change trees twice.
3879
- //
3880
- for (let i = 0, numChangeTrees = changeTrees.length; i < numChangeTrees; i++) {
3881
- const changeTree = changeTrees[i];
3882
- changeTree.discard();
3883
- changeTree.isNew = false; // Not a new instance anymore
3884
- }
3885
- }
3886
3867
  return buffer.subarray(0, it.offset);
3887
3868
  }
3888
3869
  }
@@ -3967,7 +3948,7 @@ class Encoder {
3967
3948
  let length = this.root.changes.length;
3968
3949
  if (length > 0) {
3969
3950
  while (length--) {
3970
- this.root.changes[length]?.endEncode();
3951
+ this.root.changes[length]?.endEncode('changes');
3971
3952
  }
3972
3953
  this.root.changes.length = 0;
3973
3954
  }
@@ -3975,7 +3956,7 @@ class Encoder {
3975
3956
  length = this.root.filteredChanges.length;
3976
3957
  if (length > 0) {
3977
3958
  while (length--) {
3978
- this.root.filteredChanges[length]?.endEncode();
3959
+ this.root.filteredChanges[length]?.endEncode('filteredChanges');
3979
3960
  }
3980
3961
  this.root.filteredChanges.length = 0;
3981
3962
  }
@@ -3998,6 +3979,19 @@ class Encoder {
3998
3979
  }
3999
3980
  }
4000
3981
 
3982
+ function spliceOne(arr, index) {
3983
+ // manually splice an array
3984
+ if (index === -1 || index >= arr.length) {
3985
+ return false;
3986
+ }
3987
+ const len = arr.length - 1;
3988
+ for (let i = index; i < len; i++) {
3989
+ arr[i] = arr[i + 1];
3990
+ }
3991
+ arr.length = len;
3992
+ return true;
3993
+ }
3994
+
4001
3995
  class DecodingWarning extends Error {
4002
3996
  constructor(message) {
4003
3997
  super(message);