@colyseus/schema 3.0.43 → 3.0.45

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.
@@ -1086,6 +1086,7 @@ class ChangeTree {
1086
1086
  // re-assigning a child of the same root, move it to the end
1087
1087
  // of the changes queue so encoding order is preserved
1088
1088
  //
1089
+ root.add(child);
1089
1090
  root.moveToEndOfChanges(child);
1090
1091
  return;
1091
1092
  }
@@ -1423,7 +1424,7 @@ class ChangeTree {
1423
1424
  */
1424
1425
  addParent(parent, index) {
1425
1426
  // Check if this parent already exists in the chain
1426
- if (this.hasParent((p, i) => p === parent && i === index)) {
1427
+ if (this.hasParent((p, i) => p[$changes] === parent[$changes] && i === index)) {
1427
1428
  return;
1428
1429
  }
1429
1430
  this.parentChain = {
@@ -1437,7 +1438,7 @@ class ChangeTree {
1437
1438
  * @param parent - The parent to remove
1438
1439
  * @returns true if parent was removed
1439
1440
  */
1440
- removeParent(parent) {
1441
+ removeParent(parent = this.parent) {
1441
1442
  let current = this.parentChain;
1442
1443
  let previous = null;
1443
1444
  while (current) {
@@ -3396,9 +3397,9 @@ class Schema {
3396
3397
  });
3397
3398
  return output;
3398
3399
  }
3399
- static debugRefIdEncodeOrder(ref) {
3400
+ static debugRefIdEncodingOrder(ref, changeSet = 'allChanges') {
3400
3401
  let encodeOrder = [];
3401
- let current = ref[$changes].root.allChanges.next;
3402
+ let current = ref[$changes].root[changeSet].next;
3402
3403
  while (current) {
3403
3404
  if (current.changeTree) {
3404
3405
  encodeOrder.push(current.changeTree.refId);
@@ -3407,7 +3408,7 @@ class Schema {
3407
3408
  }
3408
3409
  return encodeOrder;
3409
3410
  }
3410
- static debugRefIdsDecoder(decoder) {
3411
+ static debugRefIdsFromDecoder(decoder) {
3411
3412
  return this.debugRefIds(decoder.state, false, 0, decoder);
3412
3413
  }
3413
3414
  /**
@@ -3916,10 +3917,12 @@ class Root {
3916
3917
  }
3917
3918
  }
3918
3919
  this.refCount[changeTree.refId] = (previousRefCount || 0) + 1;
3920
+ // console.log("ADD", { refId: changeTree.refId, refCount: this.refCount[changeTree.refId] });
3919
3921
  return isNewChangeTree;
3920
3922
  }
3921
3923
  remove(changeTree) {
3922
3924
  const refCount = (this.refCount[changeTree.refId]) - 1;
3925
+ // console.log("REMOVE", { refId: changeTree.refId, refCount });
3923
3926
  if (refCount <= 0) {
3924
3927
  //
3925
3928
  // Only remove "root" reference if it's the last reference
@@ -4422,7 +4425,7 @@ class Decoder {
4422
4425
  // throw new Error(`"refId" not found: ${nextRefId}`);
4423
4426
  console.error(`"refId" not found: ${nextRefId}`, { previousRef: ref, previousRefId: this.currentRefId });
4424
4427
  console.warn("Please report this to the developers. All refIds =>");
4425
- console.warn(Schema.debugRefIdsDecoder(this));
4428
+ console.warn(Schema.debugRefIdsFromDecoder(this));
4426
4429
  this.skipCurrentStructure(bytes, it, totalBytes);
4427
4430
  }
4428
4431
  else {
@@ -4999,11 +5002,12 @@ class StateView {
4999
5002
  // TODO: allow to set multiple tags at once
5000
5003
  add(obj, tag = DEFAULT_VIEW_TAG, checkIncludeParent = true) {
5001
5004
  const changeTree = obj?.[$changes];
5005
+ const parentChangeTree = changeTree.parent;
5002
5006
  if (!changeTree) {
5003
5007
  console.warn("StateView#add(), invalid object:", obj);
5004
- return this;
5008
+ return false;
5005
5009
  }
5006
- else if (!changeTree.parent &&
5010
+ else if (!parentChangeTree &&
5007
5011
  changeTree.refId !== 0 // allow root object
5008
5012
  ) {
5009
5013
  /**
@@ -5025,18 +5029,31 @@ class StateView {
5025
5029
  // add parent ChangeTree's
5026
5030
  // - if it was invisible to this view
5027
5031
  // - if it were previously filtered out
5028
- if (checkIncludeParent && changeTree.parent) {
5032
+ if (checkIncludeParent && parentChangeTree) {
5029
5033
  this.addParentOf(changeTree, tag);
5030
5034
  }
5031
- //
5032
- // TODO: when adding an item of a MapSchema, the changes may not
5033
- // be set (only the parent's changes are set)
5034
- //
5035
5035
  let changes = this.changes.get(changeTree.refId);
5036
5036
  if (changes === undefined) {
5037
5037
  changes = {};
5038
+ // FIXME / OPTIMIZE: do not add if no changes are needed
5038
5039
  this.changes.set(changeTree.refId, changes);
5039
5040
  }
5041
+ let isChildAdded = false;
5042
+ //
5043
+ // Add children of this ChangeTree first.
5044
+ // If successful, we must link the current ChangeTree to the child.
5045
+ //
5046
+ changeTree.forEachChild((change, index) => {
5047
+ // Do not ADD children that don't have the same tag
5048
+ if (metadata &&
5049
+ metadata[index].tag !== undefined &&
5050
+ metadata[index].tag !== tag) {
5051
+ return;
5052
+ }
5053
+ if (this.add(change.ref, tag, false)) {
5054
+ isChildAdded = true;
5055
+ }
5056
+ });
5040
5057
  // set tag
5041
5058
  if (tag !== DEFAULT_VIEW_TAG) {
5042
5059
  if (!this.tags) {
@@ -5058,11 +5075,12 @@ class StateView {
5058
5075
  }
5059
5076
  });
5060
5077
  }
5061
- else {
5062
- const isInvisible = this.invisible.has(changeTree);
5078
+ else if (!changeTree.isNew || isChildAdded) {
5079
+ // new structures will be added as part of .encode() call, no need to force it to .encodeView()
5063
5080
  const changeSet = (changeTree.filteredChanges !== undefined)
5064
5081
  ? changeTree.allFilteredChanges
5065
5082
  : changeTree.allChanges;
5083
+ const isInvisible = this.invisible.has(changeTree);
5066
5084
  for (let i = 0, len = changeSet.operations.length; i < len; i++) {
5067
5085
  const index = changeSet.operations[i];
5068
5086
  if (index === undefined) {
@@ -5070,27 +5088,17 @@ class StateView {
5070
5088
  } // skip "undefined" indexes
5071
5089
  const op = changeTree.indexedOperations[index] ?? OPERATION.ADD;
5072
5090
  const tagAtIndex = metadata?.[index].tag;
5073
- if (!changeTree.isNew && // new structures will be added as part of .encode() call, no need to force it to .encodeView()
5091
+ if (op !== OPERATION.DELETE &&
5074
5092
  (isInvisible || // if "invisible", include all
5075
5093
  tagAtIndex === undefined || // "all change" with no tag
5076
5094
  tagAtIndex === tag // tagged property
5077
- ) &&
5078
- op !== OPERATION.DELETE) {
5095
+ )) {
5079
5096
  changes[index] = op;
5097
+ isChildAdded = true; // FIXME: assign only once
5080
5098
  }
5081
5099
  }
5082
5100
  }
5083
- // Add children of this ChangeTree to this view
5084
- changeTree.forEachChild((change, index) => {
5085
- // Do not ADD children that don't have the same tag
5086
- if (metadata &&
5087
- metadata[index].tag !== undefined &&
5088
- metadata[index].tag !== tag) {
5089
- return;
5090
- }
5091
- this.add(change.ref, tag, false);
5092
- });
5093
- return this;
5101
+ return isChildAdded;
5094
5102
  }
5095
5103
  addParentOf(childChangeTree, tag) {
5096
5104
  const changeTree = childChangeTree.parent[$changes];