Repository navigation
API Logical Networks
Lua API / Logical networks
Logical networks group loaded tile capabilities and schedule one callback per connected component. BetaMoon handles membership and topology; Lua defines transfer, signal, priority, loss, security, or other game rules. Network declarations are structural and require a restart after changes.
Ticks follow actual local-world simulation updates and stop during pausing screens. Non-pausing screens continue them. Remote client worlds do not run authoritative services/networks. The Java agent is required for the simulation driver. Intervals count actual updates from runtime initialization, independently of world-time changes; counters reset when that runtime is recreated. See tick timing.
| Field | Meaning |
|---|---|
key |
Required namespace:network/name. |
capability |
Required capability reference or key implemented by every node. |
topology |
Required topology definition below. |
tick.interval |
Optional component callback interval, 1–1200 ticks. Required with onTick. |
signal |
Optional typed state/pulse definition. |
canConnect(ctx) |
Optional read-only connection filter. Must return boolean. |
onTick(ctx) |
Optional mutable component callback. |
onPulse(ctx) |
Optional mutable pulse callback. Requires pulse/both signal mode. |
| Type | Connections |
|---|---|
adjacent |
Compatible ports on the six neighboring block faces. |
wireless |
Same dimension, channel and compatibility values, within optional transmitter range. |
explicit |
Persistent endpoint IDs joined through link/unlink. |
hybrid |
Union of adjacent, wireless and explicit edges. Use distinct local channels so only intended gateways bridge wirelessly. |
The topology table accepts:
| Field | Meaning |
|---|---|
type |
Required topology name from the table above. |
directions |
Optional compatibility field; the only supported value is "orthogonal". Adjacent edges use the six block faces. |
scope |
Optional compatibility field; the only supported value is "dimension". Wireless and explicit links never cross dimensions. |
range |
Default wireless transmitter range, greater than 0 and at most 1024; omit for unlimited range. |
channelField |
Capability scalar field containing the wireless channel; required for wireless and hybrid topology. |
roleField |
Capability string field containing transmitter, receiver, transceiver, or another local-only value; defaults to role. |
rangeField |
Capability integer/number field that overrides range per transmitter. |
enabledField |
Capability boolean field controlling whether the node participates. |
endpointField |
Capability string/content-key field supplying explicit endpoint identity. |
compatibilityFields |
Up to eight scalar capability fields that must compare equal before two nodes can connect. |
directions and scope are optional; omitting them uses their documented defaults.
Wireless/hybrid roles transmitter, receiver, and transceiver participate wirelessly; another string remains local
to adjacent/explicit edges. Range defaults to unlimited.
Explicit topology requires a string or content-key endpointField from immutable capability config. Links use endpoint IDs and never load offline chunks. Destroying an endpoint removes its links; unloading its chunk keeps them for later reload.
This optional read-only callback runs for a proposed pair and must return a boolean. ctx.first and ctx.second are
capability views. Each exposes key, position, detached config, optional face and port, and
call(operation, request). They do not expose direct state mutation. Action operations are unavailable because the
connection test is read-only; query operations still consume the shared capability call
budget.
The callback may run many times while topology is rebuilt. Keep it deterministic and inexpensive, and prefer
compatibilityFields for simple equality rules.
ctx.network contains key, topology, ephemeral component id, and size. ctx.nodes is a deterministic position-ordered array. Each node exposes the capability proxy plus network, position, and optional endpoint.
onTick = function(ctx)
local producers = ctx.nodes:find { config = { role = "producer" } }
local consumers = ctx.nodes:find { config = { role = "consumer" } }
for _, consumer in ipairs(consumers) do
consumer:call("receive", { amount = 10 })
end
endctx.nodes:find { config = {...}, endpoint = ... } returns matching nodes. ctx.world provides the normal scoped world API. Component IDs may change after split/merge and must not be saved as identity.
ctx.network:pathDistance(first, second) returns the shortest path length between two entries from the current
ctx.nodes list. The result counts the actual edges produced by adjacent, wireless, explicit, or hybrid topology;
the same node has distance 0. Calls are read-only, and repeated queries from the same starting node are cached for
the duration of that callback. Passing a table or node from outside the current ctx.nodes list raises an error.
local producers = ctx.nodes:find { config = { role = "producer" } }
local consumers = ctx.nodes:find { config = { role = "consumer" } }
table.sort(consumers, function(first, second)
return ctx.network:pathDistance(producers[1], first)
< ctx.network:pathDistance(producers[1], second)
end)signal.value is a structured field. Mode is state, pulse, or both. State aggregation is
latest, any, all, maximum, minimum, or sum; boolean and numeric aggregators require matching value types.
ctx.signal is the component's aggregated state. A pulse callback additionally receives ctx.pulse and its source
position. Pulse queues and lifetime are bounded. retainWithoutTransmitters = true preserves a wireless transmitter's
last publication in world data and lets compatible loaded receivers continue seeing it while that transmitter is
unloaded.
| Method | Result |
|---|---|
betamoon.logicalNetworks:get(key) |
Network reference, or nil when absent. |
betamoon.logicalNetworks:getRequired(key) |
Network reference; raises an error when absent. |
betamoon.logicalNetworks:find(query) |
Result list filtered by optional key, owner, and topology. |
betamoon.logicalNetworks:first(query) |
First match, or nil. |
betamoon.logicalNetworks:one(query) |
Sole match, nil for none, or an error for multiple matches. |
A live reference exposes key, owner, exists, topology, and tickInterval.
Replaces canConnect, onTick, onPulse, and tickInterval. Callback layers can call ctx:base() once.
Capability, topology, compatibility, and signal schemas remain structural. Removing the returned handle restores the
next lower behavior.
Tile callbacks obtain the current node through ctx.entity.networks:get(network) or getRequired(network).
| Method | Behavior |
|---|---|
markDirty() |
Re-evaluates topology after script-controlled membership facts change. Capability state changes already do this. |
publish(value) |
Stores typed state for state/both signal mode. |
pulse(value) |
Queues one typed event for pulse/both mode. |
link(endpoint) |
Adds a persistent explicit/hybrid link; returns whether changed. |
unlink(endpoint) |
Removes that link; returns whether changed. |
Only loaded nodes receive callbacks. Removing/unloading a node invalidates membership; adjacent components split, wireless receivers go offline, and no operation force-loads terrain.
One network runtime supports at most 4,096 loaded nodes and 16,384 computed edges. A network can queue at most 1,024 pulses, and one pulse may travel at most 16 hops. Exceeding the node or edge limit, or encountering a topology/callback error, disables that network with an actionable error. Exceeding the pulse count or hop limit rejects that pulse. Capability operations called by network callbacks also share the per-world 4,096-call tick budget.
Examples: energy network and wireless trigger.
- 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