|
|
253146cffe
|
gen_1_21 实测启动成功 + provision 工具
决定性验证:gen_1_21 后端在 1.21.1 上收到 {"event":"ready"}
⇒ 世代分派架构成立:同一套 Python 层,两个独立编译的 Java 后端
运行时发现第 12 处世代差异(编译期看不出):
1.20.x registryAccess 是可变 LayeredRegistryAccess → 事后反射替换
1.21.x registryAccess 是 final RegistryAccess$Frozen → 反射抛
"Can not set final field"
处理:gen_1_21 改为先载注册表 → 经 CommonListenerCookie.receivedRegistries
传入 → 再构造 listener。比 1.20 的反射做法更干净。
新增 mcfold/provision.py(从官方 manifest 装任意版本,版本无关):
- 跳过音频资源:1.21.1 实测 3911 条里跳过 3744 条
- natives 两种形态都认(1.21 起是独立库条目,非 classifiers)
- 实测 1.21.1:274 文件 / 200MB / 32s / 0 失败
|
2026-09-25 18:35:28 +08:00 |
|
|
|
8c7d5b9d38
|
世代分派体系:Python 层 switch + 各世代独立编译的 Java 后端
用户定向:在 python 层写 switch,调用不同 java 后端(而非一个文件里 switch)。
新增:
mcfold/backends/{__init__,base,gen_1_20,gen_1_21}.py 后端体系与分派
scaffold/java/gen_1_20/ 对 1.20.x client jar 编译
scaffold/java/gen_1_21/ 对 1.21.1 client jar 编译(✅ 实测编译通过)
scaffold/java/VERSION-DIFFS.md 实测差异全表
判据:DeltaTracker 类是否存在(1.21 引入,正是 render 签名变化的根源)
⇒ 比硬编码版本号稳
实测差异共 11 处(21 个检查点里 13 个跨世代完全一致):
setLevel / GameRenderer.render / countRendered* / createPackRepository /
ResourceLocation 构造 / enableDataFixerOptimizations(移除) / User 构造 /
ChunkStatus 包路径 / ClientPacketListener 构造(参数个数语义都变) /
loadEffect(变 private)
为什么必须分后端:DeltaTracker 在 1.20.x jar 中不存在,
两代调用无法共存于一份源码(实测编译报 cannot find symbol)。
1.21.1 反混淆已验证(29MB named jar,DeltaTracker 3 处)
|
2026-09-25 18:21:08 +08:00 |
|
|
|
34ed70ab53
|
修复视距不生效 + 接入统一测试
视距(用户报「无法调整视距?」)——根因是三处不同步:
1. options.renderDistance 本地设置(原先只设了这个)
2. options.setServerRenderDistance 服务端下发上限(getEffectiveRenderDistance = min(两者))
3. ClientChunkCache.updateViewRadius storage 半径
第三处最关键:官方只在收到服务端半径包时才调它(ClientPacketListener:2316),
我们不连服 ⇒ Storage.inRange 用旧半径判定,超出区块被**静默丢弃**。
另一个前置:加载半径必须跟随视距。视距 12 只喂 3 圈数据,
画面看起来就像没生效(最容易误判的坑)。
实测(同相机同存档):
视距 4 → 注入 81 渲染 55 色彩 15226
视距 12 → 注入 595 渲染 447 色彩 18477
画面差异显著:RD=12 能看到延伸到地平线的森林与完整海岸线。
(sample-render-distance-{4,12}.png)
测试:新增 tests/test_anvil.py(13 项,存档/NBT/编码)
tests/test_render_bridge.py(3 项,桥协议+合成渲染+真实存档渲染)
run_tests.sh 改为默认跑单元测试、--with-render 跑联测
合计 61 项全绿(原 48 + 13)
|
2026-09-25 17:47:58 +08:00 |
|
|
|
391d452c85
|
P9:Python 包装层 —— 真实存档 → 官方渲染器 → 出图
新增两模块:
mcfold/anvil.py 存档读取(region/NBT)+ 区块编解码工具
mcfold/render_bridge.py 桥:常驻 Java 渲染器进程,NDJSON 协议
mcfold/render.py 对外入口:WorldRenderer(存档→画面)
scaffold/McfoldRenderServer.java Java 侧服务端(常驻,NDJSON)
实测(真实存档 mc-test,DataVersion 3465=1.20.1):
injected=81 unknownBlocks=0 uniqueSpecs=111
loadedChunks=81 chunksRendered=60 distinctColors=11585
画面:草地/沙滩/树/水/天空/太阳/HUD(sample-real-save-render.png)
★ 分工落在实处(附录 D 的结论变成代码):
存档 palette 是**方块名**(minecraft:oak_log[axis=y]),网络载荷要 **state id**,
名字→id 的权威映射只有客户端注册表有 ⇒ 新增 resolve 命令,
Java 侧用 BlockStateParser.parseForBlock 解析(实测 111 种全中,0 unknown)
踩坑(本轮新发现):
1. level.dat 有两种布局(8字节头+zlib / 直接 gzip)—— 实测本机是后者
2. section 索引 ≠ 绝对 Y:存档用 -4..19,载荷用 0..23(少这步 → readerIndex 越界)
3. 注入前必须 set_viewport,否则 ClientChunkCache.inRange 丢弃区块
4. setPos 不会更新实体区块归属,要 setPosRaw + updateViewCenter
5. 生物群系只影响着色,用统一 plains 不影响「能渲染出世界」
6. camera 回包要用 JsonArray,字符串会被 Python tuple() 按字符拆开
性能:启动 66s(GL+资源重载),之后每帧渲染 ~1s(含 100 帧 tick)
|
2026-09-25 17:33:41 +08:00 |
|
|
|
541fe232a8
|
P8 完成:世界数据 → 官方渲染器 → 真实出图
不起完整客户端、不连服、不登录,只初始化 MC 渲染栈并喂入我们自己造的世界数据。
已验证(全绿):
countRenderedChunks=29 distinct colors=1450
画面:草地/原木/树叶/天空/HUD/英文文字(sample-world-render.png)
打通的关卡:
- 反混淆(client-named.jar)+ GL 离屏 + new Minecraft(cfg) 不进主循环
- 资源同步重载:22 listener(ModelManager/FontManager/Dispatcher)
★ 不能 join reloadResourcePacks(等主循环→死锁),直接调各 listener reload()
- 注册表从客户端自带 data/ 加载(dimension_type=4)
- 区块注入:LevelChunk + setBlockState → ClientChunkCache.Storage.chunks
+ LightEngine.queueSectionData(全亮)→ allChanged()
- 每帧 mc.tick() 推进网格重建队列(不跑则 countRenderedChunks=0)
踩坑记录(10 条,README 详列):
LoadingOverlay/ReceivingLevelScreen 遮挡、FolderData 参数序、
assetIndex 用落盘名、reloadShaders 包私有、读像素必须绑 FBO、
判据用 distinct colors 而非 non-black
更正附录 D:state_id=1003 → note_block 不是误映射(note_block 有 800 状态)
—— 真客户端给完整状态,是 1.20.1 上 mod 方块语义的唯一权威来源
|
2026-09-25 17:01:49 +08:00 |
|
|
|
e223be2571
|
P8: scaffold —— 反混淆 + MC 渲染栈离屏初始化 + 真渲染出图
实测链路(全绿):
1. 官方 ProGuard 映射 → SRG → SpecialSource 重映射 → client-named.jar
2. 反编译确认 MC 渲染器挂在 Minecraft 单例上,不能独立 new
3. 权威序列:tryDetectVersion → Bootstrap → RenderSystem → new Minecraft(cfg)
4. 渲 3 帧 + glReadPixels → PNG,画面是 Mojang 加载屏(真渲染,非清屏)
三个坑(实测证据):
- 漏 tryDetectVersion → Game version not set
- FolderData 参数顺序错 → icons/ 404
- assetIndex 用 id(5) 而非落盘名(1.20.1) → 资源全找不到
下一步:ClientLevel 构造只需 listener.registryAccess(),
ClientChunkCache.replaceWithPacketData 接收 map_chunk 原始字节
(与 chunk.py 同格式)⇒ 这就是数据喂渲染器的落点。
|
2026-09-25 15:39:41 +08:00 |
|