Minecraft devices and addon ownership

← Architecture

World-thread effects and devices

The Minecraft carrier owns exactly one actor endpoint and submits ordinary advancement once per server tick. Eligible host continuations may reuse the remaining frame credit, deadline and cumulative quotas described in runtime ownership. Rust starts /rom/boot, compiled from system/programs/boot.kt; boot delegates to /rom/shell, compiled from system/programs/shell.kt. A foreground child suspends its parent until it exits or fails. There is one active foreground lane today, while the runtime contract leaves room for later parallel execution. Hibernation preserves the machine stack and terminal across unload/reload; reboot replaces the complete machine stack and clears the terminal. Minecraft sends full state to a new viewer and ordered deltas thereafter. Terminal viewers submit bounded asynchronous key, text, state, resync, and resource-snapshot operations, which merge in server-arrival order without client-side echo or a terminal input lease. A valid standalone-terminal viewer samples resources immediately and then every ten server ticks through the same single-poll admission. Its viewer-local window retains one prior sample to derive semantic consumed/granted Guest-unit usage; it is discarded on close, invalidation, machine replacement, or server stop. Replies are published only after returning to the server thread and only while the viewer still refers to the same machine epoch.

Raw terminal

The raw terminal is a synchronous Rust device: cell writes, positional writes, rectangular fills, colors, cursor changes, and input polling never cross into Minecraft. The authoritative fixed 51x19 cell grid and its replication journal live in the machine, alongside a bounded 512-row history of scrolled cells. History survives viewer close/reopen and hibernation; reboot replaces it. Screen clear preserves history. Full states include history, and ordered append/replace changes preserve it through journal compaction. Minecraft owns only history navigation, rectangular selection and clipboard interaction over replicated cells. Waiting for an absent input event and foreground process execution are explicit suspension points. Kotlin guests consume ordered raw Text and Key events; there is no compatibility line buffer or second input protocol. The Guest Terminal facade returns an owned event snapshot and finishes its native event before returning, so starting an interactive child cannot retain that event ownership. The server host never blocks the Minecraft thread.

Redstone

Minecraft owns the persistent 30-bit redstone output register and samples dirty local faces before VM advancement. Rust owns the complete input snapshot, predicate waiters, and confirmed output mirror. Input crosses FFI as one scalar changed-mask-plus-levels packet; output requests are reduced in publication order and committed through one loader-independent host port at most once per computer per tick. A successful physical commit is confirmed to Rust before every original blocking request resumes. Completion and the next bounded advance share one actor command and one result without allowing multiple advances in a server tick. VM halt, fault, shutdown, reboot, and replacement never synthesize a zero output.

Sound

One-shot sound requests cross the same actor boundary as immutable (note, volume) batches. Minecraft emits the vanilla note-block pling in the block sound category, using equal-temperament pitch around neutral note 12, before the VM task receives its Boolean admission result. Each loaded computer has a four-tick cooldown, and one server-wide counter admits at most 64 computer sounds per tick. Rejected sounds return false immediately and are never queued; unloaded block entities retain no sound state or background work.

Computer GPIO sides are independent inputs and outputs. The chassis is not a passive redstone conductor: a strong input (such as a lever attached above it) cannot power a device on another face through the computer. Input sampling still reads the neighboring source, while explicit weak/direct program outputs retain their directional behavior. Samples collected before asynchronous boot completes are retained and replayed once as a complete input snapshot; normal changed-side packets resume afterward, so a steady input present at startup is not lost.

Peripheral fabric

The Minecraft carrier resolves its six direct provider contacts and persisted remote network members. Providers map contacts to canonical logical identities. A versioned overworld SavedData directory owns network UUIDs, names and member identities independently of computer lifetime; NeoForge persistent block-entity UUIDs prevent replacement blocks from inheriting membership. Member names belong to that directory; unbound adjacent devices retain the separate world-owned naming directory. Configurator selection lives in item custom data, with server-side proximity, held-item and exact-instance validation for edits. Explicit configurator joins assign unnamed members the first free device_kind_N name in that network, including unavailable members in collision checks. Existing names survive repeated joins; ordinary binding used by migration, screen assembly and split does not generate names. Composite display names remain authoritative in DisplayStorage, so configurator joins synchronize the generated name there. Numbered names use stable technical kinds rather than translated labels, and reuse vacated suffixes without a new persisted counter or schema. Chunk-load callbacks queue address-hint refresh without forcing chunk loads. They never read the overworld directory inline during level construction: force-loaded Sable plots can report loaded block entities before the overworld is registered on the server.

Membership does not imply reachability. A computer resolves only loaded, same-dimension members within the configured Euclidean radius (64 blocks by default), then deduplicates them with direct contacts. Discovery sorts canonical identities and rejects ambiguous reachable names. Networks are bounded to 1,024 members each, 4,096 networks and 65,536 total members per world. Computers in a network are membership anchors, not Guest peripheral endpoints. Cable blocks no longer contribute discovery. Guest signatures and permanently stale handles remain unchanged. The optional CompuktersPeripheralWorldIntegration SDK adapter projects storage coordinates to live world positions and supplies already-loaded nearby block entities for configurator overlays. Ordinary worlds use the identity projection. Range checks and configurator proximity use logical poses on client and server and project both endpoints, while exact block identities still use storage addresses. The independent physical-client installRenderProjection adapter receives the current frame’s partial tick; Sable projects attached displays and configurator outlines through the same interpolated render pose as its blocks. Without that adapter, rendering retains the logical projection. Unloaded/removed plot locations return unavailable without falling back to storage coordinates. Outline vertices and display quads are resolved during frame extraction, so deferred submission never rereads mutable construction poses.

Explicit batch transfers capture exact source identities before copying blocks and guard source removal and destination display creation until the whole batch completes. Closing the scope relocates only matching destinations whose source was removed; a copied member whose saved address differs from the source cannot transfer another block’s membership. The scope is cleared even when the move throws. Complete displays retain canvas UUID, name and published RGB state; relocation retires location-bound handles and private frames. Moving part of a display splits it into panels, retaining the network, each published tile and the name on the first panel. Ordinary removal outside a transfer remains destructive.

Bulk construction storage deletion must call CompuktersPeripheralWorldIntegration.removeBlocks before discarding its loaded blocks. Its ownership predicate retires only those display tiles and respects active transfer guards. Sable invokes this for permanent REMOVED plots; UNLOADED preserves saved displays.

Serialized construction adapters can hold a loaded-address guardTransfer while calling prepareTransferAsync. Its future includes final VM hibernation and filesystem attachment release; poll completion without blocking the server thread. Keep source ticks and computer admission gated until the coordinator opens beginTransfer for the exact source/destination block map. Close the move scope after source removal (or destination discard on rollback), before publishing the world checkpoint. The existing void preparation entrypoint remains available to synchronous block-move adapters.

For journal recovery, recoverTransfer guards both recorded address sets without manufacturing device identities. After removing obsolete copies, call resolve with the selected survivor already loaded; this relocates matching membership and complete display canvases. Plain close only releases guards, so cancelling or shutting down a coordinator cannot accidentally commit destination authority. A copied, missing or replaced endpoint still cannot satisfy an exact-instance descriptor.

Displays

compukters:display capability 1.2 preserves graphical operations 4–16 and the original operations 0–3, adding click polling at operation 17. Guest compukter:core 7.3.0 exposes GraphicalDisplay, resolution modes, RGB colors, drawing, typed clicks, widgets and an inline frame extension. TextDisplay remains source-compatible and rasterizes its 20x10 grid at HIGH density.

A dimension-owned DisplayStorage SavedData contains a bounded DisplayDirectory: logical screen UUIDs, one plane and fixed rectangular geometry, actual panel UUIDs, a shared name, density and packed published RGB bytes. Missing panels are holes in the logical image. Last-panel destruction removes the record; chunk unload does not. Panel block entities persist only their instance identity, never duplicate the authoritative canvas. The configurator assembles at most 8x8 blocks, selects existing screens, expands to include standalone panels and splits into 1x1 canvases. New exact block instances automatically join a same-facing hole only when one saved screen claims that slot; exterior placement never merges screens. Multiple matching holes leave the panel separate for explicit selection. Expansion copies published pixels to preserve their physical locations, with black new area and stable canvas UUID/name/density. Replacing geometry retires old leases/private frames and invalidates existing endpoints through surface identity. Split crops only installed tiles, preserves density and removes the shared name/old rectangle. Quotas and loaded exact panels are checked before splitting; the matching network member becomes one member per new independent screen.

DisplayNetworkAccess stores one network member under the canvas UUID, retaining the existing display provider and text device key. A physical panel is only an address hint; discovery and availability validate any loaded exact member within the computer’s radius. Binding, selection and removal through any panel address the same canvas. Assembly and joining inherit a single source network, or remove all participating memberships when networks differ. Partial destruction refreshes the hint; last-panel destruction removes membership. Legacy physical-panel bindings are consolidated only after their loaded block entities validate the saved panel identities and physical stamps. An incomplete legacy upgrade waits for remaining chunks without forcing loads or granting replacement blocks access. The network SavedData schema and Guest capability remain unchanged; screen names remain authoritative in DisplayStorage.

Each program holds an exclusive canvas lease. Reset, termination or loss of every reachable panel releases it without erasing pixels. Private frames belong to one cooperative task, are bounded to 262144 pixels per program, and carry a cumulative work counter. Resource checkpoints preserve leases and private frames without replaying published pixels. Asynchronous computer hibernation retains its lease validity through checkpoint capture, then host reset releases it. Guest operations still reject detached endpoints throughout that transition. Composite contracts opt into their own member reachability; the original four-argument JVM constructor remains available to already compiled addons.

The server captures owned committed canvas pixels and membership on its owner thread. A per-server, two-thread encoder prepares RGB tiles and delta rectangles without world access. Admission permits at most 16 jobs and 64 MiB of estimated snapshot/output storage, with one job per surface; busy surfaces retain their authoritative newest canvas rather than queuing intermediate copies. Completion returns through the server executor, checks the exact level/surface/canvas/membership generation and immediately offers ready ordinary block tiles. Level unload and server shutdown invalidate pending results. Attached panels use the same encoder and their existing viewer transport.

A publication stays frozen while panel tiles are sent under the dimension’s unchanged 512KiB/tick budget. Ordinary block tiles use bounded custom payloads containing block instance UUID, screen identity, publication, member positions and full/delta RGB. Chunk tracking carries identity/metadata only. Clients request independent full tiles for first tracking or missing delta bases; the server keeps bounded, expiring recovery requests while encoding/admission waits. Requests never load chunks and require the player to be tracking the requested chunk, including distant visible screens. The client validates the loaded block instance on its owner thread, then prepares images in one ordered worker lane with at most 64 queued tile jobs. Switching levels shuts down that lane. Workers touch captured images only, so retired block objects cannot update replacements.

Clients retain at most two pending immutable tiles per panel: the latest complete publication and the next partial publication. The render-thread barrier chooses the newest complete set across loaded members and commits the exact candidates it checked, preserving newer partial data. A following partial frame cannot hide an already complete frame before rendering. Publication is frozen after the first visible panel of each render frame; worker delivery between panel draws waits for the next render frame. Unloaded members and holes do not block it. Texture upload stays on the render thread; dynamic emissive textures change only on committed revisions and are released when panels unload. Deterministic clipping and a 4M pixel-work/tick budget bound server drawing. Saved canvas schema, Guest calls and terminal transport are unchanged.

Foreground termination

Ctrl+C is reserved in computer terminal input (key code 67, CONTROL modifier), including the IDE target terminal. The native computer consumes it independently of Guest input polling and queue capacity. A press marks the foreground child below the nearest /rom/shell frame, or the first child of a standalone parent, for termination. An idle shell and a root without a parent are preserved; an idle press reaches Guest input. Successive native advances unwind its descendants with status 130 and ordinary ProcessExited lifecycle events, allowing the existing host scope cleanup to release peripheral leases and reject stale completions. The host cancels pending compilation and wakes an input/compiler wait; native termination discards the corresponding compiler transaction. Queued input for the terminated command is discarded at the press. After unwinding, line-oriented output resumes below visible content without clearing the terminal; normal scrolling applies when the screen is full. Held-key repeats are consumed without scheduling another stop. Terminal keys C (67) and U (85) extend the admitted key set compatibly: existing key values, payload layouts, artifact ABI and C ABI remain unchanged; both native transports use their existing terminal-key function.

Typed peripheral discovery

The canonical compukter:core 2.0.0 library defines compukter.peripheral.Peripheral, PeripheralProvider<T>, relative Side values and TypedPeripheralProvider<T>. Companions supply a registered contract id and the typed device wrapper. Selection runs in Guest; snapshots close in finally, including predicate failure and early selection. Predicates are ordinary typed callbacks with local returns.

The base compukters:peripheral capability is ABI 1.0 with six asynchronous operations, in order: openSnapshot(String):Int, snapshotSize(Int):Int, snapshotGet(Int,Int):Int, closeSnapshot(Int):Unit, at(String,Int):Int, and named(String,String):Int. Optional direct lookup returns handle zero only for absence. Malformed requests, unavailable contracts, ambiguity, wrong device types and limits remain host failures. This adds a capability while preserving the artifact, Runtime instruction and native transport ABI.

core owns PeripheralSession and PeripheralProgramHost, independently of Minecraft. A typed contract identifies its provider and logical device kind and resolves exact endpoint instances. A program has at most four snapshots, 1024 discovered entries per snapshot and 1024 retained handles. Snapshot opening captures physical identities without retaining handles for unread entries; handles are allocated only on selection. Typed operations verify contract object identity before exposing a retained endpoint. Invalidity latches, stale tokens cannot acquire replacement instances, and reset discards state without reusing tokens. World discovery order and face/name lookup belong to the Minecraft adapter. Addons retain ownership of device operations and capability schemas.

PeripheralOwnership is shared by all program sessions on a Minecraft server, across computers and dimensions. Handle acquisition reserves an exact logical instance exclusively for that program, before reads or writes. Contract aliases share the same ownership key; unread snapshot entries are not reserved. Program stop and reset release retained leases; a server tick expires disconnected endpoints even without Guest operations. Server stop clears the registry. Device adapters may implement PeripheralHandleLease for acquisition/release effects.

The built-in Redstone Port uses compukter:redstone_port and additive compukters:redstone-port capability ABI 1.0: input(Int,Int):Int, setOutput(Int,Int,Int):Unit, awaitChange(Int,Int):Int, awaitLevel(Int,Int,Int,Int):Int, close(Int):Unit, setAllOutput(Int,Int):Unit. All operations are asynchronous. The ALL output operation commits all faces before one changed-face neighbor notification. The common host owns waiters; the server block entity samples six inputs and owns transient output levels. The final handle release clears outputs and notifies neighbors. No output NBT or persistent endpoint stamp is supplied; interrupted hibernation waits fail rather than replaying control. The existing artifact and native transport ABI is unchanged.

Evidence: PeripheralSessionTest, PeripheralProgramHostTest, and canonical peripheral companion specializes shared typed queries through testKotlinPeripheralQueriesVmConformance, including predicate short-circuiting, imported Peripheral upcasts, nullable absence, strict exceptions and snapshot cleanup after predicate failure.

The Minecraft adapter binds registered ComputerPeripheralContract<T> descriptors once per program, through ComputerPeripheralRuntime. Loaded network/direct contacts sort by x/y/z, provider and device key; side lookup resolves the contacted face directly. SDK 0.5.0 adds typed CompuktersPeripheralContract<T> registration and CompuktersComputerContext.peripheral access, retaining the earlier overloads. SDK JARs depend on core only at compile time and retain their explicit thin-archive class inventory. Both Minecraft version families compile the canonical shared adapter sources. SDK 0.6.0 adds optional SDK-owned acquisition/release callbacks mapped to the existing core handle lease, retaining old endpoint constructor ABIs without exposing core lifecycle types to addon consumers. The existing server-tick ownership expiry remains the source of disconnection cleanup. Transient actuators must not replay commands from saved block state on world load.

The shared Compukters creative tab appends lazy addon item groups from ComputerAddonCreativeItems, ordered by addon ID after base items. The host SDK exposes registration; both Minecraft target registries consume the same catalog. Empty addons create no tabs, and duplicate items are suppressed without reordering their first occurrence.

TextDisplay is a scalar value class implementing Peripheral, with a canonical box and a managed companion provider. All public acquisition uses typed providers and the common Side; the earlier Display/Create/Propulsion helpers and separate side types are removed. Display operations still own output leases; discovery creates no lease, and reset releases writer leases without erasing published pixels. The real text-display GameTest fixture covers typed selection, interface casts, predicates, optional/strict absence and cleanup after a thrown predicate before exercising a world write and network disconnection.

Addon module selection and Propulsion

Terminal, standard output and error, redstone, sound, process, filesystem, and compiler declarations live in the base guest-platform bundle under compukter:core; core language declarations belong to kotlin:builtins and environment-independent helpers to stdlib:core. Optional integrations publish bounded addon Guest API bundles instead. The server admits those bundles, includes their content hashes in the target and compilation-cache identity, and sends their metadata and optional sources to the attached IDE. Analysis indexes the bounded catalog of available addons for completion, while K2 semantics and compilation activate only the modules selected in the project lock. Compiler and analysis workers decode only this data format: they never load or execute addon code. Exact admitted bindings extend intrinsic lowering, while a same-named Guest declaration remains ordinary Guest code. General stream handles, pipes, and process redirection remain later layers. Addon host handlers report failures with a broad HostFailureKind and a non-empty UTF-8 detail of at most 256 bytes. The kind remains suitable for runtime classification; the producer-owned detail is diagnostic text and is not a stable programmatic identifier.

The independent addons/propulsion build owns named Creative Thruster and Creative Vector Thruster control and its propulsion.api Guest module. It depends on upstream Propulsion/Create/Sable types, without depending on other Compukters addon implementations. Commands and observations execute through the existing server-thread addon request boundary; physics and VM cadence are unchanged. Controller identity and device reachability bind each handle. A server-confined lease registry owns only temporary program control, validates active leases on server ticks, and restores normal redstone on release. It does not mirror authoritative thrust or physics state. Typed observations copy current upstream fields in kN. The pinned Propulsion binary persists digital commands, so a dedicated read/write mixin marks owned full NBT saves and clears the unowned digital input/mode when those saves or construction copies load; client packets are unaffected. Vector steering temporarily overrides mapped local targets without changing live redstone-link inputs. On release, targets follow the latest signals; digital input and the old shutdown envelope are cleared before the creative thrust override is removed, then physical thrust is recalculated from the current redstone input. This prevents residual program throttle from multiplying the restored engine setting. Full saves retain redstone signals and the saved engine configuration, clearing owned steering/tween and absolute thrust commands; client packets retain the live visual state. Full NBT also persists an engine UUID for exact-device peripheral rebinding. Logical computer checkpoints retain owned command values separately; restoration reacquires leases and applies power/steering before the setter that publishes custom physical thrust. Read-only handles remain read-only, replacements remain stale and competing writers cause rollback plus the common cold-boot recovery. Capturing detached resources does not revalidate world reachability. Unloaded/restoring computers do not guarantee continuous thrust; physics continues. Vector mount operation 12 copies integer computer-relative block offsets, a neutral force axis and the common construction ID. It rejects cross-construction mounts; ordinary-world mounts have an empty ID and world axes. Guest flight programs own geometry-to-torque allocation; names do not encode corner orientation. Vector capability operations append IDs 5..12, preserving ordinary operations 0..4 at capability version 1, Runtime ABI 1.13 and C ABI 20. The independent addons/dev run build composes all three addon archives and their GameTests with the upstream Aeronautics/Propulsion runtime.

Sable construction lifetime

The Compukters Sable addon supports assembly, full construction unload/reload and return to the ordinary world through the same carrier checkpoint path. Physics keeps running during computer restoration; no activation barrier or upstream Sable/Rapier patch is installed. The live-physics GameTests continue suspended Guest programs and query the same construction after reload. In unthrottled GameTests on the development machine, activation to continued Guest physics queries took 35 ms for one computer on a two-block construction and 68 ms for both computers on a 29-block construction, with the second computer eight blocks from the assembly anchor. Cold compilation precedes the measured interval. These results do not bound arbitrary heaps, construction sizes, disk latency or server load.

Cosmonautics dimensional construction transfer

The independent Cosmonautics addon wraps the pinned SubLevelWarper.WarpSubLevels transaction. All source computers capture their world-owned resources before template serialization, using asynchronous hibernation and the existing filesystem attachment barrier. The adapter opens one explicit block-transfer scope using upstream MoveInfo plot translations before any destination template loads, and closes it after source plots are retired, including exceptional completion. A source plot’s removed chunks do not invalidate an otherwise verified exact-instance destination. Network member UUIDs follow the moved addresses; copied live source metadata outside this scope cannot steal membership. Retained handles resolve their saved member UUID through the authoritative directory and still require the same endpoint stamp and exclusive process ownership. Unbound direct devices use computer-relative offsets for translated constructions. A removed or replaced peripheral remains stale; a failed/partial move does not adopt an arbitrary same-name device.

Physics continues while checkpoints publish and restore. Pending world requests can resume with their ordinary interruption failure; ascent programs recheck actual Deep Space membership before issuing cutoff through the retained handle. This is not an activation barrier or a guarantee of uninterrupted thrust. Old absolute-location checkpoints can resume at their saved addresses, but do not gain portable identities retroactively.

Interactive display input

Display capability 1.2 preserves operations 0–16 and appends operation 17, pollClick(handle: I32): BYTE_ARRAY. Minor 0/1 requests cannot invoke operation 17. An empty array means no event; otherwise exactly eight bytes contain unsigned little-endian x and y in published canvas pixels. compukter:core 7.3.0 wraps this private encoding as GraphicalDisplay.pollClick(): DisplayClick?, with a Position2i position.

Empty-hand front-face right-clicks use renderer-aligned coordinates for all four orientations and add panel offsets in a composite canvas. Shift-use passes through. Server-thread input is a FIFO limited to 64 entries; overflow drops new arrivals. Input belongs to the program’s exclusive writer lease. Polling claims that lease. Lease release/expiry, world restore, layout retirement and committed density changes clear input. Aborted frame density changes preserve it. Pending queue entries are never included in canvas or program resource checkpoints. Values already returned to Guest code are ordinary program data and follow its normal execution/checkpoint semantics.

World-display pointer gestures

The physical client sends a held-use heartbeat while empty-hand RMB is down and no GUI is open, and one release message on transition. The server derives aim/range/face/panel offsets from the actual player, never accepting client coordinates. A bounded controller keeps at most 64 player records and eight captures per canvas; only initial Down acquires a target. Moves across panels in the same exact canvas retain capture; leaving the screen cancels until release, and five missing ticks cancel stale capture. Disconnect and server shutdown release controller state. The client bridge is shared by both target families and registration is on the dedicated-server payload path as well.

Guest pollPointer and legacy pollClick are independent transient queues. The widget tree consumes only explicitly supplied events; no Minecraft-side mirror of widget state exists. Drawing regions are carried per command, so there is no ambient clipping stack to restore across frame or VM checkpoint boundaries.

Peripheral structure geometry

A provider resolves every contact on a formed multiblock to the same controller anchor and device key. The controller owns the exact-instance stamp, configured name and persistent network membership. The optional CompuktersPeripheralGeometryProvider interface supplies block-aligned world bounds for presentation; existing SAM providers and identity constructors remain unchanged. Geometry never enters peripheral equality, Guest schemas or saved network records. The overlay adapter accepts only finite bounds containing both anchor and contact, at most 64 blocks on each axis; invalid metadata falls back to the anchor block. Overlay protocol 2 transports validated inclusive block bounds, deduplicates by anchor and uses the same geometry for hover, HUD and the existing depth-tested pulsing outline.

The Create adapter resolves active Fluid Tank boilers through Create’s real controller and width/height. Inactive or unformed tanks remain unavailable. Explicit configurator interaction consolidates old per-block memberships only when their current exact-instance stamps and provider resolution still match the structure. One source network is inherited; conflicting networks leave the resulting device unbound before the requested binding action. An unambiguous name is retained. Holding the configurator only observes structures and never creates stamps or consolidates memberships.

Attached display transfer guards can open before the destination native plot exists. Publication requires loaded destination backing blocks matching the captured source. Permanent bulk removal notifies active transfer scopes before retiring metadata, proving source vacancy after plot deletion; chunk or construction unload must never send that signal. Journal recovery uses the coordinator’s existing address map and selected authority to relocate saved attached surfaces, without a second persisted manifest or a Sable dependency in the host.