Skip to content

RPC / 网络抓包面板 — 设计原则

状态:MVP 已实现(L0 + L1 只读)。
目标:在 Copilot 内增加 sproto 系通用化 + 多协议 Provider 插件 的网络/RPC 调试能力,不绑死单个 demo 项目,且 不影响现有引擎检测与常驻性能

HTTP 联调(GET/POST、JSON/XML、接口管理)可外置 CrapApi 等工具;本面板聚焦 游戏内 WebSocket / 二进制 RPC(如 sproto) 的抓包、解码、(可选)重放与 mock。


1. 架构分层(不绑 demo)

层级能力通用程度
L0WebSocket 帧抓包(hex/base64、时间、方向)任意 WS 游戏
L1sproto 解码(tag/session → 协议名 + JSON)页面存在 sproto 运行时 + 协议字典,或用户导入 schema
L2RPC 重放 / mock 回包ProtocolProvider 适配发送/响应入口
HTTP独立 Provider 或 DevTools Network非 sproto 主链路

禁止写死 demo 的 SocketForGameC2sProtocol 类名;demo 仅作第一个 ProjectPreset 验证。

ProtocolProvider 插件接口(概念)

text
detect()           → 是否适用(轻量,仅存在性探测)
decodeSend(bytes)  → { tag, name, session, body }
decodeRecv(bytes)  → { ... }
replay(entry)      → 可选
mock(entry, rsp)   → 可选,须单独开关 + 风险警示

Provider 按需加载:detect 命中 sproto 才加载 SprotoProvider;未命中可回落 L0。


2. 不影响检测 — 铁律

EngineManager.check() / haveEngine() 完全解耦

规则说明
不进引擎探针RPC 模块不得放入 packages/engine/ 的引擎注册或 EngineManager.check() 逻辑
不篡改引擎全局禁止覆盖 window.Laya / egret / cc / WebSocket 构造函数;仅 wrap 原型方法并保留原实现
独立 detectProtocolProvider.detect() 与引擎检测是两条链路;不得「有 sproto ⇒ 有引擎」
命名空间Hook 状态、缓冲、配置放在 $h5GameCopilot* 下,避免与其他检视扩展冲突
注入时机优先在 引擎 init 之后面板显式开启录制 时 install hook,避免干扰引擎加载顺序

回归必测(改动 RPC 相关代码时):

  1. Laya / Egret / Cocos 页:gameInfo 引擎名正确、场景树能出 stage
  2. 未开 RPC 面板时:行为与改前一致
  3. MV3 重载:关 F12 → 重载扩展 → 刷新游戏页 → 再开 DevTools

3. 可控性能 — 铁律

对齐 性能优化.md默认零 Hook,按需启用,热路径极简

3.1 生命周期(Lazy)

状态行为
未开 DevTools / RPC 面板关闭 / 录制 off不 install WS Hook(或 passthrough,零拷贝路径)
RPC 面板打开且用户开启录制install hook
面板关闭或录制 offuninstall 或恢复原生 send/onmessage

触发可参考:devPanelStateChange(true) + RpcCapture 面板 onShown(与 ai-lazy.js、注入日志 P0 按需轮询同一思路)。

3.2 热路径(MAIN world)

WebSocket.send / onmessage 回调内 仅允许

  • 时间戳、方向、长度
  • 拷贝 bytes 入 环形缓冲区(上限如 500 条,超出丢最旧)

禁止在 WS 回调内:sproto 全量解码、JSON.stringify、逐条 postMessage / Port 推送。

3.3 冷路径(DevPanel / inspector)

  • 解码:requestIdleCallback 或面板侧批量处理
  • IPC:批量 flush(如 200ms 一批),避免每条 RPC 一次 Port
  • UI:虚拟列表或分页;勿一次渲染万条 DOM

3.4 限流与黑名单

  • 高频 tag(心跳、移动同步等)可折叠、采样或用户配置黑名单
  • 单条 payload 过大时只存 hex 摘要 + 截断预览

3.5 包体积

  • Provider 与解码器可拆 rpc-capture.js 懒加载(类似 ai-lazy.js),不增大首屏 devpanel.js 关键路径

3.6 禁止项

  • 不得为 RPC 增加常驻 700ms 全 frame eval 轮询(见 CodePanel.pollPageConsole P0 策略)
  • 不得全局永久重写 console.log 把 RPC 灌进运行日志;独立通道,用户可选导出

4. 与其他功能域的边界

功能域要求
注入 / 运行日志RPC 抓包不走 userCodeConsoleHook 默认通道
AI 附带上下文默认不带 RPC 历史;仅「选中一条发给 AI」
暂停 / 下一帧Mock/重放须标注可能与服务端状态不一致
共存与 Charles、其他 WS Hook 扩展:链式调用原方法,禁止独占 WebSocket.prototype
Mock / 重放独立开关,UI 标注 【⚠️ 风险警示】;与「只读抓包」分离

5. 建议通信链路(实现时)

text
DevPanel(RpcCapturePanel)
  ↔ Chrome Port(DevPanel{tabId})
content.js(隔离世界)
  ↔ CustomEvent($h5GameCopilotChannel)
inspector.js(MAIN world)
  ↔ RpcCaptureBridge(WS Hook + 环形缓冲 + Provider 调度)

不得在 DevPanel 上下文直接读 window 上的游戏协议对象;解码在 MAIN world 或 inspectedWindow.eval 与现有检视链路一致。


6. MVP 建议顺序

  1. L0 + L1 只读:Lazy Hook + 缓冲 + sproto 自动 detect + 列表面板 ✅(顶栏「RPC抓包」、RpcCapturePanelrpcCapture/*
  2. L0 明文增强:WS 帧内自动识别 [...] / {...},首字段作 cmd;可选开发者 protocolMap
  3. L0 二进制包头:通用 [size:u16][msgType:u16][action?]…;hg 内置通道名;Body 为结构化摘要
  4. 单条详情、导出、发给 AI
  5. 单条重放(Provider 适配)
  6. Mock 回包(独立模式)
  7. HTTP Provider 或文档引导使用 CrapApi(避免与 CrapApi 全量重复)

双路径解码(勿混用破坏)

路径条件能力
sproto Tap页面有 window.Sproto 且可 patch SendData/HandlerType协议名 cs_/sc_ + JSON Body(自研/demo)
WS + 明文无完整 sproto抓原始帧;自动剥离包头后的 JSON/数组;列表 cmd:数字
WS + 二进制包头明文解不出,且前 4 字节 size≈帧长msgType + 可选 actionprotocolMap / hg 内置通道名;Body 为 {size,msgType,msgName,action,payloadHex}
用户字段表可选decodeSchemas:按 u8/u16/u32/u64/string… 把 payload 解成 fields;键 7027:8 / 7027 / *
开发者协议表可选protocolMap = { 7027: "MsgML", "7027:8": "MsgML_Act8" }

用户补全 Body(非 sproto)

游戏页 Console(MAIN world,与 inspector 同页):

js
window.__h5GameCopilotRpc = window.__h5GameCopilotRpc || {};
window.__h5GameCopilotRpc.protocolMap = {
  '7027': 'MsgML',
  '7027:8': 'MsgML_Act8'
};
window.__h5GameCopilotRpc.decodeSchemas = {
  '7027:8': [
    { name: 'id', type: 'u64' },
    { name: 'flag', type: 'u64' },
    { name: 'tail', type: 'restHex' }
  ]
};

对照 MsgXxx.create / processpushUint64 / popUint8 顺序写表;仅对新录制的包生效。也可在 RPC 面板点 「挂表扩展」 粘贴同一 JSON(DevPanel 经 Port 写入游戏页)。也可用 __h5GameCopilotRpcCapture.setDecodeSchemas(...)

已实现文件(MVP)

路径职责
packages/inspect/src/inspector/rpcCapture/MAIN world Hook、sproto / 明文 / 二进制包头解码、Bridge
rawTextDecode.tsWS 明文 [...]/{...} + 开发者 protocolMap
binaryHeaderDecode.ts通用长度+消息号包头;hg 通道内置表
userBinarySchema.ts用户 decodeSchemas 字段解码
packages/inspect/src/devpanel/RpcCapturePanel.tsDevPanel 列表 / 详情 UI
packages/inspect/src/common/MessageTypes.tsrpcCapture* 消息
scripts/assemble-copilot.js#rpcCaptureView + #btnRpcCapture

7. 相关文档

  • AGENTS.md — Agent 规约(RPC 改动须遵守本节原则)
  • 性能优化.md — 常驻开销与 P0/P1/P2 减负策略
  • .cursor/rules/change-impact-regression.mdc — 功能域 RPC抓包 回归地图
  • cursor.md — 路线图「RPC / 网络抓包」待办

H5 Game AI Inspector