A question which is asked from time to time is how to listen to all events, how to register a listener for all events in Bukkit/Spigot. Sadly, I was unable to find a real, up to date answer.

Some sources suggest using HandlerList. As a user later pointed out, this is an unreliable way of doing it: an Event is only registered in the HandlerList once it has been initialized, it being loaded is not enough.

What are loading and initialization?
Simply put, loading is when the bytecode (read: compiled) representation of a class is located and loaded. Initialization is a step later down the line which only happens once. It is done when a new instance of the class is created or when one of its static methods is called (there are some other triggers as well). During the initialization (among other things) the static initialization is done.

All events have a static HanderList variable, it is assigned during initialization. The constructor of the HandlerList registers the event. As mentioned earlier, we can’t rely on this behavior except if it’s enough to know that an event exists before it is fired. Aikar mentions using this registration process in his Timings, but I could find it in neither Paper nor Spigot. I think he meant something else because HandlerList instances do not reference the class they store the handlers of, therefore the call stack would have to be examined to extract this information.

It suggest tinkering with the server’s PluginManager. Events are fired by calling PluginManager#callEvent(Event). If we were to inject our omni listener before/after the implementation of that method, we would be able to listen to all events before/after the other handlers are executed. Unfortunately, this is not possible: CraftServer stores an instance of SimplePluginManager instead of PluginManager. This means that we would have to wrap/proxy a SimplePluginManager, but the class is final, therefore there is no way to do this with just reflection: bytecode manipulation is necessary. That is not ideal.

It would seem that there is only one possible solution left: getting all loaded classes which extend Event, filter them and then register a listener for them. If we want to list all events, the filtering is easy: the class mustn’t be abstract, that’s all. We can also use this filtering if we want to listen to all events, but in this case, we would need to use the HandlerList class when registering our listener. This is because we don’t want our listener to be called multiple times for the same event instance.

To achieve this task of registering a listener for all events in Bukkit/Spigot, you’ll need to make use of reflection to discover all classes that extend Event and are non-abstract. You can then register your listener for each of these events. Here’s a basic outline of how you could implement such a solution:


import org.bukkit.Bukkit;
import org.bukkit.event.Event;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.plugin.java.JavaPlugin;
import org.reflections.Reflections;

import java.lang.reflect.Method;
import java.util.Set;

public class AllEventsListenerPlugin extends JavaPlugin implements Listener {

@Override
public void onEnable() {
// Register the plugin as a listener
Bukkit.getPluginManager().registerEvents(this, this);

// Use Reflections library to find all classes that extend Event
Reflections reflections = new Reflections(“org.bukkit.event”);

// Get all classes extending Event
Set<Class<? extends Event>> eventClasses = reflections.getSubTypesOf(Event.class);

for (Class<? extends Event> eventClass : eventClasses) {
// Ensure class is not abstract and has a static HandlerList method
if (!java.lang.reflect.Modifier.isAbstract(eventClass.getModifiers())
&& hasHandlerListMethod(eventClass)) {
try {
// Register this plugin to listen to the event
Bukkit.getPluginManager().registerEvent(
eventClass,
this,
org.bukkit.event.EventPriority.NORMAL,
(listener, event) -> {
if (eventClass.isInstance(event)) {
onAnyEvent(event);
}
},
this
);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}

private boolean hasHandlerListMethod(Class<? extends Event> eventClass) {
try {
Method method = eventClass.getDeclaredMethod(“getHandlerList”);
return method != null;
} catch (NoSuchMethodException e) {
return false;
}
}

@EventHandler
public void onAnyEvent(Event event) {
// Your handling code for every event
System.out.println("Event fired: " + event.getEventName());

// Please write code here <-

}
}


### What the code does:
1. Initialization: The plugin is registered as a Listener when enabled.
2. Reflection for Event Classes: It uses the Reflections library to find all classes extending Event.
3. Filtering and Registration: For each non-abstract class that has a getHandlerList method, it registers this plugin to listen to that event.
4. Handling Events: The onAnyEvent method provides a place to handle any event discovered and that’s executed.

### Instructions:
- Dependencies: Make sure to include the Reflections library in your project. You can include it using a build tool like Maven or Gradle, or by manually adding the JAR to your project.
- Permissions: Your plugin will require the appropriate permissions and should be coded responsibly as listening to all events can impact performance.
- Compatibility: Test this solution with your target version of Spigot/Bukkit to account for any API changes.

### Caution:
Listening to all events may have performance implications since many events fire in rapid succession during server operation. Use this approach selectively and optimize the handling function (onAnyEvent) to mitigate performance overhead. 

Please explain and improve onAnyEvent() function. How can I display max information as possible about every event? Type of every event can be very different, but write universal solution to:
1) get list of all possible and available event fields (such as type (not genericgameevent!), location, entity, time, blocktype, entitytype and etc)
2) display them