跳到主要内容

事件系统

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())

生命周期事件

物品从构建到销毁的完整生命周期:

事件说明
ItemBuildPreEventDefaultItem.build(...) 开始时触发,可修改本次构建要写入的 name / lore 变量
ItemBuildPostEventBUILD 脚本和 metas 执行完成后触发,可检查当前 ItemStream 状态
ItemReleaseEventItemStream.toItemStack() 进入释放链路时触发,可修改 icondataitemMeta
ItemReleaseDisplayEvent释放流程进入显示阶段时触发
ItemReleaseDisplayBuildEvent显示模板构建前触发,可修改 displayIddisplaynamelore
ItemReleaseFinalEventPlaceholder、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 监听。两者不要混淆。