Fix network nbt reader

This commit is contained in:
2026-09-05 17:26:15 +08:00
parent 5e6e0ca5b9
commit a2eebe3d4e
8 files changed
+27 -13

No files matched your search

@@ -27,6 +27,7 @@ public expect class BytesBuffer {
public fun readLong(endian: ByteOrder = ByteOrder.BIG_ENDIAN): Long public fun readLong(endian: ByteOrder = ByteOrder.BIG_ENDIAN): Long
public fun readBytes(length: Int): ByteArray public fun readBytes(length: Int): ByteArray
public fun readBoolean(): Boolean public fun readBoolean(): Boolean
public fun readRemainingBytes(): ByteArray
public fun toByteArray(): ByteArray public fun toByteArray(): ByteArray
public fun hasRemaining(): Boolean public fun hasRemaining(): Boolean
@@ -29,13 +29,8 @@ public class PacketRegistry {
register(id, T::class, codec) register(id, T::class, codec)
} }
public fun decodePacket(packetId: Int, buffer: BytesBuffer): MinecraftPacket { public fun decodePacket(packetId: Int, buffer: BytesBuffer): MinecraftPacket =
val codec = idToCodec[packetId] idToCodec[packetId]?.decode(buffer) ?: UnknownPacket(packetId, buffer.readBytes(buffer.remaining.toInt()))
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) { public fun <T : MinecraftPacket> encodePacket(buffer: BytesBuffer, packet: T) {
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
@@ -93,6 +93,12 @@ public actual class BytesBuffer {
public actual fun readBoolean(): Boolean = this.readByte() != 0x00.toByte() public actual fun readBoolean(): Boolean = this.readByte() != 0x00.toByte()
public actual fun readRemainingBytes(): ByteArray {
val array = ensureReadArray()
if (readOffset >= array.size) return byteArrayOf()
return array.copyOfRange(readOffset, array.size)
}
public actual fun toByteArray(): ByteArray = outStream.toByteArray() public actual fun toByteArray(): ByteArray = outStream.toByteArray()
public actual fun hasRemaining(): Boolean = readOffset < ensureReadArray().size public actual fun hasRemaining(): Boolean = readOffset < ensureReadArray().size
@@ -60,6 +60,7 @@ public actual class BytesBuffer {
public actual fun readBytes(length: Int): ByteArray = _delegateBuf.readByteArray(length) public actual fun readBytes(length: Int): ByteArray = _delegateBuf.readByteArray(length)
public actual fun readBoolean(): Boolean = _delegateBuf.readByte() != 0x00.toByte() public actual fun readBoolean(): Boolean = _delegateBuf.readByte() != 0x00.toByte()
public actual fun readRemainingBytes(): ByteArray = this.toByteArray()
public actual fun toByteArray(): ByteArray { public actual fun toByteArray(): ByteArray {
val copy = _delegateBuf.peek() val copy = _delegateBuf.peek()
@@ -77,6 +77,12 @@ public fun NBTInput.readRootCompound(): NBTCompound {
} }
public fun NBTInput.readNetworkCompound(): NBTCompound { public fun NBTInput.readNetworkCompound(): NBTCompound {
val root = readCompound() return when (val type = NBTType.fromId(readByte().toInt() and 0xFF)) {
return NBTCompound("", root) NBTType.Compound -> NBTCompound("", readCompoundTag())
NBTType.String -> NBTCompound(
"", NBTTag.CompoundTag(linkedMapOf("text" to NBTTag.StringTag(readStringTag())))
)
else -> throw UnsupportedOperationException("Unsupported network nbt tag 0x${type.id.toString(16).uppercase()}")
}
} }
@@ -55,6 +55,7 @@ public class MinecraftClient internal constructor(
} catch (e: Exception) { } catch (e: Exception) {
if (e is CancellationException) throw e if (e is CancellationException) throw e
if (isActive) { if (isActive) {
e.printStackTrace()
println("Network read loop exception: ${e.message}") println("Network read loop exception: ${e.message}")
close() close()
} }
@@ -9,14 +9,14 @@ package cn.rtast.libmc.protocol.packet.login
import cn.rtast.libmc.common.BytesBuffer import cn.rtast.libmc.common.BytesBuffer
import cn.rtast.libmc.common.PacketCodec import cn.rtast.libmc.common.PacketCodec
import cn.rtast.libmc.common.readMcString import cn.rtast.libmc.nbt.NBTCompound
import cn.rtast.libmc.protocol.protocol.util.readNetworkNBTCompound
public data class ClientboundDisconnectLoginPacket(val reason: String) : ClientboundLoginPacket { public data class ClientboundDisconnectLoginPacket(val reason: NBTCompound) : ClientboundLoginPacket {
public companion object Codec : PacketCodec<ClientboundDisconnectLoginPacket> { public companion object Codec : PacketCodec<ClientboundDisconnectLoginPacket> {
override fun encode(buffer: BytesBuffer, value: ClientboundDisconnectLoginPacket) {} override fun encode(buffer: BytesBuffer, value: ClientboundDisconnectLoginPacket) {}
override fun decode(buffer: BytesBuffer): ClientboundDisconnectLoginPacket { override fun decode(buffer: BytesBuffer): ClientboundDisconnectLoginPacket {
val reasonJson = buffer.readMcString() return ClientboundDisconnectLoginPacket(reason = buffer.readNetworkNBTCompound())
return ClientboundDisconnectLoginPacket(reason = reasonJson)
} }
} }
} }
@@ -8,6 +8,7 @@
package test package test
import cn.rtast.libmc.protocol.client.createMinecraftClient import cn.rtast.libmc.protocol.client.createMinecraftClient
import cn.rtast.libmc.protocol.packet.play.ClientboundDisconnectPlayPacket
import cn.rtast.libmc.protocol.packet.play.ClientboundLoginPlayPacket import cn.rtast.libmc.protocol.packet.play.ClientboundLoginPlayPacket
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.test.runTest import kotlinx.coroutines.test.runTest
@@ -23,6 +24,9 @@ class TestClient {
cli.on<ClientboundLoginPlayPacket> { cli.on<ClientboundLoginPlayPacket> {
println(it) println(it)
} }
cli.on<ClientboundDisconnectPlayPacket> {
println(it)
}
while (true) { while (true) {
} }
} }