事件监听开发
监听和处理 Zaphkiel 物品事件
概述
Zaphkiel 提供了丰富的事件系统,允许开发者监听物品的各种状态变化和交互行为。通过监听这些事件,你可以在物品构建、释放、交互等关键时刻执行自定义逻辑。
事件系统架构
事件监听机制
Zaphkiel 的事件系统通过 ItemListener
监听 Bukkit 事件并转换为 Zaphkiel 特定的事件:
@SubscribeEvent
fun onInteract(e: PlayerInteractEvent) {
if (e.item.isAir()) {
return
}
val itemStream = e.item!!.toItemStream()
if (itemStream.isVanilla()) {
return
}
// 触发事件
val event = ItemEvent.Interact(itemStream, e)
if (event.call()) {
if (event.save) {
event.itemStream.rebuildToItemStack(e.player)
}
// 执行脚本
when (e.action) {
Action.LEFT_CLICK_AIR, Action.LEFT_CLICK_BLOCK -> {
itemStream.getZaphkielItem().invokeScript(listOf("on_left_click", "onLeftClick"), e, itemStream)
}
Action.RIGHT_CLICK_AIR, Action.RIGHT_CLICK_BLOCK -> {
itemStream.getZaphkielItem().invokeScript(listOf("on_right_click", "onRightClick"), e, itemStream)
}
}
}
}
核心事件类型
物品构建事件
物品构建过程中的事件:
// 监听构建前事件
@EventHandler
fun onItemBuildPre(event: ItemBuildEvent.Pre) {
val item = event.item
val player = event.player
val itemStream = event.itemStream
// 可以修改名称和描述
if (item.id == "special_weapon") {
event.addName("custom_suffix", " [特殊]")
event.addLore("warning", "&c注意:这是特殊武器")
}
// 可以取消构建
if (player != null && !player.hasPermission("zaphkiel.special")) {
event.isCancelled = true
}
}
// 监听构建后事件
@EventHandler
fun onItemBuildPost(event: ItemBuildEvent.Post) {
val item = event.item
val itemStream = event.itemStream
// 构建完成后的处理
if (item.id.startsWith("magic_")) {
// 添加魔法物品标记
itemStream.getZaphkielData().putDeep("magic_item", true)
}
}
物品释放事件
物品从 ItemStream 转换为 ItemStack 时的事件:
// 监听物品释放事件
@EventHandler
fun onItemRelease(event: ItemReleaseEvent) {
val itemStream = event.itemStream
val item = event.item
// 修改物品材质
if (item.id == "rainbow_sword") {
val colors = listOf(Material.RED_WOOL, Material.BLUE_WOOL, Material.GREEN_WOOL)
event.icon = colors.random()
}
// 修改物品 Meta
val lore = event.itemMeta.lore?.toMutableList() ?: mutableListOf()
lore.add("&7释放时间: ${System.currentTimeMillis()}")
event.itemMeta.lore = lore
}
// 监听显示选择事件
@EventHandler
fun onDisplaySelect(event: ItemReleaseEvent.SelectDisplay) {
val itemStream = event.itemStream
val player = event.player
// 根据玩家等级选择不同显示模板
if (player != null && player.level >= 50) {
val advancedDisplay = Zaphkiel.api().getItemManager().getDisplay("advanced_display")
if (advancedDisplay != null) {
event.display = advancedDisplay
}
}
}
// 监听显示生成事件
@EventHandler
fun onDisplayGenerate(event: ItemReleaseEvent.Display) {
val itemStream = event.itemStream
val player = event.player
// 动态修改显示内容
if (player != null) {
event.addName("player_name", player.name)
event.addLore("player_level", "玩家等级: ${player.level}")
}
}
物品交互事件
玩家与物品交互时的事件:
// 监听物品交互事件
@EventHandler
fun onItemInteract(event: ItemEvent.Interact) {
val itemStream = event.itemStream
val bukkitEvent = event.bukkitEvent
val player = bukkitEvent.player
// 检查特定物品
if (itemStream.getZaphkielItem().id == "teleport_wand") {
// 处理传送逻辑
val data = itemStream.getZaphkielData()
val cooldown = data.getDeep("cooldown")?.asLong() ?: 0L
if (System.currentTimeMillis() - cooldown > 5000) {
// 执行传送
player.teleport(player.world.spawnLocation)
data.putDeep("cooldown", System.currentTimeMillis())
event.save = true // 标记需要保存
} else {
player.sendMessage("&c传送冷却中...")
bukkitEvent.isCancelled = true
}
}
}
// 监听物品消耗事件
@EventHandler
fun onItemConsume(event: ItemEvent.Consume) {
val itemStream = event.itemStream
val bukkitEvent = event.bukkitEvent
val player = bukkitEvent.player
// 自定义消耗逻辑
if (itemStream.getZaphkielItem().id == "magic_potion") {
// 给予特殊效果
player.addPotionEffect(PotionEffect(PotionEffectType.SPEED, 600, 1))
player.sendMessage("&a你感到身体变得轻盈!")
}
}
高级事件监听
异步事件处理
// 监听异步 Tick 事件
@EventHandler
fun onAsyncTick(event: ItemEvent.AsyncTick) {
val itemStream = event.itemStream
val player = event.player
// 异步处理逻辑(不要修改 Bukkit 对象)
val item = itemStream.getZaphkielItem()
if (item.id == "energy_crystal") {
val data = itemStream.getZaphkielData()
val energy = data.getDeep("energy")?.asInt() ?: 0
// 每 5 秒恢复 1 点能量
if (energy < 100) {
data.putDeep("energy", energy + 1)
event.save = true
}
}
}
背包点击事件
// 监听背包点击事件
@EventHandler
fun onInventoryClick(event: ItemEvent.InventoryClick) {
val currentStream = event.itemStreamCurrent
val buttonStream = event.itemStreamButton
val bukkitEvent = event.bukkitEvent
// 处理特殊物品的点击
if (currentStream != null && currentStream.getZaphkielItem().id == "locked_item") {
// 阻止移动锁定物品
bukkitEvent.isCancelled = true
bukkitEvent.whoClicked.sendMessage("&c这个物品已被锁定!")
}
// 处理组合逻辑
if (currentStream != null && buttonStream != null) {
val currentId = currentStream.getZaphkielItem().id
val buttonId = buttonStream.getZaphkielItem().id
if (currentId == "upgrade_stone" && buttonId == "basic_sword") {
// 执行升级逻辑
handleItemUpgrade(bukkitEvent.whoClicked as Player, currentStream, buttonStream)
event.saveCurrent = true
event.saveButton = true
}
}
}
事件优先级和取消
设置事件优先级
// 高优先级监听器(最先执行)
@EventHandler(priority = EventPriority.HIGHEST)
fun onItemBuildHighest(event: ItemBuildEvent.Pre) {
// 最高优先级的处理逻辑
}
// 低优先级监听器(最后执行)
@EventHandler(priority = EventPriority.LOWEST)
fun onItemBuildLowest(event: ItemBuildEvent.Pre) {
// 最低优先级的处理逻辑
}
事件取消处理
@EventHandler
fun onItemBuild(event: ItemBuildEvent.Pre) {
val item = event.item
val player = event.player
// 条件检查
if (player != null && !player.hasPermission("zaphkiel.use." + item.id)) {
event.isCancelled = true
player.sendMessage("&c你没有权限使用这个物品!")
return
}
// 其他逻辑...
}
事件数据操作
修改物品数据
@EventHandler
fun onItemBuild(event: ItemBuildEvent.Pre) {
val itemStream = event.itemStream
val player = event.player
// 根据玩家属性调整物品数据
if (player != null) {
val data = itemStream.getZaphkielData()
val baseDamage = data.getDeep("damage")?.asInt() ?: 10
// 根据玩家等级增加伤害
val levelBonus = player.level * 2
data.putDeep("damage", baseDamage + levelBonus)
// 添加玩家绑定信息
data.putDeep("owner", player.uniqueId.toString())
}
}
动态显示内容
@EventHandler
fun onDisplayGenerate(event: ItemReleaseEvent.Display) {
val itemStream = event.itemStream
val player = event.player
// 获取物品数据
val data = itemStream.getZaphkielData()
val damage = data.getDeep("damage")?.asInt() ?: 0
val owner = data.getDeep("owner")?.asString()
// 动态添加显示内容
event.addLore("damage_info", "&c伤害: &f$damage")
if (owner != null) {
val ownerName = Bukkit.getOfflinePlayer(UUID.fromString(owner)).name
event.addLore("owner_info", "&7所有者: &f$ownerName")
}
// 添加时间戳
val timestamp = SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(Date())
event.addLore("timestamp", "&8生成时间: $timestamp")
}
性能优化
事件过滤
@EventHandler
fun onItemInteract(event: ItemEvent.Interact) {
val itemStream = event.itemStream
val item = itemStream.getZaphkielItem()
// 早期过滤,避免不必要的处理
if (!item.id.startsWith("special_")) {
return
}
// 只处理特定类型的物品
when (item.id) {
"special_weapon" -> handleWeaponInteract(event)
"special_tool" -> handleToolInteract(event)
"special_consumable" -> handleConsumableInteract(event)
}
}
异步处理
@EventHandler
fun onItemBuild(event: ItemBuildEvent.Post) {
val itemStream = event.itemStream
val player = event.player
// 将耗时操作移到异步线程
submitAsync {
val data = performExpensiveCalculation(itemStream, player)
// 回到主线程更新数据
submit {
itemStream.getZaphkielData().putDeep("calculated_data", data)
}
}
}