πŸ’‘ How to use this page
This is a lookup reference, not a read-through. Use Ctrl+F or the table of contents to jump to a class. Most addons only touch 5–6 classes: SpcNodeSchema, SpcPortSpec, ISpcCompiledNode, ISpcExecutionContext, SpcSignalValue, SpcNodeRegistry.

Jump to class

SpcApi

api public final class SpcApi

Version constants and mod identifiers.

FieldTypeValueDescription
API_VERSIONint3Incremented on any breaking API change
MOD_IDString"storedprogramcontrols"Main SPC mod identifier
CORE_MOD_IDString"spc_core"API mod identifier β€” depend on this in your mods.toml

SpcNodeSchema

api.node public record SpcNodeSchema

Declares a function block node type. Immutable after construction.

Constructors

new SpcNodeSchema(String typeId, SpcExecutionPhase phase, List<SpcPortSpec> ports, List<SpcParameterSpec> parameters, boolean requiresDisplay)
new SpcNodeSchema(String typeId, SpcExecutionPhase phase, List<SpcPortSpec> ports, List<SpcParameterSpec> parameters, boolean requiresDisplay, String displayName, String shortLabel, String description) // v1.1.0+

Record components

ComponentTypeDescription
typeIdStringGlobally unique node type ID (e.g., "mymod:sensor")
phaseSpcExecutionPhaseExecution phase
portsList<SpcPortSpec>Port declarations (immutable copy)
parametersList<SpcParameterSpec>Parameter declarations (immutable copy)
requiresDisplaybooleanWhether this node needs a display block
displayNameString Nullable β€” human-readable name for the palette (e.g., "Rotation Input"). Falls back to category + typeId.
shortLabelString Nullable β€” 1-3 character icon text on the block in the diagram (e.g., "RI"). Falls back to first 3 chars of typeId.
descriptionString Nullable β€” tooltip description text (e.g., "Reads rotation data"). Falls back to "N inputs, M outputs".

Methods

MethodReturnsDescription
findPort(String portId)Optional<SpcPortSpec>Find a port by its ID
findParameter(String parameterId)Optional<SpcParameterSpec>Find a parameter by its ID
portsById()Map<String, SpcPortSpec>All ports indexed by port ID
parametersById()Map<String, SpcParameterSpec>All parameters indexed by ID

SpcPortSpec

api.node public record SpcPortSpec

Declares a single input or output port on a node type.

Constructors

new SpcPortSpec(String portId, SpcPortDirection direction, SpcSignalType signalType, boolean required, String signalDomain)
new SpcPortSpec(String portId, SpcPortDirection direction, SpcSignalType signalType, boolean required) // signalDomain defaults to null (universal)
ComponentTypeDescription
portIdStringUnique within the node (e.g., "I1", "Q")
directionSpcPortDirectionINPUT or OUTPUT
signalTypeSpcSignalTypeData type: DIGITAL, INTEGER, etc.
requiredbooleanWhether a connection is required for valid programs
signalDomainString Optional domain tag (e.g., "rotation", "fluid"). null = universal compatibility.

Methods

MethodReturnsDescription
isDomainCompatible(SpcPortSpec other)boolean True if either domain is null or both are equal

SpcPortDirection

api.node public enum SpcPortDirection

ValueSerializedDescription
INPUT"input"Port receives data from upstream node
OUTPUT"output"Port sends data to downstream nodes

Methods: getSerializedName(), fromSerializedName(String)


SpcParameterSpec

api.node public record SpcParameterSpec

Declares a user-configurable parameter. Set in the editor, constant during execution.

Constructor

new SpcParameterSpec(String parameterId, SpcParameterValueType valueType, boolean required)
ComponentTypeDescription
parameterIdStringUnique within the node (e.g., "radius")
valueTypeSpcParameterValueTypeBOOLEAN, INTEGER, DECIMAL, or TEXT
requiredbooleanMust be set before running

SpcParameterValueType

api.node public enum SpcParameterValueType

ValueSerializedJava type
BOOLEAN"boolean"boolean
INTEGER"integer"int
DECIMAL"decimal"double
TEXT"text"String

ISpcCompiledNode

api.node public interface ISpcCompiledNode

A compiled, executable instance of a function block node. Created by a factory, executed every tick.

MethodReturnsDescription
nodeId()UUIDUnique ID of this node instance
typeId()StringNode type identifier (matches schema)
phase()SpcExecutionPhaseWhich phase this node executes in
execute(context, state)voidRun this node for one tick
ℹ️ Statelessness contract
Implementations must be stateless between ticks. All persistent data must go through ISpcRuntimeState persistent slots.

ISpcNodeFactory

api.node public interface ISpcNodeFactory

Factory that compiles a node definition into an executable instance.

MethodReturnsDescription
create(NodeCompilationContext context)ISpcCompiledNodeCreate a compiled node from the compilation context

Can be implemented as a lambda:

ISpcNodeFactory factory = ctx -> new MyNode(ctx.nodeId(), ctx.outputAddress("Q"));

NodeCompilationContext

api.node public record ISpcNodeFactory.NodeCompilationContext

Compilation context passed to factories. Contains resolved addresses and parameter values.

Record components

ComponentTypeDescription
nodeIdUUIDUnique instance ID
typeIdStringSchema type ID
inputAddressesMap<String, SpcSignalAddress>Resolved input port β†’ source signal addresses
outputAddressesMap<String, SpcSignalAddress>Resolved output port β†’ signal addresses
parameterValuesMap<String, String>Raw parameter values from the editor
invertedInputsMap<String, Boolean>Which inputs have negation bubbles

Helper methods

MethodReturnsDescription
inputAddress(String portId)SpcSignalAddressAddress of an input port's source (null if unconnected)
outputAddress(String portId)SpcSignalAddressAddress for an output port (always non-null)
isInverted(String portId)booleanWhether input has a negation bubble
stringParameter(String id, String def)StringString parameter with default
intParameter(String id, int def)intInteger parameter with default (parse-safe)
longParameter(String id, long def)longLong parameter with default (parse-safe)
doubleParameter(String id, double def)doubleDouble parameter with default (parse-safe)
booleanParameter(String id, boolean def)booleanBoolean parameter with default
numberedInputAddresses(String prefix, int count)List<SpcSignalAddress>Collect prefix1, prefix2, …, prefixN addresses

ISpcExecutionContext

api.execution public interface ISpcExecutionContext

World interaction interface passed to every node's execute(). All methods have safe defaults.

Digital I/O

MethodReturnsDescription
readDigitalInput(int channel)booleanRead a digital input channel
applyDigitalOutputs(Map<Integer, Boolean>)voidApply digital output states

Analog I/O

MethodReturnsDefault
readAnalogInput(int channel)int0
applyAnalogOutputs(Map<Integer, Integer>)voidno-op

Forge Energy (FE) I/O

MethodReturnsDefault
readFeInput(int channel)int0
applyFeOutputs(Map<Integer, Integer>)voidno-op

Virtual Signals

MethodReturnsDefault
readVirtualDigital(String key)booleanfalse
readVirtualInteger(String key)int0
readVirtualDecimal(String key)double0.0
writeVirtualDigital(String key, boolean v)voidno-op
writeVirtualInteger(String key, int v)voidno-op
writeVirtualDecimal(String key, double v)voidno-op

Time

MethodReturnsDefault
worldTimeTicks()long0
isDaytime()booleanComputed from worldTimeTicks

Display

MethodDescription
publishDisplayMessage(UUID nodeId, String msg, boolean active)Show message on the machine's display
publishExternalDisplayMessage(String ip, UUID nodeId, String msg, boolean active)Send to an external display at the given IP

World Sensors

MethodReturnsDescription
isRaining()booleanWeather status
isThundering()booleanStorm status
getLightLevel(int x, int y, int z)intLight at offset from machine (0–15)
getPlayerDistance()intDistance to nearest player (MAX_VALUE if none)
countEntitiesInRadius(int radius, String type)intCount entities of type within radius
isBlockAt(int x, int y, int z, String blockId)booleanBlock check at offset
getContainerFillLevel(int x, int y, int z)intContainer comparator level (0–15)
getBiomeId()StringBiome at machine position
getMoonPhase()intMoon phase (0–7)

Effects

MethodDescription
playNote(int instrument, int pitch)Play a note block sound
emitParticles(String type, int count)Spawn particles
launchSignalFlare(int color)Launch a colored signal flare
sendChatMessage(UUID nodeId, String sender, String msg)Send a chat message

Items

MethodReturnsDescription
readItemInputId(int channel, int slot)StringItem ID at channel/slot
readItemInputCount(int channel, int slot)intItem count at channel/slot
readInventoryFingerprint(int channel)longHash for change detection
applyItemOutputs(Map, Map)voidSet item outputs

Data Logging

MethodDescription
recordDataLog(UUID nodeId, Map<String, SpcSignalValue>)Log named values for the data recorder

Extensions

MethodReturnsDescription
getExtension(Class<T>)Optional<T>Retrieve a registered context extension

Custom Module I/O

MethodReturnsDefaultDescription
readCustomInput(String moduleTypeId, int channel)SpcSignalValueINTEGER_ZERORead from a custom multiblock module's input channel
applyCustomOutputs(String moduleTypeId, Map<Integer, SpcSignalValue>)voidno-opApply values to a custom module's output channels

ISpcExecutionContextExtension

api.execution public interface ISpcExecutionContextExtension

Base interface for addon execution context extensions.

MethodReturnsDescription
onTickStart(ServerLevel level, BlockPos machinePos)voidCalled once per machine per tick, before node execution. Default: no-op.

SpcExecutionPhase

api.execution public enum SpcExecutionPhase

ValueOrderPurpose
INPUT_READ1Sample physical and virtual inputs
LOGIC_EVALUATION2Combinational logic, math, comparisons
STATE_UPDATE3Timers, counters, memory elements
OUTPUT_APPLY4Write physical and virtual outputs

SpcSignalType

api.signal public enum SpcSignalType

ValueSerializedJava Type
DIGITAL"digital"boolean
INTEGER"integer"int
DECIMAL"decimal"double
TEXT"text"String
ITEM"item"String + int
ITEM_ID"item_id"String

Methods: getSerializedName(), fromSerializedName(String)


SpcSignalValue

api.signal public record SpcSignalValue

Runtime signal container carrying a typed value between nodes.

Record components

ComponentTypeDescription
typeSpcSignalTypeSignal type enum
digitalValuebooleanBoolean payload
integerValueintInteger payload
decimalValuedoubleDecimal payload
textValueStringText payload (never null)

Factory methods

MethodCreates
digital(boolean v)DIGITAL signal
integer(int v)INTEGER signal (also sets decimalValue)
decimal(double v)DECIMAL signal (also sets integerValue)
text(String v)TEXT signal
item(String itemId, int count)ITEM signal (ID + count)
itemId(String itemId)ITEM_ID signal

Conversion methods

MethodReturnsCross-type behavior
asDigital()booleanNon-zero/non-empty β†’ true
asInteger()intRounds decimals, parses text, bool→0/1
asDecimal()doubleParses text, bool→0.0/1.0
asText()StringNumbers→string, bool→"0"/"1", item→"id x count"
asItemId()StringExtracts textValue from ITEM/ITEM_ID/TEXT
asItemCount()intintegerValue from ITEM/INTEGER; bool→0/1

Static constants

DIGITAL_FALSE, DIGITAL_TRUE, INTEGER_ZERO, DECIMAL_ZERO, TEXT_EMPTY, ITEM_EMPTY, ITEM_ID_EMPTY


SpcSignalAddress

api.signal public record SpcSignalAddress

Identifies a specific port on a specific node instance. Used as keys in the signal bus.

ComponentTypeDescription
nodeIdUUIDNode instance ID
portIdStringPort identifier within the node

ISpcRuntimeState

api.state public interface ISpcRuntimeState

Mutable runtime state: signal bus + persistent storage + physical output channels.

Signal Bus

MethodReturnsDescription
setSignal(SpcSignalAddress, SpcSignalValue)voidWrite a signal to the bus
readDigitalSignal(SpcSignalAddress)booleanRead as boolean (false default)
readIntegerSignal(SpcSignalAddress)intRead as int (0 default)
readDecimalSignal(SpcSignalAddress)double Read as double (0.0 default)
readTextSignal(SpcSignalAddress)StringRead as text ("" default)
readSignalValue(SpcSignalAddress)SpcSignalValueRead raw value (ITEM_EMPTY default)

Physical Output Channels

MethodDescription
setDigitalOutput(int channel, boolean active)Set digital output channel
setAnalogOutput(int channel, int value)Set analog output channel (0–15)
setFeOutput(int channel, int amount)Set FE output channel

Persistent Slots

TypeGetSet (pending)
BooleangetBooleanSlot(UUID, String)setPendingBooleanSlot(UUID, String, boolean)
IntegergetIntegerSlot(UUID, String)setPendingIntegerSlot(UUID, String, int)
LonggetLongSlot(UUID, String)setPendingLongSlot(UUID, String, long)
DoublegetDoubleSlot(UUID, String)setPendingDoubleSlot(UUID, String, double)
TextgetTextSlot(UUID, String)setPendingTextSlot(UUID, String, String)

Markers (named global variables)

TypeGetSet (pending)
BooleangetMarkerValue(String)setPendingMarkerValue(String, boolean)
IntegergetAnalogMarkerValue(String)setPendingAnalogMarkerValue(String, int)
StringgetStringMarkerValue(String)setPendingStringMarkerValue(String, String)

Latch / Flip-Flop State

MethodReturns
getLatchState(UUID nodeId)boolean
setPendingLatchState(UUID nodeId, boolean)void

Delay Counters

MethodReturns
getOnDelayCounter(UUID nodeId)int
setPendingOnDelayCounter(UUID nodeId, int)void

SpcNodeCategory

api.category public record SpcNodeCategory

Groups nodes in the editor palette sidebar.

Constructors

new SpcNodeCategory(String categoryId, String displayName, int sortOrder, String iconTexture)
new SpcNodeCategory(String categoryId, String displayName, int sortOrder) // iconTexture defaults to null
new SpcNodeCategory(String categoryId, String displayName) // sortOrder defaults to 5000, iconTexture to null
ComponentTypeDescription
categoryIdStringUnique ID (e.g., "mymod:sensors"). Namespace it!
displayNameStringShown in the palette sidebar header
sortOrderintLower = higher in list. Built-in: 0–1000. Use 5000+ for addons.
iconTextureString Optional resource location for a category icon (e.g., "mymod:textures/gui/sensors.png"). null = no icon.

Methods

MethodReturnsDescription
hasIcon()boolean Returns true if iconTexture is non-null and non-empty

SpcNodeRegistry

api.registry public final class SpcNodeRegistry

Central registry for addon node types. Thread-safe. Freezes after mod setup.

MethodReturnsDescription
register(SpcNodeSchema, ISpcNodeFactory, SpcNodeCategory)voidRegister a node type with default brass colors.
register(SpcNodeSchema, ISpcNodeFactory, SpcNodeCategory, SpcNodeColors)voidRegister a node type with custom editor colors.
find(String typeId)Optional<SpcNodeRegistration>Look up a registered node by type ID.
all()Map<String, SpcNodeRegistration>Unmodifiable view of all registrations.
isFrozen()booleanTrue if registry is frozen.
freeze()voidInternal β€” called by SPC, not by addons.

SpcNodeRegistration

api.registry public record SpcNodeRegistration

Bundled registration: schema + factory + category + optional colors.

ComponentType
schemaSpcNodeSchema
factoryISpcNodeFactory
categorySpcNodeCategory
colorsSpcNodeColors (nullable)
MethodReturnsDescription
effectiveColors()SpcNodeColorsReturns custom colors or SpcNodeColors.DEFAULT.

SpcNodeColors

api.style public record SpcNodeColors

Custom ARGB colors for rendering a function block node in the programming editor.

FieldTypeDefaultDescription
fillint0xFFF1D789Body background fill
strokeint0xFF3A2C12Border outline
textint0xFF2A2010Symbol text inside the body
labelTextint0xFFF3E8C4Label text above the node
activeFillint0xFFF7E7A7Fill when active in simulation
StaticReturnsDescription
DEFAULTSpcNodeColorsThe built-in brass palette.
of(int fill, int stroke)SpcNodeColorsAuto-derives text and active colors from fill/stroke.
fromAccent(int accent)SpcNodeColorsDerives all 5 colors from a single accent color.

SpcProgramBlockStyle

api.style public record SpcProgramBlockStyle

Defines the tint colors for a programming block variant in the world.

FieldTypeDefaultDescription
primaryTintint0xFFD4A84BPrimary body tint for the block model
secondaryTintint0xFF8B7234Secondary accent tint for trim/details
emissiveTintint0xFF66BB6ALED/indicator light color
StaticReturnsDescription
DEFAULTSpcProgramBlockStyleThe built-in brass style.
fromAccent(int accent)SpcProgramBlockStyleDerives primary + secondary from one color (keeps green LED).

SpcProgramBlockCategory

api.style public record SpcProgramBlockCategory

A programming block category that addons register to provide new themed block variants.

FieldTypeDescription
categoryIdStringUnique ID in namespaced format: "mymod:advanced_programmer"
displayNameStringHuman-readable name for tooltips and creative menu
styleSpcProgramBlockStyleNullable β€” uses brass default if null
MethodReturnsDescription
effectiveStyle()SpcProgramBlockStyleReturns custom style or SpcProgramBlockStyle.DEFAULT.

SpcProgramBlockRegistry

api.registry public final class SpcProgramBlockRegistry

Registry for addon programming block categories. Thread-safe. Freezes after mod setup.

MethodReturnsDescription
register(SpcProgramBlockCategory)voidRegister a programming block category. Throws if frozen or duplicate.
find(String categoryId)Optional<SpcProgramBlockCategory>Look up a category by ID.
all()Map<String, SpcProgramBlockCategory>Unmodifiable view of all categories.
isFrozen()booleanTrue if registry is frozen.
freeze()voidInternal β€” called by SPC, not by addons.

SpcContextExtensionRegistry

api.registry public final class SpcContextExtensionRegistry

Central registry for context extensions. Thread-safe. Freezes after mod setup.

MethodReturnsDescription
register(Class<T>, T instance)voidRegister an extension. Throws if frozen or duplicate.
get(Class<T>)Optional<T>Retrieve extension by interface class.
all()Map<Class<?>, ...>Unmodifiable view of all extensions.
notifyTickStart(ServerLevel, BlockPos)voidInternal β€” called by SPC runtime each tick.
isFrozen()booleanTrue if registry is frozen.
freeze()voidInternal β€” called by SPC, not by addons.

Multiblock Module API

The api.multiblock package allows addons to register custom physical blocks that participate in LOGO multiblock discovery and validation.

ISpcMultiblockModule

api.multiblock @FunctionalInterface public interface ISpcMultiblockModule

Blocks implement this interface to be discovered by the LOGO multiblock BFS scanner. The module type ID must match a type registered in SpcModuleTypeRegistry.

MethodReturnsDescription
getModuleTypeId()StringRegistered module type ID (e.g., "mymod:rotational_input")

SpcModuleType

api.multiblock public record SpcModuleType

Describes a custom multiblock module type β€” where it can be placed and whether it handles I/O.

Constructors

new SpcModuleType(String moduleTypeId, String displayName, SpcMultiblockPosition position, boolean isIoModule)
new SpcModuleType(String moduleTypeId, String displayName, SpcMultiblockPosition position) // isIoModule defaults to true
ComponentTypeDescription
moduleTypeIdStringGlobally unique ID (e.g., "mymod:rotational_input")
displayNameStringHuman-readable name shown in GUI
positionSpcMultiblockPositionWhich multiblock row this type occupies
isIoModulebooleanWhether this module participates in channel assignment

SpcMultiblockPosition

api.multiblock public enum SpcMultiblockPosition

Valid placement rows within the 2×3 LOGO multiblock grid.

ValueDescription
INPUT_ROWTop row (y=+1, column ≥ 1) β€” input modules
OUTPUT_ROWBottom row (y=−1) β€” output modules
MIDDLE_ROWMiddle row (y=0, column ≥ 1) β€” processing/display modules
POWER_ROWPower slot (y=+1, column 0) β€” energy modules

ISpcPhysicalIoHandler

api.multiblock public interface ISpcPhysicalIoHandler

Handles reading/writing signal values for custom I/O module blocks at runtime.

MethodReturnsDefaultDescription
readInput(ServerLevel, BlockPos)SpcSignalValueINTEGER_ZERORead the current value from this I/O block
applyOutput(ServerLevel, BlockPos, SpcSignalValue)voidno-opApply a computed value to this I/O block

SpcModuleTypeRegistry

api.multiblock public final class SpcModuleTypeRegistry

Central registry for custom multiblock module types. Thread-safe. Freezes after mod setup.

MethodReturnsDescription
register(SpcModuleType, ISpcPhysicalIoHandler)voidRegister an I/O module type with its handler
register(SpcModuleType)voidRegister a non-I/O module type (no handler)
find(String moduleTypeId)Optional<SpcModuleTypeRegistration>Look up a module type
all()Map<String, SpcModuleTypeRegistration>All registrations (unmodifiable)
freeze()voidInternal β€” called by SPC

Inner record: SpcModuleTypeRegistration

ComponentType
moduleTypeSpcModuleType
ioHandlerISpcPhysicalIoHandler (nullable for non-I/O modules)

Network Device API

The api.network package enables addons to create custom network devices, wireless activation blocks, and cable-traversable blocks.

ISpcNetworkDevice

api.network public interface ISpcNetworkDevice

Block entities implement this to participate in LOGO network routing as addressable devices.

MethodReturnsDefaultDescription
getDeviceTypeId()StringRegistered device type ID
getNetworkIp()StringUnique network address (e.g., "192.168.0.10")
readDeviceValue()SpcSignalValueINTEGER_ZEROCurrent device signal value
applyDeviceValue(SpcSignalValue)voidno-opApply a signal value to this device

ISpcNetworkActivation

api.network public interface ISpcNetworkActivation

Blocks implement this to act as wireless activation sources (buttons, levers, pressure plates).

MethodReturnsDescription
getNetworkName()StringTransmitter network name this activation block is bound to
isSignalActive()booleanWhether the activation signal is currently active

ISpcCableTraversable

api.network public interface ISpcCableTraversable

Marker interface (no methods). Blocks implementing this are treated as cable-traversable by the network BFS route finder β€” allowing addon cable/conduit blocks to participate in network routing.


SpcNetworkRegistry

api.network public final class SpcNetworkRegistry

Registry for custom network device types. Thread-safe. Freezes after mod setup.

MethodReturnsDescription
registerDeviceType(String id, String displayName)voidRegister a new device type
findDeviceType(String id)Optional<SpcNetworkDeviceType>Look up a device type
allDeviceTypes()Map<String, SpcNetworkDeviceType>All device types (unmodifiable)
freeze()voidInternal β€” called by SPC

Inner record: SpcNetworkDeviceType

ComponentType
deviceTypeIdString
displayNameString

Runtime Event API

The api.event package provides lifecycle hooks so addons can react to program start/stop and multiblock assembly/disassembly events.

ISpcRuntimeEventListener

api.event public interface ISpcRuntimeEventListener

Lifecycle hook interface. All methods have empty defaults β€” override only what you need.

MethodParametersDescription
onProgramStartServerLevel, BlockPos machinePosCalled when a LOGO program begins execution
onProgramStopServerLevel, BlockPos machinePosCalled when a running program is stopped
onMultiblockAssembleServerLevel, BlockPos machinePosCalled when a multiblock is successfully assembled
onMultiblockDisassembleServerLevel, BlockPos machinePosCalled when a multiblock is broken or invalidated

SpcRuntimeEventRegistry

api.event public final class SpcRuntimeEventRegistry

Registry for runtime event listeners. Thread-safe. Freezes after mod setup.

MethodReturnsDescription
register(ISpcRuntimeEventListener)voidRegister a listener. Throws if frozen.
all()List<ISpcRuntimeEventListener>Snapshot of all listeners (unmodifiable)
freeze()voidInternal β€” called by SPC
💡 Usage example
SpcRuntimeEventRegistry.register(new ISpcRuntimeEventListener() {
    @Override
    public void onProgramStart(ServerLevel level, BlockPos pos) {
        // Initialize addon state for this machine
    }
});