Paklet is annotation based Java library for simple and fast packet crafting.
- Simplicity – The annotation system is straightforward and easy to use
- Flexibility – You can customize the serialization of each packet field or even the whole packet
- Expandable – Paklet can be easily extended to automate the serialization of custom types.
- Speed – Bytecode manipulation in the background ensures the packet serialization is fast
All classes annotated with @Packet
are considered packets. All their fields, if they are not static
, transient
,
or annotated with @Ignore
are automatically serialized by default serializers if not specified otherwise.
All field values are expected to be not null by default, but this behaviour can be changed
with the use of @Optional
annotation.
@Packet(id = 0x00, group = "ClientBoundStatus", catalogue = ClientBoundStatusPackets.class)
public class StatusResponsePacket {
private String jsonResponse;
// getters and setters
}
Each packet needs to specify its numeric ID, catalogue class, and can specify its group in case the packet IDs overlap, this is later used for deserialization.
Packet IDs can be alternatively resolved using @PacketID
annotation for packets that require dynamic IDs.
@Packet(id = DYNAMIC_PACKET, group = "ClientBoundStatus", catalogue = ClientBoundStatusPackets.class)
public class StatusResponsePacket {
@PacketID
public static final int ID = PacketUtil.getID(StatusResponsePacket.class);
private String jsonResponse;
// getters and setters
}
To specify which serializer to use for each packet field serialization, Paklet offers
@SerializeWith
annotation
and serializer annotation aliases.
@Packet(id = 0x01, catalogue = TestPackets.class)
public class PingPacket {
// with the usage of SerializeWith
private @SerializeWith(VarIntSerializer.class) int value;
// with the alias
private @VarInt int alias;
}
Some types can be annotated with additional metadata. Default set of supported metadata by Paklet can be found in metadata package.
Both modifiers and metadata can be used for parameters, e.g. List<@VarLong Long>
.
For packets that require fully custom serialization, Paklet offers the
CustomPacket
interface. This is
meant to be used for packets that require more complicated serialization that can not be
resolved with automatic serialization.
Note
Paklet also offers VarIntSerializer
and VarLongSerializer
compatible with the Minecraft Java Protocol.
For more examples see tests of the paklet-core
module.
Paklet allows simple way of creating custom serializers.
To create a custom serializer, implement Serializer
interface.
@Supports({Integer.class, int.class})
public class MyCustomSerializer implements Serializer<Integer> {
@Override
public void serialize(SerializerContext context, DataVisitor visitor, Integer value) {
// serialization
}
@Override
public Integer deserialize(SerializerContext context, DataVisitor visitor) {
// deserialization
}
}
@Supports
annotation specifies which types the serializer supports,
if more complex rule for choosing the types is needed (e.g. array types), the array can stay empty and custom
SerializationRule
needs to be implemented.
All serializers annotated with @DefaultSerializer
are automatically registered with given catalogue.
SerializerContext
provided for each serialization action gives
access to currently registered serializers and type of field that is currently being serialized.
Serializer | Supported types | Catalogue |
---|---|---|
Boolean | Boolean, boolean |
DefaultSerializers |
Byte | Byte, byte |
DefaultSerializers |
Short | Short, short |
DefaultSerializers |
Integer | Integer, int |
DefaultSerializers |
Long | Long, long |
DefaultSerializers |
Float | Float, float |
DefaultSerializers |
Double | Double, double |
DefaultSerializers |
Character | Character, char |
DefaultSerializers |
Number | Number, BigDecimal, BigInteger |
DefaultSerializers |
String | String |
DefaultSerializers |
Collection | Collection, SequencedCollection, List, LinkedList, ArrayList, Set, LinkedHashSet, HashSet |
DefaultSerializers |
Map | Map, SequencedMap, HashMap, LinkedHashMap, TreeMap |
DefaultSerializers |
UUID | UUID |
DefaultSerializers |
Instant | Instant |
DefaultSerializers |
BitSet | BitSet |
DefaultSerializers |
Enum | none, has to be specified | DefaultSerializers |
Array | none, has to be specified | DefaultSerializers |
Serializable | none, has to be specified | DefaultSerializers |
VarIntSerializer | Integer, int |
none |
VarLongSerializer | Long, long |
none |
For more examples of serializer implementation, see Serializers
.
To read and write packets, instance of PacketFactory
is required.
The default implementation is provided in paklet-core
module as PacketFactoryImpl
.
public static PacketFactory createFactory() {
// Creates new serializer provider
SerializerProvider serializerProvider = new SerializerProviderImpl();
// Registers default serializers and serialization rules provided by Paklet
serializerProvider.addSerializers(DefaultSerializers.class);
serializerProvider.addSerializationRules(DefaultSerializationRules.class);
// Creates new packet factory
PacketFactory packetFactory = new PacketFactoryImpl(PacketEncoder.varInt(), serializerProvider);
// Registers custom packets
packetFactory.addPackets(MyPacketsCatalogue.class);
return packetFactory;
}
Packets can be then read and written as such:
// implementation of data visitor backed by netty's byte buffer provided by Paklet.
DataVisitor visitor = new NettyDataVisitor(Unpooled.buffer());
MyPacket packet = new MyPacket();
packet.setContent("Hello World");
// Serialization
factory.write(packet, visitor);
// Deserialization
MyPacket packetClone = factory.create(packetGroup, visitor);
Paklet has much more tools to offer than shown in this README, developers are encouraged to explore the source code and discover additional APIs! :)
For more examples see tests of the paklet-core
module.
repositories {
maven {
name = "machinemcRepositoryReleases"
url = uri("https://repo.machinemc.org/releases")
}
}
dependencies {
implementation("org.machinemc:paklet-api:VERSION")
annotationProcessor("org.machinemc:paklet-processor:VERSION")
}
repositories {
maven {
name = "machinemcRepositoryReleases"
url = uri("https://repo.machinemc.org/releases")
}
}
dependencies {
implementation("org.machinemc:paklet-core:VERSION")
}
Note
Gradle plugin is a key feature of Paklet. It modifies bytecode of compiled packet classes later used by generated packet readers and writers to achieve higher speeds.
buildscript {
repositories {
maven {
url = uri("https://repo.machinemc.org/releases")
}
}
dependencies {
classpath("org.machinemc:paklet-plugin:VERSION")
}
}
apply<PakletPlugin>()
Paklet is free software licensed under the MIT license.