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
categoriesis a list of categories, each grouping bindings shown together in the Controls menu.- Each category has a
categoryname and abindingslist. - Each binding has an
actionname plus itskey,trigger, and optionalmodifiers.
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 |
|---|
KeyA – KeyZ |
Digit0 – Digit9 |
F1 – F12 |
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.
keyaccepts 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: Spaceis a name and must be spelled exactly, whilekey: ';'is a literal character and is taken as-is.
Mouse
key value | Meaning |
|---|---|
Left, Right, Middle | The corresponding mouse button |
Back, Forward | Side 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.
trigger | Fires when | Required key |
|---|---|---|
key_down | A keyboard key is held down (repeats every frame while held) | any keyboard key |
key_up | A keyboard key is released | any keyboard key |
press | A mouse button is pressed | Left, Right, Middle, Back, or Forward |
release | A mouse button is released | same as press |
button_click | A mouse button is released (fires alongside release) | same as press |
scroll_up / scroll_down | The mouse wheel is scrolled | must be Middle |
move | Every 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(orcontrol)shiftaltsuper(ormeta)
- 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