本篇教程由作者设定未经允许禁止转载。
模块化机械:社区版 从入门到入土 —— Part.Extra.1 GeckoLib 模型/动画
本篇教程皆在展示模块化机械:社区版的特殊功能。
本教程主要使用的模组为模块化机械:社区版 - 1.11.1-r53、CraftTweaker、GeckoLib。
教程目录:
Part.4.1 并行配方处理(未完成)
Part.4.2 工厂系统(未完成)
Part.4.3 工厂事件系统(未完成)
Part.4.4 智能数据接口(未完成)
Part.4.5 单方块 / 多方块机械升级(未完成)
Part.4.6 自定义 GUI 信息(未完成)
Part.5 配置文件解析(未完成)
Part.Extra.1 GeckoLib 模型/动画(当前)
环境准备
本教程强烈推荐使用 Visual Studio Code(以下简称 VSCode),可以大大减少你的魔改工作量。
使用 VSCode,你可以利用它的强大的功能来更快的完成复杂的操作,同时拥有代码提示,大大减少代码阅读难度和出错率,同时可以安装插件来扩展功能,使其更加强大。
阅读本教程即代表你已熟悉 ZenScript 的大部分高级运用,并且已经了解基本的机械创建与配方创建。
要创建模型,你需要使用 BlockBench 来制作和导出模型。
要加载模型文件,你还需要安装 ResourceLoader 或其他可以加载外部资源包的模组。
模型格式为基岩版模型。
阅读本教程即代表你已熟悉 ZenScript 的大部分高级运用,并且熟悉基岩版模型文件的格式、贴图、动画格式。
注意:2.0.0-pre5(不包括 pre5) 之前的 GeckoLib 模型不兼容 AMD 显卡,请注意辨别版本。
介绍
从 模块化机械:社区版 R53 版本起,玩家可以使用 ZenScript 脚本为机械设置一系列的自定义模型和动画。
本篇教程将为玩家提供一系列完整的使用教程。
模型文件准备
绑定模型总计需要三个文件,分别为模型文件,模型贴图,模型动画文件,名称依次为 xxx.geo.json、xxx.png、xxx.animation.json。
模型文件
在 BlockBench 导出模型时务必选择基岩版模型。
导出路径通常为 “.minecraft/resources/modularmachinery/geo/xxx.geo.json”,也可自行选择其他路径(但不可超出 ./minecraft/resource 范围)。
注意:路径选择一定要仔细检查,如果文件不存在则可能会导致游戏加载崩溃。
模型贴图
在纹理处右击并选择《另存为》。
导出路径通常为 “.minecraft/resources/modularmachinery/textures/blocks/xxx.png”,也可自行选择其他路径(但不可超出 ./minecraft/resource 范围)。
模型动画文件
在动画模式下,右击界面左方的动画列表空区,点击保存所有动画。
导出路径通常为 “.minecraft/resources/modularmachinery/animations/xxx.animation.json”,也可自行选择其他路径(但不可超出 ./minecraft/resource 范围)。
注意:如果没有动画也需要导出一个空的动画文件,文件不存在可能会导致游戏崩溃。
模型注册
在为机械配置模型前,我们需要将模型注册到游戏中。
使用 ZenScript 脚本来注册模型。
注:一个模型可以被绑定到多个机械。
示例脚本:
import mods.modularmachinery.GeoMachineModel; // 导包
GeoMachineModel.registerGeoMachineModel("model_name", // 模型名称
"modularmachinery:geo/model.geo.json", // 模型文件路径
"modularmachinery:textures/model.png", // 模型贴图路径
"modularmachinery:animations/model.animation.json" // 模型动画路径
);
脚本中的路径为演示路径,实际路径请参考自身环境的路径调整。
模型绑定
要为机械绑定模型,需要使用 ZenScript 脚本进行操作。
示例脚本:
import mods.modularmachinery.MachineModifier;
// ...此处省略注册模型部分
// 机械名称 模型名称(必须先注册后使用)
MachineModifier.setMachineGeoModel("machine_name", "model_name");
重载脚本或重启游戏,若脚本无报错,我们已经成功的为机械绑定了自定义模型。
在游戏中建造机械,成型后,即可正确渲染我们的自定义模型。
成功示例(模型文件版权归模型作者 WI-8614-ice 所有,未经授权严禁转载):
机械组件方块模型隐藏(可选)
有时候,我们可能需要为模型添加更多的细节,但是这可能会和机械原有的结构冲突,这个时候我们可以为机械设置隐藏组件的选项。
注意:要使用此功能,必须安装 Multiblocked 或者此模组(两者互相不兼容)。
打开要隐藏组件的机械的文件,在文件中添加下图所示的配置:
配置完成后,重载脚本或重启游戏,此时当机械成型后,机械就会自动隐藏所有结构组件的模型渲染。
模型动画
现在我们完成了对机械的模型绑定,但此时还不能能够使起动起来。
接下来我们将使用 ZenScript 为机械设置动画。
示例脚本:
import mods.modularmachinery.MMEvents;
import mods.modularmachinery.ControllerModelAnimationEvent;
// ...此处省略注册模型部分
// ...此处省略模型绑定部分
MMEvents.onControllerModelAnimation("machine_name", function(event as ControllerModelAnimationEvent) {
val ctrl = event.controller;
// 检查机械是否正在工作。
if (ctrl.isWorking) {
// 为模型设置名为 "working" 的动画,只播放一次。
event.addAnimation("working");
} else {
// 为模型设置名为 "idle" 的动画,并且会循环播放。
event.addAnimation("idle", true);
}
});
此段脚本会使机械在工作时运行名为 "working" 的动画,并且会循环播放,反之会运行 "idle" 动画,并且会循环播放。
除此自外,你也可以自行判断机械的各种状态,为机械播放不同的动画。
注意:动画名称必须和 BlockBench 中的动画名完全对应,否则可能会导致游戏崩溃。
动态模型切换
有时候我们可能会对机械做出一些升级,为机器更换上更高级或者更炫酷的模型,这个时候我们可以设置动态模型切换功能。
示例脚本:
import mods.modularmachinery.MMEvents;
import mods.modularmachinery.ControllerModelGetEvent;
// ...此处省略注册模型部分
// ...此处省略模型绑定部分
MMEvents.onControllerModelGet("machine_name", function(event as ControllerModelGetEvent) {
val ctrl = event.controller;
if (ctrl.hasModifierReplacement("replacement_1") {
event.modelName = "model_name_upgraded";
}
});
注意:如果模型名称对应的模型未注册,则不会使用该模型,且会被自动回滚至机械的默认模型。
ControllerModelAnimationEvent 高级运用
本段提供了关于机械模型动画事件的更多可用的高级方法。
/**
* 为模型添加一个动画,只运行一次。
* 会按照添加动画的顺序来运行动画。
*/
@ZenMethod
public void addAnimation(String animationName);
/**
* 为模型添加一个动画,并设置其是否会循环运行。
* 会按照添加动画的顺序来运行动画。
*/
@ZenMethod
public void addAnimation(String animationName, boolean loop);
/**
* 类似 addAnimation(String animationName),但是它会覆盖先前所有添加的动画。
*/
@ZenMethod
public void setAnimation(String animationName);
/**
* 类似 addAnimation(String animationName, boolean loop),但是它会覆盖先前所有添加的动画。
*/
@ZenMethod
public void setAnimation(String animationName, boolean loop);
/**
* 获取当前模型的注册名称。
*/
@ZenGetter("currentModelName")
public String getCurrentModelName();
/**
* 获取当前模型的过渡长度(单位:Tick)
*/
@ZenGetter("transitionLengthTicks")
public double getTransitionLengthTicks();
/**
* 设置当前模型的过渡长度(单位:Tick)
*/
@ZenSetter("transitionLengthTicks")
public void setTransitionLengthTicks(double transitionLengthTicks);
/**
* 获取当前机械的动画运行状态。
* 0 为运行,1 和其他数值为停止。
*/
@ZenGetter("playState")
public int getPlayState();
/**
* 设置当前机械的动画运行状态。
* 0 为运行,1 和其他数值为停止。
*/
@ZenSetter("playState")
public void setPlayState(final int playState);
/**
* 获取当前机械正在运行的动画名称。
*/
@Nullable
@ZenGetter("currentAnimationName")
public String getCurrentAnimationName();
/**
* 获取当前机械正在运行的动画速度。
*/
@ZenGetter("animationSpeed")
public double getAnimationSpeed();
/**
* 获取当前机械的动画进度(单位 Tick)。
*/
@ZenGetter("animationTick")
public double getAnimationTick();
/**
* 获取当前机械的动画状态。
* 0 为运行,1 为切换中,2 为停止中。
*/
@ZenGetter("animationState")
public int getAnimationState();
/**
* 待测试。
*/
@ZenGetter("limbSwing")
public float getLimbSwing();
/**
* 待测试。
*/
@ZenGetter("limbSwingAmount")
public float getLimbSwingAmount();
/**
* 待测试。
*/
@ZenGetter("partialTick")
public float getPartialTick();
/**
* 待测试。
*/
@ZenGetter("moving")
public boolean isMoving();