本篇教程由作者设定未经允许禁止转载。

模块化机械:社区版 从入门到入土 —— Part.3.1 高级配方运用

本篇教程皆在展示模块化机械:社区版的 CrT 的高级可用 API。

本教程主要使用的模组为模块化机械:社区版 - 1.11.1-r33、CraftTweaker

注意:本教程内容可能随时都有变化,请仔细对照本教程使用的模组版本,以免引起模组更新导致莫名其妙的报错问题。

教程目录:

  • Part.1 基本机械创建

  • Part.2 基本配方创建

  • Part.3.1 高级配方运用(当前)

  • Part 3.2 配方适配器 RecipeAdapter(未完成)

  • Part.3.3 机械事件系统(未完成)

  • Part.4.1 并行配方处理(未完成)

  • Part.4.2 工厂系统(未完成)

  • Part.4.3 工厂事件系统(未完成)

  • Part.4.4 智能数据接口(未完成)

  • Part.4.5 单方块 / 多方块机械升级(未完成)

  • Part.4.6 自定义 GUI 信息(未完成)

  • Part.5 配置文件解析(未完成)

环境准备

本教程强烈推荐使用 Visual Studio Code(以下简称 VSCode),可以大大减少你的魔改工作量。

使用 VSCode,你可以利用它的强大的功能来更快的完成复杂的操作,同时拥有代码提示,大大减少代码阅读难度和出错率,同时可以安装插件来扩展功能,使其更加强大。

阅读本教程即代表你已熟悉 ZenScript 的大部分高级运用,并且已经了解基本的机械创建与配方创建。

安装模组

如果你已安装 CraftTweaker 和模块化机械本体且已启动游戏,你可以跳过此段描述。

要创建配方,你需要使用 CraftTweaker(任意版本)。

要查看创建的配方,你需要使用 JEI(任意版本)。

高级 API

高级 API 允许你使用 CraftTweaker 来创建更丰富的机械机制和功能。

RecipeModifierBuilder

RecipeModifierBuilder 可以用来构建 RecipeModifier,而 RecipeModifier 是用来动态修改配方输入输出的关键。

导包:

import mods.modularmachinery.RecipeModifierBuilder;

RecipeModifierBuilder 提供了两种用法:

RecipeModifierBuilder.newBuilder()

//type = 要应用 RecipeModifier 的类型
//ioTypeStr = RecipeModifier 会应用到输入还是输出?("input" 为输入,"output" 为输出)
//value = RecipeModifier 的数值 (类型为 float)
//operation = RecipeModifier 数值会用哪种方法计算?(0 为加,1 为乘,默认 0)
//affectChance = RecipeModifier 是否应用到概率上?(true 为应用,false 为不应用,默认 false)
RecipeModifierBuilder.create(String type, String ioTypeStr, float value, int operation, boolean affectChance)

两种方法最终创建的内容都相同。

RecipeModifierBuilder 用例:

//Builder 模式
RecipeModifierBuilder.newBuilder()
    # 定义要应用 RecipeModifier 的类型
    .setRequirementType("modularmachinery:energy")
    # 这个 RecipeModifier 会应用到输入还是输出?("input" 为输入,"output" 为输出)
    .setIOType("input")
    # RecipeModifier 数值会用哪种方法计算?(0 为加,1 为乘,默认 0)
    .setOperation(1)
    # 定义 RecipeModifier 的数值 (类型为 float)
    .setValue(0.1)
    # RecipeModifier 是否应用到概率上?(true 为应用,false 为不应用,默认 false)
    .isAffectChance(false)
    # 构建 RecipeModifier,同时检查上方参数的合法性
    .build();

//快速构建模式
RecipeModifierBuilder.create("modularmachinery:energy", "input", 0.1, 1, false).setValue(0).build();
                                                                                ^
                                                                              //create() 后方也可以调用上方方法内容

IMachineController

IMachineController 是 MMCE 专门为 CraftTweaker 提供的接口,它提供了大量直接对控制器进行操作的功能。

IMachineController 可以通过绝大部分机械事件获取。

接口方法列表:

ZenGetter:

//获取控制器所在的世界。
IWorld world

//获取控制器方块状态。
IBlockState blockState

//获取控制器方块的位置。
IBlockPos pos

//获取机械在当前世界运行的时间(非世界时间,进入退出世界会被重置)
int ticksExisted

//获取控制器正在运行的配方列表,始终会返回一个数组(不会返回 null)。
//普通机械始终会返回一个大小为 1 的数组(但是内容有可能是 null),工厂则会返回任意大小的数组且所有内容非 null(可能会返回空数组)。
ActiveMachineRecipe[] activeRecipeList

//机器是否在运行,如果运行返回 true,反之 false。
boolean isWorking

//控制器形成的机械结构注册名(例如:"modularmachinery:machine_1"),如果为形成结构则返回 null。
//注意:是 "modularmachinery:machine_1" 而不是 "machine_1"!
String formedMachineName

//获取自定义数据,ZenScript 可以用来存储数据,且数据在游戏关闭时会被保存在 NBT 内。
IData customData

//获取控制器绑定的所有智能数据接口数据
//此方法会返回一组智能数据接口的内部数据,如果没有则为空数组,但绝不会为 null
SmartInterfaceData[] smartInterfaceDataList

//获取控制器找到的机械升级
//注:返回的是一组字符串数组,内容为机械升级的注册名。
String[] foundModifiers

ZenSetter:

//保存自定义数据,当获取的自定义数据被更改时需要调用此方法。
IData customData

//覆盖控制器当前的状态消息
String statusMessage

ZenMethod:

//向控制器添加一个自定义名称的 RecipeModifier,并且会被同步到正在运行的配方上。
void addModifier(String key, RecipeModifier modifier);

//向控制器删除对应名称的 RecipeModifier。
void removeModifier(String key);

//检查控制器是否已存在对应名称的 RecipeModifier,true 为存在,反之 false。
boolean hasModifier(String key);

//获取控制器绑定的指定智能数据接口数据。
//返回值可能为 null。
SmartInterfaceData getSmartInterfaceData(String type);

//获取机械中是否已找到指定的注册名的机械升级。
boolean hasModifierReplacement(String modifierName);
高级 CrT 配方方法大全

杂项:

//设置配方预览时显示的 NBT,不影响配方 NBT 匹配
setPreViewNBT(IData nbt)

# 例
addItemInput(<botania:terrapick>).setPreViewNBT({mana: 100000})

//为配方添加 JEI 提示
addRecipeTooltip(String... tooltips)

# 例(支持一次性传入多个提示)(注:不支持未本地化名,如需要本地化,请自行处理未本地化名)
addRecipeTooltip("输出有概率翻倍。", "有概率不消耗能量。")

催化剂:

催化剂是一种特殊的物品输入,它可以在检查配方并符合要求时给目标配方添加一组半永久性的 RecipeModifier,并且是可选输入。

//添加催化剂输入
//tooltips = JEI 鼠标提示,为数组,可以传入多个
//modifiers = 配方修改器,为数组,可以传入多个
addCatalystInput(IIngredient input, String[] tooltips, RecipeModifierBuilder[] modifiers)

# 例
addCatalystInput(<avaritia:resource:5>, ["无尽催化剂作为催化剂输入时,能量消耗降低 90%"], [RecipeModifierBuilder.create("modularmachinery:energy", "input", 0.1, 1, false)]);

自定义 NBT 检查器:

自定义 NBT 检查器允许你通过 ZenScript 来检查物品是否匹配相应的 NBT。

用法:

//设置自定义 NBT 检查器(仅限物品类型输入)
setNBTChecker(IMachineController controller, AdvancedItemNBTChecker checker)

# 例
import crafttweaker.item.IItemStack;
import mods.modularmachinery.IMachineController;

addItemInput(<botania:terrapick>).setNBTChecker(function(ctrl as IMachineController, item as IItemStack) {
    val nbt = item.tag.asMap();
    if (nbt["mana"].asInt() > 1919810) {
        # 返回 true 即为匹配
        return true;
    } else {
        # 返回 false 即为不匹配
        return false;
    }
})

自定义物品修改器:

自定义物品修改器允许你通过 ZenScript 来修改物品的输入输出内容。

//设置自定义物品修改器(仅限物品类型输入输出)
addItemModifier(IMachineController controller, AdvancedItemModifier modifier)

# 例
import crafttweaker.item.IItemStack;
import mods.modularmachinery.IMachineController;

addItemInput(<botania:manaresource:4>).addItemModifier(function(ctrl as IMachineController, oldItem as IItemStack) as IItemStack {
    if (oldItem.amount >= 2) {
        # 返回新的物品
        return <botania:manaresource:4> * 4;
    } else {
        # 返回新的物品
        return <botania:manaresource:4> * 2;
    }
})