Upgrading to version 0.16 (from 0.15)
Use this guide to migrate your existing 0.15 projects to version 0.16.
Make sure colyseus
and all @colyseus/*
packages on package.json
are pointing to ^0.16.0
. Having different versions of colyseus
and @colyseus/*
packages may lead to unexpected behavior.
Server-side:
"@colyseus/schema": "^3.0.0",
"colyseus": "^0.16.0",
"@colyseus/auth": "^0.16.0",
"@colyseus/core": "^0.16.0",
"@colyseus/loadtest": "^0.16.0",
"@colyseus/monitor": "^0.16.0",
"@colyseus/playground": "^0.16.0",
"@colyseus/testing": "^0.16.0",
"@colyseus/tools": "^0.16.0",
"@colyseus/uwebsockets-transport": "^0.16.0",
Client-side:
"colyseus.js": "^0.16.0",
Make sure you don’t have any packages under 0.15.x
, neither @colyseus/schema
under 2.0.x
. You may need to remove node_modules
and package-lock.json
before running npm install
.
Schema callbacks and $(instance)
proxy
As the callback methods have been extracted out of the Schema
instances, you now have to get a proxied version of your Schema
instances via $(yourInstance)
in order to attach callbacks into them.
import { getStateCallbacks } from "colyseus.js";
const room = await client.joinOrCreate("my_room");
const $ = getStateCallbacks(room);
$(room.state).players.onAdd((player, sessionId) => {
// this is the raw Schema instance
console.log(player);
// this is the proxied version, where you can attach the callbacks
$(player).listen("x", (value, previousValue) => {
console.log("player.x has been updated!", value, previousValue);
});
});
The proxy is capable of entering nested objects, even if they’re not available at the time you’re attaching the callback.
$(room.state)
.yourInstance // this is a Schema instance (may not be immediately available)
.yourItems // this is a MapSchema or ArraySchema (may also not be immediately available)
.onAdd((item, index) => {
console.log("item added at index", index);
});
For more context on why these changes are being applied, see colyseus/colyseus#709
@filter()
and @filterChildren()
are now deprecated!
The StateView
feature has been introduced in version 0.16, which allows you to create a view of your state with a subset of the data.
import { view, type, Schema, MapSchema } from "@colyseus/schema";
class MyState extends Schema {
@type({ map: Player }) players = new MapSchema<Player>();
}
class Player extends Schema {
// this property is visible to all
@type("string") name: string;
// this property is only visible a `StateView` that has added this Player instance.
@view() @type("number") position: number;
}
The StateView
must be assigned to the client.view
. The room serializer is going to use the client.view
to serialize the state before sending it to the client.
import { StateView } from "@colyseus/schema";
// ...
onJoin(client, options) {
const player = new Player();
client.view = new StateView();
client.view.add(player);
this.state.players.set(client.sessionId, player);
}
Each StateView
instance is going to add a new encoding step for state serialization. You may re-use the same StateView
instance for multiple clients, or create a new one for each client.
See more in the StateView
documentation.
Breaking changes
.onChange
callback on collections (MapSchema
, ArraySchema
, etc) has been removed!
Collections no longer have the .onChange
callback. You can use a combination of .onAdd
, .onRemove
to achieve the same behavior. (See discussion)
-schema.collection.onChange(callback)
+$(schema).collection.onAdd(callback)
+$(schema).collection.onRemove(callback)
Attaching playground
routes:
The playground
routes are now returned from a method call instead:
import { playground } from "@colyseus/playground";
// ...
if (process.env.NODE_ENV !== "production") {
- app.use("/", playground);
+ app.use("/", playground());
}
This change was necessary to avoid the internal monkey-patching coming from the playground module when using in production environment.
SDKs: getAvailableRooms()
method has been removed!
The getAvailableRooms()
method has been removed from the SDKs. The usage of getAvailableRooms()
was considered a security risk for many use-cases, as it was exposing the full list of rooms to any client.
If you rely on this method, you can easily re-implement it on your server-side code, although it’s recommended to implement a more secure way to query rooms, such as using the LobbyRoom
.
import { matchMaker } from "colyseus";
// ...
initializeExpress (app) {
app.get("/rooms/:roomName?", (req, res) => {
const conditions: any = {
locked: false,
private: false,
};
if (roomName) {
conditions["name"] = roomName;
}
res.json(await matchMaker.query(conditions));
});
}
From the client SDK, you can use client.http.get("/rooms/:roomName")
to get the list of rooms.
matchMaker.getRoomById()
matchMaker.getRoomById()
now returns the cached room data. This method will return properly when called from any process.matchMaker.getLocalRoomById()
returns the room instance itself, if it’s available in the current process.
ArraySchema.deleteAt()
has been removed.
You can use ArraySchema.splice()
instead:
- array.deleteAt(index);
+ array.splice(index, 1);
Sending schema-encoded messages is now deprecated
Sending schema instances as messages via client.send(instance)
or this.broadcast(instance)
is now deprecated. This feature it was introduced in previous versions due to lack of strong types in C# for messages.
.encode()
, .encodeAll()
and .decode()
methods have been moved
The Schema instances used to provide .encode()
, .encodeAll()
and .decode()
methods. These methods are called internally by the framework, and if you were not using them, you don’t need to worry about this change.
If you were using these methods, you can now use them from the Encoder
and Decoder
classes:
import { Encoder, Decoder } from "@colyseus/schema";
const encoder = new Encoder(new MyState());
const encodeAllBytes = encoder.encodeAll();
const decoded = new Decoder(new MyState());
decoded.decode(encodeAllBytes);