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

@@ -8,7 +8,7 @@
package cn.rtast.libmc.mcping.bedrock
import cn.rtast.libmc.common.PacketCodec
import cn.rtast.libmc.common._Buffer
import cn.rtast.libmc.common.BytesBuffer
import kotlin.random.Random
private val RAKNET_MAGIC = byteArrayOf(
@@ -33,14 +33,14 @@ internal data class BedrockRequestPacket(
override val packetId: Byte = 0x01
companion object Codec : PacketCodec<BedrockRequestPacket> {
override fun encode(buffer: _Buffer, value: BedrockRequestPacket) {
override fun encode(buffer: BytesBuffer, value: BedrockRequestPacket) {
buffer.writeByte(value.packetId)
buffer.writeLong(value.time)
buffer.writeBytes(value.magic)
buffer.writeLong(value.guid)
}
override fun decode(buffer: _Buffer): BedrockRequestPacket = throw UnsupportedOperationException()
override fun decode(buffer: BytesBuffer): BedrockRequestPacket = throw UnsupportedOperationException()
}
override fun equals(other: Any?): Boolean {
@@ -72,8 +72,8 @@ internal data class BedrockResponsePacket(
) : MinecraftBedrockPacket {
companion object Codec : PacketCodec<BedrockResponsePacket> {
override fun encode(buffer: _Buffer, value: BedrockResponsePacket) = throw UnsupportedOperationException()
override fun decode(buffer: _Buffer): BedrockResponsePacket {
override fun encode(buffer: BytesBuffer, value: BedrockResponsePacket) = throw UnsupportedOperationException()
override fun decode(buffer: BytesBuffer): BedrockResponsePacket {
val packetId = buffer.readByte()
if (packetId != 0x1C.toByte()) throw IllegalStateException("Expected pong id 0x1C, got $packetId")
val time = buffer.readLong()
@@ -8,12 +8,12 @@
package cn.rtast.libmc.mcping.bedrock
import cn.rtast.libmc.common.PacketCodec
import cn.rtast.libmc.common._Buffer
import cn.rtast.libmc.common.BytesBuffer
import cn.rtast.libmc.common._UdpSocket
internal fun <T : MinecraftBedrockPacket> _UdpSocket.sendPacket(packet: T, codec: PacketCodec<T>): ByteArray {
val buf = _Buffer()
val buf = BytesBuffer()
codec.encode(buf, packet)
return sendAndReceive(buf.toByteArray())
}
@@ -7,47 +7,45 @@
package cn.rtast.libmc.mcping.java
import cn.rtast.libmc.common.*
import cn.rtast.libmc.common.BytesBuffer
import cn.rtast.libmc.common.McStringCodec
import cn.rtast.libmc.common.PacketCodec
import cn.rtast.libmc.common.VarIntCodec
import cn.rtast.libmc.common.packet.MinecraftPacket
// ref https://minecraft.wiki/w/Java_Edition_protocol/Packets#Handshake
public data class HandshakePacket(
internal data class HandshakePacket(
val protocolVersion: Int,
val serverAddress: String,
val serverPort: UShort,
// 1 -> Status, 2 -> Login
val nextState: Int,
) : MinecraftPacket {
override val packetId: Int = 0x00
public companion object Codec : PacketCodec<HandshakePacket> {
override fun encode(buffer: _Buffer, value: HandshakePacket) {
companion object Codec : PacketCodec<HandshakePacket> {
override fun encode(buffer: BytesBuffer, value: HandshakePacket) {
VarIntCodec.encode(buffer, value.protocolVersion)
McStringCodec.encode(buffer, value.serverAddress)
buffer.writeShort(value.serverPort.toShort())
VarIntCodec.encode(buffer, value.nextState)
}
override fun decode(buffer: _Buffer): HandshakePacket = throw UnsupportedOperationException()
override fun decode(buffer: BytesBuffer): HandshakePacket = throw UnsupportedOperationException()
}
}
// ref https://minecraft.wiki/w/Java_Edition_protocol/Packets#Status
public data object StatusRequestPacket : MinecraftPacket, PacketCodec<StatusRequestPacket> {
override val packetId: Int = 0x00
override fun encode(buffer: _Buffer, value: StatusRequestPacket) {}
override fun decode(buffer: _Buffer): StatusRequestPacket = throw UnsupportedOperationException()
internal data object StatusRequestPacket : MinecraftPacket, PacketCodec<StatusRequestPacket> {
override fun encode(buffer: BytesBuffer, value: StatusRequestPacket) {}
override fun decode(buffer: BytesBuffer): StatusRequestPacket = throw UnsupportedOperationException()
}
public data class PingPacket(val currentTime: Long) : MinecraftPacket {
override val packetId: Int = 0x01
public companion object : PacketCodec<PingPacket> {
override fun encode(buffer: _Buffer, value: PingPacket) {
internal data class PingPacket(val currentTime: Long) : MinecraftPacket {
companion object : PacketCodec<PingPacket> {
override fun encode(buffer: BytesBuffer, value: PingPacket) {
buffer.writeLong(value.currentTime)
}
override fun decode(buffer: _Buffer): PingPacket {
override fun decode(buffer: BytesBuffer): PingPacket {
return PingPacket(buffer.readLong())
}
}
@@ -9,10 +9,11 @@ package cn.rtast.libmc.mcping.java
import cn.rtast.libmc.common.*
import cn.rtast.libmc.mcping.PingResponse
import cn.rtast.libmc.mcping.sendPacket
import kotlin.time.Clock
internal fun pingJavaServer(host: String, port: Int, context: LibMCContext): PingResponse {
val socket = _Socket(host, port, context)
val socket = Socket(host, port, context)
val receiveChannel = socket.openReadChannel()
val sendChannel = socket.openWriteChannel()
@@ -23,8 +24,8 @@ internal fun pingJavaServer(host: String, port: Int, context: LibMCContext): Pin
serverPort = port.toUShort(),
nextState = 1
)
sendChannel.sendPacket(handshakePacket, HandshakePacket)
sendChannel.sendPacket(StatusRequestPacket, StatusRequestPacket)
sendChannel.sendPacket(handshakePacket, 0x00, HandshakePacket)
sendChannel.sendPacket(StatusRequestPacket, 0x00, StatusRequestPacket)
val statusFrameBuffer = receiveChannel.readPacketFrame()
val statusPacketId = VarIntCodec.decode(statusFrameBuffer)
@@ -35,7 +36,7 @@ internal fun pingJavaServer(host: String, port: Int, context: LibMCContext): Pin
val sendTime = Clock.System.now().toEpochMilliseconds()
val pingPacket = PingPacket(sendTime)
sendChannel.sendPacket(pingPacket, PingPacket)
sendChannel.sendPacket(pingPacket, 0x01, PingPacket)
val pongFrameBuffer = receiveChannel.readPacketFrame()
val pongPacketId = VarIntCodec.decode(pongFrameBuffer)
@@ -0,0 +1,23 @@
/*
* Copyright © 2026 RTAkland
* Author: RTAkland
* Date: 2026/9/5
*/
package cn.rtast.libmc.mcping
import cn.rtast.libmc.common.*
import cn.rtast.libmc.common.packet.MinecraftPacket
public fun <T : MinecraftPacket> WriteChannel.sendPacket(packet: T, packetId: Int, codec: PacketCodec<T>) {
val bodyBuffer = BytesBuffer()
bodyBuffer.write(packetId, VarIntCodec)
codec.encode(bodyBuffer, packet)
val frameBuffer = BytesBuffer()
frameBuffer.write(bodyBuffer.size, VarIntCodec)
frameBuffer.writeBuffer(bodyBuffer)
val bytes = frameBuffer.toByteArray()
this.writeFully(bytes, 0, bytes.size)
this.flush()
}