Skip to content

Commit ddbad34

Browse files
committed
ArraySchema: fixes consecutive .shift() calls + encodeAll()
1 parent 1a52ec9 commit ddbad34

File tree

4 files changed

+67
-9
lines changed

4 files changed

+67
-9
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@colyseus/schema",
3-
"version": "3.0.25",
3+
"version": "3.0.26",
44
"description": "Binary state serializer with delta encoding for games",
55
"bin": {
66
"schema-codegen": "./bin/schema-codegen",

src/encoder/ChangeTree.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -267,7 +267,7 @@ export class ChangeTree<T extends Ref=any> {
267267
const newIndexes = {};
268268
for (const index in this.indexedOperations) {
269269
newIndexedOperations[Number(index) + shiftIndex] = this.indexedOperations[index];
270-
newIndexes[Number(index) + shiftIndex] = changeSet[index];
270+
newIndexes[Number(index) + shiftIndex] = changeSet.indexes[index];
271271
}
272272
this.indexedOperations = newIndexedOperations;
273273
changeSet.indexes = newIndexes;
@@ -372,6 +372,7 @@ export class ChangeTree<T extends Ref=any> {
372372

373373
this.indexedOperations[index] = operation ?? OPERATION.DELETE;
374374
setOperationAtIndex(changeSet, index);
375+
deleteOperationAtIndex(this.allChanges, allChangesIndex);
375376

376377
const previousValue = this.getValue(index);
377378

@@ -390,8 +391,6 @@ export class ChangeTree<T extends Ref=any> {
390391
this.root?.remove(previousValue[$changes]);
391392
}
392393

393-
deleteOperationAtIndex(this.allChanges, allChangesIndex);
394-
395394
//
396395
// FIXME: this is looking a ugly and repeated
397396
//

src/types/custom/ArraySchema.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -360,11 +360,13 @@ export class ArraySchema<V = any> implements Array<V>, Collection<number, V> {
360360
if (this.items.length === 0) { return undefined; }
361361

362362
// const index = Number(Object.keys(changeTree.indexes)[0]);
363-
const index = this.tmpItems.findIndex((item, i) => item === this.items[0]);
364363
const changeTree = this[$changes];
365364

366-
changeTree.delete(index);
367-
changeTree.shiftAllChangeIndexes(-1, index);
365+
const index = this.tmpItems.findIndex(item => item === this.items[0]);
366+
const allChangesIndex = this.items.findIndex(item => item === this.items[0]);
367+
368+
changeTree.delete(index, OPERATION.DELETE, allChangesIndex);
369+
changeTree.shiftAllChangeIndexes(-1, allChangesIndex);
368370

369371
// this.deletedIndexes[index] = true;
370372

test/ArraySchema.test.ts

Lines changed: 59 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,53 @@ describe("ArraySchema Tests", () => {
9494
assert.strictEqual(0, state.turns.length);
9595
});
9696

97+
it("consecutive shift calls should not break 'encodeAll'", () => {
98+
class Entity extends Schema {
99+
@type("number") i: number;
100+
}
101+
class MyState extends Schema {
102+
@type([Entity]) entities;
103+
}
104+
105+
const state = new MyState();
106+
state.entities = [];
107+
108+
for (let i = 0; i < 5; i++) {
109+
state.entities.push(new Entity().assign({ i }));
110+
}
111+
112+
const decodedState = createInstanceFromReflection(state);
113+
decodedState.decode(state.encode())
114+
115+
const entitiesChangeTree: ChangeTree = state.entities[$changes];
116+
assert.deepStrictEqual({ '0': 0, '1': 1, '2': 2, '3': 3, '4': 4 }, entitiesChangeTree.allChanges.indexes);
117+
118+
state.entities.shift();
119+
assert.deepStrictEqual({ '0': 1, '1': 2, '2': 3, '3': 4 }, entitiesChangeTree.allChanges.indexes);
120+
121+
state.entities.shift();
122+
assert.deepStrictEqual({ '0': 2, '1': 3, '2': 4 }, entitiesChangeTree.allChanges.indexes);
123+
124+
state.entities.shift();
125+
assert.deepStrictEqual({ '0': 3, '1': 4 }, entitiesChangeTree.allChanges.indexes);
126+
127+
state.entities.shift();
128+
assert.deepStrictEqual({ '0': 4 }, entitiesChangeTree.allChanges.indexes);
129+
130+
assertDeepStrictEqualEncodeAll(state);
131+
132+
decodedState.decode(state.encode())
133+
assertRefIdCounts(state, decodedState);
134+
135+
state.entities.shift();
136+
137+
decodedState.decode(state.encode())
138+
assertRefIdCounts(state, decodedState);
139+
140+
// encode all
141+
assertDeepStrictEqualEncodeAll(state);
142+
});
143+
97144
it("mutate previous instance + shift", () => {
98145
/**
99146
* This test shows that flagging the `changeSet` item as `undefined`
@@ -123,14 +170,16 @@ describe("ArraySchema Tests", () => {
123170
for (let i = 0; i < 2; i++) {
124171
for (let j = 0; j < 2; j++) {
125172
state.entities.forEach((entity) => entity.i++);
126-
const entity = state.entities.shift();
173+
state.entities.shift();
127174
}
128-
129175
decodedState.decode(state.encode());
130176
}
131177

132178
assertDeepStrictEqualEncodeAll(state);
133179
assertRefIdCounts(state, decodedState);
180+
181+
state.entities.shift();
182+
assertDeepStrictEqualEncodeAll(state);
134183
});
135184
});
136185

@@ -369,6 +418,8 @@ describe("ArraySchema Tests", () => {
369418
console.log("--- 5 ---")
370419

371420
assert.strictEqual(0, state.turns.length);
421+
422+
assertDeepStrictEqualEncodeAll(state);
372423
});
373424
});
374425

@@ -439,6 +490,8 @@ describe("ArraySchema Tests", () => {
439490

440491
decodedState.decode(state.encode());
441492
assert.deepStrictEqual([0, 1, 2, 3, 4], decodedState.arrayOfNumbers.toJSON());
493+
494+
assertDeepStrictEqualEncodeAll(state);
442495
});
443496

444497
it("push, unshift, pop", () => {
@@ -460,6 +513,8 @@ describe("ArraySchema Tests", () => {
460513

461514
decodedState.decode(state.encode());
462515
assert.deepStrictEqual([0, 1, 2, 3], decodedState.arrayOfNumbers.toJSON());
516+
517+
assertDeepStrictEqualEncodeAll(state);
463518
});
464519

465520
it("push, pop, unshift", () => {
@@ -481,6 +536,8 @@ describe("ArraySchema Tests", () => {
481536

482537
decodedState.decode(state.encode());
483538
assert.deepStrictEqual([0, 1, 2, 3], decodedState.arrayOfNumbers.toJSON());
539+
540+
assertDeepStrictEqualEncodeAll(state);
484541
});
485542

486543
it("push, shift, unshift", () => {

0 commit comments

Comments
 (0)