diff --git a/pom.xml b/pom.xml index 3cdb3d3..a633051 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ net.hypixel mod-api - 0.2.1 + dev-SNAPSHOT 8 @@ -14,6 +14,13 @@ UTF-8 + + + Hypixel + https://repo.hypixel.net/repository/Hypixel/ + + + Hypixel @@ -39,6 +46,12 @@ hypixel-data 0.1.2 + + org.junit.jupiter + junit-jupiter-engine + 5.9.2 + test + @@ -66,6 +79,11 @@ + + org.apache.maven.plugins + maven-surefire-plugin + 2.22.2 + diff --git a/src/main/java/net/hypixel/modapi/HypixelModAPI.java b/src/main/java/net/hypixel/modapi/HypixelModAPI.java index 64de208..3f3dff9 100644 --- a/src/main/java/net/hypixel/modapi/HypixelModAPI.java +++ b/src/main/java/net/hypixel/modapi/HypixelModAPI.java @@ -4,7 +4,15 @@ import net.hypixel.modapi.error.ModAPIException; import net.hypixel.modapi.handler.ClientboundPacketHandler; import net.hypixel.modapi.packet.HypixelPacket; -import net.hypixel.modapi.packet.HypixelPacketType; +import net.hypixel.modapi.packet.PacketRegistry; +import net.hypixel.modapi.packet.impl.clientbound.ClientboundLocationPacket; +import net.hypixel.modapi.packet.impl.clientbound.ClientboundPartyInfoPacket; +import net.hypixel.modapi.packet.impl.clientbound.ClientboundPingPacket; +import net.hypixel.modapi.packet.impl.clientbound.ClientboundPlayerInfoPacket; +import net.hypixel.modapi.packet.impl.serverbound.ServerboundLocationPacket; +import net.hypixel.modapi.packet.impl.serverbound.ServerboundPartyInfoPacket; +import net.hypixel.modapi.packet.impl.serverbound.ServerboundPingPacket; +import net.hypixel.modapi.packet.impl.serverbound.ServerboundPlayerInfoPacket; import net.hypixel.modapi.serializer.PacketSerializer; import java.util.List; @@ -17,33 +25,49 @@ public static HypixelModAPI getInstance() { return INSTANCE; } - private final List packetHandlers = new CopyOnWriteArrayList<>(); + private final PacketRegistry registry = new PacketRegistry(); + private final List handlers = new CopyOnWriteArrayList<>(); private HypixelModAPI() { + registry.registerPacketType("hypixel:ping", + ClientboundPingPacket.class, ClientboundPingPacket::new, + ServerboundPingPacket.class, ServerboundPingPacket::new); + registry.registerPacketType("hypixel:location", + ClientboundLocationPacket.class, ClientboundLocationPacket::new, + ServerboundLocationPacket.class, ServerboundLocationPacket::new); + registry.registerPacketType("hypixel:party_info", + ClientboundPartyInfoPacket.class, ClientboundPartyInfoPacket::new, + ServerboundPartyInfoPacket.class, ServerboundPartyInfoPacket::new); + registry.registerPacketType("hypixel:player_info", + ClientboundPlayerInfoPacket.class, ClientboundPlayerInfoPacket::new, + ServerboundPlayerInfoPacket.class, ServerboundPlayerInfoPacket::new); + } + + public PacketRegistry getRegistry() { + return registry; } public void registerHandler(ClientboundPacketHandler handler) { - packetHandlers.add(handler); + handlers.add(handler); } public void handle(String identifier, PacketSerializer serializer) { - if (packetHandlers.isEmpty()) { + if (handlers.isEmpty()) { return; } - HypixelPacketType packetType = HypixelPacketType.getByIdentifier(identifier); - if (packetType == null) { + if (!registry.isRegistered(identifier)) { return; } - // All responses contain a boolean of if the response is a success, if not then a string is included with the error message + // 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(packetType, reason); + throw new ModAPIException(identifier, reason); } - HypixelPacket packet = packetType.getPacketFactory().apply(serializer); - for (ClientboundPacketHandler handler : packetHandlers) { + HypixelPacket packet = registry.createClientboundPacket(identifier, serializer); + for (ClientboundPacketHandler handler : handlers) { handler.handle(packet); } } diff --git a/src/main/java/net/hypixel/modapi/error/ModAPIException.java b/src/main/java/net/hypixel/modapi/error/ModAPIException.java index 2b8857b..934474d 100644 --- a/src/main/java/net/hypixel/modapi/error/ModAPIException.java +++ b/src/main/java/net/hypixel/modapi/error/ModAPIException.java @@ -1,19 +1,17 @@ package net.hypixel.modapi.error; -import net.hypixel.modapi.packet.HypixelPacketType; - public class ModAPIException extends RuntimeException { - private final HypixelPacketType packetType; + private final String identifier; private final ErrorReason reason; - public ModAPIException(HypixelPacketType packetType, ErrorReason reason) { - super(String.format("Received error response '%s' from packet '%s'", reason, packetType)); - this.packetType = packetType; + public ModAPIException(String identifier, ErrorReason reason) { + super(String.format("Received error response '%s' from packet '%s'", reason, identifier)); + this.identifier = identifier; this.reason = reason; } - public HypixelPacketType getPacketType() { - return packetType; + public String getIdentifier() { + return identifier; } public ErrorReason getReason() { @@ -23,7 +21,7 @@ public ErrorReason getReason() { @Override public String toString() { return "ModAPIException{" + - "packetType=" + packetType + + "identifier='" + identifier + '\'' + ", reason=" + reason + "} " + super.toString(); } diff --git a/src/main/java/net/hypixel/modapi/packet/HypixelPacket.java b/src/main/java/net/hypixel/modapi/packet/HypixelPacket.java index f71492e..610d9cd 100644 --- a/src/main/java/net/hypixel/modapi/packet/HypixelPacket.java +++ b/src/main/java/net/hypixel/modapi/packet/HypixelPacket.java @@ -1,11 +1,14 @@ package net.hypixel.modapi.packet; +import net.hypixel.modapi.HypixelModAPI; import net.hypixel.modapi.serializer.PacketSerializer; public interface HypixelPacket { - HypixelPacketType getType(); - void write(PacketSerializer serializer); + default String getIdentifier() { + return HypixelModAPI.getInstance().getRegistry().getIdentifier(getClass()); + } + } diff --git a/src/main/java/net/hypixel/modapi/packet/HypixelPacketType.java b/src/main/java/net/hypixel/modapi/packet/HypixelPacketType.java deleted file mode 100644 index fff4652..0000000 --- a/src/main/java/net/hypixel/modapi/packet/HypixelPacketType.java +++ /dev/null @@ -1,44 +0,0 @@ -package net.hypixel.modapi.packet; - -import net.hypixel.modapi.packet.impl.clientbound.ClientboundLocationPacket; -import net.hypixel.modapi.packet.impl.clientbound.ClientboundPartyInfoPacket; -import net.hypixel.modapi.packet.impl.clientbound.ClientboundPingPacket; -import net.hypixel.modapi.packet.impl.clientbound.ClientboundPlayerInfoPacket; -import net.hypixel.modapi.serializer.PacketSerializer; -import org.jetbrains.annotations.Nullable; - -import java.util.Arrays; -import java.util.HashMap; -import java.util.Map; -import java.util.function.Function; - -public enum HypixelPacketType { - PING(ClientboundPingPacket::new), - LOCATION(ClientboundLocationPacket::new), - PARTY_INFO(ClientboundPartyInfoPacket::new), - PLAYER_INFO(ClientboundPlayerInfoPacket::new), - ; - private static final String IDENTIFIER_PREFIX = "hypixel:"; - private static final Map BY_IDENTIFIER = Arrays.stream(values()).collect(HashMap::new, (map, type) -> map.put(type.getIdentifier(), type), HashMap::putAll); - private final Function packetFactory; - - @Nullable - public static HypixelPacketType getByIdentifier(String identifier) { - return BY_IDENTIFIER.get(identifier); - } - - private final String identifier; - - HypixelPacketType(Function packetFactory) { - this.identifier = IDENTIFIER_PREFIX + name().toLowerCase(); - this.packetFactory = packetFactory; - } - - public String getIdentifier() { - return identifier; - } - - public Function getPacketFactory() { - return packetFactory; - } -} diff --git a/src/main/java/net/hypixel/modapi/packet/PacketRegistry.java b/src/main/java/net/hypixel/modapi/packet/PacketRegistry.java new file mode 100644 index 0000000..8161015 --- /dev/null +++ b/src/main/java/net/hypixel/modapi/packet/PacketRegistry.java @@ -0,0 +1,68 @@ +package net.hypixel.modapi.packet; + +import net.hypixel.modapi.serializer.PacketSerializer; + +import java.util.Collections; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.function.Function; + +public class PacketRegistry { + + private final Map registrations = new ConcurrentHashMap<>(); + private final Map, String> classToIdentifier = new ConcurrentHashMap<>(); + + public void registerPacketType(String identifier, + Class clientboundClazz, Function clientPacketFactory, + Class serverboundClazz, Function serverPacketFactory) { + registrations.put(identifier, new RegisteredType(clientboundClazz, clientPacketFactory, serverboundClazz, serverPacketFactory)); + classToIdentifier.put(clientboundClazz, identifier); + classToIdentifier.put(serverboundClazz, identifier); + } + + private RegisteredType getRegisteredType(String identifier) { + RegisteredType registeredType = registrations.get(identifier); + if (registeredType == null) { + throw new IllegalArgumentException("Unknown packet identifier: " + identifier); + } + return registeredType; + } + + public boolean isRegistered(String identifier) { + return registrations.containsKey(identifier); + } + + public HypixelPacket createClientboundPacket(String identifier, PacketSerializer serializer) { + return getRegisteredType(identifier).clientPacketFactory.apply(serializer); + } + + public HypixelPacket createServerboundPacket(String identifier, PacketSerializer serializer) { + return getRegisteredType(identifier).serverPacketFactory.apply(serializer); + } + + public String getIdentifier(Class clazz) { + return classToIdentifier.get(clazz); + } + + public Set getIdentifiers() { + return Collections.unmodifiableSet(registrations.keySet()); + } + + private static final class RegisteredType { + + private final Class clientboundClazz; + private final Function clientPacketFactory; + private final Class serverboundClazz; + private final Function serverPacketFactory; + + public RegisteredType(Class clientboundClazz, Function clientPacketFactory, + Class serverboundClazz, Function serverPacketFactory) { + this.clientboundClazz = clientboundClazz; + this.clientPacketFactory = clientPacketFactory; + this.serverboundClazz = serverboundClazz; + this.serverPacketFactory = serverPacketFactory; + } + } + +} diff --git a/src/main/java/net/hypixel/modapi/packet/impl/clientbound/ClientboundLocationPacket.java b/src/main/java/net/hypixel/modapi/packet/impl/clientbound/ClientboundLocationPacket.java index e607fa1..8fd44fc 100644 --- a/src/main/java/net/hypixel/modapi/packet/impl/clientbound/ClientboundLocationPacket.java +++ b/src/main/java/net/hypixel/modapi/packet/impl/clientbound/ClientboundLocationPacket.java @@ -2,7 +2,6 @@ import net.hypixel.data.region.Environment; import net.hypixel.data.type.ServerType; -import net.hypixel.modapi.packet.HypixelPacketType; import net.hypixel.modapi.packet.impl.VersionedPacket; import net.hypixel.modapi.serializer.PacketSerializer; import org.jetbrains.annotations.Nullable; @@ -46,11 +45,6 @@ public ClientboundLocationPacket(PacketSerializer serializer) { this.map = serializer.readBoolean() ? serializer.readString() : null; } - @Override - public HypixelPacketType getType() { - return HypixelPacketType.LOCATION; - } - @Override public void write(PacketSerializer serializer) { super.write(serializer); diff --git a/src/main/java/net/hypixel/modapi/packet/impl/clientbound/ClientboundPartyInfoPacket.java b/src/main/java/net/hypixel/modapi/packet/impl/clientbound/ClientboundPartyInfoPacket.java index a716523..bbb5cb5 100644 --- a/src/main/java/net/hypixel/modapi/packet/impl/clientbound/ClientboundPartyInfoPacket.java +++ b/src/main/java/net/hypixel/modapi/packet/impl/clientbound/ClientboundPartyInfoPacket.java @@ -1,6 +1,5 @@ package net.hypixel.modapi.packet.impl.clientbound; -import net.hypixel.modapi.packet.HypixelPacketType; import net.hypixel.modapi.packet.impl.VersionedPacket; import net.hypixel.modapi.serializer.PacketSerializer; import org.jetbrains.annotations.Nullable; @@ -40,11 +39,6 @@ public ClientboundPartyInfoPacket(PacketSerializer serializer) { this.members = Collections.unmodifiableSet(members); } - @Override - public HypixelPacketType getType() { - return HypixelPacketType.PARTY_INFO; - } - @Override public void write(PacketSerializer serializer) { super.write(serializer); diff --git a/src/main/java/net/hypixel/modapi/packet/impl/clientbound/ClientboundPingPacket.java b/src/main/java/net/hypixel/modapi/packet/impl/clientbound/ClientboundPingPacket.java index ef694ef..5079612 100644 --- a/src/main/java/net/hypixel/modapi/packet/impl/clientbound/ClientboundPingPacket.java +++ b/src/main/java/net/hypixel/modapi/packet/impl/clientbound/ClientboundPingPacket.java @@ -1,6 +1,5 @@ package net.hypixel.modapi.packet.impl.clientbound; -import net.hypixel.modapi.packet.HypixelPacketType; import net.hypixel.modapi.packet.impl.VersionedPacket; import net.hypixel.modapi.serializer.PacketSerializer; @@ -19,11 +18,6 @@ public ClientboundPingPacket(PacketSerializer serializer) { this.response = serializer.readString(); } - @Override - public HypixelPacketType getType() { - return HypixelPacketType.PING; - } - @Override public void write(PacketSerializer serializer) { super.write(serializer); diff --git a/src/main/java/net/hypixel/modapi/packet/impl/clientbound/ClientboundPlayerInfoPacket.java b/src/main/java/net/hypixel/modapi/packet/impl/clientbound/ClientboundPlayerInfoPacket.java index e13f5de..85215f1 100644 --- a/src/main/java/net/hypixel/modapi/packet/impl/clientbound/ClientboundPlayerInfoPacket.java +++ b/src/main/java/net/hypixel/modapi/packet/impl/clientbound/ClientboundPlayerInfoPacket.java @@ -3,7 +3,6 @@ import net.hypixel.data.rank.MonthlyPackageRank; import net.hypixel.data.rank.PackageRank; import net.hypixel.data.rank.PlayerRank; -import net.hypixel.modapi.packet.HypixelPacketType; import net.hypixel.modapi.packet.impl.VersionedPacket; import net.hypixel.modapi.serializer.PacketSerializer; import org.jetbrains.annotations.Nullable; @@ -35,11 +34,6 @@ public ClientboundPlayerInfoPacket(PacketSerializer serializer) { this.prefix = serializer.readBoolean() ? serializer.readString() : null; } - @Override - public HypixelPacketType getType() { - return HypixelPacketType.PLAYER_INFO; - } - @Override public void write(PacketSerializer serializer) { super.write(serializer); diff --git a/src/main/java/net/hypixel/modapi/packet/impl/serverbound/ServerboundLocationPacket.java b/src/main/java/net/hypixel/modapi/packet/impl/serverbound/ServerboundLocationPacket.java index 77b1978..01bfc95 100644 --- a/src/main/java/net/hypixel/modapi/packet/impl/serverbound/ServerboundLocationPacket.java +++ b/src/main/java/net/hypixel/modapi/packet/impl/serverbound/ServerboundLocationPacket.java @@ -1,6 +1,5 @@ package net.hypixel.modapi.packet.impl.serverbound; -import net.hypixel.modapi.packet.HypixelPacketType; import net.hypixel.modapi.packet.impl.VersionedPacket; import net.hypixel.modapi.serializer.PacketSerializer; @@ -15,8 +14,4 @@ public ServerboundLocationPacket(PacketSerializer serializer) { super(serializer); } - @Override - public HypixelPacketType getType() { - return HypixelPacketType.LOCATION; - } } diff --git a/src/main/java/net/hypixel/modapi/packet/impl/serverbound/ServerboundPartyInfoPacket.java b/src/main/java/net/hypixel/modapi/packet/impl/serverbound/ServerboundPartyInfoPacket.java index e980283..5727bf4 100644 --- a/src/main/java/net/hypixel/modapi/packet/impl/serverbound/ServerboundPartyInfoPacket.java +++ b/src/main/java/net/hypixel/modapi/packet/impl/serverbound/ServerboundPartyInfoPacket.java @@ -1,6 +1,5 @@ package net.hypixel.modapi.packet.impl.serverbound; -import net.hypixel.modapi.packet.HypixelPacketType; import net.hypixel.modapi.packet.impl.VersionedPacket; import net.hypixel.modapi.serializer.PacketSerializer; @@ -15,8 +14,4 @@ public ServerboundPartyInfoPacket(PacketSerializer serializer) { super(serializer); } - @Override - public HypixelPacketType getType() { - return HypixelPacketType.PARTY_INFO; - } } diff --git a/src/main/java/net/hypixel/modapi/packet/impl/serverbound/ServerboundPingPacket.java b/src/main/java/net/hypixel/modapi/packet/impl/serverbound/ServerboundPingPacket.java index fbd31e0..b0ced64 100644 --- a/src/main/java/net/hypixel/modapi/packet/impl/serverbound/ServerboundPingPacket.java +++ b/src/main/java/net/hypixel/modapi/packet/impl/serverbound/ServerboundPingPacket.java @@ -1,6 +1,5 @@ package net.hypixel.modapi.packet.impl.serverbound; -import net.hypixel.modapi.packet.HypixelPacketType; import net.hypixel.modapi.packet.impl.VersionedPacket; import net.hypixel.modapi.serializer.PacketSerializer; @@ -15,8 +14,4 @@ public ServerboundPingPacket(PacketSerializer serializer) { super(serializer); } - @Override - public HypixelPacketType getType() { - return HypixelPacketType.PING; - } } diff --git a/src/main/java/net/hypixel/modapi/packet/impl/serverbound/ServerboundPlayerInfoPacket.java b/src/main/java/net/hypixel/modapi/packet/impl/serverbound/ServerboundPlayerInfoPacket.java index 71454d9..32e8ea8 100644 --- a/src/main/java/net/hypixel/modapi/packet/impl/serverbound/ServerboundPlayerInfoPacket.java +++ b/src/main/java/net/hypixel/modapi/packet/impl/serverbound/ServerboundPlayerInfoPacket.java @@ -1,6 +1,5 @@ package net.hypixel.modapi.packet.impl.serverbound; -import net.hypixel.modapi.packet.HypixelPacketType; import net.hypixel.modapi.packet.impl.VersionedPacket; import net.hypixel.modapi.serializer.PacketSerializer; @@ -15,8 +14,4 @@ public ServerboundPlayerInfoPacket(PacketSerializer serializer) { super(serializer); } - @Override - public HypixelPacketType getType() { - return HypixelPacketType.PLAYER_INFO; - } } diff --git a/src/test/java/net/hypixe/modapi/TestPacketIdentifierLength.java b/src/test/java/net/hypixe/modapi/TestPacketIdentifierLength.java new file mode 100644 index 0000000..9932960 --- /dev/null +++ b/src/test/java/net/hypixe/modapi/TestPacketIdentifierLength.java @@ -0,0 +1,17 @@ +package net.hypixe.modapi; + +import net.hypixel.modapi.HypixelModAPI; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +public class TestPacketIdentifierLength { + private static final int LIMIT = 20; + + @Test + void testPacketIdentifierLength() { + for (String identifier : HypixelModAPI.getInstance().getRegistry().getIdentifiers()) { + Assertions.assertTrue(identifier.length() <= LIMIT, String.format("Identifier %s is too long (length %d)", identifier, identifier.length())); + } + } + +}