Migrating to version 0.15 (from 0.14)¶
See version 0.15 release announcement.
@colyseus/arena
has been renamed to@colyseus/tools
- Schema's
.triggerAll()
has been deprecated. - Schema callbacks API change
- Schema's
onChange
behaviour change MapSchema
is now strict on property accessorsclient.reconnect()
API slightly changedallowReconnection()
: second argument is now mandatory@colyseus/loadtest
has been reworked!@colyseus/command
typings update- Built-in
client.auth
is gone!@colyseus/social
fully deprecated RedisDriver
andRedisPresence
constructor change- onLeave
1001
and4000
error codes range
@colyseus/arena
has been renamed to @colyseus/tools
¶
You can remove @colyseus/arena
and install @colyseus/tools
:
You can also rename the arena.config.ts
file to app.config.ts
for consistency.
Schema's .triggerAll()
has been deprecated¶
Now, whenever you register an onAdd()
callback, it is called immediately for already existing items - thus, making the usage of .triggerAll()
not necessary anymore.
You can prevent the onAdd()
callback from being triggered automatically, though, if necessary.
By providing false
in the second argument, the onAdd()
callback is not going to be triggered for already existing items.
Schema callbacks API slightly changed¶
Now, instead of assigning a single callback per onAdd
/onChange
/onRemove
, you attach them by calling as a method instead. You can attach more than one callback this way.
See example below:
// 0.14 (old)
state.players.onAdd = function(value, key) {/* do stuff */};
state.players.onChange = function(value, key) {/* do stuff */};
state.players.onRemove = function(value, key) {/* do stuff */};
// 0.15 (new)
state.players.onAdd(function(value, key) {/* do stuff */});
state.players.onChange(function(value, key) {/* do stuff */});
state.players.onRemove(function(value, key) {/* do stuff */});
// 0.14 (old)
state.players.OnAdd += (key, value) => {/* do stuff */};
state.players.OnChange += (key, value) => {/* do stuff */};
state.players.OnRemove += (key, value) => {/* do stuff */};
// 0.15 (new)
state.players.OnAdd((key, value) => {/* do stuff */})
state.players.OnChange((key, value) => {/* do stuff */})
state.players.OnRemove((key, value) => {/* do stuff */})
-- 0.14 (old)
state.players.on_add = function(value, key) --[[ do stuff ]] end
state.players.on_change = function(value, key) --[[ do stuff ]] end
state.players.on_remove = function(value, key) --[[ do stuff ]] end
-- 0.15 (new)
-- ATTENTION: this is a method call. make sure to use `:` instead of `.` here.
state.players:on_add(function(value, key) --[[ do stuff ]] end)
state.players:on_change(function(value, key) --[[ do stuff ]] end)
state.players:on_remove(function(value, key) --[[ do stuff ]] end)
// 0.14 (old)
state.players.onAdd = function(value, key) {/* do stuff */};
state.players.onChange = function(value, key) {/* do stuff */};
state.players.onRemove = function(value, key) {/* do stuff */};
// 0.15 (new)
state.players.onAdd(function(value, key) {/* do stuff */});
state.players.onChange(function(value, key) {/* do stuff */});
state.players.onRemove(function(value, key) {/* do stuff */});
The return value of onAdd()
/onChange()
/onRemove()
is a function that can detach the callback that have been added.
Schema's onChange
behaviour change¶
On Schema
instances¶
The list of changes
inside the onChange
callback is not provided anymore.
You can still use onChange
to detect wheter the instance object had changes,
but you should use .listen()
to listen for its particular properties:
// 0.14 (old)
state.player.onChange = function(changes) {
console.log("player changed!");
changes.forEach((change) => {
if (change.field === "fieldname") {
console.log(change.value);
}
})
}
// 0.15 (new)
state.player.onChange(() =>{
console.log("player changed!");
});
state.player.listen("field", (value) => {
console.log(value);
})
On ArraySchema
and MapSchema
¶
Previously, the onChange
callback wouldn't be fired during onAdd
and onRemove
when attached to a collection of items (MapSchema
, ArraySchema
, etc).
Now, onChange
is triggered alongside with onAdd
and onRemove
.
MapSchema
is now strict on property accessors¶
Only JavaScript/TypeScript is affected. If you use a client-side SDK other than JavaScript/TypeScript, no change is needed on the client-side for you.
// 0.14 (old)
this.state.players[client.sessionId] = new Player();
// 0.15 (new)
this.state.players.set(client.sessionId, new Player());
Reasoning:
MapSchema
used to be treated as a regular JavaScript object in the early days. Since version 0.14MapSchema
uses a realMap
internally, with a "proxy" compatibility layer in order to avoid breaking existing projects. Now the "proxy" layer has been removed, improving the performance slightly.
client.reconnect()
API slightly changed¶
The previous reconnection implementation had a security vulnerability, although very unlikely to be explored, we had to update its implementation to make it secure.
// 0.14 (old)
client.reconnect(cachedRoomId, cachedSessionId)
// 0.15 (new)
client.reconnect(cachedReconnectionToken)
Insterad of providing the previously active room.roomId
and room.sessionId
for reconnection, you only provide the room.reconnectionToken
instead.
Reconnection tokens are unique and private for each client.
allowReconnection()
: second argument is now mandatory¶
Previously, by omitting the second argument of allowReconnection()
, you were in control over when to cancel the possibility for reconnection.
To make this intent more explicit, it is now mandatory to provide the second argument either as "manual"
, or the number of seconds to wait for reconnection:
async onLeave (client: Client, consented: boolean) {
// ...
try {
if (consented) { throw new Error("consented leave"); }
//
// Get reconnection token
// NOTE: do not use `await` here yet!
//
const reconnection = this.allowReconnection(client, "manual");
//
// here is the custom logic for rejecting the reconnection.
// for demonstration purposes of the API, an interval is created
// rejecting the reconnection if the player has missed 2 rounds,
// (assuming he's playing a turn-based game)
//
// in a real scenario, you would store the `reconnection` in
// your Player instance, for example, and perform this check during your
// game loop logic
//
const currentRound = this.state.currentRound;
const interval = setInterval(() => {
if ((this.state.currentRound - currentRound) > 2) {
// manually reject the client reconnection
reconnection.reject();
clearInterval(interval);
}
}, 1000);
// now it's time to `await` for the reconnection
await reconnection;
// client returned! let's re-activate it.
// ...
} catch (e) {
// reconnection has been rejected. let's remove the client.
// ...
}
}
@colyseus/loadtest
has been reworked!¶
The loadtest tool has been reworked to allow for more complex scripting, so your loadtest scripts will need to be slightly rewritten, as the new format looks like this:
import { Client, Room } from "colyseus.js";
import { cli, Options } from "@colyseus/loadtest";
async function main(options: Options) {
const client = new Client(options.endpoint);
const room: Room = await client.joinOrCreate(options.roomName, {/*
your join options here...
*/});
console.log("joined successfully!");
room.onMessage("message-type", (payload) => {
// logic
});
room.onStateChange((state) => {
console.log("state change:", state);
});
room.onLeave((code) => {
console.log("left");
});
}
// execute
cli(main);
@colyseus/command
typings update¶
On latest version of @colyseus/command
(0.2.0
), instead of providing the state as a generic when extending the Command
, you now provide your whole Room
type:
import { Command } from "@colyseus/command";
export class MyRoom extends Room<State> {/* ... */}
-export class MyCommand extends Command<State> {/* ... */}
+export class MyCommand extends Command<MyRoom> {/* ... */}
Built-in client.auth
is gone! @colyseus/social
fully deprecated.¶
The documentation has been discouraging the use of @colyseus/social
since version 0.14.
Now @colyseus/social
has been officially deprecated. If you really rely on it please reach out to the devs on Discord on how to proceed if you still need to use it.
RedisDriver
and RedisPresence
constructor change¶
Providing a URI as connection string for RedisDriver
or RedisPresence
has
changed to:
onLeave 1001
and 4000
error codes range¶
If you had a condition like this:
Now you need to validate the higher limit as well since we have the custom error codes starting on 4000
.