Skip to content

服务器 API » 服务器

Colyseus 的 Server 实例保存着服务器的配置选项, 比如传输层配置, presence, matchmaking 驱动等.

  • Transport 是实现服务器和客户端之间双向通信的逻辑层.
  • Presence 实现房间之间通信以及多 Node.js 进程间通信.
  • Driver 是存储驱动程序, 用于房间的存储以及 matchmaking 期间的房间检索.

new Server (options)

options.transport

Colyseus 默认使用其内置 WebSocket 传输. 详见 自定义传输层.

options.driver

房间 matchmaking 驱动. 用于房间缓存和检索的地方. 需要考虑服务扩展时不要使用 LocalDriver.

配置参数可以是:

  • LocalDriver - 默认.
  • RedisDriver - 取自 @colyseus/redis-driver
  • MongooseDriver - 取自@colyseus/mongoose-driver

options.presence

通过多进程/机器扩展 Colyseus 时, 您需要提供一个 presence 服务. 详见 扩展性Presence API.

import { Server, RedisPresence } from "colyseus";

const gameServer = new Server({
  // ...
  presence: new RedisPresence()
});
const colyseus = require("colyseus");

const gameServer = new colyseus.Server({
  // ...
  presence: new colyseus.RedisPresence()
});

options.gracefullyShutdown

注册关闭自动处理程序. 默认值是 true. 如果被禁用, 您需要在关闭服务时手动 调用 gracefullyShutdown() 方法.


options.server

该配置参数将被弃用

详见 WebSocket 传输配置选项

WebSocket 服务器绑定到的宿主服务器. 可以把 express 当作宿主服务器.

// Colyseus + Express
import { Server } from "colyseus";
import { createServer } from "http";
import express from "express";
const port = Number(process.env.port) || 3000;

const app = express();
app.use(express.json());

const gameServer = new Server({
  server: createServer(app)
});

gameServer.listen(port);
// Colyseus + Express
const colyseus = require("colyseus");
const http = require("http");
const express = require("express");
const port = process.env.port || 3000;

const app = express();
app.use(express.json());

const gameServer = new colyseus.Server({
  server: http.createServer(app)
});

gameServer.listen(port);
// Colyseus (不带宿主服务器)
import { Server } from "colyseus";
const port = process.env.port || 3000;

const gameServer = new Server();
gameServer.listen(port);
// Colyseus (不带宿主服务器)
const colyseus = require("colyseus");
const port = process.env.port || 3000;

const gameServer = new colyseus.Server();
gameServer.listen(port);

define (roomName: string, room:Room, options?: any)

为 matchmaker 定义一种房间类型.

参数:

  • roomName: string - 房间的类型名称. 客户端加入房间时, 需要提供该名称
  • room: Room - 房间
  • options?: any - 房间初始化使用的自定义房间参数

// 定义 "chat" 房间
gameServer.define("chat", ChatRoom);

// 定义 "battle" 房间
gameServer.define("battle", BattleRoom);

// 定义 "battle" 房间及其自定义房间参数
gameServer.define("battle_woods", BattleRoom, { map: "woods" });

多次定义同一个房间类型

允许使用不同的 房间参数 多次定义相同类型的房间. 当 Room#onCreate() 被触发时, 最终的 房间参数Server#define() 上定义的房间参数 + 房间创建时提供的参数的混合体.


房间参数

filterBy(options)

create()joinOrCreate() 方法创建的房间, 只有 filterBy()options 被保存在内部, 以便之后 join()joinOrCreate() 时用来筛选房间.

参数:

  • options: string[] - 一组参数的名字

示例: 允许不同的 "game modes".

gameServer
  .define("battle", BattleRoom)
  .filterBy(['mode']);

创建房间时, mode 会被存储在房间实例内部.

client.joinOrCreate("battle", { mode: "duo" }).then(room => {/* ... */});

可以在房间的 onCreate()onJoin() 里根据房间参数做不同处理, 以实现不同功能.

class BattleRoom extends Room {
  onCreate(options) {
    if (options.mode === "duo") {
      // 这种模式下的处理
    }
  }
  onJoin(client, options) {
    if (options.mode === "duo") {
      // 把玩家加入队伍!
    }
  }
}

示例: 用内置房间参数 maxClients 进行房间筛选

maxClients 是一个内置的房间参数, 可用于 matchmaking 和房间过滤.

gameServer
  .define("battle", BattleRoom)
  .filterBy(['maxClients']);

然后客户端可以指定请求加入某种容量的房间.

client.joinOrCreate("battle", { maxClients: 10 }).then(room => {/* ... */});
client.joinOrCreate("battle", { maxClients: 20 }).then(room => {/* ... */});


sortBy(options)

基于房间创建时的属性, 可以为房间设置优先级.

options 是一个键值对象, 键是属性名, 值是排序方法. 排序方法可以是: -1, "desc", "descending", 1, "asc""ascending".

示例: 基于内置属性 clients 排序

clients 是一个房间内置变量, 用于 matchmaking, 变量值表示当前已连接到该房间的客户端的数量. 在下面的示例中, 拥有最多客户端连接数的房间最优先. 使用 -1, "desc""descending" 进行降序排序:

gameServer
  .define("battle", BattleRoom)
  .sortBy({ clients: -1 });

想要以最少玩家数量为最优先排序, 把参数值反向即可. 即使用 1, "asc""ascending" 进行升序排序:

gameServer
  .define("battle", BattleRoom)
  .sortBy({ clients: 1 });


大厅实时房间列表

要让 LobbyRoom 接收到某指定类型房间的更新信息, 就要在房间定义的时候开启实时列表功能:

gameServer
  .define("battle", BattleRoom)
  .enableRealtimeListing();

更多详情请见 LobbyRoom


生命周期事件

可以从房间代码之外监听 matchmaking 事件, 例如:

  • "create" - 当房间被创建时
  • "dispose" - 当房间被销毁时
  • "join" - 当客户端加入房间时
  • "leave" - 当客户端离开房间时
  • "lock" - 当房间被锁定时
  • "unlock" - 当房间被解锁时

用法:

gameServer
  .define("chat", ChatRoom)
  .on("create", (room) => console.log("room created:", room.roomId))
  .on("dispose", (room) => console.log("room disposed:", room.roomId))
  .on("join", (room, client) => console.log(client.id, "joined", room.roomId))
  .on("leave", (room, client) => console.log(client.id, "left", room.roomId));

Warning

我们不建议使用这些事件监听器来维护房间 state. 而应使用房间中的 抽象方法.

simulateLatency (milliseconds: number)

这是一种在本地开发中模拟客户端 "延迟" 的好方法.

// 记得不要在生产环境中使用 `simulateLatency()` 方法.
if (process.env.NODE_ENV !== "production") {

  // 模拟服务器与客户端之间 200ms 的延迟.
  gameServer.simulateLatency(200);
}


listen (port: number)

将 WebSocket 服务器绑定至指定端口.


onShutdown (callback:Function)

注册一个回调, 在处理服务系统关闭之前被调用. 详情请见 优雅关闭.


gracefullyShutdown (exit: boolean)

关闭所有房间并清理其缓存数据. 当清理完成时, 返回一个已完成的 promise.

该方法会自动被调用, 除非在 Server 构造函数中写明 gracefullyShutdown: false.

Back to top