NMS Unlocked

NMS Unlocked

403 Downloads

With NMS Unlocked, any plugin that is being loaded on a server does no longer need to use the correct org.bukkit.craftbukkit and net.minecraft.server (NMS)  version. This makes any plugin cross-version interoperable¹ including but not limited to for future versions, provided the core features it is using even exist in that shape at that version, of course. This works with anything from your new plugin to worldedit without any loss in performance and without tedious use of java 'reflection'.

Usage:

For Server owners:

Simply download the jar and drop it into your plugins folder - done!

When first starting a config file will be generated to let you block plugins by package name from being made interoperable, should the need arise. (e.g. if a plugin wants a different adapter for a certain version by itself). It probably won't ;)

For Plugin makers:

Use CraftPlayer, PacketPlayOutChat and whatever nms and craftbukkit classes you please, whenever you want, with the jar version you just so happen to be using while developing. As long as NMS Unlocked is also on the server, your plugin will work as though the server was running the correct version (technically because your plugin is using the correct version now). That's all! Magic!

Commands

/nmsunlocked

Shows status information about the plugin. Users that do not have the nmsunlocked.status permission will see a reduced version.

/nmsunlocked list

Lists which classes are compatible because of the plugin. Requires the nmsunlocked.status permission.

Permissions:

nmsunlocked.status

Default for op. Lets users see status information about the plugin.

(1) Limitations:

There are certain types of incompatibilities that the plugin can not work around:

Changes to the core classes

While classes like CraftPlayer (or most craftbukkit classes for that matter) stay the same for a very long time, other classes do change. This is also the reason why Citizens is likely  to not work in 1.13 without patching. As a rule of thumb, methods in the net/minecraft/ package that are called a(), b() etc. don't change that often, while the methods called hX() or fA() are most likely going to change.

If you are a dev and using a class that you think may be subject to change or has changed in the past, consider using try {} catch(LinkageError) {} and handle the issue. And in such cases remember your choice as exceptions being thrown a lot could degrade performance ;)

Java 9

If you are running your server on java 9 or above, you will need to start your server with "-Djdk.attach.allowAttachSelf=true",

e.g. "java -Djdk.attach.allowAttachSelf=true -jar bukkit-1.12.1.jar". The plugin will remind you.

Plugins that are "load: STARTUP"

NMS Unlocked needs to be loaded before any other plugins version dependent functions. It does so by using the "load: STARTUP" property. If another plugin also uses "load: STARTUP" (rare) and has version dependent code in its main class or any class that is being used statically in the main class (e.g. static OtherClass a = new OtherClass()) or from their onLoad() method, that code would not be adapting to the server version.

If you encounter such a case, move the jar out of the plugins folder into the server folder and start the server with "java -javaagent:<NMS Unlocked jar>.jar -jar <server jar>.jar", where  <NMS Unlocked jar is, of course, the name of the plugin jar.

This way those plugins will still work, however the /nmsunlocked command will not be available, as the 'plugin' is no longer treated as a plugin.

Things that don't exist yet

If a plugin is written for 1.12 and uses Polar Bears somewhere, and you try to use it with a 1.9 server + NMS Unlocked, it won't work because polar bears are not a thing yet. Duh.

Plugins that refuse to start for a version

A few plugins refuse to activate if they were not built with a certain version in mind, even though they would work thanks to NMS Unlocked. This is because the developer could not anticipate it to work. In such cases hit up the dev or me to extend the version check to test if the plugin still works :)

Citizens does this, but it is entangled so deep in the server core code that it has to undergo a lot of patching for new updates anyways so it would be no use to have it not reject officially unsupported versions.

"I am not a plugin developer or have not used craftbukkit classes before.

Whats the issue this plugin is solving?"

> Good question!

Essentially, any code in java is inside a so called 'class'. Classes are inside packages (folders and subfolders basically) that have certain names, like "org.bukkit.entity.Player" (Player would be the class).

When a plugin uses another class, it refers to it by that name. Some minecraft features (the cool ones, like particle effects, nbt tags and the likes) require the use of packages in org.bukkit.<version name> and net.minecraft.server.<version name>. That version changes with every update and if a plugin built with/for the wrong version of bukkit tries to do anything, it just gives an error and does not work. With NMS unlocked, plugins can refer to any <version name> they like, be that for 1.9 or 1.13, and still work on any version.

"How was that issue solved in the past?"

Developers had two choices. They could either use so called java reflection and, in a very tedious time consuming process, not call any code directly but instead get any used code elements by their name and then do operations on those meta-elements

...or they could write a version of their code for every minecraft version they want to support and then choose to call the code that is suited for the current one - meaning no support for future (and way older) versions without manual updating. (This is how WorldEdit does it by the way, as reflection is less performant an the last thing one would want is WorldEdit to be slowed down by 80%)

> Reflection: Tedious, Time consuming, inefficient, but adaptive to new versions

> Supplying several versions: Efficient, but requires constant maintenance and does not support versions that were release after creating the plugin.

Perfomance

The performance of your code with NMS Unlocked is as fast as it can get. (technically even faster than with supplying several versions, as plugins developed with NMS Unlocked don't need interfaces to proxy calls, but the difference is absolutely negligible)

The server startup time seems to be increased by about 2% to 3% in my test case. This is hard to test because the 'natural' variation is somewhere along those lines too.