0

So I started working on a new Bukkit plugin and did some research on possible ways of automating listener registration. I came across the ServiceLoader class and read its JavaDocs. Basically I'm trying to load all the classes that implement the Listener interface, looping through them and registering them with this method:

private static void registerListeners() {
    ServiceLoader<Listener> loader = ServiceLoader.load(Listener.class);
    for (Listener listener : loader) {
        Bukkit.getPluginManager().registerEvents(listener, get());
    }
}

The get() method here returns the instance variable (private static Posc instance; "Posc" being the name of the main class and the plugin) which is declared in the onEnable() method. I would then call this method in the onEnable() method like so:

@Override
public void onEnable() {
    instance = this;
    registerListeners();
}

As stated in the documentation, I created the META-INF\services directory in the resources directory and added a text file called org.bukkit.event.Listener, in this text file I added the full names of my listener classes, one per line, like so:

me.lord.posc.listeners.PlayerJoinListener
me.lord.posc.listeners.PlayerQuitListener

My IDE (JetBrain IntelliJ IDEA Community Edition 2022.3.1) does not give any errors or warnings in any of my classes or the org.bukkit.event.Listener file. No errors or warnings were given in the console when I started the server with the plugin. In game I ran the /plugins Bukkit command which showed my plugin in green, which means it has loaded successfully, which means the onEnable() method was called. This was also confirmed when I added this line into the registerListeners() method:

get().getLogger().info("test");

"test" was written into the console by my plugin.

The PlayerJoinListener class looks like this:

package me.lord.posc.listeners;

import me.lord.posc.Posc;
import me.lord.posc.utilities.TextUtil;
import org.bukkit.Bukkit;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerJoinEvent;

public class PlayerJoinListener implements Listener {
    // TODO: Replace Bukkit.getOfflinePlayers().length with a player counting system to increase performance
    @EventHandler
    public void onPlayerJoin(PlayerJoinEvent event) {
        event.joinMessage(TextUtil.c("&7[&a+&7] &f" + event.getPlayer().getName() + (event.getPlayer().hasPlayedBefore() ? "" : " &8| &6" + TextUtil.ordinal(Bukkit.getOfflinePlayers().length) + " join")));
        Posc.get().getLogger().info("test");
    }
}

And the PlayerQuitListener class looks like this:

package me.lord.posc.listeners;

import me.lord.posc.Posc;
import me.lord.posc.utilities.TextUtil;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerQuitEvent;

public class PlayerQuitListener implements Listener {
    @EventHandler
    public void onPlayerQuit(PlayerQuitEvent event) {
        event.quitMessage(TextUtil.c("&7[&c-&7] &f" + event.getPlayer().getName()));
        Posc.get().getLogger().info("test");
    }
}

These classes, if they worked properly, would change the join and leave messages, and print "test" whenever a player joins or leaves. This is however not the case as none of these things happen when anyone leaves or joins the server which indicates that these listeners have not been registered properly or at all.

I've tried many things to get it work but with no success. I tried...

  • changing the location of the META-INF directory to src, src\main and src\main\java but none of these did anything.
  • making a new interface that extended org.bukkit.event.Listener, making the listener classes implement that and switching Listener with my interface in the META-INF\services directory and in the registerListeners() method
  • using different methods in place of the for, like streams, Iterator and foreach()
  • getClass().newInstance()

I tried loader.stream().findFirst().isEmpty() to see if it actually loaded the classes, and the method returned true which means the loader doesn't for some reason load the classes.

0 Answers0