380 lines
11 KiB
Markdown
380 lines
11 KiB
Markdown
---
|
|
title: All Registries
|
|
type: docs
|
|
weight: 2
|
|
---
|
|
|
|
Complete reference of all registries available in the Hytale Plugin API.
|
|
|
|
## Registry Overview
|
|
|
|
Registries are accessed through `PluginBase` methods:
|
|
|
|
```java
|
|
public class MyPlugin extends PluginBase {
|
|
@Override
|
|
public void start() {
|
|
EventRegistry events = getEventRegistry();
|
|
CommandRegistry commands = getCommandRegistry();
|
|
TaskRegistry tasks = getTaskRegistry();
|
|
AssetRegistry assets = getAssetRegistry();
|
|
BlockStateRegistry blocks = getBlockStateRegistry();
|
|
CodecRegistry codecs = getCodecRegistry();
|
|
EntityRegistry entities = getEntityRegistry();
|
|
}
|
|
}
|
|
```
|
|
|
|
## EventRegistry
|
|
|
|
Manages event listeners and dispatching.
|
|
|
|
### Methods
|
|
|
|
| Method | Description |
|
|
|--------|-------------|
|
|
| `register(Class, Consumer)` | Register event handler |
|
|
| `register(EventPriority, Class, Consumer)` | Register with priority |
|
|
| `registerGlobal(Class, Consumer)` | Register global handler |
|
|
| `registerAsync(Class, Function)` | Register async handler |
|
|
| `unregister(listener)` | Remove listener |
|
|
|
|
### Example
|
|
|
|
```java
|
|
import com.hypixel.hytale.event.EventRegistry;
|
|
import com.hypixel.hytale.event.EventPriority;
|
|
import com.hypixel.hytale.server.core.event.events.player.PlayerConnectEvent;
|
|
import com.hypixel.hytale.server.core.event.events.player.PlayerDisconnectEvent;
|
|
import com.hypixel.hytale.server.core.universe.PlayerRef;
|
|
import com.hypixel.hytale.server.core.Message;
|
|
import java.util.logging.Level;
|
|
|
|
EventRegistry events = getEventRegistry();
|
|
|
|
// Use getPlayerRef() - getPlayer() is deprecated
|
|
events.register(PlayerConnectEvent.class, event -> {
|
|
PlayerRef playerRef = event.getPlayerRef();
|
|
playerRef.sendMessage(Message.raw("Welcome!"));
|
|
});
|
|
|
|
events.register(EventPriority.FIRST, PlayerDisconnectEvent.class, event -> {
|
|
PlayerRef playerRef = event.getPlayerRef();
|
|
getLogger().at(Level.INFO).log(playerRef.getUsername() + " left");
|
|
});
|
|
```
|
|
|
|
## CommandRegistry
|
|
|
|
Manages command registration and execution.
|
|
|
|
### Methods
|
|
|
|
| Method | Description |
|
|
|--------|-------------|
|
|
| `registerCommand(AbstractCommand)` | Register a command |
|
|
|
|
### Example
|
|
|
|
```java
|
|
import com.hypixel.hytale.server.core.command.system.AbstractCommand;
|
|
import com.hypixel.hytale.server.core.command.system.CommandContext;
|
|
import com.hypixel.hytale.server.core.command.system.CommandRegistry;
|
|
import com.hypixel.hytale.server.core.Message;
|
|
import java.util.concurrent.CompletableFuture;
|
|
|
|
CommandRegistry commands = getCommandRegistry();
|
|
|
|
// Register a command - AbstractCommand.execute() returns CompletableFuture<Void>
|
|
commands.registerCommand(new AbstractCommand("hello", "my_plugin.commands.hello.description") {
|
|
@Override
|
|
protected CompletableFuture<Void> execute(CommandContext ctx) {
|
|
ctx.sender().sendMessage(Message.raw("Hello, World!"));
|
|
return null; // Return null for synchronous completion
|
|
}
|
|
});
|
|
```
|
|
|
|
{{< callout type="info" >}}
|
|
**Note:** Create a dedicated command class by extending `AbstractCommand` for complex commands. See [Creating Commands](/commands/creating-commands/) for details.
|
|
{{< /callout >}}
|
|
|
|
## TaskRegistry
|
|
|
|
Tracks asynchronous tasks for cleanup during plugin shutdown.
|
|
|
|
{{< callout type="warning" >}}
|
|
**Important:** TaskRegistry does NOT have `runAsync()`, `runSync()`, `runLater()`, or `runRepeating()` methods. Use Java's standard concurrency APIs instead.
|
|
{{< /callout >}}
|
|
|
|
### Methods
|
|
|
|
| Method | Description |
|
|
|--------|-------------|
|
|
| `registerTask(CompletableFuture<Void>)` | Register a CompletableFuture for tracking |
|
|
| `registerTask(ScheduledFuture<Void>)` | Register a ScheduledFuture for tracking |
|
|
|
|
### Example
|
|
|
|
```java
|
|
// Async operation
|
|
CompletableFuture<Void> task = CompletableFuture.runAsync(() -> {
|
|
// Background work
|
|
Data result = heavyComputation();
|
|
|
|
world.execute(() -> {
|
|
playerRef.sendMessage(Message.raw("Done: " + result));
|
|
});
|
|
});
|
|
getTaskRegistry().registerTask(task);
|
|
|
|
// Delayed operation (3 seconds)
|
|
CompletableFuture.delayedExecutor(3, TimeUnit.SECONDS)
|
|
.execute(() -> {
|
|
world.execute(() -> {
|
|
getLogger().at(Level.INFO).log("3 seconds passed!");
|
|
});
|
|
});
|
|
|
|
// Repeating operation
|
|
ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
|
|
ScheduledFuture<?> repeating = scheduler.scheduleAtFixedRate(() -> {
|
|
broadcastTime();
|
|
}, 0, 5, TimeUnit.MINUTES);
|
|
getTaskRegistry().registerTask((ScheduledFuture<Void>) repeating);
|
|
```
|
|
|
|
## AssetRegistry
|
|
|
|
Registers custom asset stores with the game.
|
|
|
|
**Package:** `com.hypixel.hytale.server.core.plugin.registry`
|
|
|
|
{{< callout type="warning" >}}
|
|
**Important:** `AssetRegistry` does NOT provide `getItem()`, `getBlockType()`, etc. methods. To access assets, use the asset class's static methods directly.
|
|
{{< /callout >}}
|
|
|
|
### Methods
|
|
|
|
| Method | Description |
|
|
|--------|-------------|
|
|
| `register(AssetStore)` | Register a custom AssetStore |
|
|
|
|
### Accessing Assets
|
|
|
|
Assets are accessed via their class's static methods, not through AssetRegistry:
|
|
|
|
```java
|
|
import com.hypixel.hytale.assetstore.map.DefaultAssetMap;
|
|
import com.hypixel.hytale.server.core.asset.type.item.config.Item;
|
|
import com.hypixel.hytale.server.core.asset.type.blocktype.config.BlockType;
|
|
|
|
// Get items by string ID directly (DefaultAssetMap)
|
|
DefaultAssetMap<String, Item> itemMap = Item.getAssetMap();
|
|
Item sword = itemMap.getAsset("iron_sword");
|
|
|
|
// Get block types
|
|
DefaultAssetMap<String, BlockType> blockMap = BlockType.getAssetMap();
|
|
BlockType stone = blockMap.getAsset("stone");
|
|
```
|
|
|
|
{{< callout type="info" >}}
|
|
**Note:** Most assets like `Item` and `BlockType` use `DefaultAssetMap` where you can access by string key directly. Some assets like `Interaction` use `IndexedLookupTableAssetMap` which requires getting the index first.
|
|
{{< /callout >}}
|
|
|
|
### Custom Asset Store Registration
|
|
|
|
```java
|
|
AssetRegistry assets = getAssetRegistry();
|
|
|
|
// Register a custom asset store
|
|
assets.register(MyCustomAsset.getAssetStore());
|
|
```
|
|
|
|
## BlockStateRegistry
|
|
|
|
Manages block states and their properties.
|
|
|
|
### Methods
|
|
|
|
| Method | Description |
|
|
|--------|-------------|
|
|
| `getBlockState(BlockType)` | Get default state |
|
|
| `getBlockState(BlockType, Properties)` | Get state with properties |
|
|
|
|
### Example
|
|
|
|
```java
|
|
BlockStateRegistry blocks = getBlockStateRegistry();
|
|
|
|
BlockState stone = blocks.getBlockState(stoneType);
|
|
world.setBlockState(x, y, z, stone);
|
|
```
|
|
|
|
## Codec Registration
|
|
|
|
**Package:** `com.hypixel.hytale.server.core.plugin.registry`
|
|
|
|
{{< callout type="warning" >}}
|
|
**Important:** There is no simple `CodecRegistry` class. Instead, use the typed `getCodecRegistry()` methods with codec map parameters.
|
|
{{< /callout >}}
|
|
|
|
### Methods
|
|
|
|
| Method | Description |
|
|
|--------|-------------|
|
|
| `getCodecRegistry(StringCodecMapCodec)` | Get CodecMapRegistry for string-keyed codecs |
|
|
| `getCodecRegistry(AssetCodecMapCodec)` | Get CodecMapRegistry.Assets for asset codecs |
|
|
| `getCodecRegistry(MapKeyMapCodec)` | Get MapKeyMapRegistry for map-keyed codecs |
|
|
|
|
### Example
|
|
|
|
```java
|
|
import com.hypixel.hytale.codec.builder.BuilderCodec;
|
|
import com.hypixel.hytale.server.core.plugin.registry.CodecMapRegistry;
|
|
import com.hypixel.hytale.server.core.modules.interaction.interaction.config.Interaction;
|
|
|
|
// Register a custom interaction type using the Interaction CODEC
|
|
CodecMapRegistry.Assets<Interaction, ?> registry =
|
|
getCodecRegistry(Interaction.CODEC);
|
|
|
|
registry.register("MyCustomInteraction", MyCustomInteraction.class, MyCustomInteraction.CODEC);
|
|
```
|
|
|
|
For simple data serialization, use `BuilderCodec` directly:
|
|
|
|
```java
|
|
import com.hypixel.hytale.codec.builder.BuilderCodec;
|
|
import com.hypixel.hytale.codec.KeyedCodec;
|
|
import com.hypixel.hytale.codec.Codec;
|
|
|
|
// Define a codec for your data class
|
|
public static final BuilderCodec<PlayerData> CODEC = BuilderCodec.builder(PlayerData.class, PlayerData::new)
|
|
.append(new KeyedCodec<>("name", Codec.STRING),
|
|
(obj, val) -> obj.name = val,
|
|
obj -> obj.name)
|
|
.add()
|
|
.build();
|
|
```
|
|
|
|
## EntityRegistry
|
|
|
|
Registers custom entity types with the game.
|
|
|
|
**Package:** `com.hypixel.hytale.server.core.modules.entity`
|
|
|
|
{{< callout type="warning" >}}
|
|
**Important:** `EntityRegistry` is for registering custom entity types, NOT for spawning entities. To spawn entities, use `World.spawnEntity()`.
|
|
{{< /callout >}}
|
|
|
|
### Methods
|
|
|
|
| Method | Description |
|
|
|--------|-------------|
|
|
| `registerEntity(String, Class, Function, Codec)` | Register a custom entity type |
|
|
|
|
### Registering Custom Entities
|
|
|
|
```java
|
|
import com.hypixel.hytale.server.core.entity.Entity;
|
|
import com.hypixel.hytale.codec.DirectDecodeCodec;
|
|
|
|
EntityRegistry entities = getEntityRegistry();
|
|
|
|
// Register a custom entity type
|
|
entities.registerEntity(
|
|
"my_custom_entity",
|
|
MyCustomEntity.class,
|
|
world -> new MyCustomEntity(world),
|
|
MyCustomEntity.CODEC
|
|
);
|
|
```
|
|
|
|
### Spawning Entities
|
|
|
|
To spawn entities at runtime, use `World`:
|
|
|
|
```java
|
|
import com.hypixel.hytale.server.core.universe.world.World;
|
|
import com.hypixel.hytale.server.core.entity.Entity;
|
|
|
|
World world = player.getWorld();
|
|
|
|
// Spawn an entity
|
|
Entity entity = world.spawnEntity(entityClass, position);
|
|
```
|
|
|
|
## Registry Access Patterns
|
|
|
|
### Lazy Initialization
|
|
|
|
```java
|
|
public class MyPlugin extends PluginBase {
|
|
private EventRegistry events;
|
|
private CommandRegistry commands;
|
|
|
|
@Override
|
|
public void start() {
|
|
this.events = getEventRegistry();
|
|
this.commands = getCommandRegistry();
|
|
|
|
registerEvents();
|
|
registerCommands();
|
|
}
|
|
|
|
private void registerEvents() {
|
|
events.register(PlayerConnectEvent.class, this::onJoin);
|
|
}
|
|
|
|
private void registerCommands() {
|
|
commands.register(new MyCommand());
|
|
}
|
|
}
|
|
```
|
|
|
|
### Helper Methods
|
|
|
|
```java
|
|
public class MyPlugin extends JavaPlugin {
|
|
public void runOnWorldThread(World world, Runnable task) {
|
|
world.execute(task);
|
|
}
|
|
|
|
public void runAsync(Runnable task) {
|
|
CompletableFuture.runAsync(task);
|
|
}
|
|
|
|
public Item getItem(String id) {
|
|
return getAssetRegistry().getItem(id);
|
|
}
|
|
}
|
|
```
|
|
|
|
## Thread Safety
|
|
|
|
{{< callout type="warning" >}}
|
|
**Registry Thread Safety:**
|
|
- Most registries are designed for world thread access
|
|
- Each World runs on its own dedicated thread
|
|
- Use `world.execute()` when accessing from async code
|
|
- TaskRegistry is thread-safe for task registration
|
|
{{< /callout >}}
|
|
|
|
```java
|
|
// Safe async pattern
|
|
World world = player.getWorld();
|
|
PlayerRef playerRef = player.getPlayerRef();
|
|
|
|
CompletableFuture.runAsync(() -> {
|
|
// Background work
|
|
Data result = compute();
|
|
|
|
// Return to world thread for game state changes
|
|
world.execute(() -> {
|
|
// Access other registries here safely
|
|
EventRegistry events = getEventRegistry();
|
|
playerRef.sendMessage(Message.raw("Result: " + result));
|
|
});
|
|
});
|
|
```
|