- Поддерживаемые версии
- 1.17
- 1.18
- 1.19
- 1.20
Здравствуйте!
Сразу хочу показать вам пример кода на NMS с использованием технологии paperweight:
Как вы можете увидеть, больше нет никаких однобуквенных названий. Весь код читабельный и выглядит так, будто это и вовсе не 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
Внимание!
Я не гарантирую оперативное обновление туториала. Пожалуйста, убедитесь, что используете актуальные версии плагинов, библиотек и прочих зависимостей. Также при необходимости ознакомьтесь с официальной документацией и сообщите в этой теме об изменениях. Полноценного официального гайда по paperweight до сих пор нет, но есть официальная документация репозитория:
https://github.com/PaperMC/paperweight
Приступаем.
1) Для начала необходимо определиться, какую систему сборки вы хотите использовать. Paperweight поддерживает только Gradle, поэтому вы можете использовать либо Groovy DSL, либо Kotlin DSL. В статье указаны примеры для обеих систем. Если же вы не знакомы с понятием "система сборки" - вам придётся изучить эту тему самостоятельно.
2) Далее нужно убедиться, что в нашем проекте используется JDK 17 или новее.
Если у вас возникнут с этим вопросы или сложности - привожу полный список мест, в которых может понадобиться указать целевые версии Java. Данный список поможет вам решить ошибки вида "java: error: release version 17 not supported".
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):
Блок plugins должен располагаться, как правило, в самом верху файла.
Список версий paperweight находится тут.
Указывать репозиторий плагина не требуется, поскольку релизы paperweight находятся в Gradle plugin portal, который используется по-умолчанию.
Как видно из примера, мы также подключили плагин java-library. Указывать версию у него не требуется. Данный плагин требуется для указания параметров java, для работы с задачами сборщика и другого базового функционала.
Помимо этого, по желанию вы можете использовать плагин run-paper от jpenilla, позволяющий для тестирования своего плагина запускать сервер на базе Paper при помощи задач runServer и runMojangMappedServer:
В рамках текущей статьи это НЕобязательный шаг.
6) Наконец-то мы можем добавить в наш проект зависимость для подключения ядра вместе с заветным NMS с маппингами:
После этого не забываем обновить зависимости проекта.
Готово! На данном этапе вы уже можете писать плагин с использованием NMS с маппингами от Mojang.
Но есть несколько подводных камней, о которых вам стоит знать:
1) Плагин, собранный под одну версию ядра, не обязан работать на другой. Дело в том, что в самом ядре, которое используется на серверах, по-прежнему находится обфусцированный NMS. Фактически при сборке вашего плагина paperweight применяет к коду маппинги, чтобы привести код в обфусцированный вид. Т.е. обфускация отсутствует исключительно на этапе разработки. Это сделано с целью избежать юридических проблем с Microsoft.
Таким образом, если вы хотите добавить в свой плагин поддержку разных версий ядра - вам придётся создавать несколько модулей с разными версиями зависимостей paperweightDevelopmentBundle (для Groovy DSL) или paperDevBundle (для KotlinDSL). Но сам я не проверял, работает ли такая структура.
2) При использовании нескольких модулей в проекте вы, вероятно, столкнётесь с тем, что Gradle просто не позволит подключить paperweight в этих самых модулях. Насколько мне известно, это связано с недоработкой Gradle: https://github.com/gradle/gradle/issues/14697
Решение данной проблемы элементарное - достаточно удалить указание версии из дочерних модулей:
После чего перенести указание версии плагина в скрипт сборки главного (родительского) модуля следующим образом:
Напоминаю, что блок 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'"
На этом всё. Материал подготовлен Dymeth.
Есть вопросы или дополнения?
Добро пожаловать в обсуждение
Сразу хочу показать вам пример кода на NMS с использованием технологии paperweight:
Как вы можете увидеть, больше нет никаких однобуквенных названий. Весь код читабельный и выглядит так, будто это и вовсе не 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
При необходимости вы можете самостоятельно добавить зависимость в локальный мавен- репозиторий, для этого используется BuildTools с флагом "--remapped".
Подробности можно найти тут: https://blog.jeff-media.com/nms-use-mojang-mappings-for-your-spigot-plugins/
Для применения маппинов при сборке можно использовать SpecialSource:
https://github.com/md-5/SpecialSource
Помимо этого, существует плагин, позволяющий использовать paperweight на мавене. Спасибо Huze за ссылку:
https://github.com/Alvinn8/paper-nms-maven-plugin
Но если же вы хотите использовать 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) В параметрах сборщика:
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
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)
}
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"
}
Список версий 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:
Kotlin DSL - build.gradle.kts:
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:
Kotlin DSL - build.gradle.kts:
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
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
Перед удалением рекомендую закрыть все окна IDE
На этом всё. Материал подготовлен Dymeth.
Есть вопросы или дополнения?
Добро пожаловать в обсуждение