Skip to content

📡 事件:QISkillUseEvent

上一页:API · 下一页:占位符

QS 的技能释放主链路是一个 Bukkit 事件 —— QISkillUseEvent。它由 QinhCoreLib 提供(不是 QS 也不是 QI),三方共用同一 EventBus 契约。本章讲它的字段、QS 自己怎么用它、以及别的插件如何监听 / 取消 / 读结果。本文档对应 QS 1.0.22


1. 事件身份

包名:com.qinhuai.corelib.action.skill
类名:QISkillUseEvent   (extends PlayerEvent, implements Cancellable)

为什么放在 CoreLib?因为 QI 负责"按下"、QS 负责"能不能放",两边都要引用同一个事件类型。把它放进双方都硬依赖的 CoreLib,才能共享同一条事件总线契约。

每一次技能释放(物品按键、命令、QinhSkillsAPI 调用、被动触发)都会经 SkillEventGateway.dispatch 发出一个该事件。


2. 字段一览

字段类型读/写含义
playerPlayer释放者(PlayerEvent.getPlayer()
payloadString原始 payload(技能 id / JSON)
triggerString兼容字符串触发标签(如 "api"、QI action 键)
triggerTypeTriggerType归一后的触发枚举(fromLegacy(trigger)
itemItemStack?触发用的物品(命令/API 触发时为 null)
itemIdString?触发物品的 id
rawContextRawSkillContext?原始上下文(可空),承载 itemId / item / 潜行 / 来源等触发现场信息,由 QinhCoreLib 提供
skillHandledBoolean读/写QS 是否已处理(成功释放时置 true)
castResultString?读/写CastResult.name(如 "SUCCESS""ON_COOLDOWN"
castAttemptedBoolean读/写是否进入过门控/执行尝试
fallbackInvokedBoolean读/写是否走了 fallback 处理器
mythicInvokedBoolean读/写是否调到了 MythicMobs 执行
primaryPipelineBoolean读/写是否主链路(默认 true)

取消相关:isCancelled() / setCancelled(Boolean)(来自 Cancellable)。

⚠️ castResult字符串,不是枚举。它是 CastResult.name。要拿枚举请 CastResult.valueOf(it)(注意未来新增结果码时做容错)。


3. QS 自己怎么用它

QS 内部有两条相关角色:

a) 网关发事件 —— SkillEventGateway

SkillEventGateway.dispatch 构造事件并 callEvent,随后根据结果回收 CastResult

kotlin
val event = QISkillUseEvent(
    player = player,
    payload = payload,
    trigger = trigger,
    triggerType = TriggerType.fromLegacy(trigger),
)
Bukkit.getPluginManager().callEvent(event)
if (event.isCancelled) return CastResult.SCRIPT_BLOCKED
if (!event.skillHandled) return event.castResult?.let { CastResult.valueOf(it) } ?: CastResult.MYTHIC_FAILED
return event.castResult?.let { CastResult.valueOf(it) } ?: CastResult.SUCCESS

b) 监听并执行 —— QS 的核心监听器

QS 监听 QISkillUseEvent,跑完整运行时(归一 → 状态机 → 图解析 → 门控 → 执行 → 后处理),然后回填 skillHandled / castResult / mythicInvoked 等字段。

c) QI 动作系统对接 —— QiListener

QS 还实现了 CoreLib 的 QinhActionHandler 契约(QiListener),用 handlerId = "qinhskills:cast" 注册进 QI 的动作系统。这条是 fallback 路径(主链路是 QI 直接 dispatchViaEvent 发事件),它不合成第二个事件,只在主链未处理时兜底。

kotlin
class QiListener : QinhActionHandler {
    override val handlerId: String = QISkillBridge.HANDLER_ID   // "qinhskills:cast"
    override fun isAvailable(): Boolean = true
    override fun dispatch(context: QinhActionContext): ActionDispatchResult { /* 兜底执行 */ }
}

4. 别的插件如何监听

任意插件都可注册标准 Bukkit 监听器。常见用途:审计、封禁某些技能、对释放打 buff/记录

读结果(监听后,优先级靠后)

kotlin
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
fun onSkill(event: QISkillUseEvent) {
    val skillId = QinhSkillsAPI.resolvePayloadSkillId(event.payload) ?: return
    if (event.skillHandled && event.castResult == "SUCCESS") {
        plugin.logger.info("${event.player.name} 成功释放 $skillId(mythic=${event.mythicInvoked})")
    }
}

取消(拦截某技能)

kotlin
@EventHandler(priority = EventPriority.HIGH)
fun blockInArena(event: QISkillUseEvent) {
    val skillId = QinhSkillsAPI.resolvePayloadSkillId(event.payload) ?: return
    if (skillId == "dash" && inSafeZone(event.player)) {
        event.isCancelled = true   // QS 收到取消 → 回 SCRIPT_BLOCKED,技能不放
    }
}

取消事件会让 SkillEventGateway 返回 CastResult.SCRIPT_BLOCKED,技能不会释放、不扣资源、不进冷却。


5. 监听优先级建议

你想做的事建议优先级说明
拦截 / 阻止某些技能HIGH / HIGHEST在 QS 处理前取消
只读结果做记录MONITOR + ignoreCancelled = trueQS 已回填 castResult
改 payload 前置数据LOWEST极少需要;注意别破坏归一

QS 的核心监听处于中段优先级并回填字段。把你的"只读"逻辑放 MONITOR 才能读到 QS 的最终判定结果。


6. payload 怎么解析

事件里的 payload 可能是纯技能 id,也可能是物品插件透传的 JSON。别自己手撕,交给 API:

kotlin
val skillId: String? = QinhSkillsAPI.resolvePayloadSkillId(event.payload)

返回值统一小写,解析不出返回 null


继续阅读

  • APIQinhSkillsAPI 与编程式释放
  • 脚本 API — 在 pre_js / post_js 里拦截/副作用(事件之外的另一道口)
  • 诊断与协议 — 用 debug trace 看事件 [EVENT] 阶段