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; } }