From 19b2be7731102b5057c1e580d96c64f2194951d6 Mon Sep 17 00:00:00 2001 From: Connor Linfoot Date: Sun, 28 Jul 2024 15:58:39 +0100 Subject: [PATCH 1/3] Implement the ability to handle errors --- .../net/hypixel/modapi/HypixelModAPI.java | 19 ++++++++++++++----- .../handler/ClientboundPacketHandler.java | 8 ++++++++ 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/src/main/java/net/hypixel/modapi/HypixelModAPI.java b/src/main/java/net/hypixel/modapi/HypixelModAPI.java index eecc7d7..08fd83c 100644 --- a/src/main/java/net/hypixel/modapi/HypixelModAPI.java +++ b/src/main/java/net/hypixel/modapi/HypixelModAPI.java @@ -1,7 +1,6 @@ package net.hypixel.modapi; import net.hypixel.modapi.error.ErrorReason; -import net.hypixel.modapi.error.ModAPIException; import net.hypixel.modapi.handler.ClientboundPacketHandler; import net.hypixel.modapi.packet.ClientboundHypixelPacket; import net.hypixel.modapi.packet.EventPacket; @@ -29,7 +28,7 @@ public static HypixelModAPI getInstance() { } private final PacketRegistry registry = new PacketRegistry(); - private final Map, Collection>> handlers = new ConcurrentHashMap<>(); + private final Map>> handlers = new ConcurrentHashMap<>(); private final Set subscribedEvents = ConcurrentHashMap.newKeySet(); private Set lastSubscribedEvents = Collections.emptySet(); private Predicate packetSender = null; @@ -109,7 +108,8 @@ public void handle(String identifier, PacketSerializer serializer) { // All responses contain a boolean of if the response is a success, if not then a further var int is included to identify the error if (!serializer.readBoolean()) { ErrorReason reason = ErrorReason.getById(serializer.readVarInt()); - throw new ModAPIException(identifier, reason); + handleError(identifier, reason); + return; } ClientboundHypixelPacket packet = registry.createClientboundPacket(identifier, serializer); @@ -124,7 +124,7 @@ public void handle(String identifier, PacketSerializer serializer) { @ApiStatus.Internal @SuppressWarnings("unchecked") public void handle(ClientboundHypixelPacket packet) { - Collection> typedHandlers = handlers.get(packet.getClass()); + Collection> typedHandlers = handlers.get(getRegistry().getIdentifier(packet.getClass())); // nothing registered for this packet. if (typedHandlers == null) return; for (ClientboundPacketHandler handler : typedHandlers) { @@ -133,6 +133,15 @@ public void handle(ClientboundHypixelPacket packet) { } } + @ApiStatus.Internal + public void handleError(String identifier, ErrorReason reason) { + Collection> handlers = this.handlers.get(identifier); + if (handlers == null) return; + for (ClientboundPacketHandler handler : handlers) { + handler.onError(reason); + } + } + @ApiStatus.Internal public void setPacketSender(Predicate packetSender) { if (this.packetSender != null) { @@ -143,7 +152,7 @@ public void setPacketSender(Predicate packetSender) { public void registerHandler(Class packetClass, ClientboundPacketHandler handler) { if (packetClass == null || handler == null) return; - handlers.computeIfAbsent(packetClass, cls -> new CopyOnWriteArrayList<>()).add(handler); + handlers.computeIfAbsent(getRegistry().getIdentifier(packetClass), cls -> new CopyOnWriteArrayList<>()).add(handler); } public void subscribeToEventPacket(Class packet) { diff --git a/src/main/java/net/hypixel/modapi/handler/ClientboundPacketHandler.java b/src/main/java/net/hypixel/modapi/handler/ClientboundPacketHandler.java index 2b1ea0b..16a9b5f 100644 --- a/src/main/java/net/hypixel/modapi/handler/ClientboundPacketHandler.java +++ b/src/main/java/net/hypixel/modapi/handler/ClientboundPacketHandler.java @@ -1,8 +1,16 @@ package net.hypixel.modapi.handler; +import net.hypixel.modapi.error.ErrorReason; import net.hypixel.modapi.packet.ClientboundHypixelPacket; @FunctionalInterface public interface ClientboundPacketHandler { void handle(T packet); + + /** + * Optional handling for when an error is received for this packet. + *
+ * Note: This error may be received due to any modification requesting this packet. + */ + default void onError(ErrorReason reason) {} } From c6a4e1bc81c57a92b4376f7b6b1e15bec11161ba Mon Sep 17 00:00:00 2001 From: Connor Linfoot Date: Wed, 31 Jul 2024 11:18:07 +0100 Subject: [PATCH 2/3] Better idea for error handling --- .../net/hypixel/modapi/HypixelModAPI.java | 61 +++++++++++++++---- .../handler/ClientboundPacketHandler.java | 8 --- .../hypixel/modapi/handler/ErrorHandler.java | 9 +++ .../modapi/handler/RegisteredHandler.java | 12 ++++ 4 files changed, 71 insertions(+), 19 deletions(-) create mode 100644 src/main/java/net/hypixel/modapi/handler/ErrorHandler.java create mode 100644 src/main/java/net/hypixel/modapi/handler/RegisteredHandler.java diff --git a/src/main/java/net/hypixel/modapi/HypixelModAPI.java b/src/main/java/net/hypixel/modapi/HypixelModAPI.java index 08fd83c..d780bef 100644 --- a/src/main/java/net/hypixel/modapi/HypixelModAPI.java +++ b/src/main/java/net/hypixel/modapi/HypixelModAPI.java @@ -2,6 +2,8 @@ import net.hypixel.modapi.error.ErrorReason; import net.hypixel.modapi.handler.ClientboundPacketHandler; +import net.hypixel.modapi.handler.ErrorHandler; +import net.hypixel.modapi.handler.RegisteredHandler; import net.hypixel.modapi.packet.ClientboundHypixelPacket; import net.hypixel.modapi.packet.EventPacket; import net.hypixel.modapi.packet.HypixelPacket; @@ -28,7 +30,7 @@ public static HypixelModAPI getInstance() { } private final PacketRegistry registry = new PacketRegistry(); - private final Map>> handlers = new ConcurrentHashMap<>(); + private final Map>> handlers = new ConcurrentHashMap<>(); private final Set subscribedEvents = ConcurrentHashMap.newKeySet(); private Set lastSubscribedEvents = Collections.emptySet(); private Predicate packetSender = null; @@ -124,21 +126,20 @@ public void handle(String identifier, PacketSerializer serializer) { @ApiStatus.Internal @SuppressWarnings("unchecked") public void handle(ClientboundHypixelPacket packet) { - Collection> typedHandlers = handlers.get(getRegistry().getIdentifier(packet.getClass())); + Collection> typedHandlers = handlers.get(getRegistry().getIdentifier(packet.getClass())); // nothing registered for this packet. if (typedHandlers == null) return; - for (ClientboundPacketHandler handler : typedHandlers) { - // this cast is safe as we ensure its type when it is added to the handlers list in the first place. - ((ClientboundPacketHandler) handler).handle(packet); + for (RegisteredHandlerImpl handler : typedHandlers) { + handler.handle(packet); } } @ApiStatus.Internal public void handleError(String identifier, ErrorReason reason) { - Collection> handlers = this.handlers.get(identifier); + Collection> handlers = this.handlers.get(identifier); if (handlers == null) return; - for (ClientboundPacketHandler handler : handlers) { - handler.onError(reason); + for (RegisteredHandlerImpl handler : handlers) { + handler.handleError(reason); } } @@ -150,9 +151,19 @@ public void setPacketSender(Predicate packetSender) { this.packetSender = packetSender; } - public void registerHandler(Class packetClass, ClientboundPacketHandler handler) { - if (packetClass == null || handler == null) return; - handlers.computeIfAbsent(getRegistry().getIdentifier(packetClass), cls -> new CopyOnWriteArrayList<>()).add(handler); + public RegisteredHandler registerHandler(Class packetClass, ClientboundPacketHandler handler) { + if (packetClass == null) { + throw new NullPointerException("packetClass cannot be null"); + } + + if (handler == null) { + throw new NullPointerException("handler cannot be null"); + } + + RegisteredHandlerImpl registeredHandler = new RegisteredHandlerImpl<>(handler); + handlers.computeIfAbsent(getRegistry().getIdentifier(packetClass), cls -> new CopyOnWriteArrayList<>()) + .add(registeredHandler); + return registeredHandler; } public void subscribeToEventPacket(Class packet) { @@ -171,4 +182,32 @@ public boolean sendPacket(HypixelPacket packet) { return packetSender.test(packet); } + + private static class RegisteredHandlerImpl implements RegisteredHandler { + private final ClientboundPacketHandler handler; + private ErrorHandler errorHandler; + + RegisteredHandlerImpl(ClientboundPacketHandler handler) { + this.handler = handler; + } + + @Override + public void onError(ErrorHandler errorHandler) { + if (this.errorHandler != null) { + throw new IllegalStateException("Error handler already set"); + } + this.errorHandler = errorHandler; + } + + public void handle(ClientboundHypixelPacket packet) { + // this cast is safe as we ensure its type when it is added to the handlers list in the first place. + handler.handle((T) packet); + } + + public void handleError(ErrorReason reason) { + if (errorHandler != null) { + errorHandler.onError(reason); + } + } + } } diff --git a/src/main/java/net/hypixel/modapi/handler/ClientboundPacketHandler.java b/src/main/java/net/hypixel/modapi/handler/ClientboundPacketHandler.java index 16a9b5f..2b1ea0b 100644 --- a/src/main/java/net/hypixel/modapi/handler/ClientboundPacketHandler.java +++ b/src/main/java/net/hypixel/modapi/handler/ClientboundPacketHandler.java @@ -1,16 +1,8 @@ package net.hypixel.modapi.handler; -import net.hypixel.modapi.error.ErrorReason; import net.hypixel.modapi.packet.ClientboundHypixelPacket; @FunctionalInterface public interface ClientboundPacketHandler { void handle(T packet); - - /** - * Optional handling for when an error is received for this packet. - *
- * Note: This error may be received due to any modification requesting this packet. - */ - default void onError(ErrorReason reason) {} } diff --git a/src/main/java/net/hypixel/modapi/handler/ErrorHandler.java b/src/main/java/net/hypixel/modapi/handler/ErrorHandler.java new file mode 100644 index 0000000..b2d49f9 --- /dev/null +++ b/src/main/java/net/hypixel/modapi/handler/ErrorHandler.java @@ -0,0 +1,9 @@ +package net.hypixel.modapi.handler; + +import net.hypixel.modapi.error.ErrorReason; +import net.hypixel.modapi.packet.ClientboundHypixelPacket; + +@FunctionalInterface +public interface ErrorHandler { + void onError(ErrorReason reason); +} diff --git a/src/main/java/net/hypixel/modapi/handler/RegisteredHandler.java b/src/main/java/net/hypixel/modapi/handler/RegisteredHandler.java new file mode 100644 index 0000000..79fab78 --- /dev/null +++ b/src/main/java/net/hypixel/modapi/handler/RegisteredHandler.java @@ -0,0 +1,12 @@ +package net.hypixel.modapi.handler; + +import net.hypixel.modapi.packet.ClientboundHypixelPacket; + +public interface RegisteredHandler { + /** + * Handling for when an error is received for this registered handler. + *
+ * Note: This error may be received due to any modification requesting the same packet type. + */ + void onError(ErrorHandler errorHandler); +} From a568e8b57490e5655ca27bcaf4bd4c44f31929dd Mon Sep 17 00:00:00 2001 From: Connor Linfoot Date: Wed, 31 Jul 2024 11:21:22 +0100 Subject: [PATCH 3/3] Use getIdentifier from the packet --- src/main/java/net/hypixel/modapi/HypixelModAPI.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/net/hypixel/modapi/HypixelModAPI.java b/src/main/java/net/hypixel/modapi/HypixelModAPI.java index d780bef..7169809 100644 --- a/src/main/java/net/hypixel/modapi/HypixelModAPI.java +++ b/src/main/java/net/hypixel/modapi/HypixelModAPI.java @@ -126,7 +126,7 @@ public void handle(String identifier, PacketSerializer serializer) { @ApiStatus.Internal @SuppressWarnings("unchecked") public void handle(ClientboundHypixelPacket packet) { - Collection> typedHandlers = handlers.get(getRegistry().getIdentifier(packet.getClass())); + Collection> typedHandlers = handlers.get(packet.getIdentifier()); // nothing registered for this packet. if (typedHandlers == null) return; for (RegisteredHandlerImpl handler : typedHandlers) { @@ -199,12 +199,12 @@ public void onError(ErrorHandler errorHandler) { this.errorHandler = errorHandler; } - public void handle(ClientboundHypixelPacket packet) { + void handle(ClientboundHypixelPacket packet) { // this cast is safe as we ensure its type when it is added to the handlers list in the first place. handler.handle((T) packet); } - public void handleError(ErrorReason reason) { + void handleError(ErrorReason reason) { if (errorHandler != null) { errorHandler.onError(reason); }