Not really, you can have a GenericWrapper that stores the actual class and has a getInstance that uses that stored class as the parameter. That’s still plenty ugly, but less ugly than many many events.
I misunderstood the issue, you could have the methods have a @HandlesPacket(PacketType). And register the methods in the event system as Map<Class<? extends BasePacket>, List<Method>> to store the methods that get called for the packet events.
This is actually really just a limitation in Sponge’s event bus. While it is correct that generics are mostly removed at compile time due to type erasure, they’re not deleted everywhere. You would be able to get the packet class used in the generic event handler method, but matching an instance of PacketEvent to one of these event handler methods would be difficult.
Generally said for Sponge’s event bus:
We can get which type arguments are referenced in the event handler method at runtime (using reflection)
We can not get which type arguments were used when creating the event instance (due to type erasure), which would be required for matching an existing event instance to a list of event handlers with their type arguments.
For example, if Sponge’s event bus would register event handler methods with their type arguments, you would have a CommandEvent<T extends CommandSource>, and give a CommandEvent<Player> to our event bus.
We would have no way to say if the given event instance is a CommandEvent<Player> or maybe a CommandEvent<Console>, because due to type erasure we only know it’s a CommandEvent from the instance at runtime, but not which CommandEvent specifically.
This makes support for generic events for custom events almost impossible, because you can’t say which type arguments the event instance is representing.
Because you know how the packet event classes look like, there would be no problem to implement this using a custom event bus, because you can simply check like packetEvent.getPacket().getClass() to get the type argument required to listen to this specific PacketEvent.
Here is a small (inefficient) example with a custom event bus proving it is possible:
When running the application, it will correctly print the following:
Thats awsome . But why would you call this inefficient? Looks more efficient than what I have now. (Sadly enough I still don’t have a workspace up, Its just running in the sponge workspace and I can’t push that to github ;-
Personally I wouldn’t rely on reflection for calling event handlers for events which will be frequently called. Packets will get fired several times every tick so you need to make sure your packet API isn’t slowing down the whole server.