跳转到内容

数据、设置与本地化

本页介绍 Copper 模组如何读写数据文件、创建设置项、访问资源与做多语言本地化。

主类继承自原版 Mod,直接使用 getConfigFolder() 与 getConfig():

public class ExampleMod extends CopperMod {
@Override
public void init() {
// 配置文件夹
Fi folder = getConfigFolder();
// config.json 文件句柄
Fi config = getConfig();
Log.info("config: " + config.file().getAbsolutePath());
}
}

Copper 模组的配置文件夹位于 <数据目录>/copper/datas/<作者-模组名>/(与 id 对应,冒号换连字符),与原版模组不同(见主类与生命周期 · 配置文件夹的差异)。

推荐使用 copper.core.Copper.createSettings() 创建绑定到模组数据目录的 Settings 实例:

import arc.Settings;
import copper.core.Copper;
public class ExampleMod extends CopperMod {
@Override
public void init() {
Settings settings = Copper.createSettings(ExampleMod.class);
settings.put("myOption", true);
Log.info("myOption = " + settings.getBool("myOption"));
}
}
  • 设置文件位于模组数据目录(<数据目录>/copper/datas/<作者-模组名>/);
  • 每个模组使用独立的设置实例,互不干扰;
  • 修改即保存:put()、remove()、clear() 会立即把设置写回文件,不需要手动保存;
  • 底层使用 CopperSettings(Settings 子类):它跳过了 Mindustry v146 中一次性的全局按键绑定重载,避免模组设置污染游戏全局按键数据。你无需关心,直接使用即可。

模组的设置项可以直接显示在游戏的设置菜单里,不需要自己写弹窗。

用原版 API 注册分类即可,Copper 会自动识别它属于哪个模组:

import arc.*;
import copper.core.*;
import copper.core.mod.*;
import copper.core.util.*;
import mindustry.Vars;
import mindustry.ui.*;
public class ExampleMod extends CopperMod {
public static Settings settings;
public static I18NBundle bundles;
public ExampleMod() {
settings = Copper.createSettings(ExampleMod.class);
bundles = Copper.createBundle(ExampleMod.class);
}
@Override
public void init() {
Vars.ui.settings.addCategory(bundles.get("settings.category"), Icon.settings, t -> {
CopperSettingsTable st = new CopperSettingsTable(settings, bundles);
st.checkPref("myOption", true);
st.sliderPref("myNumber", 50, 0, 100, 5, i -> i + "%");
t.add(st).grow();
});
}
}
  • 分类名用自己的 bundle 取本地化文本(bundles.get("settings.category"))。Copper 模组的 bundle 是独立实例、没有注册进游戏,因此这里不能像原版那样写 @键名,要自己把文本取出来;
  • 用 CopperSettingsTable 取代原版的 SettingsTable:原版表格的读写走游戏的全局 Settings,而 CopperSettingsTable 绑定到你传入的 Settings 实例与 bundle(见上文);
  • 把它 add 进传入的 t 即可——t 是游戏自己创建的普通表格,只作为容器使用。

CopperSettingsTable 提供与原版一致的一组方法:

方法说明
checkPref(name, def) / checkPref(name, def, changed)勾选项,可选变更回调
sliderPref(name, def, min, max, format) / sliderPref(name, def, min, max, step, format)滑条,format 把数值转成显示文本
textPref(name, def) / textPref(name, def, changed)单行文本
areaTextPref(name, def) / areaTextPref(name, def, changed)多行文本
pref(Setting)自定义条目:继承 CopperSettingsTable.Setting 并实现 add(table)

条目的标题与说明同样从你传入的 bundle 读取,键的约定与原版一致:

settings.category = 示例模组
setting.myOption.name = 启用某功能
setting.myOption.description = 鼠标悬停时显示的说明。
setting.myNumber.name = 数值
  • setting.<键名>.name:条目标题;Windows 上若存在 setting.<键名>.name.windows 则优先使用(与原版一致);
  • setting.<键名>.description:可选,鼠标悬停提示;
  • 表格底部会自动附带一个 Reset to Defaults 按钮,点击后删除该表格所有条目的值、恢复默认。

模组 Jar 内的 assets/ 目录会被挂载为原版 LoadedMod 的资源根,也就是说,游戏按原版方式加载的资源都从这里找。而 Copper 自己使用的资源约定放在 assets/copper/ 下,两者互不干扰:

位置用途
assets/原版模组资源:bundles/、sprites/、content/、maps/ 等,由游戏按原版规则加载
assets/copper/Copper 侧资源:例如 Mixin 配置 assets/copper/mixins/、Copper bundle assets/copper/bundles/,由加载器按 Copper 约定读取

构建时由 resources.srcDirs = ["res"] 把 res/ 目录内容打进 Jar,因此源目录布局为 res/assets/...。

import arc.files.Fi;
import copper.core.Copper;
// assets 文件夹
Fi assets = Copper.getModAssetFolder(ExampleMod.class);
// assets/foo/bar.png
Fi file = Copper.getModAsset(ExampleMod.class, "foo/bar.png");
// 模组根目录下的任意文件
Fi root = Copper.getModRoot(ExampleMod.class);
  • 模组目录内非 assets 的文件用 Copper.getModFile(clazz, path) 访问;
  • 图片等资源按原版规则注册到 Atlas(sprite 名前缀为 copper-<作者-模组名>-,与游戏内注册的模组名一致;命名细节与例外见命名与映射 · 贴图文件名)。

Copper 提供与 arc 的 I18NBundle 结合的工具方法。约定资源布局(Copper 自己的 bundle,位于 assets/copper/bundles/):

  • 文件夹res/
    • 文件夹assets/
      • 文件夹copper/
        • 文件夹bundles/
          • bundle.properties — 默认语言
          • bundle_zh_CN.properties — 简体中文
import arc.util.I18NBundle;
import copper.core.Copper;
public class ExampleMod extends CopperMod {
public static I18NBundle bundles;
public ExampleMod() {
bundles = Copper.createBundle(ExampleMod.class);
}
}
  • Copper.createBundle(clazz) 从 assets/copper/bundles/bundle 读取,并按系统语言自动选择语言文件;
  • 建议把 bundle 存为静态字段,在主类构造器中创建。

Copper.translateModMeta(clazz, bundle) 会用 bundle 翻译模组的 name、author、description、subtitle,并同步到原版模组注册表:

public class ExampleMod extends CopperMod {
public static I18NBundle bundles;
public ExampleMod() {
bundles = Copper.createBundle(ExampleMod.class);
Copper.translateModMeta(ExampleMod.class, bundles);
}
}

bundle 中约定使用的键:

mod.name = Example Mod
mod.author = Example
mod.description = A Copper example mod.
subtitle = My Subtitle
用途路径
加载器数据目录<数据目录>/copper
Copper 模组文件夹<数据目录>/copper/mods
Copper 模组数据目录<数据目录>/copper/datas
单个模组的配置/设置目录<数据目录>/copper/datas/<作者-模组名>
原生库(自动解压)<数据目录>/copper/lib

copper.core.Copper 提供对应访问方法(见主类与生命周期 · 模组上下文工具类)。