Files
agentmc/scaffold/README.md
JianFeeeee 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

3.0 KiB
Raw Blame History

mcfold scaffold —— 用官方客户端渲染,但不跑客户端

目标(用户 2026-09-25 定向):不起完整客户端,把 MC 的渲染能力抽出来, 用我们自己的世界数据驱动它出图。

实测结论(2026-09-25 全绿)

客户端 jar 是 ProGuard 全量混淆的(LevelRenderer 叫 fjv), 所以「抽渲染器」的第一步必须是反混淆。三层关卡全部验证通过:

关卡 证据 结果
反混淆 client-named.jar 25MB;javap 读出 net.minecraft.client.renderer.LevelRenderer ✅
编译期引用 javac 编译引用 Minecraft/LevelRenderer 的代码 ✅
GL 离屏 Xvfb + llvmpipe → OpenGL 4.5 core ✅
渲染栈初始化 new Minecraft(cfg) 完成 GL/资源/渲染器初始化,不进主循环 ✅
真渲染出图 渲 3 帧 + 读像素 → PNG,画面是 Mojang 加载屏(logo 贴图 + 进度条) ✅

为什么渲染器不能独立 new

反编译(Vineflower)给出的实测签名:

LevelRenderer(Minecraft, EntityRenderDispatcher, BlockEntityRenderDispatcher, RenderBuffers)
renderLevel(PoseStack, float, long, boolean, Camera, GameRenderer, LightTexture, Matrix4f)

全部挂在 Minecraft 单例上 ⇒ 不能 new LevelRenderer() 独立用。 正确形态是「初始化 MC 渲染栈,但不跑主循环」。

权威序列(反编译 net.minecraft.client.main.Main 得到)

SharedConstants.tryDetectVersion();          // ← 漏了会 "Game version not set"
SharedConstants.enableDataFixerOptimizations();
Bootstrap.bootStrap();
RenderSystem.initRenderThread();
RenderSystem.beginInitialization();
Minecraft mc = new Minecraft(gameConfig);    // ← 构造即完成渲染栈初始化
RenderSystem.finishInitialization();
// 此处官方会起 Game thread 跑主循环 —— 我们不做

渲染一帧(反编译 Minecraft.render() 得到):

RenderSystem.clear(16640, ON_OSX);
mainRenderTarget.bindWrite(true);
gameRenderer.render(partialTick, nanos, renderLevel);
mainRenderTarget.unbindWrite();
mainRenderTarget.blitToScreen(w, h);
window.updateDisplay();

踩过的三个坑(都有实测证据)

  1. 漏 tryDetectVersion() → DataFixers.<clinit> 抛 Game version not set
  2. FolderData 参数顺序 (gameDirectory, resourcePackDirectory, assetDirectory, assetIndex) —— 顺序写错会让 icons/icon_16x16.png 404
  3. assetIndex 名要用落盘名 version.json 里 assetIndex.id = "5",但磁盘是 assets/indexes/1.20.1.json (MCLC 按 version.number 落盘)—— 传 "5" 则索引加载失败、资源全找不到

下一步:渲染真实世界

ClientLevel 构造只需 listener.registryAccess()(其余字段不用 listener), 且 ClientChunkCache.replaceWithPacketData(...) 接收的正是 map_chunk 包的原始字节 —— 与 mcfold chunk.py 解码器同一格式。这就是设计文档说的桥梁落点。

构建

./build.sh /path/to/store/vanilla-1.20.1 1.20.1