Skip to content

API Logical Networks

Piggo41 edited this page Oct 16, 2026 · 10 revisions

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.

betamoon.logicalNetworks:add(definition)

Field definitions

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.

Topologies

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.

canConnect(ctx)

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.

Component callbacks

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
end

ctx.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)

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)

Signals

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.

Network lookup

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.

Network reference

A live reference exposes key, owner, exists, topology, and tickInterval.

network:override(definition)

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.

Node handle

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.

Clone this wiki locally