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 tosrc
,src\main
andsrc\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 switchingListener
with my interface in theMETA-INF\services
directory and in theregisterListeners()
method - using different methods in place of the
for
, like streams,Iterator
andforeach()
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.