Удобная работа с NMS на Paper 1.17+ (paperweight)

Руководство Удобная работа с NMS на Paper 1.17+ (paperweight)

Поддерживаемые версии
  1. 1.17
  2. 1.18
  3. 1.19
  4. 1.20
Здравствуйте!

Сразу хочу показать вам пример кода на NMS с использованием технологии paperweight:
1636985827253.png

Как вы можете увидеть, больше нет никаких однобуквенных названий. Весь код читабельный и выглядит так, будто это и вовсе не NMS. Тем не менее, это он - обратите внимание на импорты.

Заинтересовало? Тогда продолжаем...

Предисловие:
Использование NMS - это крайняя мера, к которой стоит прибегать только в крайнем случае. Если у какой-то функции есть апи - лучше использовать это апи.
Если же нужной вам функции в апи нет - стоит предложить её разработчикам Spigot или Paper на гитхабе данных проектов.

Для начала предлагаю вам ознакомиться с моей темой о том, что такое маппинги:
http://rubukkit.org/threads/165824/

Итак, с версии 1.14 Mojang начали публиковать официальные маппинги, включающие в себя всё кроме локальных переменных методов.
На версии 1.17 мы наконец-то дождались внедрения этих маппингов в Spigot и Paper 1.17.
Настало время использовать их в полную силу!

Использовать будем следующие технологии:
- Среда разработки Intellij IDEA
- Система сборки Gradle (с использованием Groovy DSL или Kotlin DSL)
- Ядро Paper/Purpur/Folia 1.17 или новее
- paperweight - система сборки ядра Paper и плагинов с использованием маппингов Mojang

Данная статья подходит исключительно для проектов с системой сборки Gradle. Тут вы найдёте необходимо информацию по переводу проекта с Maven на Gradle: https://docs.gradle.org/current/userguide/migrating_from_maven.html

Но если же вы хотите использовать Maven и дальше, то вам придётся разбираться самостоятельно. Я лишь дам наводку.

Зависимость с NMS (спасибо imDaniX за наводку):
https://docs.codemc.io/faq/#what-is-the-nms-maven-repository
PHP:
<dependency>
    <groupId>org.spigotmc</groupId>
    <artifactId>spigot</artifactId>
    <version>1.19.2-R0.1-SNAPSHOT</version>
    <classifier>remapped-mojang</classifier>
    <scope>provided</scope>
</dependency>

При необходимости вы можете самостоятельно добавить зависимость в локальный мавен- репозиторий, для этого используется BuildTools с флагом "--remapped".

Подробности можно найти тут: https://blog.jeff-media.com/nms-use-mojang-mappings-for-your-spigot-plugins/

Для применения маппинов при сборке можно использовать SpecialSource:
https://github.com/md-5/SpecialSource
PHP:
<plugin>
    <groupId>net.md-5</groupId>
    <artifactId>specialsource-maven-plugin</artifactId>
    <version>1.2.2</version>
    <executions>
        <execution>
            <phase>package</phase>
            <goals>
                <goal>remap</goal>
            </goals>
            <id>remap-obf</id>
            <configuration>
                <srgIn>org.spigotmc:minecraft-server:1.19.2-R0.1-SNAPSHOT:txt:maps-mojang</srgIn>
                <reverse>true</reverse>
                <remappedDependencies>org.spigotmc:spigot:1.19.2-R0.1-SNAPSHOT:jar:remapped-mojang</remappedDependencies>
                <remappedArtifactAttached>true</remappedArtifactAttached>
                <remappedClassifierName>remapped-obf</remappedClassifierName>
            </configuration>
        </execution>
        <execution>
            <phase>package</phase>
            <goals>
                <goal>remap</goal>
            </goals>
            <id>remap-spigot</id>
            <configuration>
                <inputFile>${project.build.directory}/${project.artifactId}-${project.version}-remapped-obf.jar</inputFile>
                <srgIn>org.spigotmc:minecraft-server:1.19.2-R0.1-SNAPSHOT:csrg:maps-spigot</srgIn>
                <remappedDependencies>org.spigotmc:spigot:1.19.2-R0.1-SNAPSHOT:jar:remapped-obf</remappedDependencies>
            </configuration>
        </execution>
    </executions>
</plugin>

Помимо этого, существует плагин, позволяющий использовать paperweight на мавене. Спасибо Huze за ссылку:
https://github.com/Alvinn8/paper-nms-maven-plugin

Внимание!
Я не гарантирую оперативное обновление туториала. Пожалуйста, убедитесь, что используете актуальные версии плагинов, библиотек и прочих зависимостей. Также при необходимости ознакомьтесь с официальной документацией и сообщите в этой теме об изменениях. Полноценного официального гайда по paperweight до сих пор нет, но есть официальная документация репозитория:
https://github.com/PaperMC/paperweight

Приступаем.

1) Для начала необходимо определиться, какую систему сборки вы хотите использовать. Paperweight поддерживает только Gradle, поэтому вы можете использовать либо Groovy DSL, либо Kotlin DSL. В статье указаны примеры для обеих систем. Если же вы не знакомы с понятием "система сборки" - вам придётся изучить эту тему самостоятельно.

2) Далее нужно убедиться, что в нашем проекте используется JDK 17 или новее.
Если у вас возникнут с этим вопросы или сложности - привожу полный список мест, в которых может понадобиться указать целевые версии Java. Данный список поможет вам решить ошибки вида "java: error: release version 17 not supported".
1) В параметрах сборщика:
PHP:
compileJava {
    sourceCompatibility = targetCompatibility = JavaVersion.VERSION_17
}
PHP:
java {
    sourceCompatibility = JavaVersion.VERSION_17
    targetCompatibility = JavaVersion.VERSION_17
    toolchain {
        languageVersion.set(JavaLanguageVersion.of(17))
    }
}

tasks.withType<JavaCompile> {
    options.release.set(17)
}
2) Project Structure > Platform Settings > SDKs
3) Project Structure > Project Settings > Project > Project SDK
4) Project Structure > Project Settings > Project > Project language level
5) Project Structure > Project Settings > Modules > Sources > Language level
6) Project Structure > Project Settings > Modules > Dependencies > Module SDK
7) Settings > Build, Execution, Deployment > Java Compiler > Project bytecode version
8) Settings > Build, Execution, Deployment > Java Compiler > Module > Target bytecode version
9) Settings > Build, Execution, Deployment > Build Tools > Gradle > Gradle JVM

3) Следующим пунктом необходимо проверить, что в нашем проекте используется Gradle 7-й версии или новее. На данный момент последняя версия Gradle - это 8.1.1. Следить за релизами можно тут.
Версия 7+ требуется для раз для поддержки Java 17 и новее, однако рекомендую придерживаться именно 8+, поэтому именно под неё указаны все куски кода.

Версия Gradle указывается в файле /gradle/wrapper/gradle-wrapper.properties в строке distributionUrl.
Кстати, папку wrapper'а не рекомендуется добавлять в .gitignore проекта, а загружать в гит вместе со всеми исходниками.

После выполнения 3-го пункта рекомендую вам убедиться, что ваш плагин корректно собирается и запускается на сервере с использованием Java 17+.

4) Последний этап подготовки. Необходимо удалить из проекта все зависимости от всех компонентов ядра: nms/craftbukkit/bukkit/spigot/paper - абсолютно всё. Не имеет значения, подключена ли зависимость из maven-репозитория или локальным jar-файлом. Это нужно для того, чтобы в дальнейшем избежать различных разногласий при работе с классами ядра и не ловить в рантайме NoClassDefFoundError, NoSuchMethodError и прочие.

Пора переходить непосредственно к подключению paperweight. Предлагаю обратить внимание на примеры:

Пример простого paper-плагина на Kotlin DSL:
https://github.com/PaperMC/paperweight-test-plugin
Всегда актуальная версия, обновляется командой PaperMC.

Пример простого paper-плагина на Groovy DSL:
https://github.com/Dymeth/paperweight-test-plugin-groovy
Мой форк, обновляется по мере возможностей.

Не забывайте ставить звёздочки!
Я помогу вам и разберу каждый необходимый компонент настройки.

5) Для начала подключаем Gradle-плагин paperweight к проекту. Делается это в блоке plugins в файле build.gradle (build.gradle.kts для Kotlin DSL):
PHP:
plugins {
  id("java-library")
  id("io.papermc.paperweight.userdev") version "1.5.5"
}
Блок plugins должен располагаться, как правило, в самом верху файла.

Список версий paperweight находится тут.
Указывать репозиторий плагина не требуется, поскольку релизы paperweight находятся в Gradle plugin portal, который используется по-умолчанию.

Как видно из примера, мы также подключили плагин java-library. Указывать версию у него не требуется. Данный плагин требуется для указания параметров java, для работы с задачами сборщика и другого базового функционала.

Помимо этого, по желанию вы можете использовать плагин run-paper от jpenilla, позволяющий для тестирования своего плагина запускать сервер на базе Paper при помощи задач runServer и runMojangMappedServer:
PHP:
id("xyz.jpenilla.run-paper") version "2.1.0"
В рамках текущей статьи это НЕобязательный шаг.

6) Наконец-то мы можем добавить в наш проект зависимость для подключения ядра вместе с заветным NMS с маппингами:
PHP:
dependencies {
  paperweightDevelopmentBundle("io.papermc.paper:dev-bundle:1.20-R0.1-SNAPSHOT")
}
PHP:
dependencies {
  paperDevBundle("1.20-R0.1-SNAPSHOT")
}

Groovy DSL - build.gradle:
PHP:
paperweightDevelopmentBundle("dev.folia:dev-bundle:1.20-R0.1-SNAPSHOT")

Kotlin DSL - build.gradle.kts:
PHP:
paperweight.foliaDevBundle("1.20-R0.1-SNAPSHOT")
Groovy DSL - build.gradle:
PHP:
paperweightDevelopmentBundle("com.example.paperfork:dev-bundle:1.20-R0.1-SNAPSHOT")

Kotlin DSL - build.gradle.kts:
PHP:
paperweight.devBundle("com.example.paperfork", "1.20-R0.1-SNAPSHOT")

После этого не забываем обновить зависимости проекта.

Готово! На данном этапе вы уже можете писать плагин с использованием NMS с маппингами от Mojang.

Но есть несколько подводных камней, о которых вам стоит знать:

1) Плагин, собранный под одну версию ядра, не обязан работать на другой. Дело в том, что в самом ядре, которое используется на серверах, по-прежнему находится обфусцированный NMS. Фактически при сборке вашего плагина paperweight применяет к коду маппинги, чтобы привести код в обфусцированный вид. Т.е. обфускация отсутствует исключительно на этапе разработки. Это сделано с целью избежать юридических проблем с Microsoft.
Таким образом, если вы хотите добавить в свой плагин поддержку разных версий ядра - вам придётся создавать несколько модулей с разными версиями зависимостей paperweightDevelopmentBundle (для Groovy DSL) или paperDevBundle (для KotlinDSL). Но сам я не проверял, работает ли такая структура.

2) При использовании нескольких модулей в проекте вы, вероятно, столкнётесь с тем, что Gradle просто не позволит подключить paperweight в этих самых модулях. Насколько мне известно, это связано с недоработкой Gradle: https://github.com/gradle/gradle/issues/14697
Решение данной проблемы элементарное - достаточно удалить указание версии из дочерних модулей:
PHP:
id("io.papermc.paperweight.userdev")

После чего перенести указание версии плагина в скрипт сборки главного (родительского) модуля следующим образом:
PHP:
id("io.papermc.paperweight.userdev") version "1.5.5" apply false
Напоминаю, что блок plugins должен находиться в верхней части файла.

3) Ошибка "The paperweight development bundle you are attempting to use is of data version '1', but the currently running version of paperweight only supports data version '2'"
Данная проблема связана то ли с багом в Gradle, то ли в paperweight. Так или иначе, мне удалось решить её банальным удалением директории %userprofile%/.gradle/caches/<версия>/md-rule
Перед удалением рекомендую закрыть все окна IDE

На этом всё. Материал подготовлен Dymeth.

Есть вопросы или дополнения?
Добро пожаловать в обсуждение
Автор
Dymeth
Просмотры
2,972
Первый выпуск
Обновление
Оценка
5.00 звёзд 1 оценок

Поделиться ресурсом

Последние обновления

  1. Начиная с версии Paper 1.20.5 больше нет необходимости использовать задачу reobfJar

    Начиная с версии Paper 1.20.5 больше нет необходимости использовать задачу reobfJar
  2. Актуализировал всё

    Обновил первый пост: - указал актуальные версии плагинов и зависимостей - удалил необходимость...
  3. Больше информации по Maven и Groovy

    Обновил пост: - Добавил спойлер для пользователей мавен со всеми предложенными ссылками и...

Последние рецензии

Отличный гайд, понятно все рассказано, да и сам paperweight классная штука.
Назад
Сверху Снизу