Minestom currently does not have a traditional plugin/extension system like Bukkit/Spigot. Instead, it’s designed as a library that you include in your project and extend through composition.
Minestom is intentionally built as a library rather than a traditional server with a plugin API:
import net.minestom.server.MinecraftServer;import net.minestom.server.event.GlobalEventHandler;public class MyMinestomServer { public static void main(String[] args) { // Initialize the server MinecraftServer server = MinecraftServer.init(); // Your custom logic here GlobalEventHandler eventHandler = MinecraftServer.getGlobalEventHandler(); // Register custom features registerGameModes(); registerCommands(); registerEvents(); // Start the server server.start("0.0.0.0", 25565); } private static void registerGameModes() { // Your game mode logic } private static void registerCommands() { // Your command logic } private static void registerEvents() { // Your event logic }}
This design gives you complete control over your server’s architecture. You can structure your code however you want without being constrained by a plugin API.
The OpenToLAN extra allows your server to appear in the Minecraft client’s LAN server list.
import net.minestom.server.extras.lan.OpenToLAN;import net.minestom.server.extras.lan.OpenToLANConfig;public class LANServerExample { public void setupLANBroadcast() { // Basic usage with defaults boolean success = OpenToLAN.open(); if (success) { System.out.println("Server is now broadcasting to LAN!"); } } public void setupCustomLANBroadcast() { // Advanced configuration OpenToLANConfig config = new OpenToLANConfig() .port(0) // 0 = random free port .pingDelay(Duration.ofSeconds(1)) // Send ping every 1 second .eventCallDelay(Duration.ofSeconds(30)); // Refresh server list event every 30s OpenToLAN.open(config); } public void stopLANBroadcast() { // Stop broadcasting boolean wasStopped = OpenToLAN.close(); } public void checkLANStatus() { // Check if currently broadcasting if (OpenToLAN.isOpen()) { System.out.println("LAN broadcasting is active"); } }}
OpenToLAN doesn’t actually open your server to your network - it just broadcasts its presence. Your server must already be accessible on your LAN.
OpenToLAN sends UDP packets to the multicast address 224.0.2.60:4445, which Minecraft clients listen to:
// The OpenToLAN system:// 1. Creates a DatagramSocket on the configured port// 2. Periodically sends server info to 224.0.2.60:4445// 3. Clients on the same network receive these packets// 4. Clients display the server in their server list under "LAN Worlds"
The Query extra implements the GameSpy4 Query Protocol, allowing server query tools to retrieve server information:
import net.minestom.server.extras.query.Query;public class QueryExample { public void setupQuery() { // Start query on default port (same as server port) int port = Query.start(); System.out.println("Query listening on port: " + port); } public void setupQueryOnCustomPort() { // Start query on specific port boolean success = Query.start(25566); if (success) { System.out.println("Query started on port 25566"); } } public void stopQuery() { // Stop query server boolean wasStopped = Query.stop(); } public void checkQueryStatus() { if (Query.isStarted()) { System.out.println("Query is running"); } }}
Query is commonly used by server list websites and monitoring tools to retrieve server status without connecting as a player.
The Mojang authentication extra provides cryptographic utilities for online mode authentication:
import net.minestom.server.extras.mojangAuth.MojangCrypt;import java.security.KeyPair;import java.security.PublicKey;import javax.crypto.SecretKey;public class AuthenticationExample { public void generateServerKeys() { // Generate RSA key pair for server KeyPair keyPair = MojangCrypt.generateKeyPair(); if (keyPair != null) { PublicKey publicKey = keyPair.getPublic(); // Use for authentication } } public void createAuthenticationHash(String serverId, PublicKey publicKey, SecretKey secretKey) { // Create hash for Mojang session server verification byte[] hash = MojangCrypt.digestData(serverId, publicKey, secretKey); // This hash is sent to Mojang's session server // to verify the player's identity }}
Most users don’t need to interact with MojangCrypt directly - Minestom handles authentication automatically when online mode is enabled.
package com.mycompany.minestom.game;import net.minestom.server.MinecraftServer;import net.minestom.server.entity.Player;import net.minestom.server.event.player.PlayerLoginEvent;public class GameFramework { private final GameRegistry registry = new GameRegistry(); public void initialize() { MinecraftServer.getGlobalEventHandler() .addListener(PlayerLoginEvent.class, this::onPlayerLogin); } public void registerGame(Game game) { registry.register(game); } private void onPlayerLogin(PlayerLoginEvent event) { Player player = event.getPlayer(); // Handle player joining a game }}public interface Game { String getId(); void onPlayerJoin(Player player); void onPlayerLeave(Player player); void tick();}
Others can then use your library:
// In another projectimport com.mycompany.minestom.game.GameFramework;import com.mycompany.minestom.game.Game;public class MyServer { public static void main(String[] args) { MinecraftServer server = MinecraftServer.init(); // Use the game framework GameFramework framework = new GameFramework(); framework.initialize(); framework.registerGame(new MyCustomGame()); server.start("0.0.0.0", 25565); }}
Publish your reusable Minestom libraries to Maven Central or JitPack so others can easily use them.