引言

Mindustry 里的大部分 可注册的类型——例如 方块 Block物品 Item子弹类型 BulletType单位类型 UnitType,都是 享元 (Flyweight)。这是一种设计模式,意图在 减少对象的大小和减少内存占用。
关于享元的更多信息,请参见:https://www.runoob.com/design-pattern/flyweight-pattern.html
类似于 Minecraft 中的 物品(Item)物品堆栈(ItemStack),Mindustry也有类似的设计。接下来,普冷姆会通过注册第一个物品并在游戏中加载的方式为您介绍本文主题,并持续地在本教程中介绍关于 享元模式(Flyweight Pattern) 的更多信息、意义与实现方式。

准备工作

我想,经过了上一章的介绍,您应该已经为您的 mod 取好了一个响亮而又贴合主题的名称。那么接下来,普冷姆为展示内容,也会为本 教学用mod 进行命名工作,请记住这些名称,以便 您在实际操作中可以替换对应的名称 和 不会在学习本教程时对名称感到疑惑。也请不要直接使用本教程提供的名称,请您自己取名。

将 example 包,重命名为 tutorial 将 example.ExampleJavaMod 类,重命名为 TutorialMod 同时修改 mod.hjson 里的 Mod 名称与 ID,名称为:Tutorial Mod,ID为:tutorial-mod,主类为:tutorial.TutorialMod

注意:如果你要重命名一个类——比如 mod 的主类,请同时重命名它的构造方法,因为构造方法需要和类名保持一致。并且,每个 .java 文件中,只允许存在一个 公开类 (public class) ,所以,您也不得不为它的文件进行重命名。

快捷键提示:在IDEA将光标置于您需要重命名的名称上,按下shift+F6,可以让IDEA自动找到使用了这个名称的所有引用,并同时修改名称。在修改名称后,按下Enter键,确定修改。

最终结果如下:

  1. package tutorial;
  2. import arc.util.Log;
  3. import mindustry.mod.Mod;
  4. public class TutorialMod extends Mod {
  5. public TutorialMod() {
  6. Log.info("Loaded TutorialMod constructor.");
  7. }
  8. @Override
  9. public void loadContent() {
  10. Log.info("Loading some tutorial content.");
  11. }
  12. }
  1. displayName: "Tutorial Mod"
  2. name: "tutorial-mod"
  3. author: "Liplum"
  4. main: "tutorial.TutorialMod"
  5. description: "A Mindustry mod for tutorial."
  6. version: 1.0
  7. minGameVersion: 126
  8. java: true

创建 ModItems 类

右键 tutorial 包,并选择 New >> Java Class,在弹出的窗口中输入 ModItems,然后按下 Enter 键,IDEA会自动为您新建好这个类。
RClickTutorialPackage.png
接下来,我们需要让 ModItems 类实现 ContentList(mindustry.ctype.ContentList) 接口,并覆写 void load() 方法
关于 Java 中 接口(Interface) 的介绍,请参见:https://www.runoob.com/java/java-interfaces.html
代码如下:

  1. package tutorial;
  2. import mindustry.ctype.ContentList;
  3. public class ModItems implements ContentList {
  4. @Override
  5. public void load() {
  6. }
  7. }

创建第一个物品 铥 Thulium

接下来,请您聚焦于 ModItems 类中,现在我们要创建第一个 物品 (Item)
首先,我们先在 void load( ) 方法中输入以下内容:

new Item(“thulium”);

注册一个物品,我们需要实例化 Item(mindustry.type.Item) 类——调用它的构造函数,并填入该物品的ID,ID是一个字符串。构造函数会自动调用注册相关的方法,物品会被自动注册到游戏中去。
ID用于区分不同的 可注册类型(方块,物品等),当您的 mod 中存在两个相同的ID (即名称冲突) 时,游戏会在加载时崩溃闪退,并提示您出现了名称冲突。不过,我们这里完全不用担心会和 原版(Vanilla) 或其他 mod 中的物品发生冲突,Mindustry 在为每个物品注册的时候,会加上 Mod ID,所以这个物品真正的注册名 (或ID) 为:tutorial-mod-thulium
现在这个物品已经会在游戏开始的时候被注册了,但是,我们还需要能够在这个方法 (即 void load( )) 外部进行访问——例如,您需要 使用工厂生产 或 挖掘这种物品 的时候。
那么我们就要在 ModItems 类中添加一个 静态字段 (static field) ,名为 thulium,并在 void load( ) 方法被调用时,赋值给这个静态字段。
更多有关 静态字段 (static field) 静态方法(static method) 的内容,请查阅:https://www.runoob.com/java/java-modifier-types.html
最终,这个类的代码如下所示:

  1. public class ModItems implements ContentList {
  2. public static Item thulium;
  3. @Override
  4. public void load() {
  5. thulium = new Item("thulium");
  6. }
  7. }

快捷键提示:当您输入一个类名的时候,如果在该文件中还未 导入(Import) 这个类,那么IDEA会将名称标红——提示错误。您可以将光标悬停在红色的名称上几秒,等待IDEA弹出 Tooltip 给予您如何进行修正的智能提示。或者按下Alt+Enter键,主动显示智能提示。如下图所示:

IDEASmartImport.png
接下来,我们需要在 Mod 主类的 void loadContent( ) 方法中实例化这个类,并调用 它的 void load( ) 方法。与之前同理,这里就不再赘述了。

  1. public class TutorialMod extends Mod {
  2. public static ModItems modItems;
  3. public TutorialMod() {
  4. Log.info("Loaded TutorialMod constructor.");
  5. }
  6. @Override
  7. public void loadContent() {
  8. Log.info("Loading some tutorial content.");
  9. modItems = new ModItems();
  10. modItems.load();
  11. }
  12. }

物品的贴图与本地化名称

Mod 项目文件结构 一章中,我们提到 assets 文件夹内可以放置 mod 内的资源文件,那么接下来,我们就需要为这个物品添加 贴图 (texture) 了。

贴图 Texture

首先新建 (若未创建) assets/sprites/items 文件夹,并将与该物品具有相同名称的png文件复制其中——这里即 thulium.png

额外信息 Info

  1. Mindustry 会默认加载与物品同名 (指注册名) 的贴图,具体请查阅 mindustry.ctype.UnlockableContent#loadIcon(),您也可以通过覆写该方法,加载您需要的贴图。
  2. 对于物品的贴图,建议使用 32x32 图像大小,超过/低于 这个值,会被 Mindustry 缩放至 32x32,这样会造成图像过度清晰或者过度模糊。
  3. 事实上,Mindustry 会自动递归地加载所有在 assets/sprites 文件夹中的 png 贴图,并自动加上您的 ModID。最终加载的结果会无视文件夹的名称,所以您可以任意创建文件夹,以此为贴图分类——比如为 物品(items) 或 方块(blocks) 文件夹 创建子文件等,用于管理大量的贴图。但也因此,您无法在 assets/sprites 文件夹和其子文件夹下,使用相同的文件名 (指png贴图),因为这样会导致名称冲突。

之后,我们就能在游戏内,通过 物品源(ItemSource) 来获得该物品并查看了。
ThuliumItem.png

本地化 Localization

前文提到,我们需要在 assets/bundles 下添加为 本地化(localization) 所需的语言文件。
介于读者的母语和世界较通用的语言,我们需要在这个文件夹下,添加如下两个 .properties 文件:

bundle.properties bundle_zh_CN.properties

bundle.properties 是游戏默认语言:英语(English)
bundle_zh_CN.properties 简体中文(Simplified Chinese)
对于语言文件的命名格式大致如下:
bundle<语言><地区>.properties
其中,语言代号 全部小写,地区代号 全部大写,地区是可选的。

我们需要分别在这两个文件中写入如下内容:

  1. item.tutorial-mod-thulium.name=Thulium
  2. item.tutorial-mod-thulium.description=A radioactive metal.
  1. item.tutorial-mod-thulium.name=铥
  2. item.tutorial-mod-thulium.description=一种具有放射性的金属。

其中 item. 是固定用来区分这个 非本地化(unlocalized) 键的名称的,这里 原版(Vanilla) 的命名规则为:
item.<你的Mod ID>-<你的物品名称>.name
item.<你的Mod ID>-<你的物品名称>.description
方块也同样类似:
block.<你的Mod ID>-<你的物品名称>.name
block.<你的Mod ID>-<你的物品名称>.description
具体语言文件格式、地区名称,和支持的语言请参考 Mindustry 官方项目:https://github.com/Anuken/Mindustry/tree/master/core/assets/bundles

打包 Jar 与 测试 Test

接下来,确保以上代码和操作都无误且没有疏漏后,可以如 前文 一样执行 Gradle 的 Jar Task,等待 jar 打包完毕,并导入到游戏中测试。
检查您的物品是否正常地被加载到游戏中;贴图是否正确——而不是 “oh no”;是否显示了本地化名称。

尾声

本章这是最初步的入门,之后还会介绍更多的关于 Mindustry Modding 的内容。如果您喜欢本教程,可以给 普冷姆的 Mod —— Cyber IO 点上一个 Star 哦qwq
开源项目地址 https://github.com/liplum/CyberIO

版权声明

在本 教学mod 中,普冷姆以非商用形式使用了来自 饥荒 (Don’t Starve) 的图像资源,如若侵权请书面告知。对于引用的图片,All copyright Klei reserved.