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