Skip to content

动作处理器开发

所属:开发者 · 相关:动作系统 · 处理器

QI 的动作 YAML 不能写逻辑分支。要把 if/switch/状态判断引入动作系统,唯一正道是实现一个动作处理器,逻辑写在 Kotlin/Java 里,YAML 只引用它并传 payload。


1. 接口 QinhActionHandler

kotlin
interface QinhActionHandler {
    val handlerId: String                                  // 唯一 ID,建议 "命名空间:名"
    fun dispatch(context: QinhActionContext): ActionDispatchResult
    fun isAvailable(): Boolean = true                      // 依赖插件未启用时返回 false
}

返回值 ActionDispatchResult

含义
HANDLED成功执行(会触发扣消耗 / 记冷却)
NOT_HANDLED处理器拒绝(如校验失败)
HANDLER_UNAVAILABLE依赖未加载

2. 上下文 QinhActionContext

kotlin
data class QinhActionContext(
    val trigger: String,                 // 触发器名(如 "left_click")
    val player: Player,
    val item: ItemStack,
    val itemId: String,
    val handlerId: String,
    val payload: String,                 // YAML 里传的原始 payload
    val compileEpoch: Long?,
    val providerSnapshot: ProviderSnapshot,
    val triggerType: TriggerType?,
    val rawContext: RawSkillContext,     // 扩展上下文(潜行状态等)
)

3. 注册

kotlin
QinhItemsAPI.actions().registerHandler(object : QinhActionHandler {
    override val handlerId = "myplugin:smart_cast"

    override fun dispatch(ctx: QinhActionContext): ActionDispatchResult {
        val payload = ctx.payload.trim()
        if (payload.isEmpty()) return ActionDispatchResult.NOT_HANDLED

        // 复杂逻辑:if / switch / 状态判断都写这里
        if (ctx.player.level < 10) {
            ctx.player.sendMessage("§c等级不足")
            return ActionDispatchResult.NOT_HANDLED
        }

        ctx.player.sendMessage("释放:$payload")
        return ActionDispatchResult.HANDLED
    }
})

在你插件的 onEnable() 里注册即可。之后 YAML 就能引用:

yaml
refs:
  - handler: myplugin:smart_cast
    payload: "fireball"

4. payload schema

可选:为处理器声明字段结构,让 GUI 编辑器自动生成表单并做校验。

kotlin
QinhItemsAPI.actions().registerPayloadSchema("myplugin:smart_cast") {
    serializeMode = PayloadSerializeMode.JSON      // 或 PLAIN
    string(key = "skill", required = true, label = "技能 ID")
    int(key = "power", default = "1", label = "强度")
    double(key = "multiplier", label = "倍数")
    bool(key = "silent", default = "false", label = "静默?")
}

字段类型

DSL类型校验
string(...)STRING任意文本
int(...)INT整数
double(...)DOUBLE浮点
bool(...)BOOLtrue/false/1/0

序列化模式

  • PLAIN:单字段,payload 是裸字符串。
  • JSON:多字段,payload 是 JSON 对象,如 {"skill":"fireball","power":"2"}

GUI 编辑流程见 动作编辑器。Codec 操作:

kotlin
PayloadSchemaCodec.defaults(schema)                  // 默认值
PayloadSchemaCodec.deserializeForEditor(schema, payload)
PayloadSchemaCodec.serialize(schema, editorMap)
PayloadSchemaValidator.validate(schema, fieldMap)    // Result(ok, errors)

5. 直接派发(不经触发器)

kotlin
val report = QinhItemsAPI.actions().dispatch(player, item, "left_click")

返回 DispatchReport,含每个处理器的结果。


6. 边界回顾

谁做什么
服主写「什么时候发生什么」:触发器 + refs
开发者写「怎么发生」:处理器内部逻辑

服主在 YAML 里组合处理器,开发者把复杂度收进处理器。这条边界让配置可被 GUI 完整编辑,见 动作系统概览 → 设计


7. 校验:处理器引用

保存 / 加载时 ActionRefDeclarationValidator 会校验:handler 非空、无空格、建议 命名空间:id 格式;未注册的 handler 会警告(运行时 HANDLER_UNAVAILABLE)。


下一步