首页 / 横向专题 / 协议总索引

协议总索引

八大模块涉及的全部协议,号码全部核对自 Src/Core/Define/Net/NetDefine.ts。 拿到一个陌生协议号先来这里查。

284
SCNotify
252
CSReq
1
CSPush
537
合计

1. 命名与编号规律

后缀方向客户端 API说明
XxxSCNotifyS → CNet.Register / Net.UnRegister单向通知,服务器主动推
XxxCSReqC → SNet.Call / Net.CallAsync请求,必有对应 SCRsp
XxxSCRspS → C作为 Call 的回调参数不用单独 Register,Net 层已做请求-响应一对一映射
XxxCSPushC → SNet.Push单向推送,不等回包。全工程只有 1 条
Req / Rsp 号码是连号的 WorldEnterDungeonCSReq = 20503 → WorldEnterDungeonSCRsp = 20504
WorldClientSameSceneLoadDoneCSReq = 14716 → SCRsp = 14717
看到偶数号的 Rsp,减 1 就是它的 Req。 排查时如果只看到 Req 没看到 Rsp,说明服务器没回或者被超时丢了。

1.1 号段分布

号段数量业务归属
10xxx / 11xxx42登录、玩家基础数据
13xxx34战斗
14xxx139关卡玩法(最大的一段)。坠落重生、LoadDone、场景加载都在这
15xxx17行为树 + 传送/移动同步
20xxx31副本(进出、结算、爬塔星级)
23xxx55地图与传送点(解锁、标记、追踪)
26xxx60背包、道具
29xxx111组队、社交
30xxx62任务
37xxx12爬塔局外
号段不完全等于模块 15xxx 里前半段(15002-15016)是行为树,后半段(15508-15512)才是传送。 同样 14xxx 是个大杂烩,涵盖整个关卡玩法。
所以号段只能缩小范围,精确归属还得查下面的表。

2. 传送

号协议名方向作用
15512WorldTeleportSelfSCNotifyS→C传送入口。携带目标坐标 + reason + serverMoveVersion,reason 决定走哪条分支
14716WorldClientSameSceneLoadDoneCSReqC→SLoadDone 多人栅栏。「本端准备好了」+ 重置服务端「不可主控」标记。靠 serverMoveVersion 幂等去重,5 次退避重试
14717WorldClientSameSceneLoadDoneSCRspS→CLoadDone 回包。收到即结束重试
15509WorldTeleportEnterSCNotifyS→C进入传送体积/区域
15510WorldTeleportLeaveSCNotifyS→C离开传送体积
15511WorldServerEntityMoveSCNotifyS→C服务器驱动的实体位移
15508WorldEntityMoveBatchErrorSCNotifyS→C批量移动错误通知
14596WorldSyncDirPosSCNotifyS→C朝向与位置同步,TeleportController 也监听
14525WorldClientLoadDoneCSReqC→S跨场景加载完成(和 14716 的同场景版区分开)
14564WorldClientEnterLevelDoneCSReqC→S进入关卡完成
14572WorldClientSceneLoadAnimDoneCSReqC→S场景加载动画播完。没有 Seq3 时必须显式 emit 关闸,否则只能等 20s 兜底
14716 vs 14525:同场景 vs 跨场景 SameSceneLoadDone(14716) 用于同图同步瞬移; ClientLoadDone(14525) 用于跨图传送走完整 Loading 的那条路。
用错会导致服务器状态机对不上,表现为「传送完了但服务器认为你还没到」。 改传送代码时先确认当前是哪条路径。
已删除的历史协议 15504 / 15505 / 15506(PreServerMove 三件套)已在 0.7.0 清理, 连同 moveComp 的两个字段一并删除。
但 Protocol.d.ts 是 proto 自动生成的, 需要协调服务器同步删 .proto,否则下次生成会写回。 在老日志里看到这三个号是正常的。

3. 传送点与地图

号协议名方向作用
23707WorldTeleportCSReqC→S请求传送到某传送点。传送点模块的核心请求
23705WorldUnlockTeleportSCNotifyS→C传送点解锁通知。首次靠近解锁后落存档
23701WorldMapFullDataSCNotifyS→C地图全量数据(登录/进图时)
23702WorldMapUpdateSCNotifyS→C地图增量更新
23703WorldMapDataCSReqC→S主动拉取地图数据
23706WorldUnlockMapMarkSCNotifyS→C地图标记解锁
23714WorldUnlockMapFogSCNotifyS→C迷雾解锁
23709 / 23711WorldTraceMapMarkCSReq / StopTraceC→S追踪/取消追踪地图标记
23713WorldClearTraceMapMarkSCNotifyS→C清除追踪
23715 / 23717 / 23719Save / Update / Delete CustomerMapMarkC→S自定义标记的增改删
23721WorldCustomerMapMarkChangedSCNotifyS→C自定义标记变更通知
23722 / 23724Start / Stop TraceCustomerMapMarkC→S追踪自定义标记
23726WorldTraceCustomerMapMarkChangedSCNotifyS→C自定义标记追踪变更
23727WorldTraceRoleInfoSCNotifyS→C追踪玩家信息
23728 / 23729RedNameMonster Appear / DisappearS→C红名怪出现/消失
23730 / 23732Trace / StopTrace RedNameMonsterC→S追踪红名怪

4. 副本(含结算)

号协议名方向作用
20528WorldDungeonSettleSCNotifyS→C副本结算数据下发。整个结算三阶段的起点
20501WorldDungeonFullDataSCNotifyS→C副本全量数据
20502WorldDungeonUpdateSCNotifyS→C副本增量更新
20503 / 20504WorldEnterDungeon Req/Rsp双向进入副本
20505 / 20506WorldReEnterDungeon Req/Rsp双向重进副本
20507 / 20508WorldLeaveDungeon Req/Rsp双向退出副本。ShowInfo 参数从这里透传
20512WorldDungeonRewardSCNotifyS→C副本奖励
20513 / 20514Dungeon Enter/Leave CloseAreaS→C进入/离开封闭区域
20516 / 20517DungeonTeleportCloseArea Req/Rsp双向封闭区域内传送
20518WorldDungeonDefeatSCNotifyS→C副本失败
20520WorldDungeonMatchFlagSCNotifyS→C匹配标记
20522WorldDungeonClientLoadDoneSCNotifyS→C副本内客户端加载完成广播
20523WorldDungeonStateUpdateSCNotifyS→C副本状态更新
20525 / 20527DungeonClickLike Req / Notify双向结算点赞
20529 / 20531DungeonStatistics Update / Enable双向副本统计数据(结算面板数值来源)

5. 爬塔

5.1 局内(副本内实时 HUD)

号协议名方向作用
20532WorldDungeonTowerStarStartSCNotifyS→C星级监听开启 + 全量下发。带 starList 和 starsMask。主控树上必须放「开启星级监听」节点才会发
20533WorldDungeonTowerStarUpdateSCNotifyS→C单档增量更新。只带变化的那一档,不刷整体 mask,客户端需双源 OR 反算

5.2 局外(存档与排行)

号协议名方向作用
37501WorldTowerClimbDataSCNotifyS→C爬塔总数据
37502WorldTowerClimbTaskSCNotifyS→C塔任务更新
37503WorldTowerClimbBestRecordSCNotifyS→C最佳记录(星级落存档)。局内打完的星级最终落在这
37504 / 37505TowerClimbTaskList Req/Rsp双向拉取任务列表
37506 / 37507TowerClimbTaskTakeReward Req/Rsp双向领取任务奖励
37508 / 37509TowerClimbSelfRankList Req/Rsp双向拉取自己的排行信息
37510WorldTowerClimbSelfRankListSCNotifyS→C排行信息推送。存 Map 时读写 key 不一致是已知 bug

6. 关卡玩法(重生 / 计时器 / 子弹)

号协议名方向作用
14710WorldFallingRebornCSReqC→S坠落重生请求。客户端检测到 Z 低于 SafeDepth 后发起
15016WorldBehaviorTreeTimerParameterSCNotifyS→C计时器玩法数据。带 status(Running/Paused/Stopped)+ 时间戳,只有 Running 才叠加 timeDiff
14523WorldReviveSCNotifyS→C复活通知
14522WorldForbidReviveSCNotifyS→C禁止复活
14718WorldSuicideCSReqC→S自杀(GM/卡死自救)
14712WorldLevelSwitchVolumeCSReqC→S关卡切换体积
14584WorldLevelPlayerPositionSCNotifyS→C关卡内玩家位置广播
14585WorldLevelAiSpawnerInfoUpdateSCNotifyS→C刷怪器信息更新
15002-15016WorldBehaviorTree*S→C行为树节点/变量更新。关卡玩法的驱动核心,计时器也挂在这套上
关卡子弹没有专属协议 子弹走的是环境怪(EnvMonster)中转,复用怪物系统的创建/销毁协议, 再靠 15 位 TypeId 编码子弹类型。
所以排查子弹问题不要去 grep「Bullet」协议,找不到的—— 要看环境怪的实体创建流程。

7. 场景加载与流送

号协议名方向作用
14528WorldSetLayerTaskSCNotifyS→C服务器下发子关卡列表。带 layerTaskNameList,落进 ServerLayerTasks 后与旧集合求差集开关 DataLayerRuntime_SubMap_*
14504WorldEnterLevelSCNotifyS→C进入关卡。场景加载链的常规触发源
14503WorldLeaveLevelSCNotifyS→C离开关卡,对应卸载链
14525WorldClientLoadDoneCSReqC→S跨场景加载完成(同场景版是 14716)
14526WorldClientLoadDoneSCRspS→C上面的回包
14564 / 14565WorldClientEnterLevelDoneCSReq / SCRspC→S / S→C进入关卡完成上报与回包
14572 / 14573WorldClientSceneLoadAnimDoneCSReq / SCRspC→S / S→C加载动画播完。对应主链 ⑲ SceneLoadingAnimDownCmd
14580 / 14578 / 14579WorldDestructScene*双向场景破坏物同步
DataLayer 本身不走协议 服务器只下发子关卡名字列表(14528), 拼成 DataLayerRuntime_SubMap_{name} 和实际开关都是客户端做的。 另一批 DataLayerRuntime_EntityLevel_{levelId} 更是纯客户端按当前关卡 Id 推导, 完全没有对应协议。
所以「某个 DataLayer 没开」不要先怀疑协议—— 先用 WhereAmI 看客户端算出来的状态。

8. 使用规范

8.1 注册与注销必须配对

protected override OnRegisterNetEvent(): void {
    Net.Register(ENotifyMessageId.WorldDungeonTowerStarStartSCNotify, this.OnTowerStarStart);
    Net.Register(ENotifyMessageId.WorldDungeonTowerStarUpdateSCNotify, this.OnTowerStarUpdate);
}
protected override OnUnRegisterNetEvent(): void {
    Net.UnRegister(ENotifyMessageId.WorldDungeonTowerStarStartSCNotify);
    Net.UnRegister(ENotifyMessageId.WorldDungeonTowerStarUpdateSCNotify);
}
注意 UnRegister 只要消息号,不要 handler 因为一个消息号只能有一个 handler(不是列表)。 两个模块 Register 同一个号,后注册的会覆盖前一个—— 「协议明明发了但回调没触发」时查这个。

8.2 int64 必须转换

// ❌ protobuf 的 int64 是 Long 对象,直接算得 NaN
const t = progress.condition.waitTimeData.endTimeMs;

// ✅
const t = MathUtils.LongToNumber(progress.condition?.waitTimeData?.endTimeMs ?? 0);

时间戳、uid、大数值属性都要转。这是「数值算出来是 NaN」的头号原因。

8.3 收包端的四条防御

防御为什么
Model 可能还没装载ModelManager.XxxModel?. 用可选链,协议可能早于 Model 初始化到达
字段全部可选proto3 里所有字段都是 optional,notify.info?.starList ?? []
增量按主键有则更新无则插入findIndex 找到就改、找不到就 push,不要假设顺序
处理完必须 Emit中途提前 return 会导致 UI 不刷新,「首档不亮」就是这么来的

8.4 增删协议的正确姿势

1
先和服务器约定号码和字段
号码从对应模块的号段里取,Req/Rsp 连号
2
服务器改 .proto 并同步生成
Protocol.d.ts 是自动生成的,客户端不要手改
3
在 NetDefine.ts 加枚举项 + 类型映射
枚举、TNotifyProtocol 映射、MsgConfig 路由三处都要加
4
删协议时必须双边同步
只删客户端不删 .proto,下次生成会全部写回—— 看起来「删干净了、编译过了」,几天后又冒出来