State Sync » Client-side Callbacks¶
The schema callbacks are triggered only in the client-side, right after the latest state patches sent by the server were received and applied on the client.
Schema callbacks¶
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.
Callbacks¶
When applying state changes coming from the server, the client-side is going to trigger callbacks on local instances according to the change being applied.
The callbacks are triggered based on instance reference. Make sure to attach the callback on the instances that are actually changing on the server.
On Schema
instances
- listen() for properties
- onChange ()
On collections of items
What are collections?
Collections are MapSchema
, ArraySchema
, etc. See how to define collections of items.
On Schema
instances¶
TypeScript
When your tsconfig.json
targets ES2022
or higher (e.g. ESNext
), the @type()
schema decorators may fail to work because TS moves property declarations to the constructor. Set "useDefineForClassFields": false
in your tsconfig.json
to fix this. See #510 for the discussion.
.listen(prop, callback)
¶
Listens for a single property change.
Parameters:
property
: the property name you'd like to listen for changes.callback
: the callback that is going to be triggered whenproperty
changes.
The .listen()
method returns a function that, when called, removes the attached callback:
const unbindCallback = room.state.listen("currentTurn", (currentValue, previousValue) => {
// ...
});
// later on, if you don't need the listener anymore, you can call `unbindCallback()` to stop listening for `"currentTurn"` changes.
unbindCallback();
onChange ()
¶
You can register the onChange
to track whenever a Schema
had its properties changed. When the callback is triggered, changes have already been applied.
Use .listen()
to detect changes on particular properties
Since version 0.15, the .onChange()
does not provide the full list of
properties changed. See .listen()
On collections of items¶
onAdd (fn (item, key), triggerAll = true)
¶
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.
Avoiding doubled-up callbacks
You may notice that onAdd
is called multiple times when an entry is inserted. This is because the "add" callback is called immediately by default for existing items in the collection. When the collection is nested within another schema instance, this can cause doubling. To fix this, set the second argument of onAdd
to false (e.g. .onAdd(callback, false)
). See #147.
onRemove (item, key)
¶
The onRemove
callback is called with the removed item and its key on holder object as argument.
onChange (item, key)
¶
This callback is triggered whenever a collection of primitive types (string
, number
, boolean
, etc.) updates its values at the same key.
Collection of Schema
instances?
If you'd like to get the changes of a child Schema
instance inside a
collection, you need to attach either .listen()
or .onChange()
callbacks
to the child instance directly during .onAdd()
Client-side schema generation¶
The schema-codegen
is a tool that transpiles your server-side schema definition files to be used in the client-side:
To be able to decode the state in the client-side, its local schema definitions must be compatible with the schema definitions in the server.
Not required when using JavaScript SDK
Using schema-codegen
is only required when using statically typed languages in the client-side, such as C#, Haxe, etc.
Usage:
To see the usage, From your terminal, cd
into your server's directory and run the following command:
Output:
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 code
Example: 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.cs
Using 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: