简介

自 Croparia IF 0.2.1 起,一种新的基于文件模板来对作物定义对象进行批量处理的 API 被添加:DataGenerator。模组自带的作物种子配方、作物方块的掉落物战利品表、作物果实到材料的工作台配方以及一些其他模组的兼容配方都是通过这个 API 批量生成的。

它的生成行为会注入到进入存档后的每一次数据包加载。

DataGenerator 的文件定义默认位于 {游戏目录}/config/croparia/generators,可通过配置文件中的 packPath 修改。

定义 DataGenerator

1、创建文件

在 DataGenerator 的存储目录中,创建一个文本文件。文件名随意。

2、确认输出位置

首先你要借助元标签为每一个作物定义一个相对数据包的输出位置。以模组提供用于生成 作物果实到材料物品的配方 的默认 DataGenerator 文件:material(1.18.2)为例,它的内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@enabled=true
@path=croparia/recipes/crafting/material/{name}.json
@dependency=minecraft
{
  "type": "minecraft:crafting_shapeless",
  "ingredients": [
    {
      "item": "{fruit}"
    }
  ],
  "result": {
    "item": "{result}",
    "count": {result_count.2}
  }
}

文件开头处,@path=... 定义了每一个作物后输出的位置。在这个例子中,它表示 {游戏目录}/config/croparia/data/croparia/recipes/material/ 目录下,生成的文件名以每一个作物的名称为文件名,后缀为 .json。其中,{name}占位符,我们稍后会详细解释。

你也许也注意到这个例子中还有其他元标签,它们并非必须,稍后我们详细解释。

3、基于占位符创建模板

接下来,我们根据想要创建的配方类型,在元标签下另起一行,像正常编写配方 json 一样先将配方大致的结构写出来。然后,我们需要借助占位符来为配方设置一些作物相关的值。

占位符用于文段中标记一个位置,稍后 DataGenerator API 会根据占位符的类型与批量处理的作物定义将它们替换成输出值。

比如,在步骤 2 中,我们使用的 {name} 就是一个占位符,它标记了该位置会被作物的名称所替换。同理,上文的例子中,其他形如 {xxx} 的字段也是占位符

可用的占位符如下:

  • {color}: 十进制的作物颜色;

  • {color_hex}: 十六进制的作物颜色。注意它不会带有 "#" 或 "0x" 的前缀;

  • {croparia}: 制作作物种子所需要的基础魔种的物品 ID;

  • {croparia_path}: 与 {croparia} 类似,但不包含命名空间;

  • {material_type}: 作物的材料定义类型=。如果定义的是指定物品 ID 则返回 item,如果是物品标签则返回 tag;

  • {material}: 作物的材料定义。注意不论是否为物品标签,它都会返回一个不包含 # 前缀的 ID;

  • {material_path}: 与 {material} 类似,但不包含命名空间;

  • {material_taggable}: 与 {material} 类似,但如果材料定义是物品标签的话会带有 # 前缀;

  • {name}: 作物定义名。注意它是作物定义的 name 字段,而非游戏中显示的名称;

  • {type}: 作物类型(小写);

  • {tier}: 作物等阶,决定了作物种子使用哪一级的基础魔种;

  • {seed}: 作物种子 ID;

  • {seed_path}: 没有命名空间的作物种子 ID;

  • {fruit}: 作物果实 ID;

  • {fruit_path}: 没有命名空间的作物果实 ID;

  • {crop_block}: 作物方块 ID;

  • {crop_block_path}: 没有命名空间的作物方块 ID;

  • {result}: 作物的材料定义对应的物品,注意它永远是一个物品而非标签(如果材料定义了一个物品标签,那么这里会返回这个标签所包含第一个物品);

  • {result_count.<整数>}: 基于 {result} 对应物品的数量组件,会根据这个物品的最大堆叠上限进行限制;

  • {result_path}: 没有命名空间的 {result};

  • {translation_key}: 作物定义的物品翻译键值;

  • {translation.<language_name>}: 给出对应语言在作物定义中的自定义翻译,注意它与实际游戏显示的翻译名可能不一致。

4、元标签

元标签是用于定义 DataGenerator 的一些属性,它必须在文件的开头定义且由 @ 作为开头,但顺序可以随意。

步骤 2 中我们使用的 @path=... 就是一个元标签。它是必要的。除此之外,还有一些可选的元标签

  • @enabled=<true|false>:表示该 DataGenerator 是否启用;

  • @dependency=<模组 ID>:表示该 DataGenerator 仅在指定模组加载后才会启用;

  • @crops=<作物定义名>:表示该 DataGenerator 仅为指定的作物创建数据;如果是多个作物则需要用逗号隔开。

使用 KubeJS 添加 DataGenerator

在确保你已经阅读并了解了 DataGenerator 的基本属性后,再参照如下 JS 代码为 Croparia IF 添加 DataGenerator:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// 1. 获取基类
const DataGeneratorCreator = Java.loadClass("cool.muyucloud.croparia.kubejs.DataGeneratorCreator");  // 如果是1.18及以前的版本,请使用 java(...)
// 2. 添加 DataGenerator
/**
 * 示例:创建并添加 DataGenerator
 *
 * @param enabled    元标签 @enabled,提供 null 表示默认启用
 * @param path       元标签 @path
 * @param dependency 元标签 @dependency,提供 null 以表示无模组依赖
 * @param crops      元标签 @crops,提供空列表表示支持所有作物
 * @param template   数据模板
*/
DataGeneratorCreator.create(true, "croparia/recipe/example/{name}.json", "minecraft", ["example", "example2"], `{
  "type": "minecraft:crafting_shapeless",
  "ingredients": [
    {
      "item": "{fruit}"
    }
  ],
  "result": {
    "item": "{result}",
    "count": {result_count.2}
  }
}`)

一些常见问题

如何禁用或修改默认的 DataGenerator?

默认提供的 DataGenerator 仅会在它们不存在的时候(被移动、修改文件名或删除)时重新创建,而不会去修改已有的文件。所以你对默认 DataGenerator 的修改都会被保留。(建议保持文件的格式合法性,尽管非法的格式不会导致严重的错误)

想要禁用它们,在文件开头添加 @enabled=false,或是将已经存在的 @enabled=true 修改为 @enabled=false 即可。

如何仅对部分作物更改已有的 DataGenerator?

在设计整合包的时候,可能会遇到诸如“只修改一部分作物种子的合成配方,其他作物不变”的问题。如果需要变更的作物不多的话,可以考虑用数据包定义同名文件即可。

在 Croparia IF 0.2.2 以后,DataGenerator API 不再对元标签 @path 进行重复性检查,并会按照顺序(先按照文件系统的顺序执行文件定义的 DataGenerator,然后按照代码顺序执行 KubeJS 中定义的 DataGenerator)生成并覆盖数据文件,所以你还可以通过定义新 DataGenerator 来对原有数据生成进行覆盖。

你只需要:

  • 新建一个 DataGenerator,如果通过文件定义,则需要保证文件名在文件系统中的排序位于你想要覆盖的 DataGenerator 之后(以刚刚提到的情形为例,你需要让你的文件在 seeds,即默认的种子配方生成, 之后);

  • 在你新建的 DataGenerator 中,在元标签 @crops 中指名你想要修改的作物;

  • 不需要严格遵循想要覆盖的 DataGenerator 的格式,除非你确实需要这么做。

DataGenerator 似乎只能为每一个作物创建单独的文件?

是的,这也意味着例如物品标签等具有集合特征的文件无法被其生成(当然,你也可以为每一个作物生成一个单独的标签文件)。此外,它仅支持生成数据包相关的文件,如果要生成资源包相关的文件,你需要在生成后手动打包成资源包。