Skip to content

Plugin Registries

Hytale provides a comprehensive registry system for plugins to register their components, events, commands, and other features. All registries are accessed through your plugin’s base class and automatically handle cleanup when your plugin is disabled.

  • Plugin base: com.hypixel.hytale.server.core.plugin.PluginBase
  • Component registry: com.hypixel.hytale.component.ComponentRegistryProxy
  • Event registry: com.hypixel.hytale.event.EventRegistry
  • Command registry: com.hypixel.hytale.server.core.command.system.CommandRegistry

The following registries are available:

RegistryMethodPurpose
Command RegistrygetCommandRegistry()Register commands
Event RegistrygetEventRegistry()Register event listeners
Entity Store RegistrygetEntityStoreRegistry()Register entity ECS components/systems
Chunk Store RegistrygetChunkStoreRegistry()Register chunk ECS components/systems
Block State RegistrygetBlockStateRegistry()Register custom block states
Entity RegistrygetEntityRegistry()Register entity types
Task RegistrygetTaskRegistry()Register scheduled tasks
Asset RegistrygetAssetRegistry()Register asset types
Client Feature RegistrygetClientFeatureRegistry()Register client feature flags
Codec RegistrygetCodecRegistry(codec)Register to codec maps

Register commands that players and console can execute.

@Override
protected void setup() {
getCommandRegistry().registerCommand(new MyCommand());
}
MethodDescription
registerCommand(AbstractCommand)Register a command with the server

Commands are automatically unregistered when the plugin shuts down.

See also: Command System

Register listeners for server events.

@Override
protected void setup() {
// Basic registration
getEventRegistry().register(PlayerConnectEvent.class, this::onConnect);
// With priority
getEventRegistry().register(EventPriority.LATE, PlayerChatEvent.class, this::onChat);
// Keyed events (filtered by key)
getEventRegistry().register(SomeKeyedEvent.class, myKey, this::onKeyedEvent);
// Global listener (receives all keyed events)
getEventRegistry().registerGlobal(SomeKeyedEvent.class, this::onAnyKeyedEvent);
// Unhandled listener (only if no other handler processed it)
getEventRegistry().registerUnhandled(SomeEvent.class, this::onUnhandled);
}
MethodDescription
register(Class, Consumer)Register for event with default priority
register(EventPriority, Class, Consumer)Register with specific priority
register(Class, Key, Consumer)Register for keyed event with specific key
registerGlobal(Class, Consumer)Register to receive all keyed events
registerUnhandled(Class, Consumer)Register fallback handler
registerAsync(...)Async variants of above methods

Events are processed in priority order:

PriorityValueUse Case
FIRST-21844Modify event before others see it
EARLY-10922Early processing
NORMAL0Default priority
LATE10922React after modifications
LAST21844Final processing, monitoring

You can also use raw short values for fine-grained control.

See also: Event System

Register ECS components, resources, and systems for entities.

@Override
protected void setup() {
// Register a component type
ComponentType<EntityStore, MyComponent> componentType =
getEntityStoreRegistry().registerComponent(MyComponent.class, MyComponent::new);
// Register with serialization (for saving/loading)
ComponentType<EntityStore, SavedComponent> savedType =
getEntityStoreRegistry().registerComponent(SavedComponent.class, "my_saved", SavedComponent.CODEC);
// Register a resource (world-level data)
ResourceType<EntityStore, MyResource> resourceType =
getEntityStoreRegistry().registerResource(MyResource.class, MyResource::new);
// Register a system
getEntityStoreRegistry().registerSystem(new MyTickingSystem());
// Register an ECS event type
EntityEventType<EntityStore, MyEcsEvent> eventType =
getEntityStoreRegistry().registerEntityEventType(MyEcsEvent.class);
}
MethodDescription
registerComponent(Class, Supplier)Register a component type
registerComponent(Class, String, BuilderCodec)Register serializable component
registerResource(Class, Supplier)Register a resource type
registerResource(Class, String, BuilderCodec)Register serializable resource
registerSystem(ISystem)Register an ECS system
registerSystemType(Class)Register a system type
registerSystemGroup()Create a system group
registerEntityEventType(Class)Register an entity event type
registerWorldEventType(Class)Register a world event type
registerSpatialResource(Supplier)Register spatial index resource

See also: ECS Overview

Register ECS components, resources, and systems for chunks. API mirrors Entity Store Registry.

@Override
protected void setup() {
ComponentType<ChunkStore, ChunkData> chunkDataType =
getChunkStoreRegistry().registerComponent(ChunkData.class, ChunkData::new);
getChunkStoreRegistry().registerSystem(new ChunkProcessingSystem());
}

Register custom block states for block types.

@Override
protected void setup() {
getBlockStateRegistry().register(/* block state registration */);
}

Register custom entity types.

@Override
protected void setup() {
getEntityRegistry().register(/* entity type registration */);
}

Register scheduled and async tasks that should be managed by the plugin lifecycle.

@Override
protected void setup() {
CompletableFuture<Void> asyncTask = CompletableFuture.runAsync(() -> {
// Background work
});
getTaskRegistry().registerTask(asyncTask);
ScheduledFuture<Void> scheduledTask = scheduler.schedule(() -> {
// Delayed work
}, 5, TimeUnit.SECONDS);
getTaskRegistry().registerTask(scheduledTask);
}
MethodDescription
registerTask(CompletableFuture)Register an async task
registerTask(ScheduledFuture)Register a scheduled task

Registered tasks are automatically cancelled when the plugin shuts down.

Register custom asset types and modifiers.

@Override
protected void setup() {
getAssetRegistry().register(/* asset registration */);
}

See also: Asset System

Register client feature flags that affect client behavior.

@Override
protected void setup() {
getClientFeatureRegistry().register(/* client feature */);
}

Register entries to codec maps for serialization.

@Override
protected void setup() {
// Register to a string-keyed codec map
getCodecRegistry(SomeType.CODEC_MAP).register("my_type", MyType.class, MyType.CODEC);
// Register to an asset codec map
getCodecRegistry(SomeAsset.CODEC_MAP).register(/* asset registration */);
}
MethodTypeDescription
getCodecRegistry(StringCodecMapCodec)CodecMapRegistryString-keyed registrations
getCodecRegistry(AssetCodecMapCodec)CodecMapRegistry.AssetsAsset-type registrations
getCodecRegistry(MapKeyMapCodec)MapKeyMapRegistryMap-key registrations

In addition to registries, your plugin has access to these utility methods:

// Get the plugin's logger
HytaleLogger logger = getLogger();
// Log at different levels
logger.at(Level.INFO).log("Plugin loaded!");
logger.at(Level.WARNING).log("Something might be wrong");
logger.at(Level.SEVERE).withCause(exception).log("Error occurred: %s", message);
// Get the plugin's data folder
Path dataDir = getDataDirectory();
// Example: save a file
Path configFile = dataDir.resolve("custom-data.json");
// Get the plugin's unique identifier
PluginIdentifier id = getIdentifier();
String fullId = id.toString(); // "Group/Name"
// Access manifest data
PluginManifest manifest = getManifest();
String version = manifest.getVersion().toString();
String description = manifest.getDescription();
// Get the base permission node
String basePerm = getBasePermission(); // "group.name"
// Use for custom permissions
String myPerm = basePerm + ".myfeature"; // "group.name.myfeature"
// Check plugin state
if (isEnabled()) {
// Plugin is active
}
if (isDisabled()) {
// Plugin is inactive
}
PluginState state = getState();

All registrations made through these registries are automatically cleaned up when your plugin shuts down. You don’t need to manually unregister:

  • Event listeners
  • Commands
  • ECS components, resources, and systems
  • Tasks
  • Codec registrations

The cleanup happens in reverse order of registration, ensuring proper dependency handling.

  1. Register in setup(): Perform all registrations in the setup() method
  2. Store references: Keep references to component/resource types for later use
  3. Use appropriate priorities: Choose event priorities based on your needs
  4. Let cleanup happen automatically: Don’t manually unregister unless necessary