Search code examples
minecraftcircular-dependencyspigot

Selfwritten plugins fail to load on server startup, due to "dependency-circulations"


I have two self-written plugins. NovEcon2 and RealBanks2.

NovEcon2 is my economy-plugin, which depends on Vault and RealBanks2 as softdepend. RealBanks2 is my banking-plugin, which also depends on Vault.

Source-code is available here (important, stay in branch kotlin-rewrite):

I have implemented an api inside RealBanks2, to access some functions inside NovEcon2.

The api can be enabled in NovEcon2, via a configlet-bool set to true However, since both plugins depend on Vault, loading them while the configlet-bool set to true is impossible as of now.

Since RealBanks2 requires an economy-plugin to be loaded and NovEcon2 requires RealBanks2 to be loaded, none of them are getting loaded. That ends in NovEcon2 failing to load, because RealBanks2 isn't loaded and RealBanks2 failing to load, because there is no economy-plugin hooked into vault, such as NovEcon2.

Some other people referred that as a "dependency-circulation". This is how it looks like in the console, when the server is booting up:

[18:31:35 INFO]: [Vault] Enabling Vault v1.7.3-b131
[18:31:35 INFO]: [Vault] [Permission] SuperPermissions loaded as backup permission system.
[18:31:35 INFO]: [Vault] Enabled Version 1.7.3-b131
[18:31:35 INFO]: [NovEcon2] Enabling NovEcon2 v1.0.0
[18:31:35 ERROR]: [NovEcon2] - Disabled due to no RealBanks dependency found!
[18:31:35 INFO]: [NovEcon2] Disabling NovEcon2 v1.0.0
....
[18:31:36 INFO]: [RealBanks2] Enabling RealBanks2 v2.0.0
[18:31:36 ERROR]: [RealBanks2] - Disabled due to no Vault dependency found!
[18:31:36 INFO]: [RealBanks2] Disabling RealBanks2 v2.0.0

I have thought about a separate bridge plugin, but afaik, it would end in the same issue, since the bridge-plugin would be needed by NovEcon2, and the bridge-plugin would depend on RealBanks2.

Changing the order of the depended plugins in the plugin.yml or adding loadbefore didn't help me to come a little closer to a viable solution.

This resulted in nothing but still failing.


Solution

  • After a long search, the following procedure solved my problem:

    There is an event, called ServiceRegisterEvent. It can be used to get services, when they are registered on server start.

    I listened for the service Economy and if that occured, I loaded the Economy-Plugin.

    I also had to edit the plugin.yml of the Banking-Plugin, to load before the Economy-Plugin.

    ServiceRegisterEvent:

    internal class ServiceRegisterListener(private val realBanks2: RealBanks) : Listener {
        @EventHandler
        fun onEconomyServiceRegister(e: ServiceRegisterEvent) {
            if(e.provider.service.simpleName.equals("Economy")) {
                if(!realBanks2.setupEconomy()) {
                    RealBanks.LOG.severe(String.format("[%s] - Disabled due to no Vault dependency found!", realBanks2.name))
                    realBanks2.server.pluginManager.disablePlugin(realBanks2)
                    return
                }
            }
        }
    }
    

    plugin.yml

    name: RealBanks2
    version: ${project.version}
    main: me.linuxsquare.realbanks2.RealBanks
    api-version: "1.19"
    depend: [Vault, PlayerUUIDCache]
    loadbefore:
        - NovEcon2
    author: LinuxSquare
    website: https://codeberg.org/Noveria/RealBanks2