Skip to content

Commit

Permalink
Update a few things
Browse files Browse the repository at this point in the history
  • Loading branch information
Newspicel committed Jun 17, 2023
1 parent 332ca2e commit 1a1dfa7
Show file tree
Hide file tree
Showing 369 changed files with 1,138 additions and 9,475 deletions.
63 changes: 4 additions & 59 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
KDocs: [PacketLib KDocs](https://packetlib.kdocs.layercraft.io/)

Type Safe generated Minecraft Protocol Packets in Kotlin.
For current versions: 1.19.2, 1.19.3 & 1.19.4.
For current versions: 1.19.3(also 1.19.4).
But some complex Packets are not implemented yet.

### Prewords
Expand Down Expand Up @@ -168,62 +168,7 @@ Settings.xml

## Serialization Implementations

### Included Implementations
- [ByteBuffer (Java)](https://docs.oracle.com/javase/8/docs/api/java/nio/ByteBuffer.html) -> MinecraftByteBufferSerialize / MinecraftByteBufferDeserialize
- [InputStream (Java)](https://docs.oracle.com/javase/8/docs/api/java/io/InputStream.html) -> MinecraftInputStreamSerialize / MinecraftInputStreamDeserialize
There are no more default implementations for serialization in this library, so you have to write your own.
But here are some old example implementations: https://gist.github.com/Newspicel/54184b844dee00a4f351e58de033e071

### Write your own
To write your own implementation, you need to implement the following interfaces:
- MinecraftProtocolSerializeInterface
- MinecraftProtocolDeserializeInterface

So you can use your implementation with the MinecraftCodec. e.g.: Netty, Okio, ...

### Example Implementation

```kotlin
object TranslatorAPI {

fun <T : Packet> decodeFromByteArray(bytes: ByteArray, serializer: PacketSerializer<T>): T {
val byteBuffer = ByteBuffer.wrap(bytes)
val deserialize = MinecraftByteBufferDeserialize(byteBuffer)

return serializer.deserialize(deserialize)
}

fun <T : Packet> encodeToByteArray(value: T, serializer: PacketSerializer<T>): ByteArray {
val byteBuffer = ByteBuffer.allocate(MAX_PACKET_SIZE)
val serialize = MinecraftByteBufferSerialize(byteBuffer)

serializer.serialize(serialize, value)

val size = byteBuffer.position()
val byteArray = ByteArray(size)
byteBuffer.get(0, byteArray, 0, size)

return byteArray
}

fun decodeFromInputWithCodec(codec: MinecraftCodec, input: MinecraftProtocolDeserializeInterface<*>, packetDirection: PacketDirection, packetState: PacketState, packetId: Int): Packet? {
return codec.getCodecPacket(packetDirection, packetState, packetId)?.packetSerializer?.deserialize(input)
}

fun encodeToOutputWithCodec(codec: MinecraftCodec, output: MinecraftProtocolSerializeInterface<*>, value: Packet) {
codec.getCodecPacketFromPacket(value)?.packetSerializer?.serialize(output, value)
}
}
```

Serialize a packet to a byte array:

```kotlin
val packet = SetProtocolPacket(ProtocolVersion.V1_19_2.protocolNumber, "localhost", 25565, 1)

val bytes = TranslatorAPI.encodeToByteArray(packet, SetProtocolPacket)
```

Deserialize a packet from a byte array:

```kotlin
val packet = TranslatorAPI.decodeFromByteArray(bytes, SetProtocolPacket)
```
So you need to implement the `MCProtocolSerializer` interface and the `MCProtocolDeserializer` interface. Then just get your Packet over the `MinecraftCodecs` and serialize it.
3 changes: 3 additions & 0 deletions generator/src/main/kotlin/GenerateCode.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
fun main() {
println("Hello, World!")
}
56 changes: 30 additions & 26 deletions scripts/packet_generate.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@
}

src = "src/main/kotlin"
version = input("Version: ")
# First Argument: Version
version = "custom" if len(os.sys.argv) < 2 else os.sys.argv[1]
data_url = versions[version][0]
wikivg_url_end = "&oldid=" + versions[version][1]

Expand All @@ -47,10 +48,9 @@ def codec_generate():
package_string = packet["package"]
status = packet["status"]
id = packet["id"]
direction_string = "clientBound" if packet["direction"] == "clientbound" else "serverBound"

direction_string = "registerClientBoundPacket" if packet[
"direction"] == "clientbound" else "registerServerBoundPacket"
add_text = f""" .{direction_string}({id}, {package_string}.{class_name}::class, {package_string}.{class_name}) \n"""
add_text = f""" {direction_string}({id}, {package_string}.{class_name}::class, {package_string}.{class_name}) \n"""

if status == "handshaking":
handshaking_text += add_text
Expand All @@ -61,25 +61,30 @@ def codec_generate():
elif status == "play":
play_text += add_text

handshaking_text = handshaking_text[:-1]
login_text = login_text[:-1]
status_text = status_text[:-1]
play_text = play_text[:-1]

text = f"""
val V{version_underline}: MinecraftCodec =
MinecraftCodec.create(ProtocolVersion.V{version_underline})
.registerPacketRegistry(
PacketState.HANDSHAKING,
MinecraftCodecRegistry.create()
{handshaking_text})
.registerPacketRegistry(
PacketState.LOGIN,
MinecraftCodecRegistry.create()
{login_text})
.registerPacketRegistry(
PacketState.STATUS,
MinecraftCodecRegistry.create()
{status_text})
.registerPacketRegistry(
PacketState.PLAY,
MinecraftCodecRegistry.create()
{play_text})
codec(ProtocolVersion.V{version_underline}) {{
packets(PacketState.HANDSHAKING) {{
{handshaking_text}
}}
packets(PacketState.LOGIN) {{
{login_text}
}}
packets(PacketState.STATUS) {{
{status_text}
}}
packets(PacketState.PLAY) {{
{play_text}
}}
}}
"""

# write to codec.kt.tmp file
Expand Down Expand Up @@ -276,8 +281,8 @@ def generate(self) -> str:
class_str = f"""package {self.package}
import io.layercraft.packetlib.packets.*
import io.layercraft.packetlib.serialization.MinecraftProtocolDeserializeInterface
import io.layercraft.packetlib.serialization.MinecraftProtocolSerializeInterface
import io.layercraft.packetlib.serialization.MCProtocolDeserializer
import io.layercraft.packetlib.serialization.MCProtocolSerializer
{class_other_imports_str}
/**
* {wikivg_name} | {id} | {status} | {direction}
Expand All @@ -286,18 +291,17 @@ def generate(self) -> str:
* @see <a href="https://wiki.vg/index.php?title=Protocol{wikivg_url_end}#{wikivg_id}">https://wiki.vg/Protocol#{wikivg_id}</a>
*/
@MinecraftPacket(id = {id}, state = PacketState.{status.upper()}, direction = PacketDirection.{direction.upper()})
{"data" if len(class_fields_str) > 1 else ""} class {class_name}(
{class_fields_str}
) : {direction_interface} {{
companion object : PacketSerializer<{class_name}> {{
override fun deserialize(input: MinecraftProtocolDeserializeInterface<*>): {class_name} {{
override fun deserialize(input: MCProtocolDeserializer<*>): {class_name} {{
{class_deserialize_str}
return {class_name}({class_var_list_str})
}}
override fun serialize(output: MinecraftProtocolSerializeInterface<*>, value: {class_name}) {{
override fun serialize(output: MCProtocolSerializer<*>, value: {class_name}) {{
{class_serialize_str}
}}
}}
Expand Down
2 changes: 1 addition & 1 deletion scripts/packet_generate_text.py
Original file line number Diff line number Diff line change
Expand Up @@ -418,7 +418,7 @@ def generate_extra_class_deserializer(self, field_name: str, info_deserialize_va
class_deserialize_str = f"""val {field_name} = {info_deserialize_var_name}.readVarIntArray {{ arrayInput{round_str} ->
{extra_class_deserialize_str}
return@readVarIntArray {class_name}({extra_class_fields_str})
{class_name}({extra_class_fields_str})
}}"""

return class_deserialize_str
Expand Down
69 changes: 69 additions & 0 deletions src/main/kotlin/io/layercraft/packetlib/codec/Codec.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package io.layercraft.packetlib.codec

import io.layercraft.packetlib.packets.ClientBoundPacket
import io.layercraft.packetlib.packets.Packet
import io.layercraft.packetlib.packets.PacketSerializer
import io.layercraft.packetlib.packets.ServerBoundPacket
import java.util.*
import kotlin.reflect.KClass

class Codec internal constructor(
val protocolVersion: ProtocolVersion,
internal val packets: EnumMap<PacketState, CodecRegistry> = EnumMap(PacketState::class.java),
) {

private val list: List<CodecPacket<out Packet>> by lazy {
packets.values.flatMap { it.clientPacketMap.values }.toList() + packets.values.flatMap { it.serverPacketMap.values }.toList()
}

fun getCodecPacket(packetDirection: PacketDirection, packetState: PacketState, packetId: Int): CodecPacket<*>? {
return when (packetDirection) {
PacketDirection.CLIENTBOUND -> packets[packetState]?.serverPacketMap?.get(packetId)
PacketDirection.SERVERBOUND -> packets[packetState]?.clientPacketMap?.get(packetId)
}
}

@Suppress("UNCHECKED_CAST")
fun <T : Packet> getCodecPacketFromPacket(packet: T): CodecPacket<T>? {
return list.find { it.packet == packet::class } as CodecPacket<T>?
}

fun packets(state: PacketState, registry: CodecRegistry.() -> Unit) {
packets[state] = CodecRegistry().apply(registry)
}
}

class CodecRegistry internal constructor(
val clientPacketMap: HashMap<Int, CodecPacket<out ServerBoundPacket>> = HashMap(),
val serverPacketMap: HashMap<Int, CodecPacket<out ClientBoundPacket>> = HashMap(),
) {
fun <T : ClientBoundPacket> clientBound(packetId: Int, packet: KClass<T>, packetSerializer: PacketSerializer<T>) {
serverPacketMap[packetId] = CodecPacket(packetId, packet, packetSerializer)
}

fun <T : ServerBoundPacket> serverBound(packetId: Int, packet: KClass<T>, packetSerializer: PacketSerializer<T>) {
clientPacketMap[packetId] = CodecPacket(packetId, packet, packetSerializer)
}
}

fun codec(protocolVersion: ProtocolVersion, init: Codec.() -> Unit): Codec {
return Codec(protocolVersion).apply(init)
}

fun codecCopy(protocolVersion: ProtocolVersion, codec: Codec): Codec {
return Codec(protocolVersion, codec.packets.clone())
}

data class CodecPacket<T : Packet> internal constructor(
val packetId: Int,
val packet: KClass<T>,
val packetSerializer: PacketSerializer<T>,
)

enum class PacketDirection {
SERVERBOUND, CLIENTBOUND,
}

enum class PacketState {
HANDSHAKING, STATUS, LOGIN, PLAY,
}
87 changes: 0 additions & 87 deletions src/main/kotlin/io/layercraft/packetlib/codec/MinecraftCodec.kt

This file was deleted.

Loading

0 comments on commit 1a1dfa7

Please sign in to comment.