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