KubeJS 可操作 UI(内置 Chest GUI:1.20.1 官方方案)¶
原文:原创教程(ぴよまる),API 依据 KubeJS 6.1(Minecraft 1.20.1)源码
dev.latvian.mods.kubejs.gui包
1.20.1 想要"能点能放"的可操作 UI,不用装任何第三方插件——KubeJS 6.1 官方内置了一套 GUI 系统:player.openChestGUI() 能打开一个自定义箱子界面(1~6 行格子),每个格子可以放物品、设按钮、绑点击回调;还有 player.openGUI() 和 player.openInventoryGUI() 做更自由的容器菜单。
✅ 版本说明:这是 KubeJS 6.1(Minecraft 1.20.1)内置功能,开箱即用,Forge/Fabric 均可。第三方 ScreenJS 只支持 1.19.2,1.20.1 请用本方案。
1. 最简单的用法:打开一个自定义箱子界面¶
// server_scripts/shop_gui.js
ItemEvents.rightClicked('kubejs:shop_wand', event => { // 右键"商店法杖"时打开 GUI
// openChestGUI(标题, 行数(1~6), 配置回调):打开一个自定义箱子界面
event.player.openChestGUI('我的商店', 3, gui => { // 3 行 = 27 个格子
// 在 (4, 1) 格子放一个"按钮":显示为钻石,点击后执行回调
gui.button(4, 1, 'minecraft:diamond', '买钻石', click => {
click.slot.gui.player.give('1x minecraft:diamond') // 给玩家 1 个钻石
click.slot.gui.player.tell('§a你买了一个钻石!') // 提示玩家
})
})
})
💡
button(x, y, 物品, 名称, 回调):x是列(0~8)、y是行(0~行数-1);格子里显示那个物品,鼠标移上去显示名称,左键点击触发回调。
2. 槽位操作(setItem / getItem / 点击绑定)¶
2.1 在指定格子里放物品¶
ItemEvents.rightClicked('kubejs:wand', event => { // 右键法杖打开界面
event.player.openChestGUI('展示柜', 1, gui => { // 1 行 = 9 格
// 用 getSlot(x, y) 拿到格子,setItem() 放物品进去
gui.getSlot(0, 0).setItem('minecraft:diamond') // 第 1 格放钻石
gui.getSlot(1, 0).setItem('2x minecraft:gold_ingot') // 第 2 格放 2 个金锭
gui.getSlot(2, 0).setItem('minecraft:stick') // 第 3 格放木棍
})
})
2.2 给格子绑定"点击行为"(三种点击分别处理)¶
ItemEvents.rightClicked('kubejs:wand', event => { // 右键法杖打开界面
event.player.openChestGUI('技能书', 1, gui => { // 1 行界面
let slot = gui.getSlot(0, 0) // 拿到第 1 个格子
slot.setItem('minecraft:book') // 格子里放一本书
slot.setLeftClicked(click => { // 左键点击
click.slot.gui.player.tell('你点了左键!')
})
slot.setRightClicked(click => { // 右键点击
click.slot.gui.player.tell('你点了右键!')
})
slot.setShiftLeftClicked(click => { // Shift+左键
click.slot.gui.player.tell('你 Shift 左键了!')
})
slot.setMiddleClicked(click => { // 中键点击
click.slot.gui.player.tell('你点了中键!')
})
})
})
可用的点击绑定方法:
| 方法 | 触发方式 |
|---|---|
setLeftClicked(cb) |
左键点击 |
setRightClicked(cb) |
右键点击 |
setMiddleClicked(cb) |
鼠标中键点击 |
setShiftLeftClicked(cb) |
Shift + 左键 |
setShiftRightClicked(cb) |
Shift + 右键 |
setDoubleClicked(cb) |
双击 |
setSwapped(cb) |
按交换键(默认 F)点击 |
setThrown(cb) |
丢弃键点击(默认 Q) |
3. 区域批量配置(slot 快速填充)¶
ItemEvents.rightClicked('kubejs:wand', event => { // 右键法杖打开界面
event.player.openChestGUI('宝石展架', 2, gui => { // 2 行界面
// 批量给 (0,0) 到 (8,1) 全部 18 个格子放物品
gui.slot(0, 0, 8, 1, slot => {
slot.setItem('minecraft:emerald') // 每个格子都放绿宝石
slot.setLeftClicked(click => { // 每个格子点击都给 1 个绿宝石
click.slot.gui.player.give('1x minecraft:emerald')
})
})
})
})
4. 全局回调(任何格子点击 / 点玩家背包 / 关闭界面)¶
ItemEvents.rightClicked('kubejs:wand', event => { // 右键法杖打开界面
event.player.openChestGUI('事件演示', 2, gui => { // 2 行界面
// 任意一个自定义格子被点击时触发(包括没绑回调的格子)
gui.anyClicked = click => {
console.log('点了格子 (' + click.slot.x + ',' + click.slot.y + ')')
}
// 玩家点自己背包里的物品时触发
gui.inventoryClicked = click => {
console.log('点了背包格子')
}
// 界面关闭时触发
gui.closed = () => {
console.log('界面已关闭')
}
})
})
⚠️
gui.anyClicked只在界面自己的格子上触发;玩家背包区域用gui.inventoryClicked。想阻止默认行为可以调click.setHandled()。
5. 完整案例:迷你商店(卖东西给玩家)¶
// server_scripts/mini_shop.js
// 效果:右键商店法杖 → 打开 2 行商店界面,点商品格子就花钱(经验)买东西
ItemEvents.rightClicked('kubejs:shop_wand', event => { // 监听"右键商店法杖"
let player = event.player // 拿到玩家
player.openChestGUI('迷你商店', 2, gui => { // 2 行 = 18 格
// 商品 1:钻石,价格 5 级经验
gui.button(0, 0, 'minecraft:diamond', '钻石 · 5 级经验', click => {
let p = click.slot.gui.player // 点击的玩家
if (p.experienceLevel >= 5) { // 经验够吗?
p.addExperienceLevels(-5) // 扣 5 级经验
p.give('1x minecraft:diamond') // 给钻石
p.tell('§a购买成功:钻石!')
} else {
p.tell('§c经验不足!需要 5 级。')
}
})
// 商品 2:金苹果,价格 10 级经验
gui.button(1, 0, 'minecraft:golden_apple', '金苹果 · 10 级经验', click => {
let p = click.slot.gui.player
if (p.experienceLevel >= 10) {
p.addExperienceLevels(-10)
p.give('1x minecraft:golden_apple')
p.tell('§a购买成功:金苹果!')
} else {
p.tell('§c经验不足!需要 10 级。')
}
})
// 关闭时提示
gui.closed = () => player.tell('§7商店已关闭,欢迎下次光临!')
})
})
6. 更自由的 openGUI / openInventoryGUI¶
如果箱子样式不够用,还有两个进阶入口(源码 kjs$openGUI / kjs$openInventoryGUI):
// openInventoryGUI:直接给一个物品容器(Inventory)当界面
ItemEvents.rightClicked('kubejs:bag', event => { // 右键"袋子"物品
let inv = event.player.persistentData.bag || { slots: [] } // 自己的存档当容器
event.player.openInventoryGUI(inv, '我的背包') // 打开容器界面
})
// openGUI:完全自定义尺寸的容器菜单(宽度/高度/标题)
ItemEvents.rightClicked('kubejs:custom', event => {
event.player.openGUI(gui => {
gui.title = '自定义界面' // 标题
gui.width = 176 // 界面宽度(像素)
gui.height = 166 // 界面高度(像素)
gui.inventory = /* 一个 Inventory 对象 */ // 可选:绑定物品容器
})
})
💡
openGUI的自由度最高,适合进阶玩家;日常做商店/菜单用openChestGUI就够了。
7. 速查表¶
| 想做什么 | 写法 |
|---|---|
| 打开自定义箱子界面 | player.openChestGUI(标题, 行数1~6, gui => {...}) |
| 放物品到格子 | gui.getSlot(x, y).setItem('id') 或 gui.getSlot(x, y).setItem('2x id') |
| 读格子物品 | gui.getSlot(x, y).getItem() |
| 放一个按钮 | gui.button(x, y, 物品, 名称, 点击回调) |
| 左键点击 | slot.setLeftClicked(cb) |
| 右键点击 | slot.setRightClicked(cb) |
| Shift+左键 | slot.setShiftLeftClicked(cb) |
| 中键点击 | slot.setMiddleClicked(cb) |
| 双击 | slot.setDoubleClicked(cb) |
| 批量配置区域 | gui.slot(x0, y0, x1, y1, slot => {...}) |
| 任意格子点击 | gui.anyClicked = click => {...} |
| 点背包格子 | gui.inventoryClicked = click => {...} |
| 关闭界面 | gui.closed = () => {...} |
| 阻止默认行为 | click.setHandled() |
| 打开容器界面 | player.openInventoryGUI(容器, 标题) |
| 自由容器菜单 | player.openGUI(gui => { gui.title/width/height = ... }) |
| 点击事件里拿玩家 | click.slot.gui.player |
💡 记忆口诀:
openChestGUI(标题, 行数, 回调)开界面 →gui.button(x, y, 物品, 名, 回调)放可点按钮 →gui.getSlot(x, y).setItem(...)摆物品 →slot.setLeftClicked/setRightClicked/...绑点击 →gui.closed收尾;点击回调里用click.slot.gui.player拿玩家。
本文为 KubeJS 1.20.1 中文文档原创篇目。API 依据 KubeJS 6.1 源码 dev.latvian.mods.kubejs.gui(KubeJSGUI / KubeJSMenu / CustomChestMenu / ChestMenuData / ChestMenuSlot),1.20.1 内置无需插件。