Interactable Configuration
Register placeable static objects with an inventory and Lua behavior, such as chests, furnaces, and crafting benches.
Interactables are placeable static objects with an inventory and Lua behavior — chests, furnaces, crafting benches, doors, and similar. This is the catalog file that registers them.
File Location
Register the file in your mod’s manifest (mods/<YourMod>/<YourMod>.yaml):
interactable-config: interactable-config.yaml
Then create the file it points to, relative to your mod’s folder:
mods/<YourMod>/interactable-config.yaml
The file is a single list of interactable entries:
interactables:
- name: my_chest
hitbox:
width: 2.0
height: 1.5
requires-supporting-blocks: true
time-to-break-ms: 1000
power-required: 1
tool-break-types: axe
Names are automatically prefixed with your mod name unless you write one already containing a colon.
Minimal Example
interactables:
- name: my_sign
hitbox:
width: 1.0
height: 1.0
Fields
| Field | Default | Description |
|---|---|---|
name | (required) | The interactable’s identifier. |
hitbox | (required) | { width, height } in blocks. |
requires-supporting-blocks | false | Whether this object needs solid ground beneath it to be placed. |
time-to-break-ms | 1000 | How long it takes to break with a valid tool. |
power-required | 1 | Minimum tool power level needed to break it. |
tool-break-types | (none) | Which tool categories can break it — a single string or a list. Leaving this unset means any tool or a bare hand can break it (see Breaking below). |
breakable | true | Whether it can be broken at all. false makes it permanently unbreakable — immune both to being mined directly and to having the block beneath it broken — regardless of tool-break-types. Use it for signs, monuments, or permanent structure pieces. |
collidable | true | Whether entities/players collide with it physically. |
interact-cooldown-ms | 0 | Minimum time between interactions (cooldown). |
default-state | "default" | Initial state name. Must match a states: entry in this object’s texture config, or the object resolves no state — see State names are matched exactly. |
interact-range | 10.0 | How many blocks away this object can be interacted with from. |
crafting-station | (none) | Marks this interactable as a crafting station — { power, type }. See Crafting Stations. |
light | (none) | Makes the object emit light — same shape as Shared Blocks → light. |
drop-table | (none) | Items dropped when broken — see Drop Table. |
drops-self | false | Shorthand for “drops exactly one of itself” — see Drops Self. |
draw-priority | 0 | Client-only. Draw order for this placed object. |
shader | (none) | Client-only. Overrides the render shader for this object. |
item | true | Whether registering this interactable also registers its type: interactable item, making it obtainable and placeable. Set false for one that must never exist in an inventory — same rule as a block’s item. |
particles | (none) | Client-only. Ambient particle emission — a list of emitter groups, each with its own emit-random. See the particles: block. |
Unknown keys at the top level of an entry are rejected: a misspelled field is a load-time error naming the bad key, not a silently-ignored one. Its nested blocks are validated the same way — an unrecognized key inside the light block, the scripts block, or a drop-table entry is also a load-time error naming the bad key. See Unknown Fields.
Breaking
tool-break-types and power-required gate which tools can break an interactable:
- If
tool-break-typesis set, the tool must have at least one matching entry (via the tool’s owntool-types); if it’s left empty, any tool — or a bare hand — qualifies, and - The tool’s
power-levelmust be>= power-required.
Leaving tool-break-types empty means “no tool requirement” — any tool or a bare hand can break it (subject to power-required). Set one or more categories to restrict which tools work.
To make an interactable permanent, set breakable: false. This overrides everything above: it can’t be mined directly, and breaking the block beneath it won’t destroy it either (it survives losing its support). Use it for signs, monuments, or fixed structure pieces.
tool-break-types: axe # single tool category
tool-break-types: [axe, pickaxe] # multiple categories, any one qualifies
Crafting Stations
Add a crafting-station block to turn an interactable into a crafting station. While a player stands within the station’s interact-range, the server lets them craft recipes of that type whose own crafting-station.power (see crafting-config.md) is at most this station’s power.
crafting-station:
power: 2
type: crafting # Crafting, Smelting, or any custom tag your recipes use
Notes:
- Both
powerandtypeare required whenever the block is present — a half-configured station is a load-time error rather than a silently non-functional station. typeis an open, case-insensitive tag matched against a recipe’scrafting-station.type. A recipe declares the station it requires with the same block name and keys an interactable uses to declare the station it provides, so the two sides read identically. Beyond the base game’sCrafting/Smeltingyou can invent your own categories (Anvil,Loom, …) — the station and its recipes just have to use the same tag. See crafting-config.md.- Your station’s
client-on-interacthook still has to open the crafting menu client-side (viadisplay_crafting_menu(power, type)) — that’s what the player sees. Thecrafting-stationconfig is the server’s independent authority: crafting is validated server-side against nearby stations, so a modified client can’t craft station-gated recipes out of range. - Hand-crafting baseline: every player can always craft
Craftingrecipes of power1with no station nearby (this matches the crafting menu the inventory opens by default). Anything above power1, or any recipe of anothertype(includingSmelting), requires a station in range.
Drops Self
Most interactables just drop one copy of themselves when broken. That’s what drops-self is for:
drops-self: true
It’s exactly equivalent to a drop-table with a single group holding this interactable’s own item at chance: 1.0 and min/max of 1, and requires an item registered under the interactable’s own name. If both drops-self and drop-table are given, drop-table wins and a warning is logged.
This shorthand exists for interactables and blocks only — mobs, trees, and mounts share the drop-table block below but have no drops-self field. For anything more involved than one guaranteed self-drop, use a drop-table.
Drop Table
What the interactable leaves behind when it’s broken — independent drops: rolls, weighted pick-one groups:, or a named loot-table: to defer to:
drop-table:
drops:
- item: MyMod:my_item
chance: 1.0
groups:
- entries:
- item: MyMod:common_drop
weight: 0.9
- item: MyMod:rare_drop
weight: 0.1
This is the shared drop-table block, identical here to the one on blocks, mobs, mounts and trees — see Shared Blocks → drop-table for every field, the chance-vs-weight distinction, the amount shorthand, and deferring to a named loot table.
For how this differs from a standalone loot table, see Drop Table vs Loot Table.
Lua Hooks
Interactables support several Lua callback hooks, declared under a single scripts: map keyed by event name, each value the bare path to a .lua file that returns its handler function (the same shape as items’ server-on-primary-use):
scripts: key | Side | Called |
|---|---|---|
server-on-create | Server | When placed |
server-on-interact | Server | When a player interacts with it |
server-on-inventory-close | Server | When a player closes its inventory UI |
server-update | Server | Every tick |
client-on-create | Client | When received/loaded |
client-on-interact | Client | When a player interacts with it |
client-update | Client | Every frame |
The server-on-interact handler receives (interactable, player_entity_id, player), where player is the interacting player’s entity wrapper — it can reply privately with player:send_message(text) or set the player’s respawn point with player:set_custom_spawn(x, y) / player:clear_custom_spawn().
Complete Example
interactables:
- name: crafting_bench
hitbox:
width: 3.0
height: 1.5
requires-supporting-blocks: true
time-to-break-ms: 500
power-required: 1
tool-break-types: axe
crafting-station:
power: 2
type: crafting
scripts:
client-on-interact: /interactables/crafting-bench/scripts/client_interact.lua
drops-self: true
- name: door
hitbox:
width: 1.0
height: 3.0
requires-supporting-blocks: true
time-to-break-ms: 1000
power-required: 1
tool-break-types: axe
scripts:
server-on-interact: /interactables/door/scripts/server_interact.lua
interact-cooldown-ms: 400
default-state: door_closed
drops-self: true