# 架构分层:谁负责什么 用户口径(2026-09-25):**差异放在 Java 层,Python 相当于路由。** ## 三层 ``` Python(mcfold/) ├── backends/__init__.py 路由:按 client jar 判世代 → 选后端 ← 唯一的 switch ├── backends/base.py 路由:NDJSON 协议、命令集、RLE 压缩 ├── anvil.py 读取:存档 region/NBT → 方块(名字规格) └── render.py 读取 + 编排:WorldRenderer │ │ NDJSON(chunk 数据 / RLE 方块 / 相机 / 渲染指令) ▼ Java(scaffold/java/gen_1_20/ , gen_1_21/) ├── McfoldRenderServer.java 协议格式、调色板组装、位打包、入 cache、渲染 └── McfoldBridge.java 包私有 API 桥(reloadShaders / loadEffect) │ ▼ 官方客户端 jar(各自版本,重映射为可读名) ``` ## 分界原则 | 层 | 负责 | 为什么 | |---|---|---| | **Python** | 路由、存档读取、方块名→id 查询、RLE 压缩、编排 | 这些**不随 MC 版本变** | | **Java** | 协议格式、调色板、位打包、官方序列化、渲染调用 | 这些**历代改过**,必须贴着版本走 | ### 判据:这个知识「随版本变吗」 | 知识 | 随版本变? | 归属 | |---|---|---| | 方块名 → state id | 变(mod/版本) | Java(问运行时注册表) | | 世界尺寸(sectionsCount / minSection) | 变(1.16 是 16/0,1.20 是 24/-4) | Java(`cmd="capacity"`) | | PalettedContainer 位打包 | 变过 | Java(官方 API) | | LongArray 编码 | 变过 | Java(官方 API) | | 区块入 cache 的路径 | 签名变过 | Java(官方 `replaceWithPacketData`) | | **RLE 压缩** | **不变** | Python(只是压重复值) | | **存档 NBT 结构** | 基本不变 | Python(读取) | | **NDJSON 协议** | 不变(我们自己定的) | Python(路由层) | ## 数据流:渲染一个存档 ``` 1. Python: 读 level.dat + region/*.mca 2. Python: NBT → Sections[].block_states(palette + data) 3. Python: palette 名字(+属性) → "minecraft:oak_log[axis=y]" 规格 4. Python: 向后端批量查询规格 → state id [Java: BuiltInRegistries.BLOCK.asLookup()] 5. Python: state id 列表 → RLE [[id,count],...] ← 唯一被压缩的东西 6. Python: setblocks(cx, cz, sections) ← NDJSON 7. Java: LevelChunk + LevelChunkSection.setBlockState(...) 8. Java: 光照(queueSectionData 全亮) 9. Java: ClientboundLevelChunkPacketData(chunk) ← 官方序列化 10. Java: replaceWithPacketData(官方入口入 cache) 11. Java: gameRenderer.render(...)(世代差异在此) 12. Java: 读 FBO → PNG → base64 回传 ``` **第 4/7/8/9/10/11 步都在 Java 侧** —— 版本相关知识全部集中在那里。 ## 加新世代(用户 2026-09-25 定向的收益) 1. `scaffold/java/gen_/` 建目录,拷上一代源码 2. 对着 **javap 输出**改差异点(实测共 11 处,见 VERSION-DIFFS.md) 3. `mcfold/backends/gen_.py` 声明 `markers`(判据类) 4. `mcfold/backends/__init__.py` 的 `GENERATIONS` 加一条 5. 各自对**对应版本**的 named jar 编译 **Python 侧只动第 3、4 步**(各一处),协议与渲染逻辑无需碰。 ## 已删除(防回归) | 已删 | 原因 | |---|---| | `mcfold/render_bridge.py` | 被 `backends/` 取代(旧版无世代概念) | | `render._pack/_long_array/_encode_paletted/_encode_chunk/_varint` | 协议编码下移到 Java | | `anvil.encode_* / save_chunk_to_payload` | 同上 | 回归判据见 `tests/test_anvil.py::test_import_surface` —— 这些名字**不应再出现**在 Python 里。