Peripherals and networks
A computer can reach devices directly on its six faces or through a remotely bound peripheral network. A device API belongs to the integration that provides it: displays and Redstone Ports are built into Compukters, while Create and Propulsion devices need their corresponding addons.
Connect a device
For a directly adjacent device, use Device.at(Side.front) or the API’s existing side helper. Sides are relative to the computer’s
front face: front, back, left, right, top and bottom.
For a remote connection, use the Peripheral Configurator:
- Hold RMB, point at Network binding in the radial menu, then release RMB. A short click performs the selected action; Escape or the center of the menu cancels mode selection.
- Click an unbound computer or device to create a network. Clicking an already bound member selects its network.
- Click other computers and devices to join them to the selected network. The selected configurator glows.
Unnamed devices receive a name such as
display_1orspeedometer_1. The first free number is selected within this network; existing names are preserved. Names use the technical device kind and are independent of game language. - Hold RMB and select Naming to return to naming mode. Click a peripheral to give it a name, or click a computer to rename the network and inspect its members. The inspector shows unavailable devices and lets you remove members.
Shift-use in the air clears the selected network. In network mode, Shift-click a member to unbind it; in naming mode, Shift-click a peripheral to clear its name. A member belongs to one network at a time; unbind it before joining a different network. Names must be unique within the network.
The network persists independently of its computers. After replacing a computer, select the existing network by clicking one of its peripherals, then bind the new computer. Other members keep their bindings and names. A replacement peripheral does not normally inherit the removed block’s membership. A matching display panel placed inside an existing screen automatically rejoins that screen and its network; see Display.
Each computer can reach loaded peripherals in the same dimension within 64 blocks of itself, measured in three dimensions.
The server can configure this through peripherals.access_radius (1–1,024 blocks). Joining a distant member is allowed:
a network can extend arbitrarily far, but each computer has its own accessible subset. No chunks are force-loaded.
With Compukters: Sable, distance follows the current construction position, rotation
and scale. The same network can connect devices on shore and on separate constructions. Assembly and return retain
bindings and names; no special Guest API is needed.
Cable blocks are now Computer Cables, reserved for physical connections between computers. Place a continuous line between two computers; the line can turn or run vertically, but cannot branch or loop. A computer accepts one adjacent cable. Invalid placement is rejected with a message and keeps the item in your hand. Old branched constructions remain in the world but provide no computer link. Links require the entire line and both computers to be loaded.
Cables do not participate in peripheral discovery. Bind peripherals with the configurator; old cable connections are not migrated automatically. Direct adjacent access still works without binding.
For example, open a named display:
import compukter.display.TextDisplay
fun main() {
val screen = TextDisplay.named("panel")
screen.writeAt(0, 0, "Connected")
}
The published image remains visible after the program exits. An adjacent display can instead be opened with TextDisplay.at(Side.front). Follow the
display guide for bounds and output ownership.
Send messages between computers
Connect two powered-on computers with one Computer Cable line. The cable determines the peer; no name, address, modem or configurator binding is required. Both computers and the entire cable must be loaded in the same world.
On the first computer:
import compukter.network.Network
fun main() {
if (!Network.connected) return
Network.send(byteArrayOf(0, -128, -1))
val reply = Network.receive()
println(reply.size)
}
On the second computer:
import compukter.network.Network
fun main() {
val message = Network.receive()
Network.send(message)
}
send copies one complete message into the peer’s inbox. receive waits for one message without blocking the server.
Each inbox holds up to 16 messages, each at most 4096 bytes; empty messages are valid. The world also has a shared
1 MiB queued-byte budget. A full inbox or unavailable connection throws compukter.io.IOException; applications can
catch it and retry later. Oversized Guest arguments are rejected by the VM’s host-request quota before dispatch.
Programs on one computer share its inbox and consume messages in arrival order.
Cutting the cable, replacing or powering off a computer, or unloading a participating chunk discards queued messages
and interrupts waiting receives. Repairing the cable creates a fresh connection. Queues are transient and are not saved
across hibernation or server restarts; a restored waiting receive reports interruption. Messages already accepted by
send are queued, without a delivery acknowledgment. Peripheral bindings remain separate from this cable connection.
Typed discovery
Device classes also act as providers. For example, TextDisplay, RedstonePort, Create’s Speedometer, Stressometer,
RotationController, Pump, Clutch, StockTicker and Boiler, and Propulsion’s CreativeThruster and
CreativeVectorThruster share these methods:
| Method | Result |
|---|---|
first() / first { predicate } |
First matching device; throws NoSuchElementException if absent |
firstOrNull() / firstOrNull { predicate } |
First matching device, or null |
all() / filter { predicate } |
List of reachable devices, optionally filtered |
at(Side.front) / atOrNull(Side.front) |
One device on that relative computer face |
named("name") / namedOrNull("name") |
One uniquely named reachable device |
import create.kinetics.Speedometer
import compukter.peripheral.Side
fun main() {
val moving = Speedometer.firstOrNull { it.speed() != 0f }
println(moving?.speed())
for (gauge in Speedometer.filter { it.speed() > 64f }) {
println(gauge.speed())
}
println(Speedometer.atOrNull(Side.top)?.speed())
}
Discovery follows a deterministic order by device anchor coordinates, addon id and logical device key.
first and firstOrNull stop as soon as the predicate matches. A predicate receives the typed device and may call
its operations. Snapshot resources are released after a normal return, an early match or a thrown predicate.
Optional methods return null for absence; invalid names, ambiguous names, wrong device types and resource limits
remain errors. Missing strict side/name selections throw NoSuchElementException.
The computer retains at most 1,024 typed handles across all integrations, with at most four open discovery snapshots
and 1,024 entries per snapshot. Discovery stays in loaded chunks. In the IDE, provider values have a dedicated color
and a P completion badge; the same name used as a device type keeps ordinary class presentation.
Device wrappers are value classes implementing Peripheral: direct device calls
use scalar handles, while nullable values, interface references and collections use typed managed wrappers.
The old Display, Kinetics, Boilers, Logistics, Thrusters helpers and their separate side types are removed.
Use typed providers and the common Side instead. Create uses addon API 2.1; Propulsion uses API 2.0.
Rebuild dependent Guest bundles and programs against the updated
platform; exact bundle versions and hashes still govern compiled artifacts.
One program owns a device
Acquiring a typed device reserves it exclusively for that running program, including read-only use. Another
program receives compukter.io.IOException while it is busy, even on the same computer. VM tasks inside one
program share its handles; a child process has its own ownership and cannot borrow its suspended parent’s device.
Discovery snapshots do not reserve unread devices. Selecting entries, including entries passed to predicates, acquires handles. The program retains these handles until its device API closes them, the program exits, or connectivity is lost. A second typed view of the same device does not bypass ownership. After hibernation, restoring a persistent handle requires the device to be reachable and available again.
Device handles have a lifetime
A handle refers to the device you acquired, not whichever block later occupies its position. Removing, replacing,
unloading or disconnecting a device can invalidate it. Reconnect and acquire a new handle instead of assuming an old
one will retarget. An expired typed handle fails with compukter.io.IOException; it never revives after reconnection. Control-release behavior depends on the device API. Hibernation can rebind a retained handle when the
provider supplies a persistent instance identity and the same device is reachable on wake. Previously observed
stale handles remain stale; an address alone never identifies a replacement device.
| Device | Guide |
|---|---|
| Redstone Port | Redstone |
| Text display | Display |
| Create gauges and rotation controller | Kinetics |
| Create Stock Ticker | Logistics |
| Create steam boiler | Boilers |
| Propulsion creative engines | Propulsion |
While holding the configurator in either hand, nearby configurable devices receive softly pulsing outlines. Members of a bound network share a color; hovering a member or selecting the network emphasizes the whole nearby group. Outlines are hidden behind blocks. The crosshair panel shows the current mode, target name, network and action hints. Use the item in the air to cycle modes, or shift-use it in the air to clear the selection. Display assembly also shows screen boundaries, holes and unjoined replacement panels; see Display.