Migrating to version 0.11 (from 0.10)¶
The version 0.11
improves match-making and scalability, and introduces breaking changes in both client-side and server-side.
Client-side¶
client.id
has been removed!¶
If you're using client.id
in the client-side, you should replace it with room.sessionId
.
New match-making methods available in the client-side!¶
A few methods have been added to the client-side allowing to explicitly create rooms or join them.
joinOrCreate(roomName, options)
- joins or creates a room by name (previously known asjoin()
)create(roomName, options)
- only creates new roomsjoin(roomName, options)
- only joins existing rooms by namejoinById(roomId, options)
- only joins existing rooms by idreconnect(roomId, sessionId)
- re-establish a previously lost connection (previously known asrejoin()
)
Also, the Room
instance is not returned immediatelly in the client-side. A promise is returned instead, and it is fulfilled whenever the onJoin()
has finished successfully.
Replace your existing client.join()
calls with its new client.joinOrCreate()
:
client.joinOrCreate("battle", {/* options */}).then(room => {
console.log("joined successfully", room);
}).catch(e => {
console.error("join error", e);
});
try {
Room<YourStateClass> room = await client.JoinOrCreate<YourStateClass>("battle", /* Dictionary of options */);
Debug.Log("joined successfully");
} catch (ex) {
Debug.Log("join error");
Debug.Log(ex.Message);
}
client:join_or_create("battle", {--[[options]]}, function(err, room)
if (err ~= nil) then
print("join error: " .. err)
return
end
print("joined successfully")
end)
client.joinOrCreate("battle", [/* options */], YourStateClass, function(err, room) {
if (err != null) {
trace("join error: " + err);
return;
}
trace("joined successfully");
});
client->joinOrCreate<YourStateClass>("battle", {/* options */}, [=](std::string err, Room<State>* room) {
if (err != "") {
std::cout << "join error: " << err << std::endl;
return;
}
std::cout << "joined successfully" << std::endl;
});
Lua, Haxe and C++
In languages that doesn't provide an async
mechanism out of the box, a callback is expected as last argument for the matchmaking functions. The callback gets invoked whenever the onJoin()
has been finished successfully.
room.onJoin
is not necessary anymore in the client-side¶
The room.onJoin
is now only used internally. When the promise (or callback) fulfils returning the room
instance, it has already been joined successfully.
The reconnect()
now expects the room id instead of room name.¶
Previously, the rejoin()
method accepted the room name and sessionId. Now, with reconnect()
you should pass the room id instead of the room name:
client.reconnect(roomId, sessionId).then(room => {/* ... */});
JavaScript/TypeScript: Signals API has changed slighly¶
The room signals are onLeave
, onStateChange
, onMessage
and onError
.
- Use
onStateChange(callback)
instead ofonStateChange.add(callback)
- Use
onStateChange.once(callback)
instead ofonStateChange.addOnce(callback)
C#/Unity¶
The sender
object has been removed from all Schema callbacks and events.
Schema callbacks API has changed slighly¶
- Use
players.OnAdd += (Player player, string key) => {}
. - Use
players.OnRemove += (Player player, string key) => {}
. - ... and so on!
Events API has changed slighly¶
The events are onLeave
, onStateChange
, onMessage
and onError
.
- No need to use
client.Connect()
,room.ReadyToConnect()
,room.Connect()
, orclient.Recv()
anymore. - Use
onStateChange += (State state, bool isFirstState) => {}
instead ofonStateChange += (sender, e) => {}
- Use
onMessage += (object message) => {}
instead ofonMessage += (sender, e) => {}
- Use
onLeave += (int code) => {}
instead ofonLeave += (sender, e) => {}
- Use
onError += (string message) => {}
instead ofonError += (sender, e) => {}
arraySchema.GetItems()
now returns a Dictionary<int, MySchemaType>
instead of a List<MySchemaType>
. Replace any cases of (List<MySchemaType>) state.myArraySchema.GetItems()
with ((Dictionary<int, MySchemaType>) state.myArraySchema.GetItems()).Values.ToList()
.
Server-side¶
Usage with express
¶
Before creating the Colyseus.Server
instance, you'll need to:
- use the
express.json()
middleware - use the
cors()
middleware (if you're testing server/client from different port or domain) - pass both
server
andexpress
to theColyseus.Server
constructor.
import http from "http";
import express from "express";
import cors from "cors";
import { Server } from "colyseus";
const app = express();
app.use(cors());
app.use(express.json());
const server = http.createServer(app);
const gameServer = new Server({
server: server
});
const http = require("http");
const express = require("express");
const cors = require("cors");
const colyseus = require("colyseus");
const app = express();
app.use(cors());
app.use(express.json());
const server = http.createServer(app);
const gameServer = new colyseus.Server({
server: server
});
gameServer.register
has been renamed to gameServer.define
¶
onInit(options)
has been renamed to onCreate(options)
¶
Replace your onInit(options)
method in your room with onCreate(options)
.
onAuth(options)
is now onAuth(client, options)
¶
Replace your onAuth(options)
method in your room with onAuth(client, options)
.
client.id
is now an alias to client.sessionId
¶
As the client.id
has been removed from the client-side, it is now just an alias to client.sessionId
(available in the client-side as room.sessionId
).
The client.id
was not a reliable source to identify unique users. If you need an efficient way to determine if the user is the same in multiple browser tabs, consider using some form of authentication. The anonymous authentication from @colyseus/social can serve this purpose very well.
The requestJoin()
method has been deprecated.¶
Instead of using requestJoin()
to determine wheter a player is allowed to join a room, you should use matchmaking filters for your defined rooms.
Take this example of using requestJoin()
from version 0.10
, and how to translate it to 0.11
:
// version 0.10
class MyRoom extends Room {
onInit(options) {
this.progress = options.progress;
}
requestJoin(options, isNew) {
return this.progress === options.progress;
}
}
You can have the same behaviour by defining a progress
filter when defining your room. The requestJoin()
method should be removed.
// version 0.11
gameServer
.define("dungeon", DungeonRoom)
.filterBy(['progress']);
Avoid using this.clients
inside onJoin()
or onAuth()
¶
The client
instance will be automatically added to the this.clients
list only after onJoin()
has been completed.
If you have a piece of code like this:
onJoin(client, options) {
if (this.clients.length === 2) {
// do something!
}
}
It's encouraged to replace with something else, like this:
onJoin(client, options) {
this.state.players[client.sessionId] = new Player(/*...*/);
if (Object.keys(this.state.players).length === 2) {
// do something!
}
}
onLeave(client, options) {
delete this.state.players[client.sessionId];
}