Files
Documentation/content/getting-started/creating-a-plugin.en.md
2026-01-20 20:33:59 +01:00

197 lines
5.0 KiB
Markdown

---
title: Creating a Plugin
type: docs
weight: 3
---
This guide walks you through creating your first Hytale plugin from scratch.
## Project Structure
A typical Hytale plugin project has this structure:
```
my-plugin/
├── app/
│ ├── build.gradle.kts
│ └── src/
│ ├── main/
│ │ ├── java/
│ │ │ └── com/example/myplugin/
│ │ │ └── MyPlugin.java
│ │ └── resources/
│ │ └── manifest.json
│ └── test/
│ └── java/
├── gradle/
│ ├── libs.versions.toml
│ └── wrapper/
├── build.gradle.kts
├── settings.gradle.kts
└── gradlew
```
## The manifest.json
Every plugin requires a `manifest.json` file in `src/main/resources/`:
```json
{
"Group": "com.example",
"Name": "MyPlugin",
"Version": "1.0.0",
"Description": "My first Hytale plugin",
"Authors": [
{
"Name": "Your Name"
}
],
"Main": "com.example.myplugin.MyPlugin",
"ServerVersion": "*",
"Dependencies": {},
"OptionalDependencies": {},
"DisabledByDefault": false,
"IncludesAssetPack": false,
"SubPlugins": []
}
```
### Manifest Fields
| Field | Required | Description |
|-------|----------|-------------|
| `Group` | Yes | Package group (e.g., "com.example") |
| `Name` | Yes | Plugin name (used for identification) |
| `Version` | Yes | Semantic version (e.g., "1.0.0") |
| `Description` | No | Brief description of the plugin |
| `Authors` | No | List of authors with `Name` field |
| `Main` | Yes | Fully qualified main class name |
| `ServerVersion` | Yes | Server version compatibility ("*" for any) |
| `Dependencies` | No | Required plugin dependencies |
| `OptionalDependencies` | No | Optional plugin dependencies |
| `DisabledByDefault` | No | Whether plugin is disabled by default |
| `IncludesAssetPack` | No | Whether plugin includes assets |
| `SubPlugins` | No | List of sub-plugins |
{{< callout type="warning" >}}
All manifest field names use **PascalCase** (e.g., `ServerVersion`, not `serverVersion`).
{{< /callout >}}
## Main Plugin Class
Create your main plugin class extending `JavaPlugin`:
```java
package com.example.myplugin;
import com.hypixel.hytale.server.core.plugin.JavaPlugin;
import com.hypixel.hytale.server.core.plugin.JavaPluginInit;
import java.util.logging.Level;
public class MyPlugin extends JavaPlugin {
public MyPlugin(JavaPluginInit init) {
super(init);
}
@Override
public void setup() {
// Called during plugin initialization
// Register configs, prepare resources
getLogger().at(Level.INFO).log("MyPlugin is setting up!");
}
@Override
public void start() {
// Called when the plugin starts
// Register commands, events, entities
getLogger().at(Level.INFO).log("MyPlugin has started!");
}
@Override
public void shutdown() {
// Called when the plugin is stopping
// Clean up resources
getLogger().at(Level.INFO).log("MyPlugin is shutting down!");
}
}
```
{{< callout type="info" >}}
The constructor with `JavaPluginInit` parameter is required. Always call `super(init)`.
{{< /callout >}}
## Logger API
Hytale uses a Flogger-based logging API:
```java
import java.util.logging.Level;
// Basic logging
getLogger().at(Level.INFO).log("Information message");
getLogger().at(Level.WARNING).log("Warning message");
getLogger().at(Level.SEVERE).log("Error message");
// With formatting
getLogger().at(Level.INFO).log("Player %s joined the game", playerName);
```
## build.gradle.kts
Configure your Gradle build file (Kotlin DSL):
```kotlin
plugins {
java
}
group = "com.example"
version = "1.0.0"
repositories {
mavenCentral()
}
java {
toolchain {
languageVersion = JavaLanguageVersion.of(25)
}
}
dependencies {
// Hytale Server API - compile only since it's provided at runtime
compileOnly(files("../../../HytaleServer.jar"))
// Testing
testImplementation(libs.junit)
}
tasks.jar {
archiveBaseName.set("MyPlugin")
}
```
{{< callout type="info" >}}
The path to `HytaleServer.jar` depends on where your plugin source is located relative to the game directory.
{{< /callout >}}
## Available Registries
Your plugin has access to several registries through the base class:
| Method | Registry Type | Purpose |
|--------|--------------|---------|
| `getEventRegistry()` | EventRegistry | Register event listeners |
| `getCommandRegistry()` | CommandRegistry | Register commands |
| `getEntityRegistry()` | EntityRegistry | Register custom entities |
| `getBlockStateRegistry()` | BlockStateRegistry | Register block states |
| `getTaskRegistry()` | TaskRegistry | Schedule tasks |
| `getAssetRegistry()` | AssetRegistry | Register assets |
| `getEntityStoreRegistry()` | EntityStoreRegistry | Register entity components |
| `getChunkStoreRegistry()` | ChunkStoreRegistry | Register chunk components |
## Next Steps
Learn about the [Plugin Lifecycle](../plugin-lifecycle) to understand when each method is called.