跳转至

模组介绍

Mindustry 模组只是资产的目录。根据您想要做的事情以及您愿意为此付出的努力,有许多方法可以使用模组 API。

您可以仅仅重新绘制现有的游戏内容,您可以使用更简单的 Json API 创建新的游戏内容(这是本文件的主要重点),您可以添加自定义声音(或重用现有声音)。可以将地图添加到战役模式,并添加脚本以编程特殊行为到您的模组中,例如自定义效果。

分享您的模组就像将项目目录给某人一样简单;模组也可以跨平台使用,适用于任何支持它们的平台。您将希望使用 GitHub或类似服务)来托管您的源代码。 制作模组,您只需要任何带有文本编辑器的计算机。

目录结构

您的项目目录应如下所示:

project
├── mod.hjson
├── content
│   ├── items
│   ├── blocks
│   ├── liquids
│   └── units
├── maps
├── bundles
├── sounds
├── schematics
├── scripts
├── sprites-override
└── sprites
  • mod.hjson(必需)模组的元数据文件,
  • content/* 目录用于游戏 内容
  • maps/ 目录用于游戏内地图,
  • bundles/ 目录用于 Bundles
  • sounds/ 目录用于 声音 文件,
  • schematics/ 目录用于 原理图 文件,
  • scripts/ 目录用于 脚本
  • sprites-override/ 精灵 目录用于覆盖游戏内内容,
  • sprites/ 精灵 目录用于您的内容,

每个平台都有不同的用户应用数据目录,这就是您的模组应该放置的地方:

  • Linux: ~/.local/share/Mindustry/mods/
  • Steam: steam/steamapps/common/Mindustry/saves/mods/
  • Windows: %appdata%/Mindustry/mods/
  • MacOS: ~/Library/Application Support/Mindustry/mods/

请注意,您的文件名应为小写并用连字符分隔:

  • 正确:my-custom-block.json
  • 错误:My Custom Block.json

Hjson

Mindustry 使用 Hjson,对于任何了解 Json 的人来说,它只是一个非常流行的序列化语言 Json 的超集。– 这意味着任何有效的 Json 都可以工作,但您会获得额外的有用功能:

# 单行注释

// 单行注释

/* 多行
注释 */

key1: 单行字符串

key2:
'''
多行
字符串
'''

key3: [ 值 1
        值 2
        值 3 ]

key4: { key1: 字符串
        key2: 0 }

如果您不理解这些词。– 序列化语言只是编码程序信息的语言,编码意味着将信息从一种形式转换为另一种形式,在这种情况下,将文本转换为 Java 数据结构。

mod.hjson

在您的项目目录的根部,您必须有一个 mod.json,它定义了项目的基本元数据。此文件也可以(可选)命名为 mod.hjson,以帮助您的文本编辑器选择更好的语法高亮。

name: "mod-name"
displayName: "这不是一个模组。"
author: 您自己
description: "Bbfashbjhcbabfhsbafbhajbf"
version: "1.0"
minGameVersion: "148"
dependencies: [ ]
hidden: false
  • name 将用于引用您的模组,因此请仔细命名。应为 kebab-case(无大写字母,空格用 '-' 填充),并且不应有任何颜色格式。
  • displayName 将用作 UI 的显示名称,您可以使用格式化来添加该名称。
  • description 模组的描述将在游戏内模组管理器中呈现,因此请保持简短明了。
  • dependencies 是可选的,如果您想了解更多,请参见 dependencies 部分。
  • minGameVersion 是游戏的最低构建版本。此项 必需 为大于 105 的数字。
  • hidden 是此模组是否对多人游戏至关重要,默认为 false。纹理包、JS 插件等应使用此项,以免与服务器和客户端发生冲突。作为经验法则,如果您的模组创建内容,则不应将其隐藏。

内容

在您的项目目录的根部,您可以有一个 content/ 目录,这里是所有 Json/Hjson 数据的地方。在 content/ 内,您有各种内容的子目录,这些是当前常见的:

  • content/items/ 用于 物品,如 coppersurge-alloy
  • content/blocks/ 用于 ,如炮塔和地板;
  • content/liquids/ 用于 液体,如 waterslag
  • content/units/ 用于飞行或地面 单位,如 eclipsedagger

请注意,这些子目录中的每一个都需要特定的内容类型。这些文件的文件名很重要,因为路径的主干名称(不带扩展名的文件名)用于引用它。

此外,这些 content/<content-type>/* 目录中的文件可以任意嵌套到其他任何名称的子目录中,以帮助您进一步组织它们,例如:

  • content/items/metals/iron.hjson,这将分别创建一个名为 iron 的物品。

这些文件的内容通常看起来像这样:

type: TypeOfThing
name: Name Of Thing
description: Description of thing.
# ... 这里还有更多字段 ...
字段 类型 备注
type 字符串 此对象的内容类型。
name 字符串 内容的显示名称。
description 字符串 内容的显示描述。

其他字段将包括该类型本身的字段。

附注,namedescription 在 json 结构中不是必需的。您可以为任何语言定义它们(Bundles)[#bundles]。但是,如果它们在任一处不存在,则名称将为 <type>.<modname>-<stemname>.name,描述为空。

类型

类型有许多字段,但重要的是 type;这是一个特殊字段,由内容解析器使用,改变您的对象类型。Router 类型不能是 Turret 类型,因为它们完全不同。

类型 扩展 彼此,因此如果 MissileBulletType 扩展 BasicBulletType,您将在 MissileBulletType 中访问 BasicBulletType 的所有字段,如 damagelifetimespeed。字段是区分大小写的:hitSize =/= hitsize

您可以期望字段的功能取决于特定类型,有些类型对其字段没有任何作用,主要作为基础类型扩展。这样的类型是 Block

在这个单位示例中,单位的类型是 flying。子弹的类型是 BulletType,因此您可以使用 MissileBulletType,因为 MissileBulletType 扩展了 BulletType

在这里,您还可以使用 mechlegsnavalpayload 作为单位类型。

type: flying
weapons: [
  {
    bullet: {
      type: MissileBulletType
      damage: 9000
    }
  }
]

从构建 125.1 开始,类型也可以是 Java 类的 完全限定类名

例如,要将一个块指定为 MendProjector,您可以写 type: mindustry.world.blocks.defense.MendProjector 而不是 type: MendProjector

虽然对于原版类型并不是特别有用,但这可以用于从其他 Java 模组作为依赖项加载块类型。

科技树

type 类似,存在另一个神奇字段,称为 research,可以放在任何块对象的根部,以将其放入科技树中。

research: duo

这将使您的块在科技树中位于 duo 之后,要将其放在您自己模组的块之后,您可以写您的 <block-name>,如果您使用的是来自其他模组的内容,则只需添加模组名称前缀。

研究成本:

类型 成本 备注
requirements ^ 1.1 * 20 * researchCostMultiplier researchCostMultiplier 是可以在块上设置的属性
单位 requirements ^ 1.1 * 50 ---

成本将向下舍入到最接近的 10、100、1k、10k 或 100k,具体取决于成本的高低。

requirements 是块或单位的成本。单位使用其建造成本/升级成本进行计算。

如果您想设置自定义研究要求,请使用此对象替代仅使用名称:

research: {
  parent: duo
  requirements: [
    copper/100
  ]
}

这可以用于覆盖块或单位的成本,或使资源需要研究,而不仅仅是生产它。

精灵

制作精灵所需的只是一个支持透明度的图像编辑器(即:不是画图)。块精灵应为 32 * size,因此一个 2x2 的块将需要一个 64x64 的图像。图像必须是具有 32 位 RGBA 像素格式的 PNG 文件。 任何其他像素格式,例如 16 位 RGBA,可能会导致 Mindustry 崩溃并出现"Pixmap decode error"。您可以使用命令行工具 file 打印有关您的精灵的信息:

file sprites/**.png

如果其中任何一个不是 32 位 RGBA 格式,请修复它们。

精灵可以简单地放入 sprites/ 子目录中。内容解析器将递归查找它。 图像被打包到一个"图集"中,以提高渲染效率。sprites/ 中的第一个目录,例如 sprites/blocks,决定了精灵在此图集中的页面。将块的精灵放在 units 页面上可能会导致大量延迟;因此,您应尝试以类似于 原版游戏 的方式组织内容。

内容将根据其自身名称查找精灵。content/blocks/my-hail.json 的名称为 my-hail,同样 sprites/my-hail.png 的名称为 my-hail,因此它将被此内容使用。

内容可能会查找多个精灵。my-hail 可能是一个炮塔,它可能会查找后缀 <name>-heat,这意味着它将查找 my-hail-heat

您可以在这里找到所有原版精灵:

关于精灵的另一件事是,有些精灵会被游戏修改。炮塔特别会添加黑色边框,因此您在制作精灵时必须考虑到这一点,例如在炮塔周围留出透明空间:Ripple

要覆盖游戏内内容的精灵,您可以简单地将它们放入 sprites-override/。 这会删除它们的 id 前缀 <modname>-,使它们能够覆盖原版和其他模组的精灵。 您还可以使用此方法创建具有简短名称的精灵,例如 cat,以便在脚本中轻松使用,只需注意与其他模组的名称冲突。

声音

可以通过模组系统添加自定义声音,将它们放入 sounds/ 子目录中。之后将它们放在哪里无关紧要。支持两种格式:oggmp3。请注意,mp3 文件无法无缝循环,因此尽量使用 ogg

与其他资产一样,您通过文件名的主干引用它们,因此 pewpew.oggpewpew.mp3 可以通过类型为 Sound 的字段引用 pewpew

以下是内置声音的列表:

artillery back bang beam bigshot bioLoop blaster bolt boom breaks build buttonClick cannon chatMessage click combustion conveyor corexplode cutter door drill drillCharge drillImpact dullExplosion electricHum explosion explosionbig extractLoop fire flame flame2 flux glow grinding hum largeCannon largeExplosion laser laserbeam laserbig laserblast lasercharge lasercharge2 lasershoot machine malignShoot mediumCannon message mineDeploy minebeam missile missileLarge missileLaunch missileSmall missileTrail mud noammo pew place plantBreak plasmaboom plasmadrop press pulse pulseBlast railgun rain release respawn respawning rockBreak sap shield shockBlast shoot shootAlt shootAltLong shootBig shootSmite shootSnap shotgun smelter spark spellLoop splash spray steam swish techloop thruster titanExplosion torch tractorbeam unlock wave wind wind2 wind3 windhowl none

依赖关系

您可以通过简单地在 mod.json 中添加其他模组的名称来为您的模组添加依赖关系:

dependencies: [
  other-mod-name
  not-a-mod
]

依赖关系的名称为小写,空格用 - 连字符替换,例如 Other MOD NamE 变为 other-mod-name

要引用其他模组的资产,您必须在资产前加上其他模组的名称:

  • other-mod-name-not-copper 将引用 other-mod-name 中的 not-copper
  • other-mod-name-angry-dagger 将引用 other-mod-name 中的 angry-dagger
  • not-a-mod-angry-dagger 将引用 not-a-mod 中的 angry-dagger

Bundles

模组的一个可选附加功能称为 bundles。Bundles 的主要用途是为您的内容提供翻译,但您也可以在英语中使用它们。这些是纯文本文件,放在 bundles/ 子目录中,应该命名为 bundle_ru.properties(用于俄语)。

此文件的内容非常简单:

block.example-mod-silver-wall.name = Серебряная Стена
block.example-mod-silver-wall.description = Стена из серебра.

如果您阅读了本指南的前几部分,您会立即发现:

  • <content type>.<mod name>-<content name>.name
  • <content type>.<mod name>-<content name>.description

使用您自己的自定义 bundle 行,您可以在脚本中使用任何您喜欢的键:

  • message.egg = 吃你的鸡蛋
  • randomline = 随机行

注意:

  • 模组/内容名称为小写并用连字符分隔。

内容类型列表:

item block bullet liquid status unit weather sector error planet team unitCommand unitStance

相对于语言的 bundle 后缀列表:

en be bg ca cs da de es et eu fi fil fr hu id_ID it ja ko lt nl nl_BE pl pt_BR pt_PT ro ru sr sv th tk tr uk_UA vi zh_CN zh_TW

GitHub

一旦您有了某种模组,您将希望实际分享它,您甚至可能想与其他人合作,为此您可以使用 GitHub。如果您完全不知道 Git(或 GitHub)是什么,那么您应该了解 GitHub Desktop,否则只需使用您喜欢的命令行工具或文本编辑器插件。

您只需了解如何在 GitHub 上打开存储库、在本地存储库中暂存和提交更改,以及将更改推送到 GitHub 存储库。一旦您的项目在 GitHub 上,有三种方式可以分享它:

  • 使用端点,例如 Anuken/MindustryJavaModTemplate,然后可以在游戏内 GitHub 界面中输入该内容,这将下载它;
  • 使用 zip 文件,例如 https://github.com/Anuken/MindustryJavaModTemplate/archive/master.zip,这将下载存储库作为 zip 文件,并放入模组目录(无需解压);
  • 在您的存储库上添加主题/标签 mindustry-mod,这将使其添加到主题搜索和 Mod scraper

常见问题

  • 游戏中的 time 是通过 ticks 计算的;
  • ticks 有时称为 frames 被假定为 1/60 秒;
  • tilesize 在内部为 8 单位;
  • 要根据 lifetimespeed 计算范围,您可以使用 lifetime * speed = range
  • 抽象 什么是 abstract?您需要了解的关于抽象类型的所有内容是它们不能被实例化/初始化。如果您这样做,您将收到某种 "初始化异常"
  • 什么是 NullPointerException?这是一个错误消息,表示某个字段为 null,但不应该为 null,这意味着某个必需字段可能缺失;
  • bleeding-edge 什么是 bleeding-edge?这是 Mindustry 的开发版本,特别是指 GitHub 主分支。bleeding-edge 上的更改通常会在下一个版本中进入 Mindustry。