API

界面

玩家填写的表单和屏幕元素:Boss 栏和侧边栏。无论客户端是否安装了 Crafting,这些都能正常使用。

表单

表单包含标题、正文、字段和按钮。在 ui/ 下的文件中声明,在任何需要的地方显示(命令、事件、使用物品时):

ui/shop.craftCraftScript
import { give_rubies } from "/lib/rewards"

const SHOP = form("Ruby shop", {
    body: "Rubies cost 10 emeralds each.",
    fields: [
        { slider: "amount", label: "Rubies", min: 1, max: 16, default: 1 },
        { toggle: "gift", label: "Wrap as a gift" },
        { choice: "pouch", label: "Pouch", options: ["leather", "silk"] },
        { text: "note", label: "Note" }
    ],
    buttons: [{ id: "buy", label: "Buy" }, "cancel"]
})

fun open_shop(p: Player) {
    p.show_form(SHOP, fun(r) {
        if r.button != "buy" { return }                  // closed with Esc or cancelled
        let n = int(r.number("amount") ?? 1)
        if p.inventory.count("minecraft:emerald") < n * 10 { p.send("&cNot enough emeralds"); return }
        give_rubies(p, n)
        if r.toggle("gift") { p.send("&dWrapped in {r.choice("pouch")}: {r.text("note")}") }
    })
}
commands/shop.craftCraftScript
import { open_shop } from "/ui/shop"

command shop describe "Buy rubies" {
    if player == null { return "Players only" }
    open_shop(player)
}
字段 写法 读取方式
文本 { text: "note", label: "备注", default: "" } r.text("note")
开关 { toggle: "gift", label: "这是礼物", default: false } r.toggle("gift")
滑块 { slider: "amount", label: "数量", min: 1, max: 64, step: 1, default: 8 } r.number("amount")
选项 { choice: "color", label: "颜色", options: ["red", "blue"], default: "red" } r.choice("color")
  • 每个字段的键使用小写字母、数字和 _。label 是玩家看到的文字;省略时使用键。
  • buttons 是 { id, label } 的列表,或者只是 id 的列表。没有按钮的表单会得到一个“OK”按钮。
  • 在回答中,r.button 是被按下按钮的 id;如果玩家关闭了表单(Esc),则为 null。r.values 是包含所有字段的映射。
  • 回答会传给你交给 show_form 的函数;玩家做决定期间,服务器的其余部分照常运行。

Kotlin 中

ui/ShopForm.ktKotlin
package com.example.rubies.ui

object ShopForm {
    private val form = Form("Ruby shop").apply {
        body = "Rubies cost 10 emeralds each."
        slider("amount", "Rubies", 1.0, 16.0, default = 1.0)
        toggle("gift", "Wrap as a gift")
        choice("pouch", "Pouch", listOf("leather", "silk"))
        text("note", "Note")
        button("buy", "Buy")
        button("cancel", "Cancel")
    }

    fun show(player: Player) = player.showForm(form) { r ->
        if (r.button != "buy") return@showForm                 // closed with Esc or cancelled
        val n = (r.number("amount") ?: 1.0).toInt()
        if (player.inventory.count(Identifier.parse("minecraft:emerald")) < n * 10) { player.send("&cNot enough emeralds"); return@showForm }
        player.give(ItemStack.of(Items.RUBY, n))
        if (r.toggle("gift") == true) player.send("&dWrapped in ${r.choice("pouch")}: ${r.text("note")}")
    }
}

Form(title) 搭配 body、text(key, label, default, maxLength)、toggle(key, label, default)、slider(key, label, min, max, step, default)、choice(key, label, options, default) 和 button(id, label)。player.showForm(form) { r -> … } 接收一个 FormResponse,包含 button、values 以及 text、toggle、number、choice。

Boss 栏

屏幕顶部的一条栏,带有标题、颜色、进度和样式。可用于倒计时、服务器活动或某个东西的生命值:

events/countdown.craftCraftScript
const TIMER = server.boss_bar("rubies:countdown", "&c红宝石冲刺", "red", "segments_10")
let left = 60

on join { TIMER.show(player) }

every 1 second {
    left = max(0, left - 1)
    TIMER.progress = left / 60
    TIMER.title = "&c红宝石冲刺:{left} 秒"
    if left == 0 { TIMER.remove() }
}
成员 作用
server.boss_bar(id, title?, color?, style?) 创建该栏,或返回已有的同 id 栏。每个栏一个 id:重新加载模组不会产生重复。
bar.progress 从 0 到 1。
bar.title 文字,可用 & 颜色。
bar.color pink、blue、red、green、yellow、purple、white。
bar.style solid、segments_6、segments_10、segments_12、segments_20。
bar.show(player)、bar.hide(player) 谁能看到它。bar.players 列出这些玩家。
bar.remove() 对所有人移除它,并释放该 id。

在 Kotlin 中:Crafting.server?.bossBar("rubies:countdown", "时间", BarColor.RED, BarStyle.SEGMENTS_10),属性相同,使用 camelCase。

侧边栏

屏幕右侧最多 15 行的列表,每个玩家各不相同。再次调用即可更新:

events/welcome.craftCraftScript
import { visits } from "/lib/storage"

on join {
    player.set_sidebar("&6红宝石", [
        "&f访问次数:&e{visits(player)}",
        "&f红宝石:&c{player.inventory.count("rubies:ruby")}"
    ])
}
  • player.set_sidebar(title, lines) 显示或更新侧边栏;只有该玩家能看到。用 & 表示颜色。
  • player.clear_sidebar() 移除侧边栏。
  • 在 Kotlin 中:player.setSidebar(title, lines) 和 player.clearSidebar()。

模组的按键

模组可以添加自己的按键。用 key 声明,用 on key 响应,它会在服务器上为按下按键的玩家运行。e.key 是带有模组命名空间的 id(dashmod:dash)。

content/keys.craftCraftScript
key "dash" { label: "Dash", default: "R" }
key "heal" { label: "Second wind", default: "G" }

on key(e) {
    let p = e.player
    if e.key == "dashmod:dash" && !p.has_cooldown("minecraft:feather") {
        let d = p.direction
        p.velocity = vector(d.x * 1.6, 0.35, d.z * 1.6)
        p.set_cooldown("minecraft:feather", 2)
    }
    if e.key == "dashmod:heal" { p.heal(6) }
}

按键会显示在“选项 > 控制 > 按键绑定”中,位于以模组命名的分区下。玩家可以修改,并且他们的选择会被保留。default 是按键名称,例如 "R"、"G"、"F6" 或 "LEFT_ALT"。

玩家的游戏中需要安装 Crafting 才能使用这些按键。在 Kotlin 中:ContentBuilder.key("dash", label = "Dash", default = "R") 和 Crafting.events.on<PlayerKeyEvent> { e -> … }。

注意事项

  • 表单、Boss 栏和侧边栏对任何 Minecraft Java 26.3 客户端都可见,无论是否安装了 Crafting。服务端模组可以直接使用它们,不需要任何人安装任何东西。
  • 标题、动作栏和聊天消息见世界与玩家。
  • 自定义布局的界面(菜单、机器的物品栏)目前还不支持;见路线图。