|
|
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 |
|
|
|
5038c7f679
|
feat(mcfold): P7 实例层(传入文件夹→拉起实例→读mod注册方块表→连服,含端到端验证)+ 统一测试入口
|
2026-09-25 14:36:21 +08:00 |
|
|
|
b0182de8c7
|
feat(mcfold): P6 世界模型(多区块聚合/负坐标定位/unloaded与air语义分明/mod降级统计)
|
2026-09-25 14:33:26 +08:00 |
|
|
|
85ad7e580e
|
feat(mcfold): P5 mod jar 解析(三种加载器+多加载器诊断+方块名提取,含诚实边界标注)
|
2026-09-25 14:32:39 +08:00 |
|
|
|
40c5739cae
|
feat(mcfold): P4 区块解析(位打包/三种调色板分支/注册表显式降级)+ prismarine 真实数据交叉验证
|
2026-09-25 14:25:34 +08:00 |
|
|
|
a4914b932e
|
feat(mcfold): 最小客户端 + 跨实现互操作测试(Python 客户端握手 Node 服务端成功)
|
2026-09-25 14:12:06 +08:00 |
|
|
|
fc5a1aae91
|
feat(mcfold): 声明式 protodef 解释器(原生类型+阶段作用域+switch/mapper/bitfield),真实握手字节验证通过
|
2026-09-25 14:10:40 +08:00 |
|
|
|
22cdee35e3
|
feat(mcfold): P1 按实例文件夹解析版本(inheritsFrom 归一化 + 加载器判定)+ 回归测试
|
2026-09-25 14:06:55 +08:00 |
|