Make packets public and formatted, fix state machine change state incorrectly
This commit is contained in:
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()
|
||||
|
||||
Reference in New Issue
Block a user