Do I need this page?

This is a reference page โ€” you don't need to read it top to bottom.

On this page

Registry Overview

RegistryPackageStoresAdded InGuide 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 RegisterHowExample
@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 FreezeBehavior
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

MethodReturnsParametersDescription
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)

ComponentTypeDescription
schemaSpcNodeSchemaThe node type definition (ports, params, phase)
factoryISpcNodeFactoryCreates compiled node instances
categorySpcNodeCategoryEditor palette category

Exceptions

ConditionException
Register after freezeIllegalStateException
Duplicate typeIdIllegalArgumentException
Null schema/factory/categoryNullPointerException

SpcContextExtensionRegistry

Package: com.hypernova.spc.api.registry
Storage: LinkedHashMap<Class<?>, ISpcExecutionContextExtension>
Thread safety: synchronized register, volatile frozen flag

Methods

MethodReturnsParametersDescription
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

ConditionException
Register after freezeIllegalStateException
Duplicate extension typeIllegalArgumentException
Null type/instanceNullPointerException

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

MethodReturnsParametersDescription
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

ConditionException
Register after freezeIllegalStateException
Duplicate categoryIdIllegalArgumentException
Null categoryNullPointerException

SpcModuleTypeRegistry

Package: com.hypernova.spc.api.multiblock
Storage: ConcurrentHashMap<String, SpcModuleTypeRegistration>
Thread safety: ConcurrentHashMap + volatile frozen flag

Methods

MethodReturnsParametersDescription
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)

ComponentTypeDescription
moduleTypeSpcModuleTypeThe module type definition
ioHandlerISpcPhysicalIoHandlerI/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

MethodReturnsParametersDescription
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)

ComponentTypeDescription
deviceTypeIdStringUnique identifier
displayNameStringEditor display name

SpcRuntimeEventRegistry

Package: com.hypernova.spc.api.event
Storage: CopyOnWriteArrayList<ISpcRuntimeEventListener>
Thread safety: CopyOnWriteArrayList (inherently thread-safe)

Methods

MethodReturnsParametersDescription
register(ISpcRuntimeEventListener) void listener โ€” non-null Register a runtime event listener
all() List<ISpcRuntimeEventListener> โ€” Unmodifiable snapshot
freeze() void โ€” Internal

Side-by-Side Comparison

PropertyNodeRegistryContextExtModuleTypeNetworkEvent
Key typeStringClass<?>StringStringโ€”
Value typeRegistrationExtensionRegistrationDeviceTypeListener
Backing storeLinkedHashMapLinkedHashMapConcurrentHashMapConcurrentHashMapCopyOnWriteArrayList
Allows duplicatesNoNoNoNoYes
Has find()YesYes (get)YesYesNo
Has isFrozen()YesYesYesYesNo
Tick callbackNoYesNoNoNo
API version1.1.01.1.01.1.01.1.01.1.0

Common Mistakes

MistakeSymptomFix
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