---
title: Registries
type: docs
weight: 1
---

Registries are central to Hytale plugin development. They provide a way to register and manage various game elements like commands, events, entities, and more.

**Packages:**
- `com.hypixel.hytale.server.core.command.system` (CommandRegistry)
- `com.hypixel.hytale.event` (EventRegistry)
- `com.hypixel.hytale.server.core.plugin.registry` (AssetRegistry, CodecRegistry)

## Available Registries

Your plugin has access to these registries through the `PluginBase` class:

| Registry | Method | Purpose |
|----------|--------|---------|
| CommandRegistry | `getCommandRegistry()` | Register server commands |
| EventRegistry | `getEventRegistry()` | Register event listeners |
| EntityRegistry | `getEntityRegistry()` | Register custom entities |
| BlockStateRegistry | `getBlockStateRegistry()` | Register block states |
| TaskRegistry | `getTaskRegistry()` | Schedule and manage tasks |
| AssetRegistry | `getAssetRegistry()` | Register custom assets |
| ClientFeatureRegistry | `getClientFeatureRegistry()` | Register client features |
| EntityStoreRegistry | `getEntityStoreRegistry()` | Entity storage components |
| ChunkStoreRegistry | `getChunkStoreRegistry()` | Chunk storage components |

## CommandRegistry

Register commands that players can execute:

```java
@Override
public void start() {
    getCommandRegistry().registerCommand(new MyCommand());
}
```

See [Commands](../../commands) for detailed documentation.

## EventRegistry

Subscribe to game events:

```java
import com.hypixel.hytale.event.EventPriority;
import com.hypixel.hytale.server.core.event.events.player.PlayerConnectEvent;
import java.util.logging.Level;

@Override
public void start() {
    // Simple registration
    getEventRegistry().register(PlayerConnectEvent.class, event -> {
        getLogger().at(Level.INFO).log("Player connecting: " + event.getPlayerRef().getUsername());
    });

    // With priority
    getEventRegistry().register(
        EventPriority.EARLY,
        PlayerConnectEvent.class,
        this::onPlayerConnect
    );
}
```

See [Events](../../events) for detailed documentation.

## EntityRegistry

Register custom entity types:

```java
@Override
public void start() {
    getEntityRegistry().register(MyCustomEntity.class, MyCustomEntity::new);
}
```

See [Entities](../../entities) for detailed documentation.

## BlockStateRegistry

Register custom block states:

```java
@Override
public void start() {
    getBlockStateRegistry().register(myBlockState);
}
```

## TaskRegistry

Track async tasks for cleanup during plugin shutdown:

{{< callout type="warning" >}}
TaskRegistry does NOT have `runAsync()`, `runSync()`, `runLater()`, or `runRepeating()` methods. Use Java's standard concurrency APIs.
{{< /callout >}}

```java
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;

@Override
public void start() {
    // Async operation
    CompletableFuture<Void> task = CompletableFuture.runAsync(() -> {
        // Background work
    });
    getTaskRegistry().registerTask(task);

    // Delayed operation (3 seconds)
    CompletableFuture.delayedExecutor(3, TimeUnit.SECONDS)
        .execute(() -> {
            getLogger().at(Level.INFO).log("Delayed task executed!");
        });

    // Repeating operation (every 5 minutes)
    ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
    ScheduledFuture<?> repeating = scheduler.scheduleAtFixedRate(() -> {
        getLogger().at(Level.INFO).log("Repeating task!");
    }, 0, 5, TimeUnit.MINUTES);
    getTaskRegistry().registerTask((ScheduledFuture<Void>) repeating);
}
```

See [Tasks](../../tasks) for detailed documentation.

## AssetRegistry

Register custom game assets:

```java
@Override
public void start() {
    getAssetRegistry().register(myAsset);
}
```

## CodecRegistry

For registering custom serialization codecs:

```java
getCodecRegistry(MyType.CODEC_MAP).register("my_type", MyType.CODEC);
```

## Automatic Cleanup

{{< callout type="info" >}}
All registrations are automatically cleaned up when your plugin is disabled. You don't need to manually unregister anything in your `shutdown()` method.
{{< /callout >}}

## Registration Timing

Register your components in the `start()` method, not in `setup()`:

```java
@Override
public void setup() {
    // Configuration only - don't register here
    withConfig(MyConfig.CODEC);
}

@Override
public void start() {
    // Register everything here
    getCommandRegistry().registerCommand(new MyCommand());
    getEventRegistry().register(PlayerConnectEvent.class, this::onJoin);
}
```

This ensures all plugins have completed their setup phase before any registrations occur.
