Client-side Schema Callbacks
When applying state changes coming from the server, the client-side is going to trigger callbacks on local instances according to the changes being applied.
In order to register callbacks to Schema instances, you must access the instances through a “callbacks handler”.
Overview
Get the callback handler
import { Client, getStateCallbacks } from "colyseus.js";
// initialize SDK
const client = new Client("ws://localhost:2567");
// join room
const room = await client.joinOrCreate("my_room");
// get state callbacks handler
const $ = getStateCallbacks(room);Register the callbacks
$(room.state).listen("currentTurn", (currentValue, previousValue) => {
// ...
});
// when an entity was added (ArraySchema or MapSchema)
$(room.state).entities.onAdd((entity, sessionId) => {
// ...
console.log("entity added", entity);
$(entity).listen("hp", (currentHp, previousHp) => {
console.log("entity", sessionId, "changed hp to", currentHp);
})
});
// when an entity was removed (ArraySchema or MapSchema)
$(room.state).entities.onRemove((entity, sessionId) => {
// ...
console.log("entity removed", entity);
});C#, C++, Haxe - When using statically typed languages, you need to generate the client-side schema files based on your TypeScript schema definitions. See generating schema on the client-side.
How to use
On Schema instances
Listen
Listens for a single property change within a Schema instance.
$(room.state).listen("currentTurn", (currentValue, previousValue) => {
console.log(`currentTurn is now ${currentValue}`);
console.log(`previous value was: ${previousValue}`);
});Removing the callback: The .listen() method returns a function that, when called, removes the attached callback:
const unbindCallback = $(room.state).listen("currentTurn", (currentValue, previousValue) => {
// ...
});
// stop listening for `"currentTurn"` changes.
unbindCallback();Bind To
Bind properties directly to targetObject, whenever the client receives an update from the server.
Parameters:
targetObject: the object that will receive updatesproperties: (optional) list of properties that will be assigned totargetObject. By default, every@type()’d property will be used.
$(room.state).players.onAdd((player, sessionId) => {
const playerVisual = PIXI.Sprite.from('player');
$(player).bindTo(playerVisual);
});On Change
The On Change callback is invoked whenever a direct property of a Schema instance is modified.
- Triggers only for direct property changes: It does not cascade or propagate changes from nested properties within the Schema.
- The callback fires after the changes have been applied to the Schema instance. This means you’re dealing with the updated instance when the callback executes.
$(room.state).entities.onAdd((entity, sessionId) => {
// ...
$(entity).onChange(() => {
// some property changed inside `entity`
})
});On Maps or Arrays
On Add
Register the onAdd callback is called whenever a new instance is added to a collection.
By default, the callback is called immediately for existing items in the collection.
$(room.state).players.onAdd((player, sessionId) => {
console.log(player, "has been added at", sessionId);
// add your player entity to the game world!
// detecting changes on object properties
$(player).listen("field_name", (value, previousValue) => {
console.log(value);
console.log(previousValue);
});
});On Remove
The onRemove callback is called with the removed item and its key on holder object as argument.
$(room.state).players.onRemove((player, sessionId) => {
console.log(player, "has been removed at", sessionId);
// remove your player entity from the game world!
});Client-side Schema Generation
Not required when using JavaScript SDK or Defold SDK - The following section is only required when using statically typed languages in your front-end, such as C#, Haxe, etc.
The schema-codegen is a command-line tool designed to convert your server-side schema definitions into compatible client-side schemas.
To decode the state on the client side, its local schema definitions must be compatible with those on the server.
Usage:
To see the usage, From your terminal, cd into your server’s directory and run the following command:
npx schema-codegen --helpOutput:
schema-codegen [path/to/Schema.ts]
Usage (C#/Unity)
schema-codegen src/Schema.ts --output client-side/ --csharp --namespace MyGame.Schema
Valid options:
--output: fhe output directory for generated client-side schema files
--csharp: generate for C#/Unity
--cpp: generate for C++
--haxe: generate for Haxe
--ts: generate for TypeScript
--js: generate for JavaScript
--java: generate for Java
Optional:
--namespace: generate namespace on output codeExample: Unity / C#
Below is a real example to generate the C# schema files from the demo Unity project.
npx schema-codegen src/rooms/schema/* --csharp --output ../Assets/Scripts/States/"
generated: Player.cs
generated: State.csUsing npm scripts:
For short, it is recommended to have your schema-codegen arguments configured under a npm script in your package.json:
"scripts": {
"schema-codegen": "schema-codegen src/rooms/schema/* --csharp --output ../Assets/Scripts/States/"
}This way you can run npm run schema-codegen rather than the full command:
npm run schema-codegen
generated: Player.cs
generated: State.cs