Для тех, кто немного знает Java и хочет написать свой первый плагин под Paper. Соберём проект на Gradle, сделаем сообщение при входе и команду /hello, запустим всё на тестовом сервере.
В settings.gradle.kts достаточно строки rootProject.name = "hello-cloud".
paper-api подключается как compileOnly: API уже есть на сервере, класть его в ваш jar не нужно. Версию API и minecraftVersion ставьте под версию своего сервера. run-paper - Gradle-плагин, который скачивает Paper и запускает тестовый сервер с вашим плагином, свежую версию run-paper смотрите в Gradle Plugin Portal.
main - полный путь к главному классу. api-version говорит серверу, под какую версию API написан плагин. Без него Paper считает плагин старым и включает режим совместимости.
onEnable вызывается при запуске плагина, здесь регистрируются слушатель событий и обработчик команды. Имя в getCommand должно совпадать с командой из plugin.yml, иначе получите NullPointerException.
В Paper текст - это компоненты Adventure, а не строки с цветовыми кодами. joinMessage заменяет стандартное сообщение о входе, hasPlayedBefore отличает новичка.
return true значит «команда обработана». Если вернуть false, игрок увидит строку usage из plugin.yml.
build кладёт готовый jar в build/libs, его можно копировать в plugins любого сервера. runServer запускает Paper в папке run уже с вашим плагином. Если при первом запуске сервер остановится и попросит принять EULA, поставьте eula=true в run/eula.txt и запустите снова. На Windows вместо ./gradlew пишется gradlew.bat.
Вопросы по теме — пишите ниже, ответим.
Что понадобится
- JDK 21: Paper под 1.21.x работает на Java 21.
- IntelliJ IDEA, Community хватает. Есть плагин Minecraft Development, который создаёт каркас проекта, но здесь всё руками, чтобы было видно, что где.
- Gradle отдельно ставить не нужно, IDEA создаст проект с Gradle Wrapper.
Код
hello-cloud/
settings.gradle.kts
build.gradle.kts
src/main/java/ru/example/hellocloud/HelloCloud.java
src/main/java/ru/example/hellocloud/JoinListener.java
src/main/java/ru/example/hellocloud/HelloCommand.java
src/main/resources/plugin.ymlbuild.gradle.kts
Код
plugins {
java
id("xyz.jpenilla.run-paper") version "2.3.1"
}
group = "ru.example"
version = "1.0.0"
repositories {
mavenCentral()
maven("https://repo.papermc.io/repository/maven-public/")
}
dependencies {
compileOnly("io.papermc.paper:paper-api:1.21.4-R0.1-SNAPSHOT")
}
java {
toolchain.languageVersion.set(JavaLanguageVersion.of(21))
}
tasks {
runServer {
minecraftVersion("1.21.4")
}
}plugin.yml
Код
name: HelloCloud
version: '1.0.0'
main: ru.example.hellocloud.HelloCloud
api-version: '1.21'
commands:
hello:
description: Поприветствовать игрока
usage: /hello
permission: hellocloud.hello
permissions:
hellocloud.hello:
default: trueГлавный класс
Код
package ru.example.hellocloud;
import org.bukkit.plugin.java.JavaPlugin;
public final class HelloCloud extends JavaPlugin {
@Override
public void onEnable() {
getServer().getPluginManager().registerEvents(new JoinListener(), this);
getCommand("hello").setExecutor(new HelloCommand());
getLogger().info("HelloCloud включён");
}
}Слушатель входа
Код
package ru.example.hellocloud;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerJoinEvent;
public final class JoinListener implements Listener {
@EventHandler
public void onJoin(PlayerJoinEvent event) {
Player player = event.getPlayer();
event.joinMessage(Component.text("+ " + player.getName(), NamedTextColor.GREEN));
if (!player.hasPlayedBefore()) {
player.sendMessage(Component.text("Добро пожаловать! Напиши /hello", NamedTextColor.GOLD));
}
}
}Команда
Код
package ru.example.hellocloud;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
public final class HelloCommand implements CommandExecutor {
@Override
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
if (!(sender instanceof Player player)) {
sender.sendMessage(Component.text("Команда только для игроков"));
return true;
}
player.sendMessage(Component.text("Привет, " + player.getName() + "!", NamedTextColor.AQUA));
return true;
}
}Сборка и запуск
Код
./gradlew build
./gradlew runServerЧто дальше
- Не тестируйте через /reload, перезапускайте сервер: reload оставляет в памяти старые классы и слушатели.
- Настройки в config.yml: saveDefaultConfig() в onEnable и getConfig() для чтения.
- В новых версиях Paper есть регистрация команд через Brigadier с подсказками аргументов, к ней стоит перейти, когда освоитесь.
Вопросы по теме — пишите ниже, ответим.