动态配方(1.18) - mczph/Multiblocked-Wiki-zh_cn GitHub Wiki

本教程适用于minecraft 1.18版本的multiublocked

动态配方(Dynamic Recipes)

“动态”表明该配方为可基于多方块结构中的方块与其他条件从头创建或进行调整的配方。

它能做什么?

  • 制作可被升级和调整配方条件的机器,像格雷科技5非官方版的大型化学反应器那样(移除配方中一些特殊条件)。
  • 调整配方输入、输出、持续时间(超频)与执行条件。

动态配方处理器(Dynamic Recipe Handler)

所有对配方的调整都基于此处理器(Handler),有两种方法获取该处理器:通过事件或使用反射。目前仅SearchRecipeEvent和SetupRecipeEvent提供了动态配方处理器,配方如下(放在服务端脚本里)。

onEvent('mbd.setup_recipe.tester.updatable', event => {
    let handler = event.getHandlerFromRecipe()//含原配方数据的处理器
    //具体处理
})

onEvent('mbd.search_recipe.tester.updatable', event => {
    let handler = event.getHandler()//无任何数据的处理器
    //具体处理
})

注意1: 通常,SetupRecipeEvent用于超频之类的操作,而非调整配方输入,因为仅当满足原配方的条件时被调整的配方才会被执行,但是您可以在这里调整配方输出。 注意2:

//别忘了这行!除非您想调整该动态配方。
//检查其是否为动态配方,
if (event.getRecipeLogic().dynamic) return
//处理配方

调整

注意: 动态配方处理器有大部分当KubeJS添加配方时可调用的函数。您还可以添加新输入和条件。

通用处理器(Universal Handler):

名称 参数 用法 描述
inputHandler 配方输入映射表 handler.inputHandler(map =>{//调整该映射表}) 用于操作配方输入,使用map.get("Capability名称")来获取一个"左侧"为MultiblockCapability对象,"右侧"为相应类型的输出的键值对。例如:map.get("item").getRight()可获取(配方中)物品类型的输入。
tickInputHandler 配方每tick输入的输入映射表 handler.tickInputHandler(map =>{//调整该映射表}) 类似于inputHandler,但是用于调整每tick都输入的输入。
outputHandler 配方输出映射表 handler.outputHandler(map =>{//调整该映射表}) 类似于inputHandler,但是用于调整输出。

加法器与乘法器(Adder & Multiplier)

(译者注:部分未说明内容还请根据前文举一反三)

名称 用法 描述
inputAdder(boolean perTick, String capability, double addition) handler.inputAdder(false, "item", 10) 增加相应类型capability输入的数量要求,或通过设置增加的数值为负来减少输入数量。
inputAdder(boolean perTick, String capability, double addition, Predicate predicate) handler.inputAdder(false, "item", 10, content =>{}) 当该predicate建立时调整输入数量
inputMultiplier(boolean perTick, String capability, double multiplier) handler.inputMultiplier(false, "item", 2) 类似于inputAdder,但是是与参数相乘
inputMultiplier(boolean perTick, String capability, double multiplier, Predicate predicate) - -
outputAdder(boolean perTick, String capability, double addition) handler.outputHandler(false, "item", 2) -
outputAdder(boolean perTick, String capability, double addition, Predicate predicate) - -
outputMultiplier(boolean perTick, String capability, double multiplier) - -
outputMultiplier(boolean perTick, String capability, double addition, Predicate predicate) - -

移除器(Removers)

注意: 使用MbdRegistry.getCapability(Capability名称)来获取相应的Capability

名称 用法 描述
removeTypedInputs(boolean perTick, MultiblockCapability<?> capability) handler.removeTypedInputs(false,MbdRegistry.getCapability("item") 用于删除特定类型的输入
removeTypedInputs(boolean perTick, MultiblockCapability<?> capability, Predicate predicate) handler.removeTypedInputs(false, MbdRegistry.getCapability('item'), content => {return content.chance < 1}) 移除特定类型的符合谓词的输入
removeTypedOutputs(boolean perTick, MultiblockCapability<?> capability) handler.removeTypedOutputs(false,MbdRegistry.getCapability("item") 输出的移除器
removeTypedOutputs(boolean perTick, MultiblockCapability<?> capability, Predicate predicate) - -
removeAllConditions handler.removeAllConditions() 从该配方中移除所有条件
removeTypeCondition(String type) handler.remove("block") 移除特定类型的条件
removeDimension(ResourceLocation dimension) - 移除一个维度条件
removeBiome(ResourceLocation biome) - 移除一个生物群系条件
removeRain(float level) - 移除下雨条件
removeThunder(float level) - 移除雷暴条件
removePosY(int min, int max) - 移除Y轴位置条件(高度)
removeBlock(BlockState blockState, int count) - 移除一个方块条件
removeBlock(BlockState blockState) - 移除一个方块条件

示例

本示例展示内容为: 若结构中有一个下界合金块,它会改变输出概率,将所有配方的输出概率乘2;当有一个钻石块则减少配方时间;当有一个金块时在输出中添加金锭。

onEvent('mbd.setup_recipe.tester.updatable', event => {
    //Don't forget this line unless you want to modify the dynamic recipe!
    //check if this is a dynamic recipe,
    if (event.getRecipeLogic().dynamic) return
    console.info("Ok,this a updatable multiblock machine. I'm going to change the recipe")
    let componentData = event.getComponentData()
    let goldAmount = componentData.get(Block.getBlock('minecraft:gold_block').defaultBlockState())
    let diamondAmount = componentData.get(Block.getBlock('minecraft:diamond_block').defaultBlockState())
    let netheriteAmount = componentData.get(Block.getBlock('minecraft:netherite_block').defaultBlockState())
    let handler = event.getHandlerFromRecipe()
    let duration = diamondAmount > 0 ? event.getRecipe().duration / (diamondAmount * 2) : event.getRecipe().duration;
    if (netheriteAmount > 0) {
        handler.outputHandler(map => {
            let contents = map.get('item').getRight()
            for (let i = 0; i < contents.size(); i++) {
                var content = contents.get(i)
                var nextChance = content.chance * 2
                nextChance = nextChance > 1 ? 1 : nextChance
                content.chance = nextChance
            }
        })
    }
    if (goldAmount > 0) {
        handler.outputItems({'item': 'minecraft:gold_ingot', 'count': goldAmount * 2})
    }
    handler.duration(duration)
    event.setRecipe(handler.apply())
})