Repository files navigation

bannerbanner

Paklet is annotation based Java library for simple and fast packet crafting.

LICENSERELEASE


Table of contents

Features

  • 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

Usage

Creating a packet class

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)
publicclassStatusResponsePacket {
privateStringjsonResponse;
// 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)
publicclassStatusResponsePacket {
@PacketIDpublicstaticfinalintID = PacketUtil.getID(StatusResponsePacket.class);
privateStringjsonResponse;
// 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)
publicclassPingPacket {
// with the usage of SerializeWithprivate@SerializeWith(VarIntSerializer.class) intvalue;
// with the aliasprivate@VarIntintalias;
}

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.

Custom Serializer

Paklet allows simple way of creating custom serializers. To create a custom serializer, implement Serializer interface.

@Supports({Integer.class, int.class})
publicclassMyCustomSerializerimplementsSerializer<Integer> {
@Overridepublicvoidserialize(SerializerContextcontext, DataVisitorvisitor, Integervalue) {
// serialization
}
@OverridepublicIntegerdeserialize(SerializerContextcontext, DataVisitorvisitor) {
// 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.

Provided serializers by Paklet
SerializerSupported typesCatalogue
BooleanBoolean, booleanDefaultSerializers
ByteByte, byteDefaultSerializers
ShortShort, shortDefaultSerializers
IntegerInteger, intDefaultSerializers
LongLong, longDefaultSerializers
FloatFloat, floatDefaultSerializers
DoubleDouble, doubleDefaultSerializers
CharacterCharacter, charDefaultSerializers
NumberNumber, BigDecimal, BigIntegerDefaultSerializers
StringStringDefaultSerializers
CollectionCollection, SequencedCollection, List, LinkedList, ArrayList, Set, LinkedHashSet, HashSetDefaultSerializers
MapMap, SequencedMap, HashMap, LinkedHashMap, TreeMapDefaultSerializers
UUIDUUIDDefaultSerializers
InstantInstantDefaultSerializers
BitSetBitSetDefaultSerializers
Enumnone, has to be specifiedDefaultSerializers
Arraynone, has to be specifiedDefaultSerializers
Serializablenone, has to be specifiedDefaultSerializers
VarIntSerializerInteger, intnone
VarLongSerializerLong, longnone

For more examples of serializer implementation, see Serializers.

Packet Crafting

To read and write packets, instance of PacketFactory is required. The default implementation is provided in paklet-core module as PacketFactoryImpl.

publicstaticPacketFactorycreateFactory() {
// Creates new serializer providerSerializerProviderserializerProvider = newSerializerProviderImpl();
// Registers default serializers and serialization rules provided by PakletserializerProvider.addSerializers(DefaultSerializers.class);
serializerProvider.addSerializationRules(DefaultSerializationRules.class);
// Creates new packet factoryPacketFactorypacketFactory = newPacketFactoryImpl(PacketEncoder.varInt(), serializerProvider);
// Registers custom packetspacketFactory.addPackets(MyPacketsCatalogue.class);
returnpacketFactory;
}

Packets can be then read and written as such:

// implementation of data visitor backed by netty's byte buffer provided by Paklet.DataVisitorvisitor = newNettyDataVisitor(Unpooled.buffer());
MyPacketpacket = newMyPacket();
packet.setContent("Hello World");
// Serializationfactory.write(packet, visitor);
// DeserializationMyPacketpacketClone = 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.

Importing

API and Annotation Processor

repositories {
maven {
name ="machinemcRepositoryReleases"
url = uri("https://repo.machinemc.org/releases")
}
}
dependencies {
implementation("org.machinemc:paklet-api:VERSION")
annotationProcessor("org.machinemc:paklet-processor:VERSION")
}

Implementation

repositories {
maven {
name ="machinemcRepositoryReleases"
url = uri("https://repo.machinemc.org/releases")
}
}
dependencies {
implementation("org.machinemc:paklet-core:VERSION")
}

Gradle Plugin

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>()

License

Paklet is free software licensed under the MIT license.

About

Annotation based library for easy packet crafting

Resources

Stars

5 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Repository files navigation

bannerbanner

Paklet is annotation based Java library for simple and fast packet crafting.

LICENSERELEASE


Table of contents

Features

  • 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

Usage

Creating a packet class

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)
publicclassStatusResponsePacket {
privateStringjsonResponse;
// 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)
publicclassStatusResponsePacket {
@PacketIDpublicstaticfinalintID = PacketUtil.getID(StatusResponsePacket.class);
privateStringjsonResponse;
// 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)
publicclassPingPacket {
// with the usage of SerializeWithprivate@SerializeWith(VarIntSerializer.class) intvalue;
// with the aliasprivate@VarIntintalias;
}

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.

Custom Serializer

Paklet allows simple way of creating custom serializers. To create a custom serializer, implement Serializer interface.

@Supports({Integer.class, int.class})
publicclassMyCustomSerializerimplementsSerializer<Integer> {
@Overridepublicvoidserialize(SerializerContextcontext, DataVisitorvisitor, Integervalue) {
// serialization
}
@OverridepublicIntegerdeserialize(SerializerContextcontext, DataVisitorvisitor) {
// 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.

Provided serializers by Paklet
SerializerSupported typesCatalogue
BooleanBoolean, booleanDefaultSerializers
ByteByte, byteDefaultSerializers
ShortShort, shortDefaultSerializers
IntegerInteger, intDefaultSerializers
LongLong, longDefaultSerializers
FloatFloat, floatDefaultSerializers
DoubleDouble, doubleDefaultSerializers
CharacterCharacter, charDefaultSerializers
NumberNumber, BigDecimal, BigIntegerDefaultSerializers
StringStringDefaultSerializers
CollectionCollection, SequencedCollection, List, LinkedList, ArrayList, Set, LinkedHashSet, HashSetDefaultSerializers
MapMap, SequencedMap, HashMap, LinkedHashMap, TreeMapDefaultSerializers
UUIDUUIDDefaultSerializers
InstantInstantDefaultSerializers
BitSetBitSetDefaultSerializers
Enumnone, has to be specifiedDefaultSerializers
Arraynone, has to be specifiedDefaultSerializers
Serializablenone, has to be specifiedDefaultSerializers
VarIntSerializerInteger, intnone
VarLongSerializerLong, longnone

For more examples of serializer implementation, see Serializers.

Packet Crafting

To read and write packets, instance of PacketFactory is required. The default implementation is provided in paklet-core module as PacketFactoryImpl.

publicstaticPacketFactorycreateFactory() {
// Creates new serializer providerSerializerProviderserializerProvider = newSerializerProviderImpl();
// Registers default serializers and serialization rules provided by PakletserializerProvider.addSerializers(DefaultSerializers.class);
serializerProvider.addSerializationRules(DefaultSerializationRules.class);
// Creates new packet factoryPacketFactorypacketFactory = newPacketFactoryImpl(PacketEncoder.varInt(), serializerProvider);
// Registers custom packetspacketFactory.addPackets(MyPacketsCatalogue.class);
returnpacketFactory;
}

Packets can be then read and written as such:

// implementation of data visitor backed by netty's byte buffer provided by Paklet.DataVisitorvisitor = newNettyDataVisitor(Unpooled.buffer());
MyPacketpacket = newMyPacket();
packet.setContent("Hello World");
// Serializationfactory.write(packet, visitor);
// DeserializationMyPacketpacketClone = 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.

Importing

API and Annotation Processor

repositories {
maven {
name ="machinemcRepositoryReleases"
url = uri("https://repo.machinemc.org/releases")
}
}
dependencies {
implementation("org.machinemc:paklet-api:VERSION")
annotationProcessor("org.machinemc:paklet-processor:VERSION")
}

Implementation

repositories {
maven {
name ="machinemcRepositoryReleases"
url = uri("https://repo.machinemc.org/releases")
}
}
dependencies {
implementation("org.machinemc:paklet-core:VERSION")
}

Gradle Plugin

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>()

License

Paklet is free software licensed under the MIT license.

About

Annotation based library for easy packet crafting

Resources

Stars

5 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

bannerbanner

Paklet is annotation based Java library for simple and fast packet crafting.

LICENSERELEASE


Table of contents

Features

  • 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

Usage

Creating a packet class

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)
publicclassStatusResponsePacket {
privateStringjsonResponse;
// 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)
publicclassStatusResponsePacket {
@PacketIDpublicstaticfinalintID = PacketUtil.getID(StatusResponsePacket.class);
privateStringjsonResponse;
// 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)
publicclassPingPacket {
// with the usage of SerializeWithprivate@SerializeWith(VarIntSerializer.class) intvalue;
// with the aliasprivate@VarIntintalias;
}

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.

Custom Serializer

Paklet allows simple way of creating custom serializers. To create a custom serializer, implement Serializer interface.

@Supports({Integer.class, int.class})
publicclassMyCustomSerializerimplementsSerializer<Integer> {
@Overridepublicvoidserialize(SerializerContextcontext, DataVisitorvisitor, Integervalue) {
// serialization
}
@OverridepublicIntegerdeserialize(SerializerContextcontext, DataVisitorvisitor) {
// 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.

Provided serializers by Paklet
SerializerSupported typesCatalogue
BooleanBoolean, booleanDefaultSerializers
ByteByte, byteDefaultSerializers
ShortShort, shortDefaultSerializers
IntegerInteger, intDefaultSerializers
LongLong, longDefaultSerializers
FloatFloat, floatDefaultSerializers
DoubleDouble, doubleDefaultSerializers
CharacterCharacter, charDefaultSerializers
NumberNumber, BigDecimal, BigIntegerDefaultSerializers
StringStringDefaultSerializers
CollectionCollection, SequencedCollection, List, LinkedList, ArrayList, Set, LinkedHashSet, HashSetDefaultSerializers
MapMap, SequencedMap, HashMap, LinkedHashMap, TreeMapDefaultSerializers
UUIDUUIDDefaultSerializers
InstantInstantDefaultSerializers
BitSetBitSetDefaultSerializers
Enumnone, has to be specifiedDefaultSerializers
Arraynone, has to be specifiedDefaultSerializers
Serializablenone, has to be specifiedDefaultSerializers
VarIntSerializerInteger, intnone
VarLongSerializerLong, longnone

For more examples of serializer implementation, see Serializers.

Packet Crafting

To read and write packets, instance of PacketFactory is required. The default implementation is provided in paklet-core module as PacketFactoryImpl.

publicstaticPacketFactorycreateFactory() {
// Creates new serializer providerSerializerProviderserializerProvider = newSerializerProviderImpl();
// Registers default serializers and serialization rules provided by PakletserializerProvider.addSerializers(DefaultSerializers.class);
serializerProvider.addSerializationRules(DefaultSerializationRules.class);
// Creates new packet factoryPacketFactorypacketFactory = newPacketFactoryImpl(PacketEncoder.varInt(), serializerProvider);
// Registers custom packetspacketFactory.addPackets(MyPacketsCatalogue.class);
returnpacketFactory;
}

Packets can be then read and written as such:

// implementation of data visitor backed by netty's byte buffer provided by Paklet.DataVisitorvisitor = newNettyDataVisitor(Unpooled.buffer());
MyPacketpacket = newMyPacket();
packet.setContent("Hello World");
// Serializationfactory.write(packet, visitor);
// DeserializationMyPacketpacketClone = 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.

Importing

API and Annotation Processor

repositories {
maven {
name ="machinemcRepositoryReleases"
url = uri("https://repo.machinemc.org/releases")
}
}
dependencies {
implementation("org.machinemc:paklet-api:VERSION")
annotationProcessor("org.machinemc:paklet-processor:VERSION")
}

Implementation

repositories {
maven {
name ="machinemcRepositoryReleases"
url = uri("https://repo.machinemc.org/releases")
}
}
dependencies {
implementation("org.machinemc:paklet-core:VERSION")
}

Gradle Plugin

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>()

License

Paklet is free software licensed under the MIT license.

About

Annotation based library for easy packet crafting

Resources

Stars

5 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

bannerbanner

Paklet is annotation based Java library for simple and fast packet crafting.

LICENSERELEASE


Table of contents

Features

  • 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

Usage

Creating a packet class

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)
publicclassStatusResponsePacket {
privateStringjsonResponse;
// 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)
publicclassStatusResponsePacket {
@PacketIDpublicstaticfinalintID = PacketUtil.getID(StatusResponsePacket.class);
privateStringjsonResponse;
// 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)
publicclassPingPacket {
// with the usage of SerializeWithprivate@SerializeWith(VarIntSerializer.class) intvalue;
// with the aliasprivate@VarIntintalias;
}

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.

Custom Serializer

Paklet allows simple way of creating custom serializers. To create a custom serializer, implement Serializer interface.

@Supports({Integer.class, int.class})
publicclassMyCustomSerializerimplementsSerializer<Integer> {
@Overridepublicvoidserialize(SerializerContextcontext, DataVisitorvisitor, Integervalue) {
// serialization
}
@OverridepublicIntegerdeserialize(SerializerContextcontext, DataVisitorvisitor) {
// 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.

Provided serializers by Paklet
SerializerSupported typesCatalogue
BooleanBoolean, booleanDefaultSerializers
ByteByte, byteDefaultSerializers
ShortShort, shortDefaultSerializers
IntegerInteger, intDefaultSerializers
LongLong, longDefaultSerializers
FloatFloat, floatDefaultSerializers
DoubleDouble, doubleDefaultSerializers
CharacterCharacter, charDefaultSerializers
NumberNumber, BigDecimal, BigIntegerDefaultSerializers
StringStringDefaultSerializers
CollectionCollection, SequencedCollection, List, LinkedList, ArrayList, Set, LinkedHashSet, HashSetDefaultSerializers
MapMap, SequencedMap, HashMap, LinkedHashMap, TreeMapDefaultSerializers
UUIDUUIDDefaultSerializers
InstantInstantDefaultSerializers
BitSetBitSetDefaultSerializers
Enumnone, has to be specifiedDefaultSerializers
Arraynone, has to be specifiedDefaultSerializers
Serializablenone, has to be specifiedDefaultSerializers
VarIntSerializerInteger, intnone
VarLongSerializerLong, longnone

For more examples of serializer implementation, see Serializers.

Packet Crafting

To read and write packets, instance of PacketFactory is required. The default implementation is provided in paklet-core module as PacketFactoryImpl.

publicstaticPacketFactorycreateFactory() {
// Creates new serializer providerSerializerProviderserializerProvider = newSerializerProviderImpl();
// Registers default serializers and serialization rules provided by PakletserializerProvider.addSerializers(DefaultSerializers.class);
serializerProvider.addSerializationRules(DefaultSerializationRules.class);
// Creates new packet factoryPacketFactorypacketFactory = newPacketFactoryImpl(PacketEncoder.varInt(), serializerProvider);
// Registers custom packetspacketFactory.addPackets(MyPacketsCatalogue.class);
returnpacketFactory;
}

Packets can be then read and written as such:

// implementation of data visitor backed by netty's byte buffer provided by Paklet.DataVisitorvisitor = newNettyDataVisitor(Unpooled.buffer());
MyPacketpacket = newMyPacket();
packet.setContent("Hello World");
// Serializationfactory.write(packet, visitor);
// DeserializationMyPacketpacketClone = 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.

Importing

API and Annotation Processor

repositories {
maven {
name ="machinemcRepositoryReleases"
url = uri("https://repo.machinemc.org/releases")
}
}
dependencies {
implementation("org.machinemc:paklet-api:VERSION")
annotationProcessor("org.machinemc:paklet-processor:VERSION")
}

Implementation

repositories {
maven {
name ="machinemcRepositoryReleases"
url = uri("https://repo.machinemc.org/releases")
}
}
dependencies {
implementation("org.machinemc:paklet-core:VERSION")
}

Gradle Plugin

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>()

License

Paklet is free software licensed under the MIT license.

About

Annotation based library for easy packet crafting

Resources

Stars

5 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Repository files navigation

bannerbanner

Paklet is annotation based Java library for simple and fast packet crafting.

LICENSERELEASE


Table of contents

Features

  • 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

Usage

Creating a packet class

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)
publicclassStatusResponsePacket {
privateStringjsonResponse;
// 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)
publicclassStatusResponsePacket {
@PacketIDpublicstaticfinalintID = PacketUtil.getID(StatusResponsePacket.class);
privateStringjsonResponse;
// 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)
publicclassPingPacket {
// with the usage of SerializeWithprivate@SerializeWith(VarIntSerializer.class) intvalue;
// with the aliasprivate@VarIntintalias;
}

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.

Custom Serializer

Paklet allows simple way of creating custom serializers. To create a custom serializer, implement Serializer interface.

@Supports({Integer.class, int.class})
publicclassMyCustomSerializerimplementsSerializer<Integer> {
@Overridepublicvoidserialize(SerializerContextcontext, DataVisitorvisitor, Integervalue) {
// serialization
}
@OverridepublicIntegerdeserialize(SerializerContextcontext, DataVisitorvisitor) {
// 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.

Provided serializers by Paklet
SerializerSupported typesCatalogue
BooleanBoolean, booleanDefaultSerializers
ByteByte, byteDefaultSerializers
ShortShort, shortDefaultSerializers
IntegerInteger, intDefaultSerializers
LongLong, longDefaultSerializers
FloatFloat, floatDefaultSerializers
DoubleDouble, doubleDefaultSerializers
CharacterCharacter, charDefaultSerializers
NumberNumber, BigDecimal, BigIntegerDefaultSerializers
StringStringDefaultSerializers
CollectionCollection, SequencedCollection, List, LinkedList, ArrayList, Set, LinkedHashSet, HashSetDefaultSerializers
MapMap, SequencedMap, HashMap, LinkedHashMap, TreeMapDefaultSerializers
UUIDUUIDDefaultSerializers
InstantInstantDefaultSerializers
BitSetBitSetDefaultSerializers
Enumnone, has to be specifiedDefaultSerializers
Arraynone, has to be specifiedDefaultSerializers
Serializablenone, has to be specifiedDefaultSerializers
VarIntSerializerInteger, intnone
VarLongSerializerLong, longnone

For more examples of serializer implementation, see Serializers.

Packet Crafting

To read and write packets, instance of PacketFactory is required. The default implementation is provided in paklet-core module as PacketFactoryImpl.

publicstaticPacketFactorycreateFactory() {
// Creates new serializer providerSerializerProviderserializerProvider = newSerializerProviderImpl();
// Registers default serializers and serialization rules provided by PakletserializerProvider.addSerializers(DefaultSerializers.class);
serializerProvider.addSerializationRules(DefaultSerializationRules.class);
// Creates new packet factoryPacketFactorypacketFactory = newPacketFactoryImpl(PacketEncoder.varInt(), serializerProvider);
// Registers custom packetspacketFactory.addPackets(MyPacketsCatalogue.class);
returnpacketFactory;
}

Packets can be then read and written as such:

// implementation of data visitor backed by netty's byte buffer provided by Paklet.DataVisitorvisitor = newNettyDataVisitor(Unpooled.buffer());
MyPacketpacket = newMyPacket();
packet.setContent("Hello World");
// Serializationfactory.write(packet, visitor);
// DeserializationMyPacketpacketClone = 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.

Importing

API and Annotation Processor

repositories {
maven {
name ="machinemcRepositoryReleases"
url = uri("https://repo.machinemc.org/releases")
}
}
dependencies {
implementation("org.machinemc:paklet-api:VERSION")
annotationProcessor("org.machinemc:paklet-processor:VERSION")
}

Implementation

repositories {
maven {
name ="machinemcRepositoryReleases"
url = uri("https://repo.machinemc.org/releases")
}
}
dependencies {
implementation("org.machinemc:paklet-core:VERSION")
}

Gradle Plugin

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>()

License

Paklet is free software licensed under the MIT license.

About

Annotation based library for easy packet crafting

Resources

Stars

5 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

bannerbanner

Paklet is annotation based Java library for simple and fast packet crafting.

LICENSERELEASE


Table of contents

Features

  • 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

Usage

Creating a packet class

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)
publicclassStatusResponsePacket {
privateStringjsonResponse;
// 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)
publicclassStatusResponsePacket {
@PacketIDpublicstaticfinalintID = PacketUtil.getID(StatusResponsePacket.class);
privateStringjsonResponse;
// 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)
publicclassPingPacket {
// with the usage of SerializeWithprivate@SerializeWith(VarIntSerializer.class) intvalue;
// with the aliasprivate@VarIntintalias;
}

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.

Custom Serializer

Paklet allows simple way of creating custom serializers. To create a custom serializer, implement Serializer interface.

@Supports({Integer.class, int.class})
publicclassMyCustomSerializerimplementsSerializer<Integer> {
@Overridepublicvoidserialize(SerializerContextcontext, DataVisitorvisitor, Integervalue) {
// serialization
}
@OverridepublicIntegerdeserialize(SerializerContextcontext, DataVisitorvisitor) {
// 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.

Provided serializers by Paklet
SerializerSupported typesCatalogue
BooleanBoolean, booleanDefaultSerializers
ByteByte, byteDefaultSerializers
ShortShort, shortDefaultSerializers
IntegerInteger, intDefaultSerializers
LongLong, longDefaultSerializers
FloatFloat, floatDefaultSerializers
DoubleDouble, doubleDefaultSerializers
CharacterCharacter, charDefaultSerializers
NumberNumber, BigDecimal, BigIntegerDefaultSerializers
StringStringDefaultSerializers
CollectionCollection, SequencedCollection, List, LinkedList, ArrayList, Set, LinkedHashSet, HashSetDefaultSerializers
MapMap, SequencedMap, HashMap, LinkedHashMap, TreeMapDefaultSerializers
UUIDUUIDDefaultSerializers
InstantInstantDefaultSerializers
BitSetBitSetDefaultSerializers
Enumnone, has to be specifiedDefaultSerializers
Arraynone, has to be specifiedDefaultSerializers
Serializablenone, has to be specifiedDefaultSerializers
VarIntSerializerInteger, intnone
VarLongSerializerLong, longnone

For more examples of serializer implementation, see Serializers.

Packet Crafting

To read and write packets, instance of PacketFactory is required. The default implementation is provided in paklet-core module as PacketFactoryImpl.

publicstaticPacketFactorycreateFactory() {
// Creates new serializer providerSerializerProviderserializerProvider = newSerializerProviderImpl();
// Registers default serializers and serialization rules provided by PakletserializerProvider.addSerializers(DefaultSerializers.class);
serializerProvider.addSerializationRules(DefaultSerializationRules.class);
// Creates new packet factoryPacketFactorypacketFactory = newPacketFactoryImpl(PacketEncoder.varInt(), serializerProvider);
// Registers custom packetspacketFactory.addPackets(MyPacketsCatalogue.class);
returnpacketFactory;
}

Packets can be then read and written as such:

// implementation of data visitor backed by netty's byte buffer provided by Paklet.DataVisitorvisitor = newNettyDataVisitor(Unpooled.buffer());
MyPacketpacket = newMyPacket();
packet.setContent("Hello World");
// Serializationfactory.write(packet, visitor);
// DeserializationMyPacketpacketClone = 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.

Importing

API and Annotation Processor

repositories {
maven {
name ="machinemcRepositoryReleases"
url = uri("https://repo.machinemc.org/releases")
}
}
dependencies {
implementation("org.machinemc:paklet-api:VERSION")
annotationProcessor("org.machinemc:paklet-processor:VERSION")
}

Implementation

repositories {
maven {
name ="machinemcRepositoryReleases"
url = uri("https://repo.machinemc.org/releases")
}
}
dependencies {
implementation("org.machinemc:paklet-core:VERSION")
}

Gradle Plugin

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>()

License

Paklet is free software licensed under the MIT license.

About

Annotation based library for easy packet crafting

Resources

Stars

5 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

bannerbanner

Paklet is annotation based Java library for simple and fast packet crafting.

LICENSERELEASE


Table of contents

Features

  • 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

Usage

Creating a packet class

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)
publicclassStatusResponsePacket {
privateStringjsonResponse;
// 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)
publicclassStatusResponsePacket {
@PacketIDpublicstaticfinalintID = PacketUtil.getID(StatusResponsePacket.class);
privateStringjsonResponse;
// 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)
publicclassPingPacket {
// with the usage of SerializeWithprivate@SerializeWith(VarIntSerializer.class) intvalue;
// with the aliasprivate@VarIntintalias;
}

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.

Custom Serializer

Paklet allows simple way of creating custom serializers. To create a custom serializer, implement Serializer interface.

@Supports({Integer.class, int.class})
publicclassMyCustomSerializerimplementsSerializer<Integer> {
@Overridepublicvoidserialize(SerializerContextcontext, DataVisitorvisitor, Integervalue) {
// serialization
}
@OverridepublicIntegerdeserialize(SerializerContextcontext, DataVisitorvisitor) {
// 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.

Provided serializers by Paklet
SerializerSupported typesCatalogue
BooleanBoolean, booleanDefaultSerializers
ByteByte, byteDefaultSerializers
ShortShort, shortDefaultSerializers
IntegerInteger, intDefaultSerializers
LongLong, longDefaultSerializers
FloatFloat, floatDefaultSerializers
DoubleDouble, doubleDefaultSerializers
CharacterCharacter, charDefaultSerializers
NumberNumber, BigDecimal, BigIntegerDefaultSerializers
StringStringDefaultSerializers
CollectionCollection, SequencedCollection, List, LinkedList, ArrayList, Set, LinkedHashSet, HashSetDefaultSerializers
MapMap, SequencedMap, HashMap, LinkedHashMap, TreeMapDefaultSerializers
UUIDUUIDDefaultSerializers
InstantInstantDefaultSerializers
BitSetBitSetDefaultSerializers
Enumnone, has to be specifiedDefaultSerializers
Arraynone, has to be specifiedDefaultSerializers
Serializablenone, has to be specifiedDefaultSerializers
VarIntSerializerInteger, intnone
VarLongSerializerLong, longnone

For more examples of serializer implementation, see Serializers.

Packet Crafting

To read and write packets, instance of PacketFactory is required. The default implementation is provided in paklet-core module as PacketFactoryImpl.

publicstaticPacketFactorycreateFactory() {
// Creates new serializer providerSerializerProviderserializerProvider = newSerializerProviderImpl();
// Registers default serializers and serialization rules provided by PakletserializerProvider.addSerializers(DefaultSerializers.class);
serializerProvider.addSerializationRules(DefaultSerializationRules.class);
// Creates new packet factoryPacketFactorypacketFactory = newPacketFactoryImpl(PacketEncoder.varInt(), serializerProvider);
// Registers custom packetspacketFactory.addPackets(MyPacketsCatalogue.class);
returnpacketFactory;
}

Packets can be then read and written as such:

// implementation of data visitor backed by netty's byte buffer provided by Paklet.DataVisitorvisitor = newNettyDataVisitor(Unpooled.buffer());
MyPacketpacket = newMyPacket();
packet.setContent("Hello World");
// Serializationfactory.write(packet, visitor);
// DeserializationMyPacketpacketClone = 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.

Importing

API and Annotation Processor

repositories {
maven {
name ="machinemcRepositoryReleases"
url = uri("https://repo.machinemc.org/releases")
}
}
dependencies {
implementation("org.machinemc:paklet-api:VERSION")
annotationProcessor("org.machinemc:paklet-processor:VERSION")
}

Implementation

repositories {
maven {
name ="machinemcRepositoryReleases"
url = uri("https://repo.machinemc.org/releases")
}
}
dependencies {
implementation("org.machinemc:paklet-core:VERSION")
}

Gradle Plugin

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>()

License

Paklet is free software licensed under the MIT license.

About

Annotation based library for easy packet crafting

Resources

Stars

5 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Repository files navigation

bannerbanner

Paklet is annotation based Java library for simple and fast packet crafting.

LICENSERELEASE


Table of contents

Features

  • 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

Usage

Creating a packet class

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)
publicclassStatusResponsePacket {
privateStringjsonResponse;
// 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)
publicclassStatusResponsePacket {
@PacketIDpublicstaticfinalintID = PacketUtil.getID(StatusResponsePacket.class);
privateStringjsonResponse;
// 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)
publicclassPingPacket {
// with the usage of SerializeWithprivate@SerializeWith(VarIntSerializer.class) intvalue;
// with the aliasprivate@VarIntintalias;
}

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.

Custom Serializer

Paklet allows simple way of creating custom serializers. To create a custom serializer, implement Serializer interface.

@Supports({Integer.class, int.class})
publicclassMyCustomSerializerimplementsSerializer<Integer> {
@Overridepublicvoidserialize(SerializerContextcontext, DataVisitorvisitor, Integervalue) {
// serialization
}
@OverridepublicIntegerdeserialize(SerializerContextcontext, DataVisitorvisitor) {
// 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.

Provided serializers by Paklet
SerializerSupported typesCatalogue
BooleanBoolean, booleanDefaultSerializers
ByteByte, byteDefaultSerializers
ShortShort, shortDefaultSerializers
IntegerInteger, intDefaultSerializers
LongLong, longDefaultSerializers
FloatFloat, floatDefaultSerializers
DoubleDouble, doubleDefaultSerializers
CharacterCharacter, charDefaultSerializers
NumberNumber, BigDecimal, BigIntegerDefaultSerializers
StringStringDefaultSerializers
CollectionCollection, SequencedCollection, List, LinkedList, ArrayList, Set, LinkedHashSet, HashSetDefaultSerializers
MapMap, SequencedMap, HashMap, LinkedHashMap, TreeMapDefaultSerializers
UUIDUUIDDefaultSerializers
InstantInstantDefaultSerializers
BitSetBitSetDefaultSerializers
Enumnone, has to be specifiedDefaultSerializers
Arraynone, has to be specifiedDefaultSerializers
Serializablenone, has to be specifiedDefaultSerializers
VarIntSerializerInteger, intnone
VarLongSerializerLong, longnone

For more examples of serializer implementation, see Serializers.

Packet Crafting

To read and write packets, instance of PacketFactory is required. The default implementation is provided in paklet-core module as PacketFactoryImpl.

publicstaticPacketFactorycreateFactory() {
// Creates new serializer providerSerializerProviderserializerProvider = newSerializerProviderImpl();
// Registers default serializers and serialization rules provided by PakletserializerProvider.addSerializers(DefaultSerializers.class);
serializerProvider.addSerializationRules(DefaultSerializationRules.class);
// Creates new packet factoryPacketFactorypacketFactory = newPacketFactoryImpl(PacketEncoder.varInt(), serializerProvider);
// Registers custom packetspacketFactory.addPackets(MyPacketsCatalogue.class);
returnpacketFactory;
}

Packets can be then read and written as such:

// implementation of data visitor backed by netty's byte buffer provided by Paklet.DataVisitorvisitor = newNettyDataVisitor(Unpooled.buffer());
MyPacketpacket = newMyPacket();
packet.setContent("Hello World");
// Serializationfactory.write(packet, visitor);
// DeserializationMyPacketpacketClone = 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.

Importing

API and Annotation Processor

repositories {
maven {
name ="machinemcRepositoryReleases"
url = uri("https://repo.machinemc.org/releases")
}
}
dependencies {
implementation("org.machinemc:paklet-api:VERSION")
annotationProcessor("org.machinemc:paklet-processor:VERSION")
}

Implementation

repositories {
maven {
name ="machinemcRepositoryReleases"
url = uri("https://repo.machinemc.org/releases")
}
}
dependencies {
implementation("org.machinemc:paklet-core:VERSION")
}

Gradle Plugin

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>()

License

Paklet is free software licensed under the MIT license.

About

Annotation based library for easy packet crafting

Resources

Stars

5 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages