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
seatsshape 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
| Field | Default | Description |
|---|---|---|
name | (required) | The mount’s identifier. |
hitbox | (required) | { width, height } in blocks. |
seats | (required — at least one) | Where riders sit — see Seats below. |
storage | (none) | A pack stash the rider can open — { rows, columns }. See Pack storage below. Omit it and the mount carries nothing. |
display-name | (none) | Name shown in UI. |
interact-range | 10.0 | How 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-speed | 80.0 | A 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-strength | 12.0 | Same 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. |
health | see health-config.md | Same 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-velocityto50; a mount defaults to100. That is deliberate: a mount’s ownmax-speeddefaults to80, so a50ceiling would clamp a default-configured mount to well under its configured speed.
max-speed/jump-strengthvsmovement.max-velocity. These sit at two different layers.max-speedandjump-strengthstay at the top level — mirroring where they sit inside a mob’smount:block — and are inputs to your steering script — the engine only stores them and hands them back throughget_max_speed()/get_jump_strength(); a mount with noserver-updatescript that reads them will not move at all.max-velocityis an engine-enforced ceiling applied directly to the mount’s physics object, independent of any script. So: usemax-speed/jump-strengthto tune how your script drives the mount, andmax-velocityas the safety cap it can never exceed.
Lua Hooks
scripts: key | Called |
|---|---|
server-update | Every tick (server) |
server-on-create | When the mount is created or loaded into the world (server) |
server-on-death | When destroyed, just before it leaves the world (server) |
server-on-mounted | When a rider mounts (server) |
server-on-dismounted | When a rider dismounts (server) |
client-on-interact | When a player interacts with it (client) |
client-update | Every frame (client) |
client-on-create | When received/loaded (client) |
client-on-death | When destroyed (client) |
client-on-mounted | When a rider mounts (client) |
client-on-dismounted | When 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 test_mount fixture’s
server_update.lua, in the repository’s development mod (CreationDev, not included in the game), is
a fuller worked example (ground movement plus jump/descend handling).
Pack storage
A mount can carry a stash — a small grid of slots its rider can open and use like a chest. Give it a
storage: block:
storage:
rows: 2
columns: 5
| Field | Default | Description |
|---|---|---|
rows | (required) | Rows in the stash grid. |
columns | (required) | Columns in the stash grid. |
Opening it. The rider opens the stash by interacting with the mount they are already sitting on — mount it first, then interact. There is no other open path: a mount you are not riding is out of reach of its own pack, and interacting with one you are not riding mounts it as before. Nothing has to be scripted; the panel is the same one a chest uses.
A mount with no storage: block has no stash at all, and interacting with it while riding falls
through to the world interaction as it always did.
Size limits. A stash may hold at most 25 slots, half the player’s own 50-slot pack. A larger grid is clamped down to the ceiling (with a warning at load) rather than rejected. The stash is meant to ease carry pressure, not remove it — chests at a home base stay the unbounded option.
A zero-sized grid is an error. rows: 0 or columns: 0 fails the entry at load rather than
loading a stash that holds nothing, since either almost certainly means the block was meant to say
something else. To give a mount no stash, omit storage: entirely.
Changing the size later reaches new mounts only. The grid is applied when a mount is created; one already saved in a world keeps the size it was made with, because resizing a stash empties it and that would delete whatever a player had stored.
Who can open it. A standalone mount is a vehicle, and its stash is open to any player who can
reach it — like an unlocked chest. In multiplayer that means anyone: another player can mount a
vehicle you left behind (once you are off it) and empty its pack, with no warning. That is deliberate
— a vehicle is furniture, and a shared cart should be usable by the group — but it is worth knowing
before you park a loaded one somewhere public. A tamed creature’s stash is the opposite: it belongs
to whoever tamed it, and everyone else is refused; see mob-config.md.
Seats
seats:
- x-offset: 0.0
y-offset: 2.5
rider-hidden: false
| Field | Default | Description |
|---|---|---|
x-offset / y-offset | 0.0 | Rider’s draw position relative to the mount. |
rider-hidden | false | If 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