Block Configuration
Register the placeable, world-generated blocks that make up terrain, walls, and fluids.
Blocks are the tiles that make up the world — terrain, walls, fluids, and any other placeable tile content. This is the catalog file that registers them. Server and client each load their own copy of this file independently (a few fields, noted below, are server-only).
When many blocks share the same field clusters (the repeated tool-break-types / time-to-break-ms / power-required breaking triplet, for instance), you can factor the shared shape into a preset and give each block a preset: key instead of repeating it — see Config Presets.
File Location
Register the file in your mod’s manifest (mods/<YourMod>/<YourMod>.yaml):
block-config: block-config.yaml
Then create the file it points to, relative to your mod’s folder:
mods/<YourMod>/block-config.yaml
The file is a single list of block entries:
blocks:
- name: my_block
tool-break-types: pickaxe
Block names are automatically prefixed with your mod name unless you write one already containing a colon, so my_block becomes YourMod:my_block — this is the full name used anywhere a block is referenced (world generation, item drops, structures, Lua scripts).
Block IDs are assigned dynamically in load order, with one exception: Creation:air is always ID 0.
Top-level field names are validated on load: an unknown or misspelled key (for example time-to-brek-ms instead of time-to-break-ms) is a load-time error that skips that block, rather than being silently ignored. If a block doesn’t behave as expected, check the log for a parse error naming the offending field. The nested blocks are validated the same way — an unrecognized key inside a light, block-shape, particles, scripts, or drop-table entry block is also a load-time error naming the bad key, not a silently-ignored one (see Unknown Fields).
Minimal Example
blocks:
- name: my_ore_block
tool-break-types: pickaxe
power-required: 2
time-to-break-ms: 1500
drop-table:
drops:
- item: YourMod:my_ore_item
min-amount: 1
max-amount: 1
chance: 1.0
Fields
| Field | Default | Description |
|---|---|---|
name | (required) | The block’s registered name. |
collidable | true | Whether entities collide with this block. |
breakable | true | Whether it can be destroyed at all. false makes it permanently indestructible regardless of the other breaking fields below. |
tool-break-types | None | Which tool category or categories break it — a single value or a list. Omit for no restriction (breakable by any tool or a bare hand); use breakable: false for a permanent block. |
power-required | 1 | Minimum tool power level required to break it — compared against a tool’s tool-info.power-level, and unrelated to a crafting station’s tier. See Schema Conventions → Tool power vs. crafting tier. |
time-to-break-ms | 1000 | How long it takes to break with a tool that meets power-required exactly (faster with a higher-power tool). |
tags | (none) | Membership tags this block carries — a single value or a list. A reference field that accepts a #tag (a block texture’s tiles-with, a mob’s valid-spawn-blocks) then matches every block carrying it. Global and case-insensitive. |
block-layer | 1 | Which layer this block occupies. |
particles | (none) | Client-only. Ambient particle emission — a list of emitter groups, each with its own emit-random and optional only-emit-when-exposed-below. See the particles: block. |
item | true | Whether registering this block also registers its type: block item, making it obtainable and placeable. Set false for a block that must never exist in an inventory — see Block items. |
light | (none) | Makes the block emit light — same shape as Shared Blocks → light, plus an optional animated frames list. |
light-transmission | 1.0 | Fraction of light the block lets through: 1.0 passes light unattenuated, 0.0 blocks it completely. Point lights scale continuously (e.g. 0.75 costs 25% of the ray per block crossed); sky light only passes undimmed at exactly 1.0, and costs one level per block below that. |
particles | (none) | Ambient particle emitters for this block — see internal_docs/rendering.md’s Block Particles section (not yet published as a modder-facing doc). |
drop-table | (none) | Items dropped when broken — independent drops: and/or weighted groups:; see Drop Table below. Server-only. |
drops-self | false | Shorthand for “drops one guaranteed copy of itself” — see Drop Table below. Ignored if drop-table is also set. Server-only. |
phase-all | false | Phase in all four directions at once — see Directional Phasing. |
phase | (none) | A list of directions to phase, e.g. [up, down] — see Directional Phasing. |
suffocates | (derived) | Whether an entity buried in this block takes suffocation damage. Unset means “yes, unless the block phases in some direction” — see Suffocation. Server-only. |
drag (up, down, left, right) | 0.0 each | Movement drag applied to entities passing through the block, per direction — used for fluids. Each direction defaults independently, so you can set only the ones you need. Not an {x, y} pair: drag is genuinely per-direction (a fluid can resist sinking more than rising). |
contact-damage (damage-per-second, type) | (none) | Typed damage dealt to any entity overlapping this block — lava, spikes, thorns. See Contact Damage below. Server-only. |
block-matter-type | Solid | One of Solid, Liquid, Gas. |
fluid-level | 0.0 | Fill percentage for fluid blocks. |
fluid-flow-per-second | 0.0 | Fluid flow rate, in level per second. Server-only. |
fluid-minimum-flow-threshold | 0.0 | Minimum level difference before fluid flows between cells. Server-only. |
variant-of | (none) | Declares this block as a named variant of another block — e.g. snowy_grass is the snow variant of grass. A back-reference, registered into the base block’s variant table and looked up from Lua via get_block_variation. See Variant Of below. Server-only. |
block-shape | Full | Full or Slab — see Block Shape below. |
scripts.server-on-interact | (none) | A Lua hook run when a player interacts with a placed instance of this block. Server-only. |
interact-cooldown-ms | 0 | Minimum time between interacts on a single cell of this block. Server-only. |
scripts.server-update | (none) | A per-tick Lua hook run on every placed instance of this block. Server-only. |
falls-when-unsupported | false | Makes the block fall straight down when nothing solid is beneath it — see Falling Blocks below. Server-only. |
unstable-formation (trigger-radius, telegraph-ms, impact-damage, damage-type, impact-height) | (none) | Makes the block a triggered falling hazard (dripstone stalactite): it arms on player proximity, telegraphs, then falls and crushes what is below — see Unstable Formations below. Server-only. |
required-capability | (none) | Marks the block a sealed barrier. A player interacting with it opens it (permanently) only if they hold this capability. Server-only. |
required-item | (none) | Sealed-barrier requirement: the player must have this item in their inventory to open the barrier. Combined with required-capability by AND. Server-only. |
consume-required-item | false | If true, opening the barrier removes one required-item from the player. Ignored without required-item. Server-only. |
reveals-block | air | The block a sealed barrier becomes when opened (default: cleared to air). Server-only. |
sealed-message | (none) | Message shown to a player who interacts with a sealed barrier without meeting its requirement. Server-only. |
auto-open | false | Barrier opens automatically for a qualifying player instead of on interact — see Sealed Barriers. Only applies to pure required-capability barriers. Server-only. |
Block items
A block automatically gets a matching item — same name, type: block — so it can be picked up and placed without you writing anything in item-config.yaml. Declaring a block is enough to make it obtainable.
Write an entry in item-config.yaml only when the item needs more than the defaults — a display-name, a tooltip, a material-type for crafting, or a light on the dropped stack. An explicit entry with the same name replaces the generated one entirely, so you keep full control when you want it.
# block-config.yaml — this alone gives you a placeable, obtainable block
blocks:
- name: marble
tool-break-types: pickaxe
drops-self: true
Set item: false for a block that should never be holdable — a marker or internal block placed only by world generation or Lua:
- name: my_internal_marker
item: false
You still need an item texture. The generated item is a config entry, not an asset — add the block’s icon to
assets/textures/items/items.yamlas normal (see Item Texture Configuration).
Interactables work the same way, via their own item field.
Contact Damage
Give a block a contact-damage: block to make it hurt any entity — players, mobs, mounts — whose hitbox overlaps it. This is how lava, spikes, brambles, and other damaging terrain deal damage:
- name: lava
collidable: false
block-matter-type: liquid
contact-damage:
damage-per-second: 6.0
type: fire
| Key | Default | Meaning |
|---|---|---|
damage-per-second | 0.0 | Continuous damage rate while an entity stays in contact, scaled by the tick delta (like drowning) — not a per-hit amount. A quick brush costs a fraction; standing in it costs the full rate each second. A value of 0 (or omitting the block) means no contact damage. |
type | (required) | The damage type, one of physical, fire, blast, decay, radiant (see Damage Types). An unknown name is a config error: it is logged and the block is left dealing no contact damage. |
ward-capability | (none) | Optional. Turns the block into a hazard-field floor: a player holding this capability takes no contact damage, and a player without it takes it bypassing armor (a ward, not gear, is the only defense). Omitted → an ordinary armor-mitigated contact hazard. Mobs and mounts hold no capabilities, so they always take the block’s contact damage, mitigated as usual. |
Behaviour:
- Passable blocks only. Contact damage applies while an entity overlaps the block’s cell, so it fits fluids and other non-collidable hazards you walk into (
collidable: false). A solid block is stood on, not entered, so a full collidable block never deals contact damage through this property. - Mitigated by armor (unless warded). Contact damage is reduced by the victim’s armor (a
fire-resistant set will one day reduce lava specifically), but it is not stopped by an active block/parry and is not raised to the min-damage floor — a per-tick rate stays proportional to the tick. Award-capabilityblock is the exception: for a player without the ward it bypasses armor entirely (and holding the ward negates it outright). - Environmental. It has no attacker, so it never triggers or is blocked by invulnerability frames, and it never counts as a kill credit for another entity.
- Server-authoritative. The check runs in the server-side entity tick; noclipping players pass through unharmed.
Falling Blocks
Setting falls-when-unsupported: true makes a placed block (sand, gravel, and the like) fall straight down whenever the cell directly below it is not solid support:
- name: sand
tool-break-types: shovel
falls-when-unsupported: true
Behaviour:
- Vertical only. The block drops straight down one cell at a time and settles as soon as it lands on a solid block. There is no sideways sliding or pile-forming.
- Fluids are destroyed. A falling block falls through fluid, erasing the fluid in each cell it passes.
- Runtime only. Naturally world-generated blocks of a falling type do not fall on their own — a falling block only starts falling when it (or the block beneath it) is placed or removed during play. This matches Minecraft: generated overhangs of sand stay put until disturbed.
- Foreground layer only. Falling applies to the foreground collision layer (
block-layer: 1); it has no effect on background/wall layers.
Unstable Formations (falling hazard)
An unstable-formation: block is a triggered falling hazard — a dripstone stalactite, a collapsing crust. Unlike falls-when-unsupported, it does not fall just because nothing is beneath it: it hangs inert until a player comes close, telegraphs its collapse, then detaches and falls through the shared falling-block system, crushing whatever is below where it lands.
- name: dripstone
tool-break-types: pickaxe
drops-self: true
unstable-formation:
trigger-radius: 3.0 # blocks; a player this close arms it
telegraph-ms: 700 # dust-tell delay before it detaches
impact-damage: 25.0 # dealt once, on landing
damage-type: physical # physical | fire | blast
impact-height: 3 # blocks above the landing cell that get crushed
Lifecycle:
- Inert. The block sits like any other solid block.
- Armed / telegraphing. When a player’s position comes within
trigger-radiusblocks, the block arms and emits a repeating dust tell (the same particle burst as block-breaking) fortelegraph-ms. - Falling. After the telegraph it detaches and falls straight down one cell at a time, reusing the falling-block system (so it destroys fluid it passes through and settles on the first solid block).
- Impact. On landing it deals
impact-damageonce, ofdamage-type, to every entity whose feet are in the block column reachingimpact-heightcells up from the landing cell (plus the cell it lands on). The hit is mitigated by armor and typed resistance, like contact damage. Setimpact-damage: 0for a harmless (visual-only) collapse.
Fields (all optional; sensible defaults shown above):
| Field | Default | Meaning |
|---|---|---|
trigger-radius | 3.0 | Player distance in blocks that arms the formation. |
telegraph-ms | 700 | Delay between arming and detaching, during which the dust tell plays. |
impact-damage | 0.0 | Damage dealt once on landing. 0 = falls harmlessly. |
damage-type | physical | Mitigation channel of the impact hit (physical / fire / blast). |
impact-height | 3 | Height of the crushed column, measured up from the landing cell. |
Notes:
- One-shot. A formation only arms while the cell directly below it is open (air or fluid) — i.e. it can actually fall. Once it lands on solid ground it becomes inert rubble: it will not re-arm, re-telegraph, or re-crush when a player walks past. (This is why it must hang with open space beneath it, like a ceiling stalactite.)
- Proximity trigger only (players). Only player proximity arms a formation today; mobs walking underneath do not.
- Foreground layer only, like falling blocks.
- Reusable. The property is data-driven, so it is not dripstone-specific — any block can be an environmental collapse hazard (e.g. an unstable ceiling crust) by declaring
unstable-formation:.
Sealed Barriers (capability-gated)
A sealed barrier is a wall block that a player can only pass once they meet a requirement — the Metroidvania “locked door” primitive. A block becomes a barrier as soon as it declares required-capability and/or required-item:
# Opens only for a player who holds the `storm_ward` capability.
- name: sealed_stormward
breakable: false
required-capability: storm_ward
reveals-block: air # what it becomes when opened (default: air)
sealed-message: "The way is sealed."
# Opens for a player carrying a `void_key` item, consuming one on use.
- name: sealed_vault_door
breakable: false
required-item: void_key
consume-required-item: true
Behaviour:
- Interact to open. When a player interacts (uses) a barrier and meets the requirement, the block is permanently swapped to its
reveals-block(default: cleared to air). The change is broadcast to every client and saved with the world, so it stays open. - Requirements combine by AND. If both
required-capabilityandrequired-itemare set, the player needs both.consume-required-itemremoves one matching item on a successful open. - Gates who opens, not who passes. Once opened the way is open for everyone (co-op friendly); the requirement controls who can open it.
- Feedback. A player who interacts without qualifying is sent
sealed-message(or a default message if unset). - Foreground layer only, checked on the collision layer (
block-layer: 1). Make barriersbreakable: falseso they can only be removed by opening them.
Auto-opening barriers
Interacting with every block of a large sealed wall is tedious. Set auto-open: true and the barrier clears on its own for a qualifying player — no interact:
- name: sealed_stormward
breakable: false
required-capability: storm_ward
auto-open: true
It triggers both when a qualifying player streams the chunk (walks into the area with the capability) and the moment they gain the capability while standing among already-loaded barriers — so a whole wall falls away at once. Notes:
- Capability barriers only.
auto-openis ignored forrequired-itembarriers (a key must never be consumed without a deliberate interact); it logs a warning at load if combined withrequired-itemor used withoutrequired-capability. - World-wide, first-come. Because opening broadcasts and persists, an
auto-openbarrier vanishes the instant the first qualifying player reaches it — for everyone. That fits “once you have the ability, these gates are just gone”; leaveauto-openoff if you want a barrier the player must deliberately open.
Capabilities are free-form string ids. Grant them from Lua with player:grant_capability("storm_ward") (see Server Entity API) — typically from a boss-death, item-use, mount, or interactable script. required-item refers to an item name (namespaced to the block’s mod, like drop-table items).
Placement. Barriers are ordinary blocks, so place them by authoring them into a structure or via world generation — no special placement mode is needed.
Tool-tier region seals
A sealed barrier gates who passes (opened by an interact once you hold the key). The other Metroidvania hard-gate is a tool-tier seal: a wall you can’t mine until you carry a high-enough-power tool. It needs no special fields — it’s just power-required and tool-break-types tuned above the tool tier available before the gate:
# Unbreakable by every tool in the pre-gate tier ladder; opens only once a
# power-5 pickaxe exists (e.g. a per-world material upgrade).
- name: sealed_deepstone
tool-break-types: pickaxe # a bare hand is power 1 and has no pickaxe, so hands never work
power-required: 5
Why this is a genuine seal, not just slow:
- A below-tier tool does zero damage — it is a hard gate, not a speed penalty, so no amount of grinding chips through. Mining progress only accrues once the wielded tool’s
power-levelmeetspower-required. - Bare hands are power
1with tool types[shovel, axe, shears](nopickaxe). Requiringtool-break-types: pickaxealone already stops hand-mining; a highpower-requiredthen stops every tool below the intended tier. - Tune it against your ladder. The base game ships tools at
power-level2–4, sopower-required: 5seals a region against all current tools until a higher-tier tool is introduced. Pick a value one step above whatever the player can obtain before the gate. - Sandbox-robust. Because a builder can neither dig through nor (with a tall enough wall / sealed ceiling) tower past a wall they can’t break, this is the map’s backbone gate — the level geometry decides “can’t pass,” not a scripted check.
Like barriers, tool-tier seals are ordinary blocks — author them into a structure or lay them in world generation.
Tags
tags are free-form membership labels a block carries, so that another config can refer to a
group of blocks at once instead of listing each by name. A block declares them plural, as a single
value or a list:
- name: iron_ore
tags: ore # one tag
- name: coal_ore
tags: [ore, fuel] # several
Wherever a field accepts a #tag reference, writing #ore matches every block carrying the
ore tag. Two fields accept it today:
- a block texture’s
tiles-with— “visually connect to any#ore.” - a mob’s
valid-spawn-blocks— “spawn on any#soil.”
# In block-texture-config.yaml — connect to every ore block, whoever defined it:
tiles-with: ["#ore"]
The # sigil is what distinguishes a tag from a block name: #ore is the tag, a bare ore is
the single block literally named ore. (You’ll recognise # from Minecraft’s tag syntax.)
Tags differ from a content name in two ways worth knowing:
- Global, never mod-prefixed. A tag is not qualified with your mod name the way a block name is
— the whole point of
#oreis that ore blocks from any mod match it. Two mods both tagging their oresorecontribute to the same group. - Case-insensitive.
ore,OreandOREare one tag (they normalize to upper-case), unlike the other open registries where casing is preserved. A tag is still an open registry liketool-break-types— you invent whatever you need, so a typo is a new (empty) tag rather than a load error. A#tagthat no block carries is reported where it’s used (e.g. avalid-spawn-blocksentry fails to load), not silently ignored.
tool-break-types
One tool category, or a list of them — each one of shovel, pickaxe, axe, shears — matched against the wielded tool’s own tool-types list. A block breaks if the wielded tool matches any listed category. This is the same shape interactables and trees use, so a single value (tool-break-types: Shovel) and a list (tool-break-types: [Pickaxe, Axe]) are both accepted.
Those four are what the base game ships, not the complete set — tool categories are an open registry, so tool-break-types: hammer is a valid requirement as soon as some item declares tool-types: hammer.
The consequence to know is what a typo does. tool-break-types: pickaxee is not a load error — it names a category, just one no item has — so the block becomes breakable by nothing. That is deliberately the safe direction: it used to resolve to “no tool requirement”, leaving a pickaxe-only block breakable by hand, which is both the opposite of what was written and indistinguishable from omitting the field. The server also warns at load, naming the block and the unmatched category.
Leaving this unset means “no tool requirement” — the block breaks with a bare hand or any tool (still subject to power-required). List one or more categories to restrict which tools work; use breakable: false to make a block permanent. Bare hands are internally treated as a tool with tool-types: [Shovel, Axe, Shears] (no pickaxe) at power level 1, so:
- A block with no
tool-break-typesbreaks with anything, including a bare hand. - A block with
tool-break-types: Axeand the defaultpower-required: 1can be broken by hand (a hand hasAxe). - A block with
tool-break-types: Pickaxecan never be broken by hand — only by a wielded item withpickaxein its owntool-types.
tool-break-types: pickaxe # single category
# or
tool-break-types: [pickaxe, axe] # any of several
block-layer
Which of the world’s layers this block occupies:
| Layer | Use |
|---|---|
0 | Background/walls — non-collidable. |
1 | Foreground — default. Collision, entities, players. Fluids belong here too, so entities passing through them pick up the block’s drag-* physics. |
2+ | Overlay — effects drawn on top of the foreground. |
Drop Table
Blocks use the same shared drop-table block as interactables, mobs, trees, and mounts. It has two optional parts — independent drops: and weighted pick-one groups::
drop-table:
groups: # weighted pick-one — each group yields at most one entry
- entries:
- item: YourMod:dirt
min-amount: 1
max-amount: 1
weight: 0.9
- item: YourMod:stone
min-amount: 1
max-amount: 1
weight: 0.1
drops: # optional: independent rolls (e.g. a rare bonus drop)
- item: YourMod:flint
chance: 0.1
Each group rolls once, picking one entry weighted by weight relative to the group’s total (the classic “always drop the block, weighted by variant” pattern); each drops entry rolls independently on its own chance (a 0.0–1.0 probability). The two keys are different words because they behave differently — a group weight is a relative weight (a lone entry always wins), a drops chance is a probability. See the shared Drop Table reference for full semantics, and Drop Table vs Loot Table for how this differs from standalone Loot Tables.
Shorthand: drops-self
The most common case — a block that drops exactly one guaranteed copy of itself — has a one-line shorthand:
- name: stone
tool-break-types: pickaxe
drops-self: true
drops-self: true is exactly equivalent to writing:
drop-table:
groups:
- entries:
- item: YourMod:stone # this block's own full name
min-amount: 1
max-amount: 1
weight: 1.0
It requires an item registered under the block’s own full name (blocks and items share the Mod:name namespace) — the same requirement as spelling the drop table out by hand. If you set both drops-self and an explicit drop-table, the drop-table wins and a warning is logged.
Variant Of
Registers this block as an alternate visual form of another already-defined block — for example, a snow-covered variant of grass:
- name: snowy_grass
# ...this block's own fields...
variant-of:
- base-block-name: grass
variant-name: snow
base-block-name must be defined somewhere the loader can see it — in this same file, or in a dependency loaded earlier. Order within a file doesn’t matter: a variant may be listed before or after its base block, since variations are resolved after every block in the file has been registered. At runtime, code can look up snowy_grass’s ID via GRASS’s ID plus the variant name SNOW, without either block needing to know about the other beyond this declaration.
Directional Phasing
Controls which directions a block can visually “phase” through a neighbor (used for logs, leaves, platforms, and other blocks that render flush against adjacent tiles). There are two interchangeable ways to set it — a direction is phased if either of them enables it, so you can mix them freely:
# 1. The most common case — all four directions:
phase-all: true
# 2. An explicit subset (directions: up, down, left, right):
phase: [up, down]
phase-all: true is the concise form for the usual “phase in every direction” case; phase: [...] is for an explicit subset. Both forms produce the same underlying per-direction flags.
Suffocation
An entity whose body a block occupies is buried, and takes the suffocation damage configured by its health.suffocation-damage-per-second (see health-config.md). suffocates controls whether this block counts:
# A solid block that should never suffocate — decorative fog, a soft snowdrift:
suffocates: false
# A phasable block that should suffocate anyway — a bramble the player chokes in:
phase-all: true
suffocates: true
Left unset, it is derived: a block that phases in any direction does not suffocate, and every other block does. Phasable blocks (leaves, platforms, logs) are meant to be walked into, so standing inside one is ordinary movement — a player crossing their base on wooden platforms must not choke on them. Set the field explicitly only to override that default in either direction.
The same flag decides whether a block counts as terrain a player is embedded in at spawn: a player who loads in inside a non-suffocating block is left where they are rather than lifted out of it.
Block Shape
block-shape:
type: slab
divisions: 8
side: bottom
count: 1
| Field | Default | Description |
|---|---|---|
type | Full | Full (a normal full-size block) or Slab (a partial-height block). |
divisions | 2 | Slab only. How many pieces a full block is divided into. Must be greater than 0. |
count | 1 | Slab only. How many of those divisions the slab fills. Must be greater than 0. E.g. divisions: 8, count: 1 is a one-eighth-thick slab. |
side | Bottom | Slab only. Which edge of the cell the slab sits against: Top, Bottom, Left, or Right. See the note below — this does not control which way a player-placed slab faces. |
These fields set the shape a block starts with wherever it is placed without a player aiming at it — world generation, Lua, and similar.
side and player placement: when a player places a slab, its side is always taken from where the cursor sits within the target cell — the lower half of the cell gives a Bottom slab, the upper half gives Top, and with horizontal placement toggled off the left/right halves give Left/Right. The configured side is overridden and has no effect on that placement. So setting side: Top does not make a block place as a top slab; it only affects instances placed by world generation or a mod script. divisions and count are always used as configured.
Animated Light Frames
If a block’s light block declares frames, its emitted light pulses in step with its texture animation instead of staying static:
light:
magnitude: 3.0
color: { r: 1.0, g: 0.9, b: 0.4, a: 1.0 }
frames:
- magnitude: 4.0
intensity: 0.8
- magnitude: 3.0
Each frame entry corresponds to one frame of the block’s texture animation (see the block’s texture config). magnitude/intensity are both optional per frame and fall back to the light’s own base magnitude/intensity when omitted. Declaring any frames forces the light to be dynamic rather than static — reserve this for a handful of accent lights, not bulk content, since dynamic lights are considerably more expensive to render.
Lua Hooks
Both hooks are declared under a single scripts: map, 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-on-interact: /blocks/scripts/my_block_interact.lua
server-update: /blocks/scripts/my_block_tick.lua
interact-cooldown-ms: 200
server-on-interactruns when a player interacts with a placed instance of this block. Its handler receives(world, x, y, layer, actor_entity_id, actor), whereactoris the interacting player’s entity object — useactor:has_item(...),actor:grant_capability(...),actor:send_message(...), etc. (Older five-argument handlers that ignoreactorkeep working.)interact-cooldown-mssets a minimum time between interacts on the same cell (0means no cooldown).server-updateruns every server tick for every placed instance of this block. Use sparingly — a block with this hook joins the world’s ticking-blocks registry, so placing many instances means many per-tick Lua calls.
Complete Example
Based on a real light-emitting, interactable block:
blocks:
- name: glow_rock
tool-break-types: pickaxe
time-to-break-ms: 1000
power-required: 2
scripts:
server-on-interact: /blocks/scripts/glow_rock_interact.lua
interact-cooldown-ms: 200
light:
magnitude: 3.0
color:
r: 1.0
g: 0.945
b: 0.4627
a: 0.9
drop-off-distance: 4.0
is-static: true
drop-table:
drops:
- item: YourMod:glow_rock
min-amount: 1
max-amount: 1
chance: 1.0
And a fluid block:
- name: water
collidable: false
breakable: false
block-layer: 1
drag:
up: 0.5
down: 0.5
left: 0.8
right: 0.8
block-matter-type: liquid
fluid-level: 1.0
fluid-flow-per-second: 5.0
fluid-minimum-flow-threshold: 0.5
Last updated