Group Details Private
Global Moderators
Forum wide moderators
Member List
Node.js
//传入请求HttpRequest
function getClientIp(req) {
return req.headers['x-forwarded-for'] ||
req.connection.remoteAddress ||
req.socket.remoteAddress ||
req.connection.socket.remoteAddress;
}
Express
//express框架则简单许多
req.ip
Colyseus
- 使用 Express
//arena.config.ts 的 initializeExpress 函数中
app.use('/*', (req, res) => {
console.log("getting ip address...")
var ip = req.ip;
console.log(ip);
});
- 使用 onAuth 函数
//Room 类的 onAuth 函数
onAuth(client: Client, options: any, request?: http.IncomingMessage): any {
console.log("getting ip address...")
var ip = request.headers['x-forwarded-for'] || request.connection.remoteAddress;
console.log(ip);
return true;
}
Filter 是什么意思?
Filter 这个词在检索和匹配类的程序中经常见到.
比如下面这个网站.
Type to filter... 这里我们填写关键词,
匹配程序精准地帮我们找到了需要的内容.
Colyseus 里面有两处与 Filter 有关的地方. 一个是 Matchmaking 用的 filterBy(); 一个是 Schema 用的 @filter 装饰器.
RegisteredHandler.filterBy()
这次我们用 Colyseus Server + Cocos Creator Client 来做展示.
首先建立服务器环境.
不知道这个菜单哪里来的的话请参考这里.
新建 Cocos 项目, 安装 Colyseus 客户端 SDK.
如果发现导入时报错,
要在 tsconfig.json 文件中开启 allowSyntheticDefaultImports
参数.
好了, 准备工作结束, 让我们来连接房间看看.
joinOrCreate
函数的第一个参数是房间名, 第二个参数是自定义的房间参数.
这里我们自定义一个叫做 mode
的参数, 值为 duo
, 表示是双人游戏房间.
this.room = await this.client.joinOrCreate("my_room", { mode: "duo" });
在服务器端, 我们定义了房间名 my_room, 然后后面跟着一个 filterBy, 里面有两个过滤参数, "mode" 和 "level".
gameServer.define('my_room', MyRoom).filterBy(["mode", "level"]);
它的意思是, 在进行房间匹配的时候, 把所有房间根据 "mode" 和 "level" 两个参数过滤, 只有这两个参数 完全匹配
的玩家才可以匹配进入相应房间.
还记得客户端连接时的需求吗? 玩家要进入 "mode" 为 "duo" 的房间, "level" 没有指定.
匹配器会根据 server 上已有的没有锁定的房间, 过滤出 "mode" 为 "duo" 的, "level" 为 null 的房间, 如果存在, 优先进入; 如果不存在, 新建一个这样的房间再进入.
如果客户端没有要求参数, 如何匹配房间呢? 匹配器会寻找 "mode" 为 "null" 而且 "level" 为 "null" 的房间优先匹配进入; 对于 "mode" 为 "duo" 的房间, 它是 不考虑在内
的.
除了 filterBy, 常用的还有一个 sortBy, 两个联合使用又是什么意思呢?
gameServer.define('my_room', MyRoom).filterBy(["mode"]).sortBy({level:-1});
sortBy 的意思是排序. 根据参数值升序 (+) 或者降序 (-) 排序, 然后进行优先匹配.
上面那条语句的意思是, 寻找 mode 一致的, 按 level 从大到小排列, 选最大的, 进行匹配.
可以看出, filterBy 的作用就是告诉匹配器, 如何寻找, 找什么样的房间, 来给客户端进行分配.
Schema 的 @filter 装饰器
众所周知(?), Schema 是会自动同步到房间的每一个客户端中的, 是 "服务器权威" 模式的基础.
但是有时候, 我们需要某个客户端只能知道 Schema 的一部分而非全部.
典型的需求就是牌类游戏, 每个客户端只能了解自己的手牌而不能知道其他人的牌.
让我们开发一个简单的猜骰子点数大小的游戏. 游戏分三个步骤:
- 玩家进入服务器房间, 服务器开始摇骰子出一个点数, 此时玩家虽然知道已摇出点数, 但是不能知道点数是多少;
- 玩家猜测点数大小并发送到服务器;
- 服务器开点数, 并把结果发回给客户端.
点数 1~3 是 "小", 4~6 是 "大".
游戏的 Schema 设定是关键所在:
import {Schema, Context, type, filter} from "@colyseus/schema";
import {Client} from "colyseus";
export class Dice extends Schema {
@type("string") status: string = "rolling";
@type("string") result: string = "";
@filter(function (this: Dice, client: Client, value: Dice['number'], root: Schema) {
return this.status == "opened";
})
@type("uint8") number: number;
}
首先导入 filter 装饰器, 才能使用. 这个游戏我们要过滤的是骰子点数, 也就是最后的 number. 过滤方法是看当前状态是否已经到了开点数的 status.
status 分为 "要骰子", "猜点数", "开点数" 三个阶段.
"猜点数" 阶段虽然客户端知道有 "number" 这个数据, 但是值是 undefined.
当服务器在任何地方执行了 this.state.status = "opened";
这条语句, 过滤自动失效, 此后客户端就能知道具体点数了.
代码和手册参考:
https://github.com/CocosGames/ColyseusFilters
https://docs.colyseus.io/colyseus/state/schema/#filtering-data-per-client
Hi. There isn't OT functions out of box, but you can do it yourself with colyseus.
Hi, lots of things can cause issues like this, please post more details.
HI! There's an example here: https://github.com/CocosGames/ColyseusAudience.
Hello everyone!
Long time without posting any updates here, I'm still alive!
We are on Beta.24 already and you can find the full post about it here:
https://www.reldens.com/news/beta-24
As always feel free to reach me! I would love to get any feedback.
Hope you like it!
Change log: Releases · damian-pastorini/reldens · GitHub
Demo: https://demo.reldens.com
Admin Panel: Reldens - Administration Panel (login with any registered email and password in the game)