Esta guía te lleva de cero a tener tu primer plugin funcional instalado en un servidor. Cubre el setup del entorno con IntelliJ, la API de Spigot/Paper, manejo de eventos, creación de comandos, acceso a la configuración y deployment. No necesitas experiencia previa en desarrollo de Minecraft.
com.tunombre — ArtifactId: MiPrimerPluginEdita el archivo pom.xml que se generó. Reemplaza el contenido con:
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.tunombre</groupId>
<artifactId>MiPrimerPlugin</artifactId>
<version>1.0.0</version>
<packaging>jar</packaging>
<repositories>
<repository>
<id>papermc</id>
<url>https://repo.papermc.io/repository/maven-public/</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>io.papermc.paper</groupId>
<artifactId>paper-api</artifactId>
<version>1.21.4-R0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>21</source>
<target>21</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
Crea la carpeta src/main/resources/ y dentro el archivo plugin.yml. Este archivo le dice al servidor qué es tu plugin:
name: MiPrimerPlugin
version: 1.0.0
main: com.tunombre.MiPrimerPlugin
api-version: '1.21'
author: TuNombre
description: Mi primer plugin de Minecraft
commands:
hola:
description: Saluda al jugador
usage: /hola
permission: miplugin.hola
permissions:
miplugin.hola:
description: Permite usar /hola
default: true
Crea el archivo Java en src/main/java/com/tunombre/MiPrimerPlugin.java:
package com.tunombre;
import org.bukkit.plugin.java.JavaPlugin;
public class MiPrimerPlugin extends JavaPlugin {
@Override
public void onEnable() {
getLogger().info("MiPrimerPlugin activado correctamente!");
// Registrar el listener de eventos
getServer().getPluginManager().registerEvents(new MisEventos(this), this);
// Registrar el comando /hola
getCommand("hola").setExecutor(new ComandoHola());
}
@Override
public void onDisable() {
getLogger().info("MiPrimerPlugin desactivado.");
}
}
Crea MisEventos.java en el mismo paquete. Los listeners reciben notificaciones cuando pasan cosas en el servidor:
package com.tunombre;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerDeathEvent;
import org.bukkit.event.block.BlockBreakEvent;
public class MisEventos implements Listener {
private final MiPrimerPlugin plugin;
public MisEventos(MiPrimerPlugin plugin) {
this.plugin = plugin;
}
// Se ejecuta cuando un jugador entra al servidor
@EventHandler
public void onPlayerJoin(PlayerJoinEvent event) {
event.getPlayer().sendMessage("§aiBienvenido al servidor, §e" + event.getPlayer().getName() + "§a!");
}
// Se ejecuta cuando un jugador muere
@EventHandler
public void onPlayerDeath(PlayerDeathEvent event) {
event.getDeathMessage( "\u00a7c" + event.getEntity().getName() + " murió. §f¡Qué mal!");
}
// Se ejecuta cuando se rompe un bloque
@EventHandler
public void onBlockBreak(BlockBreakEvent event) {
// Cancelar el evento niega la acción completamente:
// event.setCancelled(true);
plugin.getLogger().info(event.getPlayer().getName() +
" rompió " + event.getBlock().getType());
}
}
Crea ComandoHola.java:
package com.tunombre;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
public class ComandoHola implements CommandExecutor {
@Override
public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
// Verificar que lo ejecuta un jugador (no la consola)
if (!(sender instanceof Player player)) {
sender.sendMessage("Este comando solo lo pueden usar jugadores.");
return true;
}
if (args.length == 0) {
player.sendMessage("§aHola, §e" + player.getName() + "§a!");
} else {
// /hola [mensaje]
String mensaje = String.join(" ", args);
player.sendMessage("§e" + player.getName() + " dice: §f" + mensaje);
}
return true; // retornar true = comando ejecutado correctamente
}
}
Los plugins pueden leer y escribir configuración:
// En onEnable() de la clase principal:
// Crea el config.yml si no existe
saveDefaultConfig();
// Leer valores
String mensaje = getConfig().getString("mensaje-bienvenida", "Bienvenido!");
boolean modoDebug = getConfig().getBoolean("debug", false);
int limiteJugadores = getConfig().getInt("max-jugadores", 20);
// Guardar/modificar config en runtime
getConfig().set("ultima-actualizacion", System.currentTimeMillis());
saveConfig();
// Recargar desde disco
reloadConfig();
Y en src/main/resources/config.yml:
mensaje-bienvenida: "Bienvenido al servidor!"
debug: false
max-jugadores: 20
.jar en target/MiPrimerPlugin-1.0.0.jar/plugins/ de tu servidor[MiPrimerPlugin] MiPrimerPlugin activado correctamente!@EventHandler(priority = EventPriority.HIGH) si tu listener necesita ejecutarse tras otros pluginsBukkit.getScheduler().runTaskAsynchronously() para no bloquear el main threadPlaceholderAPI para integrar tus datos en otros plugins de chat/scoreboardgetLogger().warning() o getLogger().info() — los logs aparecen en consolaSube tu plugin a un servidor Paper 1.21.11 en segundos. Plan gratuito disponible, sin configuración de servidor.
🎮 Ver planes → 🔌 Instalar Plugins