Appearance
网络包参考
文档版本:基于 2026-06-01 代码分析
面向对象:开发者 | 本文档列出全部53个网络包的技术细节,普通管理员无需阅读。
概述
逃走中MOD使用 NeoForge 的 CustomPacketPayload + PayloadRegistrar 机制(NeoForge 21.x 标准网络 API)实现客户端与服务端之间的数据同步。总计注册 53 个 Payload 类型(S→C 方向 27 个,C→S 方向 26 个),分为 Phone(27个)、RFM(25个)、Permission(1个)三大模块。
网络协议版本号硬编码为 "1",客户端与服务端版本不匹配时网络包将被拒绝。
核心概念
架构分层
ModNetwork.registerPayloads()
|
+-- PayloadRegistrar (version "1")
| +-- playToServer(...) : 25 条 C->S 注册
| +-- playToClient(...) : 31 条 S->C 注册
|
+-- PhonePayloadHandler(分派层,27个payload → 5个子handler)
| +-- PhoneRegistrationPayloadHandler 手机注册
| +-- PhoneCallPayloadHandler 通话管理
| +-- PhoneContactsPayloadHandler 通讯录管理
| +-- PhoneMessagePayloadHandler 短信管理
| +-- PhoneConfigPayloadHandler 配置管理
|
+-- RfmPayloadHandler(单层,28个payload)
|
+-- PermissionPayloadHandler(单层,1个payload)三种交互模式
| 模式 | 描述 | 典型命名 |
|---|---|---|
| 请求-响应 | 客户端 Request*Payload → 服务端 Sync*Payload | RequestRfmNoticesPayload → SyncRfmNoticesPayload |
| 服务端推送 | 服务端主动发送 Notify*、Append*、Play* | NotifyIncomingMessagePayload、PlayRfmTitleWriterPayload |
| 命令-执行 | 客户端发送 Update*Payload(含 action 字段),服务端根据 action 执行 | UpdateRfmControlPayload(action="start") |
数据方向标注
| 标注 | 含义 |
|---|---|
| C→S | 客户端发送到服务端(playToServer) |
| S→C | 服务端发送到客户端(playToClient) |
架构设计
网络包处理流程
mermaid
sequenceDiagram
participant Client as 客户端
participant PReg as PayloadRegistrar
participant Handler as PayloadHandler
participant Server as 服务端
rect rgb(40, 40, 60)
Note over Client,Server: C→S 请求-响应模式
Client->>PReg: playToServer(RequestPayload)
PReg->>Handler: handle(RequestPayload, context)
Handler->>Server: 委托给 Manager
Server->>PReg: playToClient(SyncPayload, player)
PReg->>Client: 发送到客户端
end
rect rgb(40, 60, 40)
Note over Client,Server: S→C 推送模式
Server->>PReg: playToClient(NotifyPayload, player)
PReg->>Client: 发送到客户端
Client->>Handler: handle(NotifyPayload, context)
Handler->>Client: 写入 ClientState
end关键文件
| 文件 | 说明 |
|---|---|
com/chenxi/chenxi_rfm/common/network/ModNetwork.java | 网络包注册入口 |
com/chenxi/chenxi_rfm/common/network/handler/PhonePayloadHandler.java | Phone 分派层 Handler |
com/chenxi/chenxi_rfm/common/network/handler/RfmPayloadHandler.java | RFM 单体 Handler |
com/chenxi/chenxi_rfm/common/network/handler/permission/PermissionPayloadHandler.java | 权限同步 Handler |
com/chenxi/chenxi_rfm/common/network/handler/phone/PhoneRegistrationPayloadHandler.java | 手机注册子Handler |
com/chenxi/chenxi_rfm/common/network/handler/phone/PhoneCallPayloadHandler.java | 通话管理子Handler |
com/chenxi/chenxi_rfm/common/network/handler/phone/PhoneContactsPayloadHandler.java | 通讯录子Handler |
com/chenxi/chenxi_rfm/common/network/handler/phone/PhoneMessagePayloadHandler.java | 短信子Handler |
com/chenxi/chenxi_rfm/common/network/handler/phone/PhoneConfigPayloadHandler.java | 配置管理子Handler |
com/chenxi/chenxi_rfm/common/network/handler/phone/PhonePayloadSupport.java | Phone 工具类(非网络Handler) |
网络包清单
手机 — 注册(3个)
| Payload 类 | 方向 | 字段 | 用途 |
|---|---|---|---|
RegisterPhoneAppPayload | C→S | (无字段) | 客户端请求注册当前手机 |
RequestPhoneRegistrationStatePayload | C→S | (无字段) | 客户端请求查询手机注册状态 |
SyncPhoneRegistrationStatePayload | S→C | boolean registered, String ownerName | 服务端同步手机注册状态 |
手机 — 通话(5个)
| Payload 类 | 方向 | 字段 | 用途 |
|---|---|---|---|
RequestStartPhoneCallPayload | C→S | String phoneNumber, String displayName | 客户端请求发起通话 |
RequestHandlePhoneCallPayload | C→S | String callId, String action | 客户端处理通话(接听/挂断) |
SyncPhoneCallStatePayload | S→C | String callId, state, peerUuid, peerName, peerPhone, message, long stateStartMillis, stateEndMillis, serverNowMillis | 服务端同步通话状态 |
RequestCallHistoryPayload | C→S | (无字段) | 客户端请求通话记录 |
SyncCallHistoryPayload | S→C | List<PhoneCallHistoryData> records | 服务端同步通话记录 |
手机 — 通讯录(4个)
| Payload 类 | 方向 | 字段 | 用途 |
|---|---|---|---|
RequestContactsPayload | C→S | (无字段) | 客户端请求联系人列表 |
SyncContactsPayload | S→C | List<PhoneContactData> contacts | 服务端同步联系人列表 |
RequestContactDetailPayload | C→S | String targetName | 客户端请求联系人详情 |
SyncContactDetailPayload | S→C | String ownerUuid, ownerName, phoneNumber | 服务端同步联系人详情 |
手机 — 消息(8个)
| Payload 类 | 方向 | 字段 | 用途 |
|---|---|---|---|
RequestMessageThreadsPayload | C→S | (无字段) | 客户端请求消息线程列表 |
SyncMessageThreadsPayload | S→C | List<PhoneMessageThreadData> threads | 服务端同步消息线程列表 |
RequestMessageConversationPayload | C→S | String targetName | 客户端请求对话内容 |
SyncMessageConversationPayload | S→C | String targetName, List<PhoneMessageLineData> messages | 服务端同步完整对话 |
SendPhoneMessagePayload | C→S | String targetName, String content | 客户端发送短信 |
NotifyIncomingMessagePayload | S→C | String senderName, String threadKey | 服务端通知新消息 |
SyncSingleMessageThreadPayload | S→C | PhoneMessageThreadData thread | 服务端同步单个消息线程 |
AppendMessageConversationLinePayload | S→C | String targetName, PhoneMessageLineData line | 服务端追加消息行 |
手机 — 冷却/配置(7个)
| Payload 类 | 方向 | 字段 | 用途 |
|---|---|---|---|
UpdateMessageCooldownPayload | C→S | int cooldownSeconds | OP 更新消息冷却秒数 |
SyncMessageCooldownPayload | S→C | int cooldownSeconds | 服务端同步消息冷却秒数 |
UpdateCallWaitSecondsPayload | C→S | int callWaitSeconds | OP 更新呼叫等待秒数 |
SyncCallWaitSecondsPayload | S→C | int callWaitSeconds | 服务端同步呼叫等待秒数 |
UpdateMaxCallSecondsPayload | C→S | int maxCallSeconds | OP 更新最大通话秒数 |
SyncMaxCallSecondsPayload | S→C | int maxCallSeconds | 服务端同步最大通话秒数 |
SyncConversationCooldownPayload | S→C | String targetName, int remainingSeconds | 服务端同步对话冷却剩余秒数 |
RFM — 游戏控制(9个)
| Payload 类 | 方向 | 字段 | 用途 |
|---|---|---|---|
RequestOpenRfmManagerPanelPayload | C→S | int initialTab | 客户端请求打开管理面板 |
OpenRfmManagerPanelPayload | S→C | int initialTab, hasBlockContext, String boundNoticeId, blockDimension, int blockX, blockY, blockZ | 服务端响应打开管理面板 |
RequestRfmGameStatePayload | C→S | (无字段) | 客户端请求游戏状态 |
SyncRfmGameStatePayload | S→C | String state, phase, int totalSeconds, elapsedSeconds, long syncMillis, serverNowMillis, int escapersRemaining | 服务端同步游戏状态 |
UpdateRfmControlPayload | C→S | String action, int value | OP 发送控制指令(start/pause/resume/stop/setTime/setRate/clearCoin) |
RequestRfmManagerPlayersPayload | C→S | (无字段) | 客户端请求管理器玩家列表 |
SyncRfmManagerPlayersPayload | S→C | List<RfmManagerPlayerData> players | 服务端同步管理器玩家列表 |
UpdateRfmPlayerManagePayload | C→S | String action, targetUuid, value | OP 管理玩家(nickname/role/eliminate/abstain/traitor/addCoin) |
SyncRfmHudPayload | S→C | String mode, int originX, originY, originZ, List<RfmHudPlayerData> players, List<String> aliveParticipantUuids, boolean resurrectStageActive, List<String> pendingResurrectRunnerUuids | 服务端同步游戏HUD数据 |
RFM — 通知(6个)
| Payload 类 | 方向 | 字段 | 用途 |
|---|---|---|---|
RequestRfmNoticesPayload | C→S | (无字段) | 客户端请求通知列表 |
SyncRfmNoticesPayload | S→C | List<RfmNoticeData> notices | 服务端同步通知列表 |
UpdateRfmNoticePayload | C→S | String action, RfmNoticeData notice | OP 管理通知(create/save/delete/send) |
BindRfmNoticeToBlockPayload | C→S | String noticeId, dimension, int blockX, blockY, blockZ | OP 绑定通知到 notice_sender 方块 |
RequestRfmNoticeTargetsPayload | C→S | (无字段) | 客户端请求通知目标列表 |
SyncRfmNoticeTargetsPayload | S→C | List<RfmNoticeTargetData> targets | 服务端同步通知目标列表 |
RFM — 坐标(3个)
| Payload 类 | 方向 | 字段 | 用途 |
|---|---|---|---|
RequestRfmCoordinatesPayload | C→S | (无字段) | 客户端请求坐标点列表 |
SyncRfmCoordinatesPayload | S→C | List<RfmCoordinateData> coordinates | 服务端同步坐标点列表 |
UpdateRfmCoordinatePayload | C→S | String action, RfmCoordinateData coordinate, boolean useCurrentPosition | OP 管理坐标点(add/delete/teleport) |
RFM — 触发器(3个)
| Payload 类 | 方向 | 字段 | 用途 |
|---|---|---|---|
RequestRfmTriggersPayload | C→S | (无字段) | 客户端请求触发器列表 |
SyncRfmTriggersPayload | S→C | List<RfmTriggerData> triggers | 服务端同步触发器列表 |
UpdateRfmTriggerPayload | C→S | String action, RfmTriggerData trigger | OP 管理触发器(save/trigger/reset/teleport/clear) |
RFM — 手机通知(2个)
| Payload 类 | 方向 | 字段 | 用途 |
|---|---|---|---|
SyncPhoneRfmNoticesPayload | S→C | List<RfmPhoneNoticeData> notices | 服务端同步手机端通知列表 |
AppendPhoneRfmNoticePayload | S→C | RfmPhoneNoticeData notice | 服务端追加一条手机通知 |
RFM — 标题动画(2个)
| Payload 类 | 方向 | 字段 | 用途 |
|---|---|---|---|
PlayRfmTitleWriterPayload | S→C | String fileId, int startGroup, List<RfmTitleWriterGroupData> groups | 服务端播放字幕动画 |
StopRfmTitleWriterPayload | S→C | (无字段) | 服务端停止字幕动画 |
权限(1个)
| Payload 类 | 方向 | 字段 | 用途 |
|---|---|---|---|
SyncPermissionLevelPayload | S→C | NfaPermissionLevel level(枚举序列化为 String id) | 服务端同步玩家的权限等级 |
内嵌数据结构
以下 13 个类为内嵌数据结构(record),不实现 CustomPacketPayload,仅作为列表元素嵌入在 Sync 类中:
| 类名 | 所属模块 | 包含字段 |
|---|---|---|
PhoneCallHistoryData | phone.call | peerUuid, peerName, peerPhone, directionText, statusText, missed, timeMillis |
PhoneContactData | phone.contacts | ownerUuid, ownerName |
PhoneMessageThreadData | phone.messages | threadKey, ownerUuid, ownerName, lastMessage, lastMessageTimeMillis, unread |
PhoneMessageLineData | phone.messages | senderOwnerName, receiverOwnerName, content, timestampMillis |
RfmManagerPlayerData | rfm | uuid, displayName, nickname, role, state, permissionLevel |
RfmHudPlayerData | rfm | uuid, displayName, role, runnerEliminated, runnerAbstained, traitor |
RfmNoticeData | rfm | noticeId, name, content, receiverType, extraReceivers |
RfmNoticeVariableData | rfm | key, type, value(未被网络直接使用) |
RfmNoticeTargetData | rfm | uuid, displayName, originalName, runnerEliminated, runnerAbstained, online |
RfmCoordinateData | rfm | coordinateId, name, dimension, x, y, z |
RfmTriggerData | rfm | dimension, name, mode, blockX, blockY, blockZ, targetRemainingSeconds, powered |
RfmPhoneNoticeData | rfm | title, content, titleColorRgb, titleBold |
RfmTitleWriterGroupData | rfm | index, next, preBlinkTicks, charIntervalTicks, cursorBlinkTicks, stayTicks, blankAfterTicks, line1Text, line2Text, line1Style, line2Style |
关键流程
Payload 序列化方式
所有 Payload 均为 Java record,使用 StreamCodec 进行序列化:
| 编码方式 | 适用场景 |
|---|---|
StreamCodec.composite() | 有字段的 Payload,组合多个 ByteBufCodecs.* |
StreamCodec.of() | 手动读写 ByteBuf,用于自定义编解码 |
StreamCodec.unit() | 无字段的空 Payload(纯请求类) |
注意事项 / 限制
- 协议版本硬编码:
ModNetwork使用version "1",升级网络协议时必须手动增加版本号,否则新旧客户端无法通信。 - Payload 不可变性:所有 Payload 使用 Java
record定义,是不可变的。修改数据必须构造新实例。 - 内嵌数据类不独立传输:13 个 Data 类(如
PhoneContactData、RfmTriggerData)只能作为列表元素嵌入在 Sync 类中传输,不能独立作为网络包发送。 - 代码风格不一致:部分类使用了
ByteBufCodecs.list()的流式风格(如SyncRfmNoticesPayload),部分使用了手动列表读写循环(如SyncRfmHudPayload)。后者可能是为了更好的 null 安全性。 - PhonePayloadHandler 非严格分派:
SyncMessageCooldownPayload等三个 sync 包在PhonePayloadHandler中被路由到了PhoneRegistrationPayloadHandler而非PhoneConfigPayloadHandler,这是实现层面的设计选择。 - 权限检查在 Handler 层:
RfmPayloadHandler和PhonePayloadHandler中的服务端 handler 方法在执行业务逻辑前会调用NfaPermissionService进行权限检查。