Skip to content

Server API » Presence

When you need to scale your server on multiple processes and/or machines, you'd need to provide the Presence option to the Server. The purpose of Presence is to allow communicating and sharing data between different processes, specially during match-making.

The presence instance is also available on every Room handler. You may use its API to persist data and communicate between rooms via PUB/SUB.


LocalPresence

This is the default option. It's meant to be used when you're running Colyseus in a single process.


RedisPresence (clientOpts?)

Use this option when you're running Colyseus on multiple processes and/or machines.

Parameters:

import config from "@colyseus/tools";
import { RedisPresence } from "@colyseus/redis-presence";

export default config({
    // ...
    options: {
        presence: new RedisPresence()
    },
    // ...
});
import { Server } from "colyseus";
import { RedisPresence } from "@colyseus/redis-presence";

// This happens on the slave processes.
const gameServer = new Server({
    // ...
    presence: new RedisPresence()
});

gameServer.listen(2567);
const colyseus = require('colyseus');
const RedisPresence = require('@colyseus/redis-presence').RedisPresence;

// This happens on the slave processes.
const gameServer = new colyseus.Server({
    // ...
    presence: new RedisPresence()
});

gameServer.listen(2567);

API

The Presence API is highly based on Redis's API, which is a key-value database.

Every Room instance has a presence property:

export class MyRoom extends Room {
    onCreate() {
        this.presence // full Presence API is available from here
    }
}

Alternatively, you can access matchMaker.presence from anywhere, by importing the Match-maker API:

import { matchMaker } from "colyseus";

matchMaker.presence // full Presence API is available from here

subscribe(topic: string, callback: Function)

Subscribes to the given topic. The callback will be triggered whenever a message is published on topic.

this.presence.subscribe("global-event", (data) => {
    console.log("received message:", data);
});

unsubscribe(topic: string, callback?: Function)

Unsubscribe from given topic.

Example: Unsubscribe from all previously subscribed "global-event" callbacks.

//
this.presence.unsubscribe("global-event");

Example: Unsubscribe from a specific "topic" callback.

function callback(data) { }
this.presence.subscribe("global-event", callback);

// unsubscribing from specific callback
this.presence.unsubscribe("global-event", callback);

publish(topic: string, data: any)

Posts a message to given topic.

this.presence.publish("global-event", { any: 1, data: 2, here: "3" });

set(key: string, value: string)

Set key to hold the string value.

Example: Setting a "global-key" to hold "a string value".

this.presence.set("global-key", "a string value");

setex(key: string, value: string, seconds: number)

Set key to hold the string value and set key to timeout after a given number of seconds.

Example: Setting a "global-key" that is globally available for 2 minutes.

this.presence.setex("global-key", "a string value", 120);

get(key: string)

Get the value of key.

const globalKeyValue = await this.presence.get("global-key");

del(key: string): void

Removes the specified key.

await this.presence.del("global-key");

exists(key: string): Promise<boolean>

Returns if key exists.

const globalKeyExists = await this.presence.exists("global-key");

incr(key: string)

Increments the number stored at key by one.

If the key does not exist, it is set to 0 before performing the operation.

An error is returned if the key contains a value of the wrong type or contains a string that can not be represented as integer.

This operation is limited to 64 bit signed integers.

await this.presence.incr("global-count");
await this.presence.incr("global-count");
await this.presence.incr("global-count");

// get value from "global-count" key
const count = await this.presence.get("global-count");
console.log(count) // => 3

decr(key: string)

Decrements the number stored at key by one.

If the key does not exist, it is set to 0 before performing the operation.

An error is returned if the key contains a value of the wrong type or contains a string that can not be represented as integer.

This operation is limited to 64 bit signed integers.

await this.presence.decr("global-count");
await this.presence.decr("global-count");
await this.presence.decr("global-count");

// get value from "global-count" key
const count = await this.presence.get("global-count");
console.log(count) // => 33

sadd(key: string, value: any)

Add the specified members to the set stored at key.

Specified members that are already a member of this set are ignored.

If key does not exist, a new set is created before adding the specified members.

await this.presence.sadd("global-set1", "member-one");
await this.presence.sadd("global-set1", "member-one"); // ignored, not added
await this.presence.sadd("global-set1", "member-two");
await this.presence.sadd("global-set1", "member-three");

smembers(key: string)

Returns all the members of the set value stored at key.

const globalSetMembers = await this.presence.del("global-set1");
console.log(globalSetMembers) // => ["member-one", "member-two", "member-three"]

sismember(key: string, member: string)

Returns if member is a member of the set stored at key

Return value

  • 1 if the element is a member of the set.
  • 0 if the element is not a member of the set, or if key does not exist.
const isMember = await this.presence.sismember("global-set1", "member-three");

if (isMember) {
    console.log("member-three IS present on 'global-set1'");

} else {
    console.log("member-three IS NOT present on 'global-set1'");
}

srem(key: string, value: any)

Remove the specified members from the set stored at key.

Specified members that are not a member of this set are ignored.

If key does not exist, it is treated as an empty set and this command returns 0.

await this.presence.srem("global-set1", "member-three");

scard(key: string)

Returns the set number of elements (cardinality) of the set stored at key.

const cardinality = await this.presence.scard("global-set1");
console.log(cardinality) // => 2

sinter(...keys: string[])

Returns the members of the set resulting from the intersection of all the given sets.

// add members to "global-set1"
await this.presence.sadd("global-set1", "member-one");
await this.presence.sadd("global-set1", "member-two");

// add members to "global-set2"
await this.presence.sadd("global-set2", "member-two");
await this.presence.sadd("global-set2", "member-three");

// get the intersection
const intersection = await this.presence.sinter("global-set1", "global-set2");
console.log(intersection); // => ["member-two"]

hset(key: string, field: string, value: string)

Sets field in the hash stored at key to value.

If key does not exist, a new key holding a hash is created.

If field already exists in the hash, it is overwritten.

await this.presence.hset("global-hashmap1", "key1", "1");
await this.presence.hset("global-hashmap1", "key2", "2");

hincrby(key: string, field: string, value: number)

Increments the number stored at field in the hash stored at key by increment.

If key does not exist, a new key holding a hash is created.

If field does not exist the value is set to 0 before the operation is performed.

await this.presence.hset("global-hashmap1", "key1", "2");
const incr = await this.presence.hincrby("global-hashmap1", "key1", "5");
console.log(incr) // => "7"

hget(key: string, field: string): Promise<string>

Returns the value associated with field in the hash stored at key.

await this.presence.hset("global-hashmap1", "key", "value");
const value = await this.presence.hget("global-hashmap1", "key");
console.log(value) // => "value"

hgetall(key: string): Promise<{[field: string]: string}>

Returns all fields and values of the hash stored at key.

await this.presence.hset("global-hashmap1", "key1", "1");
await this.presence.hset("global-hashmap1", "key2", "2");

const value = await this.presence.hgetall("global-hashmap1");
console.log(value) // => {"key1": "1", "key2": "2"}

hdel(key: string, field: string)

Removes the specified fields from the hash stored at key.

Specified fields that do not exist within this hash are ignored.

If key does not exist, it is treated as an empty hash and this command returns 0.

await this.presence.hset("global-hashmap1", "key1", "1");
await this.presence.hset("global-hashmap1", "key2", "2");

// delete "key2" from "global-hashmap1".
await this.presence.hset("global-hashmap1", "key2");

hlen(key: string): Promise<number>

Returns the number of fields contained in the hash stored at key

await this.presence.hset("global-hashmap1", "key1", "1");
await this.presence.hset("global-hashmap1", "key2", "2");

// get length from "global-hashmap1".
const length = await this.presence.hlen("global-hashmap1");
console.log(length) // => 2