Create kinetics

The optional Create addon exposes speedometers, stressometers, Rotation Speed Controllers, programmable pumps and programmable clutches on Minecraft 1.21.1. See the Create overview for installation, project setup, peripheral cables, and device naming.

The device classes also support shared typed discovery: first, firstOrNull, filter, all, at/atOrNull, and named/namedOrNull. See typed peripheral discovery. Use these typed providers for every device lookup.

Named devices

Give a kinetic device a unique name with the Peripheral Configurator, then acquire it over a connected cable:

import create.kinetics.RotationController
import create.kinetics.Speedometer
import create.kinetics.Stressometer

fun main() {
    val input = Speedometer.named("input")
    val load = Stressometer.named("main_load")
    val controller = RotationController.named("governor")

    println(input.speed())
    println(load.capacity())
    println(controller.setTargetSpeed(128))
}

Discovery uses loaded chunks only and never forces a chunk to load. Breaking the cable path makes subsequent acquisitions unavailable. An already acquired handle remains tied to its exact block entity and never follows another device that later receives the same name.

Direct sides and devices

Sides are relative to the front of the computer, just like the redstone API:

import create.kinetics.RotationController
import create.kinetics.Speedometer
import create.kinetics.Stressometer
import compukter.peripheral.Side

fun main() {
    val input = Speedometer.at(Side.left)
    val load = Stressometer.at(Side.bottom)
    val controller = RotationController.at(Side.top)

    println(input.speed())
    println(load.stress())
    println(load.capacity())
    println(controller.setTargetSpeed(128))
}

front, back, left, right, top, and bottom inspect exactly one adjacent loaded block. They never scan the world or force a chunk to load. The requested block must be the matching Create block entity:

Accessor Adjacent Create device Operations
speedometer() Speedometer speed(): Float, awaitSpeedChange(): Float
stressometer() Stressometer stress(): Float, capacity(): Float, awaitChange(): Unit
rotationController() Rotation Speed Controller targetSpeed(): Int, setTargetSpeed(Int): Int

Speed, stress, and capacity retain Create’s Float values without integer rounding. Speeds are signed. A rotation controller applies Create’s own configured bounds, and setTargetSpeed returns the value that was actually accepted. If Create exposes NaN, positive or negative infinity, or signed zero, the same binary32 value reaches Guest Kotlin; the integration does not sanitize, widen, or convert it to fixed point. Change waits compare the observed binary32 value, including the distinction between positive and negative zero.

awaitSpeedChange() suspends until the observed speed changes and returns the new value. awaitChange() suspends until either stress or capacity changes. These waits do not busy-poll in Guest code.

Lifetime and limits

A device accessor creates a handle for that exact acquired block entity. Replacing the block invalidates the old handle; it never silently reconnects to the replacement. Missing, mismatched, unloaded, removed, or stale devices fail the Guest operation deterministically, and the terminal process diagnostic identifies which condition prevented the operation.

Each running computer may retain the shared limit of 1,024 typed peripheral handles and at most 64 pending Create waits. Host requests and completions cross the same bounded asynchronous actor path as other world-facing computer operations and execute on the server thread where Minecraft and Create state may safely be accessed.

Programmable actuators

The Create addon adds Programmable Mechanical Pump (compukters_create:programmable_pump) and Programmable Clutch (compukters_create:programmable_clutch). Craft either with its ordinary Create block and one Compukters Redstone Port. They appear together in the existing Compukters creative tab, after base-mod items. Addon groups stay together in stable addon-id order; installing another addon does not add a creative tab.

Only these programmable variants support the actuator API. Name and connect them with the Peripheral Configurator, then use the same typed discovery as other devices:

import create.actuators.Pump
import create.actuators.Clutch

fun main() {
    val fuel = Pump.named("fuel")
    val load = Clutch.named("load")
    fuel.setReversed(true)
    load.setConnected(true)
    println(fuel.reversed())
    println(load.connected())
    readln()
    load.setConnected(false)
}

Pump.setReversed(Boolean): Boolean reverses the actual fluid-flow direction without reversing the kinetic input. Calling it again with the same value does not flip the pump again. reversed() reports the selected direction, relative to its placement; wrench reversal updates this flag too. The direction survives program exit and world reload. Changing its direction requires rotation and a valid pipe route before fluid can move.

Clutch.setConnected(Boolean): Boolean engages or disengages the kinetic output, and connected() reads its state. It ignores redstone. A newly placed clutch is disengaged. It also disengages after program exit, Ctrl+C, loss of peripheral connectivity, unloading or world reload. Ownership is transient and is never restored from saved data. An expired handle cannot engage a replacement block. Keep the controlling program running while the load is connected. Both setters return the resulting state. Create’s kinetic stress rules still apply.