基础知识


KubeJS 是什么?

KubeJS(以下简称 KJS)是一个 Minecraft 模组,作用是修改合成配方、操控游戏事件、加载数据包和资源包等等。这一切都使用 JavaScript 完成。

为什么用 KJS?

你可能会想,要改合成配方的话,不是有 CraftTweaker 吗?这个 KubeJS 是哪里冒出来的?我为什么要用它?

那么就举个例子好了,以下是同一个工作台合成配方分别用两个模组实现的代码,游戏版本为 1.18。

onEvent('recipes', event => { // 指定代码作用的事件,'event'可以改成任何合法的变量名 event.shaped('2x minecraft:golden_apple', // 添加有序合成配方,此配方输出两个金苹果 [ 'GGG', 'GAG', 'GGG' ], // 物品的摆放样式,使用字符代替不同的物品 { G: '#forge:storage_blocks/gold', A: 'minecraft:apple' } // 定义上面的字符代表的物品(或标签) ).id('kubejs:shaped_example_1') // 指定配方 ID,这不是必须的 }) craftingTable.addShaped("shaped_example_1", <item:minecraft:golden_apple> * 2, [ [<tag:forge:storage_blocks/gold>, <tag:forge:storage_blocks/gold>, <tag:forge:storage_blocks/gold>], [<tag:forge:storage_blocks/gold>, <item:minecraft:apple>, <tag:forge:storage_blocks/gold>], [<tag:forge:storage_blocks/gold>, <tag:forge:storage_blocks/gold>, <tag:forge:storage_blocks/gold>] ]);

为了更好地说明,下面是使用 MC 原版机制的数据包配方。

{ "type": "minecraft:crafting_shaped", "pattern": [ "GGG", "GAG", "GGG" ], "key": { "G": { "tag":"forge:storage_blocks/gold" }, "A": { "item":"minecraft:apple" } }, "result": { "item": "minecraft:golden_apple", "count": 2 } }

显然,KJS 的语法与原版的 JSON 更为接近,毕竟 JSON 的全称就是 JavaScript Object Notation。

除此之外,很容易看出 KJS 的其他优点:

  1. 物品和标签的写法简单,格式为'modid:name',如果是标签,只需要在前面加上#号,要指定数量,在前面加上数字和x即可。
  2. pattern 的写法直观,你能一眼看出这些物品在工作台上要摆成什么样子。
  3. 字符数量少。
  4. 不必写分号。(这很牛逼!)

你可能会说,我可以这样写啊:

var A = <item:minecraft:apple> var G = <tag:forge:storage_blocks> craftingTable.addShaped("shaped_example_1", <item:minecraft:golden_apple> * 2, [ [G, G, G], [G, A, G], [G, G, G] ]);

没错,但是在每个合成表前面都要定义一遍变量实在是不太优雅,而且我仍然觉得对于工作台这样只有 9 个格子的 pattern 用一个二维数组来表示实在是小题大做。

另外,KJS 还可以访问和操控游戏内的许多事件:玩家聊天、方块放置与破坏、实体死亡、爆炸、世界生成等等,我会在后面的文章介绍。

还有一点是 CrT 无法做到的:反射,或称访问 Java 类。请看下面的代码:

const Base = java('com.simibubi.create.content.curiosities.tools.SandPaperItem') const Prop = java('net.minecraft.world.item.Item$Properties') const KubeJS = java('dev.latvian.mods.kubejs.KubeJS') let defProperties = new Prop().tab(KubeJS.tab) onEvent('item.registry', event => { defProperties.defaultDurability(4) event.custom('custom_sandpaper', new Base(defProperties)) })

这段代码的作用是创建一个自定义的砂纸物品,拥有和 Create 的砂纸一样的功能和 4 点耐久度。有过模组开发经验的人应该能很容易看懂这段代码。

基本上,你可以使用反射使用游戏中的任何 Java 类,这意味着哪怕模组没有提供对 KJS 的支持,你也可以自定义一些使用此模组特性的东西。

怎么用 KJS?

首先你需要安装好这个模组,这应该不是什么问题。

然后启动一次游戏,你会在游戏目录发现一个名为kubejs的文件夹,里面有client_scriptsserver_scriptsstartup_scripts和一些其他的文件夹。在里面新建.js文件,然后开始写代码。

这三个文件夹分别对应 KubeJS 事件的三种类型:Client,Server 和 Startup。

“事件”是一个非常重要的概念,游戏中的一切都是事件,KubeJS 支持的所有事件,以及它们的类型在这里列出。

接着是三种事件类型的特点:

  1. Client 事件只在客户端生效,例如物品提示(tooltip),JEI 等等。主要是视觉上的。支持热重载。
  2. Server 事件在服务端生效,例如配方、标签等数据包特性,以及方块放置、生物死亡等事件。支持热重载。
  3. Startup 事件在游戏启动时生效,例如物品、方块注册、物品属性修改等。只在游戏启动时加载,无法热重载。

在后面的文章中,我将介绍各种事件,使用各种例子,你还能学到一点 JavaScript 知识。


KJSEXP 配方事件