ModCandidateV2 数据模型

基本信息

属性 值
类 com.mitchej123.jarjar.fml.common.discovery.ModCandidateV2
父类 cpw.mods.fml.common.discovery.ModCandidate
实现接口 com.mitchej123.jarjar.discovery.SortableCandidate
API 注解 descriptor Lcpw/mods/fml/common/API;

ModCandidateV2 是 FML 原版 ModCandidate 的扩展载体,保存 JarJar 引入的全部元数据:access transformer 列表、cascaded tweaker、coreMod、嵌套 jar 候选、API 包声明、earlyPackages、nestLevel、SHA-256 hash、sourceFilename 等。

字段

字段 类型 默认 说明
accessTransformers Map<String, String> null FMLAT 解析后的 jar→AT 内容映射
cascadedTweaker String null manifest TweakClass
fmlCorePlugin String null manifest FMLCorePlugin
containsMod boolean false manifest FMLCorePluginContainsFMLMod 或 ForceLoadAsMod=true
containsAPI boolean false 在 class scanning 阶段发现 @API
earlyPackages Set<String> null class scanning 阶段收集的包前缀
declaredApiPackages Map<String, DefaultArtifactVersion> null package-info.class 中 @API(apiVersion=...)
nestedModcandidates Collection<ModCandidateV2> null Jar-in-Jar 嵌套候选列表
parentModcandidates Collection<ModCandidateV2> null 父 jar 引用(用于 nestLevel 累计)
nestLevel int 0 嵌套深度
wrappedMods List<ModContainerWrapper> null 类扫描阶段构建的 ModContainer 列表
asmDataCollection List<ASMModParserV2> new ArrayList<>() 该 jar 内每个 .class 解析结果
nestedJars List<JarUtil.NestedJar> null 抽取出来的嵌套 jar(scan 后释放)
hash String null 整个 jar 的 SHA-256(嵌套 jar 才填)
sourceFilename String null 在外层 jar 中的 entry 名(嵌套 jar 才填)
sortOrder int 0 manifest TweakOrder 或覆写
metadataCollection MetadataCollection null mcmod.info 解析结果
version DefaultArtifactVersion "0.0.0" 从 mcmod.info 或文件名提取

getId 重写

@Override
public String getId() {
    if (fmlCorePlugin != null) return fmlCorePlugin;
    if (sourceFilename != null) return sourceFilename;
    return modContainer.getName();
}

fmlCorePlugin 优先(coremod 用类名去重);嵌套 jar 用其在父 jar 里的 entry 名;普通 jar 用文件 basename。

getFilename

public String getFilename() {
    if (sourceFilename != null) return sourceFilename;
    return modContainer.getName();
}

nestLevel 累计

private void updateNestLevel(ModCandidateV2 parent) {
    if (parent != null && parent.nestLevel + 1 > this.nestLevel) {
        this.nestLevel = parent.nestLevel + 1;
    }
}

ParallellModDiscoverer.discoverMods 在递归发现 parent → child 时调用 addParent:

public boolean addParent(ModCandidateV2 parent) {
    if (this.parentModcandidates == null) this.parentModcandidates = new ArrayList<>();
    if (this.parentModcandidates.contains(parent)) return false;
    this.parentModcandidates.add(parent);
    updateNestLevel(parent);
    return true;
}

释放流程

方法 释放内容
releaseEarlyScanData() earlyPackages、declaredApiPackages
releaseAccessTransformers() accessTransformers
releaseNestedJars() nestedJars
releaseParsedData() asmDataCollection → 空列表;metadataCollection → null

LoaderV2.identifyMods 在所有 candidates 加入后调 releaseParsedData 释放 ASM 字节与 metadata 引用,降低内存峰值。

sendToTable

public void sendToTable(ASMDataTable table) {
    setTable(table);
    for (ASMModParserV2 asmData : asmDataCollection) {
        addClassEntry(asmData.getClassEntry());
        asmData.sendToTable(table, this);
    }
}

addClassEntry 来自父类 ModCandidate,把 jar 内的 class 完整路径加到 classEntries。asmData.sendToTable 触发 ASMModParserV2.sendToTable 把 @Mod 与 interface ASMData 注入 table。

构造

public ModCandidateV2(File classPathRoot, File modContainer, ContainerType sourceType, boolean isMinecraft, boolean classpath) {
    super(classPathRoot, modContainer, sourceType, isMinecraft, classpath);
}

isMinecraft 标记 Minecraft jar(classpath 阶段唯一拥有此标志);classpath 标记为 classpath mod。

相关条目