Do I need this page?
- Use as a lookup when you need to know exact method signatures, freeze timing, or return types
- For beginners: you only need
SpcNodeRegistry.register() โ that's covered in the tutorial
- Come back later when you start using context extensions, multiblock modules, network devices, or events
This is a reference page โ you don't need to read it top to bottom.
Registry Overview
| Registry | Package | Stores | Added In | Guide Page |
SpcNodeRegistry |
api.registry |
Node schemas + factories + categories |
v1 |
Core Concepts, Tutorial |
SpcContextExtensionRegistry |
api.registry |
Execution context extensions |
v1 |
Context Extensions |
SpcProgramBlockRegistry |
api.registry |
Programming block categories + visual styles |
1.1.0 |
API Reference |
SpcModuleTypeRegistry |
api.multiblock |
Custom multiblock module types + I/O handlers |
|
Multiblock Modules |
SpcNetworkRegistry |
api.network |
Network device type definitions |
|
Network Devices |
SpcRuntimeEventRegistry |
api.event |
Runtime event listeners |
|
Runtime Events |
Registration Timing
All registrations must happen before the registry is frozen by SPC.
| When to Register | How | Example |
@Mod constructor |
Call register() directly in your mod's constructor |
SpcNodeRegistry.register(schema, factory, category); |
FMLCommonSetupEvent |
Register inside the event handler |
modBus.addListener(e -> SpcNodeRegistry.register(...)); |
โ ๏ธ Never register lazily
Do not register in
ServerStartingEvent,
LevelEvent.Load,
or any per-world event. By that time, all registries are frozen.
Freeze Behavior
After mod loading completes, SPC calls freeze() on every registry.
| After Freeze | Behavior |
register() | Throws IllegalStateException |
find() / get() | Works normally (read-only) |
all() | Returns unmodifiable view |
isFrozen() | Returns true |
โน๏ธ Do not call freeze() yourself
The
freeze() method is internal to SPC. Addon mods should never call it.
SpcNodeRegistry
Package: com.hypernova.spc.api.registry
Storage: LinkedHashMap<String, SpcNodeRegistration> (preserves insertion order)
Thread safety: synchronized register, volatile frozen flag
Methods
| Method | Returns | Parameters | Description |
register(SpcNodeSchema, ISpcNodeFactory, SpcNodeCategory) |
void |
schema โ node type declaration
factory โ compiled node creator
category โ palette group |
Register a custom function block node type |
find(String typeId) |
Optional<SpcNodeRegistration> |
typeId โ the node type ID |
Look up a registration |
all() |
Map<String, SpcNodeRegistration> |
โ |
Unmodifiable view of all registrations |
isFrozen() |
boolean |
โ |
Whether frozen |
freeze() |
void |
โ |
Internal |
SpcNodeRegistration (inner record)
| Component | Type | Description |
schema | SpcNodeSchema | The node type definition (ports, params, phase) |
factory | ISpcNodeFactory | Creates compiled node instances |
category | SpcNodeCategory | Editor palette category |
Exceptions
| Condition | Exception |
| Register after freeze | IllegalStateException |
| Duplicate typeId | IllegalArgumentException |
| Null schema/factory/category | NullPointerException |
SpcContextExtensionRegistry
Package: com.hypernova.spc.api.registry
Storage: LinkedHashMap<Class<?>, ISpcExecutionContextExtension>
Thread safety: synchronized register, volatile frozen flag
Methods
| Method | Returns | Parameters | Description |
register(Class<T>, T instance) |
void |
extensionType โ interface class (lookup key)
instance โ implementation |
Register a context extension |
get(Class<T>) |
Optional<T> |
extensionType |
Look up a registered extension by type |
all() |
Map<Class<?>, ISpcExecutionContextExtension> |
โ |
Unmodifiable view of all extensions |
notifyTickStart(ServerLevel, BlockPos) |
void |
level, machinePos |
Internal โ calls onTickStart() on all extensions |
isFrozen() |
boolean |
โ |
Whether frozen |
freeze() |
void |
โ |
Internal |
Exceptions
| Condition | Exception |
| Register after freeze | IllegalStateException |
| Duplicate extension type | IllegalArgumentException |
| Null type/instance | NullPointerException |
SpcProgramBlockRegistry
Package: com.hypernova.spc.api.registry
Storage: LinkedHashMap<String, SpcProgramBlockCategory>
Thread safety: synchronized register, volatile frozen flag
Allows addons to register custom programming block categories with distinct visual styles.
Each category defines a themed variant of the programming block (custom tint colors).
Categories without an explicit style default to the brass palette.
Methods
| Method | Returns | Parameters | Description |
register(SpcProgramBlockCategory) |
void |
category |
Register a programming block category |
find(String) |
Optional<SpcProgramBlockCategory> |
categoryId |
Look up by ID |
all() |
Map<String, SpcProgramBlockCategory> |
โ |
Unmodifiable view of all categories |
isFrozen() |
boolean |
โ |
Whether frozen |
freeze() |
void |
โ |
Internal |
Example Registration
SpcProgramBlockRegistry.register(new SpcProgramBlockCategory(
"mymod:advanced_programmer",
"Advanced Programmer",
new SpcProgramBlockStyle(0xFF4488CC, 0xFF2255AA, 0xFF66BB6A)
));
Exceptions
| Condition | Exception |
| Register after freeze | IllegalStateException |
| Duplicate categoryId | IllegalArgumentException |
| Null category | NullPointerException |
SpcModuleTypeRegistry
Package: com.hypernova.spc.api.multiblock
Storage: ConcurrentHashMap<String, SpcModuleTypeRegistration>
Thread safety: ConcurrentHashMap + volatile frozen flag
Methods
| Method | Returns | Parameters | Description |
register(SpcModuleType, ISpcPhysicalIoHandler) |
void |
moduleType; ioHandler (nullable for non-I/O) |
Register a module type with its handler |
register(SpcModuleType) |
void |
moduleType |
Register non-I/O module (handler = null) |
find(String moduleTypeId) |
Optional<SpcModuleTypeRegistration> |
moduleTypeId |
Look up a registration |
all() |
Map<String, SpcModuleTypeRegistration> |
โ |
Unmodifiable view |
isFrozen() |
boolean |
โ |
Whether frozen |
freeze() |
void |
โ |
Internal |
SpcModuleTypeRegistration (inner record)
| Component | Type | Description |
moduleType | SpcModuleType | The module type definition |
ioHandler | ISpcPhysicalIoHandler | I/O handler (null for non-I/O modules) |
SpcNetworkRegistry
Package: com.hypernova.spc.api.network
Storage: ConcurrentHashMap<String, SpcNetworkDeviceType>
Thread safety: ConcurrentHashMap + volatile frozen flag
Methods
| Method | Returns | Parameters | Description |
registerDeviceType(String, String) |
void |
deviceTypeId, displayName |
Register a device type |
findDeviceType(String) |
Optional<SpcNetworkDeviceType> |
deviceTypeId |
Look up a type |
allDeviceTypes() |
Map<String, SpcNetworkDeviceType> |
โ |
Unmodifiable view |
isFrozen() |
boolean |
โ |
Whether frozen |
freeze() |
void |
โ |
Internal |
SpcNetworkDeviceType (inner record)
| Component | Type | Description |
deviceTypeId | String | Unique identifier |
displayName | String | Editor display name |
SpcRuntimeEventRegistry
Package: com.hypernova.spc.api.event
Storage: CopyOnWriteArrayList<ISpcRuntimeEventListener>
Thread safety: CopyOnWriteArrayList (inherently thread-safe)
Methods
| Method | Returns | Parameters | Description |
register(ISpcRuntimeEventListener) |
void |
listener โ non-null |
Register a runtime event listener |
all() |
List<ISpcRuntimeEventListener> |
โ |
Unmodifiable snapshot |
freeze() |
void |
โ |
Internal |
Side-by-Side Comparison
| Property | NodeRegistry | ContextExt | ModuleType | Network | Event |
| Key type | String | Class<?> | String | String | โ |
| Value type | Registration | Extension | Registration | DeviceType | Listener |
| Backing store | LinkedHashMap | LinkedHashMap | ConcurrentHashMap | ConcurrentHashMap | CopyOnWriteArrayList |
| Allows duplicates | No | No | No | No | Yes |
Has find() | Yes | Yes (get) | Yes | Yes | No |
Has isFrozen() | Yes | Yes | Yes | Yes | No |
| Tick callback | No | Yes | No | No | No |
| API version | 1.1.0 | 1.1.0 | 1.1.0 | 1.1.0 | 1.1.0 |
Common Mistakes
| Mistake | Symptom | Fix |
Registering in ServerStartingEvent |
IllegalStateException: โฆ is frozen |
Move registration to @Mod constructor or FMLCommonSetupEvent |
| Duplicate type ID |
IllegalArgumentException / IllegalStateException |
Namespace your IDs: "mymod:type" instead of "type" |
Calling freeze() from addon |
Other addons can't register anymore |
Never call freeze() โ SPC does it automatically |
| Forgetting to register I/O handler |
Module works structurally but signals are always zero |
Use register(moduleType, handler) not register(moduleType) |
| Not namespacing IDs |
Collisions with other addons |
Always use "yourmod:name" format |