DelegatedTransformer
基本信息
| 属性 | 值 |
|---|---|
| 类全名 | codechicken.core.asm.DelegatedTransformer |
| 实现接口 | net.minecraft.launchwrapper.IClassTransformer |
| 约定名 | JAR Manifest 属性 CCTransformer(DelegatedTransformer.java:105) |
| 源码行数 | 198 |
功能
这是 CodeChicken 生态的扩展槽机制:任何模组只要在自己的 JAR manifest 里写一行 CCTransformer: 某个类名,该类就会被本模组实例化并接入整条类转换链。CodeChicken 家族之外的模组(如 CodeChickenLib 生态里的任意附属)无需自己实现 IFMLLoadingPlugin,就能对 Minecraft 与其他模组的字节码做变换。
load() 由 coremod 的 injectData() 调用(CodeChickenCorePlugin.java:95)。若扫描到 0 个委托转换器,打 debug 日志后直接返回,不注册(DelegatedTransformer.java:59-63);否则一次性 registerTransformer 自身(:66-69),把所有委托者收拢到单一入口,避免逐个注册。
扫描范围
scanModsForDelegatedTransformers()(DelegatedTransformer.java:72-93)遍历两个目录:
| 目录 | 行 |
|---|---|
<minecraftDir>/mods |
:73-81 |
<minecraftDir>/mods/<currentMcVersion> |
:82-92 |
scanMod(File)(:95-113)只处理 .jar 与 .zip 结尾的文件(:96),读出 manifest 的 main attributes,取 CCTransformer 键(:105)。manifest 缺失时静默 return(:101、:103)。
加载与依赖解析
addTransformer(String, JarFile, File)(:115-148)的流程:
- 先尝试
Launch.classLoader.getClassBytes(transformer)(:119) - 取不到则从该 mod 自己的 jar 里读
transformer.replace('.','/') + ".class"(:122-130) defineDependancies(...)递归解析并定义依赖类(:132)- 校验类型:
IClassTransformer.class.isAssignableFrom(clazz),否则抛异常(:135-136) - 优先用
getDeclaredConstructor(File.class)构造,让转换器知道自己属于哪个 jar;捕获NoSuchMethodException后回退到无参构造(:139-143)
defineDependancies(:150-182)用 ASM ClassReader + DependancyLister 读出类依赖列表,递归深度由 Stack<String> depStack 的 contains 去重(:160-163)。依赖类若不在类加载器中,则必须存在于同一个 jar 内,否则抛 "Dependency ... not found in jar file ..."(:168-170)。
类通过 ClassLoader.defineClass 反射注入(:184-188),并手动写入 LaunchClassLoader.cachedClasses——否则 FML 的类缓存不会认识这个类。
失败处理
- 扫描单个 jar 失败:
CodeChickenCorePlugin.logger.error("CodeChickenCore: Failed to read jar file: " + file.getName(), e)(:110-112),有日志,不影响其他 jar - 加载单个转换器失败:
e.printStackTrace()(:145-147)——只有标准错误输出,不写 CodeChickenCore 的 log4j logger,且吞掉异常继续处理下一个 addTransformer是public static(:115),供外部直接调用
与 Gradle 依赖的关系
本机制是运行时的,与构建期的 dependencies.gradle 无关。CodeChickenCore/dependencies.gradle 中除 JUnit 5 测试依赖外没有任何 Minecraft 侧依赖声明。
相关条目
- CodeChickenCorePlugin - 调用
DelegatedTransformer.load()的位置 - CodeChicken 生态契约 - 谁在用这套委托机制