Skip to content

v3 Module System

Jake Moore edited this page Dec 21, 2024 · 2 revisions

❗ This Documentation is Outdated! It is recommended to use v4 with its documentation instead.

See V4 Getting Started for more information.

⚠️ Usage ⚠️

This feature is only available in spigot-utils and its inheritors (spigot-jar).

The module system in KamiCommon provides an abstract layer to create mini-plugins (called "modules") in your plugin.
These can be used for anything, including additional toggleable features, or to organize your code into one project instead of many.

Module Core Methods & Life Cycle

The Module class defines a set of methods that make each module mimic an individual plugin.
However, the lifecycle of these methods is a bit different. These methods are:

  • getCommands(): A method for you to provide a list of commands to be registered at the very start (before onConfigLoaded() or onEnable()).
    • The commands returned are a list of KamiCommand objects, which will be registered by the module system.
  • onConfigLoaded(): Called after the module config is loaded. Guaranteed to be called once before onEnable().
    • Once called, the config is safe to be accessed via Module#getConfig().
  • onEnable(): Called after the module config is loaded and onConfigLoaded() is called.
    • For your enable logic, but not your configuration logic.
  • onDisable(): Called when the module is disabled.
    • For your disable logic. Note: A module can be disabled and then re-enabled, but it will go through the entire lifecycle again, staring with getCommands(). Note: A module config can be reloaded, and thus most initialization of config fields should be handled in onConfigLoaded(), and not in onEnable().

Creating a Module

Each module must extend the Module class. Which defines a set of methods each module must implement.
Often it is easier to create your own abstract class extending Module for your plugin's modules.
For instance FactionsModule, in which you override a few defaults, leaving the core methods (mentioned above) abstract for your modules to override.

Easier Registrations

Like KamiPlugin, the same registration methods are available for modules. These are:

this.registerListener(myListener = new MyListener());
this.registerDisableable(myDisableableObject = new MyDisableableObject());
this.registerTask(myBukkitTask);

// Corresponding methods exist to unregister these objects as well.
this.unregisterListener(myListener);
this.unregisterDisableable(myDisableableObject);
this.unregisterTask(myBukkitTask);

Registering the Module

All modules are required to have an empty constructor for reflection class instantiation.
To register a module, you can use the following method in KamiPlugin:

kamiPlugin.registerModule(CustomEnchantsModule.class);

This method will create a new object using the empty constructor, and start the life cycle.

⚠️ Module Configs ⚠️

This is perhaps the most important part of this wiki page. Set up is required in order to get the module configs to work properly.
This is the recommended layout for the packages containing your modules in your plugin:

image

Note that the module config is in the same package as the module itself, using the same class name, but with the .yml file extension.
Next, you need to override the getModuleYmlPath() method in KamiPlugin to tell the module system where your modules package is located.
For example if your full module path was: com.myname.myplugin.modules.yourmodule.YourModule then you would want to override:

@Override
public String getModuleYmlPath() {
    // Stop before you get to a specific module package.
    // You don't need to append a / at the end.
    return "com/myname/myplugin/modules";
}

Without this step the module system will search for module configs inside the root of your plugin jar.
Note: You can use a different layout for your module configs, but this is the only officially supported layout being tested.

The modules config

When your plugin is using modules, you will notice a new modules.yml file appear in your plugin's data directory on the server.
This file is used to disabled and modify properties of each module. If a module is disabled here, it will not be loaded on the next server restart.

The modulePrefix field is used in in conjunction with the MessageBuilder class that you get when you use Module#buildMessage(String configKey).
Messages constructed in this manner have the placeholders {prefix} and %prefix% replaced with the module prefix, for easier configuration of the module messages.