Announcement Important dev PSA: Future removal of CB package relocation

Future removal of CB package relocation + moving away from obfuscation at runtime​

If you are not a developer but a server owner, this might still be important for you. Check the bottom section on what action you might have to take.

Update: This change has been put into effect in 1.20.5, make sure you test with the latest Paper 1.20.5 builds.

As already announced before, at some point in the foreseeable future, we will remove the CraftBukkit package relocation (e.g. v1_20_R3). This may be as soon as 1.20.5, as we expect almost every plugin using internals to break due to major changes in vanilla anyways.

Note: This also includes testing of automated remapping of plugins to make them run on Mojang mapped servers, even if a plugin is compiled against the obfuscated class and method names (if you don't use any vanilla internals, this doesn't affect you). So even if you have already fixed CB package parsing, please check whether your plugins are able to run on this jar if they are using internals (or "nms").

Once these changes are present in stable Paper builds, you can expect a much better experience when using the often dreaded internals by using our userdev Gradle plugin. Most notably, small Minecraft updates will no longer unconditionally break your plugins.

How to make sure your plugin does not break​

If you reflect on CB classes
Easy, just don't try to parse the package version. The following will work on servers with and without CB relocation:
Java:
private static final String CRAFTBUKKIT_PACKAGE = Bukkit.getServer().getClass().getPackage().getName();

public static String cbClass(String className) {
    return CRAFTBUKKIT_PACKAGE + "." + className);
}

Class.forName(cbClass("entity.CraftBee"))

If you try to parse the server version
Do NOT do this:
Java:
String craftBukkitPackage = Bukkit.getServer().getClass().getPackage().getName();
// This is the *bad* part, including any other parsing of the version
String version = craftBukkitPackage.substring(craftBukkitPackage.lastIndexOf('.') + 1);
if (version.equals("v1_20_R3")) {
    // ...
} else {
  // Unsupported
}
Instead, use long-standing API:
Java:
// Paper method that was added in 2020
// Example value: 1.20.4
String minecraftVersion = Bukkit.getServer().getMinecraftVersion();

// Bukkit method that was added in 2011
// Example value: 1.20.4-R0.1-SNAPSHOT
String bukkitVersion = Bukkit.getServer().getBukkitVersion();

if (minecraftVersion.equals("1.20.4")) {
    // ...
} else {
  // Assume latest still works, or error as unsupported
  // Alternatively for extra compatibility, check if
  // the latest package version is valid by catching
  // ClassNotFoundException with: Class.forName("org.bukkit.craftbukkit.v1_20_R3.CraftServer")
}
The Minecraft version strings you can parse and evaluate to your heart's content. Another (less recommended) alternative is getting the server protocol version from Bukkit.getUnsafe.

As a server owner​

If you are running a somewhat recent server version with up-to-date plugins (!), you should also test whether your plugins are able to run on the test server jar also linked above. Please make sure not to use the server jar on your main servers, but to copy your plugin setup to a separate test server.

The error that plugin developers need to fix will look something like this:
[11:46:19] [Server thread/ERROR]: Error occurred while enabling PLUGINNAME v1 (Is it up to date?)
java.lang.ArrayIndexOutOfBoundsException: Index 3 out of bounds for length 3
at ...
Alternatively, they might log an error saying you are using an unknown or unsupported server version.

If any of your plugins start printing new errors like these and you have made sure that they are already up-to-date, please report the error with a link to this announcement to the relevant plugin authors.
 
Last edited by a moderator:
  • Like
  • Love
Reactions: EterNity and Camm
the hardness, obviously! personally I perfer the term softspoon

(the result is the same, we are just not calling it hard fork anymore to avoid scaring people that think we are gonna instantly break compatibility)
 
the hardness, obviously! personally I perfer the term softspoon

(the result is the same, we are just not calling it hard fork anymore to avoid scaring people that think we are gonna instantly break compatibility)
is paper going to break compatibility ever? if so will it be soon?
 
we will not promise to never break anything, that would be stupid (and is the reason the api is so meh right now)
we will promise to be careful with what we do, putting out test builds like this one, talking to the community, listening to feedback etc
and there will never be a big bang kinda thing where every plugin suddenly breaks (unless mojang does big changes that require that, but that is unlikely)
 
we will not promise to never break anything, that would be stupid (and is the reason the api is so meh right now)
we will promise to be careful with what we do, putting out test builds like this one, talking to the community, listening to feedback etc
and there will never be a big bang kinda thing where every plugin suddenly breaks (unless mojang does big changes that require that, but that is unlikely)
i meant break away from spigot
 
plugins are already not compatible with spigot if they use our api, that gap will only widen in the future. and yes, there will be a time when we will no longer consider spigot to be a direct upstream and work on vanilla directly. however, that will not have much impact on plugins. if spigot adds api we deem good, we can still merge it in, plus it will allow us to get paper updates out way quicker, like for pre releasing, so plugin devs (and to an extend, sevrer owners) will have a much better time
 
just like they do now. far down the road (talking about many years here) the apis might have diverged so far that that is not viable anymore, but I doubt spigot will last that long :)
 
  • Like
Reactions: ysl3000
I was recently made aware of this, when an update I made for a primarily Spigot plugin broke because of this inconsistency between Spigot and PaperMC. I am kind of surprised that this was done, especially with the listed 'solution' being to use the Minecraft version instead. The remapping version and the minecraft version are very much not the same however. There have been a couple cases in the past where a small Mojang bugfix bumped the Minecraft version, without changing the internals at all. As such, the internal/remapping version stayed the same, allowing an NMS-based plugin to stay working. If you followed the 'solution' suggested here, your NMS-based plugin would break at every new version (since it wouldn't have an implementation with a matching version) even if no actual changes were made to the internals. As such, Spigot, and a lot of plugins use the remapping version, which is more informative.

Is there truly no way to detect the remapping version in this new Paper update? I understand the CraftBukkit package has been relocated, but are there any other packages that still have the remapping information?
 
The remapping version and the minecraft version are very much not the same however.
Yes, absolutely. That's the point. Its completely arbitrary. It's meaningless, impossible to predict why that number has been increased.

What plugins should do is detect the presence of the methods they use, not some arbitrary numbers.

And no, there is no way to get that info, it doesn't exist anymore.
 
There have been a couple cases in the past where a small Mojang bugfix bumped the Minecraft version, without changing the internals at all.

And there have been many cases where mojang have changed a bunch of the internals which caused a few methods to be renamed and spigot didn't change the

number, causing plugins to break in unexpected manners.

There is no "remapping version", because it's just a dice rolled incremented number by spigot. This information still exists in the manifest,
Code:
CraftBukkit-Package-Version: v1_20_R4
but, do note that we will be removing that in the future when we hardfork, we're already using mojang mappings and so there is no long term desire to try to represent a broken concept for a failed experimental CB did many years ago.