AuroraUI 公开 API
从 v3 起,所有第三方交互通过 AuroraUI 单例 完成。
没有 Bukkit ServicesManager、没有 AuroraUIApi 接口、没有继承 AuroraUIApplicationSession。
一切是 DSL 声明式 + Lambda 事件。
Maven 依赖 auroraui-api Kotlin 1.4+ SAM 必须在主线程调用
设计理念
单例入口
AuroraUI object 是唯一公开入口。没有注册服务,没有接口查询。DSL 声明
用AuroraUI.declare(id, owner) { ... } 一次性写完应用配置与所有事件。Lambda 事件
不再抽象类继承,每个回调是一个 lambda;不需要的就不写。AuroraUIRealm
事件 receiver 自带上下文(player / surface / mode),不再需要显式传 context。类型安全
所有返回值是 Kotlin data class / enum,不再有Object 强转。向后兼容
旧AuroraUIApi / AuroraUIApplication / AuroraUIApplicationContext 在 LegacyCompat.kt 保留为 @Deprecated 桥接。快速上手
依赖(pom.xml):
<dependency>
<groupId>aurora.studio.aurora.ui</groupId>
<artifactId>auroraui-api</artifactId>
<version>LATEST</version>
<scope>provided</scope>
</dependency>
最小可用示例 — 一个"商店"锚点,带画布、权限、点击事件:
import aurora.studio.aurora.ui.api.*
import org.bukkit.plugin.java.JavaPlugin
class MyShopPlugin : JavaPlugin() {
override fun onEnable() {
AuroraUI.declare("myshop:shop", this) {
permission = "myshop.use"
captureScroll = true
tickEvery = 2
onActivate { evt ->
// this == AuroraUIRealm,直接访问上下文
server.broadcast("${player.name} 进入商店")
cursor(true)
}
onScroll { evt ->
// 滚轮翻页
}
onClose { evt ->
// evt.reason ∈ AuroraUICloseReason
}
}
}
}
通过命名空间路由打开锚点(或从 HTML 菜单用 open-app: myshop:shop):
AuroraUI.route("myshop:shop", this, AuroraUIRoute { player, args ->
AuroraUI.show(player, "myshop:shop", args, AuroraUIShowKind.ANCHOR)
})
AuroraUI.declare(id, owner) { ... }
声明一个锚点(独立于菜单的、由第三方插件托管的 UI 会话)。DSL 块里可写以下属性与回调:
| DSL 项 | 类型 | 说明 |
|---|---|---|
permission | String | 打开前检查的 Bukkit 权限节点(空字符串 = 无要求) |
captureScroll | Boolean | 是否在锚点活跃时接管滚轮(默认 false) |
inheritCanvas | Boolean | 是否继承上一个会话的画布平面(默认 true) |
tickEvery | Int | onTick 触发间隔(tick),1–1200;默认 20 |
canvas { ... } | AuroraUICanvas DSL | 逻辑画布:width / height / pixelsPerBlock / distance |
onActivate { realm, evt -> ... } | Lambda | 点击命中区时触发 |
onPointerMove { realm, evt -> ... } | Lambda | 指针位置变化时触发 |
onPointerModeChange { realm, evt -> ... } | Lambda | touch ↔ mouse 切换 |
onScroll { realm, evt -> ... } | Lambda | 滚轮事件 |
onSurfaceChange { realm, evt -> ... } | Lambda | 画布平面变化(打开、传送、重生) |
onTick { realm, evt -> ... } | Lambda | 周期性 tick |
onClose { realm, evt -> ... } | Lambda | 锚点关闭,evt.reason 说明原因 |
AuroraUI.declare 返回 AuroraUIAnchorHandle:
val handle: AuroraUIAnchorHandle = AuroraUI.declare("myshop:shop", this) { ... }
handle.alive // 是否已注册
handle.remove() // 手动注销(插件禁用时自动移除)
// handle.close() 等价于 remove()
AuroraUI.route / AuroraUI.dispatch
轻量命名空间路由 —— 菜单 open-app: myshop:shop args... 的入口。
// 注册
AuroraUI.route("myshop:shop", this, AuroraUIRoute { player, arguments ->
AuroraUI.show(player, "myshop:shop", arguments, AuroraUIShowKind.ANCHOR)
})
// 也可以直接打开菜单
AuroraUI.route("myshop:quick-help", this, AuroraUIRoute { player, args ->
AuroraUI.show(player, "help", args, AuroraUIShowKind.MENU)
})
// 查询/移除
AuroraUI.namespaces() // Set<String>
// 插件禁用时自动移除其所有 route
AuroraUI.show / AuroraUI.hide / AuroraUI.back
| 方法 | 签名 | 说明 |
|---|---|---|
AuroraUI.show | (Player, String, List<String>, AuroraUIShowKind): Boolean | 打开菜单 MENU 或锚点 ANCHOR |
AuroraUI.hide | (Player): Unit | 关闭当前会话 |
AuroraUI.back | (Player): Boolean | 从历史栈返回上一级 |
AuroraUI.animate | (Player, String): Boolean | 播放动画轨道 |
AuroraUI.stop | (Player, String): Boolean | 停止动画轨道 |
AuroraUI.anchors | (Player): Set<String> | 该玩家正在播放的轨道 |
AuroraUI.anchors | (): Set<String> | 所有已注册锚点 ID |
指针模式
| 枚举 | 说明 |
|---|---|
AuroraUIMode.TOUCH | 默认"十字准星"模式 |
AuroraUIMode.MOUSE | 真正的光标模式 |
AuroraUIPolicy.CHOICE | 玩家可以自己选择模式 |
AuroraUIPolicy.FORCE_TOUCH | 服务器强制 touch |
AuroraUIPolicy.FORCE_MOUSE | 服务器强制 mouse |
AuroraUI.modeOf(player) // AuroraUIMode
AuroraUI.modeOf(player, AuroraUIMode.MOUSE) // Boolean(是否成功切换)
AuroraUI.policy() // AuroraUIPolicy
// 查询当前画布/指针
AuroraUI.surfaceOf(player) // AuroraUISurface?
AuroraUI.pointOf(player) // AuroraUIPoint?
DSL 事件 —— 生命周期
onActivate
onActivate { evt ->
// this@AuroraUIRealm 可用
val p: Player = player
val point: AuroraUIPoint? = evt.point
val button: AuroraUIButton = evt.button // LEFT / RIGHT / SHIFT_LEFT ...
val sneaking: Boolean = evt.sneaking
cursor(true)
// 打开子锚点:
showAnchor("myshop:detail", listOf("item=5"))
}
onClose
onClose { evt ->
val reason: AuroraUICloseReason = evt.reason
// REQUESTED / BACK / REPLACED / PLAYER_QUIT / PLUGIN_DISABLE / ERROR ...
}
DSL 事件 —— 指针
onPointerMove { evt ->
val current: AuroraUIPoint? = evt.point
val prev: AuroraUIPoint? = evt.previous
}
onPointerModeChange { evt ->
val prev = evt.previous // AuroraUIMode
val now = evt.current
}
onScroll { evt ->
val steps: Int = evt.steps // 正=上, 负=下
}
DSL 事件 —— 画布 & Tick
onSurfaceChange { evt ->
val surface: AuroraUISurface = evt.surface
val initial: Boolean = evt.initial // true = 首次建立
}
onTick { evt ->
val tick: Long = evt.tick
}
AuroraUIRealm —— 事件 receiver 的上下文
所有 DSL lambda 的 receiver 都是 AuroraUIRealm,自带 player、画布、指针等能力:
| 成员 | 类型 | 说明 |
|---|---|---|
player | Player | 直接可用的 Bukkit Player |
anchorId | String | 当前锚点 ID |
args | List<String> | 打开时传入的参数 |
surface() | AuroraUISurface? | 当前画布快照 |
point() | AuroraUIPoint? | 当前指针位置 |
mode() | AuroraUIMode | 当前指针模式 |
alive | Boolean | 锚点是否还活着(onClose 触发时先变 false) |
cursor(interactive) | Unit | 视觉光标样式 |
从旧 API 迁移
旧 API(
AuroraUIApi / AuroraUIApplication / AuroraUIApplicationContext)在 LegacyCompat.kt 保留为 @Deprecated 桥接层,当前 Paper 端仍接受。但所有新代码应直接写 AuroraUI DSL。旧代码
AuroraUIApi ui = Bukkit.getServicesManager().load(AuroraUIApi.class);
AuroraUIApplicationHandle handle = ui.registerApplication(
this, "myshop:shop",
AuroraUIApplicationOptions.builder()
.permission("myshop.use")
.captureMouseScroll(true)
.build(),
context -> new ShopSession(context)
);
// ShopSession 继承 AuroraUIApplicationSession,重写 onActivate / onClose ...
新代码(等价)
AuroraUI.declare("myshop:shop", this) {
permission = "myshop.use"
captureScroll = true
onActivate { evt ->
// 原来写在 ShopSession.onActivate 的逻辑
}
onClose { evt ->
// 原来写在 ShopSession.onClose 的逻辑
}
}
对照表
| 旧 API | 新 API |
|---|---|
ServicesManager.load(AuroraUIApi.class) | 直接 AuroraUI 单例(无需获取) |
ui.registerApplication(...) | AuroraUI.declare(id, owner) { ... } |
AuroraUIApplicationOptions.Builder | DSL 里直接写属性:permission = / captureScroll = ... |
extends AuroraUIApplicationSession | DSL 里写 onActivate { ... } 等 lambda |
AuroraUIApplicationContext(显式传递) | 隐式 AuroraUIRealm receiver(this.player / this.surface()) |
ui.registerRoute(owner, id, AuroraUIRoute) | AuroraUI.route(id, owner, AuroraUIRoute { player, args -> ... }) |
ui.open(player, menuId, args) | AuroraUI.show(player, menuId, args, AuroraUIShowKind.MENU) |
ui.openApplication(player, id, args) | AuroraUI.show(player, id, args, AuroraUIShowKind.ANCHOR) |
AuroraUICapability.APPLICATION_SESSIONS | 已废弃,所有能力始终可用 |
AuroraUIApplicationHandle.unregister() | handle.remove() 或让插件禁用时自动移除 |