๐ฆShip Your Own Loader
Every protected plugin ships its own loader, named after itself. Here is why, and the ten lines it takes.
If you sell a protected plugin, build a loader named after your plugin and ship that. Do not ship the generic one.
Why
A loader hosts exactly one protected module. It has one config file, one product id, one license key, and one module in memory.
Bukkit refuses to enable two plugins with the same name, and Velocity refuses two plugins with the same id. So if every seller shipped the stock ObsidianLoader, a customer who bought protected plugins from two different sellers could install exactly one of them. The second would fail to load, and the two would fight over the same plugins/ObsidianLoader/config.yml anyway.
Name the loader after your plugin and the problem disappears. Your customers install MyPlugin, someone else's install TheirPlugin, and both run happily side by side.
The generic loader from the dashboard is still useful: for testing, and for a customer who only ever runs one protected plugin. It is just not what you distribute.
Get the code
Everything the loader is made of is public:
Use velocity instead of paper for a proxy plugin. You can also just copy the sources into your project if you would rather not add a dependency.
The loader, in full
plugin.yml:
config.yml, which is all your customer ever edits:
Shade the dependency so the loader carries its own classes:
Velocity
The same shape, with VelocityLoaderSupport and your own plugin id:
Full template: MyProxyLoader.java.
Plain Java
There is no plugin to name, so there is no collision to avoid: use ObsidianLoader directly from your own main. See StandaloneHost.java.
What you ship
Two jars, from two builds:
MyPlugin.jar (the loader)
Your loader project
Your customers
my-plugin-1.0.0.jar (the module)
Your real plugin
Uploaded to the dashboard, never shipped
The module jar is the one that stays secret. The loader is public by nature: it runs on customer machines and can be decompiled by anyone, which is why none of its security depends on being hidden. It pins a public key, and every real check happens on the server.
Keeping it up to date
Bump the dependency when the platform's signed envelope changes, then rebuild and redistribute your loader. Older loaders fail closed with "response signature invalid" rather than doing anything unsafe, but your customers will notice. Release notes call out any change that needs this.
Last updated