# 世代差异清单(实测,非推断) 来源:官方 `client_mappings.txt` 逐版本对比(1.20.1 / 1.20.2 / 1.21.1), 以及两侧源码对各自 client jar 的实际编译结果。 ## 判据 **`net.minecraft.client.DeltaTracker` 类是否存在** ⇒ 1.21+。 这是 1.21 引入的时间抽象,也正是 `GameRenderer.render` 签名变化的根源。 比硬编码版本号稳(官方改版本号不影响判据)。 实现:`mcfold/backends/__init__.py:detect_generation()` ## 差异全表(8 处,覆盖 21 个检查点中的 13 个「完全一致」之外的部分) | # | API | 1.20.x | 1.21+ | 处理 | |---|---|---|---|---| | 1 | `Minecraft.setLevel` | `(ClientLevel)` | `(ClientLevel, ReceivingLevelScreen$Reason)` | gen_1_21 传 `Reason.OTHER` | | 2 | `GameRenderer.render` | `(float,long,boolean)` | `(DeltaTracker, boolean)` | gen_1_21 用 `mc.getTimer()` | | 3 | 区块计数 | `countRenderedChunks()` | `countRenderedSections()` | 各世代用各自名字 | | 4 | 同理 | `hasRenderedAllChunks()` | `hasRenderedAllSections()` | 同上 | | 5 | `ServerPacksSource.createPackRepository` | `(Path)` | `(Path, DirectoryValidator)` | gen_1_21 构造 validator | | 6 | `ResourceLocation` 构造 | `new ResourceLocation(s)` | `ResourceLocation.parse(s)` | 静态工厂 | | 7 | `SharedConstants.enableDataFixerOptimizations` | 有 | **已移除** | gen_1_21 不调 | | 8 | `User` 构造 | `(String,String sessionId,...)` | `(String,UUID,...)` | 传 UUID | | 9 | `ChunkStatus` | `world.level.chunk.ChunkStatus` | `world.level.chunk.status.ChunkStatus` | 包路径变了 | | 10 | `ClientPacketListener` 构造 | `(Minecraft,Screen,Connection,ServerData,GameProfile,Telemetry)` | `(Minecraft,Connection,CommonListenerCookie)` | ★ 参数个数与语义都变 | | 11 | `GameRenderer.loadEffect` | package-private(同包可调) | **private**(同包也调不到) | gen_1_21 用反射 | ★ 关键结论:**差异集中在 11 处,而不是「每个版本一套」**。 21 个检查点里 13 个(如 `tick`/`allChanged`/`replaceWithPacketData`/ `updateViewCenter`/`getChunkSource`/`PackRepository.*`)跨世代**完全一致**。 ## 为什么必须分后端(而不是一个文件里 switch) Java 编译期绑定签名。实测: ``` 世代 B 的调用对 1.20.1 jar 编译: error: cannot find symbol class DeltaTracker ``` `DeltaTracker` 在 1.20.x 的 jar 里不存在 ⇒ 两代的调用**无法共存于一份源码**。 所以每个世代独立编译,Python 层做分派。 ## 加新世代的做法(用户 2026-09-25 定向) 1. `scaffold/java/gen_/` 建目录,拷上一代源码 2. 按上表改差异点(对着 **javap 输出**改,不要凭印象写 API 名) 3. `mcfold/backends/gen_.py` 声明 `markers`(判据类) 4. `mcfold/backends/__init__.py` 的 `GENERATIONS` 加一条 5. 各自对**对应版本**的 named jar 编译 ⚠️ 教训(本轮踩过):`Reason.LEVEL_LOAD`、`DirectoryValidator.NONE` 都是凭印象写出来的、实际不存在的 API;`loadEffect` 的可见性也没验证。 **改之前先 `javap`。**