closes#3080
If plugins fail to load for some reason, it's highly likely that some critical functionality of the server is compromised. For example:
- if an NPC plugin fails to load, all custom entities added by that plugin will be deleted from worlds
- if a world protection plugin fails, players will be able to grief your otherwise immutable lobby map
- if a worldgen plugin fails, worlds using custom generators won't load
- if a permission plugin fails, players might have access to commands and features they aren't supposed to have
- the list goes on...
This change makes the server commit graceful suicide if any plugin fails to load for error-related reasons, including (but not limited to):
- Incompatible API version
- Missing dependencies
- Invalid plugin.yml
- Invalid main class
Plugins prevented from loading by `plugin_list.yml` are not considered errors and **are not** included in this change. If a plugin is disallowed from loading due to the `plugin_list`, the server will continue to run as if the plugin was not present.
I've stuck to only doing this in the places where I'm sure we should never get false back. Other places I'm less sure of (and I found more bugs along the way).
this is not as good as phpstan/phpstan-src#769 (e.g. array_key_first()/array_key_last() aren't covered by this, nor is array_rand()) but it does eliminate the most infuriating cases where this usually crops up.
this could happen if a plugin declared a permission already declared by another plugin, and then declared a different default for it (e.g. true instead of op).
loadPlugins() is now the preferred option, since it does all the proper checks.
In addition, the server now acknowledges that loading a single plugin may cause multiple plugins to be loaded, so returning only a single Plugin is not representative of what's actually happening.
loadPlugins() is now a superior option to loadPlugin(), since it enforces dependency checks and also supports automatic loading of plugins when new loaders are installed.
for some reason we were reading and parsing the plugin.yml at least twice for every plugin loaded.
We were repeating work already done by the initial loadPlugins() triage (discovering correct loader, loading plugin.yml from disk, parsing plugin.yml, validating plugin.yml) every time loadPlugin() was called with that plugin.
this makes translation usage much more statically analysable.
The only places this isn't used are:
- places that prefix translations with colours (those are still a problem)
- places where server/client translations don't match (e.g. gameMode.changed accepts different parameters in vanilla than in PM)
literally nobody uses this. I don't think anyone even knows it exists.
It's also an obstacle to separating event handler registration from PluginManager.
this fixes#3200.
This causes permissions to be registered before plugin load, which changes some behaviour, but after discussions on #internals-dev we couldn't see any reason to keep the behaviour the way it was, and several reasons to change it to be something like this.