Files
agentmc/scaffold/RegistryProbe.java
JianFeeeee 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

83 lines
3.6 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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.core.registries.BuiltInRegistries;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.Bootstrap;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.state.BlockState;
import java.io.File;
import java.net.Proxy;
import java.util.Optional;
import java.util.OptionalInt;
/**
* 证明:真客户端的注册表能给出 state id ↔ 方块名的权威映射。
*
* 这正是不起完整客户端、只用客户端注册表的价值所在:
* 1.20.1 不从网络下发方块表(附录D),mod 方块的 state id 只有客户端注册表知道。
*/
public class RegistryProbe {
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");
String assetIdx = arg(args, "--assetIndex", "1.20.1");
SharedConstants.tryDetectVersion();
SharedConstants.enableDataFixerOptimizations();
Bootstrap.bootStrap();
File runDir = new File(gameDir);
User user = new User("mcfold_cam", "0".repeat(32), "mcfold_cam",
Optional.empty(), Optional.empty(), User.Type.LEGACY);
PropertyMap props = new PropertyMap();
GameConfig cfg = new GameConfig(
new GameConfig.UserData(user, props, props, Proxy.NO_PROXY),
new DisplayData(854, 480, OptionalInt.empty(), OptionalInt.empty(), false),
new GameConfig.FolderData(runDir, new File(runDir, "resourcepacks"), new File(assets), assetIdx),
new GameConfig.GameData(false, "mcfold", "release", false, false),
new GameConfig.QuickPlayData(null, null, null, null));
RenderSystem.initRenderThread();
RenderSystem.beginInitialization();
Minecraft mc = new Minecraft(cfg);
RenderSystem.finishInitialization();
System.out.println("[reg] Minecraft constructed");
// ★ 核心:客户端的方块注册表
int blockCount = BuiltInRegistries.BLOCK.size();
int stateCount = Block.BLOCK_STATE_REGISTRY.size();
System.out.println("[reg] BLOCK registry size = " + blockCount);
System.out.println("[reg] BLOCK_STATE registry size = " + stateCount);
// ★ 关键验证:mineflayer 会静默误映射的那些越界 id,客户端怎么答
int[] probes = {0, 1, 1002, 1003, 1502, 30000, stateCount - 1};
for (int id : probes) {
BlockState st = Block.stateById(id);
ResourceLocation key = BuiltInRegistries.BLOCK.getKey(st.getBlock());
System.out.println("[reg] state_id=" + id + " -> " + key + " [" + st + "]");
}
// ★ 列出几个方块名(证明可读)
System.out.println("[reg] sample blocks:");
for (int i = 0; i < 5; i++) {
ResourceLocation k = BuiltInRegistries.BLOCK.getKey(BuiltInRegistries.BLOCK.byId(i));
System.out.println(" id=" + i + " -> " + k);
}
System.out.println("[reg] DONE");
System.exit(0);
}
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;
}
}