配方简介

配方

配方是在 Minecraft 世界中将一定数量的对象转化为其他对象的方式。原版系统只处理物品转换,但整个系统可以扩展为使用程序员创建的任何对象。

配方加载与查询流程:配方 JSON 加载到 RecipeManager,查询提供配方类型、输入和世界上下文,经 matches 检查后,getRecipeFor 返回首个匹配配方,getRecipesFor 返回所有匹配配方。

原创说明图,依据 Forge 1.21.x 官方文档 绘制。

数据驱动配方

原版大多数配方实现由 JSON 数据驱动,因此创建新配方不需要 Mod,只需要数据包。如何创建配方并放入 Mod 的 resources 文件夹,参见 Minecraft Wiki。

完成进度后,配方可作为奖励在配方书中获得。配方进度总是以 minecraft:recipes/root 为父级,因此不会出现在进度界面。默认条件检查用户是否使用过配方一次,或通过 /recipe 等命令获得配方:

带注释和省略号的示例用于说明结构;实际 JSON 文件需移除注释并补全内容。

// 在某个配方进度 JSON 中
"has_the_recipe": { // 条件标签
  // 使用 examplemod:example_recipe 时成功
  "trigger": "minecraft:recipe_unlocked",
  "conditions": { "recipe": "examplemod:example_recipe" }
},
// ...
"requirements": [
  ["has_the_recipe" /* ...其他以 OR 组合来解锁配方的条件标签 */]
]

数据驱动配方及解锁它的进度可通过 RecipeProvider 生成。

配方管理器

配方由 RecipeManager 加载和保存,获取可用配方的操作由其处理。两个重要方法:

方法 说明
getRecipeFor 获取匹配当前输入的第一个配方。
getRecipesFor 获取匹配当前输入的所有配方。

每个方法接收表示使用配方方式(合成、烧炼等)的 RecipeType、保存输入配置的 Container,以及当前世界;世界与容器一起传给 Recipe#matches。

重要:Forge 提供 RecipeWrapper 工具类,它扩展 Container,用于包装 IItemHandler 并将其传给需要 Container 参数的方法。

// 在具有 IItemHandlerModifiable handler 的方法中
recipeManger.getRecipeFor(RecipeType.CRAFTING, new RecipeWrapper(handler), level);

附加功能

Forge 对配方格式及实现提供额外行为,以便更好地控制系统。

配方 ItemStack 结果

除 minecraft:stonecutting 配方外,所有原版配方序列化器都扩展了 result 标签,使其可接收表示完整 ItemStack 的 JsonObject,而非某些情况下仅有的物品名称和数量。

// 在某个配方 JSON 中
"result": {
  "item": "examplemod:example_item", // 作为结果给出的注册物品名称
  "count": 4, // 返回的物品数量
  "nbt": { // 堆的标签数据,也可以是字符串
    // 在此添加标签数据
  }
}

nbt 也可为包含字符串化 NBT(SNBT)的字符串,用于无法正确表示为 JSON 对象的数据,例如 IntArrayTag。

条件配方

配方及其解锁进度可以根据现有信息(Mod 是否加载、物品是否存在等)条件加载并使用默认值。

更大的合成网格

原版默认将合成网格的最大宽高设为 3×3。可在 FMLCommonSetupEvent 中调用 ShapedRecipe#setCraftingSize 并传入新宽高来扩展。

警告:ShapedRecipe#setCraftingSize 不是线程安全的,必须通过 FMLCommonSetupEvent#enqueueWork 加入同步工作队列。

较大的配方网格可以数据生成。

配料类型

Forge 添加了额外的配料类型,使配方输入能够检查标签数据,或将多个配料组合为一个输入检查器。

原文:Recipes。