Control Bindings (Actions)

Declare your mod's keyboard and mouse bindings (actions), grouped into categories shown in the Controls settings menu.

Mods declare their keyboard and mouse bindings — called actions — in a single YAML file. Actions are grouped into named categories, shown to the player in the Controls settings menu, and can be freely rebound by the player without touching your mod.


File Location

Register the file in your mod’s manifest (mods/<YourMod>/<YourMod>.yaml):

control-config: control-config.yaml

Then create the file it points to, relative to your mod’s folder:

mods/<YourMod>/control-config.yaml

Minimal Example

categories:
  - category: MOVEMENT
    bindings:
      - action: JUMP
        key: Space
        trigger: key_down

This registers one action, JUMP, in a category called MOVEMENT, bound to the Space key while it’s held down.


Full File Reference

categories:
  - category: CATEGORY_NAME     # Groups bindings together in the Controls settings menu.
    bindings:
      - action: ACTION_NAME      # The action's identifier. Referenced elsewhere by this exact name.
        key: KeyW                 # Required. See "Valid Keys" below.
        trigger: key_down         # Required. See "Valid Triggers" below.
        modifiers: [shift]        # Optional. See "Modifiers" below.

      - action: ANOTHER_ACTION
        key: KeyE
        trigger: key_up

  - category: ANOTHER_CATEGORY
    bindings:
      - action: THIRD_ACTION
        key: Left
        trigger: press
  • categories is a list of categories, each grouping bindings shown together in the Controls menu.
  • Each category has a category name and a bindings list.
  • Each binding has an action name plus its key, trigger, and optional modifiers.

No other fields are accepted at either level — see Errors.

Categories appear in the Controls settings menu in the order you declare them, and bindings within a category in the order they appear. Action and category names should be unique — reusing a name already defined by another mod will overwrite that binding’s display entry.


Valid Keys

Keyboard

key values
KeyAKeyZ
Digit0Digit9
F1F12
ArrowUp, ArrowDown, ArrowLeft, ArrowRight
Escape, Space, Backspace, Enter, Tab
Home, End, PageUp, PageDown, Delete, Insert

For any other keyboard key (punctuation, symbols, etc.), use the literal character the key produces instead of a name, e.g. key: ',' for comma, key: '-' for minus, key: ';' for semicolon. Quote it if the character has special meaning in YAML (:, #, ', ", etc.).

A name that isn’t on this list is rejected. key accepts exactly the names above, the mouse buttons below, or a single literal character — anything else (Spac, KeyDD, MouseLeft) fails the binding at load time with an error naming the key. Multi-character names are the trap here: key: Space is a name and must be spelled exactly, while key: ';' is a literal character and is taken as-is.

Mouse

key valueMeaning
Left, Right, MiddleThe corresponding mouse button
Back, ForwardSide buttons, if present
a number (e.g. 6)Additional device-specific mouse buttons

Mouse-wheel scroll and mouse-move triggers (below) require a specific fixed key value regardless of which physical button is involved — see the Triggers table.


Valid Triggers

Keyboard and mouse are separate input paths, so each has its own trigger names: keyboard keys use key_down / key_up, and mouse buttons use press / release (there is no key_down for a mouse button, nor press for a keyboard key). Pick the trigger that matches the kind of key you bound.

triggerFires whenRequired key
key_downA keyboard key is held down (repeats every frame while held)any keyboard key
key_upA keyboard key is releasedany keyboard key
pressA mouse button is pressedLeft, Right, Middle, Back, or Forward
releaseA mouse button is releasedsame as press
button_clickA mouse button is released (fires alongside release)same as press
scroll_up / scroll_downThe mouse wheel is scrolledmust be Middle
moveEvery frame no other mouse action occurs (a per-frame idle tick, not an actual movement event)must be Left

Any other value is an error — the binding is rejected rather than registered against an event that never fires.


Modifiers

Any binding — keyboard or mouse — can require one or more modifier keys to be held using modifiers: [...]. Valid entries:

  • ctrl (or control)
  • shift
  • alt
  • super (or meta)
- action: TOGGLE_SLAB_PLACEMENT
  key: KeyF
  trigger: key_up
  modifiers: [shift]

- action: QUICK_MOVE_ITEM
  key: Left
  trigger: release
  modifiers: [shift]

A binding with no modifiers list requires no modifiers, but it still fires when one happens to be held: bindings are matched against the modifiers actually down, and if nothing declares that exact combination, the unmodified binding is used instead. So PRIMARY_USE (a plain Left/press) keeps working while the player holds Shift, and walking doesn’t stop the moment a modifier goes down.

The consequence is that a modified binding shadows the unmodified binding for the same key and trigger. With both of the examples below declared, Shift+Left release fires only QUICK_MOVE_ITEM, never GRAB_ITEM:

- action: GRAB_ITEM
  key: Left
  trigger: release
- action: QUICK_MOVE_ITEM
  key: Left
  trigger: release
  modifiers: [shift]

Categories and Display Names

Category and action names are shown in the Controls settings menu with underscores converted to spaces and each word capitalized — MOVE_EAST displays as “Move East”. Use SCREAMING_SNAKE_CASE names for consistency with the base game’s bindings, and avoid spaces: structure_editor would display as “Structure editor”, not “Structure Editor”.


User Overrides

Players can rebind any keyboard action from the Controls settings menu. Their choices are saved to user_config/keybindings.yaml, layered on top of whatever your mod defines — you don’t need to do anything to support this. “Reset to Defaults” in the settings menu restores the bindings your control-config.yaml declared.

An override for an action that no longer exists — one you renamed or removed in a later version of your mod — is ignored rather than re-registered, so players carrying an old override file won’t resurrect a binding you deleted.


Errors

Each category and each binding is validated as a whole when the mod loads. A category missing category/bindings, a binding missing action/key/trigger, an unknown key, trigger or modifier name, a key/trigger pair from different devices, or any unrecognized field rejects that entry only — it is skipped with an error naming the problem in logs/client.log, and everything else in the file still loads.

This means a typo fails loudly instead of silently doing nothing:

- action: OPEN_MAP
  key: KeyM
  trigger: key_upp      # rejected: unknown trigger

- action: OPEN_MAP
  key: KeyMM            # rejected: unknown key name
  trigger: key_up

- action: OPEN_MAP
  key: KeyM
  trigger: press        # rejected: keyboard key with a mouse trigger
                        # (see "Valid Triggers" — key_down/key_up are the keyboard ones)

- action: OPEN_MAP
  key: KeyM
  trigger: key_up
  modifier: [Shift]     # rejected: unknown field (should be "modifiers")

- action: OPEN_MAP
  key: KeyM
  trigger: key_up
  modifiers: [Shfit]    # rejected: unknown modifier

If the file itself is missing, unreadable, not valid YAML, or has no categories list, none of its actions are loaded.


Complete Example

categories:
  - category: MOVEMENT
    bindings:
      - action: MOVE_EAST
        key: KeyD
        trigger: key_down
      - action: MOVE_WEST
        key: KeyA
        trigger: key_down
      - action: JUMP
        key: Space
        trigger: key_down

  - category: INVENTORY
    bindings:
      - action: TOGGLE_INVENTORY
        key: KeyE
        trigger: key_up
      - action: TOGGLE_SLAB_PLACEMENT
        key: KeyF
        trigger: key_up
        modifiers: [shift]
      - action: SELECT_ITEM
        key: Left
        trigger: press
      - action: INCREMENT_SELECTED
        key: Middle
        trigger: scroll_down
      - action: DECREMENT_SELECTED
        key: Middle
        trigger: scroll_up

  - category: CHAT
    bindings:
      - action: OPEN_CHAT
        key: KeyT
        trigger: key_up