Skip to content

Mechanism System (triggers × actions)

In: Server Admin Guide Overview · Previous: Spawning & Clearing · Next: Placement Profiles

Related: Blueprint & Objectives · Mechanism Editing · config.yml Full Configuration


A Mechanism is a programmable world interaction in the blueprint: "trigger → a chain of actions." A player steps on a plate, digs through a wall, walks into a region, advances a stage, applies a redstone charge… and the actions you configured run: open a door, spawn an ambush, play a title, give a reward, teleport…

🔑 Architecture red line: a mechanism is pure world interaction and never touches attributes / damage. It can fill blocks, spawn mobs, play sounds, and dispense loot, but it won't change anyone's attack or health—that's the job of QinhItems / attribute plugins. This is of a piece with QR's overall "doesn't compute numbers" stance (see Core Concepts).

Mechanisms are written in the mechanisms section of templates/<template-id>/blueprint.yml, and can also be configured visually with /qr editor's Mechanism Editing.

🖼️ [Image placeholder] A "trigger → action chain" flow illustration (step on plate → spawn ambush + play title + play sound) · suggested assets/mechanism-flow.png


1. What a mechanism looks like

Each mechanism is an entry in the mechanisms list:

yaml
mechanisms:
  - id: open_door                                    # Unique identifier
    trigger: { type: REDSTONE, x: 4, y: 1, z: 0 }    # Trigger: which kind, where
    actions:                                         # Action chain: executed in order
      - { type: FILL, from: { x: 3, y: 1, z: 0 }, to: { x: 5, y: 3, z: 0 }, material: AIR }
    once: false        # Whether to trigger only once
    cooldown: 0        # Cooldown (seconds)
    require-stage: 0   # Required stage
    radius: 24         # Audience / effect radius (blocks)

Mechanism top-level fields

FieldMeaningDefaultNotes
idUnique identifier of the mechanismrequiredNo duplicates within the same blueprint
triggerTrigger (see §2)requiredContains type and the corresponding pos / region / interval / stage
actionsAction chain (see §3)requiredA list, executed in order; a mechanism with an empty list is ignored
onceWhether to trigger only oncefalsetrue = this anchor triggers only once ever (persistently recorded, survives reload)
cooldownTrigger cooldown (seconds)0After triggering, no response for N seconds
require-stageRequired stage0Only triggers when the current clear stage ≥ this value; 0 = unrestricted
radiusAudience / effect radius (blocks)24Used by "find nearby players" actions like MESSAGE / TITLE / SOUND / EFFECT / TELEPORT(all)

Caution

All coordinates are relative to the structure origin (structure minimum corner = 0,0,0), consistent with the other blueprint fields. See Blueprint & Objectives §1.

The pre-fire gates (check order before firing)

After a mechanism is hit by its trigger, it passes these checks in order before the actions actually run:

  1. require-stage: current clear stage insufficient → skip.
  2. once: already triggered (present in the persistent record) → skip.
  3. cooldown: still on cooldown → skip.
  4. All passed → execute actions in order; if once, record it; if there's a cooldown, start the timer.

2. The 6 triggers (MechTriggerType)

trigger.type decides "what triggers this mechanism," 6 in total. Different triggers read different fields from trigger:

Trigger typeTrigger conditionRequired fields
INTERACTPlayer right-clicks the specified blockx/y/z (trigger block coordinate)
BLOCK_BREAKPlayer mines the specified blockx/y/z (trigger block coordinate)
REDSTONEThe specified block goes from unpowered to powered (rising edge)x/y/z (trigger block coordinate)
REGION_ENTERPlayer walks into the specified region (fires once on entry)from + to (the two corners of the region)
TIMERWhile a player is nearby, fires every N secondsinterval (seconds)
STAGEFires when clear progress advances to the specified stagestage (stage number)

How to write trigger fields

yaml
# Block kinds (INTERACT / BLOCK_BREAK / REDSTONE): give a single-point coordinate
trigger: { type: INTERACT, x: 4, y: 1, z: 0 }

# Region kind (REGION_ENTER): give the from / to corners
trigger:
  type: REGION_ENTER
  from: { x: 2, y: 1, z: 2 }
  to:   { x: 6, y: 3, z: 6 }

# Timer kind (TIMER): give interval (seconds)
trigger: { type: TIMER, interval: 30 }

# Stage kind (STAGE): give stage
trigger: { type: STAGE, stage: 2 }

A few key behaviors

  • REDSTONE only triggers on the rising edge (the moment it goes from 0 power to powered); it won't keep firing because of sustained power.
  • BLOCK_BREAK's trigger block is allowed to be dug through—even when the ruin is in protection lock, this block can be broken (otherwise it couldn't trigger). See Spawning & Clearing §5.
  • REGION_ENTER is "fires once on entry": standing inside the region won't repeatedly trigger; you have to walk out and back in for it to trigger again.
  • TIMER requires a nearby player for its timer to advance (it doesn't idle-spin when nobody's around).
  • INTERACT only recognizes a main-hand right-click on the block.

⚙️ REGION_ENTER and TIMER rely on background periodic scanning, constrained by config.yml's mechanisms.scan-radius (default 48, mechanisms are only evaluated when a player enters this range) and mechanisms.period-ticks (default 10, evaluation interval). Block kinds (INTERACT / BLOCK_BREAK / REDSTONE) respond instantly via events and don't consume the scan budget.


3. The 12 actions (MechActionType)

Each item's type in actions decides what it does, 12 in total. Action parameters have two writing styles:

  • Structured coordinates: pos / from / to (written as { x:.., y:.., z:.. }), used for positional actions;
  • params: every remaining key besides type / pos / from / to / x / y / z is read as a parameter (values parsed as strings).

Below, each one is explained, listing which parameters it reads.

1. FILL — fill a region with blocks

Fill an entire region with a certain block (open a door, cave-in, raise a wall, flood with water…).

ParameterMeaningDefault
from / toThe two corners of the region (relative coordinates)required
materialFill material (Bukkit Material name)AIR
yaml
# Fill the doorway with air = open the door
- { type: FILL, from: { x: 3, y: 1, z: 0 }, to: { x: 5, y: 3, z: 0 }, material: AIR }
# Raise a stone wall to block the path
- { type: FILL, from: { x: 0, y: 1, z: 5 }, to: { x: 8, y: 4, z: 5 }, material: STONE }

Caution

A region whose volume exceeds config.yml's mechanisms.max-fill-volume (default 20000 blocks) is skipped outright to prevent server lag. For large-scale remodeling, split it into multiple mechanisms or raise the limit. A misspelled material name is silently skipped.

2. SPAWN — spawn mobs

Spawn mobs at a specified point (ambush, reinforcement, stage boss).

ParameterMeaningDefault
posSpawn point (relative coordinates)(0,0,0)
mobMob key: vanilla name or mm-<MM name>required
levelLevel (only takes effect for MM mobs)1
countHow many to spawn1
yaml
- { type: SPAWN, pos: { x: 5, y: 2, z: 8 }, mob: ZOMBIE, count: 4, level: 1 }
- { type: SPAWN, pos: { x: 6, y: 2, z: 9 }, mob: mm-FireSkeleton, count: 1, level: 5 }

Tip

Mobs spawned by a SPAWN mechanism carry no clear-kill marker and don't count toward objectives stage progress. For mobs that should count toward progress, use the blueprint's spawn-points (see Blueprint & Objectives). Mechanism SPAWN suits "atmospheric ambushes."

3. MESSAGE — chat message

Send one line of chat message to players within the radius.

ParameterMeaning
textMessage text (supports color codes)
yaml
- { type: MESSAGE, text: "&c机关启动!小心脚下!" }

Constrained by radius (sent to players near the triggerer).

4. TITLE — screen title

Display a screen title to players within the radius.

ParameterMeaning
titleMain title
subtitleSubtitle (optional)
yaml
- { type: TITLE, title: "&6封印解除", subtitle: "&7通往深处的门已开启" }

5. SOUND — sound effect

Play a sound to players within the radius.

ParameterMeaningDefault
soundSound name (Bukkit Sound name)required
volumeVolume1.0
pitchPitch1.0
yaml
- { type: SOUND, sound: BLOCK_PISTON_EXTEND, volume: 1.0, pitch: 0.8 }

6. EFFECT — potion effect

Apply a potion effect to players within the radius (slowness trap, blindness, night-vision buff…).

ParameterMeaningDefault
effectEffect name (PotionEffectType name)required
levelLevel (from 1, 1 = base level)1
secondsDuration in seconds5
yaml
- { type: EFFECT, effect: SLOWNESS, level: 2, seconds: 8 }

7. COMMAND — execute a command

Execute a command. {player} is replaced with the triggerer's name.

ParameterMeaningDefault
commandCommand (leading / may be omitted)required
asAs whom: console (console) / player (the triggering player)console
yaml
# Console gives the triggerer money
- { type: COMMAND, command: "eco give {player} 100", as: console }
# Execute as the player
- { type: COMMAND, command: "warp dungeon_exit", as: player }

Tip

With as: player the triggering player runs the command themselves, subject to their permissions; as: console has full console permissions.

8. LOOT — dispense loot

Dispense loot to the triggerer per a loot table (dropped on the ground).

ParameterMeaningDefault
tableLoot table name (loottables/<name>.yml)required
posDrop point (relative coordinates); if omitted, drops at the triggerer's feettriggerer's position
growth-scaledWhether to scale quantity by growthtrue
yaml
- { type: LOOT, table: vault, pos: { x: 6, y: 1, z: 6 }, growth-scaled: true }

Caution

Requires a triggerer (player) to dispense; a mechanism triggered without a player (REDSTONE / STAGE, etc.) using LOOT won't dispense because there's no recipient.

9. TELEPORT — teleport

Teleport players to a specified point.

ParameterMeaningDefault
posDestination point (relative coordinates)required
yawFacing yaw (optional)unchanged
pitchFacing pitch (optional)unchanged
targetWho to teleport: trigger (triggerer only) / all (everyone within the radius)trigger
yaml
# Teleport the triggerer to a secret room
- { type: TELEPORT, pos: { x: 2, y: 10, z: 2 }, yaw: 90, target: trigger }
# Pull the whole team into the boss room
- { type: TELEPORT, pos: { x: 10, y: 1, z: 10 }, target: all }

10. PARTICLE — particles

Emit particles at a specified point for visual effect.

ParameterMeaningDefault
posParticle center (relative coordinates)(0,0,0)
particleParticle name (Bukkit Particle name)FLAME
countParticle count (1–2000)20
spreadSpread radius0.5
yaml
- { type: PARTICLE, pos: { x: 6, y: 2, z: 6 }, particle: SOUL_FIRE_FLAME, count: 60, spread: 1.0 }

11. GIVE — give an item

Put an item directly into the triggerer's inventory (drops at their feet if full).

ParameterMeaningDefault
itemItem reference (item-source identifier such as qi-xxx, resolved by the CoreLib item bridge)required
amountQuantity1
yaml
- { type: GIVE, item: qi-dungeon_key, amount: 1 }

Tip

item goes through CoreLib's unified item bridge and can reference item sources like QinhItems / MMOItems / vanilla; if it can't be resolved, nothing is given. Requires a triggering player.

12. NPC — spawn an NPC

Spawn a Citizens NPC at a specified point (gatekeeper, guide, story character).

ParameterMeaningDefault
posSpawn point (relative coordinates)(0,0,0)
nameNPC nameNPC
skinSkin (player name, optional)unset
yawFacing yaw (optional)unset
yaml
- { type: NPC, pos: { x: 4, y: 1, z: 4 }, name: "&e守墓人", skin: Notch, yaw: 180 }

Caution

The NPC action requires Citizens installed; without it, this action has no effect.


4. config.yml — mechanisms section

The global switch and rate limiting for the mechanism system are in config.yml:

yaml
# Programmable mechanisms (in-blueprint trigger→action, pure world interaction not attributes)
mechanisms:
  enabled: true           # Master switch (off = no mechanisms respond server-wide)
  scan-radius: 48         # Region/timer trigger scan radius (mechanisms evaluated only when a player enters this range)
  period-ticks: 10        # Region/timer trigger evaluation interval in ticks (larger = cheaper, slower region-entry response, floor 2)
  max-fill-volume: 20000  # Max blocks per FILL action (prevents oversized-region lag)
ConfigMeaningDefault
mechanisms.enabledMechanism system master switchtrue
mechanisms.scan-radiusScan radius for REGION_ENTER / TIMER48
mechanisms.period-ticksEvaluation interval in ticks for REGION_ENTER / TIMER10
mechanisms.max-fill-volumeMax blocks per FILL (excess skipped)20000

5. Complete example set

Example 1: pressure-plate door (region entry → open door + prompt)

The player walks into the area in front of the door; the doorway is automatically filled with air, with a sound and a prompt:

yaml
mechanisms:
  - id: auto_door
    trigger:
      type: REGION_ENTER
      from: { x: 3, y: 1, z: 7 }
      to:   { x: 5, y: 2, z: 8 }
    actions:
      - { type: FILL, from: { x: 3, y: 1, z: 9 }, to: { x: 5, y: 3, z: 9 }, material: AIR }
      - { type: SOUND, sound: BLOCK_IRON_DOOR_OPEN, volume: 1.0, pitch: 1.0 }
      - { type: MESSAGE, text: "&7一道暗门在你面前缓缓开启……" }
    cooldown: 3
    radius: 16

Example 2: dig through a hidden wall to spawn an ambush (break block → spawn + title)

The player mines the marker block hidden in the wall, triggering the ambush:

yaml
mechanisms:
  - id: ambush
    trigger: { type: BLOCK_BREAK, x: 6, y: 2, z: 4 }
    actions:
      - { type: TITLE, title: "&c埋伏!", subtitle: "&7你触发了陷阱" }
      - { type: SOUND, sound: ENTITY_ZOMBIE_AMBIENT, volume: 1.0, pitch: 0.7 }
      - { type: SPAWN, pos: { x: 6, y: 2, z: 5 }, mob: ZOMBIE, count: 4, level: 1 }
      - { type: SPAWN, pos: { x: 7, y: 2, z: 5 }, mob: mm-FireSkeleton, count: 1, level: 3 }
    once: true        # This wall ambushes only once
    require-stage: 1  # Only triggers after stage one

Example 3: stage-completion teleport + reward (stage advance → teleport whole team into boss room + dispense reward)

When clear progress advances to stage 2, pull everyone nearby into the secret chamber and dispense loot:

yaml
mechanisms:
  - id: stage2_gate
    trigger: { type: STAGE, stage: 2 }
    actions:
      - { type: TITLE, title: "&6前哨已肃清", subtitle: "&7深处的守卫苏醒了" }
      - { type: TELEPORT, pos: { x: 10, y: 1, z: 10 }, yaw: 0, target: all }
      - { type: LOOT, table: vault, pos: { x: 10, y: 1, z: 12 }, growth-scaled: true }
    once: true
    radius: 32

Example 4: timed mechanism (timer → periodic particles + slowness)

While a player is nearby, emit poison-mist particles and apply slowness every 20 seconds, creating a dangerous room:

yaml
mechanisms:
  - id: poison_room
    trigger: { type: TIMER, interval: 20 }
    actions:
      - { type: PARTICLE, pos: { x: 6, y: 2, z: 6 }, particle: SNEEZE, count: 80, spread: 3.0 }
      - { type: EFFECT, effect: SLOWNESS, level: 1, seconds: 6 }
      - { type: SOUND, sound: ENTITY_GENERIC_DRINK, volume: 0.6, pitch: 0.5 }
    radius: 8

Example 5: redstone-linked door (redstone charge → open door)

The classic mechanism: a lever / pressure plate powers a block, and the mechanism fills the door with air:

yaml
mechanisms:
  - id: lever_door
    trigger: { type: REDSTONE, x: 4, y: 1, z: 0 }
    actions:
      - { type: FILL, from: { x: 3, y: 1, z: 0 }, to: { x: 5, y: 3, z: 0 }, material: AIR }
    once: false   # Can be opened repeatedly
    cooldown: 0

Example 6: right-click altar for a reward (interact → give item + command reward + effect)

The player right-clicks the altar block to dispense a key, give money, and show an effect; each person can claim only once (using once together with… here we use a command to limit it, since the mechanism once is once per anchor):

yaml
mechanisms:
  - id: altar_reward
    trigger: { type: INTERACT, x: 6, y: 1, z: 6 }
    actions:
      - { type: PARTICLE, pos: { x: 6, y: 2, z: 6 }, particle: HAPPY_VILLAGER, count: 40, spread: 0.8 }
      - { type: SOUND, sound: UI_TOAST_CHALLENGE_COMPLETE, volume: 1.0, pitch: 1.0 }
      - { type: GIVE, item: qi-ancient_relic, amount: 1 }
      - { type: COMMAND, command: "eco give {player} 200", as: console }
      - { type: MESSAGE, text: "&a你获得了祭坛的恩赐!" }
    require-stage: 2   # Only claimable after clearing
    cooldown: 1

6. Troubleshooting cheat sheet

SymptomPossible cause
Mechanism does nothing at allmechanisms.enabled: false; or actions is empty and ignored; or require-stage not reached
REGION_ENTER / TIMER not triggeringPlayer not within scan-radius; or period-ticks too large so its turn hasn't come
FILL has no effectRegion volume exceeds max-fill-volume; or material name misspelled
LOOT / GIVE dispenses nothingThe mechanism is triggered by a playerless trigger (REDSTONE / STAGE / TIMER), so there's no recipient; or the table name / item reference can't be resolved
NPC doesn't appearCitizens not installed
Trigger block won't breakIt's an INTERACT / REDSTONE trigger block (protected); only BLOCK_BREAK trigger blocks are allowed to be mined
Mechanism triggered once and never responds againonce: true; the record is persisted and won't reset even on reload (/qr remove that anchor to clear it)

Next steps