promotional bannermobile promotional banner

MALAHIT Peripherals

Integrates CC: Tweaked with Synaxis through non-blocking peripherals and adds a radar, a chunk loader, a ballast block, a peripheral hub and a telemetry API for computer-controlled Sable constructions.

Malachite Peripherals

Malachite Peripherals is a NeoForge mod for Minecraft 1.21.1 that connects computer-controlled machines to the physics of Sable constructions. It provides a non-blocking CC: Tweaked bridge for Synaxis devices, a global telemetry API, a radar, a peripheral hub, a ballast block with configurable mass and a chunk loader for flying constructions.

The mod is intended for players who build aircraft, missiles, turrets and other vehicles and control them with Lua programs, and for server operators who need such vehicles to remain loaded and to behave predictably.

Contents

Features

  • Synaxis bridge. Synaxis flaps, jet thrusters, turret drive motors and kinetic resistors become CC: Tweaked peripherals. Every setter returns immediately, so a control program can command all devices of a vehicle within a single loop iteration instead of waiting one game tick per call. Turret targets, torques and locks are written directly to the thread-safe Synaxis control ports and take effect without delay.
  • Telemetry API. Every computer receives a global telemetry table that reports the position, linear and angular velocity, orientation, mass, centre of mass and inertia tensor of the Sable construction on which the computer is located. No block is required, and any number of vehicles can read their own state simultaneously.
  • Radar. A block that detects Sable constructions and Create contraptions within a configurable range, height and field of view, reports each contact with its position, velocity and size, and notifies attached computers after every update.
  • Peripheral hub. A block that relays up to 32 linked peripherals to an adjacent computer through the standard CC: Tweaked wired-modem protocol. Links are stored relative to the hub, so a construction copied with a schematic keeps every link and every peripheral name. The hub also reports the position and orientation of each linked device in the construction's local frame, which allows flight control programs to compute lever arms directly.
  • Ballast. An invisible block with a mass between 0.01 and 100000 Sable units, set through an in-game screen or from a computer. The mass contributes to the mass, centre of mass and inertia tensor of the construction, survives saves, blueprints and sub-level assembly, and breaking the block never destroys the construction.
  • Chunk loader. A block that keeps a flying Sable construction loaded regardless of its distance from players and, optionally, a ring of world chunks around it.

Dependencies

The mod requires only Minecraft 1.21.1 and NeoForge 21.1.248 or later. All other mods are optional; each one enables a set of features. The blocks are always registered, so worlds remain valid when an optional mod is added or removed; a block whose integration is absent remains in place but has no effect.

Mod Version Enables
CC: Tweaked 1.115 or later All peripherals, the telemetry API, the peripheral hub and the Hub Linker
Synaxis 1.4.3 or later Peripherals for Synaxis flaps, jet thrusters, dynamic motors and kinetic resistors (together with CC: Tweaked)
Sable any The chunk loader, ballast mass, telemetry data and radar detection of Sable constructions
Create any Radar detection of Create contraptions

The following combinations are useful without the other mods:

  • Sable alone: the ballast block (with its in-game mass screen) and the chunk loader.
  • CC: Tweaked alone: the peripheral hub.
  • CC: Tweaked with Create: the radar, detecting Create contraptions.

When the game starts, the log contains one line for every absent integration, stating which features are disabled.

The mod must be installed on both the client and the server.

Blocks and items

The mod does not currently define crafting recipes. The blocks are available in the Functional Blocks creative tab, the Hub Linker in the Tools and Utilities creative tab, and all of them through the /give command.

Block or item Identifier Purpose
Radar malperiph:radar Detects moving constructions; peripheral type radar. Its front face indicates the axis of the field of view.
Peripheral Hub malperiph:peripheral_hub Relays linked peripherals to an adjacent computer; peripheral types malahit_hub and peripheral_hub.
Hub Linker malperiph:hub_linker Creates and removes hub links.
Ballast malperiph:ballast Adds a configurable mass to a Sable construction; peripheral type ballast.
Chunk Loader malperiph:chunk_loader Keeps a Sable construction and, optionally, the surrounding world chunks loaded.

Synaxis bridge

The bridge attaches peripherals to existing Synaxis blocks; it adds no blocks of its own. Place a computer, or a wired modem connected to a computer, against a Synaxis device, or link the device to a peripheral hub.

In the tables below, Immediate methods return without waiting for a tick. Queued methods return immediately and are applied on the next server tick in the order in which they were called. Main thread methods wait for the next server tick and should not be called in a fast control loop.

Compact flap (compact_flap)

Method Execution Description
setAngle(degrees) Queued Deflection angle of the flap.
setTilt(degrees) Queued Tilt of the flap about its tilt axis.
setLift(k) Queued Lift coefficient, as displayed in the Synaxis interface. Raises an error for a negative or non-finite value.
setDrag(k) Queued Drag coefficient, as displayed in the Synaxis interface. Raises an error for a negative or non-finite value.
getLift(), getDrag() Immediate Current coefficients. The value may lag one tick behind a setter that has just been queued.
getAngle(), getTilt() Main thread Current angle and tilt in degrees.

A newly placed flap has a lift coefficient of 150 and a drag coefficient of 30. Coefficients set from a computer are saved with the block and appear in the Synaxis interface.

Jet thruster (synaxis_jet)

Method Execution Description
setThrust(newtons) Queued Thrust.
setHorizontalAngle(radians), setVerticalAngle(radians) Queued Thrust vectoring angles. They take effect only when the thruster has a Synaxis jet rudder and are limited to ±π/2 by Synaxis.
getThrust(), getHorizontalAngle(), getVerticalAngle() Main thread Current values.

Dynamic motors (synaxis_revolute_motor, synaxis_joint_motor)

The Synaxis revolute motor (horizontal axis, for example turret traverse) and joint motor (vertical axis, for example gun elevation) share one interface. The peripheral types differ, so a program can locate each axis with peripheral.find.

Method Execution Description
setTarget(value) Immediate Controller target: an angle in radians in angle mode, or an angular velocity in rad/s in speed mode.
setTorque(newtonMetres) Immediate Feed-forward torque added to the controller output in the force backend.
setLock(locked) Immediate Manual lock request; holds the current angle.
getKind() Immediate "revolute" or "joint".
getAngle(), getSpeed() Immediate Current angle (rad) and angular velocity (rad/s); suitable for polling every tick.
getAppliedTorque() Immediate Torque applied by the motor during the last tick (N·m).
getTarget(), getTorque() Immediate Current target and feed-forward torque.
isConnected(), isLocked(), isAutoLocked() Immediate Assembly and lock state.
getMode() Immediate true in angle mode, false in speed mode.
getDriveBackend() Immediate "force" or "joint".
getStatus() Immediate Table {kind, angle, speed, appliedTorque, target, torque, connected, locked, autoLocked, angleMode, driveBackend}.
setMode(angleMode) Queued Selects angle mode (true) or speed mode (false); resets the controllers.
setDriveBackend(name) Queued "force" (PID torque) or "joint" (physics engine joint motor); resets the gains to the recommended profile.
setGainP(p), setGainI(i), setGainD(d), setPID(p, i, d) Queued PID gains of the force backend.
setJointPD(p, d) Queued Gains of the joint backend.
setGravityCompensation(enabled), setJointGravityCompensation(enabled) Queued Gravity compensation in the force and joint backends.
setCounterTorque(enabled) Queued Reaction torque on the motor's own body in the force backend (enabled by default).
setJointContacts(enabled) Queued Collisions between the bodies connected by the joint.
setAutoLock(enabled) Queued Automatic lock at the target angle or at a zero target speed.
setAutoLockThresholds(enter, exit, speed) Queued Automatic lock thresholds: entry angle (rad), exit angle (rad), target speed (rad/s).
setJointLimit(min, max[, acrossWrap]) Queued Angle limit of the joint backend, in radians within [-π, π]; acrossWrap permits an arc across ±π.
clearJointLimit() Queued Removes the angle limit.
getGainP(), getGainI(), getGainD(), getGravityCompensation() Main thread Current configuration.
getJointLimit() Main thread Table {enabled, min, max, acrossWrap, angleOffset}.
collect() Main thread The complete configuration and state in one table.
local azimuth = peripheral.find("synaxis_revolute_motor")
local elevation = peripheral.find("synaxis_joint_motor")

azimuth.setPID(4.0, 0.1, 0.5)
elevation.setPID(4.0, 0.1, 0.5)

while true do
  azimuth.setTarget(math.rad(90))
  elevation.setTarget(math.rad(15))
  print(azimuth.getAngle(), elevation.getAngle())
  sleep(0.05)
end

Kinetic resistor (synaxis_kinetic_resistor)

The kinetic resistor is a transmission on Create shafts: output speed = input speed × ratio.

Method Execution Description
setRatio(ratio) Immediate Gear ratio. Zero stops the output shaft; a negative value reverses it. Synaxis 1.5.0 clamps the ratio to [-2, 2] and replaces a non-finite value with 1. Applied on the next tick.
getRatio() Immediate Applied ratio.
getSourceSpeed(), getOutputSpeed() Immediate Input and output shaft speeds in RPM.
getStatus() Immediate Table {ratio, sourceSpeed, outputSpeed}.

Telemetry API

Every computer has a global telemetry table, in the same way as os or redstone. It describes the Sable construction on which the computer is located. All methods are immediate: the data is refreshed once per tick and read without waiting.

Method Returns
isValid() true if the computer is on a Sable construction and the data is valid.
getId() Stable UUID of the construction, or an empty string.
getName() Name of the construction.
getPosition() {x, y, z}: world position of the computer itself.
getVelocity() {x, y, z}: linear velocity of the construction's centre of mass, world axes, blocks per second.
getSpeed() Magnitude of the linear velocity.
getAngularVelocity() {x, y, z}: angular velocity, world axes, rad/s. The direction is the rotation axis and the magnitude is the rotation rate.
getOrientation() {x, y, z, w}: quaternion that rotates the construction's local frame into world axes.
getSize() {x, y, z}: extent of the construction's bounding box.
getMass(), getInverseMass() Mass in Sable units (an ordinary block has a mass of 1) and its inverse (0 if not available).
getCenterOfMass() {x, y, z}: centre of mass in the construction's local frame.
getInertiaTensor(), getInverseInertiaTensor() 3 × 3 matrix as t[row][column], about the centre of mass, local axes.
getMassProperties() {mass, inverseMass, centerOfMass, inertiaTensor, inverseInertiaTensor}.
getTelemetry() {valid, id, name, position, velocity, angularVelocity, orientation, mass, centerOfMass, size}.

If the computer is not on a Sable construction, or Sable is not installed, isValid() returns false, getPosition() returns the position of the computer block and the remaining methods return neutral values: zero vectors, zero mass, the identity orientation and identity tensors.

if telemetry.isValid() then
  local p = telemetry.getPosition()
  print(("altitude %.0f  speed %.1f  mass %.1f"):format(p.y, telemetry.getSpeed(), telemetry.getMass()))
end

Radar

The radar detects Sable constructions (when Sable is installed) and Create contraptions (when Create is installed). It uses flat lists of active constructions rather than a spatial scan, so its range and height are limited only by its settings. The construction that carries the radar is excluded from its contacts. All methods except getPosition are immediate.

Method Description
getContacts(), scan() List of contacts from the last update, sorted by distance.
getContactCount() Number of contacts from the last update.
getPosition() {x, y, z}: world position of the radar. Runs on the main thread.
getConfig() {range, height, angle, freq, type, sideBound}.
getRange(), setRange(blocks) Horizontal detection range, 1 to 100000 (default 20000).
getHeight(), setHeight(blocks) Vertical detection limit above and below the radar, 1 to 100000 (default 20000).
getAngle(), setAngle(degrees) Full aperture of the detection cone, 1 to 360 (default 360).
getFrequency(), setFrequency(ticks) Update period, 1 to 200 ticks (default 5).
getScanType(), setScanType(type) "all" (default), "sable" or "contraption".
isSideBound(), setSideBound(enabled) Directional mode: when enabled and the angle is below 360, the cone is centred on the radar's front face.
setConfig(table) Sets several parameters at once, for example setConfig{range = 1500, angle = 120, sideBound = true}.

Values outside the permitted ranges are clamped. The settings are stored in the block and survive world reloads.

Each contact is a table with the fields kind ("sable" or "contraption"), id, name, world position x, y, z (centre of the bounding box), velocity vx, vy, vz (blocks per second), bounding-box size sx, sy, sz and distance dist from the radar.

After every update each attached computer receives the event radar_contacts with the radar's attachment name and the number of contacts. A single radar may serve several computers.

local radar = peripheral.find("radar")
radar.setConfig{range = 1500, angle = 120, sideBound = true}

while true do
  os.pullEvent("radar_contacts")
  for _, c in ipairs(radar.getContacts()) do
    print(("%s %s  %.0f m"):format(c.kind, c.name, c.dist))
  end
end

Peripheral hub

The peripheral hub is placed against a computer. It exposes the additional peripheral type peripheral_hub, which CC: Tweaked treats in the same way as a wired modem: peripheral.getNames, peripheral.find, peripheral.wrap, peripheral.getType, peripheral.hasType, peripheral.getMethods, peripheral.call and rednet.open work with linked devices as if they were attached to the computer directly. No changes to programs are required.

Linking

Links are created with the Hub Linker.

Action Result
Right-click a hub Selects the hub.
Right-click a peripheral Links the peripheral to the selected hub, or unlinks it if it is already linked.
Shift + right-click a hub Lists the hub's links in chat.
Shift + right-click the air Clears the selection.

A hub supports up to 32 links, each within 16 blocks of the hub on every axis. Other hubs and wired modems cannot be linked. Each linked device receives the name <type>_<n>, where n is the lowest free number within the hub.

Links are stored in the hub block as offsets in the hub's own frame. A construction copied with a schematic or a structure block, rotated or mirrored, therefore keeps every link and every name, and Sable sub-level assembly does not affect them. The hub re-resolves its links every 10 ticks and raises the peripheral and peripheral_detach events when the set of available devices changes. A device that remains the same object keeps its wrapper, so the rednet channels of a linked modem are not closed.

Methods

In addition to the wired-modem protocol methods (getNamesRemote, isPresentRemote, getTypeRemote, hasTypeRemote, getMethodsRemote, callRemote), the hub provides the following immediate methods:

Method Description
getLinks() All links, including offline ones: {name, type, block, online, x, y, z, side}. The offsets are in the hub's frame.
getGeometry([name]) Geometry of all links, or of the named link (nil if it does not exist).
getPosition() {x, y, z}: centre of the hub in the construction's local frame.
refresh() Re-resolves the links on the next tick.

Each geometry record contains:

Field Description
name, type, block, online Link name, peripheral type, block identifier and availability.
pos {x, y, z}: centre of the device block in the construction's local frame.
offset {x, y, z}: pos minus the centre of the hub, local axes.
facing, dir Orientation of the block: side name and unit vector, if the block has an orientation.
front, left Basis vectors of an online Synaxis device. For a flap, front is the angle axis and left is the tilt axis; for a jet thruster, front is the thrust direction.
normal Compact flap only: plate normal at zero angle and tilt.

The geometry is refreshed every 10 ticks.

local hub = peripheral.find("malahit_hub")
local com = telemetry.getCenterOfMass()

for _, g in ipairs(hub.getGeometry()) do
  local r = {x = g.pos.x - com.x, y = g.pos.y - com.y, z = g.pos.z - com.z}
  print(g.name, r.x, r.y, r.z)
end

Ballast

The ballast block is invisible and has a configurable mass between 0.01 and 100000 Sable units (default 1; an ordinary block has a mass of 1). With Sable installed, the mass contributes to the mass, centre of mass and inertia tensor of the construction that contains the block.

  • Visibility. A marker is displayed over ballast blocks while a ballast item is held. The block can be targeted and broken only while a ballast item or a Hub Linker is held; otherwise it obstructs neither view nor clicks. Its collision shape is always a full block.
  • Setting the mass. Right-click a ballast block with a ballast item to open the mass screen; Enter or Done applies the value. Shift + right-click places a block adjacent to the ballast as usual.
  • Persistence. The mass is stored in the block and is preserved through world saves, Sable blueprints and sub-level assembly. A broken ballast block drops an item that retains its mass, and the mass is shown in the item tooltip.
  • Safety. Breaking a ballast block removes exactly the mass that it contributed, so the construction is never destroyed.
Method Description
setMass(mass) Sets the mass. Raises an error for a value outside [0.01, 100000]. Applied on the next tick.
getMass() Configured mass.
getAppliedMass() Mass currently accounted by Sable; equals getMass() one tick after a change, and 1 while the block is not on a construction.
getMassRange() {min = 0.01, max = 100000, default = 1}.

All ballast methods are immediate.

Chunk loader

The chunk loader has no interface and no in-game settings. When placed on a Sable construction, it keeps the construction loaded regardless of the distance from players, including after a server restart. Each chunk loader uses its own ticket, so removing one loader does not unload other constructions.

It can additionally keep a ring of ordinary world chunks loaded around the construction's current position, so that terrain beneath a distant vehicle remains loaded. The ring is configured in config/malperiph-common.toml (see Configuration). The tickets are released when the block is broken or destroyed.

Coordinate frames and units

  • World frame. telemetry.getPosition(), getVelocity(), getAngularVelocity(), radar contacts and radar.getPosition() use world coordinates and world axes.
  • Local frame. telemetry.getCenterOfMass(), telemetry.getInertiaTensor(), hub.getGeometry() and hub.getPosition() use the local frame of the Sable construction (its plot coordinates). A lever arm is therefore pos - centerOfMass, and a local vector is converted into world axes as v_world = q · v_local, where q = telemetry.getOrientation().
  • Units. Distances in blocks, velocities in blocks per second, angles in radians, angular velocities in rad/s, forces in newtons and torques in N·m. The flap methods use degrees, in accordance with the Synaxis interface. Masses are in Sable units, where an ordinary block has a mass of 1.

Threading model

CC: Tweaked runs Lua programs on its own threads. Methods that must touch the world are usually executed on the server thread, which costs one tick per call. The mod avoids this cost:

  • Device setters are placed in a queue and applied once per tick on the server thread, in call order.
  • Turret targets, torques, locks and resistor ratios are written through the thread-safe ports that Synaxis itself uses from its physics thread.
  • Telemetry, radar contacts and hub geometry are assembled on the server thread once per tick or per update and published as immutable snapshots, which Lua reads without waiting.

Only the methods marked "Main thread" above wait for a tick.

Configuration

config/malperiph-common.toml, section chunk_loader:

Key Default Range Description
worldChunks true Whether world chunks around the construction are kept loaded. false keeps only the construction itself.
surroundingChunkRadius 0 0 to 8 Ring radius in chunks: 0 is the chunk under the construction, 1 is 3 × 3, 2 is 5 × 5.
positionCheckIntervalTicks 2 1 to 20 How often a moving loader checks whether it has entered another chunk.
chunkTicketChangesPerTick 4 1 to 64 Maximum number of chunk tickets a loader may add or remove per tick.
newChunksPerTick 1 1 to 8 Of those, the maximum number of previously unloaded chunks per tick (terrain generation).

For small, fast vehicles a radius of 0 or 1 is recommended.

Known limitations

  • The ring of world chunks cannot keep pace with constructions that travel faster than approximately one chunk per tick. A larger radius increases the cost without extending coverage ahead of the construction; the construction itself remains loaded in any case.
  • Hub links are stored in the hub block and are lost if the hub is broken and placed again. A hub cannot be rotated in place.
  • Links are identified by their offset from the hub. A linked device that is moved, even by one block, must be linked again.
  • The radar does not check line of sight. A construction behind terrain is reported if it is within the detection volume.

Notes for modpack developers

  • The Synaxis bridge accesses Synaxis through block entity identifiers and reflection. When the game starts, the log reports how many Synaxis device types were found. If a Synaxis update renames a device or a method, the affected peripheral stops responding and a warning prefixed with [malperiph] is written to the log; other features are unaffected.
  • The ballast mass is applied to Sable through a mixin, which is loaded only when Sable is installed.

Credits

Malachite Peripherals integrates with Synaxis by Rew1nd, CC: Tweaked by SquidDev and contributors, Create by simibubi and the Create team, and Sable by RyanHCode. It contains no code or assets of these mods.

License

Copyright (c) 2026 Graide (Malachite_Project). All Rights Reserved.

The mod may be used in single-player worlds and on servers, shown in videos and streams, and included in modpacks that obtain the unmodified file from an official page of the mod. Programs that use the mod's API may be published under any licence. See LICENSE.txt for the full terms.

MALAHIT Peripherals Team

profile avatar
Owner
  • 1
    Followers
  • 6
    Projects
  • 515
    Downloads

More from GraideView all

  • Sable Drydock project image

    Sable Drydock

    Resizes Sable sub-levels with real physics and adds a sub-level manager with a 3D view, bulk actions and an assembly dock for welding, hinging and placing sub-levels and blueprints.

    • 82
    • October 3, 2026
  • Tracks+ Fix project image

    Tracks+ Fix

    Performance addon for Create: Tracks+ (by ChiyahaRe, fork of Create: Tracks by qwxon). Caches track terrain-probe data once per tick, cutting server lag and memory churn on tracked vehicles. No content changes.

    • 28
    • October 3, 2026
  • MALAHIT Monitors project image

    MALAHIT Monitors

    Flat multi-block wall monitors up to 8×6. CC:Tweaked peripheral with dense UTF-8 text, transparent background and 128×128-per-block pixel graphics. Shows Vista camera feeds with computer-drawn overlays.

    • 56
    • October 2, 2026
  • Vista Thermal Camera project image

    Vista Thermal Camera

    The mod adds a thermal vision mode to the Vista camera, controllable via CC:T.

    • 223
    • September 29, 2026
  • Sable Drydock project image

    Sable Drydock

    Resizes Sable sub-levels with real physics and adds a sub-level manager with a 3D view, bulk actions and an assembly dock for welding, hinging and placing sub-levels and blueprints.

    • 82
    • October 3, 2026
  • Tracks+ Fix project image

    Tracks+ Fix

    Performance addon for Create: Tracks+ (by ChiyahaRe, fork of Create: Tracks by qwxon). Caches track terrain-probe data once per tick, cutting server lag and memory churn on tracked vehicles. No content changes.

    • 28
    • October 3, 2026
  • MALAHIT Monitors project image

    MALAHIT Monitors

    Flat multi-block wall monitors up to 8×6. CC:Tweaked peripheral with dense UTF-8 text, transparent background and 128×128-per-block pixel graphics. Shows Vista camera feeds with computer-drawn overlays.

    • 56
    • October 2, 2026
  • Vista Thermal Camera project image

    Vista Thermal Camera

    The mod adds a thermal vision mode to the Vista camera, controllable via CC:T.

    • 223
    • September 29, 2026