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 同格式)⇒ 这就是数据喂渲染器的落点。
This commit is contained in:
91
scaffold/Scaffold.java
Normal file
91
scaffold/Scaffold.java
Normal file
@ -0,0 +1,91 @@
|
||||
import com.mojang.blaze3d.platform.DisplayData;
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
import com.mojang.authlib.properties.PropertyMap;
|
||||
import net.minecraft.SharedConstants;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.User;
|
||||
import net.minecraft.client.main.GameConfig;
|
||||
import net.minecraft.server.Bootstrap;
|
||||
|
||||
import java.io.File;
|
||||
import java.net.Proxy;
|
||||
import java.util.OptionalInt;
|
||||
|
||||
/**
|
||||
* mcfold scaffold —— 只起 MC 的**渲染栈**,不进游戏主循环。
|
||||
*
|
||||
* 依据(反编译 net.minecraft.client.main.Main 的实测序列):
|
||||
* Bootstrap.bootStrap()
|
||||
* RenderSystem.initRenderThread(); beginInitialization();
|
||||
* new Minecraft(gameConfig) ← 构造即完成 GL/资源/渲染器初始化
|
||||
* RenderSystem.finishInitialization()
|
||||
* 之后 Main 才起 Game thread 跑主循环 —— 我们**不**走那步。
|
||||
*/
|
||||
public class Scaffold {
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
String gameDir = arg(args, "--gameDir", "/home/newqqagent/mcview/instances/default");
|
||||
String assets = arg(args, "--assets", "/home/newqqagent/mcview/store/vanilla-1.20.1/assets");
|
||||
// ★ 索引名必须是 assets/indexes/<name>.json 中真实存在的那个。
|
||||
// version.json 的 assetIndex.id 是 "5",但 MCLC 落盘用 version.number(1.20.1)
|
||||
// —— 传 "5" 会导致索引加载失败,所有资源/icons 全部找不到(实测踩过)。
|
||||
String assetIdx = arg(args, "--assetIndex", "1.20.1");
|
||||
int width = Integer.parseInt(arg(args, "--width", "1280"));
|
||||
int height = Integer.parseInt(arg(args, "--height", "720"));
|
||||
|
||||
System.out.println("[scaffold] bootstrap...");
|
||||
// ★ 官方 Main 的实测序列:tryDetectVersion 必须在 bootStrap 之前,
|
||||
// 否则 DataFixers.<clinit> 抛 "Game version not set"
|
||||
SharedConstants.tryDetectVersion();
|
||||
SharedConstants.enableDataFixerOptimizations();
|
||||
Bootstrap.bootStrap();
|
||||
System.out.println("[scaffold] bootstrap ok, mcVersion=" + SharedConstants.getCurrentVersion().getName());
|
||||
|
||||
File runDir = new File(gameDir);
|
||||
File assetsDir = new File(assets);
|
||||
|
||||
User user = new User("mcfold_cam", "0".repeat(32), "mcfold_cam",
|
||||
java.util.Optional.empty(), java.util.Optional.empty(), User.Type.LEGACY);
|
||||
PropertyMap props = new PropertyMap();
|
||||
|
||||
GameConfig cfg = new GameConfig(
|
||||
new GameConfig.UserData(user, props, props, Proxy.NO_PROXY),
|
||||
new DisplayData(width, height, OptionalInt.empty(), OptionalInt.empty(), false),
|
||||
new GameConfig.FolderData(
|
||||
// ★ 顺序是 (gameDirectory, resourcePackDirectory, assetDirectory, assetIndex)
|
||||
// 反着写会把 assets 当游戏目录,导致资源全找不到(实测踩过:icons/icon_16x16.png 404)
|
||||
runDir, new File(runDir, "resourcepacks"), assetsDir, assetIdx),
|
||||
new GameConfig.GameData(
|
||||
false, // demo
|
||||
"mcfold", // version
|
||||
"release", // versionType
|
||||
false, // disableMultiplayer
|
||||
false), // disableChat
|
||||
new GameConfig.QuickPlayData(null, null, null, null)
|
||||
);
|
||||
|
||||
System.out.println("[scaffold] RenderSystem init...");
|
||||
RenderSystem.initRenderThread();
|
||||
RenderSystem.beginInitialization();
|
||||
|
||||
System.out.println("[scaffold] new Minecraft(cfg) ...");
|
||||
Minecraft mc = new Minecraft(cfg);
|
||||
|
||||
RenderSystem.finishInitialization();
|
||||
System.out.println("[scaffold] OK Minecraft constructed");
|
||||
|
||||
// 检查渲染栈关键对象是否就绪(不启主循环)
|
||||
System.out.println("[scaffold] window=" + mc.getWindow().getWidth() + "x" + mc.getWindow().getHeight());
|
||||
System.out.println("[scaffold] levelRenderer=" + (mc.levelRenderer != null ? "present" : "null"));
|
||||
System.out.println("[scaffold] gameRenderer=" + (mc.gameRenderer != null ? "present" : "null"));
|
||||
System.out.println("[scaffold] level=" + (mc.level != null ? "present" : "null (не connected)"));
|
||||
|
||||
System.out.println("[scaffold] DONE (no main loop)");
|
||||
}
|
||||
|
||||
private static String arg(String[] a, String key, String def) {
|
||||
for (int i = 0; i < a.length - 1; i++)
|
||||
if (a[i].equals(key)) return a[i + 1];
|
||||
return def;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user