Skip to content

Action System Overview

Belongs to: Server Owner Guide → Action System · Subpages: Triggers · Handlers · Cooldown/Cost/Condition

The action system is the "active effect / skill" engine for QI items: the player does something (trigger) → executes a chain of effects (handlers). This page covers the overall structure and YAML syntax; details are split into subpages.


1. What an action looks like

yaml
my_item:
  actions:
    triggers:
      left_click:                    # trigger name (custom)
        trigger:
          atom: left_click           # trigger atom, see Triggers
        cooldown: 3s                 # cooldown, see Cooldown/Cost/Condition
        consume:                     # resource cost
          - "item:minecraft-redstone:1"
        conditions:                  # trigger conditions (all must pass to execute)
          - "player_level:>=10"
        refs:                        # handler references executed in order
          - handler: qi:title
            payload: "<gold>Spark</gold>||<gray>Blade Resonance</gray>||3||30||10"
          - handler: qi:sound
            payload: "minecraft:entity.player.attack.crit;1;1.2"

Structure hierarchy:

actions:
  triggers:
    <trigger name>:
      trigger: { atom: ... }   or   trigger: { sequence: [...] , window: ms }
      cooldown: <duration>          (optional)
      consume: [ <cost>, ... ]   (optional)
      conditions: [ <condition>, ... ] (optional)
      refs:
        - handler: <handler ID>
          payload: <payload>
        - ...

2. Execution flow

player action (e.g. left click)
  → trigger atom left_click matches
  → evaluate all conditions (must all be true)
  → check cooldown (stop if on cooldown)
  → pre-trigger event QinhActionTriggerEvent (cancellable by plugins)
  → check consume (stop if resources are insufficient)
  → execute each ref's handler in order (passing payload)
        each handler returns HANDLED / NOT_HANDLED / HANDLER_UNAVAILABLE
        post-dispatch event QinhActionDispatchedEvent (for listening)
  → if any handler returns HANDLED:
        deduct consume, record cooldown

For event details, see Events.


3. Key design: no logic in YAML

QI deliberately forbids writing flow control in action YAML: if / else / when / unless / switch / filter / rules / flow, etc., are all forbidden fields (ActionRoutingPolicy). Under a trigger, it is simply "run a chain of handlers in order"; handlers do not depend on each other's results.

What if you need complex logic? Have a developer implement an action handler, writing the if/switch/state checks into Kotlin/Java, while the YAML only references it and passes a payload.

This boundary keeps the configuration simple and fully editable by a GUI. When action-routing.strict: true in config.yml, violations raise an error; when false, they only produce a warning.


4. Where actions are loaded from

SourceDescription
Embedded (recommended)Written directly in the item YAML's actions.triggers section
Standalone fileThe actions_file field points to a separate file (deprecated, embedding recommended)

⚠️ Actions are only loaded on /qi reload. After changing the YAML, you must reload, otherwise it won't take effect. Reloading resets all cooldowns and combo states.


5. Triggers and handlers at a glance

  • Trigger: 100+ atoms. Click-type (left/right/shift), sneak (single click / double click / sequence), movement (sprint / glide / jump), combat (hit / take damage / kill / crit), container / crafting, entity interaction, environment, server events, tick periodic. For the full list, see Triggers.
  • Handler: 10 built-in (qi:message / qi:action_bar / qi:title / qi:subtitle / qi:sound / qi:bossbar / qi:command / qi:console_command / qi:give_item / qi:close_inventory) + ecosystem (qinhskills:cast / combat:swing). For each one's payload format, see Handlers.

6. A complete multi-action item

yaml
legendary_sword:
  type: weapon
  material: diamond_sword
  display_name: "<gold>Legendary Blade</gold>"
  actions:
    triggers:
      # single atom + condition
      left_click:
        trigger:
          atom: left_click
        cooldown: 1s
        conditions:
          - "player_level:>=15"
        refs:
          - handler: qi:action_bar
            payload: "<gold>▶ Slash</gold>"
          - handler: combat:swing
            payload: "light"

      # sequence combo (sneak → left click → left click)
      whirlwind:
        trigger:
          sequence:
            - sneak_down
            - left_click
            - left_click
          window: 400              # inter-step window (milliseconds)
        cooldown: 5s
        consume:
          - "level:2"
        refs:
          - handler: qi:message
            payload: "<gold>Whirlwind Slash!</gold>"
          - handler: qinhskills:cast
            payload: '{"skill":"whirlwind_slash","level":1}'

      # on-hit trigger
      on_hit:
        trigger:
          atom: on_hit
        cooldown: 3s
        consume:
          - "item:redstone:1"
        conditions:
          - "player_sneaking:true"
        refs:
          - handler: qi:title
            payload: "<red>Counter!</red>||<dark_red>+10 Defense</dark_red>||5||20||5"
          - handler: combat:swing
            payload: "heavy"

🖼️ [Image placeholder] In-game scene at the moment an action triggers (title + sound + particles) · suggested assets/action-trigger.png


7. Diagnosing actions

CommandPurpose
/qi trigger reportShow the ActionTable trigger configuration report
/qi trigger test [itemId] [player]Manually execute the first trigger binding of a given item
/qi status / /qi diagnoseView action table loading status and issues

See Commands.


Subpage navigation