If you need to access NMS classes from inside your Spigot plugin, it is a very good idea to use the so called Mojang mappings.
Disclaimer: This post is written for 1.20.4. If you use another version, you of course have to replace every occurance of “1.20.4” with the version you actually use.
What are Mojang mappings?
Mojang is obfuscating certain method and field names before shipping Minecraft. That means you will have a very bad experience when you want to access NMS in the classic way, because most fields are simply called “a”, “b”, “c”, etc. Fortunately, Mojang decided to release their obfuscation map, which means that you can actually use the same names that the Mojang developers are using.
How to use Mojang mappings
First of all, you have to run BuildTools and tell it to get yourself a nice, fresh compiled spigot version with the Mojang mappings:
java -jar BuildTools.jar --rev 1.20.4 --remapped
It does not matter in which folder you run BuildTools as long as it’s on the same computer that you use to code your plugin. BuildTools will install all dependencies to your local maven repository. You can now adjust your build file (pom.xml when using Maven, or build.gradle/build.gradle.kts when using Gradle) to use the Mojang mapped .jar, and to reobfuscate all needed method/class calls at compile time.
When using Maven
When using Maven, you can use the official specialsource-maven-plugin which is available on Maven Central. We’ll also change our dependency to use spigot
instead of spigot-api
with classifier remapped-mojang
:
<build> <plugins> <plugin> <groupId>net.md-5</groupId> <artifactId>specialsource-maven-plugin</artifactId> <version>2.0.2</version> <executions> <execution> <phase>package</phase> <goals> <goal>remap</goal> </goals> <id>remap-obf</id> <configuration> <srgIn>org.spigotmc:minecraft-server:1.20.4-R0.1-SNAPSHOT:txt:maps-mojang</srgIn> <reverse>true</reverse> <remappedDependencies>org.spigotmc:spigot:1.20.4-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.20.4-R0.1-SNAPSHOT:csrg:maps-spigot</srgIn> <remappedDependencies>org.spigotmc:spigot:1.20.4-R0.1-SNAPSHOT:jar:remapped-obf</remappedDependencies> </configuration> </execution> </executions> </plugin> </plugins> </build> [...] <dependencies> <dependency> <groupId>org.spigotmc</groupId> <artifactId>spigot</artifactId> <version>1.20.4-R0.1-SNAPSHOT</version> <scope>provided</scope> <classifier>remapped-mojang</classifier> <!-- Important! --> </dependency> </dependencies>
Obviously, you might want to adjust “1.20.4” when you want to use a different spigot version (e.g. change it from “1.20.4” to “1.19.4” in both, your <dependency> section, and in all 4 places it appears in the <plugin> section). You are now fine to go to use Mojang mappings. Maven will automatically “reobfuscate” your code so it’ll be compatible with the actual server software.
When using Gradle
For Gradle, there is no official remapping plugin available from SpigotMC, but we can just use one of the community ones. I suggest to use patrick-choe’s mojang-spigot-remapper. We’ll also need to add mavenCentral() (for transitive dependencies) and mavenLocal() to our repositories so that Gradle can find our spigot dependency (again, we’ll use the artifact spigot
with classifier remapped-mojang
instead of the regular spigot-api
), and then we’ll make the build
task depend on the remap
task so that we don’t have to run it manually everytime:
// Using Kotlin DSL: plugins { java id("io.github.patrick.remapper") version "1.4.0" } // ... repositories { mavenCentral() mavenLocal() } dependencies { compileOnly("org.spigotmc:spigot:1.20.4-R0.1-SNAPSHOT:remapped-mojang") } java { toolchain { languageVersion.set(JavaLanguageVersion.of(17)) // Spigot 1.18+ requires Java 17+ } } tasks.remap { version.set("1.20.4") } tasks.build { dependsOn(tasks.remap) }
If you’re using Groovy, then you’ll obviously have to adjust that code a bit.
That’s it!
You’re done! You can now use Mojang Mappings in your code and don’t have to rely on those stupid obfuscated method names anymore.
You’ll notice that some classes or methods can’t be found anymore if you’re switching from the old Spigot Mappings. Check out this blog post to see how you can find out the new class, method and field names.
If you’re writing your plugin to be compatible with more than one NMS version, you want to create a multi-module project instead. For Maven, you can check out this blog post.
Join my Discord Server for feedback or support. Just check out the channel #programming-help
🙂
Super Cool!
ya know, google doesn’t turn up particularly helpful results from spigot, thanks for the post 🙂
You’re welcome!
Saving my life every single time
Hi, I don’t know if you give support here but this for some reason doesn’t work for me… I keep getting this error no matter how many clean installs I do or reloads:
Could not find artifact org.spigotmc:spigot:jar:remapped-mojang:1.20.4-R0.1-SNAPSHOT in spigot repo (https://hub.spigotmc.org/nexus/content/repositories/snapshots/)
Which basically means it’s not finding the files anywhere… I think I did every step
You haven’t ran BuildTools as described in the post:
java -jar BuildTools.jar --rev 1.20.4 --remapped
Hey so after it compiles, which target jar should you use?
-VanaByte-1.0-shaded.jar
-VanaByte-1.0-remapped-obf.jar
-VanaByte-1.0-remapped.jar
-VanaByte-1.0.jar
-original-VanaByte-1.0.jar
VanaByte-1.0.jar
It seems that you have forgotten to say that this implementation is for when using the InteliJ IDE.
The section would be different when using Eclipse (for example).
What do you mean? It’s independant of any IDE. It only requires changes in your maven pom.xml or gradle build file
* Configuration Section which points to a local directory