配料
Ingredient 是基于物品的输入谓词处理器,检查某个 ItemStack 是否满足作为配方有效输入的条件。所有接收输入的原版配方都使用一个 Ingredient 或一组最终合并为一个 Ingredient 的配料。
原创说明图,依据 Forge 1.21.x 官方文档 绘制。
自定义配料
将 type 设为配料序列化器名称即可指定自定义配料,复合配料除外。未指定类型时默认为原版 minecraft:item。自定义配料也可以方便地用于数据生成。
Forge 类型
Forge 提供若干额外的 Ingredient 类型。
CompoundIngredient
复合配料取代配方中的配料列表写法,功能相同:作为集合 OR,传入的堆至少要匹配其中一个配料。此更改让自定义配料在列表中正确工作,因此无需指定类型。
带注释和省略号的示例用于说明结构;实际 JSON 文件需移除注释并补全内容。
// 某个输入:至少一个配料必须匹配
[
{ /* 配料 */ },
{ "type": "examplemod:example_ingredient" } // 自定义配料
]
StrictNBTIngredient
严格比较 ItemStack 的物品、损伤及共享标签(由 IForgeItem#getShareTag 定义)是否完全相等。类型为 forge:nbt。
{
"type": "forge:nbt",
"item": "examplemod:example_item",
"nbt": { /* 添加 NBT 数据,必须与堆完全一致 */ }
}
PartialNBTIngredient
这是 StrictNBTIngredient 的宽松版本:比较一个或一组物品,以及共享标签中指定的键。类型为 forge:partial_nbt。
{
"type": "forge:partial_nbt",
// 必须指定 item 或 items;如果两者都有,只读取 item
"item": "examplemod:example_item",
"items": ["examplemod:example_item", "examplemod:example_item2"],
"nbt": {
// 只比较 key1 和 key2,堆中的其他键不检查
"key1": "data1",
"key2": { /* 数据 2 */ }
}
}
IntersectionIngredient
作为集合 AND,传入的堆必须匹配所有给定配料,且至少提供两个。类型为 forge:intersection。
{
"type": "forge:intersection",
// 所有配料都必须返回 true
"children": [ { /* 配料 1 */ }, { /* 配料 2 */ } /* ... */ ]
}
DifferenceIngredient
作为集合减法,传入的堆必须匹配第一个配料,但不能匹配第二个。类型为 forge:difference。
{
"type": "forge:difference",
"base": { /* 堆所属的配料 */ },
"subtracted": { /* 堆不属于的配料 */ }
}
创建自定义配料
为创建的 Ingredient 子类实现 IIngredientSerializer。建议继承 AbstractIngredient,因为它提供便于实现的抽象。
Ingredient 子类
需要实现三个重要方法:
| 方法 | 说明 |
|---|---|
getSerializer |
返回用于读写配料的序列化器。 |
test |
输入对此配料有效时返回 true。 |
isSimple |
根据堆的标签匹配时返回 false。AbstractIngredient 子类需定义此行为,Ingredient 子类默认返回 true。 |
其他定义的方法留给读者根据子类需要自行使用。
IIngredientSerializer
子类必须实现三个方法:parse(JSON)将 JsonObject 转为 Ingredient;parse(网络)读取缓冲区并解码配料;write 将配料写入网络缓冲区。
此外,Ingredient 子类应实现 Ingredient#toJson 以用于数据生成。AbstractIngredient 将 #toJson 声明为抽象方法,要求实现。
声明静态实例保存初始化后的序列化器,然后在 RecipeSerializer 的 RegisterEvent 或 FMLCommonSetupEvent 期间使用 CraftingHelper#register 注册。配料子类的 Ingredient#getSerializer 返回该静态实例。
// 在某个序列化器类中
public static final ExampleIngredientSerializer INSTANCE = new ExampleIngredientSerializer();
// 在某个处理器类中
public void registerSerializers(RegisterEvent event) {
event.register(ForgeRegistries.Keys.RECIPE_SERIALIZERS,
helper -> CraftingHelper.register(registryName, INSTANCE)
);
}
// 在某个配料子类中
@Override
public IIngredientSerializer<? extends Ingredient> getSerializer() {
return INSTANCE;
}
提示:如果在
FMLCommonSetupEvent注册配料序列化器,必须通过FMLCommonSetupEvent#enqueueWork加入同步工作队列,因为CraftingHelper#register不是线程安全的。
原文:Ingredients。