MultiblockInstance & Registry
Packages: net.astronomy.multilib.api.instance (MultiblockInstance), net.astronomy.multilib.core.registry (MultiblockRegistry, BlockDefinitionRegistry), net.astronomy.multilib.core.tracking (WorldMultiblockTracker)
MultiblockInstance
A formed structure in the world - created once matching succeeds, and tracked persistently until broken. Unlike the old API's one-shot PatternAction reaction, this is a real, NBT-serialized object with identity.
public final class MultiblockInstance {
public UUID getId();
public ResourceLocation getDefinitionId();
public BlockPos getOrigin();
public TransformData getTransform();
public boolean contains(BlockPos pos);
public Set<BlockPos> getPositions();
public Set<BlockPos> getPositionsFor(char symbol);
public Optional<BlockPos> getCorePos();
public Optional<UUID> getFormedBy();
}
getId()- stable UUID, assigned at formation, used as the tracker's primary key.getOrigin()- the world position corresponding to the pattern's top-layer center cell, in the matched orientation.getTransform()- theTransformData(rotation/axis) describing exactly which orientation matched.getPositions()- every world position this instance occupies.getPositionsFor(char symbol)- positions matched to a specific pattern symbol (includes free-block positions, if any).getCorePos()- resolves the core symbol's position(s) via the owning definition, ifhasCore().getFormedBy()- the player who triggered formation, if any (emptyfor anonymous formation, e.g. a dispenser pushing the core into place, or periodic re-formation viasetValidationInterval(...)). Consulted byAbstractMultiblockControllerBEto attribute progression records on state change - see Multiblock States & Progress Tracking.
Serialized to/from CompoundTag (save()/load(tag)) by WorldMultiblockTracker; orphaned instances (definition no longer registered, or corrupted data) are discarded with a logged warning on load rather than crashing world load.
MultiblockRegistry
Process-wide, in-memory registry of every registered MultiblockDefinition (Java-defined and JSON-defined alike).
public final class MultiblockRegistry {
public static void register(MultiblockDefinition definition);
public static void registerJson(MultiblockDefinition definition);
public static void clearJsonDefinitions();
public static Optional<MultiblockDefinition> get(ResourceLocation id);
public static Collection<MultiblockDefinition> getAll();
public static List<MultiblockDefinition> getCandidatesFor(Block block);
}
register(...)throwsIllegalStateExceptionif the id is already registered - ids must be unique across the whole game, not just your mod.registerJson(...)/clearJsonDefinitions()- used by the datapack reload listener to swap out JSON-defined definitions on/reloadwithout touching Java-defined ones.getCandidatesFor(Block block)- the core lookup used byBlockActivationHandler: returns every definition indexed underblock(viaBlockIngredient.getCandidateBlocks()) plus every "always-checked" definition (one whose activation/core ingredient can't be enumerated - tags, predicates,any()). Results are sorted bypriority(descending), then JSON-defined before Java-defined on ties (the same "data overrides hardcoded defaults" convention vanilla uses for recipes/loot tables/tags).
Prefer MultiLib.getDefinition(id) / getAllDefinitions() from outside MultiLib itself - this class is the internal implementation.
BlockDefinitionRegistry
Companion registry for block-level metadata (see BlockDefinition):
public final class BlockDefinitionRegistry {
public static void register(BlockDefinition definition);
public static Optional<BlockDefinition> get(Block block);
public static List<Block> getIoPortBlocks();
public static Optional<ResourceLocation> findDeclaredCoreFor(Block block, ResourceLocation multiblockId);
}
WorldMultiblockTracker
A SavedData (one per ServerLevel, obtained via WorldMultiblockTracker.get(level)) tracking every currently-formed MultiblockInstance in that world/dimension.
public class WorldMultiblockTracker extends SavedData {
public static WorldMultiblockTracker get(ServerLevel level);
public void register(MultiblockInstance instance, MultiblockDefinition definition);
public void unregister(UUID id);
public Set<MultiblockInstance> getInstancesAt(BlockPos pos);
public Optional<MultiblockInstance> getById(UUID id);
public Collection<MultiblockInstance> getAllInstances();
public void tick(ServerLevel level);
}
- Maintains a position → instance ids index (
getInstancesAt), soBlockBreakHandlercan find affected instances in O(1) rather than scanning every tracked instance on every block break. tick(...)(driven byMultiblockTickHandler'sLevelTickEvent.Postsubscription) drives every registeredonTick/onAmbientcallback - see Callbacks & Events.- Persisted automatically as part of the level's saved data - instances survive server restarts.
You'll mostly interact with this indirectly (via IMultiblockPart.getInstance(level) / getController(level), or AbstractMultiblockControllerBE's own instanceId field) rather than calling it directly, unless you're writing custom tooling.