写在前面:本章教程的部分代码需要农夫乐事和腌渍乐事才能运行。
同时本章相当一部分内容是关于农夫乐事的修改——毕竟这些教程的本色是模拟经营整合包教程。

这是上一期教程最后的图片——这实现的是一个基本的交互功能:通过用沙威玛刀与沙威玛方块交互,产生沙威玛烤肉物品。
那么,这个功能是如何实现的呢?
很简单:写一段server_scripts就可以了。server_scripts代表游戏运行时执行的代码,比如物品交互。

这一段代码写在server_scripts/src/interaction.js里面。
那么这一段代码干了什么?
首先:BlockEvents.rightClicked()是一个event。你可以把它理解为某种触发器:当方块被右键的时候,触发这一段代码,而第一个参数("kubejs:shawarma_block")则是这个触发器的限制:只有沙威玛方块被右键的时候,这段代码才会被触发。
接下来则会经过这样一段流程:
如果event.item(右键的物品)不是沙威玛刀,则直接退出,跳过所有流程。
(需要注意,.rightClicked()和.leftClicked()都会针对左右手分别触发一次!!如果没有物品要求的话,建议加上主手/副手要求,检测event.hand)
把event.player(玩家)和event.block(方块)存入变量里面。let是JavaScript的变量语法。
对于方块,调用.popItem(),弹出一个沙威玛物品。
对于玩家,调用.swing(),播放玩家挥手动画。
至此,一个最简单的交互逻辑就写好了。
但是这么简单的交互逻辑不一定够用:无限右键切沙威玛,是不是有点破坏平衡?
这时就可以加入一段随机逻辑:

我们都知道,沙威玛烤肉是一种不断切掉烤好的外部烤肉,露出里面没烤好的烤肉继续烤的做法。
那么在这里,切沙威玛的时候有1/8的几率沙威玛方块会变成生的沙威玛方块。
生的沙威玛方块怎么变熟呢?这里我们可以引入另一种方块逻辑:随机刻。KubeJS支持自定义方块受到随机刻时的变化——不过这就不是server_scripts能处理的内容了。我们回到上一章写好的代码:

.randomTick()会在方块接收到随机刻的时刻触发。这里我们写了这样一段逻辑:遍历方块四个方向的其他方块,如果有农夫乐事认定的热源,就把自身变成熟的沙威玛方块。
重启游戏之后,就可以把生的沙威玛方块在火旁烤熟了。是不是很像那么一回事?

不过这样子会有一些别的问题——随机刻和切肉逻辑都是随机的,这就导致烤肉可能切一片就不能切了,也可能切一百片还能切,这显然很破坏游戏体验,不过进一步的改善就是下一章——方块实体与Jade——的内容了。
当然,交互逻辑远远不止BlockEvents.rightClicked();这里就是时候体验一下ProbeJS的强大功能了。


ProbeJS可以直接告诉你有哪些可以触发的事件。你可以自己试试这些事件在什么情况下触发,或者直接从别的魔改包里面找代码看看是干啥的。
接下来——生的沙威玛要怎么获取呢?
很显然,我们需要为此增加一个合成配方。合成配方相关的内容在ServerEvents.recipes这个事件里面触发。
我们都知道,沙威玛是一种用鸡肉和番茄串起来做成的烤肉——

那么我们就可以写一个工作台的合成配方,用番茄,生鸡肉和原木合成一个生沙威玛方块!
写完这样一段代码,保存,然后/kubejs reload server_scripts重载脚本,/reload重载配方数据,就可以找到这样的配方:

除了event.shaped和event.shapeless,KubeJS还提供了一些其他的便捷合成函数:

不过,如果我们想做一个深入安排各个模组的内容的魔改包,我们不可能限制于原版的这些合成方式。要怎么才能注册其他模组的合成方式呢?
很简单:首先,我们找到上一章解压好的模组,点进data文件夹,然后选择模组自身的名称(其他的名称一般是联动数据)

点进recipes,找到你想要的配方,在VScode里面打开:

比如这是农夫乐事用剪刀把皮革马铠转化为皮革的砧板合成。我们把这段json黏贴到一个event.custom()里面:

稍作修改:

然后,按照上述步骤重载配方,就成了。非常简单。

但是如果我们要对每一个砧板配方都复制黏贴上面那一段代码,未免也有点太呆了。
(其实你翻我整合包的代码会发现我是这么干的……别学我)
编程的一大特点就是自动化掉重复的内容——我们可以编写这样一个“助手函数”:

因为event.custom接受的是一个Javascript的Object,以Json格式注册配方,那么我们大可用代码依照几个参数自动生成这个Object,这是助手函数的基本逻辑。
这个助手函数可能稍显复杂,但是重点是,这个助手函数使用的时候就非常丝滑了。
本章教程的代码会附在教程最后,哪怕不知道具体流程的原理,直接抄走当黑箱也是不错的。
只需要一行代码,就可以轻松注册一个新的砧板配方,而且全都能生效。

不过目前为止的配方只是对于唯一确定的输入有唯一确定的输出——这很清晰明了,但是有些时候,就不太足够了。比如海岛寿司店的复合寿司——又或者,沙威玛店的沙威玛。
沙威玛传奇原作中,饼皮里面卷什么是可以自定义的,甚至可以什么都不卷。
但是如果我们要在MC里面还原这一点,要怎么做呢?枚举的话,可能要枚举几十种可能性,未免显得有点太呆了。
这时候我们就需要用到另外一个强大的功能: .modifyResult()函数。

我们遍历一遍0个到4个沙威玛配料的合成表,生成了五个沙威玛卷饼的合成表:
然后对于每个合成表,我们加入一段逻辑,把合成台上面的物品id获取成列表,并且将排序后的列表记录在成品的NBT里面,同时生成一段文本提示。


不过写这段代码的时候你会发现一个问题:probeJS居然没有给grid和stack生成补全词。要怎么解决这一点问题呢?
首先,把鼠标放在函数上,确认grid和stack是什么属性:

然后,在函数参数前面打出/**,随后按下Enter:

接下来,会自动生成两个@param,往里面填充你之前看到的属性类型:

然后就能继续用ProbeJS的补全了。耶!

回顾一下这一篇的内容:我们可以创建各种与方块的交互,创建各种原版配方,各种根据材料有不同结果的特殊原版配方,各种mod配方……
而且都是可以在游戏里面直接热重载的!
下篇预告:方块实体和Jade
本专栏所用的KubeJS脚本和材质压缩包的蓝奏云下载链接:
https://wwqi.lanzoue.com/i3o132bux9yf
(附赠农夫乐事烹饪锅的帮手函数)
KubeJS官方Wiki:
https://kubejs.com/wiki