Skip to content

Commit 1885762

Browse files
committed
ArraySchema: fixes OPERATION.DELETE_BY_REFID and OPERATION.ADD_BY_REFID
1 parent d3663c3 commit 1885762

File tree

4 files changed

+108
-7
lines changed

4 files changed

+108
-7
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.28",
3+
"version": "3.0.29",
44
"description": "Binary state serializer with delta encoding for games",
55
"bin": {
66
"schema-codegen": "./bin/schema-codegen",

src/decoder/DecodeOperation.ts

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -326,10 +326,15 @@ export const decodeArray: DecodeOperation = function (
326326
const refId = decode.number(bytes, it);
327327
const itemByRefId = decoder.root.refs.get(refId);
328328

329-
// use existing index, or push new value
330-
index = (itemByRefId)
331-
? ref.findIndex((value) => value === itemByRefId)
332-
: ref.length;
329+
// if item already exists, use existing index
330+
if (itemByRefId) {
331+
index = ref.findIndex((value) => value === itemByRefId);
332+
}
333+
334+
// fallback to use last index
335+
if (index === -1 || index === undefined) {
336+
index = ref.length;
337+
}
333338

334339
} else {
335340
index = decode.number(bytes, it);

src/encoder/EncodeOperation.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,7 @@ export const encodeArray: EncodeOperation = function (
210210
encode.number(bytes, refOrIndex, it);
211211

212212
// Do not encode value for DELETE operations
213-
if (operation === OPERATION.DELETE) {
213+
if (operation === OPERATION.DELETE || operation === OPERATION.DELETE_BY_REFID) {
214214
return;
215215
}
216216

test/StateView.test.ts

Lines changed: 97 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import * as assert from "assert";
22
import { Schema, type, view, ArraySchema, MapSchema, StateView, Encoder, ChangeTree, $changes, OPERATION, SetSchema, CollectionSchema } from "../src";
33
import { createClientWithView, encodeMultiple, assertEncodeAllMultiple, getDecoder, getEncoder, createInstanceFromReflection, encodeAllForView, encodeAllMultiple } from "./Schema";
4-
import { getDecoderStateCallbacks } from "../src/decoder/strategy/StateCallbacks";
54
import { nanoid } from "nanoid";
65

76
describe("StateView", () => {
@@ -1489,6 +1488,103 @@ describe("StateView", () => {
14891488

14901489
assertEncodeAllMultiple(encoder, state, [client])
14911490
});
1491+
1492+
it("nested arrays of a filtered entity", () => {
1493+
class Component extends Schema {
1494+
@type("string") name: string;
1495+
@type("number") value: number;
1496+
}
1497+
class QuestCondition extends Schema {
1498+
@type('number') level: number = null;
1499+
@type('string') quest: string = null;
1500+
}
1501+
class QuestReward extends Schema {
1502+
@type('number') amount: number;
1503+
}
1504+
class QuestRequirement extends Schema {
1505+
@type('number') progress: number = 0;
1506+
}
1507+
class Quest extends Schema {
1508+
@type('string') name: string;
1509+
@type([QuestRequirement]) requirements = new ArraySchema<QuestRequirement>();
1510+
@type([QuestReward]) rewards = new ArraySchema<QuestReward>();
1511+
@type([QuestCondition]) conditions = new ArraySchema<QuestCondition>();
1512+
}
1513+
class QuestBook extends Component {
1514+
@type([Quest]) finished: Quest[] = new ArraySchema<Quest>();
1515+
@type([Quest]) ongoing: Quest[] = new ArraySchema<Quest>();
1516+
}
1517+
class Entity extends Schema {
1518+
@type("string") id: string = nanoid(9);
1519+
@type([Component]) components = new ArraySchema<Component>();
1520+
}
1521+
1522+
class MyRoomState extends Schema {
1523+
@view() @type({ map: Entity }) entities = new MapSchema<Entity>();
1524+
}
1525+
1526+
const state = new MyRoomState();
1527+
const encoder = getEncoder(state);
1528+
1529+
const questBook = new QuestBook().assign({
1530+
finished: [],
1531+
ongoing: [
1532+
new Quest().assign({
1533+
name: "Quest1",
1534+
requirements: [new QuestRequirement().assign({ progress: 0 })],
1535+
rewards: [new QuestReward().assign({ amount: 300 })],
1536+
conditions: [new QuestCondition().assign({ level: 3, quest: "Quest1" })]
1537+
}),
1538+
new Quest().assign({
1539+
name: "Quest2",
1540+
requirements: [new QuestRequirement().assign({ progress: 0 })],
1541+
rewards: [new QuestReward().assign({ amount: 400 })],
1542+
conditions: [new QuestCondition().assign({ level: 4, quest: "Quest2" })]
1543+
}),
1544+
new Quest().assign({
1545+
name: "Quest3",
1546+
requirements: [new QuestRequirement().assign({ progress: 0 })],
1547+
rewards: [new QuestReward().assign({ amount: 400 })],
1548+
conditions: [new QuestCondition().assign({ level: 4, quest: "Quest3" })]
1549+
})
1550+
]
1551+
});
1552+
1553+
state.entities.set("one", new Entity().assign({
1554+
id: "one",
1555+
components: [questBook]
1556+
}));
1557+
1558+
state.entities.set("two", new Entity().assign({
1559+
id: "two",
1560+
components: []
1561+
}));
1562+
1563+
const client = createClientWithView(state);
1564+
encodeMultiple(encoder, state, [client]);
1565+
1566+
// add entities for the first time
1567+
client.view.add(state.entities.get("one"));
1568+
1569+
encodeMultiple(encoder, state, [client]);
1570+
assert.strictEqual(1, client.state.entities.size);
1571+
1572+
assert.deepStrictEqual(state.entities.get("one").toJSON(), client.state.entities.get("one").toJSON());
1573+
1574+
// 1st remove ongoing + add to finished
1575+
const ongoing1 = questBook.ongoing.shift();
1576+
questBook.finished.push(ongoing1);
1577+
encodeMultiple(encoder, state, [client]);
1578+
assert.deepStrictEqual(state.entities.get("one").toJSON(), client.state.entities.get("one").toJSON());
1579+
1580+
// 2st remove ongoing + add to finished
1581+
const ongoing2 = questBook.ongoing.shift();
1582+
questBook.finished.push(ongoing2);
1583+
encodeMultiple(encoder, state, [client]);
1584+
assert.deepStrictEqual(state.entities.get("one").toJSON(), client.state.entities.get("one").toJSON());
1585+
1586+
assertEncodeAllMultiple(encoder, state, [client]);
1587+
});
14921588
});
14931589

14941590
describe("Deep and nested structures", () => {

0 commit comments

Comments
 (0)