| title | paperweight-userdev |
|---|---|
| description | A guide on how to use the paperweight-userdev Gradle plugin to access internal code. |
| slug | paper/dev/userdev |
paperweight is the name of Paper's custom build tooling. The paperweight-userdev Gradle plugin part of that provides access to internal code (also known as NMS) during development.
:::note
This guide is written using the Gradle Kotlin DSL and assumes you have some basic knowledge of Gradle. If you want to see a fully-functioning plugin that uses paperweight-userdev, check out this example plugin.
:::
This is the only supported way of accessing server internals, as redistributing the server JAR is against the Minecraft EULA and general license assumption. Even if you manually depended on the patched server, you would be hindering other people working on your project and would be missing deployed API javadocs/sources in your IDE.
On top of that, Spigot and pre-1.20.5 Paper versions still use Spigot mappings, which are a mix of obfuscated fields/methods and mapped as well as custom named classes. This can make it hard to work with in a development environment. This plugin lets you use fully deobfuscated types, names, and fields during development, and then remaps your plugin, so it can still be used with the obfuscated server. However, this does not apply to reflection. Look at something like this library to be able to use non-obfuscated names in reflection if you want to support obfuscated servers.
:::note[Removal of obfuscations in 26.1]
From Minecraft version 26.1 onwards, Paper no longer supports obfuscated plugins due to Mojang themselves removing obfuscation of their server JAR. As Minecraft now ships unobfuscated, there are no 26.1 Spigot mappings to obfuscate to. For this reason, the reobfuscation function no longer works for dev bundles for 26.1+.
:::
Add the plugin to your build.gradle.kts file.
plugins {
id("io.papermc.paperweight.userdev") version "\{LATEST_USERDEV_RELEASE}"
}:::note[Gradle Version]
Please make sure you are using the latest stable version of Gradle. For more information on upgrading Gradle, check out the Gradle Wrapper documentation.
:::
The latest version of paperweight-userdev supports dev bundles for Minecraft 1.17.1 and newer, so it's best practice to keep it up to date!
Only the latest version of paperweight-userdev is officially supported, and we will ask you to update first if you are having problems with old versions.
Furthermore, if you are having issues with paperweight-userdev, you should ask in the
#build-tooling-help channel in our dedicated Discord server!
:::note[Snapshots]
paperweight-userdev SNAPSHOT (pre-release) versions are only available through Paper's Maven repository.
pluginManagement {
repositories {
gradlePluginPortal()
maven("https://repo.papermc.io/repository/maven-public/")
}
}:::
If you try to load your Gradle project now, you will receive an error saying you have to declare
a dev bundle dependency. You can do that by adding to your dependencies block in your build.gradle.kts
file.
dependencies {
// Other Dependencies
paperweight.paperDevBundle("\{LATEST_PAPER_RELEASE}.build.+")
}:::tip
You should remove any dependency on the Paper API, as the dev bundle includes that.
:::
:::note[Configuring the Java toolchain for userdev setup]
A given dev bundle may not always support the Java toolchain Gradle is configured to use
(whether configured explicitly or inherited from the Gradle runtime).
If you are getting an error during the execution of paperweightUserdevSetup (especially patch application failures),
you can try setting paperweight's javaLauncher property to a different Java version.
For example, with 1.17.1:
paperweight {
javaLauncher = javaToolchains.launcherFor {
// Example scenario:
// Paper 1.17.1 was originally built with JDK 16 and the bundle
// has not been updated to work with 21+ (but we want to compile with a 25 toolchain)
languageVersion = JavaLanguageVersion.of(17)
}
}Among others, the multi-project branch of the PaperMC/paperweight-test-plugin makes use of this feature.
:::
:::danger
Since Minecraft version 26.1, Paper no longer supports remapping your plugin to Spigot runtime mappings. This section is kept as a reference for older versions, however reobfuscated plugins will not work from Paper 26.1 onwards!
:::
The reobfJar task creates a plugin JAR that is re-obfuscated to Spigot's runtime mappings.
This means it will work on standard Paper servers.
The output will be inside the build/libs folder. The JAR whose filename includes -dev
is Mojang-mapped (not re-obfuscated) and will not work on non-Paper servers.
:::note[Shadow]
If you have the shadow Gradle plugin applied in your build script, paperweight-userdev will
detect that and use the shaded JAR as the input for the reobfJar task.
The -dev-all.jar file in build/libs is the shaded, but not re-obfuscated JAR.
:::
You can make the reobfJar task run on the default build task with:
tasks.assemble {
dependsOn(tasks.reobfJar)
}As of 1.20.5, Paper ships with a Mojang-mapped runtime instead of re-obfuscating the server to Spigot mappings. Additionally, CraftBukkit classes will no longer be relocated into a versioned package. This requires plugins to be deobfuscated before loading when necessary.
Most of this process is done automatically by paperweight, but there are some important things to know when using server internals (or "NMS") from now on.
- By default, all Spigot/Bukkit plugins will be assumed to be Spigot-mapped if they do not specify their mappings namespace in the manifest. The other way around, all Paper plugins will be assumed to be Mojang-mapped if they do not specify their mappings namespace in the manifest.
- Spigot-mapped plugins will need to be deobfuscated on first load, Mojang-mapped plugins will not.
:::note
This is the preferred option, as the one-time plugin remapping process during server startup will be skipped and it may allow you to keep version compatibility across smaller updates without changes or additional modules. However, this makes your plugin incompatible with Spigot servers.
:::
If you want your main output to use Mojang mappings, you need to remove all dependsOn(reobfJar) lines and add the following code to your build script:
paperweight.reobfArtifactConfiguration = io.papermc.paperweight.userdev.ReobfArtifactConfiguration.MOJANG_PRODUCTIONIf you want your main output to use Spigot mappings, add the following code to your build script:
paperweight.reobfArtifactConfiguration = io.papermc.paperweight.userdev.ReobfArtifactConfiguration.REOBF_PRODUCTIONThis is useful for plugins that have loaders for both Spigot and Paper and want to keep compatibility with both.
:::note
If you are using Gradle with the Groovy DSL, you should instead access the fields via static methods like getMOJANG_PRODUCTION().
:::