From a46bba2435eb6c4e75f19c2c0b4bc17e44135273 Mon Sep 17 00:00:00 2001 From: TermiNexus Date: Tue, 27 Oct 2026 02:08:01 +0800 Subject: [PATCH] =?UTF-8?q?docs:=20=E4=BF=AE=E6=AD=A3=E8=BF=98=E5=8E=9F?= =?UTF-8?q?=E8=AE=A1=E5=88=92=EF=BC=8C=E7=A1=AE=E8=AE=A4=20net=20=E6=A8=A1?= =?UTF-8?q?=E5=9D=97=E5=B7=B2=E5=AE=9E=E7=8E=B0=E6=95=B0=E6=8D=AE=E5=8C=85?= =?UTF-8?q?=E8=A7=A3=E6=9E=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 3DTank/docs/FullRestorationPlan.md | 163 +++++++++++++++-------------- 3DTank/docs/NetCoverage.md | 109 +++++++++++++++++++ 2 files changed, 195 insertions(+), 77 deletions(-) create mode 100644 3DTank/docs/NetCoverage.md diff --git a/3DTank/docs/FullRestorationPlan.md b/3DTank/docs/FullRestorationPlan.md index f894cac..ed53439 100644 --- a/3DTank/docs/FullRestorationPlan.md +++ b/3DTank/docs/FullRestorationPlan.md @@ -236,113 +236,118 @@ --- -## 5. 官方 Socket 链路反编译 +## 5. 官方 Socket 链路 -### 5.1 先纠正一个事实 +### 5.1 先纠正:数据包解析已经实现 -官方客户端**没有 Socket.IO**。在 `3DTank/src` 与 `main.6469b966.js` 中搜索 `socket.io` / `engine.io` / `io.connect` 均为 0 命中。 +不是“从零反编译”。KT 工程已经有一套完整的官方包解析: -官方用的是**原生 WebSocket + 自定义二进制协议**: +- `TankiOffline/net/src/jsMain/kotlin/Net/Generated/`: + - `DownlinkRegistry`:**681** 个 methodId → codec + - `UplinkRegistry`:**361** 个 methodId → codec + - `ModelRegistry`:**363** 个 modelId → codec + - 14 个 codec 模块:85183 / 47243 / 85196 / 31908 / 16100 / 10283 / 25377 / 54199 / 37504 / 88693 / 89803 / 85667 / 67222 / 99527 + - 另有 24635 / 1510 / 29554 / 45686 / 61860 / 71105 / 85745 / 87072 +- `Net/Protocol/`: + - `Entry`:Hash Request / Hash Response / EnterSpace / OpenSpace + - `SpaceFrame`:帧体 → 记录 + - `StreamDecoder`:明文/探测/解密三阶段、XOR key + - `Containers`:Lt / Pt / Zt / Alias + - `TankStateCodec` +- `Net/Wire/ModelCodec` +- `App/Session/`: + - `SpaceSession`:Feed → DecodedRecord + - `SessionRouter`:DecodedRecord → DownlinkActions → Redux Store + - `UplinkEncoder`:动作 → 上行帧 + - `SessionCheck` / `StateCheck` / `AutoTest`:自检与真实中继测试 +- `App/State/`: + - 89/89 reducer 切片 + - `DownlinkActions` / `DownlinkModelActions` + - `RootState` / `RootWiring` -- `3DTank/src/module_61860.js:992`:`new WebSocket(this.t7u_1)` -- `this.t7u_1 = t + "://" + n + ":" + i + "/"`(protocol / host / port) -- `binaryType = "arraybuffer"` -- 连接后走 `Ee(t)` 协议对象、`p7u_1` / `q7u_1` 编解码、`r7u_1` 命令分发 +所以“官方所有的数据包解析”这件事,KT 工程已经做了大部分,不需要重新读 14 个 codec 模块。 -所以计划是反编译**官方 WebSocket 链路**;如果另有 Socket.IO 入口(例如网页活动页),需要单独给出 URL,我再补一条支线。 +### 5.2 真正缺的是“链路前半段” -### 5.2 链路分层 +现在的 `LobbyClient` 是: ```text -启动 -└─ 配置 / 区域 - ├─ config.xml(c{server}.3dtank.com/config.xml) - ├─ status.js(3dtank.com/s/status.js) - └─ balancer(balancer.*.tankionline.com/balancer) - └─ BalancerStatus / BalancerNode / BalancerNodeEndpoint - └─ 选节点 host:port - └─ WebSocket(protocol://host:port/) - ├─ 登录 / 鉴权 - ├─ Hash Request / Hash Response - ├─ Open Space / EnterSpace - ├─ LoadDependencies - └─ Space 二进制帧 - ├─ 解帧 / 解密 - ├─ 命令 id + 字段 - └─ SessionRouter → RootState +登录表单 → LobbyClient.Login → Connect(中继 URL) → Hash Request → ... ``` -### 5.3 反编译步骤 +它缺的是官方链路的前半段: -#### S1 配置 / Balancer +1. **config / status / balancer**:官方节点发现 +2. **auth**:账号密码 → token/cookie +3. **官方 WebSocket 建连**:protocol/host/port、header、子协议 +4. **覆盖率**:真实官方会话下 `SessionRouter.Unmapped` / `Failed` 是否归零 +5. **golden 帧校验**:现有 codec 是否 byte-for-byte 对得上 -1. 读 `module_13431`:区域、`config.xml`、`status.js`、balancer URL 规则。 -2. 读 `module_61860` 的 `BalancerStatus` / `BalancerNode` / `BalancerNodeEndpoint` 字段。 -3. 抓一次官方启动请求:config、status、balancer。 -4. 产出 `docs/BalancerProtocol.md`:URL 规则、字段、选节点算法。 +### 5.3 链路分层(已有 / 待补) -#### S2 登录 / 鉴权 +| 层 | 状态 | 位置 | +|---|---|---| +| config / status / balancer | 待补 | `module_13431` / `module_61860` | +| auth / 登录 | 待补 | `module_82347` Entrance / `module_61860` | +| WebSocket 建连 | 待补 | `module_61860:992` `Ie` | +| Hash / OpenSpace / EnterSpace | 已有 | `Net/Protocol/Entry.kt` | +| 帧解码 / XOR | 已有 | `Net/Protocol/StreamDecoder.kt` | +| 记录解码 | 已有 | `Net/Protocol/SpaceFrame.kt` + `Registry.kt` | +| 容器 Lt/Pt/Zt/Alias | 已有 | `Net/Protocol/Containers.kt` | +| 记录 → 动作 | 已有 | `App/Session/SessionRouter.kt` | +| 动作 → 上行 | 已有 | `App/Session/UplinkEncoder.kt` | +| 状态 | 已有 | `App/State/` | -1. 读 `module_82347` 的 `EntranceComponentStyle` + `xxn` / `Tzn` / `gKt` / `sWt`。 -2. 找登录请求:HTTP/WS、方法、路径、body、header、cookie、token。 -3. 抓包:登录成功/失败、验证码、记住我、社交登录。 -4. 产出 `docs/AuthProtocol.md`:请求/响应、错误码、token 生命周期。 +### 5.4 待补工作 -#### S3 WebSocket 建连 +#### S1 config / balancer -1. 读 `module_61860` `Ie`:URL、子协议、header、binaryType。 -2. 读 `Ee(t)`:protocol 对象、版本、握手字段。 -3. 读 `p7u_1` / `q7u_1`:帧格式、长度、压缩、加密。 -4. 产出 `docs/SocketProtocol.md`:建连、帧格式、心跳、重连。 +1. 读 `module_13431` 的 URL 规则、区域、config.xml、status.js、balancer。 +2. 读 `module_61860` 的 `BalancerStatus` / `BalancerNode` / `BalancerNodeEndpoint`。 +3. 抓官方启动请求。 +4. 在 Kotlin 实现 `BalancerClient`,输出 `docs/BalancerProtocol.md`。 -#### S4 Lobby 握手 +#### S2 auth -1. `Hash Request` / `Hash Response`:字段、digest、加密标志。 -2. `Open Space`:spaceId、节点、token。 -3. `EnterSpace`:digest、spaceId。 -4. `LoadDependencies`:zt 载荷、依赖列表。 -5. 与现有 `LobbyClient` 逐字段对照,删掉中继特化代码。 +1. 读 `module_82347` Entrance 的登录请求。 +2. 抓登录成功/失败、token/cookie。 +3. 在 `LobbyClient.Login` 里替换 `Connect(中继)` 为官方 auth + 官方 WS。 +4. 输出 `docs/AuthProtocol.md`。 -#### S5 Space 协议 +#### S3 官方 WebSocket -1. 读 14 个 codec 模块:85183 / 47243 / 85196 / 31908 / 16100 / 10283 / 25377 / 54199 / 37504 / 88693 / 89803 / 85667 / 67222 / 99527。 -2. 命令 id + 字段序号 + 默认值逐项入表。 -3. 用 `wss_server.js` 抓 golden 帧,做 encode/decode 对比。 -4. 产出 `docs/SpaceProtocol.md` + `names/codec_fields.json`。 +1. 读 `module_61860` `Ie`:URL、header、子协议、binaryType。 +2. 用官方 URL 替换 `LobbyClient.Connect`。 +3. 保留现有 `Entry` / `SpaceSession` / `SessionRouter`。 +4. 输出 `docs/SocketProtocol.md`。 -#### S6 状态映射 +#### S4 覆盖率审计 -1. 读 `module_10032`(Redux 核心)、`module_18334`(DI)、`module_61860`(对象模型)。 -2. 命令 → 记录 → RootState 槽位逐项对照。 -3. 产出 `docs/StateMap.md` 更新。 +1. 用官方会话跑 `SessionRouter`,收集 `UnmappedIds` / `FailedIds`。 +2. 对照 `Registry.kt` / `DownlinkActions`,逐项补齐。 +3. 目标:`Unmapped = 0`、`Failed = 0`(或只剩明确不需要的 UI-only 记录)。 +4. 输出 `docs/NetCoverage.md`。 -### 5.4 工具链 +#### S5 golden 帧 -| 工具 | 用途 | -|---|---| -| `3DTank/tools/serve.js` | 本地静态 + 反向代理 + config 改写 | -| `3DTank/tools/wss_server.js` | 中继 + 抓包 + 实时解密 | -| `3DTank/tools/analyze_packets.js` | 抓包分析 | -| `3DTank/tools/prefetch_assets.js` | 资源预拉 | -| `3DTank/tools/headless_probe.js` | 页面探针 / CSS / 截图 | -| `3DTank/tools/server/` | 协议服务端骨架(codec/dispatch/session/space/world) | -| Chrome DevTools Protocol | 网络抓包、HAR、WS frames | -| mitmproxy / Fiddler | TLS 抓包(如需要) | +1. 用 `wss_server.js` / CDP 抓官方帧。 +2. 对每个 methodId 做 encode/decode 对比。 +3. 差异写入 `docs/NetCoverage.md`。 ### 5.5 验收 -1. 不经过 `9091` 中继,直接连官方节点。 +1. 不经过 `9091` 中继,直连官方节点。 2. 登录成功,拿到 Lobby 状态。 3. 进入 Space,收到 `LoadDependencies` 并完成依赖加载。 -4. 抓包 golden 帧回放,编解码 byte-for-byte 一致。 -5. 同一账号下,客户端 RootState 与官方客户端一致(至少用户、货币、车库、任务、聊天)。 +4. `SessionRouter.Unmapped = 0`、`Failed = 0`。 +5. golden 帧 byte-for-byte 一致。 ### 5.6 风险 -- TLS/证书、区域限制、登录验证码。 -- 官方协议版本更新(codec 字段漂移)。 -- token/加密密钥的获取方式。 -- 反作弊/风控(只做本地复现,不绕过官方限制)。 +- TLS/证书、区域限制、验证码。 +- token/加密密钥获取。 +- 官方协议版本更新导致 codec 漂移。 +- 反作弊/风控(只做本地复现,不绕过限制)。 --- @@ -381,10 +386,14 @@ - 补 `EntranceComponentStyle` 的社交登录、找回密码、错误 tooltip。 - 补 `gKt` 输入组件的 `visualState` / `error` / 图标。 - 补 `sWt` 共享按钮的完整样式。 -2. 同时开 **S1/S2 链路取证**: +2. 同时做 **Net 覆盖率审计**(不是重写 codec): + - 用现有 `net` 模块 + `SessionRouter` 跑真实/中继会话。 + - 收集 `UnmappedIds` / `FailedIds`,逐项补齐 `Registry.kt` / `DownlinkActions`。 + - 产出 `NetCoverage.md`。 +3. 同时开 **S1/S2 链路取证**: - 用 CDP 抓官方 config/status/balancer/login。 - 产出 `BalancerProtocol.md` / `AuthProtocol.md`。 -3. 把 `UiTranslationStatus.md` 改成“只有 100% 才写已完成”,其余全部列“进行中”。 +4. 把 `UiTranslationStatus.md` 改成“只有 100% 才写已完成”,其余全部列“进行中”。 --- diff --git a/3DTank/docs/NetCoverage.md b/3DTank/docs/NetCoverage.md new file mode 100644 index 0000000..b7fdc90 --- /dev/null +++ b/3DTank/docs/NetCoverage.md @@ -0,0 +1,109 @@ +# Net Coverage + +> 目的:证明 KT 工程已经实现官方数据包解析,并明确“还缺什么”。 +> 结论:**解析层基本完成**;缺的是官方链路前半段(config/balancer/auth/WS)和真实会话覆盖率审计。 + +## 1. 已实现 + +### 1.1 生成物(`TankiOffline/net/src/jsMain/kotlin/Net/Generated/`) + +| 文件 | 内容 | 数量 | +|---|---|---| +| `Registry.kt` → `DownlinkRegistry.ByMethodId` | methodId → downlink codec | **681** | +| `Registry.kt` → `UplinkRegistry.ByMethodId` | methodId → uplink codec | **361** | +| `Registry.kt` → `ModelRegistry.ByModelId` | modelId → model codec | **363** | +| `Metadata.kt` | 模型名 / method 名 / 字段元数据 | — | + +生成的 codec 模块: + +```text +Downlink: 10283 1510 25377 29554 31908 37504 47243 54199 85183 85196 85667 88693 89803 +Models: 01510 10283 16100 24635 25377 31908 37504 45686 47243 54199 61860 67222 + 71105 85183 85196 85667 85745 87072 88693 89803 99527 +Uplink: 10283 25377 37504 47243 54199 85183 85196 85667 89803 +``` + +覆盖原版 14 个 codec 模块:85183 / 47243 / 85196 / 31908 / 16100 / 10283 / 25377 / 54199 / 37504 / 88693 / 89803 / 85667 / 67222 / 99527。 + +### 1.2 协议层(`Net/Protocol/`) + +| 文件 | 作用 | +|---|---| +| `Entry.kt` | Hash Request / Hash Response / EnterSpace / OpenSpace / BuildObjectDataRequest | +| `SpaceFrame.kt` | 帧体 → 记录;处理 nullmap / alias | +| `StreamDecoder.kt` | 明文 / 探测 / 解密三阶段;XOR key | +| `Containers.kt` | Lt / Pt / Zt / Alias 容器 | +| `TankStateCodec.kt` | 坦克状态 | +| `Wire/ModelCodec.kt` | 模型编解码接口 | + +### 1.3 会话层(`App/Session/`) + +| 文件 | 作用 | +|---|---| +| `SpaceSession.kt` | WebSocket 字节 → `DecodedRecord` | +| `SessionRouter.kt` | `DecodedRecord` → `DownlinkActions` / `DownlinkModelActions` → Redux | +| `UplinkEncoder.kt` | 动作 → 上行帧 | +| `SessionCheck.kt` | 会话自检 | +| `StateCheck.kt` | Redux 状态自检 | +| `AutoTest.kt` | 真实中继一次性测试 | + +### 1.4 状态层(`App/State/`) + +- 89/89 reducer 切片(见 `KtRebuild_Plan.md`)。 +- `RootState.kt` / `RootWiring.kt`。 +- `DownlinkActions.kt` / `DownlinkModelActions.kt`。 +- `ActionCatalog.kt` / `ActionSamples.kt`。 + +## 2. 还没实现 + +### 2.1 链路前半段 + +| 层 | 状态 | 依据 | +|---|---|---| +| config.xml / status.js | 未实现 | `module_13431` | +| balancer | 未实现 | `module_13431` / `module_61860` | +| auth(账号密码 → token/cookie) | 未实现 | `module_82347` Entrance / `module_61860` | +| 官方 WebSocket 建连 | 未实现 | `module_61860:992` `Ie` | +| 直连官方节点 | 未实现 | 当前 `LobbyClient` 走 `9091` 中继 | + +### 2.2 覆盖率审计 + +`SessionRouter` 已有计数器: + +```kotlin +var Unmapped: Int +var Failed: Int +val UnmappedIds: MutableMap +val UnmappedModels: MutableMap +val FailedIds: MutableMap +val FailedReasons: MutableMap +``` + +目标: + +- `Unmapped = 0` +- `Failed = 0` +- `UnmappedModels` 为空 + +需要跑一次真实官方会话,收集并补齐。 + +### 2.3 golden 帧 + +现有 codec 是否 byte-for-byte 对得上,需要: + +1. 用 `wss_server.js` / CDP 抓官方帧。 +2. 对每个 methodId 做 encode/decode 对比。 +3. 差异写入本文件。 + +## 3. 结论 + +- **数据包解析:已实现**(681 downlink / 361 uplink / 363 model / 14 codec 模块 / Entry / SpaceFrame / StreamDecoder / Containers / SessionRouter / 89 reducer)。 +- **官方链路:未实现**(config / balancer / auth / 官方 WS)。 +- **覆盖率:未审计**(`Unmapped` / `Failed` 未归零验证)。 +- **golden 帧:未校验**。 + +下一步不是重写 codec,而是: + +1. 补 config / balancer / auth / 官方 WS。 +2. 跑真实会话,驱动 `Unmapped` / `Failed` 归零。 +3. golden 帧 byte diff。