跳到主要内容

消息与事件 ​

桥接本身不定义业务,只规定一份通用的消息格式。你发什么、对方怎么理解,全靠 type + action 约定。

消息格式 ​

一条消息就是一个 JSON 对象:

json
{
  "type": "mc_event",
  "action": "player_join",
  "data": { "player": "Steve", "uuid": "069a79f4-44e9-4726-a5be-fca90e38aaf5" },
  "clientId": "survival",
  "timestamp": "2026-11-12T10:00:00Z",
  "requestId": null,
  "replyTo": null
}
字段类型必填说明
type字符串✅消息大类,业务路由的第一级。建议小写 + 下划线,如 mc_event、mc_command、mc_chat
action字符串❌同一大类下的细分动作,如 player_join、exec。内置脚本要求它非空才处理
data任意 JSON❌业务数据,对象 / 数组 / 字符串都行,通常用对象
clientId字符串❌发送方的服务器标识。MC 侧发出的消息会自动带上自己的 client-id;Bngeuit 侧发出的消息由服务端填成发送目标或 *
timestamp字符串/数字✅RFC3339 时间(如 2026-11-12T10:00:00Z)或 Unix 秒/毫秒数字。插件自动填,不用手写
requestId字符串❌需要对方回复时才有,12 位随机串
replyTo字符串❌这是一条「回复」时才有,值等于原请求的 requestId

别自己拼 JSON

MC 侧脚本一律用 BridgeMessage 或 channel.send(type, action, data),时间戳、requestId、clientId 都会自动补齐。手拼 JSON 最容易漏 timestamp。

认证流程 ​

连接建立后不是立刻能发消息,先握手:

MC-BngeuitBridge(客户端)              BngeuitBridge(服务端)
        │                                      │
        │──────── WebSocket 连接 ─────────────→│
        │←─── {"type":"auth","action":"request"}│
        │                                      │
        │─── {"type":"auth","data":{           │
        │       "token":"xxx",                 │
        │       "clientId":"survival"}} ──────→│
        │                                      │
        │←─── {"type":"auth","action":"ok",    │  认证成功
        │       "data":{"clientId":"survival"}}│
        │                                      │
        │←═══════ 双向业务消息 ═══════════════→│

认证通过之前发的业务消息会被服务端拒绝(not_authenticated)。

认证失败的三种情况 ​

服务端返回含义MC 控制台提示
auth / auth_failedtoken 不对BngeuitBridge 认证失败!请检查 token 配置
error / client_id_required认证包里没有 clientId服务端要求必须提供 clientId,请在 config.yml 中配置 client-id
error / client_id_takenclientId 已被别的连接占用clientId "survival" 已被占用,请修改 config.yml

三种情况客户端都会主动断开,不会自动重连,改完配置重载插件才会重新握手。

其他协议层错误 ​

action触发条件
invalid_json发过去的不是合法 JSON
not_authenticated认证完成前发业务消息
message_too_large单条消息超过 max-message-size(默认 64 KB),data 里会带 maxSize
binary_not_supported发了二进制帧,本协议只收文本 JSON

请求-响应 ​

普通消息是「发出去就不管」,但有些场景要等对方回话,比如查状态、查白名单。

发请求时用 channel.send(message),插件会给消息加上 requestId 并返回一个 BridgeResponse:

nc
val request = BridgeMessage.of("mc_query", "online", null)
channel.send(request)
    .onSuccess { resp -> Bukkit.getLogger().info("对方回了: " + resp.getData()) }
    .onFailure { err -> Bukkit.getLogger().warning("没等到回复: " + err) }

对方收到带 requestId 的消息后,用 message.reply(data) 回复,replyTo 自动指向原请求,发起方那边的 onSuccess 就会被触发。

A ── type=query, requestId=abc123 ──→ B
A ←── type=query, replyTo=abc123 ──── B

规则:

  • 超时 30 秒,超时后 onFailure 收到「请求超时」
  • 连接断开时所有待响应请求立刻失败,onFailure 收到「连接已断开」
  • 回复消息(带 replyTo)不会再产生 requestId,也不会等待回执,避免套娃
  • BridgeResponse.get(timeout, unit) 可以阻塞等待,别在主线程用

内置约定:bridge/status ​

游戏内 /bngeuitbridge status 走的就是请求-响应:

项值
请求type=bridge、action=status
应答方Bngeuit 侧的 McBridgeStatus.nc
应答 data{version, uptimeSeconds, connectedClients, clientIds}
超时30 秒(没装应答脚本就会走到这一步)

这个应答不是 BngeuitBridge 内置的,必须装 McBridgeStatus.nc,否则命令一定超时。同理,你想加别的查询(TPS、内存、在线人数),在同一个 type=bridge 下加 action 分支即可。

事件 ​

两侧都能通过事件监听桥接的动静。

MC 侧(Bukkit 事件) ​

事件类触发时机线程
BridgeConnectEventTCP 连上服务端,此时还没认证WebSocket 线程
BridgeAuthEvent收到认证结果。成功时 success=true、有 clientId;失败时 errorMessage 有值WebSocket 线程
BridgeDisconnectEvent断开连接。closeCode、reason、wasAuthenticatedWebSocket 线程
BridgeMessageReceiveEvent收到一条业务消息(不含 auth、不含回复)异步线程
BridgeMessageSendEvent自己发出一条业务消息(含回复,不含 auth / 心跳)异步线程

字段:

事件可用字段
BridgeConnectEventserverUrl
BridgeAuthEventsuccess、clientId、errorMessage
BridgeDisconnectEventcloseCode、reason、wasAuthenticated
BridgeMessageReceiveEvent / BridgeMessageSendEventmessage,以及快捷属性 type、action、data、clientId

这些事件都不在主线程

除认证/连接类事件外,消息事件都在 WebSocket 线程触发。任何 Bukkit API(改方块、发消息给玩家、注册监听、执行命令)都必须切主线程,用 SchedulerUtils.sync { ... } 包一层,否则轻则数据错乱重则崩服。

BridgeMessageReceiveEvent 是异步事件(async = true),可以直接在监听器里做耗时操作,但同样不能碰 Bukkit。

Bngeuit 侧(插件事件) ​

Bngeuit 的脚本插件监听的是同名但不同包的类:cn.org.bukkit.bngeuit.bridge.event.*。

事件类触发时机可用字段
BridgeConnectEvent有客户端连上(未认证)remoteAddress
BridgeAuthEvent有客户端认证成功/失败remoteAddress、clientId、reason
BridgeDisconnectEvent客户端断开clientId、remoteAddress、reason
BridgeMessageReceiveEvent收到某台 MC 发来的业务消息message、clientId、type、action、data
BridgeMessageSendEvent自己发出的消息message、clientId(广播时是 *)

Bngeuit 侧写脚本的完整方式见 Bngeuit 脚本插件文档,本插件相关部分见 脚本与插件开发。