IMC 集成 API
基本信息
| 属性 | 值 |
|---|---|
| IMC 消息键 | addMineTweakerScript(大小写不敏感比较,MineTweakerMod.java:119) |
| 接收端 | MineTweakerMod.onIMCEvent,@Mod.EventHandler(MineTweakerMod.java:116-130) |
| 载荷类型 | String 消息或 NBT 消息({name, content} 两字段) |
| 脚本容器 | ScriptProviderCustom("intermod")(MineTweakerMod.java:107) |
| 组名 | intermod |
| 本仓发送方 | 无 —— 纯对外接口,供其他模组推送脚本 |
这是本模组对外暴露的唯一正式集成接口:其他模组通过 Forge 的 InterModComms 在自己的初始化阶段推送 ZenScript 片段,MineTweaker 会把它们编入同一批脚本执行。
消息格式
onIMCEvent 遍历 event.getMessages(),只处理键等于 addMineTweakerScript(equalsIgnoreCase)的消息,其余静默忽略(MineTweakerMod.java:118-119)。
字符串载荷
if (imcMessage.isStringMessage()) {
scriptsIMC.add(imcMessage.getSender() + "::imc", imcMessage.getStringValue());
}
(MineTweakerMod.java:120-121)组名为 "<发送方 modid>::imc"。
NBT 载荷
} else if (imcMessage.isNBTMessage()) {
NBTTagCompound message = imcMessage.getNBTValue();
scriptsIMC.add(
imcMessage.getSender() + "::" + message.getString("name"),
message.getString("content"));
}
(MineTweakerMod.java:122-127)组名为 "<发送方 modid>::<name>",name 字段允许推送方自定义分组。
ScriptProviderMemory.collect / ScriptProviderCustom 由此成为第三级脚本来源,参与三级级联(顺序最末,优先级最低)。
Java 侧扩展点
MineTweakerAPI 提供 4 个供其他模组调用的注册方法(均无 ZenScript 注解,仅 Java 可见):
| 方法 | 作用 | 源码行 |
|---|---|---|
registerClass(annotatedClass) |
注册一个带 @ZenClass / @ZenExpansion / @BracketHandler 的类 |
MineTweakerAPI.java:304-326 |
registerBracketHandler(handler) |
直接注册括号处理器实例 | MineTweakerAPI.java:353 |
registerRemover(remover) |
注册配方删除器 | MineTweakerAPI.java:343-345 |
registerGlobalSymbol(name, symbol) |
注册自定义全局符号 | MineTweakerAPI.java:334-336 |
registerClass 是模组间共享脚本类型的主要途径:其他模组只要提供带注解的类并调用它,脚本里就能用。推荐做法是走 IMC 推脚本而非直接调这些方法。
已失效的 5 个 ClassRegistry 常量
MineTweakerMod.java:59-63 声明了 5 个「按模组拆分」的类注册表字符串:
private static final String[] REGISTRIES = { "minetweaker.mods.ic2.ClassRegistry",
"minetweaker.mods.nei.ClassRegistry", "minetweaker.mods.mfr.ClassRegistry",
"minetweaker.mods.gregtech.ClassRegistry", "minetweaker.mods.buildcraft.ClassRegistry" };
private static final String[] REGISTRY_DESCRIPTIONS = { "IC2 mod support", "NEI mod support", "MFR mod support",
"GregTech mod support", "Buildcraft mod support" };
这 5 个类在本仓全部不存在。 逐个检查 src/main/java/minetweaker/mods/<pkg>/ClassRegistry.java 均为 MISSING;git ls-files | grep -i ClassRegistry 全仓只命中 minetweaker/ClassRegistry.java(其 getClasses 还是空壳)。mods/ 下只有 ic2/ 与 nei/ 两个子目录,没有 mfr/、gregtech/、buildcraft/。
registerClassRegistry(String, String) 吞掉 ClassNotFoundException 返回 false(MineTweakerAPI.java:289-296),调用方 MineTweakerMod.java:144-146 不看返回值,于是:
- 5 次循环每次静默失败,无异常、无日志。
Loaded class registry: <description>一条都不会打印。- MFR / GregTech / Buildcraft 集成在本仓没有任何代码,其
REGISTRY_DESCRIPTIONS描述字符串是纯死数据。
实际生效的 IC2 / NEI 支持改由 MineTweakerRegistry 构建期自动扫描(见类注册机制)。
@ModOnly 门控机制
模组专属脚本类的门控靠 @ModOnly(定义在 minetweaker/annotations/ModOnly.java):
@ZenClass("mods.ic2.Macerator")
@ModOnly("IC2")
public class Macerator { ... }
registerClassRegistry 在注册每个类前检查(MineTweakerAPI.java:245-256):
for (Annotation annotation : cls.getAnnotations()) {
if (annotation instanceof ModOnly) {
String[] value = ((ModOnly) annotation).value();
String version = ((ModOnly) annotation).version();
for (String mod : value) {
if (!loadedMods.contains(mod)) continue outer;
if (!loadedMods.get(mod).getVersion().startsWith(version)) continue outer;
}
}
}
语义:
- 注解值是 AND 关系:列出的每个 mod 都必须已加载,任一缺失即跳过该类。
version()默认为空串,startsWith("")恒为 true,因此默认不做版本检查。- 未通过门控的类不会打印任何提示。
全仓 @ModOnly 共 23 处,全部在 mods/ 下,api/ 与 mc1710/ 一处都没有:
| 区域 | 数量 | 明细 |
|---|---|---|
mods/ic2/ |
22 | 14 台机器 + 4 个作物类 + 2 个扩展 + IC2BracketHandler + IC2ExplosionWhitelist |
mods/nei/ |
1 | NEI.java |
即只有模组专属支持层做门控,核心 API 不做 —— 这符合设计:核心 API 必须在任何模组环境下都可用。门控依赖 ILoadedMods.contains,即 @ZenOperator(CONTAINS),见Minecraft 层 API。