事件系统
Baikiruto 使用自定义的 ItemEventBus 事件总线,而非 Bukkit 原生事件系统。同时提供少量 Bukkit 代理事件。
ItemEventBus
| 方法 | 返回值 | 说明 |
|---|---|---|
post(event: Any) | Unit | 发布事件 |
subscribe(type: Class<T>, handler: (T) -> Unit) | AutoCloseable | 订阅事件 |
val api = Baikiruto.api()
val bus = api.getItemEventBus()
// 订阅物品构建事件
bus.subscribe(ItemBuildPostEvent::class.java) { event ->
println("物品构建完成: ${event.itemId}")
}
// 发布自定义事件
bus.post(MyCustomEvent())
生命周期事件
物品从构建到销毁的完整生命周期:
| 事件 | 说明 |
|---|---|
ItemBuildPreEvent | DefaultItem.build(...) 开始时触发,可修改本次构建要写入的 name / lore 变量 |
ItemBuildPostEvent | BUILD 脚本和 metas 执行完成后触发,可检查当前 ItemStream 状态 |
ItemReleaseEvent | ItemStream.toItemStack() 进入释放链路时触发,可修改 icon、data、itemMeta |
ItemReleaseDisplayEvent | 释放流程进入显示阶段时触发 |
ItemReleaseDisplayBuildEvent | 显示模板构建前触发,可修改 displayId、display、name、lore |
ItemReleaseFinalEvent | Placeholder、NBT 同步和版本特性处理完成后触发,可最后修改返回的 ItemStack |
ItemGiveEvent | 物品给予玩家时触发 |
ItemUpdateEvent | 物品数据更新时触发 |
ItemCheckUpdateEvent | 检查物品是否需要更新时触发 |
ItemSelectDisplayEvent | 选择物品显示方案时触发 |
val bus = api.getItemEventBus()
// 在物品构建前修改参数
bus.subscribe(ItemBuildPreEvent::class.java) { event ->
// 可以修改构建上下文
println("即将构建物品: ${event.itemId}")
}
// 物品构建完成后处理
bus.subscribe(ItemBuildPostEvent::class.java) { event ->
val itemStream = event.itemStream
println("物品已构建: ${event.itemId}")
}
// 物品给予玩家时
bus.subscribe(ItemGiveEvent::class.java) { event ->
println("${event.player?.name} 获得了物品 ${event.itemId}")
}
// 物品更新
bus.subscribe(ItemUpdateEvent::class.java) { event ->
println("物品 ${event.itemId} 已更新")
}
修改描述时该监听哪个事件
如果你在开发附属插件,想改的是“最终给玩家看到的 lore”,通常不要一上来就直接改 ItemMeta。不同阶段的职责如下:
| 场景 | 推荐事件 / 方法 | 原因 |
|---|---|---|
| 在 build 阶段给本次构建注入默认描述变量 | ItemBuildPreEvent | 这时写入的 name / lore 会继续参与 BUILD 脚本和 metas |
| 根据最终 display、玩家上下文改写可见描述 | ItemReleaseDisplayBuildEvent | 显示方案已经选好,但模板还没渲染,最适合改 item_description |
只想临时覆盖当前 ItemStack 的最终文本 | ItemReleaseFinalEvent | 最后一跳可直接改成品,但不会把语义重新写回 runtimeData |
val api = Baikiruto.api()
val bus = api.getItemEventBus()
bus.subscribe(ItemReleaseDisplayBuildEvent::class.java) { event ->
if (event.itemId != "demo:sword") return@subscribe
event.addLore(
"item_description",
listOf(
"&7附属插件追加描述",
"&8Owner: {unique.player}"
)
)
}
提示
ItemReleaseDisplayBuildEvent 修改的是显示变量,不是现成的 ItemMeta。这份数据后面还会继续经过 ItemDisplay.build(...)、applyRuntimeDisplay() 和 ItemStreamTransport.sync(),更适合需要让 readItem() / rebuild() 继续理解的数据。
注意
如果你只在 ItemReleaseFinalEvent 里改 event.itemStack,玩家拿到的成品会变化,但 runtimeData 的显示语义不会同步更新。后续一旦进入重新构建或版本更新,这类“最后一跳补丁”就可能被覆盖。
动作触发事件
玩家与 Baikiruto 物品交互时触发的事件:
| 事件 | 说明 |
|---|---|
ItemInteractActionEvent | 物品交互(通用) |
ItemLeftClickActionEvent | 左键点击 |
ItemRightClickActionEvent | 右键点击 |
ItemUseActionEvent | 使用物品 |
ItemInteractEntityActionEvent | 右键点击实体 |
ItemAttackActionEvent | 攻击实体 |
ItemDamageActionEvent | 物品受损 |
ItemBlockBreakActionEvent | 使用物品破坏方块 |
ItemItemBreakActionEvent | 物品耐久耗尽损坏 |
ItemConsumeActionEvent | 消耗物品(食物/药水) |
ItemPickupActionEvent | 拾取物品 |
ItemDropActionEvent | 丢弃物品 |
ItemSwapToMainhandActionEvent | 切换到主手 |
ItemSwapToOffhandActionEvent | 切换到副手 |
ItemInventoryClickTriggerEvent | 在背包中点击物品 |
ItemInventoryClickActionEvent | 背包点击动作(双物品流) |
ItemSelectActionEvent | 选中物品(切换快捷栏) |
ItemAsyncTickActionEvent | 异步 Tick 触发 |
val bus = api.getItemEventBus()
// 监听右键点击
bus.subscribe(ItemRightClickActionEvent::class.java) { event ->
val player = event.player ?: return@subscribe
val itemId = event.itemId
player.sendMessage("你右键点击了 $itemId")
}
// 监听攻击
bus.subscribe(ItemAttackActionEvent::class.java) { event ->
println("${event.player?.name} 使用 ${event.itemId} 攻击了实体")
}
// 监听物品拾取
bus.subscribe(ItemPickupActionEvent::class.java) { event ->
println("${event.player?.name} 拾取了 ${event.itemId}")
}
Bukkit 代理事件
以下事件通过 Bukkit 原生事件系统分发,使用 @EventHandler 监听:
| 事件 | 说明 |
|---|---|
PluginReloadEvent.Item | 物品配置重载完成 |
PluginReloadEvent.Display | 显示配置重载完成 |
import org.bukkit.event.EventHandler
import org.bukkit.event.Listener
class BaikirutoListener : Listener {
@EventHandler
fun onItemReload(event: PluginReloadEvent.Item) {
println("Baikiruto 物品配置已重载")
// 刷新依赖 Baikiruto 物品的缓存
}
@EventHandler
fun onDisplayReload(event: PluginReloadEvent.Display) {
println("Baikiruto 显示配置已重载")
}
}
备注
生命周期事件和动作触发事件通过 ItemEventBus 订阅,Bukkit 代理事件通过标准的 @EventHandler 监听。两者不要混淆。