Files
agentmc/scaffold/java/launcher_fabric/LoaderBoot.java
JianFeeeee 35534b1564 feat: get_block_info —— 方块信息查询(Java 侧回答,Python 只路由)
新增 cmd=blockinfo(两代后端编译通过、实测):
  返回 block 名(含 mod 方块)、stateId、属性、isAir/isSolid、
  光照/硬度、贴图缺失的程序化判据、是否来自 mod。

★ 修掉一个真实缺陷(附录 D 的语义区分落到了实处):
  未加载区块原先返回 void_air(known=true),实测发现两个 API 都不可用:
    - ClientLevel.hasChunk()      反编译实测**恒返回 true**
    - ChunkSource.hasChunk()      走 getChunk(...,false),而 ClientChunkCache
      覆写后在该参数下返回 emptyChunk(占位,非 null)⇒ 也恒 true
  正解:getChunk(..., requireChunk=**false**) 判 null
    (反编译:return requireChunk ? emptyChunk : null;)
  ⇒ 现在未加载明确回 known=false + reason=chunk_not_loaded

实测(1.20.1):
  草地 → minecraft:grass_block props={'snowy':'false'} missing=False
  原木 → minecraft:oak_log       props={'axis':'y'}
  空气 → minecraft:air
  远处 → known=false reason=chunk_not_loaded        ← 与空气区分

实测(1.21.1 + mod):
  mts:mtsofficialpack.fancydirt_block   mod=True tex=mtsofficialpack:block/fancydirt
  createbigcannons:steel_block          mod=True tex=createbigcannons:block/steel_block
  ⇒ mod 方块同样能查到正确贴图名与 fromMod 标记

顺带修 gen_1_21 两处世代差异(ChunkStatus 换包、bridge 编译顺序)。
测试:69 项全绿(新增 test_get_block_info 6 条判据)
2026-09-26 00:24:29 +08:00

68 lines
3.3 KiB
Java
Raw Permalink 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 net.fabricmc.api.EnvType;
import net.fabricmc.loader.impl.launch.knot.Knot;
/**
* 【加载器后端】用 Fabric 加载器,但不写 mod。
*
* 用户定向(2026-09-25):
* 「不写 mod」+「用 mod 加载器」+「功能在现有后端里」。
*
* 实现关键(全部实测):
* 1. Knot.init() 是 **public**,它做完
* 「发现 mod → 建 KnotClassLoader → 应用 mixin → invokeEntrypoints(preLaunch)」
* 后返回,**不**启动官方主循环(那在 GameProvider.launch() 里 —— 我们不调)。
* 2. Knot.loadIntoTarget(name) 把我们的启动类加载进同一个 KnotClassLoader
* ⇒ 我们的代码与 mod 共享 classloader 与 mixin 变换,但控制权仍在我们手里。
*
* 实测输出:
* [loaderboot] ✅ init 返回: net.fabricmc.loader.impl.launch.knot.KnotClassLoader
* [loaderboot] - mcfold_loadprobe 1.0 ← mod 被识别
* [loaderboot] - minecraft 1.20.1
* [loaderboot] ✅ 加载到: McfoldRenderServer / CL=KnotClassLoader
* {"event":"ready"} ← 我们的渲染服务同时就绪
*
* ★ 两个必需条件(缺一则我们的 named 代码无法在加载器下运行):
* a) classpath 里放 **反混淆后的** client jar(client-named.jar),不是官方 obf jar
* b) -Dfabric.gameMappingNamespace=named
* 否则游戏被 remap 成 intermediary,堆栈里是 `enn.<init>`,
* 我们的代码会抛 NoClassDefFoundError: net/minecraft/client/Minecraft(实测)。
*
* 启动示例:
* java -cp "<vanilla基础库(去asm)>:<fabric的8库>:client-named.jar:<我们的classes>" \
* -Dfabric.gameMappingNamespace=named \
* -Dfabric.modsFolder=/path/to/mods \
* LoaderBoot --gameDir ... --assets ... --assetIndex 1.20.1
*
* ★ asm 必须只留一份(用 Fabric 的 9.10.1):1.20.1 自带 9.2 与 9.6 两版,
* 与 Fabric 的并存会让 Knot.<clinit> 抛 "duplicate ASM classes found on classpath"。
*/
public class LoaderBoot {
/** 我们自己的服务端主类(默认包,与 McfoldRenderServer 同名)。 */
private static final String TARGET = "McfoldRenderServer";
public static void main(String[] args) throws Exception {
Knot knot = new Knot(EnvType.CLIENT);
// ① 加载 mod + 应用 mixin;不起官方主循环
ClassLoader gameCl = knot.init(args);
System.err.println("[loaderboot] KnotClassLoader = " + gameCl.getClass().getName());
// 报告已加载的 mod(诊断用;也是「加载器真的在工作」的证据)
try {
for (var m : net.fabricmc.loader.api.FabricLoader.getInstance().getAllMods()) {
System.err.println("[loaderboot] mod " + m.getMetadata().getId()
+ " " + m.getMetadata().getVersion().getFriendlyString());
}
} catch (Throwable t) {
System.err.println("[loaderboot] 读 mod 列表失败: " + t);
}
// ② 把我们的服务端注入同一个 classloader,然后调用它的 main
Class<?> boot = knot.loadIntoTarget(TARGET);
System.err.println("[loaderboot] 注入 " + boot.getName()
+ " 到 " + boot.getClassLoader().getClass().getSimpleName());
boot.getMethod("main", String[].class).invoke(null, (Object) args);
}
}