Repository navigation
API Capabilities
Lua API / Capabilities
Capabilities define reusable typed behavior contracts for BetaMoon tile entities. A contract declares persistent per-tile state, immutable attachment configuration, and operations. Different tile types can implement the same operations differently, so a network or neighboring machine can use them through one interface.
Registers during modInit() and returns a capability reference with key.
Capability contracts and attachments are structural registrations; changes require a restart.
local energy = betamoon.capabilities:add {
key = "mymod:capability/energy",
state = { stored = { type = "integer", default = 0 } },
config = { capacity = { type = "integer" } },
operations = {
status = {
mode = "query",
response = { stored = { type = "integer" } }
},
receive = {
mode = "action",
request = { amount = { type = "integer" } },
response = { accepted = { type = "integer" } }
}
}
}| Field | Meaning |
|---|---|
key |
Required namespace:capability/name. |
state |
Optional structured fields, saved separately on every attached tile. |
config |
Optional structured fields supplied by each attachment. Fields without declared defaults are required. |
operations |
Optional map of operation names to typed definitions. |
An operation accepts optional request and response field maps. mode = "query" is the default and prevents gameplay mutation. mode = "action" permits mutation when its caller is also in a mutable callback.
| Method | Result |
|---|---|
betamoon.capabilities:get(key) |
Capability reference, or nil when absent. |
betamoon.capabilities:getRequired(key) |
Capability reference; raises an error when absent. |
betamoon.capabilities:find(query) |
Result list filtered by optional key and owner. |
betamoon.capabilities:first(query) |
First match, or nil. |
betamoon.capabilities:one(query) |
Sole match, nil for none, or an error for multiple matches. |
A live reference exposes key, owner, and exists.
Overrides implementations of already declared operations through changes.operations. Schemas and attachment
configuration remain unchanged. An override receives the normal (ctx, request) arguments and can call
ctx:base() to invoke the next lower implementation once.
local patch = energy:override {
changes = { operations = {
status = function(ctx, request)
local result = ctx:base()
result.stored = math.min(result.stored, 1000)
return result
end
} }
}Add an array entry to tileEntities:add { capabilities = ... }.
capabilities = {{
capability = energy,
config = { capacity = 4000 },
ports = { north = "energy", south = "energy", east = false },
operations = {
status = function(ctx)
return { stored = ctx.capability.data:get("stored") }
end,
receive = function(ctx, request)
local stored = ctx.capability.data:get("stored")
local accepted = math.min(request.amount, ctx.capability.config.capacity - stored)
ctx.capability.data:set("stored", stored + accepted)
return { accepted = accepted }
end
}
}}Every declared operation needs an implementation. ports accepts the six absolute faces and front, back, left, right on horizontally facing blocks. Values may be a port name or false to close that face. Omitted ports use the default port.
Operation callbacks receive ctx.world, integer x/y/z, a detached position, ctx.entity.data/capabilities, and:
ctx.capability field |
Meaning |
|---|---|
key |
Exact capability key. |
data |
Persistent local capability state with get, set, and snapshot. Query operations cannot mutate it. |
config |
Detached immutable attachment configuration. |
face |
Requested physical face for external access, when one was supplied. |
port |
Attachment port name, false for a closed face, or absent when no face was selected. |
Requests and responses must exactly match their schemas. A callback error, illegal query mutation, or invalid response rolls state back and disables that operation for the instance to prevent repeated corruption.
Tile callbacks expose ctx.entity.capabilities:
local value = ctx.entity.capabilities:get(energy)
local required = ctx.entity.capabilities:getRequired("mymod:capability/energy")
required.data:set("stored", 20)
local response = required:call("status", {})Local proxies expose:
| Field/method | Meaning |
|---|---|
key |
Exact capability key. |
position |
Detached tile position. |
face |
Selected physical face, when applicable. |
port |
Resolved port name, false for a closed face, or absent without a selected face. |
config |
Detached attachment configuration. |
data |
Persistent local state access; only local proxies expose it. |
call(operation, request) |
Invoke one declared operation and return its validated response table. |
data:get, data:set, and data:snapshot operate on persistent capability state.
ctx.world:getCapability(position, capability, face) or getCapability(x, y, z, capability, face) returns an operation-only proxy, or nil if the chunk/tile/capability/face is unavailable. It never loads a chunk.
local target = ctx.world:getCapability(ctx.x + 1, ctx.y, ctx.z, energy, "west")
if target then
local result = target:call("receive", { amount = 10 })
endExternal callers cannot read or write capability state directly. Proxies and callback contexts expire when the callback returns, and stale proxies reject calls after a tile is removed or replaced. Calls are bounded by nesting depth and a per-world tick budget.
At most 16 capability calls may be nested. Across all scripts, callbacks, and logical networks in one world, at most 4,096 capability calls may begin during one world tick. The shared counter resets when that world's time advances to the next tick. Exceeding either bound raises an error before the requested operation callback begins; it does not by itself disable that operation. Avoid all-to-all network loops, cache repeated query results inside one callback, and limit work per tick when processing large node collections.
Example: Energy network.
- Installation
- Install scripts
- Getting started
- VS Code and LuaLS
- Examples
- Reload and compatibility
- Troubleshooting
- Changelog
Scripts and shared values
- Script lifecycle
- Packaged Lua mods
- Modules
- References and stacks
- Queries
- Overrides
- Minecraft constants
- Chat and positions
- Structured data
- Script configuration
- Particles
Blocks and items
- Multiblocks
- Blocks
- Block state and placement
- Block shapes and rendering
- Block callbacks
- Block ticks and redstone
- Items
- Fluids
- Item callbacks
- Tools and armor
- Materials
- Textures
Entities
- Entities
- Entity access and movement
- Entity lifecycle and data
- Entity health and loot
- Entity inventories and relationships
- Projectiles and pickups
- Entity presentation and sounds
- Living entities and AI
- Entity parts and sensors
Assets and audio
- Assets
- Models and animations
- Built-in Minecraft models
- Model appearances
- Blockbench workflow
- Audio
- Texture-pack overrides
Events and world actions
World generation
World systems
Inventories and screens
Recipes