与 Minecraft Mixin 的差异
This content is not available in your language yet.
Copper 使用的 Mixin 是 SpongePowered Mixin 0.8.7 的修改版(仓库:MDTCopper/Mixin),版本号 0.1.x。它删去了与 Minecraft 相关的代码,调整了若干默认值,并扩展了 Java 版本支持。
原版 Mixin 为了适配 Minecraft 的各种加载环境(Forge、Fabric/ModLauncher、旧版启动器),内置了大量平台服务。这些在 Mindustry 场景下全部无用,因此被删除:
| 被删内容 | 用途 | 对 Copper 的影响 |
|---|---|---|
Mojang 服务(service.mojang.*) | 旧版 Minecraft 启动器(LaunchWrapper)集成 | 无。Mindustry 不使用 LaunchWrapper |
ModLauncher 服务(service.modlauncher.*) | Fabric/Forge 的类加载服务集成 | 无 |
| Forge/FML 平台代理 | Forge 专用平台 | 无 |
| RuntimeDecompiler(Fernflower) | 导出时反编译 | 无(导出仍可用,见下文) |
混淆相关(tools.obfuscation.* 的 JSON/Mapping) | 官方混淆映射 | Mindustry 不混淆,无需映射 |
module-info 等 | Java 模块化 | 无 |
结论: 面向 Minecraft 的配置项(refmap、混淆映射、MixinPlatformAgent 等)在 Copper 中不存在或无效,不要使用。
原版 Mixin 的所有注解 remap 默认为 true(因为 Minecraft 有混淆)。本项目把全部注解的 remap 默认值改为 false:
@Mixin(value = Vars.class, remap = false) // remap 可省略,默认就是 falsepublic abstract class MyPatch { ... }涉及注解:@Mixin、@Overwrite、@Shadow、@Accessor、@Invoker、@At、@Inject、@ModifyArg、@ModifyArgs、@ModifyConstant、@ModifyVariable、@Redirect。
影响:
- 你不需要(也不应该)写
remap = false,省略即可; - 不要把
remap设为true——没有映射表可查,会直接报错; refmap相关配置无需处理。
Java 版本支持扩展
Section titled “Java 版本支持扩展”原版 Mixin 0.8.7 官方支持到 Java 21。本项目扩展支持 Java 22–27(Mixin 环境兼容级别 JAVA_17 ~ JAVA_27)。上限不是”越新越好”,而是由内置 ASM 能解析的类文件版本钉死的:
- 最低兼容级别
JAVA_17:加载器的 Mixin 服务把下限报成它。低于它,JVM 连加载器与 Mixin 的类文件都加载不了; - 上限来自 ASM:Mixin 解析标准库类时读的是运行中 JRE 的 modules——解析
java.lang.Object拿到的就是这份 JRE 里的那一份,类文件版本随本机 JDK 走。加载器当前带 ASM 9.10.1,认到类文件主版本 71,即 Java 27;在 JDK 28 上读到主版本 72 的标准库类,ASM 直接抛Unsupported class file major version 72。所以换更新的 JDK 不会把上限抬高,只会踩到 ASM 的上限,不存在无限向上兼容; - 兼容级别说的是类文件版本:你的 Mixin 类如果按更高的版本编译,可以在配置里声明
compatibilityLevel(该字段原样透传,见配置 JSON 详解 · 原版字段透传),但它同样不能越过JAVA_27与 ASM 的能力。
这条上限同时也是加载器自己声明的 Java 支持范围,即 17 到 27。范围写在 gradle.properties 的 javaVersionRange 里,与同一份文件里的 asmVersion 配套维护:构建时连同版本号一起写进 Jar 内的 version.properties,供启动器与工具判断某个加载器版本该配哪版 Java(见加载器命令行 · 准备,报错现象见启动报错 · Java 版本问题)。
目标选择器默认值
Section titled “目标选择器默认值”Mixin 配置的 target 字段(@env(...) 目标选择器)在原版中无默认值;本项目默认设为 @env(DEFAULT)。绝大多数情况下你不需要书写 target 字段。
调试输出目录可运行时修改
Section titled “调试输出目录可运行时修改”原版的 Mixin 调试导出目录是编译期常量。本项目改为运行时可变,加载器会为每个容器设置独立的子目录:
.mixin.out/<容器id>/容器 id 示例:mindustry、example-examplemod。配合 --mixin-flag <modId,DEBUG_EXPORT> 使用(见入门教程 · 调试技巧)。
服务提供方式不同
Section titled “服务提供方式不同”原版 Mixin 通过扫描 classpath 发现服务。本项目实现了一套自有的 Mixin 服务(copper.loader.mixin.MixinEngineService),通过 META-INF/services 注册:
- 字节码来源:不是文件系统,而是加载器的容器系统(按容器解析目标类的字节码);
- 配置来源:Mixin 配置在内存中提供(
copper://<id>.json),不会去磁盘扫描mixins.json; - 全局属性服务:
MixinEngineGlobalPropertyService。
对模组作者的影响:
- 不要在 Jar 里放原版风格的
mixins.json(不会生效),一切以copper.mod.json+assets/copper/下的配置为准(见配置 JSON 详解); - Mixin 引擎按容器独立初始化,不同模组的注入互不干扰;
- 每个容器一个引擎实例,但共享全局单例的变换器——注入顺序由配置登记顺序决定。
注解处理器被保留,且修复了与 remap 默认值不一致的判定逻辑(AP 侧同样默认 remap = false)。构建时引入:
annotationProcessor "com.github.MDTCopper:Mixin:$mixinVersion:processor"它在编译期检查注解用法(目标类存在性、签名匹配等),能在开发期发现大部分低级错误,强烈建议配置。
Mixin 配置语法差异速查
Section titled “Mixin 配置语法差异速查”| 项目 | Minecraft 原版 | Copper |
|---|---|---|
| 配置文件名 | mixins.json(任意位置) | assets/copper/<任意名>.json(由元数据引用) |
| 配置格式 | 纯 Mixin 配置 | { "version": 1, "config": {...} } |
mixins 字段 | 类名数组 | 版本过滤器 → 类名映射(可多分支合并) |
target | 需显式设置 | 默认 @env(DEFAULT) |
| 混淆映射 | 需要 refmap | 不需要 |
| 加载方式 | 扫描 classpath | 容器 + 内存 copper:// |
| Java agent | 需要 -javaagent | 由加载器自行启动(Launcher-Agent-Class),不用自己配置;仅用于调试模组 |