Paper: [Discussion] New Plugin Life-cycle API

Created on 12 Sep 2020  路  4Comments  路  Source: PaperMC/Paper

Bukkit has long had its problems with plugin life-cycles. Plugins have had no explicit control over whether they are safe to be reloaded or not, if they're shutting down or reloading during JavaPlugin#onDisable (up until #3129), and how many plugin cycles a plugin has gone through. Combine those core problems with upstream's desire to not expose plugin life-cycles through API (because think about all those non-ticking, Bukkit-implementing server softwares that never shutdown!~!!1!11!) and no wonder reloading plugins is such a nightmare.

This is where this issue comes into play. I will be writing and PRing a new plugin life-cycle API to Paper within in the next couple of days/weeks (depends on how busy I am with work). Below are my current plans for the new API which should help solve some of the problems listed below.

The reason I am opening this as an issue for discussion is so that project members, contributors, or plugin developers can give their two-cents on the current API plans and/or suggest even more plugin life-cycle API that would help them write their plugins to respect (or avoid) plugin life-cycles better.


New reload Property in plugin.yml

This property would have 3 different configuration options: always meaning the plugin is safe to be reloaded and properly handles its own life-cycle; never meaning the plugin in not safe to reload and that the reload command should skip over this plugin; same-hash (please suggest a better name) meaning that the plugin is safe to be reloaded as long as the plugin's hash (probably md5 hash due to its speed and since this isn't a security feature) hasn't been changed since the server start.

Something I'd like input on here is the default value for this property. I'm leaning towards same-hash to ensure existing compatibility while adding some safety but it could also be set to false or true idk.

New API getPluginReloadCount()I & getGlobalReloadCount()I

The motivation behind this API is to get the number of times the plugin/server has been run through a life-cycle (reloaded). The number of plugin cycles would be incremented each time a plugin is reloaded (forcibly or not). The number of global cycles would be incremented each time the /reload command is used.

The destination of these methods are TBD as I'm writing this before looking too deeply into implementation.

New API Bukkit#isStarting & Server#isStarting

This API would allow for plugins to understand what part of the plugin life-cycle they are in during JavaPlugin#onEnable

New behavior of /reload

The /reload command will have a new argument added to it, force, which will forcibly reload plugins and ignore their reload property. (Personally, I'm on the side of not documenting this in the confirmation message as I think that would train users to always use it.) Also, the /reload command will now display what plugins are reloaded and what plugins aren't.

New behavior in /version

The /version command will now display the number of global cycles or will display the number of plugin cycles if a plugin is specified.


So those are my changes that I plan on making! I'd love feedback from project members, contributors, or plugin developers on improvements or additions I could make!


in progress feature

Most helpful comment

but the question is if I should break PlugMan until it specifically accounts for these new changes from Paper.

Noo, never, do not break shit; if a plugin makes others misbehave, we don't really have reason to give a shit. PlugMan should add support once the API lands, and its users should update the plugin that already causes many, many headaches.

All 4 comments

I'm fully in support of the new APIs, behaviour, and especially the property in plugin.yml.

Could we also have some API to know when the server is starting and/or the plugin is loaded for the first time (e.g. in the case of PlugMan where a plugin may be loaded well into the server lifetime)?

One thing I am somewhat scared of however is when #getPluginCycles would be incremented. Would plugins like PlugMan automatically respect this (disclaimer: I do not entirely know how PlugMan works)? If so, is it only on reload, or also on unload & load?

Could we also have some API to know when the server is starting and/or the plugin is loaded for the first time (e.g. in the case of PlugMan where a plugin may be loaded well into the server lifetime)?

Yeah sure, I could add Bukkit#isStarting to compliment that Bukkit#isStopping I added in #3129

One thing I am somewhat scared of however is when #getPluginCycles would be incremented. Would plugins like PlugMan automatically respect this (disclaimer: I do not entirely know how PlugMan works)? If so, is it only on reload, or also on unload & load?

I can try my best to force plugins like PlugMan to respect the changes in this document, the cycle count shouldn't be a problem to enforce but the question is if I should break PlugMan until it specifically accounts for these new changes from Paper.

but the question is if I should break PlugMan until it specifically accounts for these new changes from Paper.

Noo, never, do not break shit; if a plugin makes others misbehave, we don't really have reason to give a shit. PlugMan should add support once the API lands, and its users should update the plugin that already causes many, many headaches.

cycles feels like a weird word to use instead of just getReloadCount lol.

and commands dont use - syntax so it should be /reload force
and prob would need like /reload safe to exhibit NEW behavior

ultimately the issue with reloading partial boils down to dependency order. loadafter is fine, but if a reloadable plugin has a loadbefore and that loadbefore plugin is not reloadable, then you have order issues.

But i think the idea is valid just going to be iffy to achieve strong enforcement of behavior.

ideally would need to bring this up w/ spigot to try to get more adoption.

Was this page helpful?
0 / 5 - 0 ratings