Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Kotlin serialization based networking #69

Draft
wants to merge 7 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
82 changes: 82 additions & 0 deletions library/api/library.api
Original file line number Diff line number Diff line change
Expand Up @@ -796,6 +796,88 @@ public final class org/quiltmc/qkl/library/networking/ServerEventsKt {
public static final fun onPlayReady (Lorg/quiltmc/qkl/library/EventRegistration;Lkotlin/jvm/functions/Function3;)V
}

public final class org/quiltmc/qkl/library/networking/serialization/PacketByteBufDecoder : kotlinx/serialization/encoding/AbstractDecoder {
public static final field Companion Lorg/quiltmc/qkl/library/networking/serialization/PacketByteBufDecoder$Companion;
public fun <init> (Lnet/minecraft/network/PacketByteBuf;Lkotlinx/serialization/modules/SerializersModule;)V
public synthetic fun <init> (Lnet/minecraft/network/PacketByteBuf;Lkotlinx/serialization/modules/SerializersModule;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public fun decodeBoolean ()Z
public fun decodeByte ()B
public fun decodeChar ()C
public fun decodeCollectionSize (Lkotlinx/serialization/descriptors/SerialDescriptor;)I
public fun decodeDouble ()D
public fun decodeElementIndex (Lkotlinx/serialization/descriptors/SerialDescriptor;)I
public fun decodeEnum (Lkotlinx/serialization/descriptors/SerialDescriptor;)I
public fun decodeFloat ()F
public fun decodeInt ()I
public fun decodeLong ()J
public fun decodeNotNullMark ()Z
public fun decodeSequentially ()Z
public fun decodeSerializableValue (Lkotlinx/serialization/DeserializationStrategy;)Ljava/lang/Object;
public fun decodeShort ()S
public fun decodeString ()Ljava/lang/String;
public final fun getInput ()Lnet/minecraft/network/PacketByteBuf;
public fun getSerializersModule ()Lkotlinx/serialization/modules/SerializersModule;
}

public final class org/quiltmc/qkl/library/networking/serialization/PacketByteBufDecoder$Companion {
}

public final class org/quiltmc/qkl/library/networking/serialization/PacketByteBufEncoder : kotlinx/serialization/encoding/AbstractEncoder {
public static final field Companion Lorg/quiltmc/qkl/library/networking/serialization/PacketByteBufEncoder$Companion;
public fun <init> ()V
public fun <init> (Lkotlinx/serialization/modules/SerializersModule;)V
public synthetic fun <init> (Lkotlinx/serialization/modules/SerializersModule;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public fun beginCollection (Lkotlinx/serialization/descriptors/SerialDescriptor;I)Lkotlinx/serialization/encoding/CompositeEncoder;
public fun encodeBoolean (Z)V
public fun encodeByte (B)V
public fun encodeChar (C)V
public fun encodeDouble (D)V
public fun encodeEnum (Lkotlinx/serialization/descriptors/SerialDescriptor;I)V
public fun encodeFloat (F)V
public fun encodeInt (I)V
public fun encodeLong (J)V
public fun encodeNotNullMark ()V
public fun encodeNull ()V
public fun encodeSerializableValue (Lkotlinx/serialization/SerializationStrategy;Ljava/lang/Object;)V
public fun encodeShort (S)V
public fun encodeString (Ljava/lang/String;)V
public final fun getPacketByteBuf ()Lnet/minecraft/network/PacketByteBuf;
public fun getSerializersModule ()Lkotlinx/serialization/modules/SerializersModule;
public final fun setPacketByteBuf (Lnet/minecraft/network/PacketByteBuf;)V
}

public final class org/quiltmc/qkl/library/networking/serialization/PacketByteBufEncoder$Companion {
}

public final class org/quiltmc/qkl/library/networking/serialization/SerializedClientPlayNetworking {
public static final field INSTANCE Lorg/quiltmc/qkl/library/networking/serialization/SerializedClientPlayNetworking;
}

public final class org/quiltmc/qkl/library/networking/serialization/SerializedPacketRegistration {
public fun <init> (Lnet/minecraft/util/Identifier;Lorg/quiltmc/qkl/library/networking/serialization/SerializedPacketRegistration$Direction;Lkotlinx/serialization/modules/SerializersModule;)V
public final fun getDirection ()Lorg/quiltmc/qkl/library/networking/serialization/SerializedPacketRegistration$Direction;
public final fun getId ()Lnet/minecraft/util/Identifier;
public final fun getOnClientReceiveAction ()Lkotlin/jvm/functions/Function4;
public final fun getOnServerReceiveAction ()Lkotlin/jvm/functions/Function5;
public final fun getSerializersModule ()Lkotlinx/serialization/modules/SerializersModule;
public final fun onClientReceive (Lkotlin/jvm/functions/Function4;)V
public final fun onServerReceive (Lkotlin/jvm/functions/Function5;)V
public final fun setOnClientReceiveAction (Lkotlin/jvm/functions/Function4;)V
public final fun setOnServerReceiveAction (Lkotlin/jvm/functions/Function5;)V
}

public final class org/quiltmc/qkl/library/networking/serialization/SerializedPacketRegistration$Direction : java/lang/Enum {
public static final field BiDirectional Lorg/quiltmc/qkl/library/networking/serialization/SerializedPacketRegistration$Direction;
public static final field ClientToServer Lorg/quiltmc/qkl/library/networking/serialization/SerializedPacketRegistration$Direction;
public static final field ServerToClient Lorg/quiltmc/qkl/library/networking/serialization/SerializedPacketRegistration$Direction;
public static fun valueOf (Ljava/lang/String;)Lorg/quiltmc/qkl/library/networking/serialization/SerializedPacketRegistration$Direction;
public static fun values ()[Lorg/quiltmc/qkl/library/networking/serialization/SerializedPacketRegistration$Direction;
}

public final class org/quiltmc/qkl/library/networking/serialization/SerializedServerPlayNetworking {
public static final field INSTANCE Lorg/quiltmc/qkl/library/networking/serialization/SerializedServerPlayNetworking;
}

public final class org/quiltmc/qkl/library/recipe/RecipeEventsKt {
public static final fun onAddRecipes (Lorg/quiltmc/qkl/library/EventRegistration;Lkotlin/jvm/functions/Function1;)V
public static final fun onModifyRecipes (Lorg/quiltmc/qkl/library/EventRegistration;Lkotlin/jvm/functions/Function1;)V
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
/*
* Copyright 2023 QuiltMC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.quiltmc.qkl.library.networking.serialization

import kotlinx.serialization.DeserializationStrategy
import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.descriptors.SerialDescriptor
import kotlinx.serialization.encoding.AbstractDecoder
import kotlinx.serialization.encoding.CompositeDecoder
import kotlinx.serialization.modules.EmptySerializersModule
import kotlinx.serialization.modules.SerializersModule
import kotlinx.serialization.serializer
import net.minecraft.network.PacketByteBuf

/**
* An [AbstractDecoder] that is capable of reading a class from a packet byte buf
*/
@OptIn(ExperimentalSerializationApi::class)
public class PacketByteBufDecoder(
public val input: PacketByteBuf,
override val serializersModule: SerializersModule = EmptySerializersModule()
) : AbstractDecoder() {
private val byteArraySerializer = serializer<ByteArray>()
private var elementIndex = 0
override fun decodeSequentially(): Boolean = true

override fun <T> decodeSerializableValue(deserializer: DeserializationStrategy<T>): T {
if (deserializer.descriptor == byteArraySerializer.descriptor) {
@Suppress("UNCHECKED_CAST")
return input.readByteArray() as T
} else {
return super.decodeSerializableValue(deserializer)
}
}

override fun decodeElementIndex(descriptor: SerialDescriptor): Int {
if (input.readerIndex() >= input.readableBytes()) return CompositeDecoder.DECODE_DONE
return elementIndex++
}

override fun decodeBoolean(): Boolean {
return input.readBoolean()
}

override fun decodeByte(): Byte {
return input.readByte()
}

override fun decodeChar(): Char {
return input.readChar()
}

override fun decodeShort(): Short {
return input.readShort()
}

override fun decodeInt(): Int {
return input.readInt()
}

override fun decodeLong(): Long {
return input.readLong()
}

override fun decodeFloat(): Float {
return input.readFloat()
}

override fun decodeDouble(): Double {
return input.readDouble()
}

override fun decodeString(): String {
return input.readString()
}

override fun decodeEnum(enumDescriptor: SerialDescriptor): Int {
return input.readVarInt()
}

override fun decodeNotNullMark(): Boolean {
return input.readBoolean()
}

override fun decodeCollectionSize(descriptor: SerialDescriptor): Int {
return input.readVarInt()
}

public companion object {
/**
* Decodes a [PacketByteBuf] to an instance of [T]
*/
public inline fun <reified T> decode(
packetByteBuf: PacketByteBuf,
serializersModule: SerializersModule = EmptySerializersModule()
): T {
return PacketByteBufDecoder(packetByteBuf, serializersModule).decodeSerializableValue(serializer())
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
/*
* Copyright 2023 QuiltMC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.quiltmc.qkl.library.networking.serialization

import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.Serializable
import kotlinx.serialization.SerializationStrategy
import kotlinx.serialization.descriptors.SerialDescriptor
import kotlinx.serialization.encoding.AbstractDecoder
import kotlinx.serialization.encoding.AbstractEncoder
import kotlinx.serialization.encoding.CompositeEncoder
import kotlinx.serialization.modules.EmptySerializersModule
import kotlinx.serialization.modules.SerializersModule
import kotlinx.serialization.serializer
import net.minecraft.network.PacketByteBuf
import org.quiltmc.qsl.networking.api.PacketByteBufs

/**
* An [AbstractDecoder] that is capable of writing a class to a packet byte buf
*/
@OptIn(ExperimentalSerializationApi::class)
public class PacketByteBufEncoder(
override val serializersModule: SerializersModule = EmptySerializersModule()
) : AbstractEncoder() {
private val byteArraySerializer = serializer<ByteArray>()

public var packetByteBuf: PacketByteBuf = PacketByteBufs.create()

override fun <T> encodeSerializableValue(serializer: SerializationStrategy<T>, value: T) {
if (serializer.descriptor == byteArraySerializer.descriptor) {
packetByteBuf.writeByteArray(value as ByteArray)
} else {
super.encodeSerializableValue(serializer, value)
}
}

override fun encodeBoolean(value: Boolean) {
packetByteBuf.writeBoolean(value)
}

override fun encodeByte(value: Byte) {
packetByteBuf.writeByte(value.toInt())
}

override fun encodeChar(value: Char) {
packetByteBuf.writeChar(value.code)
}

override fun encodeShort(value: Short) {
packetByteBuf.writeShort(value.toInt())
}

override fun encodeInt(value: Int) {
packetByteBuf.writeInt(value)
}

override fun encodeLong(value: Long) {
packetByteBuf.writeLong(value)
}

override fun encodeFloat(value: Float) {
packetByteBuf.writeFloat(value)
}

override fun encodeDouble(value: Double) {
packetByteBuf.writeDouble(value)
}

override fun encodeString(value: String) {
packetByteBuf.writeString(value)
}

@ExperimentalSerializationApi
override fun encodeNotNullMark() {
encodeBoolean(true)
}

@ExperimentalSerializationApi
override fun encodeNull() {
encodeBoolean(false)
}

override fun encodeEnum(enumDescriptor: SerialDescriptor, index: Int) {
packetByteBuf.writeVarInt(index)
}

override fun beginCollection(descriptor: SerialDescriptor, collectionSize: Int): CompositeEncoder {
packetByteBuf.writeVarInt(collectionSize)
return this
}

public companion object {
/**
* Encodes an instance of [T] and returns the [PacketByteBuf].
*/
public inline fun <reified T> encode(
value: @Serializable T,
serializersModule: SerializersModule = EmptySerializersModule()
): PacketByteBuf {
val encoder = PacketByteBufEncoder(serializersModule)
encoder.encodeSerializableValue(serializer(), value)
return encoder.packetByteBuf
}
}
}
Loading