From 8d2efb30df31b4f1c947d9d20a7357cab5506519 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maurice=20Eisenbl=C3=A4tter?= Date: Sun, 22 Sep 2024 23:10:50 +0200 Subject: [PATCH 1/6] feat(api): add some basic api interfaces --- .../dev/protocollib/api/BinaryPacket.java | 8 +++++ .../java/dev/protocollib/api/Connection.java | 30 +++++++++++++++++++ .../dev/protocollib/api/PacketContainer.java | 9 ++++++ .../dev/protocollib/api/PacketDirection.java | 7 +++++ .../java/dev/protocollib/api/PacketEvent.java | 11 +++++++ .../dev/protocollib/api/PacketListener.java | 8 +++++ .../api/PacketListenerBuilder.java | 16 ++++++++++ .../api/PacketListenerPriority.java | 7 +++++ .../api/PacketListenerRegistration.java | 6 ++++ .../java/dev/protocollib/api/PacketType.java | 13 ++++++++ .../java/dev/protocollib/api/PacketTypes.java | 7 +++++ .../java/dev/protocollib/api/ProtocolLib.java | 12 ++++++++ .../dev/protocollib/api/ProtocolPhase.java | 7 +++++ 13 files changed, 141 insertions(+) create mode 100644 src/main/java/dev/protocollib/api/BinaryPacket.java create mode 100644 src/main/java/dev/protocollib/api/Connection.java create mode 100644 src/main/java/dev/protocollib/api/PacketContainer.java create mode 100644 src/main/java/dev/protocollib/api/PacketDirection.java create mode 100644 src/main/java/dev/protocollib/api/PacketEvent.java create mode 100644 src/main/java/dev/protocollib/api/PacketListener.java create mode 100644 src/main/java/dev/protocollib/api/PacketListenerBuilder.java create mode 100644 src/main/java/dev/protocollib/api/PacketListenerPriority.java create mode 100644 src/main/java/dev/protocollib/api/PacketListenerRegistration.java create mode 100644 src/main/java/dev/protocollib/api/PacketType.java create mode 100644 src/main/java/dev/protocollib/api/PacketTypes.java create mode 100644 src/main/java/dev/protocollib/api/ProtocolLib.java create mode 100644 src/main/java/dev/protocollib/api/ProtocolPhase.java diff --git a/src/main/java/dev/protocollib/api/BinaryPacket.java b/src/main/java/dev/protocollib/api/BinaryPacket.java new file mode 100644 index 000000000..75da830c2 --- /dev/null +++ b/src/main/java/dev/protocollib/api/BinaryPacket.java @@ -0,0 +1,8 @@ +package dev.protocollib.api; + +public interface BinaryPacket { + + int id(); + + byte[] payload(); +} diff --git a/src/main/java/dev/protocollib/api/Connection.java b/src/main/java/dev/protocollib/api/Connection.java new file mode 100644 index 000000000..4ea34bde3 --- /dev/null +++ b/src/main/java/dev/protocollib/api/Connection.java @@ -0,0 +1,30 @@ +package dev.protocollib.api; + +import java.net.InetSocketAddress; + +import javax.annotation.Nullable; + +import org.bukkit.entity.Player; + +public interface Connection { + + @Nullable + Player player(); + + InetSocketAddress address(); + + int protocolVersion(); + + ProtocolPhase protocolPhase(PacketDirection packetDirection); + + boolean isConnected(); + + void sendPacket(BinaryPacket packet); + + void sendPacket(PacketContainer packet); + + void receivePacket(PacketContainer packet); + + void disconnect(String reason); + +} diff --git a/src/main/java/dev/protocollib/api/PacketContainer.java b/src/main/java/dev/protocollib/api/PacketContainer.java new file mode 100644 index 000000000..4a1af7cf8 --- /dev/null +++ b/src/main/java/dev/protocollib/api/PacketContainer.java @@ -0,0 +1,9 @@ +package dev.protocollib.api; + +public interface PacketContainer { + + PacketType packetType(); + + Object packet(); + +} diff --git a/src/main/java/dev/protocollib/api/PacketDirection.java b/src/main/java/dev/protocollib/api/PacketDirection.java new file mode 100644 index 000000000..541c54cdc --- /dev/null +++ b/src/main/java/dev/protocollib/api/PacketDirection.java @@ -0,0 +1,7 @@ +package dev.protocollib.api; + +public enum PacketDirection { + + SERVERBOUND, CLIENTBOUND; + +} diff --git a/src/main/java/dev/protocollib/api/PacketEvent.java b/src/main/java/dev/protocollib/api/PacketEvent.java new file mode 100644 index 000000000..7e93a5958 --- /dev/null +++ b/src/main/java/dev/protocollib/api/PacketEvent.java @@ -0,0 +1,11 @@ +package dev.protocollib.api; + +import org.bukkit.event.Cancellable; + +public interface PacketEvent extends Cancellable { + + Connection connection(); + + PacketContainer packet(); + +} diff --git a/src/main/java/dev/protocollib/api/PacketListener.java b/src/main/java/dev/protocollib/api/PacketListener.java new file mode 100644 index 000000000..392b80d9c --- /dev/null +++ b/src/main/java/dev/protocollib/api/PacketListener.java @@ -0,0 +1,8 @@ +package dev.protocollib.api; + +@FunctionalInterface +public interface PacketListener { + + void handlePacket(PacketEvent event); + +} diff --git a/src/main/java/dev/protocollib/api/PacketListenerBuilder.java b/src/main/java/dev/protocollib/api/PacketListenerBuilder.java new file mode 100644 index 000000000..8a044643a --- /dev/null +++ b/src/main/java/dev/protocollib/api/PacketListenerBuilder.java @@ -0,0 +1,16 @@ +package dev.protocollib.api; + +import java.util.Collection; + +public interface PacketListenerBuilder { + + PacketListenerBuilder types(PacketType...packetTypes); + + PacketListenerBuilder types(Collection packetTypes); + + PacketListenerBuilder priority(PacketListenerPriority priority); + + PacketListenerBuilder listener(PacketListener listener); + + PacketListenerRegistration register(); +} diff --git a/src/main/java/dev/protocollib/api/PacketListenerPriority.java b/src/main/java/dev/protocollib/api/PacketListenerPriority.java new file mode 100644 index 000000000..8c3bc8f89 --- /dev/null +++ b/src/main/java/dev/protocollib/api/PacketListenerPriority.java @@ -0,0 +1,7 @@ +package dev.protocollib.api; + +public enum PacketListenerPriority { + + LOWEST, LOW, NORMAL, HIGH, HIGHEST, MONITOR; + +} diff --git a/src/main/java/dev/protocollib/api/PacketListenerRegistration.java b/src/main/java/dev/protocollib/api/PacketListenerRegistration.java new file mode 100644 index 000000000..a26b32780 --- /dev/null +++ b/src/main/java/dev/protocollib/api/PacketListenerRegistration.java @@ -0,0 +1,6 @@ +package dev.protocollib.api; + +public interface PacketListenerRegistration { + + void unregister(); +} diff --git a/src/main/java/dev/protocollib/api/PacketType.java b/src/main/java/dev/protocollib/api/PacketType.java new file mode 100644 index 000000000..406046972 --- /dev/null +++ b/src/main/java/dev/protocollib/api/PacketType.java @@ -0,0 +1,13 @@ +package dev.protocollib.api; + +public interface PacketType { + + PacketDirection packetDirection(); + + Class packetClass(); + + boolean isSupported(); + + boolean isDeprecated(); + +} diff --git a/src/main/java/dev/protocollib/api/PacketTypes.java b/src/main/java/dev/protocollib/api/PacketTypes.java new file mode 100644 index 000000000..8a623ccf3 --- /dev/null +++ b/src/main/java/dev/protocollib/api/PacketTypes.java @@ -0,0 +1,7 @@ +package dev.protocollib.api; + +public class PacketTypes { + + // TODO should contain all packet types as public static final fields + +} diff --git a/src/main/java/dev/protocollib/api/ProtocolLib.java b/src/main/java/dev/protocollib/api/ProtocolLib.java new file mode 100644 index 000000000..ee10801af --- /dev/null +++ b/src/main/java/dev/protocollib/api/ProtocolLib.java @@ -0,0 +1,12 @@ +package dev.protocollib.api; + +import org.bukkit.entity.Player; +import org.bukkit.plugin.Plugin; + +public interface ProtocolLib { + + PacketListenerBuilder createListener(Plugin plugin); + + Connection connection(Player player); + +} diff --git a/src/main/java/dev/protocollib/api/ProtocolPhase.java b/src/main/java/dev/protocollib/api/ProtocolPhase.java new file mode 100644 index 000000000..a01084656 --- /dev/null +++ b/src/main/java/dev/protocollib/api/ProtocolPhase.java @@ -0,0 +1,7 @@ +package dev.protocollib.api; + +public enum ProtocolPhase { + + HANDSHAKE, PLAY, STATUS, LOGIN, CONFIGURATION, UNKNOWN; + +} From ba5f278419fb06c6e10802d79e1d7801e2c90675 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maurice=20Eisenbl=C3=A4tter?= Date: Mon, 21 Oct 2024 23:47:44 +0200 Subject: [PATCH 2/6] feat(api): add basic packet processing interfaces --- .../dev/protocollib/api/BinaryPacket.java | 14 ++++ .../java/dev/protocollib/api/Connection.java | 75 +++++++++++++++++-- .../dev/protocollib/api/PacketContainer.java | 13 ++++ .../dev/protocollib/api/PacketDirection.java | 7 -- .../java/dev/protocollib/api/PacketEvent.java | 11 --- .../dev/protocollib/api/PacketListener.java | 8 -- .../api/PacketListenerBuilder.java | 16 ---- .../api/PacketListenerPriority.java | 7 -- .../api/PacketListenerRegistration.java | 6 -- .../java/dev/protocollib/api/PacketType.java | 37 +++++++-- .../protocollib/api/ProtocolDirection.java | 14 ++++ .../java/dev/protocollib/api/ProtocolLib.java | 35 ++++++++- .../dev/protocollib/api/ProtocolPhase.java | 3 + .../api/listener/AsyncPacketListener.java | 32 ++++++++ .../listener/AsyncPacketListenerContext.java | 21 ++++++ .../api/listener/PacketListenerBuilder.java | 74 ++++++++++++++++++ .../api/listener/PacketListenerPriority.java | 22 ++++++ .../listener/PacketListenerRegistration.java | 14 ++++ .../api/listener/PacketSentListener.java | 16 ++++ .../api/listener/SyncPacketListener.java | 19 +++++ .../listener/SyncPacketListenerContext.java | 36 +++++++++ 21 files changed, 414 insertions(+), 66 deletions(-) delete mode 100644 src/main/java/dev/protocollib/api/PacketDirection.java delete mode 100644 src/main/java/dev/protocollib/api/PacketEvent.java delete mode 100644 src/main/java/dev/protocollib/api/PacketListener.java delete mode 100644 src/main/java/dev/protocollib/api/PacketListenerBuilder.java delete mode 100644 src/main/java/dev/protocollib/api/PacketListenerPriority.java delete mode 100644 src/main/java/dev/protocollib/api/PacketListenerRegistration.java create mode 100644 src/main/java/dev/protocollib/api/ProtocolDirection.java create mode 100644 src/main/java/dev/protocollib/api/listener/AsyncPacketListener.java create mode 100644 src/main/java/dev/protocollib/api/listener/AsyncPacketListenerContext.java create mode 100644 src/main/java/dev/protocollib/api/listener/PacketListenerBuilder.java create mode 100644 src/main/java/dev/protocollib/api/listener/PacketListenerPriority.java create mode 100644 src/main/java/dev/protocollib/api/listener/PacketListenerRegistration.java create mode 100644 src/main/java/dev/protocollib/api/listener/PacketSentListener.java create mode 100644 src/main/java/dev/protocollib/api/listener/SyncPacketListener.java create mode 100644 src/main/java/dev/protocollib/api/listener/SyncPacketListenerContext.java diff --git a/src/main/java/dev/protocollib/api/BinaryPacket.java b/src/main/java/dev/protocollib/api/BinaryPacket.java index 75da830c2..bdc14e2b9 100644 --- a/src/main/java/dev/protocollib/api/BinaryPacket.java +++ b/src/main/java/dev/protocollib/api/BinaryPacket.java @@ -1,8 +1,22 @@ package dev.protocollib.api; +/** + * Representing a raw binary packet with a packet id and payload. + */ public interface BinaryPacket { + /** + * Retrieves the packet id. + * + * @return the packet ID + */ int id(); + /** + * Retrieves the payload (data) of the packet. + * + * @return the packet payload as a byte array + */ byte[] payload(); } + diff --git a/src/main/java/dev/protocollib/api/Connection.java b/src/main/java/dev/protocollib/api/Connection.java index 4ea34bde3..9e6825506 100644 --- a/src/main/java/dev/protocollib/api/Connection.java +++ b/src/main/java/dev/protocollib/api/Connection.java @@ -1,30 +1,95 @@ package dev.protocollib.api; import java.net.InetSocketAddress; - -import javax.annotation.Nullable; +import java.util.Optional; import org.bukkit.entity.Player; +import dev.protocollib.api.listener.PacketSentListener; + +/** + * Representing a connection of a player. + */ public interface Connection { - @Nullable - Player player(); + /** + * Retrieves the player associated with the connection, if available. + * + * @return an optional containing the player, or empty if the player is not present + */ + Optional player(); + /** + * Retrieves the address of the connection. + * + * @return the remote address of the connection + */ InetSocketAddress address(); + /** + * Retrieves the protocol version used by the connection. + * + * @return the protocol version + */ int protocolVersion(); - ProtocolPhase protocolPhase(PacketDirection packetDirection); + /** + * Retrieves the current protocol phase of the connection for a given direction. + * + * @param packetDirection the direction of the packet (clientbound or serverbound) + * @return the protocol phase of the connection + */ + ProtocolPhase protocolPhase(ProtocolDirection packetDirection); + /** + * Checks if the connection is currently open. + * + * @return true if the connection is open, false otherwise + */ boolean isConnected(); + /** + * Sends a binary packet over the connection. + * + * @param packet the binary packet to send + */ void sendPacket(BinaryPacket packet); + /** + * Sends a binary packet over the connection and registers a listener for when the packet is sent. + * + * @param packet the binary packet to send + * @param listener the listener to invoke once the packet is sent + */ + void sendPacket(BinaryPacket packet, PacketSentListener listener); + + /** + * Sends a packet container over the connection. + * + * @param packet the packet container to send + */ void sendPacket(PacketContainer packet); + /** + * Sends a packet container over the connection and registers a listener for when the packet is sent. + * + * @param packet the packet container to send + * @param listener the listener to invoke once the packet is sent + */ + void sendPacket(PacketContainer packet, PacketSentListener listener); + + /** + * Receives a packet container from the connection. + * + * @param packet the packet container received + */ void receivePacket(PacketContainer packet); + /** + * Disconnects the connection with the specified reason. + * + * @param reason the reason for disconnecting + */ void disconnect(String reason); } diff --git a/src/main/java/dev/protocollib/api/PacketContainer.java b/src/main/java/dev/protocollib/api/PacketContainer.java index 4a1af7cf8..f23655c6e 100644 --- a/src/main/java/dev/protocollib/api/PacketContainer.java +++ b/src/main/java/dev/protocollib/api/PacketContainer.java @@ -1,9 +1,22 @@ package dev.protocollib.api; +/** + * Representing a container for a packet. + */ public interface PacketContainer { + /** + * Retrieves the type of the packet. + * + * @return the packet type + */ PacketType packetType(); + /** + * Retrieves the raw packet object. + * + * @return the packet object + */ Object packet(); } diff --git a/src/main/java/dev/protocollib/api/PacketDirection.java b/src/main/java/dev/protocollib/api/PacketDirection.java deleted file mode 100644 index 541c54cdc..000000000 --- a/src/main/java/dev/protocollib/api/PacketDirection.java +++ /dev/null @@ -1,7 +0,0 @@ -package dev.protocollib.api; - -public enum PacketDirection { - - SERVERBOUND, CLIENTBOUND; - -} diff --git a/src/main/java/dev/protocollib/api/PacketEvent.java b/src/main/java/dev/protocollib/api/PacketEvent.java deleted file mode 100644 index 7e93a5958..000000000 --- a/src/main/java/dev/protocollib/api/PacketEvent.java +++ /dev/null @@ -1,11 +0,0 @@ -package dev.protocollib.api; - -import org.bukkit.event.Cancellable; - -public interface PacketEvent extends Cancellable { - - Connection connection(); - - PacketContainer packet(); - -} diff --git a/src/main/java/dev/protocollib/api/PacketListener.java b/src/main/java/dev/protocollib/api/PacketListener.java deleted file mode 100644 index 392b80d9c..000000000 --- a/src/main/java/dev/protocollib/api/PacketListener.java +++ /dev/null @@ -1,8 +0,0 @@ -package dev.protocollib.api; - -@FunctionalInterface -public interface PacketListener { - - void handlePacket(PacketEvent event); - -} diff --git a/src/main/java/dev/protocollib/api/PacketListenerBuilder.java b/src/main/java/dev/protocollib/api/PacketListenerBuilder.java deleted file mode 100644 index 8a044643a..000000000 --- a/src/main/java/dev/protocollib/api/PacketListenerBuilder.java +++ /dev/null @@ -1,16 +0,0 @@ -package dev.protocollib.api; - -import java.util.Collection; - -public interface PacketListenerBuilder { - - PacketListenerBuilder types(PacketType...packetTypes); - - PacketListenerBuilder types(Collection packetTypes); - - PacketListenerBuilder priority(PacketListenerPriority priority); - - PacketListenerBuilder listener(PacketListener listener); - - PacketListenerRegistration register(); -} diff --git a/src/main/java/dev/protocollib/api/PacketListenerPriority.java b/src/main/java/dev/protocollib/api/PacketListenerPriority.java deleted file mode 100644 index 8c3bc8f89..000000000 --- a/src/main/java/dev/protocollib/api/PacketListenerPriority.java +++ /dev/null @@ -1,7 +0,0 @@ -package dev.protocollib.api; - -public enum PacketListenerPriority { - - LOWEST, LOW, NORMAL, HIGH, HIGHEST, MONITOR; - -} diff --git a/src/main/java/dev/protocollib/api/PacketListenerRegistration.java b/src/main/java/dev/protocollib/api/PacketListenerRegistration.java deleted file mode 100644 index a26b32780..000000000 --- a/src/main/java/dev/protocollib/api/PacketListenerRegistration.java +++ /dev/null @@ -1,6 +0,0 @@ -package dev.protocollib.api; - -public interface PacketListenerRegistration { - - void unregister(); -} diff --git a/src/main/java/dev/protocollib/api/PacketType.java b/src/main/java/dev/protocollib/api/PacketType.java index 406046972..18290de30 100644 --- a/src/main/java/dev/protocollib/api/PacketType.java +++ b/src/main/java/dev/protocollib/api/PacketType.java @@ -1,13 +1,40 @@ package dev.protocollib.api; -public interface PacketType { +import java.util.Optional; - PacketDirection packetDirection(); +import net.kyori.adventure.key.Keyed; - Class packetClass(); +/** + * Representing the type of a network packet. + * + *

A {@code PacketType} identifies a specific type of packet in the protocol, + * including information about its direction, associated class (if any), and + * whether the packet is currently supported.

+ */ +public interface PacketType extends Keyed { - boolean isSupported(); + /** + * Retrieves the direction in which the packet is being sent. + * + * @return the {@link ProtocolDirection} of the packet, either clientbound or serverbound + */ + ProtocolDirection protocolDirection(); + + /** + * Retrieves the class associated with the packet type, if available. + * + *

Not all packet types have an associated class. If there is no class, + * an empty {@link Optional} is returned.

+ * + * @return an {@link Optional} containing the class of the packet, or empty if not applicable + */ + Optional> packetClass(); - boolean isDeprecated(); + /** + * Checks whether the packet type is supported by the current protocol version. + * + * @return {@code true} if the packet type is supported, {@code false} otherwise + */ + boolean isSupported(); } diff --git a/src/main/java/dev/protocollib/api/ProtocolDirection.java b/src/main/java/dev/protocollib/api/ProtocolDirection.java new file mode 100644 index 000000000..f9e8b055d --- /dev/null +++ b/src/main/java/dev/protocollib/api/ProtocolDirection.java @@ -0,0 +1,14 @@ +package dev.protocollib.api; + +/** + * Representing the direction of a packet, either sent to or from the server. + */ +public enum ProtocolDirection { + + /** Packet sent from the client to the server. */ + SERVERBOUND, + + /** Packet sent from the server to the client. */ + CLIENTBOUND; + +} diff --git a/src/main/java/dev/protocollib/api/ProtocolLib.java b/src/main/java/dev/protocollib/api/ProtocolLib.java index ee10801af..859c7b441 100644 --- a/src/main/java/dev/protocollib/api/ProtocolLib.java +++ b/src/main/java/dev/protocollib/api/ProtocolLib.java @@ -3,10 +3,43 @@ import org.bukkit.entity.Player; import org.bukkit.plugin.Plugin; +import dev.protocollib.api.listener.PacketListenerBuilder; + +/** + * Representing the main entry point for the ProtocolLib API. + */ public interface ProtocolLib { + /** + * Creates a packet listener for the provided plugin. + * + * @param plugin the plugin registering the packet listener + * @return a builder to configure and register the packet listener + */ PacketListenerBuilder createListener(Plugin plugin); - + + /** + * Retrieves the connection associated with a specific player. + * + * @param player the player whose connection is being retrieved + * @return the connection for the specified player + */ Connection connection(Player player); + /** + * Creates a new binary packet with the given type and payload. + * + * @param packetType the type of the packet to create + * @param payload the binary payload to include in the packet + * @return a new {@link BinaryPacket} instance + */ + BinaryPacket createBinaryPacket(PacketType packetType, byte[] payload); + + /** + * Creates a new packet container for the given packet type. + * + * @param packetType the type of the packet to create + * @return a new {@link PacketContainer} instance + */ + PacketContainer createPacket(PacketType packetType); } diff --git a/src/main/java/dev/protocollib/api/ProtocolPhase.java b/src/main/java/dev/protocollib/api/ProtocolPhase.java index a01084656..e3b92e02a 100644 --- a/src/main/java/dev/protocollib/api/ProtocolPhase.java +++ b/src/main/java/dev/protocollib/api/ProtocolPhase.java @@ -1,5 +1,8 @@ package dev.protocollib.api; +/** + * Representing the different protocol phases of a minecraft. + */ public enum ProtocolPhase { HANDSHAKE, PLAY, STATUS, LOGIN, CONFIGURATION, UNKNOWN; diff --git a/src/main/java/dev/protocollib/api/listener/AsyncPacketListener.java b/src/main/java/dev/protocollib/api/listener/AsyncPacketListener.java new file mode 100644 index 000000000..e9196bd41 --- /dev/null +++ b/src/main/java/dev/protocollib/api/listener/AsyncPacketListener.java @@ -0,0 +1,32 @@ +package dev.protocollib.api.listener; + +import dev.protocollib.api.PacketContainer; + +/** + * Functional interface for handling packets asynchronously. + * + *

Once a packet is processed by the listener, the context's + * {@code resumeProcessing()} or {@code resumeProcessingWithException(Throwable)} + * methods must be called to signal that the listener is done with the packet. + * Failing to call one of these methods will cause the packet to remain in + * a waiting state until it times out, preventing further listeners from + * receiving the packet. + *

+ */ +@FunctionalInterface +public interface AsyncPacketListener { + + /** + * Handles a packet that was sent or received, asynchronously. + * + *

Once processing is complete, ensure that one of the {@code resumeProcessing} + * methods from the {@link AsyncPacketListenerContext} is called. This allows the + * packet to continue to the next listener. If not called, the packet will remain + * in a waiting state and will only proceed after a timeout occurs.

+ * + * @param packet the packet to handle + * @param context the context providing additional information about the packet and connection + */ + void handlePacket(PacketContainer packet, AsyncPacketListenerContext context); + +} diff --git a/src/main/java/dev/protocollib/api/listener/AsyncPacketListenerContext.java b/src/main/java/dev/protocollib/api/listener/AsyncPacketListenerContext.java new file mode 100644 index 000000000..3676edcfa --- /dev/null +++ b/src/main/java/dev/protocollib/api/listener/AsyncPacketListenerContext.java @@ -0,0 +1,21 @@ +package dev.protocollib.api.listener; + +/** + * Representing the context of an asynchronous packet listener. + */ +public interface AsyncPacketListenerContext extends SyncPacketListenerContext { + + /** + * Singles the listener is done with processing the packet. + */ + void resumeProcessing(); + + /** + * Singles the listener is done with processing the packet and finished + * with an exception. + * + * @param throwable the processing exception + */ + void resumeProcessingWithException(Throwable throwable); + +} diff --git a/src/main/java/dev/protocollib/api/listener/PacketListenerBuilder.java b/src/main/java/dev/protocollib/api/listener/PacketListenerBuilder.java new file mode 100644 index 000000000..4cb9e4fba --- /dev/null +++ b/src/main/java/dev/protocollib/api/listener/PacketListenerBuilder.java @@ -0,0 +1,74 @@ +package dev.protocollib.api.listener; + +import java.util.Collection; + +import dev.protocollib.api.PacketType; + +/** + * Builder for creating and registering packet listeners. + */ +public interface PacketListenerBuilder { + + /** + * Specifies the types of packets to listen for. + * + * @param packetTypes the packet types to listen for + * @return the same builder for further configuration + */ + PacketListenerBuilder.WithType types(PacketType... packetTypes); + + /** + * Specifies the types of packets to listen for. + * + * @param packetTypes the collection of packet types to listen for + * @return the same builder for further configuration + */ + PacketListenerBuilder.WithType types(Collection packetTypes); + + /** + * Interface for building a packet listener with specific packet types. + */ + public interface WithType { + + /** + * Specifies the priority of the packet listener. + * + * @param priority the priority to assign to the listener + * @return the same builder for further configuration + */ + PacketListenerBuilder.WithType priority(PacketListenerPriority priority); + + /** + * Marks the listener as immutable, preventing modifications of packets + * inside the listener. + * + * @return the same builder for further configuration + */ + PacketListenerBuilder.WithType immutable(); + + /** + * Configures the listener to ignore packets that have been cancelled. + * + * @return the same builder for further configuration + */ + PacketListenerBuilder.WithType ignoreCancelledPackets(); + + /** + * Registers the packet listener to operate synchronously. The listener + * will always get called on the main game thread. + * + * @param listener the synchronous packet listener to register + * @return the same builder for further configuration + */ + PacketListenerRegistration registerSync(SyncPacketListener listener); + + /** + * Registers the packet listener to operate asynchronously. + * + * @param listener the asynchronous packet listener to register + * @return the same builder for further configuration + */ + PacketListenerRegistration registerAsync(AsyncPacketListener listener); + } +} + diff --git a/src/main/java/dev/protocollib/api/listener/PacketListenerPriority.java b/src/main/java/dev/protocollib/api/listener/PacketListenerPriority.java new file mode 100644 index 000000000..b7a912134 --- /dev/null +++ b/src/main/java/dev/protocollib/api/listener/PacketListenerPriority.java @@ -0,0 +1,22 @@ +package dev.protocollib.api.listener; + +/** + * Representing the priority levels for packet listeners. + */ +public enum PacketListenerPriority { + + /** Lowest priority, executed first. */ + LOWEST, + + /** Low priority, executed after lowest but before normal. */ + LOW, + + /** Normal priority, executed after low but before high. */ + NORMAL, + + /** High priority, executed after normal but before highest. */ + HIGH, + + /** Highest priority, executed last. */ + HIGHEST; +} diff --git a/src/main/java/dev/protocollib/api/listener/PacketListenerRegistration.java b/src/main/java/dev/protocollib/api/listener/PacketListenerRegistration.java new file mode 100644 index 000000000..e18a92c66 --- /dev/null +++ b/src/main/java/dev/protocollib/api/listener/PacketListenerRegistration.java @@ -0,0 +1,14 @@ +package dev.protocollib.api.listener; + +/** + * Representing the registration of a packet listener. + * Allows unregistering the listener when no longer needed. + */ +public interface PacketListenerRegistration { + + /** + * Unregisters the packet listener, stopping it from receiving further packets. + */ + void unregister(); +} + diff --git a/src/main/java/dev/protocollib/api/listener/PacketSentListener.java b/src/main/java/dev/protocollib/api/listener/PacketSentListener.java new file mode 100644 index 000000000..dc28b346f --- /dev/null +++ b/src/main/java/dev/protocollib/api/listener/PacketSentListener.java @@ -0,0 +1,16 @@ +package dev.protocollib.api.listener; + +/** + * Functional interface for a listener that is invoked when a packet has been sent. + * + * This method will get invoked on the underlying channel's event-loop. + */ +@FunctionalInterface +public interface PacketSentListener { + + /** + * Invoked when a packet has been successfully sent. + */ + void invoke(); +} + diff --git a/src/main/java/dev/protocollib/api/listener/SyncPacketListener.java b/src/main/java/dev/protocollib/api/listener/SyncPacketListener.java new file mode 100644 index 000000000..1bc35b4ae --- /dev/null +++ b/src/main/java/dev/protocollib/api/listener/SyncPacketListener.java @@ -0,0 +1,19 @@ +package dev.protocollib.api.listener; + +import dev.protocollib.api.PacketContainer; + +/** + * Functional interface for handling packets synchronously. + */ +@FunctionalInterface +public interface SyncPacketListener { + + /** + * Synchronously handles a packet that was sent or received. + * + * @param packet the packet to handle + * @param context the context providing additional information about the packet and functions + */ + void handlePacket(PacketContainer packet, SyncPacketListenerContext context); + +} diff --git a/src/main/java/dev/protocollib/api/listener/SyncPacketListenerContext.java b/src/main/java/dev/protocollib/api/listener/SyncPacketListenerContext.java new file mode 100644 index 000000000..4afa166b1 --- /dev/null +++ b/src/main/java/dev/protocollib/api/listener/SyncPacketListenerContext.java @@ -0,0 +1,36 @@ +package dev.protocollib.api.listener; + +import dev.protocollib.api.Connection; + +/** + * Representing the context of a synchronous packet listener. + */ +public interface SyncPacketListenerContext { + + /** + * Retrieves the connection associated with the packet. + * + * @return the connection handling the packet + */ + Connection connection(); + + /** + * Checks if the packet handling has been cancelled. + * + * @return true if the packet is cancelled, false otherwise + */ + boolean isCancelled(); + + /** + * Cancels the packet, preventing it from being processed further. + */ + void cancel(); + + /** + * Adds a listener to be invoked after the packet is sent. + * + * @param listener the post-sent listener + */ + void addPostSentListener(PacketSentListener listener); +} + From 34ed976c624e37c44679b97e0598ea6d4ee9bb60 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maurice=20Eisenbl=C3=A4tter?= Date: Sat, 26 Oct 2024 03:05:37 +0200 Subject: [PATCH 3/6] feat(api): add send/receive packet methods --- build.gradle | 4 +- .../java/dev/protocollib/api/Connection.java | 53 ++++++++----------- .../java/dev/protocollib/api/ProtocolLib.java | 22 ++++++++ .../api/listener/AsyncPacketListener.java | 2 +- .../api/listener/PacketListenerBuilder.java | 2 +- ...r.java => PacketTransmissionListener.java} | 6 ++- .../api/listener/SyncPacketListener.java | 2 +- .../listener/SyncPacketListenerContext.java | 6 +-- .../api/{ => packet}/BinaryPacket.java | 5 +- .../api/{ => packet}/PacketContainer.java | 11 +++- .../protocollib/api/packet/PacketLike.java | 5 ++ .../api/packet/PacketOperationBuilder.java | 44 +++++++++++++++ .../api/{ => packet}/PacketType.java | 3 +- .../api/{ => packet}/PacketTypes.java | 2 +- 14 files changed, 119 insertions(+), 48 deletions(-) rename src/main/java/dev/protocollib/api/listener/{PacketSentListener.java => PacketTransmissionListener.java} (59%) rename src/main/java/dev/protocollib/api/{ => packet}/BinaryPacket.java (76%) rename src/main/java/dev/protocollib/api/{ => packet}/PacketContainer.java (53%) create mode 100644 src/main/java/dev/protocollib/api/packet/PacketLike.java create mode 100644 src/main/java/dev/protocollib/api/packet/PacketOperationBuilder.java rename src/main/java/dev/protocollib/api/{ => packet}/PacketType.java (93%) rename src/main/java/dev/protocollib/api/{ => packet}/PacketTypes.java (74%) diff --git a/build.gradle b/build.gradle index 058187d92..879cfc783 100644 --- a/build.gradle +++ b/build.gradle @@ -52,8 +52,8 @@ dependencies { } java { - sourceCompatibility = JavaVersion.VERSION_1_8 - targetCompatibility = JavaVersion.VERSION_1_8 + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 withJavadocJar() withSourcesJar() diff --git a/src/main/java/dev/protocollib/api/Connection.java b/src/main/java/dev/protocollib/api/Connection.java index 9e6825506..f789b1833 100644 --- a/src/main/java/dev/protocollib/api/Connection.java +++ b/src/main/java/dev/protocollib/api/Connection.java @@ -5,24 +5,31 @@ import org.bukkit.entity.Player; -import dev.protocollib.api.listener.PacketSentListener; +import dev.protocollib.api.packet.PacketLike; +import dev.protocollib.api.packet.PacketOperationBuilder; /** - * Representing a connection of a player. + * Represents a connection associated with a player. + * + *

This interface provides methods to interact with the player's network connection, + * including retrieving the player's information, connection address, protocol version, + * and current connection state. It also allows for sending and receiving packets + * through the connection.

*/ public interface Connection { + /** * Retrieves the player associated with the connection, if available. * - * @return an optional containing the player, or empty if the player is not present + * @return an {@link Optional} containing the player, or empty if the player is not present */ Optional player(); /** * Retrieves the address of the connection. * - * @return the remote address of the connection + * @return the remote {@link InetSocketAddress} of the connection */ InetSocketAddress address(); @@ -37,53 +44,37 @@ public interface Connection { * Retrieves the current protocol phase of the connection for a given direction. * * @param packetDirection the direction of the packet (clientbound or serverbound) - * @return the protocol phase of the connection + * @return the {@link ProtocolPhase} representing the current phase of the connection */ ProtocolPhase protocolPhase(ProtocolDirection packetDirection); /** * Checks if the connection is currently open. * - * @return true if the connection is open, false otherwise + * @return {@code true} if the connection is open, {@code false} otherwise */ boolean isConnected(); /** - * Sends a binary packet over the connection. - * - * @param packet the binary packet to send - */ - void sendPacket(BinaryPacket packet); - - /** - * Sends a binary packet over the connection and registers a listener for when the packet is sent. - * - * @param packet the binary packet to send - * @param listener the listener to invoke once the packet is sent - */ - void sendPacket(BinaryPacket packet, PacketSentListener listener); - - /** - * Sends a packet container over the connection. + * Initiates a packet operation, which can involve sending or receiving a packet. * - * @param packet the packet container to send + * @return a {@link PacketOperationBuilder} to configure the packet operation */ - void sendPacket(PacketContainer packet); + PacketOperationBuilder packetOperation(); /** - * Sends a packet container over the connection and registers a listener for when the packet is sent. + * Sends a packet to the client. * - * @param packet the packet container to send - * @param listener the listener to invoke once the packet is sent + * @param packet the packet to send */ - void sendPacket(PacketContainer packet, PacketSentListener listener); + void sendPacket(PacketLike packet); /** - * Receives a packet container from the connection. + * Receives a packet as if the client had sent it. * - * @param packet the packet container received + * @param packet the received packet */ - void receivePacket(PacketContainer packet); + void receivePacket(PacketLike packet); /** * Disconnects the connection with the specified reason. diff --git a/src/main/java/dev/protocollib/api/ProtocolLib.java b/src/main/java/dev/protocollib/api/ProtocolLib.java index 859c7b441..dda0bf1ef 100644 --- a/src/main/java/dev/protocollib/api/ProtocolLib.java +++ b/src/main/java/dev/protocollib/api/ProtocolLib.java @@ -4,6 +4,10 @@ import org.bukkit.plugin.Plugin; import dev.protocollib.api.listener.PacketListenerBuilder; +import dev.protocollib.api.packet.BinaryPacket; +import dev.protocollib.api.packet.PacketContainer; +import dev.protocollib.api.packet.PacketLike; +import dev.protocollib.api.packet.PacketType; /** * Representing the main entry point for the ProtocolLib API. @@ -26,6 +30,24 @@ public interface ProtocolLib { */ Connection connection(Player player); + /** + * Sends a packet to the player. + * + * @param packet the packet to send + */ + default void sendPacket(Player player, PacketLike packet) { + connection(player).sendPacket(packet); + } + + /** + * Receives a packet as if the player had sent it. + * + * @param packet the received packet + */ + default void receivePacket(Player player, PacketLike packet) { + connection(player).receivePacket(packet); + } + /** * Creates a new binary packet with the given type and payload. * diff --git a/src/main/java/dev/protocollib/api/listener/AsyncPacketListener.java b/src/main/java/dev/protocollib/api/listener/AsyncPacketListener.java index e9196bd41..9c46ee300 100644 --- a/src/main/java/dev/protocollib/api/listener/AsyncPacketListener.java +++ b/src/main/java/dev/protocollib/api/listener/AsyncPacketListener.java @@ -1,6 +1,6 @@ package dev.protocollib.api.listener; -import dev.protocollib.api.PacketContainer; +import dev.protocollib.api.packet.PacketContainer; /** * Functional interface for handling packets asynchronously. diff --git a/src/main/java/dev/protocollib/api/listener/PacketListenerBuilder.java b/src/main/java/dev/protocollib/api/listener/PacketListenerBuilder.java index 4cb9e4fba..1a9a6951d 100644 --- a/src/main/java/dev/protocollib/api/listener/PacketListenerBuilder.java +++ b/src/main/java/dev/protocollib/api/listener/PacketListenerBuilder.java @@ -2,7 +2,7 @@ import java.util.Collection; -import dev.protocollib.api.PacketType; +import dev.protocollib.api.packet.PacketType; /** * Builder for creating and registering packet listeners. diff --git a/src/main/java/dev/protocollib/api/listener/PacketSentListener.java b/src/main/java/dev/protocollib/api/listener/PacketTransmissionListener.java similarity index 59% rename from src/main/java/dev/protocollib/api/listener/PacketSentListener.java rename to src/main/java/dev/protocollib/api/listener/PacketTransmissionListener.java index dc28b346f..0b030375d 100644 --- a/src/main/java/dev/protocollib/api/listener/PacketSentListener.java +++ b/src/main/java/dev/protocollib/api/listener/PacketTransmissionListener.java @@ -1,12 +1,14 @@ package dev.protocollib.api.listener; /** - * Functional interface for a listener that is invoked when a packet has been sent. + * Functional interface for a listener that is invoked when a packet has been sent + * (according to the underlying write's ChannelFuture) or received (just before the + * packet gets processed by mojangs packet handlers). * * This method will get invoked on the underlying channel's event-loop. */ @FunctionalInterface -public interface PacketSentListener { +public interface PacketTransmissionListener { /** * Invoked when a packet has been successfully sent. diff --git a/src/main/java/dev/protocollib/api/listener/SyncPacketListener.java b/src/main/java/dev/protocollib/api/listener/SyncPacketListener.java index 1bc35b4ae..37b951a40 100644 --- a/src/main/java/dev/protocollib/api/listener/SyncPacketListener.java +++ b/src/main/java/dev/protocollib/api/listener/SyncPacketListener.java @@ -1,6 +1,6 @@ package dev.protocollib.api.listener; -import dev.protocollib.api.PacketContainer; +import dev.protocollib.api.packet.PacketContainer; /** * Functional interface for handling packets synchronously. diff --git a/src/main/java/dev/protocollib/api/listener/SyncPacketListenerContext.java b/src/main/java/dev/protocollib/api/listener/SyncPacketListenerContext.java index 4afa166b1..32dd4a35c 100644 --- a/src/main/java/dev/protocollib/api/listener/SyncPacketListenerContext.java +++ b/src/main/java/dev/protocollib/api/listener/SyncPacketListenerContext.java @@ -27,10 +27,10 @@ public interface SyncPacketListenerContext { void cancel(); /** - * Adds a listener to be invoked after the packet is sent. + * Adds a listener to be invoked after the packet is sent or received. * - * @param listener the post-sent listener + * @param listener the transmission listener to invoke */ - void addPostSentListener(PacketSentListener listener); + void addTransmissionListener(PacketTransmissionListener listener); } diff --git a/src/main/java/dev/protocollib/api/BinaryPacket.java b/src/main/java/dev/protocollib/api/packet/BinaryPacket.java similarity index 76% rename from src/main/java/dev/protocollib/api/BinaryPacket.java rename to src/main/java/dev/protocollib/api/packet/BinaryPacket.java index bdc14e2b9..d845c0c80 100644 --- a/src/main/java/dev/protocollib/api/BinaryPacket.java +++ b/src/main/java/dev/protocollib/api/packet/BinaryPacket.java @@ -1,9 +1,9 @@ -package dev.protocollib.api; +package dev.protocollib.api.packet; /** * Representing a raw binary packet with a packet id and payload. */ -public interface BinaryPacket { +public non-sealed interface BinaryPacket extends PacketLike { /** * Retrieves the packet id. @@ -19,4 +19,3 @@ public interface BinaryPacket { */ byte[] payload(); } - diff --git a/src/main/java/dev/protocollib/api/PacketContainer.java b/src/main/java/dev/protocollib/api/packet/PacketContainer.java similarity index 53% rename from src/main/java/dev/protocollib/api/PacketContainer.java rename to src/main/java/dev/protocollib/api/packet/PacketContainer.java index f23655c6e..5e1452b42 100644 --- a/src/main/java/dev/protocollib/api/PacketContainer.java +++ b/src/main/java/dev/protocollib/api/packet/PacketContainer.java @@ -1,9 +1,9 @@ -package dev.protocollib.api; +package dev.protocollib.api.packet; /** * Representing a container for a packet. */ -public interface PacketContainer { +public non-sealed interface PacketContainer extends PacketLike { /** * Retrieves the type of the packet. @@ -19,4 +19,11 @@ public interface PacketContainer { */ Object packet(); + /** + * Creates and returns a mutable copy of this packet. + * + * @return a clone of this instance. + */ + PacketContainer clone(); + } diff --git a/src/main/java/dev/protocollib/api/packet/PacketLike.java b/src/main/java/dev/protocollib/api/packet/PacketLike.java new file mode 100644 index 000000000..b9a2b4a66 --- /dev/null +++ b/src/main/java/dev/protocollib/api/packet/PacketLike.java @@ -0,0 +1,5 @@ +package dev.protocollib.api.packet; + +public sealed interface PacketLike permits BinaryPacket, PacketContainer { + +} diff --git a/src/main/java/dev/protocollib/api/packet/PacketOperationBuilder.java b/src/main/java/dev/protocollib/api/packet/PacketOperationBuilder.java new file mode 100644 index 000000000..4c2e2622f --- /dev/null +++ b/src/main/java/dev/protocollib/api/packet/PacketOperationBuilder.java @@ -0,0 +1,44 @@ +package dev.protocollib.api.packet; + +import dev.protocollib.api.listener.PacketTransmissionListener; + +/** + * Builder interface for constructing packet operations. + * + *

This interface provides methods to configure how packets are sent + * or received within ProtocolLib.

+ */ +public interface PacketOperationBuilder { + + /** + * Skips processing the packet in ProtocolLib's pipeline. + * + *

This method allows the caller to prevent further handling of the packet + * by other plugin listeners in the pipeline.

+ * + * @return the same builder for further configuration + */ + PacketOperationBuilder skipProcessing(); + + /** + * Registers a listener to be called once the packet has been sent or received. + * + * @param listener the listener to be notified upon packet transmission + * @return the same builder for further configuration + */ + PacketOperationBuilder postTransmission(PacketTransmissionListener listener); + + /** + * Sends a packet to the client. + * + * @param packet the {@link PacketContainer} to send + */ + void send(PacketLike packet); + + /** + * Receives a packet as if the client had sent it. + * + * @param packet the {@link PacketContainer} to receive + */ + void receive(PacketLike packet); +} diff --git a/src/main/java/dev/protocollib/api/PacketType.java b/src/main/java/dev/protocollib/api/packet/PacketType.java similarity index 93% rename from src/main/java/dev/protocollib/api/PacketType.java rename to src/main/java/dev/protocollib/api/packet/PacketType.java index 18290de30..4d874f53b 100644 --- a/src/main/java/dev/protocollib/api/PacketType.java +++ b/src/main/java/dev/protocollib/api/packet/PacketType.java @@ -1,7 +1,8 @@ -package dev.protocollib.api; +package dev.protocollib.api.packet; import java.util.Optional; +import dev.protocollib.api.ProtocolDirection; import net.kyori.adventure.key.Keyed; /** diff --git a/src/main/java/dev/protocollib/api/PacketTypes.java b/src/main/java/dev/protocollib/api/packet/PacketTypes.java similarity index 74% rename from src/main/java/dev/protocollib/api/PacketTypes.java rename to src/main/java/dev/protocollib/api/packet/PacketTypes.java index 8a623ccf3..92418b6b8 100644 --- a/src/main/java/dev/protocollib/api/PacketTypes.java +++ b/src/main/java/dev/protocollib/api/packet/PacketTypes.java @@ -1,4 +1,4 @@ -package dev.protocollib.api; +package dev.protocollib.api.packet; public class PacketTypes { From fbc24f659ab41fa889a0a1fffa35db197d66706d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maurice=20Eisenbl=C3=A4tter?= Date: Sun, 23 Mar 2025 00:38:12 +0100 Subject: [PATCH 4/6] feat: add bundle behavior, terminal packets --- src/main/java/dev/protocollib/Example.java | 102 ++++++++++++++++++ .../dev/protocollib/api/ProtocolPhase.java | 2 +- .../api/listener/AsyncPacketListener.java | 4 +- .../listener/AsyncPacketListenerContext.java | 4 +- .../api/listener/PacketListenerBuilder.java | 42 ++++++-- .../PacketListenerBundleBehavior.java | 31 ++++++ .../listener/PacketListenerRegistration.java | 1 - .../listener/PacketTransmissionListener.java | 1 - .../api/listener/SyncPacketListener.java | 4 +- .../listener/SyncPacketListenerContext.java | 13 ++- .../api/packet/PacketContainer.java | 18 +++- .../api/packet/PacketOperationBuilder.java | 11 +- .../protocollib/api/packet/PacketType.java | 29 ++++- .../protocollib/api/packet/PacketTypes.java | 5 + 14 files changed, 237 insertions(+), 30 deletions(-) create mode 100644 src/main/java/dev/protocollib/Example.java create mode 100644 src/main/java/dev/protocollib/api/listener/PacketListenerBundleBehavior.java diff --git a/src/main/java/dev/protocollib/Example.java b/src/main/java/dev/protocollib/Example.java new file mode 100644 index 000000000..75f1e4e84 --- /dev/null +++ b/src/main/java/dev/protocollib/Example.java @@ -0,0 +1,102 @@ +package dev.protocollib; + +import org.bukkit.entity.Player; +import org.bukkit.plugin.Plugin; +import dev.protocollib.api.ProtocolLib; +import dev.protocollib.api.listener.*; +import dev.protocollib.api.packet.*; +import java.util.concurrent.*; + +public class Example { + + private static final ExecutorService EXECUTOR = Executors.newCachedThreadPool(); + private static ProtocolLib protocolLib; + private static Plugin plugin; + + // ======================== + // Packet Listeners + // ======================== + + static void registerListeners() { + // sync read-only listener + protocolLib + .createListener(plugin) + .types(PacketTypes.Game.LEVEL_CHUNK) + .priority(PacketListenerPriority.LOW) + .includeCanceledPackets() + .bundleBehavior(PacketListenerBundleBehavior.SKIP_OUTSIDE_BUNDLE) + .registerSync((packet, context) -> { + Chunk chunk = Chunk.from(packet); + // Sync processing + }); + + // async modify packet on netty thread + protocolLib + .createListener(plugin) + .types(PacketTypes.Game.LEVEL_CHUNK) + .mutable() + .registerAsync((packet, context) -> { + Chunk chunk = Chunk.from(packet); + + // do processing here ... + // write changes to packet ... + + context.addTransmissionListener(chunk::markSent); + context.resumeProcessing(); + }); + + // async modify packet on app thread-pool + protocolLib + .createListener(plugin) + .types(PacketTypes.Game.LEVEL_CHUNK) + .mutable() + .registerAsync((packet, context) -> { + Chunk chunk = Chunk.from(packet); + + EXECUTOR.execute(() -> { + + // do heavy processing here ... + // write changes to packet ... + + context.addTransmissionListener(chunk::markSent); + context.resumeProcessing(); + }); + }); + } + + // ======================== + // Packet Sending + // ======================== + + static void sendPackets(Player player, Chunk chunk) { + // full packet operation + protocolLib + .connection(player) + .packetOperation() + .skipProcessing() + .postTransmission(chunk::markSent) + .send(chunk.packet()); + + // connection shortcut + protocolLib + .connection(player) + .sendPacket(chunk.packet()); + + // direct API shortcut + protocolLib + .sendPacket(player, chunk.packet()); + } + + // ======================== + // Chunk Implementation + // ======================== + + static class Chunk { + static Chunk from(PacketContainer packet) { + return new Chunk(); + } + + PacketContainer packet() { return null; } + void markSent() {} + } +} \ No newline at end of file diff --git a/src/main/java/dev/protocollib/api/ProtocolPhase.java b/src/main/java/dev/protocollib/api/ProtocolPhase.java index e3b92e02a..003596478 100644 --- a/src/main/java/dev/protocollib/api/ProtocolPhase.java +++ b/src/main/java/dev/protocollib/api/ProtocolPhase.java @@ -5,6 +5,6 @@ */ public enum ProtocolPhase { - HANDSHAKE, PLAY, STATUS, LOGIN, CONFIGURATION, UNKNOWN; + HANDSHAKE, GAME, STATUS, LOGIN, CONFIGURATION, UNKNOWN; } diff --git a/src/main/java/dev/protocollib/api/listener/AsyncPacketListener.java b/src/main/java/dev/protocollib/api/listener/AsyncPacketListener.java index 9c46ee300..1027a0ec1 100644 --- a/src/main/java/dev/protocollib/api/listener/AsyncPacketListener.java +++ b/src/main/java/dev/protocollib/api/listener/AsyncPacketListener.java @@ -1,5 +1,7 @@ package dev.protocollib.api.listener; +import org.jetbrains.annotations.NotNull; + import dev.protocollib.api.packet.PacketContainer; /** @@ -27,6 +29,6 @@ public interface AsyncPacketListener { * @param packet the packet to handle * @param context the context providing additional information about the packet and connection */ - void handlePacket(PacketContainer packet, AsyncPacketListenerContext context); + void handlePacket(@NotNull PacketContainer packet, @NotNull AsyncPacketListenerContext context); } diff --git a/src/main/java/dev/protocollib/api/listener/AsyncPacketListenerContext.java b/src/main/java/dev/protocollib/api/listener/AsyncPacketListenerContext.java index 3676edcfa..f014651b2 100644 --- a/src/main/java/dev/protocollib/api/listener/AsyncPacketListenerContext.java +++ b/src/main/java/dev/protocollib/api/listener/AsyncPacketListenerContext.java @@ -1,5 +1,7 @@ package dev.protocollib.api.listener; +import org.jetbrains.annotations.NotNull; + /** * Representing the context of an asynchronous packet listener. */ @@ -16,6 +18,6 @@ public interface AsyncPacketListenerContext extends SyncPacketListenerContext { * * @param throwable the processing exception */ - void resumeProcessingWithException(Throwable throwable); + void resumeProcessingWithException(@NotNull Throwable throwable); } diff --git a/src/main/java/dev/protocollib/api/listener/PacketListenerBuilder.java b/src/main/java/dev/protocollib/api/listener/PacketListenerBuilder.java index 1a9a6951d..f12bec871 100644 --- a/src/main/java/dev/protocollib/api/listener/PacketListenerBuilder.java +++ b/src/main/java/dev/protocollib/api/listener/PacketListenerBuilder.java @@ -2,6 +2,9 @@ import java.util.Collection; +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.NotNull; + import dev.protocollib.api.packet.PacketType; /** @@ -15,7 +18,8 @@ public interface PacketListenerBuilder { * @param packetTypes the packet types to listen for * @return the same builder for further configuration */ - PacketListenerBuilder.WithType types(PacketType... packetTypes); + @NotNull + PacketListenerBuilder.WithType types(@NotNull PacketType... packetTypes); /** * Specifies the types of packets to listen for. @@ -23,7 +27,8 @@ public interface PacketListenerBuilder { * @param packetTypes the collection of packet types to listen for * @return the same builder for further configuration */ - PacketListenerBuilder.WithType types(Collection packetTypes); + @NotNull + PacketListenerBuilder.WithType types(@NotNull Collection packetTypes); /** * Interface for building a packet listener with specific packet types. @@ -36,22 +41,36 @@ public interface WithType { * @param priority the priority to assign to the listener * @return the same builder for further configuration */ - PacketListenerBuilder.WithType priority(PacketListenerPriority priority); + @Contract("_ -> this") + PacketListenerBuilder.WithType priority(@NotNull PacketListenerPriority priority); /** - * Marks the listener as immutable, preventing modifications of packets - * inside the listener. + * Allows the listener to modify packets. By default, listeners are read-only and + * cannot modify packets. * * @return the same builder for further configuration */ - PacketListenerBuilder.WithType immutable(); + @Contract("_ -> this") + PacketListenerBuilder.WithType mutable(); /** - * Configures the listener to ignore packets that have been cancelled. + * Configures the bundle behavior for the listener, determining how packets in bundles are handled. * + * @param bundleBehavior the bundle behavior to apply * @return the same builder for further configuration + * @see PacketListenerBundleBehavior */ - PacketListenerBuilder.WithType ignoreCancelledPackets(); + @Contract("_ -> this") + PacketListenerBuilder.WithType bundleBehavior(@NotNull PacketListenerBundleBehavior bundleBehavior); + + /** + * Configures the listener to include packets that have been canceled. By default, + * canceled packets are skipped. + * + * @return the same builder for further configuration + */ + @Contract("_ -> this") + PacketListenerBuilder.WithType includeCanceledPackets(); /** * Registers the packet listener to operate synchronously. The listener @@ -60,7 +79,8 @@ public interface WithType { * @param listener the synchronous packet listener to register * @return the same builder for further configuration */ - PacketListenerRegistration registerSync(SyncPacketListener listener); + @NotNull + PacketListenerRegistration registerSync(@NotNull SyncPacketListener listener); /** * Registers the packet listener to operate asynchronously. @@ -68,7 +88,7 @@ public interface WithType { * @param listener the asynchronous packet listener to register * @return the same builder for further configuration */ - PacketListenerRegistration registerAsync(AsyncPacketListener listener); + @NotNull + PacketListenerRegistration registerAsync(@NotNull AsyncPacketListener listener); } } - diff --git a/src/main/java/dev/protocollib/api/listener/PacketListenerBundleBehavior.java b/src/main/java/dev/protocollib/api/listener/PacketListenerBundleBehavior.java new file mode 100644 index 000000000..e6eb9111e --- /dev/null +++ b/src/main/java/dev/protocollib/api/listener/PacketListenerBundleBehavior.java @@ -0,0 +1,31 @@ +package dev.protocollib.api.listener; + +/** + * Controls packet processing behavior relative to packet bundles (groups of + * packets processed atomically). + *

+ * Determines whether individual packets should be processed or ignored based on + * their membership in a packet bundle. Packet bundles typically represent + * groups of packets that are be processed together as an atomic unit. + *

+ */ +public enum PacketListenerBundleBehavior { + + /** + * Processes all packets unconditionally, regardless of whether they are part of + * a packet bundle. + */ + ALWAYS, + + /** + * Processes only packets that exist outside of packet bundles, ignoring those + * inside bundles. + */ + SKIP_INSIDE_BUNDLE, + + /** + * Processes only packets that are part of packet bundles, ignoring standalone + * packets. + */ + SKIP_OUTSIDE_BUNDLE; +} diff --git a/src/main/java/dev/protocollib/api/listener/PacketListenerRegistration.java b/src/main/java/dev/protocollib/api/listener/PacketListenerRegistration.java index e18a92c66..cfcc71722 100644 --- a/src/main/java/dev/protocollib/api/listener/PacketListenerRegistration.java +++ b/src/main/java/dev/protocollib/api/listener/PacketListenerRegistration.java @@ -11,4 +11,3 @@ public interface PacketListenerRegistration { */ void unregister(); } - diff --git a/src/main/java/dev/protocollib/api/listener/PacketTransmissionListener.java b/src/main/java/dev/protocollib/api/listener/PacketTransmissionListener.java index 0b030375d..0ea27c869 100644 --- a/src/main/java/dev/protocollib/api/listener/PacketTransmissionListener.java +++ b/src/main/java/dev/protocollib/api/listener/PacketTransmissionListener.java @@ -15,4 +15,3 @@ public interface PacketTransmissionListener { */ void invoke(); } - diff --git a/src/main/java/dev/protocollib/api/listener/SyncPacketListener.java b/src/main/java/dev/protocollib/api/listener/SyncPacketListener.java index 37b951a40..81e0caf77 100644 --- a/src/main/java/dev/protocollib/api/listener/SyncPacketListener.java +++ b/src/main/java/dev/protocollib/api/listener/SyncPacketListener.java @@ -1,5 +1,7 @@ package dev.protocollib.api.listener; +import org.jetbrains.annotations.NotNull; + import dev.protocollib.api.packet.PacketContainer; /** @@ -14,6 +16,6 @@ public interface SyncPacketListener { * @param packet the packet to handle * @param context the context providing additional information about the packet and functions */ - void handlePacket(PacketContainer packet, SyncPacketListenerContext context); + void handlePacket(@NotNull PacketContainer packet, @NotNull SyncPacketListenerContext context); } diff --git a/src/main/java/dev/protocollib/api/listener/SyncPacketListenerContext.java b/src/main/java/dev/protocollib/api/listener/SyncPacketListenerContext.java index 32dd4a35c..7439d13d1 100644 --- a/src/main/java/dev/protocollib/api/listener/SyncPacketListenerContext.java +++ b/src/main/java/dev/protocollib/api/listener/SyncPacketListenerContext.java @@ -1,5 +1,7 @@ package dev.protocollib.api.listener; +import org.jetbrains.annotations.NotNull; + import dev.protocollib.api.Connection; /** @@ -12,6 +14,7 @@ public interface SyncPacketListenerContext { * * @return the connection handling the packet */ + @NotNull Connection connection(); /** @@ -22,15 +25,17 @@ public interface SyncPacketListenerContext { boolean isCancelled(); /** - * Cancels the packet, preventing it from being processed further. + * Sets whether the packet handling is cancelled. If cancelled, the packet + * will not be processed further. + * + * @param cancelled true to cancel the packet, false to allow processing */ - void cancel(); + void setCancelled(boolean cancelled); /** * Adds a listener to be invoked after the packet is sent or received. * * @param listener the transmission listener to invoke */ - void addTransmissionListener(PacketTransmissionListener listener); + void addTransmissionListener(@NotNull PacketTransmissionListener listener); } - diff --git a/src/main/java/dev/protocollib/api/packet/PacketContainer.java b/src/main/java/dev/protocollib/api/packet/PacketContainer.java index 5e1452b42..b7f7f6626 100644 --- a/src/main/java/dev/protocollib/api/packet/PacketContainer.java +++ b/src/main/java/dev/protocollib/api/packet/PacketContainer.java @@ -1,5 +1,8 @@ package dev.protocollib.api.packet; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + /** * Representing a container for a packet. */ @@ -10,6 +13,7 @@ public non-sealed interface PacketContainer extends PacketLike { * * @return the packet type */ + @NotNull PacketType packetType(); /** @@ -17,13 +21,23 @@ public non-sealed interface PacketContainer extends PacketLike { * * @return the packet object */ + @NotNull Object packet(); + /** + * Retrieves the packet bundle that this packet is part of, if any. + * A packet bundle represents a collection of packets that are processed together. + * + * @return the packet bundle containing this packet, or {@code null} if not part of a bundle + */ + @Nullable + PacketContainer bundle(); + /** * Creates and returns a mutable copy of this packet. * - * @return a clone of this instance. + * @return a clone of this instance */ + @Nullable PacketContainer clone(); - } diff --git a/src/main/java/dev/protocollib/api/packet/PacketOperationBuilder.java b/src/main/java/dev/protocollib/api/packet/PacketOperationBuilder.java index 4c2e2622f..50fdb123b 100644 --- a/src/main/java/dev/protocollib/api/packet/PacketOperationBuilder.java +++ b/src/main/java/dev/protocollib/api/packet/PacketOperationBuilder.java @@ -1,5 +1,8 @@ package dev.protocollib.api.packet; +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.NotNull; + import dev.protocollib.api.listener.PacketTransmissionListener; /** @@ -18,6 +21,7 @@ public interface PacketOperationBuilder { * * @return the same builder for further configuration */ + @Contract("_ -> this") PacketOperationBuilder skipProcessing(); /** @@ -26,19 +30,20 @@ public interface PacketOperationBuilder { * @param listener the listener to be notified upon packet transmission * @return the same builder for further configuration */ - PacketOperationBuilder postTransmission(PacketTransmissionListener listener); + @Contract("_ -> this") + PacketOperationBuilder postTransmission(@NotNull PacketTransmissionListener listener); /** * Sends a packet to the client. * * @param packet the {@link PacketContainer} to send */ - void send(PacketLike packet); + void send(@NotNull PacketLike packet); /** * Receives a packet as if the client had sent it. * * @param packet the {@link PacketContainer} to receive */ - void receive(PacketLike packet); + void receive(@NotNull PacketLike packet); } diff --git a/src/main/java/dev/protocollib/api/packet/PacketType.java b/src/main/java/dev/protocollib/api/packet/PacketType.java index 4d874f53b..c3dd19f6e 100644 --- a/src/main/java/dev/protocollib/api/packet/PacketType.java +++ b/src/main/java/dev/protocollib/api/packet/PacketType.java @@ -3,14 +3,15 @@ import java.util.Optional; import dev.protocollib.api.ProtocolDirection; +import dev.protocollib.api.ProtocolPhase; import net.kyori.adventure.key.Keyed; /** * Representing the type of a network packet. * *

A {@code PacketType} identifies a specific type of packet in the protocol, - * including information about its direction, associated class (if any), and - * whether the packet is currently supported.

+ * including information about its direction, phase in the protocol, associated class (if any), + * whether the packet is currently supported and if it terminates the current phase.

*/ public interface PacketType extends Keyed { @@ -21,11 +22,23 @@ public interface PacketType extends Keyed { */ ProtocolDirection protocolDirection(); + /** + * Retrieves the protocol phase during which this packet is used. + * This indicates which phase of the protocol (e.g., HANDSHAKE, LOGIN, GAME) + * the packet belongs to. + * + * @return the {@link ProtocolPhase} associated with this packet + */ + ProtocolPhase protocolPhase(); + /** * Retrieves the class associated with the packet type, if available. * - *

Not all packet types have an associated class. If there is no class, - * an empty {@link Optional} is returned.

+ *

If the packet is supported (i.e., {@link #isSupported()} returns {@code true}), + * this method will always return a non-empty {@link Optional} containing the packet class. + * Note that the same packet class may be reused across different protocol phases. + * The current protocol phase should be checked via {@link #protocolPhase()} to determine + * the correct context.

* * @return an {@link Optional} containing the class of the packet, or empty if not applicable */ @@ -38,4 +51,12 @@ public interface PacketType extends Keyed { */ boolean isSupported(); + /** + * Determines if processing this packet terminates the current protocol phase, + * potentially transitioning to a new phase. For example, a login success packet + * might terminate the LOGIN phase and transition to the CONFIGURATION phase. + * + * @return {@code true} if this packet ends the current protocol phase, {@code false} otherwise + */ + boolean isTerminal(); } diff --git a/src/main/java/dev/protocollib/api/packet/PacketTypes.java b/src/main/java/dev/protocollib/api/packet/PacketTypes.java index 92418b6b8..703aaaec7 100644 --- a/src/main/java/dev/protocollib/api/packet/PacketTypes.java +++ b/src/main/java/dev/protocollib/api/packet/PacketTypes.java @@ -4,4 +4,9 @@ public class PacketTypes { // TODO should contain all packet types as public static final fields + public static class Game { + + public static final PacketType LEVEL_CHUNK = null; + + } } From 30fe6465dbd65456f7f4afcf6090db3e62d4f209 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maurice=20Eisenbl=C3=A4tter?= Date: Mon, 24 Mar 2025 22:30:53 +0100 Subject: [PATCH 5/6] feat(api): wip - add immutable packet listener --- src/main/java/dev/protocollib/Example.java | 67 +++++++++++++++++-- .../java/dev/protocollib/api/ProtocolLib.java | 6 +- .../api/listener/AsyncPacketListener.java | 4 +- .../api/listener/ImmutablePacketListener.java | 12 ++++ .../ImmutablePacketListenerContext.java | 30 +++++++++ .../api/listener/PacketListenerBuilder.java | 27 +++++--- .../api/listener/SyncPacketListener.java | 4 +- .../listener/SyncPacketListenerContext.java | 2 +- .../api/packet/MutablePacketContainer.java | 26 +++++++ .../api/packet/PacketContainer.java | 9 +-- .../api/packet/PacketOperationBuilder.java | 4 +- .../protocollib/api/reflect/Converter.java | 12 ++++ .../api/reflect/GenericAccessor.java | 31 +++++++++ .../api/reflect/GenericMutator.java | 46 +++++++++++++ .../api/reflect/MutableGenericAccessor.java | 12 ++++ 15 files changed, 262 insertions(+), 30 deletions(-) create mode 100644 src/main/java/dev/protocollib/api/listener/ImmutablePacketListener.java create mode 100644 src/main/java/dev/protocollib/api/listener/ImmutablePacketListenerContext.java create mode 100644 src/main/java/dev/protocollib/api/packet/MutablePacketContainer.java create mode 100644 src/main/java/dev/protocollib/api/reflect/Converter.java create mode 100644 src/main/java/dev/protocollib/api/reflect/GenericAccessor.java create mode 100644 src/main/java/dev/protocollib/api/reflect/GenericMutator.java create mode 100644 src/main/java/dev/protocollib/api/reflect/MutableGenericAccessor.java diff --git a/src/main/java/dev/protocollib/Example.java b/src/main/java/dev/protocollib/Example.java index 75f1e4e84..df840f650 100644 --- a/src/main/java/dev/protocollib/Example.java +++ b/src/main/java/dev/protocollib/Example.java @@ -1,11 +1,18 @@ package dev.protocollib; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + import org.bukkit.entity.Player; import org.bukkit.plugin.Plugin; + import dev.protocollib.api.ProtocolLib; -import dev.protocollib.api.listener.*; -import dev.protocollib.api.packet.*; -import java.util.concurrent.*; +import dev.protocollib.api.listener.PacketListenerBundleBehavior; +import dev.protocollib.api.listener.PacketListenerPriority; +import dev.protocollib.api.packet.MutablePacketContainer; +import dev.protocollib.api.packet.PacketContainer; +import dev.protocollib.api.packet.PacketTypes; +import dev.protocollib.api.reflect.MutableGenericAccessor; public class Example { @@ -13,6 +20,56 @@ public class Example { private static ProtocolLib protocolLib; private static Plugin plugin; + public static class ParticleData { + public String s; + public int i; + } + + public static class ParticlePacket { + public int duration; + public String name; + public ParticleData data; + } + + static { + MutablePacketContainer packet = null; + Class clazz = MutableGenericAccessor.class; + + packet.accessor().update(a -> { + a.update(ParticleData.class, 0, b -> { + + }); + }); + + packet.accessor().getAccessor(ParticleData.class, 0).update(accessor -> { + + }); + + packet.accessor().update(accessor -> { + + accessor.setObject(clazz, 1, ""); + accessor.set(Integer.class, 1, 1235); + accessor.set(String.class, 1, "world"); + + accessor.getAccessor(Object.class, 1).getAccessor(Object.class, 1).update(mutableAccessor -> { + + }); + + accessor.update(Object.class, 1, mutableAccessor -> { + mutableAccessor.set(int.class, 1, -1); + }); + + accessor.update(ParticleData.class, 1, (pd) -> { + pd.i++; + return pd; + }); + + accessor.update(ParticleData.class, 1, (pd) -> { + pd.set(int.class, 1, pd.get(int.class, 1) + 1); + }); + }); + } + // ======================== // Packet Listeners // ======================== @@ -41,7 +98,7 @@ static void registerListeners() { // do processing here ... // write changes to packet ... - context.addTransmissionListener(chunk::markSent); + context.addAsyncTransmissionListener(chunk::markSent); context.resumeProcessing(); }); @@ -58,7 +115,7 @@ static void registerListeners() { // do heavy processing here ... // write changes to packet ... - context.addTransmissionListener(chunk::markSent); + context.addAsyncTransmissionListener(chunk::markSent); context.resumeProcessing(); }); }); diff --git a/src/main/java/dev/protocollib/api/ProtocolLib.java b/src/main/java/dev/protocollib/api/ProtocolLib.java index dda0bf1ef..2a86b11f6 100644 --- a/src/main/java/dev/protocollib/api/ProtocolLib.java +++ b/src/main/java/dev/protocollib/api/ProtocolLib.java @@ -5,7 +5,7 @@ import dev.protocollib.api.listener.PacketListenerBuilder; import dev.protocollib.api.packet.BinaryPacket; -import dev.protocollib.api.packet.PacketContainer; +import dev.protocollib.api.packet.MutablePacketContainer; import dev.protocollib.api.packet.PacketLike; import dev.protocollib.api.packet.PacketType; @@ -61,7 +61,7 @@ default void receivePacket(Player player, PacketLike packet) { * Creates a new packet container for the given packet type. * * @param packetType the type of the packet to create - * @return a new {@link PacketContainer} instance + * @return a new {@link MutablePacketContainer} instance */ - PacketContainer createPacket(PacketType packetType); + MutablePacketContainer createPacket(PacketType packetType); } diff --git a/src/main/java/dev/protocollib/api/listener/AsyncPacketListener.java b/src/main/java/dev/protocollib/api/listener/AsyncPacketListener.java index 1027a0ec1..324a7d811 100644 --- a/src/main/java/dev/protocollib/api/listener/AsyncPacketListener.java +++ b/src/main/java/dev/protocollib/api/listener/AsyncPacketListener.java @@ -2,7 +2,7 @@ import org.jetbrains.annotations.NotNull; -import dev.protocollib.api.packet.PacketContainer; +import dev.protocollib.api.packet.MutablePacketContainer; /** * Functional interface for handling packets asynchronously. @@ -29,6 +29,6 @@ public interface AsyncPacketListener { * @param packet the packet to handle * @param context the context providing additional information about the packet and connection */ - void handlePacket(@NotNull PacketContainer packet, @NotNull AsyncPacketListenerContext context); + void handlePacket(@NotNull MutablePacketContainer packet, @NotNull AsyncPacketListenerContext context); } diff --git a/src/main/java/dev/protocollib/api/listener/ImmutablePacketListener.java b/src/main/java/dev/protocollib/api/listener/ImmutablePacketListener.java new file mode 100644 index 000000000..209443824 --- /dev/null +++ b/src/main/java/dev/protocollib/api/listener/ImmutablePacketListener.java @@ -0,0 +1,12 @@ +package dev.protocollib.api.listener; + +import org.jetbrains.annotations.NotNull; + +import dev.protocollib.api.packet.PacketContainer; + +@FunctionalInterface +public interface ImmutablePacketListener { + + void handlePacket(@NotNull PacketContainer packet, @NotNull ImmutablePacketListenerContext context); + +} diff --git a/src/main/java/dev/protocollib/api/listener/ImmutablePacketListenerContext.java b/src/main/java/dev/protocollib/api/listener/ImmutablePacketListenerContext.java new file mode 100644 index 000000000..37354b718 --- /dev/null +++ b/src/main/java/dev/protocollib/api/listener/ImmutablePacketListenerContext.java @@ -0,0 +1,30 @@ +package dev.protocollib.api.listener; + +import org.jetbrains.annotations.NotNull; + +import dev.protocollib.api.Connection; + +public interface ImmutablePacketListenerContext { + + /** + * Retrieves the connection associated with the packet. + * + * @return the connection handling the packet + */ + @NotNull + Connection connection(); + + /** + * Checks if the packet handling has been cancelled. + * + * @return true if the packet is cancelled, false otherwise + */ + boolean isCancelledVolatile(); + + /** + * Adds a listener to be invoked after the packet is sent or received. + * + * @param listener the transmission listener to invoke + */ + void addAsyncTransmissionListener(@NotNull PacketTransmissionListener listener);// TODO async via netty +} diff --git a/src/main/java/dev/protocollib/api/listener/PacketListenerBuilder.java b/src/main/java/dev/protocollib/api/listener/PacketListenerBuilder.java index f12bec871..8319717c3 100644 --- a/src/main/java/dev/protocollib/api/listener/PacketListenerBuilder.java +++ b/src/main/java/dev/protocollib/api/listener/PacketListenerBuilder.java @@ -44,15 +44,6 @@ public interface WithType { @Contract("_ -> this") PacketListenerBuilder.WithType priority(@NotNull PacketListenerPriority priority); - /** - * Allows the listener to modify packets. By default, listeners are read-only and - * cannot modify packets. - * - * @return the same builder for further configuration - */ - @Contract("_ -> this") - PacketListenerBuilder.WithType mutable(); - /** * Configures the bundle behavior for the listener, determining how packets in bundles are handled. * @@ -72,6 +63,24 @@ public interface WithType { @Contract("_ -> this") PacketListenerBuilder.WithType includeCanceledPackets(); + /** + * Allows the listener to modify packets. By default, listeners are read-only and + * cannot modify packets. + * + * @return the same builder for further configuration + */ + @NotNull + PacketListenerBuilder.Mutable mutable(); + + @NotNull + PacketListenerRegistration registerSync(@NotNull ImmutablePacketListener listener); + + @NotNull + PacketListenerRegistration registerAsync(@NotNull ImmutablePacketListener listener); + } + + public interface Mutable { + /** * Registers the packet listener to operate synchronously. The listener * will always get called on the main game thread. diff --git a/src/main/java/dev/protocollib/api/listener/SyncPacketListener.java b/src/main/java/dev/protocollib/api/listener/SyncPacketListener.java index 81e0caf77..1ee833cdf 100644 --- a/src/main/java/dev/protocollib/api/listener/SyncPacketListener.java +++ b/src/main/java/dev/protocollib/api/listener/SyncPacketListener.java @@ -2,7 +2,7 @@ import org.jetbrains.annotations.NotNull; -import dev.protocollib.api.packet.PacketContainer; +import dev.protocollib.api.packet.MutablePacketContainer; /** * Functional interface for handling packets synchronously. @@ -16,6 +16,6 @@ public interface SyncPacketListener { * @param packet the packet to handle * @param context the context providing additional information about the packet and functions */ - void handlePacket(@NotNull PacketContainer packet, @NotNull SyncPacketListenerContext context); + void handlePacket(@NotNull MutablePacketContainer packet, @NotNull SyncPacketListenerContext context); } diff --git a/src/main/java/dev/protocollib/api/listener/SyncPacketListenerContext.java b/src/main/java/dev/protocollib/api/listener/SyncPacketListenerContext.java index 7439d13d1..bd4dab6e6 100644 --- a/src/main/java/dev/protocollib/api/listener/SyncPacketListenerContext.java +++ b/src/main/java/dev/protocollib/api/listener/SyncPacketListenerContext.java @@ -37,5 +37,5 @@ public interface SyncPacketListenerContext { * * @param listener the transmission listener to invoke */ - void addTransmissionListener(@NotNull PacketTransmissionListener listener); + void addAsyncTransmissionListener(@NotNull PacketTransmissionListener listener);// TODO async via netty } diff --git a/src/main/java/dev/protocollib/api/packet/MutablePacketContainer.java b/src/main/java/dev/protocollib/api/packet/MutablePacketContainer.java new file mode 100644 index 000000000..17df5a279 --- /dev/null +++ b/src/main/java/dev/protocollib/api/packet/MutablePacketContainer.java @@ -0,0 +1,26 @@ +package dev.protocollib.api.packet; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import dev.protocollib.api.reflect.MutableGenericAccessor; + +public interface MutablePacketContainer extends PacketContainer { + + /** + * Retrieves the raw packet object. + * + * @return the packet object + */ + @NotNull + Object packet(); + + @NotNull + MutableGenericAccessor accessor(); + + @Nullable + MutablePacketContainer bundle(); + + @Nullable + MutablePacketContainer clone(); +} diff --git a/src/main/java/dev/protocollib/api/packet/PacketContainer.java b/src/main/java/dev/protocollib/api/packet/PacketContainer.java index b7f7f6626..c39c476d5 100644 --- a/src/main/java/dev/protocollib/api/packet/PacketContainer.java +++ b/src/main/java/dev/protocollib/api/packet/PacketContainer.java @@ -3,6 +3,8 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import dev.protocollib.api.reflect.GenericAccessor; + /** * Representing a container for a packet. */ @@ -16,13 +18,8 @@ public non-sealed interface PacketContainer extends PacketLike { @NotNull PacketType packetType(); - /** - * Retrieves the raw packet object. - * - * @return the packet object - */ @NotNull - Object packet(); + GenericAccessor accessor(); /** * Retrieves the packet bundle that this packet is part of, if any. diff --git a/src/main/java/dev/protocollib/api/packet/PacketOperationBuilder.java b/src/main/java/dev/protocollib/api/packet/PacketOperationBuilder.java index 50fdb123b..27cbc7dd6 100644 --- a/src/main/java/dev/protocollib/api/packet/PacketOperationBuilder.java +++ b/src/main/java/dev/protocollib/api/packet/PacketOperationBuilder.java @@ -36,14 +36,14 @@ public interface PacketOperationBuilder { /** * Sends a packet to the client. * - * @param packet the {@link PacketContainer} to send + * @param packet the packet to send */ void send(@NotNull PacketLike packet); /** * Receives a packet as if the client had sent it. * - * @param packet the {@link PacketContainer} to receive + * @param packet the packet to receive */ void receive(@NotNull PacketLike packet); } diff --git a/src/main/java/dev/protocollib/api/reflect/Converter.java b/src/main/java/dev/protocollib/api/reflect/Converter.java new file mode 100644 index 000000000..0a71ae0cb --- /dev/null +++ b/src/main/java/dev/protocollib/api/reflect/Converter.java @@ -0,0 +1,12 @@ +package dev.protocollib.api.reflect; + +public interface Converter { + + Object getGeneric(T specific); + + Class getGenericType(); + + T getSpecific(Object generic); + + Class getSpecificType(); +} diff --git a/src/main/java/dev/protocollib/api/reflect/GenericAccessor.java b/src/main/java/dev/protocollib/api/reflect/GenericAccessor.java new file mode 100644 index 000000000..b573bf261 --- /dev/null +++ b/src/main/java/dev/protocollib/api/reflect/GenericAccessor.java @@ -0,0 +1,31 @@ +package dev.protocollib.api.reflect; + +public interface GenericAccessor { + + // ==================================================== + // Value Retrieval Optional + // ==================================================== + + GenericAccessor getAccessor(Class type, int ordinal); + GenericAccessor getAccessorOrThrow(Class type, int ordinal); + + Object getObject(Class type, int ordinal); + Object getObjectOrThrow(Class type, int ordinal); + + T get(Class type, int ordinal); + T getOrThrow(Class type, int ordinal); + + T get(Converter converter, int ordinal); + T getOrThrow(Converter converter, int ordinal); + + // ==================================================== + // Metadata + // ==================================================== + + boolean isSupported(Class type, int ordinal); + boolean isSupported(Converter type, int ordinal); + + int count(Class type); + int count(Converter type); + +} diff --git a/src/main/java/dev/protocollib/api/reflect/GenericMutator.java b/src/main/java/dev/protocollib/api/reflect/GenericMutator.java new file mode 100644 index 000000000..4c9cc9bc9 --- /dev/null +++ b/src/main/java/dev/protocollib/api/reflect/GenericMutator.java @@ -0,0 +1,46 @@ +package dev.protocollib.api.reflect; + +import java.util.function.Consumer; +import java.util.function.UnaryOperator; + +public interface GenericMutator extends GenericAccessor { + + MutableGenericAccessor getAccessor(Class type, int ordinal); + MutableGenericAccessor getAccessorOrThrow(Class type, int ordinal); + + // ==================================================== + // Value Modification + // ==================================================== + + Object updateObject(Class type, int ordinal, UnaryOperator operator); + Object updateObjectOrThrow(Class type, int ordinal, UnaryOperator operator); + + T update(Class type, int ordinal, UnaryOperator operator); + T updateOrThrow(Class type, int ordinal, UnaryOperator operator); + + T update(Converter converter, int ordinal, UnaryOperator operator); + T updateOrThrow(Converter converter, int ordinal, UnaryOperator operator); + + Object update(Class type, int ordinal, Consumer operator); + Object updateOrThrow(Class type, int ordinal, Consumer operator); + + // ==================================================== + // Value Assignment + // ==================================================== + + void setObject(Class type, int ordinal, Object value); + void setObjectOrThrow(Class type, int ordinal, Object value); + + void setDefault(Class type, int ordinal); + void setDefaultOrThrow(Class type, int ordinal); + + void setDefault(Converter type, int ordinal); + void setDefaultOrThrow(Converter type, int ordinal); + + void set(Class type, int ordinal, T value); + void setOrThrow(Class type, int ordinal, T value); + + void set(Converter converter, int ordinal, T value); + void setOrThrow(Converter converter, int ordinal, T value); + +} diff --git a/src/main/java/dev/protocollib/api/reflect/MutableGenericAccessor.java b/src/main/java/dev/protocollib/api/reflect/MutableGenericAccessor.java new file mode 100644 index 000000000..186909da8 --- /dev/null +++ b/src/main/java/dev/protocollib/api/reflect/MutableGenericAccessor.java @@ -0,0 +1,12 @@ +package dev.protocollib.api.reflect; + +import java.util.function.Consumer; + +public interface MutableGenericAccessor extends GenericAccessor { + + MutableGenericAccessor getAccessor(Class type, int ordinal); + MutableGenericAccessor getAccessorOrThrow(Class type, int ordinal); + + void update(Consumer consumer); + +} From 0b03f1da710812f5a9e880f3bc7f33f1e9c2f788 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maurice=20Eisenbl=C3=A4tter?= Date: Wed, 26 Mar 2025 17:52:32 +0100 Subject: [PATCH 6/6] feat(api): add immutable packet listener --- src/main/java/dev/protocollib/Example.java | 16 +++---- .../listener/AsyncPacketListenerContext.java | 23 ---------- .../api/listener/ImmutablePacketListener.java | 14 +++++- .../ImmutablePacketListenerContext.java | 11 +++-- ...r.java => MutableAsyncPacketListener.java} | 10 ++--- .../MutableAsyncPacketListenerContext.java | 25 +++++++++++ ...er.java => MutableSyncPacketListener.java} | 8 ++-- .../MutableSyncPacketListenerContext.java | 18 ++++++++ .../api/listener/PacketListenerBuilder.java | 43 ++++++++++++++----- .../listener/SyncPacketListenerContext.java | 41 ------------------ .../protocollib/api/packet/BinaryPacket.java | 3 ++ .../api/packet/MutablePacketContainer.java | 25 ++++++++++- .../api/packet/PacketContainer.java | 13 ++++-- .../api/packet/PacketOperationBuilder.java | 2 + .../protocollib/api/packet/PacketType.java | 5 +++ .../api/reflect/GenericMutator.java | 3 -- .../api/reflect/MutableGenericAccessor.java | 3 -- 17 files changed, 157 insertions(+), 106 deletions(-) delete mode 100644 src/main/java/dev/protocollib/api/listener/AsyncPacketListenerContext.java rename src/main/java/dev/protocollib/api/listener/{AsyncPacketListener.java => MutableAsyncPacketListener.java} (76%) create mode 100644 src/main/java/dev/protocollib/api/listener/MutableAsyncPacketListenerContext.java rename src/main/java/dev/protocollib/api/listener/{SyncPacketListener.java => MutableSyncPacketListener.java} (62%) create mode 100644 src/main/java/dev/protocollib/api/listener/MutableSyncPacketListenerContext.java delete mode 100644 src/main/java/dev/protocollib/api/listener/SyncPacketListenerContext.java diff --git a/src/main/java/dev/protocollib/Example.java b/src/main/java/dev/protocollib/Example.java index df840f650..94f8125b1 100644 --- a/src/main/java/dev/protocollib/Example.java +++ b/src/main/java/dev/protocollib/Example.java @@ -37,13 +37,9 @@ public static class ParticlePacket { packet.accessor().update(a -> { a.update(ParticleData.class, 0, b -> { - + b.set(int.class, 0, -1); }); }); - - packet.accessor().getAccessor(ParticleData.class, 0).update(accessor -> { - - }); packet.accessor().update(accessor -> { @@ -51,8 +47,10 @@ public static class ParticlePacket { accessor.set(Integer.class, 1, 1235); accessor.set(String.class, 1, "world"); - accessor.getAccessor(Object.class, 1).getAccessor(Object.class, 1).update(mutableAccessor -> { - + accessor.update(Object.class, 1, a -> { + a.update(Object.class, 1, b -> { + b.set(int.class, 2, -1); + }); }); accessor.update(Object.class, 1, mutableAccessor -> { @@ -98,7 +96,7 @@ static void registerListeners() { // do processing here ... // write changes to packet ... - context.addAsyncTransmissionListener(chunk::markSent); + context.addTransmissionListener(chunk::markSent); context.resumeProcessing(); }); @@ -115,7 +113,7 @@ static void registerListeners() { // do heavy processing here ... // write changes to packet ... - context.addAsyncTransmissionListener(chunk::markSent); + context.addTransmissionListener(chunk::markSent); context.resumeProcessing(); }); }); diff --git a/src/main/java/dev/protocollib/api/listener/AsyncPacketListenerContext.java b/src/main/java/dev/protocollib/api/listener/AsyncPacketListenerContext.java deleted file mode 100644 index f014651b2..000000000 --- a/src/main/java/dev/protocollib/api/listener/AsyncPacketListenerContext.java +++ /dev/null @@ -1,23 +0,0 @@ -package dev.protocollib.api.listener; - -import org.jetbrains.annotations.NotNull; - -/** - * Representing the context of an asynchronous packet listener. - */ -public interface AsyncPacketListenerContext extends SyncPacketListenerContext { - - /** - * Singles the listener is done with processing the packet. - */ - void resumeProcessing(); - - /** - * Singles the listener is done with processing the packet and finished - * with an exception. - * - * @param throwable the processing exception - */ - void resumeProcessingWithException(@NotNull Throwable throwable); - -} diff --git a/src/main/java/dev/protocollib/api/listener/ImmutablePacketListener.java b/src/main/java/dev/protocollib/api/listener/ImmutablePacketListener.java index 209443824..5a142a3b9 100644 --- a/src/main/java/dev/protocollib/api/listener/ImmutablePacketListener.java +++ b/src/main/java/dev/protocollib/api/listener/ImmutablePacketListener.java @@ -4,9 +4,21 @@ import dev.protocollib.api.packet.PacketContainer; +/** + * Functional interface for handling immutable packets. + * + *

An immutable packet listener can be executed either synchronously or asynchronously + * depending on how it was registered. If registered asynchronously, it will be executed + * in parallel with other listeners, ensuring non-blocking packet processing.

+ */ @FunctionalInterface public interface ImmutablePacketListener { + /** + * Handles a packet that was sent or received. + * + * @param packet the immutable packet to handle + * @param context the context providing additional information about the packet + */ void handlePacket(@NotNull PacketContainer packet, @NotNull ImmutablePacketListenerContext context); - } diff --git a/src/main/java/dev/protocollib/api/listener/ImmutablePacketListenerContext.java b/src/main/java/dev/protocollib/api/listener/ImmutablePacketListenerContext.java index 37354b718..9a23c27d7 100644 --- a/src/main/java/dev/protocollib/api/listener/ImmutablePacketListenerContext.java +++ b/src/main/java/dev/protocollib/api/listener/ImmutablePacketListenerContext.java @@ -4,6 +4,9 @@ import dev.protocollib.api.Connection; +/** + * Context for immutable packet listeners. + */ public interface ImmutablePacketListenerContext { /** @@ -19,12 +22,14 @@ public interface ImmutablePacketListenerContext { * * @return true if the packet is cancelled, false otherwise */ - boolean isCancelledVolatile(); + boolean isCancelled(); /** - * Adds a listener to be invoked after the packet is sent or received. + * Adds a listener to be invoked after the packet is fully sent or received. + * The transmission listener will get invoked on the underlying channel's + * event-loop. * * @param listener the transmission listener to invoke */ - void addAsyncTransmissionListener(@NotNull PacketTransmissionListener listener);// TODO async via netty + void addTransmissionListener(@NotNull PacketTransmissionListener listener); } diff --git a/src/main/java/dev/protocollib/api/listener/AsyncPacketListener.java b/src/main/java/dev/protocollib/api/listener/MutableAsyncPacketListener.java similarity index 76% rename from src/main/java/dev/protocollib/api/listener/AsyncPacketListener.java rename to src/main/java/dev/protocollib/api/listener/MutableAsyncPacketListener.java index 324a7d811..6c57e1983 100644 --- a/src/main/java/dev/protocollib/api/listener/AsyncPacketListener.java +++ b/src/main/java/dev/protocollib/api/listener/MutableAsyncPacketListener.java @@ -5,7 +5,7 @@ import dev.protocollib.api.packet.MutablePacketContainer; /** - * Functional interface for handling packets asynchronously. + * Functional interface for handling and manipulating packets asynchronously. * *

Once a packet is processed by the listener, the context's * {@code resumeProcessing()} or {@code resumeProcessingWithException(Throwable)} @@ -16,19 +16,19 @@ *

*/ @FunctionalInterface -public interface AsyncPacketListener { +public interface MutableAsyncPacketListener { /** * Handles a packet that was sent or received, asynchronously. * *

Once processing is complete, ensure that one of the {@code resumeProcessing} - * methods from the {@link AsyncPacketListenerContext} is called. This allows the + * methods from the {@link MutableAsyncPacketListenerContext} is called. This allows the * packet to continue to the next listener. If not called, the packet will remain - * in a waiting state and will only proceed after a timeout occurs.

+ * in a waiting state and will eventually timeout.

* * @param packet the packet to handle * @param context the context providing additional information about the packet and connection */ - void handlePacket(@NotNull MutablePacketContainer packet, @NotNull AsyncPacketListenerContext context); + void handlePacket(@NotNull MutablePacketContainer packet, @NotNull MutableAsyncPacketListenerContext context); } diff --git a/src/main/java/dev/protocollib/api/listener/MutableAsyncPacketListenerContext.java b/src/main/java/dev/protocollib/api/listener/MutableAsyncPacketListenerContext.java new file mode 100644 index 000000000..22008c1da --- /dev/null +++ b/src/main/java/dev/protocollib/api/listener/MutableAsyncPacketListenerContext.java @@ -0,0 +1,25 @@ +package dev.protocollib.api.listener; + +import org.jetbrains.annotations.NotNull; + +/** + * Context of a mutable asynchronous packet listener. + */ +public interface MutableAsyncPacketListenerContext extends MutableSyncPacketListenerContext { + + /** + * Singles the listener is done with processing the packet. Handing + * it over to the next asynchronous packet listener. + */ + void resumeProcessing(); + + /** + * Singles the listener is done with processing the packet and finished + * with an exception. Handing it over to the next asynchronous packet + * listener. + * + * @param throwable the processing exception + */ + void resumeProcessingWithException(@NotNull Throwable throwable); + +} diff --git a/src/main/java/dev/protocollib/api/listener/SyncPacketListener.java b/src/main/java/dev/protocollib/api/listener/MutableSyncPacketListener.java similarity index 62% rename from src/main/java/dev/protocollib/api/listener/SyncPacketListener.java rename to src/main/java/dev/protocollib/api/listener/MutableSyncPacketListener.java index 1ee833cdf..d1a5880dd 100644 --- a/src/main/java/dev/protocollib/api/listener/SyncPacketListener.java +++ b/src/main/java/dev/protocollib/api/listener/MutableSyncPacketListener.java @@ -5,17 +5,17 @@ import dev.protocollib.api.packet.MutablePacketContainer; /** - * Functional interface for handling packets synchronously. + * Functional interface for handling and manipulating packets synchronously. */ @FunctionalInterface -public interface SyncPacketListener { +public interface MutableSyncPacketListener { /** - * Synchronously handles a packet that was sent or received. + * Handles a packet that was sent or received, synchronously. * * @param packet the packet to handle * @param context the context providing additional information about the packet and functions */ - void handlePacket(@NotNull MutablePacketContainer packet, @NotNull SyncPacketListenerContext context); + void handlePacket(@NotNull MutablePacketContainer packet, @NotNull MutableSyncPacketListenerContext context); } diff --git a/src/main/java/dev/protocollib/api/listener/MutableSyncPacketListenerContext.java b/src/main/java/dev/protocollib/api/listener/MutableSyncPacketListenerContext.java new file mode 100644 index 000000000..ee9ba6dd1 --- /dev/null +++ b/src/main/java/dev/protocollib/api/listener/MutableSyncPacketListenerContext.java @@ -0,0 +1,18 @@ +package dev.protocollib.api.listener; + +/** + * Context of a mutable synchronous packet listener. + */ +public interface MutableSyncPacketListenerContext extends ImmutablePacketListenerContext { + + /** + * Sets whether the packet handling is cancelled. If cancelled, the packet will + * not be processed further unless a listener is using the + * {@link PacketListenerBuilder.WithType#includeCanceledPackets() includeCanceledPackets} flag. + * + * @param cancelled true to cancel the packet, false to allow processing + * + * @see PacketListenerBuilder + */ + void setCancelled(boolean cancelled); +} diff --git a/src/main/java/dev/protocollib/api/listener/PacketListenerBuilder.java b/src/main/java/dev/protocollib/api/listener/PacketListenerBuilder.java index 8319717c3..7c63924eb 100644 --- a/src/main/java/dev/protocollib/api/listener/PacketListenerBuilder.java +++ b/src/main/java/dev/protocollib/api/listener/PacketListenerBuilder.java @@ -9,6 +9,10 @@ /** * Builder for creating and registering packet listeners. + * + *

This builder allows configuring packet listeners with various settings, + * including the packet types they should handle, execution priority, and behavior + * regarding canceled packets and packet bundles.

*/ public interface PacketListenerBuilder { @@ -49,6 +53,7 @@ public interface WithType { * * @param bundleBehavior the bundle behavior to apply * @return the same builder for further configuration + * * @see PacketListenerBundleBehavior */ @Contract("_ -> this") @@ -67,37 +72,55 @@ public interface WithType { * Allows the listener to modify packets. By default, listeners are read-only and * cannot modify packets. * - * @return the same builder for further configuration + * @return the mutable packet listener builder for further configuration */ @NotNull PacketListenerBuilder.Mutable mutable(); + /** + * Registers the packet listener to operate synchronously. The listener will be executed + * in order relative to other synchronous listeners. + * + * @param listener the immutable synchronous packet listener to register + * @return the packet listener registration instance + */ @NotNull PacketListenerRegistration registerSync(@NotNull ImmutablePacketListener listener); + /** + * Registers the packet listener to operate asynchronously. The listener will be executed + * in parallel with other asynchronous listeners, ensuring non-blocking packet processing. + * + * @param listener the immutable asynchronous packet listener to register + * @return the packet listener registration instance + */ @NotNull PacketListenerRegistration registerAsync(@NotNull ImmutablePacketListener listener); } + /** + * Interface for building a mutable packet listener, allowing packet modifications. + */ public interface Mutable { /** - * Registers the packet listener to operate synchronously. The listener - * will always get called on the main game thread. + * Registers the packet listener to operate synchronously. The listener will always + * be executed on the main game thread. * - * @param listener the synchronous packet listener to register - * @return the same builder for further configuration + * @param listener the synchronous mutable packet listener to register + * @return the packet listener registration instance */ @NotNull - PacketListenerRegistration registerSync(@NotNull SyncPacketListener listener); + PacketListenerRegistration registerSync(@NotNull MutableSyncPacketListener listener); /** - * Registers the packet listener to operate asynchronously. + * Registers the packet listener to operate asynchronously. The listener will be executed + * in parallel with other asynchronous listeners, ensuring non-blocking packet processing. * - * @param listener the asynchronous packet listener to register - * @return the same builder for further configuration + * @param listener the asynchronous mutable packet listener to register + * @return the packet listener registration instance */ @NotNull - PacketListenerRegistration registerAsync(@NotNull AsyncPacketListener listener); + PacketListenerRegistration registerAsync(@NotNull MutableAsyncPacketListener listener); } } diff --git a/src/main/java/dev/protocollib/api/listener/SyncPacketListenerContext.java b/src/main/java/dev/protocollib/api/listener/SyncPacketListenerContext.java deleted file mode 100644 index bd4dab6e6..000000000 --- a/src/main/java/dev/protocollib/api/listener/SyncPacketListenerContext.java +++ /dev/null @@ -1,41 +0,0 @@ -package dev.protocollib.api.listener; - -import org.jetbrains.annotations.NotNull; - -import dev.protocollib.api.Connection; - -/** - * Representing the context of a synchronous packet listener. - */ -public interface SyncPacketListenerContext { - - /** - * Retrieves the connection associated with the packet. - * - * @return the connection handling the packet - */ - @NotNull - Connection connection(); - - /** - * Checks if the packet handling has been cancelled. - * - * @return true if the packet is cancelled, false otherwise - */ - boolean isCancelled(); - - /** - * Sets whether the packet handling is cancelled. If cancelled, the packet - * will not be processed further. - * - * @param cancelled true to cancel the packet, false to allow processing - */ - void setCancelled(boolean cancelled); - - /** - * Adds a listener to be invoked after the packet is sent or received. - * - * @param listener the transmission listener to invoke - */ - void addAsyncTransmissionListener(@NotNull PacketTransmissionListener listener);// TODO async via netty -} diff --git a/src/main/java/dev/protocollib/api/packet/BinaryPacket.java b/src/main/java/dev/protocollib/api/packet/BinaryPacket.java index d845c0c80..6acbde6a3 100644 --- a/src/main/java/dev/protocollib/api/packet/BinaryPacket.java +++ b/src/main/java/dev/protocollib/api/packet/BinaryPacket.java @@ -1,5 +1,7 @@ package dev.protocollib.api.packet; +import org.jetbrains.annotations.NotNull; + /** * Representing a raw binary packet with a packet id and payload. */ @@ -17,5 +19,6 @@ public non-sealed interface BinaryPacket extends PacketLike { * * @return the packet payload as a byte array */ + @NotNull byte[] payload(); } diff --git a/src/main/java/dev/protocollib/api/packet/MutablePacketContainer.java b/src/main/java/dev/protocollib/api/packet/MutablePacketContainer.java index 17df5a279..507fbfbb7 100644 --- a/src/main/java/dev/protocollib/api/packet/MutablePacketContainer.java +++ b/src/main/java/dev/protocollib/api/packet/MutablePacketContainer.java @@ -5,22 +5,45 @@ import dev.protocollib.api.reflect.MutableGenericAccessor; +/** + * Represents a mutable packet container that allows modifications. + */ public interface MutablePacketContainer extends PacketContainer { /** * Retrieves the raw packet object. * - * @return the packet object + *

This method provides access to the underlying packet instance, + * allowing direct interaction with its data.

+ * + * @return the raw packet object */ @NotNull Object packet(); + /** + * Provides a {@link MutableGenericAccessor} for modifying packet fields reflectively. + * + * @return the mutable generic accessor for packet data + */ @NotNull MutableGenericAccessor accessor(); + /** + * Retrieves the packet bundle that this packet is part of, if any. + * + * @return the packet bundle containing this packet, or {@code null} if not part of a bundle + */ @Nullable MutablePacketContainer bundle(); + /** + * Creates and returns a mutable copy of this packet. + * + *

The cloned packet retains mutability, allowing further modifications.

+ * + * @return a mutable clone of this packet container + */ @Nullable MutablePacketContainer clone(); } diff --git a/src/main/java/dev/protocollib/api/packet/PacketContainer.java b/src/main/java/dev/protocollib/api/packet/PacketContainer.java index c39c476d5..45eb3fe58 100644 --- a/src/main/java/dev/protocollib/api/packet/PacketContainer.java +++ b/src/main/java/dev/protocollib/api/packet/PacketContainer.java @@ -6,7 +6,7 @@ import dev.protocollib.api.reflect.GenericAccessor; /** - * Representing a container for a packet. + * Represents a container for a packet. */ public non-sealed interface PacketContainer extends PacketLike { @@ -18,6 +18,11 @@ public non-sealed interface PacketContainer extends PacketLike { @NotNull PacketType packetType(); + /** + * Provides a {@link GenericAccessor} for accessing packet fields reflectively. + * + * @return the generic accessor for packet data + */ @NotNull GenericAccessor accessor(); @@ -32,8 +37,10 @@ public non-sealed interface PacketContainer extends PacketLike { /** * Creates and returns a mutable copy of this packet. - * - * @return a clone of this instance + * + *

The cloned packet allows modifications, unlike the immutable {@code PacketContainer}.

+ * + * @return a mutable clone of this packet container */ @Nullable PacketContainer clone(); diff --git a/src/main/java/dev/protocollib/api/packet/PacketOperationBuilder.java b/src/main/java/dev/protocollib/api/packet/PacketOperationBuilder.java index 27cbc7dd6..1cb0f26e3 100644 --- a/src/main/java/dev/protocollib/api/packet/PacketOperationBuilder.java +++ b/src/main/java/dev/protocollib/api/packet/PacketOperationBuilder.java @@ -26,6 +26,8 @@ public interface PacketOperationBuilder { /** * Registers a listener to be called once the packet has been sent or received. + * The transmission listener will get invoked on the underlying channel's + * event-loop. * * @param listener the listener to be notified upon packet transmission * @return the same builder for further configuration diff --git a/src/main/java/dev/protocollib/api/packet/PacketType.java b/src/main/java/dev/protocollib/api/packet/PacketType.java index c3dd19f6e..0e0ac8d34 100644 --- a/src/main/java/dev/protocollib/api/packet/PacketType.java +++ b/src/main/java/dev/protocollib/api/packet/PacketType.java @@ -2,6 +2,8 @@ import java.util.Optional; +import org.jetbrains.annotations.NotNull; + import dev.protocollib.api.ProtocolDirection; import dev.protocollib.api.ProtocolPhase; import net.kyori.adventure.key.Keyed; @@ -20,6 +22,7 @@ public interface PacketType extends Keyed { * * @return the {@link ProtocolDirection} of the packet, either clientbound or serverbound */ + @NotNull ProtocolDirection protocolDirection(); /** @@ -29,6 +32,7 @@ public interface PacketType extends Keyed { * * @return the {@link ProtocolPhase} associated with this packet */ + @NotNull ProtocolPhase protocolPhase(); /** @@ -42,6 +46,7 @@ public interface PacketType extends Keyed { * * @return an {@link Optional} containing the class of the packet, or empty if not applicable */ + @NotNull Optional> packetClass(); /** diff --git a/src/main/java/dev/protocollib/api/reflect/GenericMutator.java b/src/main/java/dev/protocollib/api/reflect/GenericMutator.java index 4c9cc9bc9..f78d65dc2 100644 --- a/src/main/java/dev/protocollib/api/reflect/GenericMutator.java +++ b/src/main/java/dev/protocollib/api/reflect/GenericMutator.java @@ -5,9 +5,6 @@ public interface GenericMutator extends GenericAccessor { - MutableGenericAccessor getAccessor(Class type, int ordinal); - MutableGenericAccessor getAccessorOrThrow(Class type, int ordinal); - // ==================================================== // Value Modification // ==================================================== diff --git a/src/main/java/dev/protocollib/api/reflect/MutableGenericAccessor.java b/src/main/java/dev/protocollib/api/reflect/MutableGenericAccessor.java index 186909da8..7e17e7856 100644 --- a/src/main/java/dev/protocollib/api/reflect/MutableGenericAccessor.java +++ b/src/main/java/dev/protocollib/api/reflect/MutableGenericAccessor.java @@ -4,9 +4,6 @@ public interface MutableGenericAccessor extends GenericAccessor { - MutableGenericAccessor getAccessor(Class type, int ordinal); - MutableGenericAccessor getAccessorOrThrow(Class type, int ordinal); - void update(Consumer consumer); }