快速开始
本页从官方模板 mod-templete 起步:把模板改成你自己的模组,构建出 Jar,最后在 IDEA 里直接断点调试。不用从零手写工程——构建脚本、示例主类与 Mixin、调试用的运行配置,模板里都配好了。
| 项目 | 要求 |
|---|---|
| JDK | 17–27。Mindustry v9 起要求 Java 25,所以配 v9 的 gameVersion 调试时,请用 25 到 27 之间的 JDK(见加载器命令行 · 准备) |
| 游戏 | 加载器要求官方发行版 146.0 及以上或 BE 构建号 24369 及以上(见版本、依赖与冲突),模板默认的 gameVersion 已满足 |
| 网络 | 首次构建要从 jitpack 拉取加载器与 Mixin 依赖;调试时还要下载加载器 Jar 与游戏 Jar |
-
拿一份模板。 在仓库页面点 Code → Download ZIP,或者直接克隆:
Terminal window git clone https://github.com/MDTCopper/mod-templete.git my-mod -
用 IDEA 打开项目根目录,按提示以 Gradle 项目导入。模板自带 Gradle wrapper(
gradlew、gradlew.bat与gradle/wrapper/),本机不装 Gradle 也能构建。 -
改掉示例的身份,让加载器把它当成你的模组:见从示例改起。
克隆下来的模板长这样:
文件夹my-mod/
- build.gradle — 依赖与构建、调试任务
- settings.gradle — 根项目名,决定产物 Jar 的文件名
- copper.mod.json — 模组元数据(必填;HJSON 写法为 copper.mod.hjson)
- icon.png — 模组图标(可选)
- gradlew / gradlew.bat — Gradle wrapper
文件夹.run/ — IDEA 运行配置:BuildJar、PrepareDebug、Debug
- …
文件夹res/
文件夹assets/ — 原版资源:游戏按原版规则加载
文件夹bundles/
- …
文件夹sprites/
- …
文件夹copper/ — Copper 资源
文件夹mixins/
- mindustry.json — Mixin 配置(可选,见 Mixin 专题)
文件夹src/
文件夹example/examplemod/
- ExampleMod.java — 主类,继承 CopperMod
文件夹patch/impl/
- MyPatch.java — Mixin 类(可选)
icon.png 是可选的:没有它模组照常加载,只是不会显示模组图标。
与 Mindustry 官方模板的差异:
- 元数据文件是
copper.mod.json(HJSON 写法则是copper.mod.hjson),且格式与原版的mod.hjson完全不同(见模组元数据); - 主类需要继承
CopperMod(见主类与生命周期); - 资源布局上,
assets/会被挂载为原版LoadedMod的资源根,因此原版模组资源(bundles/、sprites/、content/等)放在assets/下,而 Copper 自己的资源(Mixin 配置等)放在assets/copper/下,两者互不干扰(详见数据、设置与本地化 · 资源文件)。
模板里的一切都是示例,挨个换成自己的就行:
| 改哪里 | 说明 |
|---|---|
settings.gradle 的 rootProject.name | 只影响产物文件名,改成模组名即可 |
copper.mod.json 的 id / name / author / version / main | id 是模组标识,形如 作者:模组名;main 是主类的全限定名(见模组元数据) |
src/ 下的目录与类名 | 目录结构就是包名,改完记得同步 copper.mod.json 的 main |
res/assets/copper/mixins/mindustry.json 的 package | Mixin 类所在的包,必须与源码一致(见配置 JSON 详解) |
模板的主类就是一个能跑的最小模组:
package example.examplemod;
import copper.core.mod.*;
public class ExampleMod extends CopperMod { public ExampleMod() { }
@Override public void registerPackets() { // 需要自定义网络数据包时在这里注册 }}registerPackets() 之类的扩展方法都是可选的,用不到就删掉(见主类与生命周期)。MyPatch 是往 Vars::finishLaunch 注入一行日志的示例 Mixin:删掉它的同时,要一并删掉 copper.mod.json 里的 mixins 和 res/assets/copper/mixins/。
build.gradle 通常只需要改版本号:
ext { // 发行 tag 或 commit hash;不要写 snapshot copperVersion = '<加载器版本>' // 从这个版本的 gradle.properties 里取 mixinVersion = '<Mixin 版本>' gameVersion = 'v159.7'}copperVersion填加载器的发行 tag(例如0.2.0)或某个 commit hash。别写snapshot——那是给 GitHub Release 用的通道名,也别写-SNAPSHOT,jitpack 每次拉取都会重新构建,卡很久;mixinVersion必须与copperVersion配套:去https://github.com/MDTCopper/loader/blob/<copperVersion>/gradle.properties上看同一份声明(mixinVersion=...)。两者成对出现,例如加载器0.2.0对应mixinVersion=0.1.7;gameVersion决定编译时用的游戏 API,也决定调试时下载哪个游戏版本。
依赖部分模板已经写好,一般不用动:
dependencies { compileOnly "com.github.MDTCopper.loader:core:$copperVersion" // 加载器核心 API compileOnly "com.github.MDTCopper.loader:mod:$copperVersion" // CopperMod 等模组侧 API compileOnly "com.github.Anuken.Mindustry:core:$gameVersion" annotationProcessor "com.github.MDTCopper:Mixin:$mixinVersion:processor" loaderDesktop "com.github.MDTCopper.loader:desktop:$copperVersion" // 仅调试用}loader:core(含copper.loader.*)与loader:mod(含copper.core.mod.CopperMod)通过 jitpack 拉取;annotationProcessor是 Mixin 注解处理器,用来在编译期检查 Mixin 注解的正确性;compileOnly的依赖不会被打进 Jar——这些类运行时由加载器提供;loaderDesktop只在调试任务里用到,同样不进 Jar;jar任务会把copper.mod.json(或copper.mod.hjson)与icon.png放到 Jar 根目录。
模板还注册了四个调试用的任务,Debug 运行配置会按顺序调用它们:
| 任务 | 作用 |
|---|---|
downloadLoader | 把 loader:desktop 存成项目根目录下的 loader.jar |
downloadMindustry | 从 GitHub Release 下载 gameVersion 的游戏 Jar,存成 game.jar |
prepareDebugJar | 构建模组,并复制成 .mindustry/copper/mods/mod-to-debug.jar |
prepareDebug | 依次执行上面三个 |
-
构建 Jar。 在项目根目录执行:
Terminal window ./gradlew jarWindows 用
gradlew.bat jar;在 IDEA 里跑 BuildJar 配置也一样。产物是build/libs/<根项目名>.jar。 -
放入模组文件夹。 把 Jar 复制到
<数据目录>/copper/mods/(见使用桌面版 · 模组放在哪里)。文件名随便取,加载器按 Jar 里的元数据认模组,与文件名无关。 -
启动验证。 启动游戏,日志里会列出加载到的模组。只放了一个模组时是:
Found 2 mods.除了你的模组,另一个是加载器的核心模组。数量比预期少,通常是文件没放进上面那个文件夹。
模板的 .run/ 里带了三份 IDEA 运行配置,以 Gradle 项目导入后开箱即用,不用自己拼命令行:
| 配置 | 做什么 |
|---|---|
| BuildJar | 跑 jar 任务,产出可安装的 Jar |
| PrepareDebug | 跑 prepareDebug,准备好 loader.jar、game.jar 与待调试的模组 Jar |
| Debug | 用 loader.jar 启动游戏并接上调试器,启动前自动执行 PrepareDebug |
- 打断点。 在
src/里的模组代码上点一下断点。 - 以 Debug 方式运行 Debug 配置。 第一次会先下载加载器与游戏 Jar,需要联网;下完自动启动游戏,命中断点后就能看调用栈、变量、单步执行。
- 改完再编译。 改动后按
Ctrl+F9重新编译,IDEA 提示 Reload changed classes 时确认,游戏里跑的立刻就是新代码——不用重启游戏,也不用重新打包。
Debug 配置实际执行的命令大致是:
java --enable-native-access=ALL-UNNAMED -jar loader.jar -G game.jar \ --mod-debug-jar .mindustry/copper/mods/mod-to-debug.jar \ --mod-debug-classpath build/classes/java/main几个要点:
- 用的是项目自己的数据目录。 配置的工作目录是项目根目录,加载器默认把当前目录下的
.mindustry当数据目录,所以调试不会碰你平时玩的存档与模组(该目录已在.gitignore里)。想改用真实数据目录,就在 Program arguments 里加-D <路径>; - 编译输出优先于 Jar。
--mod-debug-classpath指向 Gradle 的编译输出build/classes/java/main,它排在 Jar 里的同名类之前,所以代码改完必须重新编译才生效;copper.mod.json这类元数据读的仍是被调试的那份 Jar,改了要重跑prepareDebug; - 热交换默认只能改方法体。 改方法体、改 Mixin 的注入逻辑可以热交换;增删字段或方法、改继承关系要重启游戏——这是运行用的 JDK 的限制,换掉它就能放宽,见增强热交换。原理见加载器命令行 · 调试模组;
- JDK 版本。
Debug配置把运行 JRE 指定成了 25(加载器支持 17–27,见环境要求),本机没有 JDK 25 就换成 25 到 27 之间的一个; - 看 Mixin 的注入过程。 在 Program arguments 末尾加上
--mixin-log 你的模组id,启动日志会打印每个 Mixin 的应用情况(见Mixin 入门教程 · 调试技巧)。
不想用 IDEA 的话,上面那条命令就是等价做法,各参数的含义见加载器命令行。
上面那些限制来自普通的 JDK。换成 JetBrains Runtime(JBR)就能改得更多:JBR 内置了 DCEVM 的增强类重定义,加载新类时允许增删方法、增删字段、改方法签名、增删内部类,同样不用重启游戏。这个能力在 JBR 里默认关闭,要用 -XX:+AllowEnhancedClassRedefinition 打开。
用 IDEA 自带的 JBR 最省事:
-
让运行配置用 JBR。 在 Project Structure → SDKs 里添加一个 JDK:新版 IDEA 的 Download JDK 列表里直接有 JetBrains Runtime,也可以指向 IDEA 安装目录下的
jbr。加好后把Debug运行配置的 JRE 换成它。 -
打开增强重定义。 在
Debug运行配置的 VM options 里,把-XX:+AllowEnhancedClassRedefinition追加到原有的--enable-native-access=ALL-UNNAMED后面。 -
照旧重新编译。 按
Ctrl+F9并确认 Reload changed classes,这次增删的方法与字段也会一起生效。
- 完整掌握元数据语法:模组元数据
- 了解主类的全部能力:主类与生命周期
- 为模组添加第一个 Mixin:Mixin 入门教程