PacketDispatcher.java 2.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. package me.lethunderhawk.network.packet;
  2. import com.esotericsoftware.kryonet.Connection;
  3. import java.lang.reflect.InvocationTargetException;
  4. import java.lang.reflect.Method;
  5. import java.util.List;
  6. import java.util.Map;
  7. import java.util.concurrent.ConcurrentHashMap;
  8. import java.util.concurrent.CopyOnWriteArrayList;
  9. public class PacketDispatcher {
  10. private static final Map<Class<? extends Packet>, List<RegisteredListener>> listeners = new ConcurrentHashMap<>();
  11. public static void registerListener(PacketListener listener) {
  12. for (Method method : listener.getClass().getDeclaredMethods()) {
  13. if (!method.isAnnotationPresent(PacketHandler.class)) {
  14. continue;
  15. }
  16. Class<?>[] params = method.getParameterTypes();
  17. if (params.length != 1 && params.length != 2) {
  18. continue;
  19. }
  20. if (!Packet.class.isAssignableFrom(params[0])) {
  21. continue;
  22. }
  23. if (params.length == 2 && !Connection.class.isAssignableFrom(params[1])) {
  24. continue;
  25. }
  26. method.setAccessible(true);
  27. listeners.computeIfAbsent((Class<? extends Packet>) params[0], c -> new CopyOnWriteArrayList<>())
  28. .add(new RegisteredListener(listener, method, params.length));
  29. }
  30. }
  31. public static void dispatchPacket(Packet packet, Connection connection) {
  32. List<RegisteredListener> packetListeners = listeners.get(packet.getClass());
  33. if (packetListeners == null || packetListeners.isEmpty()) {
  34. return;
  35. }
  36. for (RegisteredListener entry : packetListeners) {
  37. try {
  38. if (entry.argCount == 2) {
  39. entry.method.invoke(entry.listener, packet, connection);
  40. } else {
  41. entry.method.invoke(entry.listener, packet);
  42. }
  43. } catch (InvocationTargetException e) {
  44. // Unwrap the actual listener exception for clearer stack traces
  45. throw new RuntimeException("Packet listener failed for " + packet.getClass().getSimpleName(),
  46. e.getCause() != null ? e.getCause() : e);
  47. } catch (Exception e) {
  48. throw new RuntimeException("Failed to invoke listener for " + packet.getClass().getSimpleName(), e);
  49. }
  50. }
  51. }
  52. public static void dispatchPacket(Packet packet) {
  53. dispatchPacket(packet, null);
  54. }
  55. private static class RegisteredListener {
  56. private final PacketListener listener;
  57. private final Method method;
  58. private final int argCount;
  59. public RegisteredListener(PacketListener listener, Method method, int argCount) {
  60. this.listener = listener;
  61. this.method = method;
  62. this.argCount = argCount;
  63. }
  64. }
  65. }