M1+M2:1.21.1 构建跑通 + 协议客户端进 play 阶段
M1(构建): - build.sh 编译 CP 加入 $OUT/fabric/*.jar,解决 net.fabricmc.* 找不到 - gen_1_21 内联 Sodium 通知改为委托共用 RenderCompat,补 reportRenderCompat - 1.21.1 全量七步构建产物齐备(classes-intermediary.jar / names*.json / srg / inheritance.map) M2(协议): - login_start 按协议数据发 UUID(1.21 必填;1.20 可选) - login_acknowledged / serverbound 包 id 改为查表,不再写死 0x00 - send() 实现压缩帧格式(varint(dataLen)+数据,小包不压) - configuration 双向协商:发 settings、回 select_known_packs、拒 resource_pack - protodef 补 bitflags / entityMetadataLoop / count(ctx引用) / compareTo 路径表达式 - NBT 读取器由占位符改为真实现(anonymousNbt 支撑 registry_data) - 坏包容错:长度前缀是帧层权威,解不开整包丢弃并布告,不断流 实测:login→configuration(11 注册表)→play,位置 (5.5,-60.0,-0.5),map_chunk×9 判据:protodef 6→13 项(含线上真实 entity_metadata 字节回归);全量 77 项通过
This commit is contained in:
38
plan.md
38
plan.md
@ -560,8 +560,8 @@ shot.rough → ASCII + 线索(给 agent 看它为什么选了这个角度)
|
||||
| # | 内容 | 依赖 | 状态 |
|
||||
|---|---|---|---|
|
||||
| **M0** | 起**空白测试服**(§1c),版本隔离三件套 | — | ✅ |
|
||||
| **M1** | 修 build.sh 编译 CP(加 Fabric 库)⇒ 1.21.1 构建跑通 | — | 🔄 |
|
||||
| **M2** | **协议客户端**:连测试服 → configuration → registry_data → 进 play | M0 | ⬜ |
|
||||
| **M1** | 修 build.sh 编译 CP(加 Fabric 库)⇒ 1.21.1 构建跑通 | — | ✅ |
|
||||
| **M2** | **协议客户端**:连测试服 → configuration → registry_data → 进 play | M0 | ✅ |
|
||||
| | (这是最大缺口:现有只到 `login_start` 冒烟级) | | |
|
||||
| **M3** | **状态层**:World / entities / inventory 从**服务端真状态**来 | M2 | ⬜ |
|
||||
| **M4** | **事件层**:粗粒度 + 细分层(照 mineflayer,省 token) | M2 | ⬜ |
|
||||
@ -571,6 +571,40 @@ shot.rough → ASCII + 线索(给 agent 看它为什么选了这个角度)
|
||||
| **M8** | **细渲染**(单次调用):出图,带光影 | M2 | ⬜ |
|
||||
| **M9** | 第一个用例:`capture_photo()`(粗搜机位 → 细出图) | M6, M8 | ⬜ |
|
||||
|
||||
### M2 实测结论(2026-09-26)
|
||||
|
||||
**已达成的可复现事实**(连 M0 测试服 127.0.0.1:25566):
|
||||
|
||||
```
|
||||
login phase=login → success(服务端回 UUID 与离线算法一致)
|
||||
configuration phase=play 注册表=11(biome/damage_type/enchantment/…)
|
||||
play 28 种包 map_chunk×9、position、declare_commands、entity_metadata
|
||||
position (5.5, -60.0, -0.5)
|
||||
```
|
||||
|
||||
**踩过的 7 个真实坑**(都是「世代差异」或协议数据理解错误):
|
||||
|
||||
| 症状 | 根因 |
|
||||
|---|---|
|
||||
| `Failed to decode packet 'hello'` | 1.21.1 `login_start.playerUUID` 是**必填 UUID**;1.20 是 `['option','UUID']` |
|
||||
| configuration 收不到包 | `login_acknowledged` 包 id 写死 `0x00`,实际 **`0x03`** |
|
||||
| `Badly compressed packet` | 写侧没实现压缩帧:`varint(dataLen)+数据`,小包 `dataLen=0` |
|
||||
| 服务端发完 `select_known_packs` 不动 | configuration 是**双向协商**,必须回 `select_known_packs`/发 `settings` |
|
||||
| `registry_data` 解不开 | 缺 `anonymousNbt`;旧 NBT 只是占位符 |
|
||||
| `declare_recipes` 流错位 | 数组计数有 `countType`(103处) 与 **`count`(引用 ctx,6处)** 两种 |
|
||||
| `player_info`/`declare_commands` 解不开 | `compareTo` 可用**路径**:`flags/x`、`../flags/x`(12 处) |
|
||||
| `entity_metadata` 越界 | 终止符是**光秃 0xFF 一个字节**,不含 type/value |
|
||||
|
||||
**关键架构发现(修正项目前提)**:vanilla 1.21.1 只在线同步 **11 个动态注册表**,
|
||||
**不含 `minecraft:block` / `minecraft:item`**。静态注册表不走线同步 ——
|
||||
客户端用自己 jar 里的。⇒ Java 侧读 client jar 的路线对 vanilla 正确;
|
||||
但 **mod 新增方块 vanilla 不会告诉客户端**,那条要靠加载器自身的同步机制。
|
||||
|
||||
**已知上游数据缺口(非本仓 bug,已容错)**:`declare_recipes`(108KB)
|
||||
在**官方 minecraft-data 3.117 + minecraft-protocol** 上同样解不开
|
||||
(PartialReadError: found 108271 / expected 114153)。
|
||||
处理:长度前缀是帧层权威 ⇒ **坏包整包丢弃不断流**(`decode_failures` 布告)。
|
||||
|
||||
**建议顺序:M0 → M1 → M2**。
|
||||
- M0/M1 是解阻断(M1 是我已经查到根因的那个 classpath bug)
|
||||
- **M2 是真正的门槛**:从「能渲染」到「能玩」,缺的不是渲染,是**完整协议层**。
|
||||
|
||||
Reference in New Issue
Block a user