java-25-hytale

SKILL.md

Java 25 for Hytale

Modern Java features and patterns for Hytale plugin development.

Why Java 25?

Hytale server runs on Java 25 - you must use this version for plugin development.

Installation

Windows (Recommended)

# Using winget (Windows Package Manager)
winget install EclipseAdoptium.Temurin.25.JDK

# Verify installation
java --version

Manual Download

  1. Go to Adoptium.net
  2. Download Temurin 25 (LTS)
  3. Run installer
  4. Add to PATH if not automatic

macOS

brew install --cask temurin@25

Linux

# Ubuntu/Debian
sudo apt install temurin-25-jdk

# Fedora
sudo dnf install temurin-25-jdk

Key Java 25 Features for Hytale

Records (Data Classes)

Perfect for immutable data objects:

// Instead of verbose class with getters/equals/hashCode
public record PlayerData(String name, int level, double health) {}

// Usage
var data = new PlayerData("Steve", 10, 100.0);
System.out.println(data.name());  // "Steve"

Pattern Matching

Cleaner type checks:

// Old way
if (obj instanceof Player) {
    Player player = (Player) obj;
    player.sendMessage("Hello!");
}

// Java 25 way
if (obj instanceof Player player) {
    player.sendMessage("Hello!");
}

Switch Expressions

String message = switch (gameMode) {
    case SURVIVAL -> "Good luck surviving!";
    case CREATIVE -> "Build freely!";
    case ADVENTURE -> "Explore the world!";
    default -> "Welcome!";
};

Pattern Matching in Switch

Object entity = getEntity();
String type = switch (entity) {
    case Player p -> "Player: " + p.getName();
    case NPC n -> "NPC: " + n.getType();
    case Monster m -> "Monster: " + m.getName();
    case null -> "No entity";
    default -> "Unknown entity";
};

Sealed Classes

Restrict inheritance:

public sealed class GameEvent permits PlayerEvent, WorldEvent, BlockEvent {
    // Base event class
}

public final class PlayerEvent extends GameEvent {
    // Cannot be extended further
}

Virtual Threads (Project Loom)

Lightweight concurrency for async operations:

// Old way - platform threads are heavy
new Thread(() -> loadPlayerData()).start();

// Java 25 way - virtual threads are lightweight
Thread.startVirtualThread(() -> loadPlayerData());

// Or with executor
try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
    executor.submit(() -> loadPlayerData());
    executor.submit(() -> loadWorldData());
}

Text Blocks

Multi-line strings:

String json = """
    {
        "name": "MyPlugin",
        "version": "1.0.0",
        "author": "YourName"
    }
    """;

Hytale-Specific Patterns

Null Safety

Always check for null components:

// Good
var health = entity.getComponent(HealthComponent.class);
if (health != null) {
    health.heal(10);
}

// Better with Optional
entity.getComponentOptional(HealthComponent.class)
    .ifPresent(h -> h.heal(10));

Functional Event Handling

// Lambda for simple handlers
registerEventListener(PlayerJoinEvent.class, 
    e -> e.getPlayer().sendMessage("Welcome!"));

// Method reference for reusable handlers
registerEventListener(PlayerJoinEvent.class, this::onPlayerJoin);

private void onPlayerJoin(PlayerJoinEvent event) {
    // Complex logic here
}

Stream API for Collections

// Filter and process players
List<Player> onlinePlayers = getServer().getPlayers();

onlinePlayers.stream()
    .filter(p -> p.getLevel() > 10)
    .forEach(p -> p.giveReward("veteran_badge"));

// Count specific types
long monsterCount = getWorld().getEntities().stream()
    .filter(e -> e instanceof Monster)
    .count();

Common Issues

Issue Solution
Wrong Java version Set JAVA_HOME to Java 25
Class not found Check Gradle compileOnly dependency
Unsupported class version Rebuild with Java 25 toolchain
IntelliJ uses wrong JDK Project Structure → SDK → Java 25

IDE Configuration

IntelliJ IDEA

  1. File → Project Structure → Project
  2. Set SDK to Java 25
  3. Set Language Level to 25

Gradle (build.gradle.kts)

java {
    toolchain {
        languageVersion.set(JavaLanguageVersion.of(25))
    }
}
Weekly Installs
5
GitHub Stars
3
First Seen
Feb 10, 2026
Installed on
github-copilot5
codex5
gemini-cli5
opencode4
claude-code4
cursor4