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

模块化机械:社区版 从入门到入土 —— Part.3.3 机械事件系统

本篇教程皆在展示模块化机械:社区版的 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 和模块化机械本体且已启动游戏,你可以跳过此段描述。

介绍

MMCE 提供的事件系统允许作者更方便的编写配方的高级机制,上手简单且易用。

截止 MMCE-R33 版本,目前共有 9 个配方事件和 4 个机械事件。

本篇教程将介绍普通机械控制器的 5 个配方事件与 4 个机械事件。

配方事件

所有的配方事件都是独立的,它们只会被指定注册名的配方触发。

配方事件共有 5 种,按照触发顺序分别为 RecipeCheckEvent(配方检查事件) -> RecipeStartEvent(配方开始事件) -> RecipePreTickEvent(配方预 Tick 事件) -> RecipePostTickEvent(配方完成 Tick 事件) -> RecipeFinishEvent(配方完成事件)。

其中 RecipePreTickEvent(配方预 Tick 事件)和 RecipePostTickEvent(配方完成 Tick 事件)会被触发多次

这些事件只能通过 RecipePrimer(配方构建器)添加。


通用 ZenGetter

所有的配方事件都可以使用这些方法。

//获取事件对应的机械配方
ActiveMachineRecipe activeRecipe

//获取触发事件的机械控制器
IMachineController getController


RecipeCheckEvent(配方检查事件)

此事件会在机械控制器扫描配方时触发,当配方满足运行条件后触发此事件。

同时,机械完成一个配方后,会继续检查此配方,当满足运行条件时也会触发一次此事件。

示例:

//为当前配方添加一个配方检查事件监听器
addCheckHandler(IEventHandler<RecipeCheckEvent> event);

# 例
import mods.modularmachinery.RecipeCheckEvent;

addCheckHandler(function(event as RecipeCheckEvent) {
    //处理事件...
})

此事件还有一个额外的 ZenMethod:

//调用此方法会将配方检查设置为失败,并且会阻止其他事件监听器继续收到此事件。
//一旦被设置为失败,配方就不会开始工作,机械会继续扫描其他配方。
//reason 为机械失败的原因(支持本地化字符串)
void setFailed(String reason)


RecipeStartEvent(配方开始事件)

此事件会在机械运行配方后触发,通常在 RecipeCheckEvent 触发后触发此事件。

示例:

//为当前配方添加一个配方开始事件监听器
addStartHandler(IEventHandler<RecipeStartEvent> event)

# 例
import mods.modularmachinery.RecipeStartEvent;

addStartHandler(function(event as RecipeStartEvent) {
    //处理事件...
})


RecipePreTickEvent(配方预 Tick 事件)

此事件会在配方开始 Tick(例如:能量输入输出)前触发,每个 Tick 都会触发此事件。

示例:

RecipePreTickEvent(配方预 Tick 事件):

//为当前配方添加一个配方预 Tick 事件监听器
addPreTickHandler(IEventHandler<RecipeTickEvent> event)

# 例
import mods.modularmachinery.RecipeTickEvent;

addPreTickHandler(function(event as RecipeTickEvent) {
    //处理事件...
})

此事件还有两个额外的 ZenMethod:

//阻止机器增加进度(但是依然会 Tick 并消耗能量),并设置阻止原因,原因会被输出在控制器上。
void preventProgressing(String reason)

//将运行状态设置为失败,并设置失败原因。
//当 destructRecipe 为 true 时,还会取消运行配方(吞材料),false 则不会。
void setFailed(boolean destructRecipe, String reason)


RecipePostTickEvent(配方完成 Tick 事件)

此事件会在配方完成 Tick(例如:能量已消耗或输出后)后触发,每个 Tick 都会触发此事件。

示例:

RecipePostTickEvent(配方预 Tick 事件):

//为当前配方添加一个配方预 Tick 事件监听器
addPostTickHandler(IEventHandler<RecipeTickEvent> event)

# 例
import mods.modularmachinery.RecipeTickEvent;

addPostTickHandler(function(event as RecipeTickEvent) {
    //处理事件...
})

此事件还有两个额外的 ZenMethod:

//阻止机器增加进度(但是依然会 Tick 并消耗能量),并设置阻止原因,原因会被输出在控制器上。
void preventProgressing(String reason)//将运行状态设置为失败,并设置失败原因。

//当 destructRecipe 为 true 时,还会取消运行配方(吞材料),false 则不会。
void setFailed(boolean destructRecipe, String reason)


RecipeFinishEvent(配方完成事件)

此事件会在配方完成后触发,只会触发一次。

示例:

# 例
import mods.modularmachinery.RecipeFinishEvent;

addFinishHandler(function(event as RecipeFinishEvent) {
    //处理事件...
})


机械事件

所有的机器事件都是独立的,它们只会被指定注册名的机器触发。

这些事件监听器可以通过 MMEvents 或 MachineBuilder 来添加。

通用 ZenGetter

所有的机械事件都可以使用这些方法。

//获取触发事件的机械控制器
IMachineController getController


MachineStructureFormedEvent(机械结构形成事件)

当机械控制器形成结构时,触发此事件。

示例:

//形成结构事件
MMEvents.onStructureFormed(String machineRegistryName, IEventHandler<MachineStructureFormedEvent> function)

# 例
MMEvents.onStructureFormed("tokmak_reactor", function(event as MachineStructureFormedEvent) {
    //处理事件...
});


MachinePreTickEvent(机械预 Tick 事件)

当机械形成结构时,在机械逻辑开始前触发此事件。

示例:

//预 Tick 事件
MMEvents.onMachinePreTick(String machineRegistryName, IEventHandler<MachineTickEvent> function)

# 例
MMEvents.onMachinePreTick("tokmak_reactor", function(event as MachineTickEvent) {
    //处理事件...
});


MachinePostTickEvent(机械完成 Tick 事件)

当机械形成结构时,机械逻辑执行完成后触发此事件。

示例:

//完成 Tick 事件
MMEvents.onMachinePostTick(String machineRegistryName, IEventHandler<MachineTickEvent> function)

# 例
MMEvents.onMachinePostTick("tokmak_reactor", function(event as MachineTickEvent) {
    //处理事件...
});


ControllerGUIRenderEvent(控制器 GUI 渲染事件)

当客户端打开对应机械的控制器时触发此事件,允许作者向控制器添加自定义信息。

示例:

//控制器 GUI 渲染事件
MMEvents.onControllerGUIRender(String machineRegistryName, IEventHandler<ControllerGUIRenderEvent> function)

# 例
MMEvents.onControllerGUIRender("tokmak_reactor", function(event as ControllerGUIRenderEvent) {
    //处理事件...
});

此事件还有一个额外的 ZenGetter 与 ZenSetter:

//获取或设置额外信息数组
String[] extraInfo


SmartInterfaceUpdateEvent(智能数据接口更新事件)

当控制器绑定的智能数据接口内部的数据更新后,触发此事件。

示例:

//智能数据接口更新事件
MMEvents.onSmartInterfaceUpdate(String machineRegistryName, IEventHandler<SmartInterfaceUpdateEvent> function)

# 例
MMEvents.onSmartInterfaceUpdate("tokmak_reactor", function(event as SmartInterfaceUpdateEvent) {
    //处理事件...
});

此事件还有两个额外的 ZenGetter:

//获取触发事件的智能数据接口的位置
IBlockPos interfacePos

//获取更新的数据
SmartInterfaceData newData