@colyseus/schema 3.0.57 → 3.0.59

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.
@@ -990,7 +990,7 @@ function createChangeSet(queueRootNode) {
990
990
  }
991
991
  // Linked list helper functions
992
992
  function createChangeTreeList() {
993
- return { next: undefined, tail: undefined, length: 0 };
993
+ return { next: undefined, tail: undefined };
994
994
  }
995
995
  function setOperationAtIndex(changeSet, index) {
996
996
  const operationsIndex = changeSet.indexes[index];
@@ -1082,11 +1082,11 @@ class ChangeTree {
1082
1082
  this.forEachChild((child, index) => {
1083
1083
  if (child.root === root) {
1084
1084
  //
1085
- // re-assigning a child of the same root, move it to the end
1086
- // of the changes queue so encoding order is preserved
1085
+ // re-assigning a child of the same root, move it next to parent
1086
+ // so encoding order is preserved
1087
1087
  //
1088
1088
  root.add(child);
1089
- root.moveToEndOfChanges(child);
1089
+ root.moveNextToParent(child);
1090
1090
  return;
1091
1091
  }
1092
1092
  child.setParent(this.ref, root, index);
@@ -4013,8 +4013,8 @@ class Root {
4013
4013
  this.remove(child);
4014
4014
  }
4015
4015
  else if (child.parentChain) {
4016
- // re-assigning a child of the same root, move it to the end
4017
- this.moveToEndOfChanges(child);
4016
+ // re-assigning a child of the same root, move it next to parent
4017
+ this.moveNextToParent(child);
4018
4018
  }
4019
4019
  }
4020
4020
  });
@@ -4023,34 +4023,52 @@ class Root {
4023
4023
  this.refCount[changeTree.refId] = refCount;
4024
4024
  //
4025
4025
  // When losing a reference to an instance, it is best to move the
4026
- // ChangeTree to the end of the encoding queue.
4026
+ // ChangeTree next to its parent in the encoding queue.
4027
4027
  //
4028
4028
  // This way, at decoding time, the instance that contains the
4029
4029
  // ChangeTree will be available before the ChangeTree itself. If the
4030
4030
  // containing instance is not available, the Decoder will throw
4031
4031
  // "refId not found" error.
4032
4032
  //
4033
- this.moveToEndOfChanges(changeTree);
4034
- changeTree.forEachChild((child, _) => this.moveToEndOfChanges(child));
4033
+ this.recursivelyMoveNextToParent(changeTree);
4035
4034
  }
4036
4035
  return refCount;
4037
4036
  }
4038
- moveToEndOfChanges(changeTree) {
4037
+ recursivelyMoveNextToParent(changeTree) {
4038
+ this.moveNextToParent(changeTree);
4039
+ changeTree.forEachChild((child, _) => this.recursivelyMoveNextToParent(child));
4040
+ }
4041
+ moveNextToParent(changeTree) {
4039
4042
  if (changeTree.filteredChanges) {
4040
- this.moveToEndOfChangeTreeList("filteredChanges", changeTree);
4041
- this.moveToEndOfChangeTreeList("allFilteredChanges", changeTree);
4043
+ this.moveNextToParentInChangeTreeList("filteredChanges", changeTree);
4044
+ this.moveNextToParentInChangeTreeList("allFilteredChanges", changeTree);
4042
4045
  }
4043
4046
  else {
4044
- this.moveToEndOfChangeTreeList("changes", changeTree);
4045
- this.moveToEndOfChangeTreeList("allChanges", changeTree);
4047
+ this.moveNextToParentInChangeTreeList("changes", changeTree);
4048
+ this.moveNextToParentInChangeTreeList("allChanges", changeTree);
4046
4049
  }
4047
4050
  }
4048
- moveToEndOfChangeTreeList(changeSetName, changeTree) {
4051
+ moveNextToParentInChangeTreeList(changeSetName, changeTree) {
4049
4052
  const changeSet = this[changeSetName];
4050
4053
  const node = changeTree[changeSetName].queueRootNode;
4051
- if (!node || node === changeSet.tail)
4054
+ if (!node)
4055
+ return;
4056
+ // Find the parent in the linked list
4057
+ const parent = changeTree.parent;
4058
+ if (!parent || !parent[$changes])
4059
+ return;
4060
+ const parentNode = parent[$changes][changeSetName]?.queueRootNode;
4061
+ if (!parentNode || parentNode === node)
4062
+ return;
4063
+ // Use cached positions - no iteration needed!
4064
+ const parentPosition = parentNode.position;
4065
+ const childPosition = node.position;
4066
+ // If child is already after parent, no need to move
4067
+ if (childPosition > parentPosition)
4052
4068
  return;
4053
- // Remove from current position
4069
+ // Child is before parent, so we need to move it after parent
4070
+ // This maintains decoding order (parent before child)
4071
+ // Remove node from current position
4054
4072
  if (node.prev) {
4055
4073
  node.prev.next = node.next;
4056
4074
  }
@@ -4063,16 +4081,18 @@ class Root {
4063
4081
  else {
4064
4082
  changeSet.tail = node.prev;
4065
4083
  }
4066
- // Add to end
4067
- node.prev = changeSet.tail;
4068
- node.next = undefined;
4069
- if (changeSet.tail) {
4070
- changeSet.tail.next = node;
4084
+ // Insert node right after parent
4085
+ node.prev = parentNode;
4086
+ node.next = parentNode.next;
4087
+ if (parentNode.next) {
4088
+ parentNode.next.prev = node;
4071
4089
  }
4072
4090
  else {
4073
- changeSet.next = node;
4091
+ changeSet.tail = node;
4074
4092
  }
4075
- changeSet.tail = node;
4093
+ parentNode.next = node;
4094
+ // Update positions after the move
4095
+ this.updatePositionsAfterMove(changeSet, node, parentPosition + 1);
4076
4096
  }
4077
4097
  enqueueChangeTree(changeTree, changeSet, queueRootNode = changeTree[changeSet].queueRootNode) {
4078
4098
  // skip
@@ -4083,7 +4103,12 @@ class Root {
4083
4103
  changeTree[changeSet].queueRootNode = this.addToChangeTreeList(this[changeSet], changeTree);
4084
4104
  }
4085
4105
  addToChangeTreeList(list, changeTree) {
4086
- const node = { changeTree, next: undefined, prev: undefined };
4106
+ const node = {
4107
+ changeTree,
4108
+ next: undefined,
4109
+ prev: undefined,
4110
+ position: list.tail ? list.tail.position + 1 : 0
4111
+ };
4087
4112
  if (!list.next) {
4088
4113
  list.next = node;
4089
4114
  list.tail = node;
@@ -4093,13 +4118,35 @@ class Root {
4093
4118
  list.tail.next = node;
4094
4119
  list.tail = node;
4095
4120
  }
4096
- list.length++;
4097
4121
  return node;
4098
4122
  }
4123
+ updatePositionsAfterRemoval(list, removedPosition) {
4124
+ // Update positions for all nodes after the removed position
4125
+ let current = list.next;
4126
+ let position = 0;
4127
+ while (current) {
4128
+ if (position >= removedPosition) {
4129
+ current.position = position;
4130
+ }
4131
+ current = current.next;
4132
+ position++;
4133
+ }
4134
+ }
4135
+ updatePositionsAfterMove(list, node, newPosition) {
4136
+ // Recalculate all positions - this is more reliable than trying to be clever
4137
+ let current = list.next;
4138
+ let position = 0;
4139
+ while (current) {
4140
+ current.position = position;
4141
+ current = current.next;
4142
+ position++;
4143
+ }
4144
+ }
4099
4145
  removeChangeFromChangeSet(changeSetName, changeTree) {
4100
4146
  const changeSet = this[changeSetName];
4101
4147
  const node = changeTree[changeSetName].queueRootNode;
4102
4148
  if (node && node.changeTree === changeTree) {
4149
+ const removedPosition = node.position;
4103
4150
  // Remove the node from the linked list
4104
4151
  if (node.prev) {
4105
4152
  node.prev.next = node.next;
@@ -4113,7 +4160,8 @@ class Root {
4113
4160
  else {
4114
4161
  changeSet.tail = node.prev;
4115
4162
  }
4116
- changeSet.length--;
4163
+ // Update positions for nodes that came after the removed node
4164
+ this.updatePositionsAfterRemoval(changeSet, removedPosition);
4117
4165
  // Clear ChangeTree reference
4118
4166
  changeTree[changeSetName].queueRootNode = undefined;
4119
4167
  return true;
@@ -4335,8 +4383,8 @@ class Encoder {
4335
4383
  }
4336
4384
  }
4337
4385
  get hasChanges() {
4338
- return (this.root.changes.length > 0 ||
4339
- this.root.filteredChanges.length > 0);
4386
+ return (this.root.changes.next !== undefined ||
4387
+ this.root.filteredChanges.next !== undefined);
4340
4388
  }
4341
4389
  }
4342
4390
 
@@ -4519,8 +4567,7 @@ class Decoder {
4519
4567
  if (!nextRef) {
4520
4568
  // throw new Error(`"refId" not found: ${nextRefId}`);
4521
4569
  console.error(`"refId" not found: ${nextRefId}`, { previousRef: ref, previousRefId: this.currentRefId });
4522
- console.warn("Please report this to the developers. All refIds =>");
4523
- console.warn(Schema.debugRefIdsFromDecoder(this));
4570
+ console.warn("Please report this issue to the developers.");
4524
4571
  this.skipCurrentStructure(bytes, it, totalBytes);
4525
4572
  }
4526
4573
  else {