@colyseus/schema 3.0.29 → 3.0.30

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.
@@ -28,6 +28,8 @@ export class ArraySchema<V = any> implements Array<V>, Collection<number, V> {
28
28
  static [$encoder] = encodeArray;
29
29
  static [$decoder] = decodeArray;
30
30
 
31
+ protected isMovingItems = false;
32
+
31
33
  /**
32
34
  * Determine if a property must be filtered.
33
35
  * - If returns false, the property is NOT going to be encoded.
@@ -60,7 +62,6 @@ export class ArraySchema<V = any> implements Array<V>, Collection<number, V> {
60
62
  }
61
63
 
62
64
  constructor (...items: V[]) {
63
-
64
65
  Object.defineProperty(this, $childType, {
65
66
  value: undefined,
66
67
  enumerable: false,
@@ -92,33 +93,42 @@ export class ArraySchema<V = any> implements Array<V>, Collection<number, V> {
92
93
  assertInstanceType(setValue, obj[$childType] as typeof Schema, obj, key);
93
94
 
94
95
  const previousValue = obj.items[key as unknown as number];
95
- if (previousValue !== undefined) {
96
- if (setValue[$changes].isNew) {
97
- this[$changes].indexedOperation(Number(key), OPERATION.MOVE_AND_ADD);
98
96
 
99
- } else {
100
- if ((obj[$changes].getChange(Number(key)) & OPERATION.DELETE) === OPERATION.DELETE) {
101
- this[$changes].indexedOperation(Number(key), OPERATION.DELETE_AND_MOVE);
97
+ if (!obj.isMovingItems) {
98
+ obj.$changeAt(Number(key), setValue);
99
+
100
+ } else {
101
+ if (previousValue !== undefined) {
102
+ if (setValue[$changes].isNew) {
103
+ obj[$changes].indexedOperation(Number(key), OPERATION.MOVE_AND_ADD);
104
+
102
105
  } else {
103
- this[$changes].indexedOperation(Number(key), OPERATION.MOVE);
106
+ if ((obj[$changes].getChange(Number(key)) & OPERATION.DELETE) === OPERATION.DELETE) {
107
+ obj[$changes].indexedOperation(Number(key), OPERATION.DELETE_AND_MOVE);
108
+
109
+ } else {
110
+ obj[$changes].indexedOperation(Number(key), OPERATION.MOVE);
111
+ }
104
112
  }
113
+
114
+ } else if (setValue[$changes].isNew) {
115
+ obj[$changes].indexedOperation(Number(key), OPERATION.ADD);
105
116
  }
106
117
 
118
+ setValue[$changes].setParent(this, obj[$changes].root, key);
119
+ }
120
+
121
+ if (previousValue !== undefined) {
107
122
  // remove root reference from previous value
108
123
  previousValue[$changes].root?.remove(previousValue[$changes]);
109
-
110
- } else if (setValue[$changes].isNew) {
111
- this[$changes].indexedOperation(Number(key), OPERATION.ADD);
112
124
  }
113
125
 
114
- setValue[$changes].setParent(this, obj[$changes].root, key);
115
-
116
126
  } else {
117
127
  obj.$changeAt(Number(key), setValue);
118
128
  }
119
129
 
120
- this.items[key as unknown as number] = setValue;
121
- this.tmpItems[key as unknown as number] = setValue;
130
+ obj.items[key as unknown as number] = setValue;
131
+ obj.tmpItems[key as unknown as number] = setValue;
122
132
  }
123
133
 
124
134
  return true;
@@ -251,9 +261,13 @@ export class ArraySchema<V = any> implements Array<V>, Collection<number, V> {
251
261
  return;
252
262
  }
253
263
 
254
- const changeTree = this[$changes];
255
- const operation = changeTree.indexes?.[index]?.op ?? OPERATION.ADD;
264
+ const operation = (this.items[index] !== undefined)
265
+ ? typeof(value) === "object"
266
+ ? OPERATION.DELETE_AND_ADD // schema child
267
+ : OPERATION.REPLACE // primitive
268
+ : OPERATION.ADD;
256
269
 
270
+ const changeTree = this[$changes];
257
271
  changeTree.change(index, operation);
258
272
 
259
273
  //
@@ -390,6 +404,8 @@ export class ArraySchema<V = any> implements Array<V>, Collection<number, V> {
390
404
  * ```
391
405
  */
392
406
  sort(compareFn: (a: V, b: V) => number = DEFAULT_SORT): this {
407
+ this.isMovingItems = true;
408
+
393
409
  const changeTree = this[$changes];
394
410
  const sortedItems = this.items.sort(compareFn);
395
411
 
@@ -397,6 +413,8 @@ export class ArraySchema<V = any> implements Array<V>, Collection<number, V> {
397
413
  sortedItems.forEach((_, i) => changeTree.change(i, OPERATION.REPLACE));
398
414
 
399
415
  this.tmpItems.sort(compareFn);
416
+
417
+ this.isMovingItems = false;
400
418
  return this;
401
419
  }
402
420
 
@@ -786,6 +804,39 @@ export class ArraySchema<V = any> implements Array<V>, Collection<number, V> {
786
804
  return this.items.toSpliced.apply(copy, arguments);
787
805
  }
788
806
 
807
+ shuffle() {
808
+ return this.move((_) => {
809
+ let currentIndex = this.items.length;
810
+ while (currentIndex != 0) {
811
+ let randomIndex = Math.floor(Math.random() * currentIndex);
812
+ currentIndex--;
813
+ [this[currentIndex], this[randomIndex]] = [this[randomIndex], this[currentIndex]];
814
+ }
815
+ });
816
+ }
817
+
818
+ /**
819
+ * Allows to move items around in the array.
820
+ *
821
+ * Example:
822
+ * state.cards.move((cards) => {
823
+ * [cards[4], cards[3]] = [cards[3], cards[4]];
824
+ * [cards[3], cards[2]] = [cards[2], cards[3]];
825
+ * [cards[2], cards[0]] = [cards[0], cards[2]];
826
+ * [cards[1], cards[1]] = [cards[1], cards[1]];
827
+ * [cards[0], cards[0]] = [cards[0], cards[0]];
828
+ * })
829
+ *
830
+ * @param cb
831
+ * @returns
832
+ */
833
+ move(cb: (arr: this) => void) {
834
+ this.isMovingItems = true;
835
+ cb(this);
836
+ this.isMovingItems = false;
837
+ return this;
838
+ }
839
+
789
840
  protected [$getByIndex](index: number, isEncodeAll: boolean = false) {
790
841
  //
791
842
  // TODO: avoid unecessary `this.tmpItems` check during decoding.