Migrating to version 0.14 (from 0.13)¶
As a result from colyseus/schema#75 - the Colyseus version 0.14
introduces a few breaking changes on the usage of MapSchema
, and schema callbacks on the client-side, as both the Schema encoder and decoder have been reworked.
New feature @filterChildren()
, and better @filter()
support! Read more about how filters work here.
Upgrading the server:
npm install colyseus@^0.14.0 --save
Upgrading the client:
npm install colyseus.js@^0.14.0 --save
If you're using Unity or other client, please check on its respective repository on GitHub. If you have questions feel free to ask on Discord
Use .assign({})
instead of constructor()
¶
If you're sharing your concrete schema implementation with the client-side and have the constructor()
implemented, some error may happen because the decoder is not going to provide any arguments during initialization of that structure.
With the addition of the .assign({})
method, it is recommended to use it instead of providing arguments to constructor()
for setting initial data in your structures:
const player = new Player().assign({ x: 10, y: 10 });
MapSchema
breaking changes¶
MapSchema
used to be treated as a plain JavaScript object ({}
). Now, it uses the built-in Map
internally.
By using the built-in Map
, issues regarding the order of map keys are gone (#51 and #70).
There are a few breaking changes, which you should fix in your project, though.
Iterating through all items¶
Previous version:
for (const key in yourMap) {
key // map key
yourMap[key] // map value
}
New version:
yourMap.forEach((value, key) => {
key // map key
value // map value
});
Alternatively, you may iterate through the map's keys, or values alone, by using the iterators map.keys()
or map.values()
.
Getting the total number of items¶
Previous version:
const size = Object.keys(this.state.players).length;
console.log("Number of items =>", size);
New version:
const size = this.state.players.size;
console.log("Number of items =>", size);
Getting the keys of a MapSchema¶
Previous version:
Object.keys(map)
New version:
Array.from(map.keys())
Getting and setting on MapSchema
¶
This is not a breaking change! You can still use the bracket accessors to get and set values on MapSchema
. It is recommended to use the new Map
-like methods instead, though.
Previous version:
// get with bracket accessor
// (the type of "entry" here is "any")
const entry = yourMap["key"];
// set with bracket accessor
yourMap["key"] = "value";
New version:
// get with .get() method
// (the type of "entry" matches the type definition)
const entry = yourMap.get("key");
// set with .set() method
yourMap.set("key", "value");
Client-side: Schema callbacks¶
TLDR: Double-check all your onChange
callbacks in the client-side. You may need to add more onChange
callbacks for children structures.
onChange
on Schema references¶
Previous version: Whenever a change happens on deeper children, the field of the parent container is triggered as a change.
// Server-side
state.player.position.x = 10;
// Client-side
state.player.onChange = function(changes) {
changes[0].field // "position" is here!
}
New version: Now, changes are not propagated to parent Schema instances anymore. If you need to listen for a change on player.position
(and .position
is of type of Schema
), you need to attach a onChange
callback to the .position
instance as well.
// Server-side
state.player.position.x = 10;
// Client-side
state.player.position.onChange = function(changes) {
changes[0].field // "x" is here!
}
onChange
on collections (ArraySchema, MapSchema, etc.)¶
Similarly as on the previous example, onChange
is not triggered anymore if the children of the collection is an Schema instance. onChange
is only triggered for primitive values.
Previous version:
state.arrayOfSchemas.onChange = function(value, key) {
console.log(value, "has changed at", key);
}
state.arrayOfPrimitives.onChange = function(value, key) {
console.log(value, "has changed at", key);
}
New version:
state.arrayOfSchemas.onAdd = function(value, key) {
value.onChange = function(changes) {
console.log("List of changes", changes);
}
}
state.arrayOfSchemas.onChange = function(value, key) {
// you can remove this callback, as it is never going to be called.
}
state.arrayOfPrimitives.onChange = function(value, key) {
// here remains the same for primitive values (string, number, boolean)
console.log(value, "has changed at", key);
}