编辑配方 (Editing Recipes)

预计阅读时间: 14 分钟

添加、删除和修改配方

配方、回调函数和你 (Recipes, Callbacks, and You)

配方事件可用于添加、删除或替换配方。

任何修改配方的脚本都应放在 server_scripts/ 文件夹中,并且可以随时使用 /reload 命令重新加载。

任何对配方的修改都应该在 recipes 事件的上下文中进行。这意味着我们需要为 ServerEvents.recipes 事件注册一个"事件监听器",并提供一些代码在游戏准备好修改配方时执行。以下是如何告诉KubeJS在配方时间执行一些代码:

1.19.2+ 1.18.2

/* 
 * ServerEvents.recipes(callback) 是一个接受另一个函数(称为"回调函数")作为参数的函数。
 * 回调函数在服务器处理配方时运行,然后我们可以进行自己的更改。
 * 当回调函数运行时,也被称为事件"触发"。
*/
// 监听"recipes"服务器事件。
ServerEvents.recipes(event => {
  // 您可以用任何喜欢的名称替换 `event`,
  // 只要在回调函数内也更改它即可!

  // 花括号内的这部分是回调函数。
  // 您可以在这里修改任意数量的配方,
  // 无需再次使用 ServerEvents.recipes()。

  console.log('Hello! The recipe event has fired!')
})
/*
 * onEvent('recipes', callback) 是一个接受另一个函数(称为"回调函数")作为参数的函数。
 * 回调函数在服务器处理配方时运行,然后我们可以进行自己的更改。
 * 当回调函数运行时,也被称为事件"触发"。
*/

// 监听"recipes"服务器事件。
onEvent('recipes', event => {
  // 您可以用任何喜欢的名称替换 `event`,
  // 只要在回调函数内也更改它即可!

  // 花括号内的这部分是回调函数。
  // 您可以在这里修改任意数量的配方,
  // 无需再次使用 onEvent()。

  console.log('Hello! The recipe event has fired!')
})

在接下来的部分中,您可以看到在回调函数中应该放入什么内容。

添加配方 (Adding Recipes)

以下所有代码都应该放在您的配方回调函数内部

有形状配方 (Shaped)

有形状配方通过 event.shaped() 方法添加。有形状配方的成分必须按照特定的顺序和形状排列才能匹配玩家的输入。event.shaped() 的参数是:

  1. 输出物品,可以有1-64的数量

  2. 一个数组(最大长度3)表示合成台的行,用字符串表示(最大长度3)。空格表示没有物品的槽位,字母表示物品。字母不必有特定含义;您可以在下一个参数中解释它们的含义。

  3. 一个将字母映射到物品的对象,如 {letter: item}。输入物品的数量必须为1。

如果您想在合成网格上强制严格位置或禁用镜像,请参阅自定义配方的方法。

event.shaped(
  Item.of('minecraft:stone', 3), // 参数1: 输出
  [
    'A B',
    ' C ', // 参数2: 形状(字符串数组)
    'B A'
  ],
  {
    A: 'minecraft:andesite',
    B: 'minecraft:diorite',  // 参数3: 映射对象
    C: 'minecraft:granite'
  }
)

无形状配方 (Shapeless)

无形状配方通过 event.shapeless() 方法添加。玩家可以将无形状配方的成分放在网格上的任何位置,仍然可以合成。event.shapeless() 的参数是:

  1. 输出物品

  2. 输入物品数组。输入物品的总数最多为9个。

event.shapeless(
  Item.of('minecraft:dandelion', 3), // 参数1: 输出
  [
    'minecraft:bone_meal',
    'minecraft:yellow_dye', 	       // 参数2: 输入数组
    '3x minecraft:ender_pearl'
  ]
)

锻造配方 (Smithing)

锻造配方有2或3个输入(取决于Minecraft版本,见下文)和一个输出,通过 event.smithing() 方法添加。锻造配方在锻造台中合成。

1.20+ 1.19.2及以下

event.smithing(
  'minecraft:netherite_ingot',                     // 参数1: 输出
  'minecraft:netherite_upgrade_smithing_template', // 参数2: 锻造模板
  'minecraft:iron_ingot',                          // 参数3: 要升级的物品
  'minecraft:black_dye'                            // 参数4: 升级物品
)
event.smithing(
  'minecraft:netherite_ingot',  // 参数1: 输出
  'minecraft:iron_ingot',       // 参数2: 要升级的物品
  'minecraft:black_dye'         // 参数3: 升级物品
)

熔炼与烹饪 (Smelting & Cooking)

烹饪配方都非常相似,接受一个输入(单个物品)并给出一个输出(最多可以是64个相同物品)。在此配方事件中无法更改燃料,应该通过标签来完成。

  • 熔炼配方通过 event.smelting() 添加,需要普通熔炉。

  • 高炉配方通过 event.blasting() 添加,需要高炉。

  • 烟熏配方通过 event.smoking() 添加,需要烟熏炉。

  • 篝火烹饪配方通过 event.campfireCooking() 添加,需要篝火。

获得的经验值通过追加 .xp() 设置。烹饪时间(以刻为单位)通过追加 .cookingTime() 设置。它们也可以在输入和输出之后指定。

// 在熔炉中将1个石头烧制成3个沙砾:
event.smelting('3x minecraft:gravel', 'minecraft:stone')

// 在高炉中将1个铁锭烧制成10个铁粒:
event.blasting('10x minecraft:iron_nugget', 'minecraft:iron_ingot')

// 在烟熏炉中将玻璃熏制成染色玻璃并给予0.35经验值:
event.smoking('minecraft:tinted_glass', 'minecraft:glass').xp(0.35)

// 在篝火上将木棍烧成火把,给予0.35经验值,耗时30秒:
event.campfireCooking('minecraft:torch', 'minecraft:stick', 0.35, 600)

切石机配方 (Stonecutting)

与烹饪配方一样,切石机配方非常简单,有一个输入(单个物品)和一个输出(最多可以是64个相同物品)。它们通过 event.stonecutting() 方法添加。

// 允许在切石机上从任何木板切出3根木棍
event.stonecutting('3x minecraft:stick', '#minecraft:planks')

自定义/模组JSON配方 (Custom/Modded JSON recipes)

如果模组支持数据包配方,您可以在没有任何插件模组支持的情况下为其添加配方!不幸的是,我们无法给出具体建议,因为每个模组的布局都不同,但如果模组有GitHub(大多数都有!)或其他源代码,您可以在 /src/generated/resources/data/<modname>/recipes/ 中找到相关的JSON文件。否则,您可以通过解压模组的 .jar 文件找到它。

以下是添加 Farmer's Delight 砧板配方的示例,它定义了一个输入、输出和工具,直接来自他们的GitHub。显然,您可以替换这里的任何物品来制作自己的配方!

// 在砧板上切蛋糕!
event.custom({
  type: 'farmersdelight:cutting',
  ingredients: [
    { item: 'minecraft:cake' }
  ],
  tool: { tag: 'forge:tools/knives' },
  result: [
    { item: 'farmersdelight:cake_slice', count: 7 }
  ]
})

以下是 event.custom() 的另一个示例,用于制作 Tinkers' Construct 合金配方,它定义了输入、输出和温度,直接来自他们的GitHub(已移除条件):

// 添加来自 Tinkers' Construct 的熔融银金合金配方
event.custom({
  type: 'tconstruct:alloy',
  inputs: [
    { tag: 'forge:molten_gold', amount: 90 },
    { tag: 'forge:molten_silver', amount: 90 }
  ],
  result: { fluid: 'tconstruct:molten_electrum', amount: 180 },
  temperature: 760
})

删除配方 (Removing Recipes)

删除配方可以通过 event.remove() 方法完成。它接受1个参数:配方过滤器。过滤器是一组属性,用于确定选择哪些配方。您可以使用许多条件来选择配方:

  • 按输出物品 {output: '<item_id>'}

  • 按输入物品 {input: '<item_id>'}

  • 按模组 {mod: '<mod_id>'}

  • 按唯一配方ID {id: '<recipe_id>'}

  • 以上条件的组合:

    • 要求满足所有条件:{condition1: 'value', condition2: 'value2'}

    • 要求满足任何条件:[{condition_a: 'true'}, {condition_b: 'true'}]

    • 要求不满足条件:{not: {condition: 'requirement'}}

以下所有内容都可以正常放入您的配方回调函数中:

// 空条件删除所有配方(显然不推荐):
event.remove({})

// 删除所有输出为石镐的配方:
event.remove({ output: 'minecraft:stone_pickaxe' })

// 删除所有输出具有羊毛标签的配方:
event.remove({ output: '#minecraft:wool' })

// 删除所有输入具有红石粉标签的配方:
event.remove({ input: '#forge:dusts/redstone' })

// 删除 Farmer's Delight 的所有配方:
event.remove({ mod: 'farmersdelight' })

// 删除所有篝火烹饪配方:
event.remove({ type: 'minecraft:campfire_cooking' })

// 删除所有输出石头的配方,除了熔炼配方:
event.remove({ not: { type: 'minecraft:smelting' }, output: 'stone' })

// 删除输出熟鸡肉且在篝火上烹饪的配方:
event.remove({ output: 'minecraft:cooked_chicken', type: 'minecraft:campfire_cooking' })

// 删除任何输出 minecraft:iron_ingot 的高炉或熔炼配方:
event.remove([{ type: 'minecraft:smelting', output: 'minecraft:iron_ingot' }, { type: 'minecraft:blasting', output: 'minecraft:iron_ingot' }])

// 按ID删除配方。在这种情况下,data/minecraft/recipes/glowstone.json:
// 注意:配方ID和输出通常不同!
event.remove({ id: 'minecraft:glowstone' })

要找到配方的唯一ID,请使用 F3 + H 键打开高级提示(您将在聊天中看到通知),然后将鼠标悬停在 [+] 符号上(如果使用REI)或输出上(如果使用EMI或JEI)。

注意:当同时安装EMI和JEI时,JEI添加的配方的ID类似于 jei:/mod_id/pathway_1/pathway_2。实际配方ID将是 mod_id:pathway_1/pathway_2

修改和替换配方 (Modifying & Replacing Recipes)

您可以使用 event.replaceInput()event.replaceOutput() 批量修改支持的配方。它们各接受3个参数:

  1. 过滤器,类似于删除配方时使用的过滤器

  2. 要替换的成分

  3. 替换成分(可以是标签)

例如,假设您要删除所有木棍,并希望让人们用树苗来合成东西。在您的回调函数中,您可以放入:

1.21.1 1.20及以下

event.replaceInput(
  { input: 'minecraft:stick' },         // 参数1: 过滤器
  'minecraft:stick',                    // 参数2: 要替换的物品
  Ingredient.of('#minecraft:saplings')  // 参数3: 替换物品
  // 使用您想要使用的物品运行 /kjs hand 查看它们的所有标签。
)
event.replaceInput(
  { input: 'minecraft:stick' }, // 参数1: 过滤器
  'minecraft:stick',            // 参数2: 要替换的物品
  '#minecraft:saplings'         // 参数3: 替换物品
  // 注意:在Fabric上,带标签的流体成分不起作用,但带标签的物品起作用。
)

高级技巧 (Advanced Techniques)

辅助函数 (Helper functions)

您是否在制作许多相似的配方?感觉您在一遍又一遍地输入相同的文本?试试辅助函数!辅助函数通过只接受相关部分,然后为您执行重复的工作,可以在更少的空间内执行重复操作!

以下是一个辅助函数,它允许您通过在指定物品周围合成花盆来制作物品。

ServerEvents.recipes(event => {
  const potting = (output, pottedInput) => {
    event.shaped(output, [
      'BIB',
      ' B '
    ], {
      B: 'minecraft:brick',
      I: pottedInput
    })
  }

  // 现在我们可以制作许多'potting'配方,而无需一遍又一遍地输入那个大块!
  potting('kubejs:potted_snowball', 'minecraft:snowball')
  potting('kubejs:potted_lava', 'minecraft:lava_bucket')
  potting('minecraft:blast_furnace', 'minecraft:furnace')
})

循环 (Looping)

除了辅助函数,您还可以遍历数组对数组中的每个物品执行操作。

ServerEvents.recipes(event => {
	// 有一个有用的内置数组,包含所有染料颜色。
	// 可以使用 `forEach` 遍历它,因此您不需要为每种颜色指定单独的配方!
	Color.DYE.forEach(color => {
		event.shapeless(`kubejs:${color}_clay`, ['minecraft:clay', `minecraft:${color}_dye`])
	})

	// 您也可以创建自己的数组...
	const metals = ['iron', 'copper', 'gold', 'netherite']
	// ...并以相同的方式遍历它们!
	metals.forEach(metal => {
		event.shapeless(`kubejs:${metal}_plate`, [`minecraft:${metal}_ingot`, 'kubejs:hammer'])
			.damageIngredient('kubejs:hammer')
	})
})

脚本文件夹:server_scripts/