Skip to content
This repository was archived by the owner on Oct 29, 2023. It is now read-only.

The plugin loading process

Alexander edited this page Jun 26, 2017 · 4 revisions

Plugin loading commences just before the game is loaded. This article describes the different stages of plugin loading.

Locating plugins

Locating plugins is done using the reflections library. The client's classloader is paired with a PluginClassLoader that includes all folders and JAR files in user.home\Wingman\plugins. The library then helps with constructing a set of all classes annotated with the Plugin class.

Parsing the plugins

It takes the plugin classes and wraps them using the PluginContainer class. This class tries to locate the PluginDependency/PluginDependencies, Plugin.Setup, Plugin.Activate, Plugin.Deactivate, Plugin.Refresh and Plugin.Helper annotations, setting the PluginContainer's fields to whatever the annotations are annotated to.

Here it also makes sure that you don't load a plugin that you've already loaded. It determines if you've done this by keeping a set of IDs of previously loaded plugins. This means that plugin makers should take care of having a very unique plugin ID for their plugin. This can be done by appending a string of random characters to it.

Parsing dependencies

Since you might want your plugin to depend on another plugin, there is plugin dependency functionality. To specify that you want to depend on for example the newest version of the Developer Utilities plugin:

@PluginDependency(
        id = "DevUtils-defaultplugins",
        version = ">=0.0.1"
)

The dependency parser will then make sure that a user has a plugin with the ID DevUtils-defaultplugins of atleast version 0.0.1. An exception will be thrown if the user's DevUtils plugin is outdated, or if it's simply missing. Plugin versions are based on Semantic Versioning.

After this, plugins are sorted topologically, as to load dependencies before dependants.

Setting up the plugins

At this stage, the method annotated with Plugin.Setup is called for plugins that have it defined. Since the plugin loading is done before the game is loaded, you would want to place any code that will need to be executed before the game launches within the Plugin.Setup method. Please be clever about what code you include in this step, since this is where the user is waiting for the game to boot up.

Baking event listeners

Here, it iterates over all event classes that have atleast one callback attached to them. It gets the static eventListenerList field of the event classes, and calls bake() on them. "Baking" the event listeners puts all registered listeners for that event from a Set over to an array, since an array is quicker to iterate over than a Set.

Activating the plugins

The game starts loading at this stage, and after it has been loaded the plugin activation phase starts. A new thread is spawned that invokes the Plugin.Activate method of the plugins that have defined it. This is where your more heavy plugin execution code should be placed, or simply put, any code that isn't dependant on being run before the game has started.

Clone this wiki locally