Skip to content

Creating and Sharing Modifiers

Quick Start: Spice it up with twists.

Modifiers are named command bundles: one .yml file each under mods/modifiers/, presets beside them under mods/presets/. The id is the filename minus .yml, so gear-dice.yml is the gear-dice modifier. Subdirectories are allowed and load recursively. A modifier can run commands when a match starts, on an interval, on game events, and when the match ends, from the console or per player. New entries start disabled.

Bundled defaults ship with the plugin and copy in the first time each folder is created. Deleting a file removes it for good: defaults are never restored. All examples below match the bundled files in the mods/ folder.

Writing commands by hand is tedious. Use mcstacker.net to generate up-to-date commands, then paste them into your modifier. Then check the file with the Mod Validator: it catches tag, syntax, trigger, key-typo, and settings mistakes locally before you load or share the mod.

Creating Modifiers and Presets

Build entries in the GUI or inline from chat; both write the same per-file entries manual editing produces. Everything lands as a root-level file: mods/modifiers/<id>.yml or mods/presets/<id>.yml. Ids use letters, numbers, - and _, up to 64 chars; a taken name gets {n} numbering.

In the GUI, the create button sits top-right of the lists. It prompts for a display name (you become the author) and opens the new entry in its editor; right-clicking any existing entry opens the same editor. The create command behaves the same (the console records CONSOLE as author). The modifier editor covers every field: meta, triggers, timing and chance options, and every command list. Blank answers clear optional fields back to defaults. See Your First Modifier for a worked kit example.

  • Commands validate on save: unbalanced brackets, empty commands, malformed random args, unknown root commands, and unknown give items are refused with an error, while unknown tags only warn. Set advanced.misc.modifier-editor.validate-commands to false to skip the root and item checks. See Modifiers for the create flags. Lines edited outside the GUI skip that check, so at runtime an unterminated <run> warns in the console naming the line instead of running silently.
  • Some command roots can never dispatch from a modifier; see Blacklisted Commands.
  • Toggling a modifier mid-match runs its start and ON_CLEANUP behaviors on every toggle, which suits rapid testing. Set advanced.misc.modifier-editor.prevent-duplicate-toggle to true so each runs at most once per match and rewards never duplicate.

Presets keep display data under meta: with the member list beside it:

mods/presets/chaos-mode.yml:

meta:
  name: "Chaos Mode"
  description: "Random mobs, random items, gear dice"
  visibility:
    icon: TNT
    color: ffaa00
    broadcast: true
modifiers:
  - random-mob-spawner
  - random-item-giver
  • Presets carry the same visibility block as modifiers (icon, broadcast toggle, hex color), edited from the Meta panel's Visibility page. The icon lives only in visibility.icon; a file that still carries the retired top-level meta.icon warns as an unknown key and the stale value is ignored. Every icon field accepts JMH Icon Data. The match-start line for a preset uses the preset's own color; a preset with broadcast off stays silent.
  • A modifier's message color lives only in visibility.color: behavior reads it with <modcolor> instead of defining a second color setting (bingo is the exception with its extra normal color for card text).
  • Member ids with no loaded modifier show as 'id' missing in red and are skipped by toggles; a preset with nothing but missing members refuses to toggle.
  • Presets written in the old flat shape (display keys next to modifiers:) no longer load: re-indent the four display keys under meta:, and re-export old share strings. Upgrading from the single modifiers.yml layout: copy entries into per-file form by hand, nothing migrates automatically.

Presets can nest other presets with a presets: list beside modifiers:, as deep as you like:

meta:
  name: "Everything Pack"
modifiers:
  - gear-dice
presets:
  - chaos-mode
  • Toggling a stacking preset flips every transitive member, and the preset reads on only when all of them are on. A preset holding more present members than the match allows refuses the whole enable with an error instead of partially enabling.
  • The lore lists direct modifiers first, then direct nested presets with a (preset) suffix; nested contents are never inlined, so open the nested preset to see them.
  • At match start, a preset whose transitive members exactly equal the active set replaces the member lines with one line; when several presets match, the outermost wins and the nested ones stay silent.
  • The (by ...) slot lists every credited author: the preset creator first, then each deeper nesting level, then the transitive modifier authors, with repeats keeping their highest spot.
  • A cycle (a nesting b nesting a) warns at load naming the full path and ignores the closing link in memory; the file is left alone, and the GUI refuses nests that would close a cycle. Unknown nested ids warn and skip like missing members, renames follow into presets: lists, and share strings carry nesting (strings exported before nesting import as direct-only).

Sharing Modifiers and Presets

Export any entry to a share string: a click-to-copy chat line for friends or the community. Import takes one back in, always disabled no matter the export state; colliding names get numbered automatically. Strings that fail their checksum or schema check are refused without touching anything.

/manhunt modifiers export modifier gear-dice
/manhunt modifiers export preset chaos-mode
/manhunt modifiers import modifier JMH1D:...

The lists carry an import button that prompts for the string, and every editor has an export button for its own share string.

Mod Files and Load Order

  • Modifiers load fully before presets. Inside each tree, every directory loads its subdirectories first (sorted naturally by name, each processed with this same rule), then its own .yml files sorted naturally by filename. Root-level files therefore load after everything nested. Sorting is Explorer style: case-insensitive, with digit runs compared numerically (mod2 before mod10).
  • Two files of the same kind with the same id in different folders are a duplicate: the first in load order wins and the rest are skipped, with a console warning naming both paths. A modifier and a preset may share an id; they are separate namespaces.
  • Loads warn about mistakes that used to pass silently: unknown YAML keys are ignored with a warning naming the key and level; unknown runs-on triggers never fire and warn; <setting:> references to undefined settings read null and warn; duplicate setting names drop the whole config.settings block with a warning; setting defaults outside their allowed range clamp with a warning. The validator reports the same findings offline.
  • Non-.yml files are reported as unknown files on reload (temp files and dotfiles are ignored silently). A .yml file that fails to parse or validate is logged as <path>: <error>, skipped, and reported; fixing it later reloads quietly.
  • A preset that names an unknown modifier id warns and skips that member in memory only: the file keeps the id, so a later reload picks it up once the modifier exists.
  • Enable flags stored in the lobby config for ids that no longer exist are pruned on load and reload (with one console warning); per-setting values are kept, so re-adding the file restores its customization. The Added/Removed counts only reflect files: mods created or deleted in-game never re-report on the next reload.

Example

A minimal starter kit for every participant:

mods/modifiers/starter-kit.yml:

enabled: false
behavior:
  0:
    commands:
      player:
        - "give <p> cooked_beef 8"

The bundled files ship more examples to copy from: full-leather-kit, speedrunner-health-advantage, random-mob-spawner, random-item-giver, random-start-resources, gear-dice, regen-on-kill, diamond-on-advancement, fireres-on-nether-enter, hunter-start-debuffs, get-stronger-on-kill, speedrunner-gapple-on-low-hp, vip-escort, and infection.

Get Stronger On Kill

Runs on every player kill (executor: the killer) and every respawn (executor: the respawner). Each run works in half-hearts from two tunables (cap 40, step 4): cache the baseline max health, set base to baseline plus step times session kills capped at cap, heal 2 hearts on the spot, and refill only missing hunger. Respawn re-applies the target from the still-current counter, so a killer who dies keeps their hearts. ON_CLEANUP clears this modifier's ledger entry per participant.

Gapple On Low HP

Runs every 2 seconds for speedrunners. Lines exit cheapest-first: cooldown read, health check, inventory scan, then the gate itself. <pcooldown> yields true and stamps at most every 300 seconds, so the apple lands only when all four pass.

VIP Escort

Flags one random speedrunner as the VIP after the pre-start window; runners lose outright when the VIP dies. Run it with speedrunner lives at -1 so everyone else respawns forever while the VIP stays mortal. Four blocks: an ON_START pick, an ON_DEATH guard that ends the match for the hunters, a 1-second INTERVAL armor toggle, and an ON_START plus ON_RESPAWN effects toggle (effects and no_armor in config.settings).

Infection

Speedrunners who die their final death come back as hunters via <pswitch>. Guards read the victim's former role plus live role, so hunter deaths, non-final runner deaths, and disconnect removals (which never fire ON_DEATH) exit quietly. When no runners remain, the engine ends the match with a hunter win on its own. A second block runs every 12 seconds per hunter: converted hunters get sporadic blindness plus occasional drops (80% give-fail chance by default), while root hunters exit untouched. Durations and counts live in config.settings.