Mount Configuration

Register standalone rideable mounts — boats, rafts, and other non-creature vehicles.

Mounts are standalone rideable entities (boats, rafts) — always mountable, no taming required. This is the catalog file that registers them.

Which file does my rideable thing go in? A mob can be a mount, but not every mount is a mob. The dividing line is whether the thing is a creature:

  • A creature that can be ridden — a horse, a giant beetle — is a mob with a mount: block. It lives its own life: it spawns by biome rules, wanders, has an AI script, can be attacked, and can be tamed.

  • A vehicle — a boat, a raft — is a mount, registered here. It does nothing on its own; it exists to be ridden and is driven entirely by its rider and your steering script.

    The mount entity itself is general — build whatever your mod wants with it. Note only that the base game’s own setting stays pre-industrial, so first-party content has no rail carts, tracks, or mechanical mounts.

Both use the same seats shape described below. The practical difference is that the mob path adds the creature-only features — spawn rules, AI hooks, and taming — while this path stays deliberately light.

Mounts cannot be tamed. Taming is a creature mechanic: food-items and a feed-progress threshold describe befriending an animal, which has no meaning for a cart. Writing a taming: block here fails the entry at load with a message pointing you to mob-config.yaml. If your rideable thing should be tamed, it’s a mob.

To give a mount a sprite, register it in the mount texture config under the same name you use here.


File Location

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

mount-config: mount-config.yaml

The key alone is enough — it defaults to mount-config.yaml in your mod folder. Give it a value only to use a different filename.

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

mods/<YourMod>/mount-config.yaml

The file is a single list of mount entries:

mounts:
  - name: my_boat
    hitbox:
      width: 2.0
      height: 3.0
    seats:
      - x-offset: 0.0
        y-offset: 2.5

Names are automatically prefixed with your mod name unless you write one already containing a colon.


Minimal Example

mounts:
  - name: my_boat
    hitbox:
      width: 2.0
      height: 3.0
    seats:
      - x-offset: 0.0
        y-offset: 2.5

Fields

FieldDefaultDescription
name(required)The mount’s identifier.
hitbox(required){ width, height } in blocks.
seats(required — at least one)Where riders sit — see Seats below.
display-name(none)Name shown in UI.
interact-range10.0How far away a player may be and still mount it, in blocks, measured hitbox-to-hitbox. Same key and default as items, interactables and mobs. Worth raising for a physically large vehicle — on a long cart or a wide boat, a seat at the far end can otherwise sit outside the default reach.
max-speed80.0A steering value for your Lua script — not applied by the engine. Your server-update reads it with entity:get_max_speed() to decide how fast to drive the mount (see Steering a mount). Changing it only matters if your script actually uses it.
jump-strength12.0Same as max-speed — a value your script reads via entity:get_jump_strength() and applies itself. The engine does not make the mount jump on its own.
movement.max-velocity{x: 100.0, y: 100.0}A hard per-axis clamp (blocks/sec) that the engine does enforce on the mount’s physics — the mount can never move faster than this on either axis, no matter what a script (or a shove, or a fall) tries. x/y each default independently if only one is set, and omitting movement: entirely keeps both defaults. Nested under movement: like a mob’s and the player’s.
shader(none)Client-only. Name of a shader from your shader config to render this mount with, instead of the default entity shader. Same key and behaviour as a mob’s shader.
healthsee health-config.mdSame shape as the standalone health config.
drop-table(none)Items dropped when destroyed — see Shared Blocks → drop-table (same shared block).

Why the default is higher than a mob’s. A mob and the player default max-velocity to 50; a mount defaults to 100. That is deliberate: a mount’s own max-speed defaults to 80, so a 50 ceiling would clamp a default-configured mount to well under its configured speed.

max-speed/jump-strength vs movement.max-velocity. These sit at two different layers. max-speed and jump-strength stay at the top level — mirroring where they sit inside a mob’s mount: block — and are inputs to your steering script — the engine only stores them and hands them back through get_max_speed() / get_jump_strength(); a mount with no server-update script that reads them will not move at all. max-velocity is an engine-enforced ceiling applied directly to the mount’s physics object, independent of any script. So: use max-speed/jump-strength to tune how your script drives the mount, and max-velocity as the safety cap it can never exceed.

Lua Hooks

scripts: keyCalled
server-updateEvery tick (server)
server-on-createWhen the mount is created or loaded into the world (server)
server-on-deathWhen destroyed, just before it leaves the world (server)
server-on-mountedWhen a rider mounts (server)
server-on-dismountedWhen a rider dismounts (server)
client-on-interactWhen a player interacts with it (client)
client-updateEvery frame (client)
client-on-createWhen received/loaded (client)
client-on-deathWhen destroyed (client)
client-on-mountedWhen a rider mounts (client)
client-on-dismountedWhen a rider dismounts (client)

server-on-death receives the mount entity, and runs before it is removed from the world so the hook can still read its position and state. client-on-mounted / client-on-dismounted receive (rider, mount) — the same pair their server-side counterparts get.

server-on-create receives the mount entity and fires on both creation paths — a freshly spawned mount and one loaded back from a save — so treat it as “this mount now exists in the world” rather than “this mount was just made”, and make it idempotent.

Each hook is declared under a single scripts: block, keyed by the event name, with the bare path to a .lua file that returns its handler function (the same shape as items’ server-on-primary-use):

scripts:
  server-update: /mounts/my_boat/scripts/server_update.lua

Steering a mount

Mounts do not move on their own — the engine only records rider input and enforces the max-velocity clamp. All actual movement is up to your server-update script, which runs every tick for each mount. Inside it you read the rider’s input and your own config values, then set the mount’s velocity:

Method (on the mount entity)Returns
entity:get_rider_input_x() / get_rider_input_y()The current rider’s steering input on each axis (0.0 when no input).
entity:get_max_speed()The max-speed value from this mount’s config.
entity:get_jump_strength()The jump-strength value from this mount’s config.
entity:get_riders()The list of mounted rider entity IDs (empty when nobody is aboard).

A minimal ground-mount loop:

return function(entity, delta_time_ns)
    if #entity:get_riders() == 0 then
        entity:set_applying_x_velocity(false)
        return
    end

    local input_x = entity:get_rider_input_x()
    local max_speed = entity:get_max_speed()   -- reads max-speed from config

    entity:set_max_x_velocity(max_speed)
    if input_x ~= 0.0 then
        entity:set_x_velocity(input_x / math.abs(input_x) * max_speed)
        entity:set_applying_x_velocity(true)
    else
        entity:set_x_velocity(0.0)
        entity:set_applying_x_velocity(false)
    end
end

Because max-speed and jump-strength are read from config here, a modder (or player) can retune the mount by editing the YAML alone — no script change needed. The shipped test_mount mount’s server_update.lua is a fuller worked example (ground movement plus jump/descend handling).


Seats

seats:
  - x-offset: 0.0
    y-offset: 2.5
    rider-hidden: false
FieldDefaultDescription
x-offset / y-offset0.0Rider’s draw position relative to the mount.
rider-hiddenfalseIf true, the rider entity isn’t rendered at all (useful for fully-enclosed mounts).

A mount can have multiple seats — the first free one is assigned when a player mounts.


Complete Example

mounts:
  - name: sailboat
    display-name: Sailboat
    hitbox:
      width: 4.0
      height: 3.0
    max-speed: 30.0
    health:
      max: 50.0
      regen-per-second: 0
      takes-damage: true
    seats:
      - x-offset: 0.0
        y-offset: 1.0
      - x-offset: 1.5
        y-offset: 1.0
        rider-hidden: true
    drop-table:
      drops:
        - item: MyMod:sailboat
          min-amount: 1
          max-amount: 1
          chance: 1.0
    scripts:
      server-update: /mounts/sailboat/scripts/server_update.lua

Last updated