@colyseus/schema 3.0.50 → 3.0.52

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.
@@ -57,8 +57,8 @@ export interface ChangeSet {
57
57
  queueRootNode?: ChangeTreeNode; // direct reference to ChangeTreeNode in the linked list
58
58
  }
59
59
 
60
- function createChangeSet(): ChangeSet {
61
- return { indexes: {}, operations: [] };
60
+ function createChangeSet(queueRootNode?: ChangeTreeNode): ChangeSet {
61
+ return { indexes: {}, operations: [], queueRootNode };
62
62
  }
63
63
 
64
64
  // Linked list helper functions
@@ -66,23 +66,6 @@ export function createChangeTreeList(): ChangeTreeList {
66
66
  return { next: undefined, tail: undefined, length: 0 };
67
67
  }
68
68
 
69
- export function addToChangeTreeList(list: ChangeTreeList, changeTree: ChangeTree): ChangeTreeNode {
70
- const node: ChangeTreeNode = { changeTree, next: undefined, prev: undefined };
71
-
72
- if (!list.next) {
73
- list.next = node;
74
- list.tail = node;
75
- } else {
76
- node.prev = list.tail;
77
- list.tail!.next = node;
78
- list.tail = node;
79
- }
80
-
81
- list.length++;
82
-
83
- return node;
84
- }
85
-
86
69
  export function setOperationAtIndex(changeSet: ChangeSet, index: number) {
87
70
  const operationsIndex = changeSet.indexes[index];
88
71
  if (operationsIndex === undefined) {
@@ -129,22 +112,6 @@ export function debugChangeSet(label: string, changeSet: ChangeSet) {
129
112
  console.log(operations.join("\n"), "\n}");
130
113
  }
131
114
 
132
- export function enqueueChangeTree(
133
- root: Root,
134
- changeTree: ChangeTree,
135
- changeSet: 'changes' | 'filteredChanges' | 'allFilteredChanges' | 'allChanges',
136
- queueRootNode = changeTree[changeSet].queueRootNode
137
- ) {
138
- // skip
139
- if (!root) { return; }
140
-
141
- if (queueRootNode) {
142
- } else {
143
- // Add to linked list if not already present
144
- changeTree[changeSet].queueRootNode = addToChangeTreeList(root[changeSet], changeTree);
145
- }
146
- }
147
-
148
115
  export interface ParentChain {
149
116
  ref: Ref;
150
117
  index: number;
@@ -283,11 +250,11 @@ export class ChangeTree<T extends Ref = any> {
283
250
  // this is checked during .encode() time.
284
251
  if (this.filteredChanges !== undefined) {
285
252
  this.filteredChanges.operations.push(-op);
286
- enqueueChangeTree(this.root, this, 'filteredChanges');
253
+ this.root?.enqueueChangeTree(this, 'filteredChanges');
287
254
 
288
255
  } else {
289
256
  this.changes.operations.push(-op);
290
- enqueueChangeTree(this.root, this, 'changes');
257
+ this.root?.enqueueChangeTree(this, 'changes');
291
258
  }
292
259
  }
293
260
 
@@ -316,13 +283,13 @@ export class ChangeTree<T extends Ref = any> {
316
283
  setOperationAtIndex(this.allFilteredChanges, index);
317
284
 
318
285
  if (this.root) {
319
- enqueueChangeTree(this.root, this, 'filteredChanges');
320
- enqueueChangeTree(this.root, this, 'allFilteredChanges');
286
+ this.root.enqueueChangeTree(this, 'filteredChanges');
287
+ this.root.enqueueChangeTree(this, 'allFilteredChanges');
321
288
  }
322
289
 
323
290
  } else {
324
291
  setOperationAtIndex(this.allChanges, index);
325
- enqueueChangeTree(this.root, this, 'changes');
292
+ this.root?.enqueueChangeTree(this, 'changes');
326
293
  }
327
294
  }
328
295
 
@@ -385,12 +352,12 @@ export class ChangeTree<T extends Ref = any> {
385
352
  if (this.filteredChanges !== undefined) {
386
353
  setOperationAtIndex(this.allFilteredChanges, allChangesIndex);
387
354
  setOperationAtIndex(this.filteredChanges, index);
388
- enqueueChangeTree(this.root, this, 'filteredChanges');
355
+ this.root?.enqueueChangeTree(this, 'filteredChanges');
389
356
 
390
357
  } else {
391
358
  setOperationAtIndex(this.allChanges, allChangesIndex);
392
359
  setOperationAtIndex(this.changes, index);
393
- enqueueChangeTree(this.root, this, 'changes');
360
+ this.root?.enqueueChangeTree(this, 'changes');
394
361
  }
395
362
  }
396
363
 
@@ -461,10 +428,10 @@ export class ChangeTree<T extends Ref = any> {
461
428
  //
462
429
  if (this.filteredChanges !== undefined) {
463
430
  deleteOperationAtIndex(this.allFilteredChanges, allChangesIndex);
464
- enqueueChangeTree(this.root, this, 'filteredChanges');
431
+ this.root?.enqueueChangeTree(this, 'filteredChanges');
465
432
 
466
433
  } else {
467
- enqueueChangeTree(this.root, this, 'changes');
434
+ this.root?.enqueueChangeTree(this, 'changes');
468
435
  }
469
436
 
470
437
  return previousValue;
@@ -499,10 +466,11 @@ export class ChangeTree<T extends Ref = any> {
499
466
  }
500
467
 
501
468
  if (discardAll) {
502
- this.allChanges = createChangeSet();
469
+ // preserve queueRootNode references
470
+ this.allChanges = createChangeSet(this.allChanges.queueRootNode);
503
471
 
504
472
  if (this.allFilteredChanges !== undefined) {
505
- this.allFilteredChanges = createChangeSet();
473
+ this.allFilteredChanges = createChangeSet(this.allFilteredChanges.queueRootNode);
506
474
  }
507
475
  }
508
476
  }
@@ -539,17 +507,19 @@ export class ChangeTree<T extends Ref = any> {
539
507
  this._checkFilteredByParent(parent, parentIndex);
540
508
 
541
509
  if (this.filteredChanges !== undefined) {
542
- enqueueChangeTree(this.root, this, 'filteredChanges');
510
+ this.root?.enqueueChangeTree(this, 'filteredChanges');
511
+
543
512
  if (isNewChangeTree) {
544
- enqueueChangeTree(this.root, this, 'allFilteredChanges');
513
+ this.root?.enqueueChangeTree(this, 'allFilteredChanges');
545
514
  }
546
515
  }
547
516
  }
548
517
 
549
518
  if (!this.isFiltered) {
550
- enqueueChangeTree(this.root, this, 'changes');
519
+ this.root?.enqueueChangeTree(this, 'changes');
520
+
551
521
  if (isNewChangeTree) {
552
- enqueueChangeTree(this.root, this, 'allChanges');
522
+ this.root?.enqueueChangeTree(this, 'allChanges');
553
523
  }
554
524
  }
555
525
  }
@@ -177,7 +177,12 @@ export const encodeArray: EncodeOperation = function (
177
177
  let refOrIndex: number;
178
178
 
179
179
  if (useOperationByRefId) {
180
- refOrIndex = ref['tmpItems'][field][$changes].refId;
180
+ const item = ref['tmpItems'][field];
181
+
182
+ // Skip encoding if item is undefined (e.g. when clear() is called)
183
+ if (!item) { return; }
184
+
185
+ refOrIndex = item[$changes].refId;
181
186
 
182
187
  if (operation === OPERATION.DELETE) {
183
188
  operation = OPERATION.DELETE_BY_REFID;
@@ -1,6 +1,6 @@
1
1
  import { OPERATION } from "../encoding/spec";
2
2
  import { TypeContext } from "../types/TypeContext";
3
- import { ChangeTree, setOperationAtIndex, ChangeTreeList, createChangeTreeList, ChangeSetName, Ref } from "./ChangeTree";
3
+ import { ChangeTree, setOperationAtIndex, ChangeTreeList, createChangeTreeList, ChangeSetName, type ChangeTreeNode } from "./ChangeTree";
4
4
 
5
5
  export class Root {
6
6
  protected nextUniqueId: number = 0;
@@ -47,7 +47,7 @@ export class Root {
47
47
 
48
48
  this.refCount[changeTree.refId] = (previousRefCount || 0) + 1;
49
49
 
50
- // console.log("ADD", { refId: changeTree.refId, refCount: this.refCount[changeTree.refId] });
50
+ // console.log("ADD", { refId: changeTree.refId, ref: changeTree.ref.constructor.name, refCount: this.refCount[changeTree.refId], isNewChangeTree });
51
51
 
52
52
  return isNewChangeTree;
53
53
  }
@@ -55,6 +55,8 @@ export class Root {
55
55
  remove(changeTree: ChangeTree) {
56
56
  const refCount = (this.refCount[changeTree.refId]) - 1;
57
57
 
58
+ // console.log("REMOVE", { refId: changeTree.refId, ref: changeTree.ref.constructor.name, refCount, needRemove: refCount <= 0 });
59
+
58
60
  if (refCount <= 0) {
59
61
  //
60
62
  // Only remove "root" reference if it's the last reference
@@ -147,7 +149,36 @@ export class Root {
147
149
  changeSet.tail = node;
148
150
  }
149
151
 
150
- protected removeChangeFromChangeSet(changeSetName: ChangeSetName, changeTree: ChangeTree) {
152
+ public enqueueChangeTree(
153
+ changeTree: ChangeTree,
154
+ changeSet: 'changes' | 'filteredChanges' | 'allFilteredChanges' | 'allChanges',
155
+ queueRootNode = changeTree[changeSet].queueRootNode
156
+ ) {
157
+ // skip
158
+ if (queueRootNode) { return; }
159
+
160
+ // Add to linked list if not already present
161
+ changeTree[changeSet].queueRootNode = this.addToChangeTreeList(this[changeSet], changeTree);
162
+ }
163
+
164
+ protected addToChangeTreeList(list: ChangeTreeList, changeTree: ChangeTree): ChangeTreeNode {
165
+ const node: ChangeTreeNode = { changeTree, next: undefined, prev: undefined };
166
+
167
+ if (!list.next) {
168
+ list.next = node;
169
+ list.tail = node;
170
+ } else {
171
+ node.prev = list.tail;
172
+ list.tail!.next = node;
173
+ list.tail = node;
174
+ }
175
+
176
+ list.length++;
177
+
178
+ return node;
179
+ }
180
+
181
+ public removeChangeFromChangeSet(changeSetName: ChangeSetName, changeTree: ChangeTree) {
151
182
  const changeSet = this[changeSetName];
152
183
  const node = changeTree[changeSetName].queueRootNode;
153
184
 
@@ -1,6 +1,6 @@
1
1
  import { $changes, $childType, $decoder, $deleteByIndex, $onEncodeEnd, $encoder, $filter, $getByIndex, $onDecodeEnd } from "../symbols";
2
2
  import type { Schema } from "../../Schema";
3
- import { ChangeTree, enqueueChangeTree, setOperationAtIndex } from "../../encoder/ChangeTree";
3
+ import { ChangeTree, setOperationAtIndex } from "../../encoder/ChangeTree";
4
4
  import { OPERATION } from "../../encoding/spec";
5
5
  import { registerType } from "../registry";
6
6
  import { Collection } from "../HelperTypes";
@@ -482,10 +482,10 @@ export class ArraySchema<V = any> implements Array<V>, Collection<number, V> {
482
482
  // FIXME: this code block is duplicated on ChangeTree
483
483
  //
484
484
  if (changeTree.filteredChanges !== undefined) {
485
- enqueueChangeTree(changeTree.root, changeTree, 'filteredChanges');
485
+ changeTree.root?.enqueueChangeTree(changeTree, 'filteredChanges');
486
486
 
487
487
  } else {
488
- enqueueChangeTree(changeTree.root, changeTree, 'changes');
488
+ changeTree.root?.enqueueChangeTree(changeTree, 'changes');
489
489
  }
490
490
 
491
491
  return this.items.splice(start, deleteCount, ...insertItems);
@@ -118,6 +118,10 @@ export class MapSchema<V=any, K extends string = string> implements Map<K, V>, C
118
118
  }
119
119
  }
120
120
 
121
+ if (this.deletedItems[index]) {
122
+ delete this.deletedItems[index];
123
+ }
124
+
121
125
  } else {
122
126
  index = changeTree.indexes[$numFields] ?? 0;
123
127
  operation = OPERATION.ADD;