Skip to content

API Tile Entities

Piggo41 edited this page Oct 16, 2026 · 17 revisions

Tile entities

Lua API / Tile entities

On this page

betamoon.tileEntities:add(definition)

Registers a persistent tile definition and returns a tile handle with name. Attach it through a block's tileEntity field. Register from modInit(); the owning script is retained on hot reload and changes require restart.

local tile = betamoon.tileEntities:add {
    name = "mymod:block/storage",
    inventory = { slots = { input = { index = 0 }, output = { index = 1 } } },
    data = { progress = { type = "integer", default = 0, sync = true } }
}

Field definitions

Field Type Requirement / default
name string Required. Unqualified names receive a namespace derived from the script filename; qualified names are lowercased.
inventory table Optional. Omit for a data/capability-only tile with no slots.
inventory.name string Defaults to qualified tile name; inventory display label.
inventory.slots map of names to tables Optional slot definitions.
inventory.slots.<name>.index integer Optional explicit persistent index, 0 through slot count minus one. Must be unique.
data map of names to field definitions Optional persistent fields.
capabilities array of attachments Optional reusable capability implementations.
onTick table Optional tile ticking configuration.
onInventoryChanged table Optional notification callback.

Explicit slot indices preserve saved inventory layout. Missing indices receive free indices in sorted slot-name order. Re-registering an existing qualified name returns its retained definition.

data fields

Field Meaning
type Required structured-data type.
default Optional type-appropriate initial value.
sync Default false. Only integer and boolean fields may synchronize to container GUIs.

Values are saved per placed tile. Lists, records, vectors, block positions, item stacks, and content keys are supported. GUI-bound fields must use sync=true. Schema changes require restart and a saved-world compatibility review.

onTick

Required action = function(ctx) ... end and mode.

Mode Behavior / options
continuous or default One update per active tile tick.
scheduled Required schedule.delay > 0; optional schedule.repeatEvery ≥ 0, default 0 (no repeat).
random Per-tile tick probability chance, default 0.05; range 0–1.

Tile random mode evaluates its configured chance each tile tick.

onTick = {
    mode = "continuous",
    action = function(ctx)
        ctx.entity.data:set("progress", ctx.entity.data:get("progress") + 1)
    end
}

onInventoryChanged

Optional { action = function(ctx) ... end }. Notifies inventory changes with a tile context. Avoid recursively modifying inventory from its own notification. Failed tile callbacks are reported and disabled.

Tile lookup

Method Result
betamoon.tileEntities:get(name) Tile handle, or nil when absent.
betamoon.tileEntities:getRequired(name) Tile handle; raises an error when absent.
betamoon.tileEntities:find(query) Result list filtered by optional name and owner.
betamoon.tileEntities:first(query) First match, or nil.
betamoon.tileEntities:one(query) Sole match, nil for none, or an error for multiple matches.

Tile handle

A live handle exposes name, owner, exists, tickMode, initialTickDelay, repeatTickDelay, and randomTickChance.

tile:override(definition)

Overrides onInventoryChanged and onTick. An onTick table may replace the action, cadence, or both using the same mode, schedule, and chance fields as registration. Existing placed tiles restart their transient tick schedule when cadence changes. Inventory, data, and capability schemas remain fixed. Removing the returned handle restores the next lower behavior.

Tile context

Field Meaning
x, y, z Tile block coordinates.
entity.data Persistent data access.
entity.inventory Named inventory access below.
entity.capabilities Local capability access.
entity.networks Local logical-network node access.
entity.markDirty Save-dirty notification method.
world Full world action access, including power, block/entity actions, and explosions.
recipes Smelting lookup and bound recipe matching.
fuels Burn-time lookup.
state Scoped block-state access when the attached block has a callback definition.

Use this context for the current callback. Its tile data, inventory, recipe, and fuel helpers are tile-specific; its world handle follows the shared action-world contract.

Data access

data:get(name)

Returns the saved field value. Used as ctx.entity.data:get(name) in tile callbacks, or ctx.tileEntity.data:get(name) through scoped block access. Structured values are detached.

local progress = ctx.entity.data:get("progress")

data:set(name, value)

Validates against the declared field type, updates the value and marks changed data dirty. Unknown fields or incompatible values raise an error. Scoped block access also enforces callback lifetime and mutation permissions.

ctx.entity.data:set("progress", 0)

data:snapshot()

Returns a detached table of all declared values. Changing the table does not mutate the tile.

local saved = ctx.entity.data:snapshot()

Inventory access

All methods use declared slot-name strings. Unknown names raise an error. Returned stacks are detached { id, count, damage } descriptions. Inventory, data, recipe, fuel, capability, and network handles expire when the callback returns.

inventory:get(slot)

Returns the slot's stack snapshot or nil when empty.

local input = ctx.entity.inventory:get("input")

inventory:set(slot, stack)

Replaces the slot; nil clears it. Accepts a stack input as described in References and stacks. Native inventory limits may clamp assigned counts.

ctx.entity.inventory:set("input", nil)

inventory:remove(slot, count)

Removes up to count items and returns the removed stack or nil. Count defaults to 1; use a positive integer.

local taken = ctx.entity.inventory:remove("input", 1)

inventory:canAdd(slot, stack)

Returns whether a non-nil incoming stack can be added. For occupied slots, identity/damage must match and combined count must fit both the inventory limit and item limit. The current empty-slot check does not enforce those limits; supply valid bounded counts.

local fits = ctx.entity.inventory:canAdd("output", betamoon.stack(265))

inventory:add(slot, stack)

Adds to one slot and returns true, or false if incompatible/full/nil. Empty-slot insertion uses normal slot assignment, which may clamp counts. This is not a multi-slot atomic recipe operation.

local added = ctx.entity.inventory:add("output", betamoon.stack(265))

inventory:consumeFuel(slot, set)

Resolves and consumes one accepted fuel atomically, returning its duration in ticks or 0 without changing the slot. set is an optional fuel-set reference or key and defaults to betamoon.mc.fuels.furnace. A native container-item fuel leaves its container in the slot.

local burnTime = ctx.entity.inventory:consumeFuel("fuel", boilerFuels)

See Fuels for set declarations, matching order and reload behavior.

ctx.entity:markDirty()

Marks the tile for saving. Data/inventory mutators already mark their own changes.

ctx.entity:markDirty()

ctx.world:isPowered(x, y, z)

Returns aggregate indirect power at the tile position when coordinates are omitted. Supply all three integer coordinates to inspect another loaded position. This method has no directional face argument.

local powered = ctx.world:isPowered()
local remotePowered = ctx.world:isPowered(ctx.x + 4, ctx.y, ctx.z)

ctx.world:notifyNeighbors(x, y, z)

Notifies neighboring blocks of a change at the tile when coordinates are omitted. Supply all three integer coordinates to notify another loaded position. Returns whether the notification was performed.

ctx.world:notifyNeighbors()

ctx.recipes:getSmeltingResult(stack)

Returns a detached vanilla smelting output or nil. Looks up by input ID, not custom recipe types.

local output = ctx.recipes:getSmeltingResult(ctx.entity.inventory:get("input"))

ctx.recipes:match(query)

Matches against this tile's bound inventory. Returns a match object with canApply and apply, or nil. See Recipe matching.

ctx.fuels:getBurnTime(stack, set)

Returns the matching duration without consuming anything, or 0. set defaults to the built-in furnace set and can be a fuel-set reference or key.

local ticks = ctx.fuels:getBurnTime(ctx.entity.inventory:get("fuel"), boilerFuels)

See Fuels.

Examples: Storage declarations, custom furnace.

Multiblock controller gate

A live tile context exposes optional ctx.multiblock when its block is a managed controller. Check ctx.multiblock:isFormed() before continuing machine processing. Recognition does not change this tile's inventory, data, metadata or appearance. The handle expires when the callback returns; reacquire it in later callbacks. See multiblocks.

Clone this wiki locally