Make packets public and formatted, fix state machine change state incorrectly

This commit is contained in:
2026-09-05 13:22:00 +08:00
parent 15aefbb869
commit 799edce45f
96 files changed
+1718 -873

No files matched your search

@@ -10,7 +10,7 @@ package cn.rtast.libmc.common
import kotlin.uuid.Uuid
@Suppress("CLASSNAME")
public expect class _Buffer {
public expect class BytesBuffer {
public constructor()
public constructor(bytes: ByteArray)
@@ -35,29 +35,27 @@ public expect class _Buffer {
public val remaining: Long
}
public fun ByteArray.wrap(): _Buffer = _Buffer(this)
@Suppress("NOTHING_TO_INLINE")
public inline fun ByteArray.wrap(): BytesBuffer = BytesBuffer(this)
public fun _Buffer.writeUuid(uuid: Uuid): Unit = uuid.toLongs { mostSignificantBits, leastSignificantBits ->
public fun BytesBuffer.writeUuid(uuid: Uuid): Unit = uuid.toLongs { mostSignificantBits, leastSignificantBits ->
this.writeLong(mostSignificantBits)
this.writeLong(leastSignificantBits)
}
public fun _Buffer.readUuid(): Uuid {
public fun BytesBuffer.readUuid(): Uuid {
val most = this.readLong()
val least = this.readLong()
return Uuid.fromLongs(most, least)
}
public fun _Buffer.writeVarInt(value: Int): Unit = VarIntCodec.encode(this, value)
public fun _Buffer.readVarInt(): Int = VarIntCodec.decode(this)
public fun BytesBuffer.writeVarInt(value: Int): Unit = VarIntCodec.encode(this, value)
public fun BytesBuffer.readVarInt(): Int = VarIntCodec.decode(this)
public fun _Buffer.writeMcString(value: String): Unit = McStringCodec.encode(this, value)
public fun _Buffer.readMcString(): String = McStringCodec.decode(this)
public fun BytesBuffer.writeMcString(value: String): Unit = McStringCodec.encode(this, value)
public fun BytesBuffer.readMcString(): String = McStringCodec.decode(this)
public fun _ReadChannel.readPacketFrame(): _Buffer {
public fun ReadChannel.readPacketFrame(): BytesBuffer {
val length = this.readVarInt()
val frameBytes = this.readBytes(length)
return _Buffer().apply {
writeBytes(frameBytes)
}
return this.readBytes(length).wrap()
}
@@ -8,7 +8,7 @@
package cn.rtast.libmc.common
@Suppress("CLASSNAME")
public expect class _ReadChannel {
public expect class ReadChannel {
public fun readByte(): Byte
public fun readShort(endian: ByteOrder = ByteOrder.BIG_ENDIAN): Short
public fun readInt(endian: ByteOrder = ByteOrder.BIG_ENDIAN): Int
@@ -18,12 +18,12 @@ public expect class _ReadChannel {
}
@Suppress("CLASSNAME")
public expect class _WriteChannel {
public expect class WriteChannel {
public fun writeFully(value: ByteArray, startIndex: Int = 0, endIndex: Int = value.size)
public fun flush()
}
public fun _ReadChannel.readVarInt(): Int {
public fun ReadChannel.readVarInt(): Int {
var numRead = 0
var result = 0
var read: Byte
@@ -8,17 +8,17 @@
package cn.rtast.libmc.common
public interface Encoder<in T> {
public fun encode(buffer: _Buffer, value: T)
public fun encode(buffer: BytesBuffer, value: T)
public fun encodeToByteArray(value: T): ByteArray {
val buf = _Buffer()
val buf = BytesBuffer()
encode(buf, value)
return buf.toByteArray()
}
}
public interface Decoder<out T> {
public fun decode(buffer: _Buffer): T
public fun decode(buffer: BytesBuffer): T
public fun decodeFromByteArray(bytes: ByteArray): T = decode(bytes.wrap())
}
@@ -26,12 +26,12 @@ public interface Decoder<out T> {
public interface PacketCodec<T> : Encoder<T>, Decoder<T>
@Suppress("NOTHING_TO_INLINE")
public inline fun <T> _Buffer.write(value: T, encoder: Encoder<T>): Unit = encoder.encode(this, value)
public inline fun <T> BytesBuffer.write(value: T, encoder: Encoder<T>): Unit = encoder.encode(this, value)
@Suppress("NOTHING_TO_INLINE")
public inline fun <T> _Buffer.read(decoder: Decoder<T>): T = decoder.decode(this)
public inline fun <T> BytesBuffer.read(decoder: Decoder<T>): T = decoder.decode(this)
public fun _Buffer.writeBuffer(source: _Buffer, length: Long = source.remaining) {
public fun BytesBuffer.writeBuffer(source: BytesBuffer, length: Long = source.remaining) {
if (length <= 0) return
val bytes = source.readBytes(length.toInt())
this.writeBytes(bytes)
@@ -7,7 +7,7 @@
package cn.rtast.libmc.common
public object VarIntCodec : PacketCodec<Int> {
override fun encode(buffer: _Buffer, value: Int) {
override fun encode(buffer: BytesBuffer, value: Int) {
var v = value
while (true) {
if ((v and 0x7F.inv()) == 0) {
@@ -19,7 +19,7 @@ public object VarIntCodec : PacketCodec<Int> {
}
}
override fun decode(buffer: _Buffer): Int {
override fun decode(buffer: BytesBuffer): Int {
var numRead = 0
var result = 0
var read: Byte
@@ -35,13 +35,13 @@ public object VarIntCodec : PacketCodec<Int> {
}
public object McStringCodec : PacketCodec<String> {
override fun encode(buffer: _Buffer, value: String) {
override fun encode(buffer: BytesBuffer, value: String) {
val bytes = value.encodeToByteArray()
VarIntCodec.encode(buffer, bytes.size)
buffer.writeBytes(bytes)
}
override fun decode(buffer: _Buffer): String {
override fun decode(buffer: BytesBuffer): String {
val length = VarIntCodec.decode(buffer)
val bytes = buffer.readBytes(length)
return bytes.decodeToString()
@@ -1,12 +0,0 @@
/*
* Copyright © 2026 RTAkland
* Author: RTAkland
* Date: 2026/9/4
*/
package cn.rtast.libmc.common
public interface MinecraftPacket {
public val packetId: Int
}
@@ -0,0 +1,10 @@
/*
* Copyright © 2026 RTAkland
* Author: RTAkland
* Date: 2026/9/4
*/
package cn.rtast.libmc.common.packet
public interface MinecraftPacket
@@ -0,0 +1,48 @@
/*
* Copyright © 2026 RTAkland
* Author: RTAkland
* Date: 2026/9/5
*/
package cn.rtast.libmc.common.packet
import cn.rtast.libmc.common.BytesBuffer
import cn.rtast.libmc.common.PacketCodec
import cn.rtast.libmc.common.writeVarInt
import kotlin.reflect.KClass
public class PacketRegistry {
private val idToCodec = mutableMapOf<Int, PacketCodec<out MinecraftPacket>>()
private val classToInfo = mutableMapOf<KClass<out MinecraftPacket>, RegisteredPacket<*>>()
private data class RegisteredPacket<P : MinecraftPacket>(
val id: Int, val codec: PacketCodec<P>,
)
public fun <T : MinecraftPacket> register(id: Int, kClass: KClass<T>, codec: PacketCodec<T>) {
idToCodec[id] = codec
classToInfo[kClass] = RegisteredPacket(id, codec)
}
public inline fun <reified T : MinecraftPacket> register(id: Int, codec: PacketCodec<T>) {
register(id, T::class, codec)
}
public fun decodePacket(packetId: Int, buffer: BytesBuffer): MinecraftPacket {
val codec = idToCodec[packetId]
if (codec != null) return codec.decode(buffer) else {
// println("Ignored unknown packet 0x${packetId.toString(16).uppercase()}")
return UnknownPacket(packetId, buffer.readBytes(buffer.remaining.toInt()))
}
}
public fun <T : MinecraftPacket> encodePacket(buffer: BytesBuffer, packet: T) {
@Suppress("UNCHECKED_CAST")
val info = requireNotNull(classToInfo[packet::class]) {
"Unregistered Packet ${packet::class.simpleName}"
} as RegisteredPacket<T>
buffer.writeVarInt(info.id)
info.codec.encode(buffer, packet)
}
}
@@ -0,0 +1,31 @@
/*
* Copyright © 2026 RTAkland
* Author: RTAkland
* Date: 2026/9/5
*/
package cn.rtast.libmc.common.packet
/**
* reserved packet
*/
public data class UnknownPacket(val packetId: Int, val data: ByteArray): MinecraftPacket {
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other == null || this::class != other::class) return false
other as UnknownPacket
if (packetId != other.packetId) return false
if (!data.contentEquals(other.data)) return false
return true
}
override fun hashCode(): Int {
var result = packetId
result = 31 * result + data.contentHashCode()
return result
}
}
@@ -1,20 +0,0 @@
/*
* Copyright © 2026 RTAkland
* Author: RTAkland
* Date: 2026/9/4
*/
package cn.rtast.libmc.common
public fun <T : MinecraftPacket> _WriteChannel.sendPacket(packet: T, codec: PacketCodec<T>) {
val bodyBuffer = _Buffer()
bodyBuffer.write(packet.packetId, VarIntCodec)
codec.encode(bodyBuffer, packet)
val frameBuffer = _Buffer()
frameBuffer.write(bodyBuffer.size, VarIntCodec)
frameBuffer.writeBuffer(bodyBuffer)
val bytes = frameBuffer.toByteArray()
this.writeFully(bytes, 0, bytes.size)
this.flush()
}
@@ -8,9 +8,9 @@
package cn.rtast.libmc.common
@Suppress("CLASSNAME")
public expect class _Socket public constructor(host: String, port: Int, context: LibMCContext) {
public fun openReadChannel(): _ReadChannel
public fun openWriteChannel(): _WriteChannel
public expect class Socket public constructor(host: String, port: Int, context: LibMCContext) {
public fun openReadChannel(): ReadChannel
public fun openWriteChannel(): WriteChannel
public fun close()
}
@@ -9,7 +9,7 @@ package cn.rtast.libmc.common
import java.io.ByteArrayOutputStream
@Suppress("CLASSNAME")
public actual class _Buffer {
public actual class BytesBuffer {
private val outStream = ByteArrayOutputStream()
private var readBuffer: ByteArray? = null
private var readOffset = 0
@@ -12,7 +12,7 @@ import java.io.InputStream
import java.io.OutputStream
@Suppress("CLASSNAME")
public actual class _ReadChannel(private val _inputStream: InputStream) {
public actual class ReadChannel(private val _inputStream: InputStream) {
public actual fun readByte(): Byte = _inputStream.read().toByte()
public actual fun readBytes(length: Int): ByteArray = _inputStream.readNBytes(length)
@@ -33,7 +33,7 @@ public actual class _ReadChannel(private val _inputStream: InputStream) {
}
@Suppress("CLASSNAME")
public actual class _WriteChannel {
public actual class WriteChannel {
private val _outputStream: OutputStream
public constructor(outputStream: OutputStream) {
@@ -12,11 +12,11 @@ import java.net.InetSocketAddress
import java.net.Socket as JvmSocket
@Suppress("CLASSNAME")
public actual class _Socket public actual constructor(host: String, port: Int, context: LibMCContext) {
public actual class Socket public actual constructor(host: String, port: Int, context: LibMCContext) {
private val socket = JvmSocket(host, port)
public actual fun openReadChannel(): _ReadChannel = _ReadChannel(socket.getInputStream())
public actual fun openWriteChannel(): _WriteChannel = _WriteChannel(socket.getOutputStream())
public actual fun openReadChannel(): ReadChannel = ReadChannel(socket.getInputStream())
public actual fun openWriteChannel(): WriteChannel = WriteChannel(socket.getOutputStream())
public actual fun close(): Unit = socket.close()
}
@@ -12,7 +12,7 @@ import kotlinx.io.Buffer
import kotlinx.io.readByteArray
@Suppress("CLASSNAME")
public actual class _Buffer {
public actual class BytesBuffer {
private val _delegateBuf: Buffer
public actual constructor() {
@@ -11,7 +11,7 @@ import io.ktor.utils.io.bits.reverseByteOrder
import kotlinx.coroutines.runBlocking
@Suppress("CLASSNAME")
public actual class _ReadChannel(private val _readChannel: ByteReadChannel) {
public actual class ReadChannel(private val _readChannel: ByteReadChannel) {
public actual fun readByte(): Byte = runBlocking { _readChannel.readByte() }
public actual fun readBytes(length: Int): ByteArray = runBlocking { _readChannel.readByteArray(length) }
@@ -35,7 +35,7 @@ public actual class _ReadChannel(private val _readChannel: ByteReadChannel) {
}
@Suppress("CLASSNAME")
public actual class _WriteChannel {
public actual class WriteChannel {
private val _writeChannel: ByteWriteChannel
public constructor(writeChannel: ByteWriteChannel) {
@@ -12,13 +12,13 @@ import kotlinx.coroutines.runBlocking
import kotlinx.io.readByteArray
@Suppress("CLASSNAME")
public actual class _Socket public actual constructor(host: String, port: Int, context: LibMCContext) {
public actual class Socket public actual constructor(host: String, port: Int, context: LibMCContext) {
private val ctx = context
private val socket = runBlocking { aSocket(ctx._selectorManager).tcp().connect(host, port) }
public actual fun openReadChannel(): _ReadChannel = _ReadChannel(socket.openReadChannel())
public actual fun openWriteChannel(): _WriteChannel =
_WriteChannel(socket.openWriteChannel(autoFlush = true))
public actual fun openReadChannel(): ReadChannel = ReadChannel(socket.openReadChannel())
public actual fun openWriteChannel(): WriteChannel =
WriteChannel(socket.openWriteChannel(autoFlush = true))
public actual fun close() {
socket.close()