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