JarJar

[!INFO] Git Commit: 1bf1b8f | Updated: 2026-06-17

JarJar 是 GTNH 维护的 RFB (RetroFuturaBootstrap) Plugin —— 对 Minecraft 1.7.10 ForgeModLoader (FML) 进行大量重写的引导增强库,无任何方块/物品/实体/维度注册。其核心价值在于把 Fabric-loader 与较新版 Forge 中的 mod 发现与排序机制移植回 1.7.10:

  • Jar-in-Jar (嵌套 jar):从 mcmod.info 的 Jar-In-Jar 清单里抽取嵌套 jar 到 <mc>/nestedmods/ 目录并按 SHA-256 去重,按独立 mod 加载
  • Parallel Mod Discoverer:用共享 ForkJoinPool 并发解析 mods 目录下的 jar(基于 Fabric ModDiscoverer 移植)
  • 重复版本选择:相同 mod id 出现多次时自动保留版本号最高者,支持通过 jarjar_coremod_exemptions.cfg 豁免特定 coremod
  • API 优先排序 (API ownership):基于 @API 注解 + package-info.class 中声明的 apiVersion,在拓扑排序中保证 API 提供者 jar 先于 repackaging 它们的 jar 加入 classpath
  • FML 可见性拓宽:EarlyAccessTransformer 在 ASM 层面把 CoreModManager/MetadataCollection/ModDiscoverer 等关键类的字段、方法、内部类改为 public,供后续 transformer 使用
  • V2 类替换:V2ConstructionReplacerTransformer 把 Loader/ModContainerFactory/ModDiscoverer/ASMModParser 构造指令中的 new/invokespecial 重定向到 JarJar 的 V2 版本
  • 接口捕获:ASMDataTableV2 在 cpw.mods.fml.common.API 之外,也记录 @Mod/@SidedProxy 等类实现的接口(仿造新版 Forge ASMDataTable)
  • SortingIndex 覆写:jarjar.properties 中 SortingIndex.<coremod class>=<n> 可手动设定某 coremod 的加载顺序;预置 Hodgepodge < 2.7.147 自动置为 1
  • CodeChickenCore 兼容:CodeChickenCoreTransformer 在 codechicken.core.ClassDiscoverer.findClasspathMods 注入 Hooks.shouldIgnore(File),阻止它重复加载已被 JarJar 标记为默认库/已禁用的 jar
  • 从 CoreTweaks / Fabric-loader / FancyModLoader 借鉴的速度优化:包括 ASM 常量池预扫、ClassConstantPoolParser、文件去重的 nashornPath 规范化等

需要 RetroFuturaBootstrap 作为宿主启动器,所有 RFB transformer 注册在 com.mitchej123.jarjar.rfb.plugin.JarJarRfbPlugin.makeTransformers()。

所有 wiki 条目均归在 setting/ 子目录下,因为 JarJar 本身不注册任何游戏内容,只改写启动器/类加载器行为。

游戏设定

  • RFB 插件入口 - JarJarRfbPlugin 注册 6 个 transformer,提供 JVM 开关 jarjar.disable
  • 系统属性开关 - jarjar.disable / jarjar.disabled / jarjar.rfbPluginLoaded / jarjar.debug.discoveryTimeout / fml.coreMods.load
  • JarJar 配置文件 - config/jarjar.properties 的 maxThreads / enableSortingIndexOverrides / SortingIndex.<coremod>=<n> 三段
  • Jar-in-Jar 嵌套 jar - 解析 mcmod.info 中 Jar-In-Jar 列表,按 SHA-256 抽取到 <mc>/nestedmods/ 并去重
  • 并行 mod 发现 - ParallellModDiscoverer + 共享 ForkJoinPool,并发扫描 classpath/mods/versioned-mods
  • 重复 mod 去重 - ModCandidateV2Sorter.handleDuplicates 按 id+版本保留最高版本
  • Coremod 豁免清单 - jarjar_coremod_exemptions.cfg 跳过重复检测的 coremod 类名清单
  • API 所有权排序 - 基于 @API 与 package-info 拓扑排序,让 API 提供者先于 repackaging 它的 jar 加入 classpath
  • Hodgepodge 排序兜底 - Hodgepodge < 2.7.147 自动赋 SortingIndex=1,避免 NEI 注册顺序问题
  • EarlyAccessTransformer - 在 ASM 层面把 FML 关键类私有成员全部公开
  • FMLTransformer - 把 CoreModManager.handleLaunch 整段重写为转发到 CoreModManagerV2.handleLaunch;并把所有静态调用重定向到 V2 版本
  • V2ConstructionReplacerTransformer - 替换 new Loader()/new ModContainerFactory()/new ModDiscoverer()/new ASMModParser() 为 V2 版本
  • MixinPlatformAgentTransformer - 让 MixinPlatformAgentFMLLegacy.initFMLCoreMod 直接返回 null,避免与 JarJar 重复加载
  • CodeChickenCoreTransformer - 在 ClassDiscoverer.findClasspathMods 注入 Hooks.shouldIgnore,屏蔽已被 JarJar 处理的 jar
  • MetadataCollectionTransformer - 为 MetadataCollection.modList 字段注入 Gson @SerializedName 注解,识别 modlist / ModList 别名
  • DefaultLibraries 过滤 - 启动期已知 JVM/Mojang 类库的 42 个前缀,启动期加速 classpath 解析
  • DiscoveryPool 共享线程池 - 整个 JarJar 共享一个 ForkJoinPool,线程数由 maxThreads 配置
  • ASMDataTableV2 - 排序 @API 按 apiVersion;为每个 ModContainer 缓存来自其 jar 的 annotation 子集
  • ASMModParserV2 - 记录类的 binaryInterfaceNames 并作为 ASMData 加入 table,仿造新版 Forge 接口捕获
  • ModClassVisitorV2 - 把 visit() 的 interface 数组转发给 ASMModParserV2
  • ModCandidateV2 数据模型 - ModCandidate 的扩展字段:access transformers、cascaded tweaker、coreMod、嵌套候选、API 包声明、earlyPackages
  • LoaderV2 - 替换 cpw.mods.fml.common.Loader,使用 V2 discoverer / sort / 装载流程
  • CoreModManagerV2 - 替换 CoreModManager,并提供 Jar-in-Jar + parallel coremod 加载
  • ModCandidateV2Sorter - 通用类型候选排序 + API 所有权拓扑 + 重复版本去重
  • ClasspathModCandidateFinder - 扫描 ModClassLoader.getParentSources(),过滤 default/loaded/reparsable 库后输出 Minecraft jar/相关 jars
  • DirectoryModCandidateFinder - 扫描 mods 目录(支持 versioned 子目录与额外文件),过滤隐藏/已禁用/非 .jar 文件
  • ModCandidateFinder 接口 - findCandidates(ModCandidateConsumer) 函数式接口
  • LoaderUtil 路径缓存 - path.toRealPath() 的 ConcurrentHashMap 缓存,避免重复 fs syscall
  • Hooks 跨 transformer 钩子 - Hooks.shouldIgnore(File) 让 CCC/其它 transformer 能复用 JarJar 的忽略列表
  • JarUtil 嵌套抽取与版本识别 - getNestedJar + guessVersion(从 mcmod.info 或文件名) + scanPackagesAndApi + applyConfiguredSortOrder + checkNestedMods / checkNestedJars
  • JarByteSource 字节源 - Guava ByteSource 对 JarEntry 的薄封装
  • RewindableModInputStream - 一次性读取整个 jar 条目到 ByteBuffer 支持 rewind,从 Fabric 移植
  • SortableCandidate 接口 - getId/getVersion/getFile 三方法的通用候选类型
  • APIOnlyWrapper - 不产出 ModContainer 但参与排序/分类的纯 API jar 包装
  • ModContainerFactoryV2 - buildV2 构造 ModContainer 并把 @API 标记写入 candidate
  • ModContainerWrapper - record 实现 SortableCandidate;携带 candidate + parser
  • MetadataCollectionV2 - 支持 mcmod.info 中的 modListVersion: 2 多重结构 + jars 嵌套 jar 列表