Update all codec to suspend; added a default ProtocolCryptoContext implementation
This commit is contained in:
296 files changed
+2199
-1818
No files matched your search
@@ -48,3 +48,4 @@ bin/
|
|||||||
.kotlin/
|
.kotlin/
|
||||||
**/build/*
|
**/build/*
|
||||||
/libmc-protocol/src/jvmTest/resources/accessToken.txt
|
/libmc-protocol/src/jvmTest/resources/accessToken.txt
|
||||||
|
/libmc-protocol-encrypt/src/commonTest/resources/accessToken.txt
|
||||||
@@ -3,24 +3,27 @@ kotlin = "2.4.10"
|
|||||||
kotlinx-io = "0.9.1"
|
kotlinx-io = "0.9.1"
|
||||||
ktor-network = "3.5.2"
|
ktor-network = "3.5.2"
|
||||||
coroutines-test = "1.11.0"
|
coroutines-test = "1.11.0"
|
||||||
#kotlinx-serialization = "1.11.0"
|
|
||||||
kotlinx-coroutines = "1.11.0"
|
kotlinx-coroutines = "1.11.0"
|
||||||
ktor-core = "3.5.2"
|
ktor-core = "3.5.2"
|
||||||
|
cryptography-core = "0.6.0"
|
||||||
|
#kotlinx-serialization = "1.11.0"
|
||||||
|
|
||||||
[libraries]
|
[libraries]
|
||||||
kotlinx-io = { module = "org.jetbrains.kotlinx:kotlinx-io-core", version.ref = "kotlinx-io" }
|
kotlinx-io = { module = "org.jetbrains.kotlinx:kotlinx-io-core", version.ref = "kotlinx-io" }
|
||||||
ktor-network = { module = "io.ktor:ktor-network", version.ref = "ktor-network" }
|
ktor-network = { module = "io.ktor:ktor-network", version.ref = "ktor-network" }
|
||||||
kotlinx-coroutines-test = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-test", version.ref = "coroutines-test" }
|
kotlinx-coroutines-test = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-test", version.ref = "coroutines-test" }
|
||||||
|
kotlinx-coroutines = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "kotlinx-coroutines" }
|
||||||
|
cryptography-provider-optimal = { module = "dev.whyoleg.cryptography:cryptography-provider-optimal", version.ref = "cryptography-core" }
|
||||||
|
cryptography-core = { module = "dev.whyoleg.cryptography:cryptography-core", version.ref = "cryptography-core" }
|
||||||
|
ktor-client-core = { module = "io.ktor:ktor-client-core", version.ref = "ktor-core" }
|
||||||
|
ktor-client-darwin = { module = "io.ktor:ktor-client-darwin", version.ref = "ktor-core" }
|
||||||
|
ktor-client-winhttp = { module = "io.ktor:ktor-client-winhttp", version.ref = "ktor-core" }
|
||||||
|
ktor-client-curl = { module = "io.ktor:ktor-client-curl", version.ref = "ktor-core" }
|
||||||
|
ktor-client-okhttp = { module = "io.ktor:ktor-client-okhttp", version.ref = "ktor-core" }
|
||||||
#kotlinx-serialization-core = { module = "org.jetbrains.kotlinx:kotlinx-serialization-core", version.ref = "kotlinx-serialization" }
|
#kotlinx-serialization-core = { module = "org.jetbrains.kotlinx:kotlinx-serialization-core", version.ref = "kotlinx-serialization" }
|
||||||
#kotlinx-serialization-json = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version.ref = "kotlinx-serialization" }
|
#kotlinx-serialization-json = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version.ref = "kotlinx-serialization" }
|
||||||
kotlinx-coroutines = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "kotlinx-coroutines" }
|
|
||||||
ktor-client-core = { module = "io.ktor:ktor-client-core", version.ref = "ktor-core" }
|
|
||||||
#ktor-client-darwin = { module = "io.ktor:ktor-client-darwin", version.ref = "ktor-core" }
|
|
||||||
#ktor-client-winhttp = { module = "io.ktor:ktor-client-winhttp", version.ref = "ktor-core" }
|
|
||||||
#ktor-client-curl = { module = "io.ktor:ktor-client-curl", version.ref = "ktor-core" }
|
|
||||||
ktor-client-okhttp = { module = "io.ktor:ktor-client-okhttp", version.ref = "ktor-core" }
|
|
||||||
|
|
||||||
[plugins]
|
[plugins]
|
||||||
kotlin-multiplatform = { id = "org.jetbrains.kotlin.multiplatform", version.ref = "kotlin" }
|
kotlin-multiplatform = { id = "org.jetbrains.kotlin.multiplatform", version.ref = "kotlin" }
|
||||||
kotlinx-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" }
|
|
||||||
maven-publish = { id = "maven-publish" }
|
maven-publish = { id = "maven-publish" }
|
||||||
|
#kotlinx-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" }
|
||||||
@@ -11,10 +11,10 @@ kotlin {
|
|||||||
jvm { compilerOptions.jvmTarget = JvmTarget.JVM_1_8 }
|
jvm { compilerOptions.jvmTarget = JvmTarget.JVM_1_8 }
|
||||||
|
|
||||||
sourceSets {
|
sourceSets {
|
||||||
jvmMain.dependencies {
|
commonMain.dependencies {
|
||||||
// no dependencies needed
|
api(libs.kotlinx.coroutines)
|
||||||
}
|
}
|
||||||
|
jvmMain.dependencies {}
|
||||||
nativeMain.dependencies {
|
nativeMain.dependencies {
|
||||||
implementation(libs.ktor.network)
|
implementation(libs.ktor.network)
|
||||||
implementation(libs.kotlinx.io)
|
implementation(libs.kotlinx.io)
|
||||||
|
|||||||
@@ -1,47 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright © 2026 RTAkland
|
|
||||||
* Author: RTAkland
|
|
||||||
* Date: 2026/9/3
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
package cn.rtast.libmc.common
|
|
||||||
|
|
||||||
public expect class BytesBuffer {
|
|
||||||
public constructor()
|
|
||||||
public constructor(bytes: ByteArray)
|
|
||||||
|
|
||||||
public fun writeByte(value: Byte)
|
|
||||||
public fun writeShort(value: Short, endian: ByteOrder = ByteOrder.BIG_ENDIAN)
|
|
||||||
public fun writeInt(value: Int, endian: ByteOrder = ByteOrder.BIG_ENDIAN)
|
|
||||||
public fun writeLong(value: Long, endian: ByteOrder = ByteOrder.BIG_ENDIAN)
|
|
||||||
public fun writeDouble(value: Double, endian: ByteOrder = ByteOrder.BIG_ENDIAN)
|
|
||||||
public fun writeFloat(value: Float, endian: ByteOrder = ByteOrder.BIG_ENDIAN)
|
|
||||||
public fun writeBytes(bytes: ByteArray)
|
|
||||||
public fun writeBoolean(value: Boolean)
|
|
||||||
|
|
||||||
public fun readByte(): Byte
|
|
||||||
public fun readUByte(): UByte
|
|
||||||
public fun readShort(endian: ByteOrder = ByteOrder.BIG_ENDIAN): Short
|
|
||||||
public fun readInt(endian: ByteOrder = ByteOrder.BIG_ENDIAN): Int
|
|
||||||
public fun readLong(endian: ByteOrder = ByteOrder.BIG_ENDIAN): Long
|
|
||||||
public fun readDouble(endian: ByteOrder = ByteOrder.BIG_ENDIAN): Double
|
|
||||||
public fun readFloat(endian: ByteOrder = ByteOrder.BIG_ENDIAN): Float
|
|
||||||
public fun readBytes(length: Int): ByteArray
|
|
||||||
public fun readBoolean(): Boolean
|
|
||||||
public fun readRemainingBytes(): ByteArray
|
|
||||||
|
|
||||||
public fun toByteArray(): ByteArray
|
|
||||||
public fun hasRemaining(): Boolean
|
|
||||||
public fun close()
|
|
||||||
public val size: Int
|
|
||||||
public val remaining: Long
|
|
||||||
}
|
|
||||||
|
|
||||||
@Suppress("NOTHING_TO_INLINE")
|
|
||||||
public inline fun ByteArray.wrap(): BytesBuffer = BytesBuffer(this)
|
|
||||||
|
|
||||||
public fun ReadChannel.readPacketFrame(): BytesBuffer {
|
|
||||||
val length = this.readVarInt()
|
|
||||||
return this.readBytes(length).wrap()
|
|
||||||
}
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright © 2026 RTAkland
|
|
||||||
* Author: RTAkland
|
|
||||||
* Date: 2026/9/3
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
package cn.rtast.libmc.common
|
|
||||||
|
|
||||||
public expect open class ReadChannel() {
|
|
||||||
public open fun readByte(): Byte
|
|
||||||
public open fun readShort(endian: ByteOrder = ByteOrder.BIG_ENDIAN): Short
|
|
||||||
public open fun readInt(endian: ByteOrder = ByteOrder.BIG_ENDIAN): Int
|
|
||||||
public open fun readLong(endian: ByteOrder = ByteOrder.BIG_ENDIAN): Long
|
|
||||||
public open fun readBytes(length: Int): ByteArray
|
|
||||||
public open fun readFully(out: ByteArray, start: Int = 0, end: Int = out.size)
|
|
||||||
}
|
|
||||||
|
|
||||||
public expect open class WriteChannel() {
|
|
||||||
public open fun writeFully(value: ByteArray, startIndex: Int = 0, endIndex: Int = value.size)
|
|
||||||
public open fun flush()
|
|
||||||
}
|
|
||||||
|
|
||||||
public fun ReadChannel.readVarInt(): Int {
|
|
||||||
var numRead = 0
|
|
||||||
var result = 0
|
|
||||||
var read: Byte
|
|
||||||
do {
|
|
||||||
read = this.readByte()
|
|
||||||
val value = (read.toInt() and 0x7F)
|
|
||||||
result = result or (value shl (7 * numRead))
|
|
||||||
numRead++
|
|
||||||
if (numRead > 5) throw IllegalArgumentException("VarInt is too big")
|
|
||||||
} while ((read.toInt() and 0x80) != 0)
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright © 2026 RTAkland
|
|
||||||
* Author: RTAkland
|
|
||||||
* Date: 2026/9/4
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
package cn.rtast.libmc.common
|
|
||||||
|
|
||||||
public interface Encoder<in T> {
|
|
||||||
public fun encode(buffer: BytesBuffer, value: T)
|
|
||||||
}
|
|
||||||
|
|
||||||
public interface Decoder<out T> {
|
|
||||||
public fun decode(buffer: BytesBuffer): T
|
|
||||||
}
|
|
||||||
|
|
||||||
public interface PacketCodec<T> : Encoder<T>, Decoder<T>
|
|
||||||
|
|
||||||
@Suppress("NOTHING_TO_INLINE")
|
|
||||||
public inline fun <T> BytesBuffer.write(value: T, encoder: Encoder<T>): Unit = encoder.encode(this, value)
|
|
||||||
|
|
||||||
@Suppress("NOTHING_TO_INLINE")
|
|
||||||
public inline fun <T> BytesBuffer.read(decoder: Decoder<T>): T = decoder.decode(this)
|
|
||||||
|
|
||||||
public fun BytesBuffer.writeBuffer(source: BytesBuffer, length: Long = source.remaining) {
|
|
||||||
if (length <= 0) return
|
|
||||||
val bytes = source.readBytes(length.toInt())
|
|
||||||
this.writeBytes(bytes)
|
|
||||||
}
|
|
||||||
+1
-1
@@ -5,7 +5,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
package cn.rtast.libmc.protocol.session
|
package cn.rtast.libmc.common.crypto
|
||||||
|
|
||||||
public fun interface AuthenticationProvider {
|
public fun interface AuthenticationProvider {
|
||||||
public suspend fun joinServer(url: String, accessToken: String, uuid: String, serverIdHash: String)
|
public suspend fun joinServer(url: String, accessToken: String, uuid: String, serverIdHash: String)
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
/*
|
||||||
|
* Copyright © 2026 RTAkland
|
||||||
|
* Author: RTAkland
|
||||||
|
* Date: 2026/9/7
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
package cn.rtast.libmc.common.crypto
|
||||||
|
|
||||||
|
public interface NetworkCipher {
|
||||||
|
public suspend fun encrypt(buffer: ByteArray, offset: Int, length: Int)
|
||||||
|
public suspend fun decrypt(buffer: ByteArray, offset: Int, length: Int)
|
||||||
|
}
|
||||||
+7
-9
@@ -5,9 +5,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
package cn.rtast.libmc.protocol.crypto
|
package cn.rtast.libmc.common.crypto
|
||||||
|
|
||||||
import cn.rtast.libmc.protocol.session.AuthenticationProvider
|
|
||||||
|
|
||||||
public data class ProtocolContext(
|
public data class ProtocolContext(
|
||||||
val rsaEncryptor: RSA1024Encryptor,
|
val rsaEncryptor: RSA1024Encryptor,
|
||||||
@@ -16,25 +14,25 @@ public data class ProtocolContext(
|
|||||||
val authProvider: AuthenticationProvider,
|
val authProvider: AuthenticationProvider,
|
||||||
)
|
)
|
||||||
|
|
||||||
public class ProtocolContextBuilder internal constructor(private val onlineMode: Boolean) {
|
public class ProtocolContextBuilder(private val onlineMode: Boolean) {
|
||||||
public lateinit var rsaEncryptor: RSA1024Encryptor
|
public lateinit var rsaEncryptor: RSA1024Encryptor
|
||||||
public lateinit var sha1Hasher: Sha1Hasher
|
public lateinit var sha1Hasher: Sha1Hasher
|
||||||
public lateinit var cipherFactory: (sharedKey: ByteArray) -> NetworkCipher
|
public lateinit var cipherFactory: (sharedKey: ByteArray) -> NetworkCipher
|
||||||
public lateinit var authProvider: AuthenticationProvider
|
public lateinit var authProvider: AuthenticationProvider
|
||||||
|
|
||||||
internal fun build(): ProtocolContext = ProtocolContext(
|
public fun build(): ProtocolContext = ProtocolContext(
|
||||||
rsaEncryptor = if (::rsaEncryptor.isInitialized) rsaEncryptor else error("rsaEncryptor is required"),
|
rsaEncryptor = if (::rsaEncryptor.isInitialized) rsaEncryptor else error("rsaEncryptor is required"),
|
||||||
sha1Hasher = if (::sha1Hasher.isInitialized) sha1Hasher else error("sha1Hasher is required"),
|
sha1Hasher = if (::sha1Hasher.isInitialized) sha1Hasher else error("sha1Hasher is required"),
|
||||||
cipherFactory = if (::cipherFactory.isInitialized) cipherFactory else error("cipherFactory is required"),
|
cipherFactory = if (::cipherFactory.isInitialized) cipherFactory else error("cipherFactory is required"),
|
||||||
authProvider = if (::authProvider.isInitialized && !onlineMode) authProvider else error("authProvider is required")
|
authProvider = if (::authProvider.isInitialized) if (onlineMode) authProvider
|
||||||
|
else error("authProvider is required") else error("authProvider is required")
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun interface RSA1024Encryptor {
|
public fun interface RSA1024Encryptor {
|
||||||
public fun encrypt(key: ByteArray, data: ByteArray): ByteArray
|
public suspend fun encrypt(key: ByteArray, data: ByteArray): ByteArray
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public fun interface Sha1Hasher {
|
public fun interface Sha1Hasher {
|
||||||
public fun hash(serverId: String, secretKey: ByteArray, publicKey: ByteArray): String
|
public suspend fun hash(serverId: String, secretKey: ByteArray, publicKey: ByteArray): String
|
||||||
}
|
}
|
||||||
@@ -1,232 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright © 2026 RTAkland
|
|
||||||
* Author: RTAkland
|
|
||||||
* Date: 2026/9/3
|
|
||||||
*/
|
|
||||||
|
|
||||||
package cn.rtast.libmc.common
|
|
||||||
|
|
||||||
import kotlin.uuid.Uuid
|
|
||||||
|
|
||||||
public object VarIntCodec : PacketCodec<Int> {
|
|
||||||
override fun encode(buffer: BytesBuffer, value: Int) {
|
|
||||||
var v = value
|
|
||||||
while (true) {
|
|
||||||
if ((v and 0x7F.inv()) == 0) {
|
|
||||||
buffer.writeByte(v.toByte())
|
|
||||||
return
|
|
||||||
}
|
|
||||||
buffer.writeByte(((v and 0x7F) or 0x80).toByte())
|
|
||||||
v = v ushr 7
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun decode(buffer: BytesBuffer): Int {
|
|
||||||
var numRead = 0
|
|
||||||
var result = 0
|
|
||||||
var read: Byte
|
|
||||||
do {
|
|
||||||
read = buffer.readByte()
|
|
||||||
val value = (read.toInt() and 0x7F)
|
|
||||||
result = result or (value shl (7 * numRead))
|
|
||||||
numRead++
|
|
||||||
if (numRead > 5) throw IllegalArgumentException("VarInt is too big")
|
|
||||||
} while ((read.toInt() and 0x80) != 0)
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public object VarLongCodec : PacketCodec<Long> {
|
|
||||||
override fun encode(buffer: BytesBuffer, value: Long) {
|
|
||||||
var v = value
|
|
||||||
while (true) {
|
|
||||||
if ((v and 0x7FL.inv()) == 0L) {
|
|
||||||
buffer.writeByte(v.toByte())
|
|
||||||
return
|
|
||||||
}
|
|
||||||
buffer.writeByte(((v and 0x7F) or 0x80).toByte())
|
|
||||||
v = v ushr 7
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun decode(buffer: BytesBuffer): Long {
|
|
||||||
var numRead = 0
|
|
||||||
var result = 0L
|
|
||||||
var read: Byte
|
|
||||||
do {
|
|
||||||
read = buffer.readByte()
|
|
||||||
val value = (read.toLong() and 0x7F)
|
|
||||||
result = result or (value shl (7 * numRead))
|
|
||||||
numRead++
|
|
||||||
if (numRead > 10) throw IllegalArgumentException("VarLong is too big")
|
|
||||||
} while ((read.toInt() and 0x80) != 0)
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public object McStringCodec : PacketCodec<String> {
|
|
||||||
override fun encode(buffer: BytesBuffer, value: String) {
|
|
||||||
val bytes = value.encodeToByteArray()
|
|
||||||
VarIntCodec.encode(buffer, bytes.size)
|
|
||||||
buffer.writeBytes(bytes)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun decode(buffer: BytesBuffer): String {
|
|
||||||
val length = VarIntCodec.decode(buffer)
|
|
||||||
val bytes = buffer.readBytes(length)
|
|
||||||
return bytes.decodeToString()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public sealed interface IdOrX<out T> {
|
|
||||||
public data class Inline<T>(val value: T) : IdOrX<T>
|
|
||||||
public data class Reference(val registryId: Int) : IdOrX<Nothing>
|
|
||||||
}
|
|
||||||
|
|
||||||
public inline fun <T> BytesBuffer.writeIdOrX(value: IdOrX<T>, writeX: BytesBuffer.(T) -> Unit) {
|
|
||||||
when (value) {
|
|
||||||
is IdOrX.Inline -> {
|
|
||||||
this.writeVarInt(0)
|
|
||||||
this.writeX(value.value)
|
|
||||||
}
|
|
||||||
|
|
||||||
is IdOrX.Reference -> this.writeVarInt(value.registryId + 1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public inline fun <T> BytesBuffer.readIdOrX(readX: BytesBuffer.() -> T): IdOrX<T> {
|
|
||||||
val id = this.readVarInt()
|
|
||||||
return if (id == 0) IdOrX.Inline(this.readX()) else IdOrX.Reference(id - 1)
|
|
||||||
}
|
|
||||||
|
|
||||||
public fun BytesBuffer.writeUuid(uuid: Uuid): Unit = uuid.toLongs { mostSignificantBits, leastSignificantBits ->
|
|
||||||
this.writeLong(mostSignificantBits)
|
|
||||||
this.writeLong(leastSignificantBits)
|
|
||||||
}
|
|
||||||
|
|
||||||
public fun BytesBuffer.readUuid(): Uuid {
|
|
||||||
val most = this.readLong()
|
|
||||||
val least = this.readLong()
|
|
||||||
return Uuid.fromLongs(most, least)
|
|
||||||
}
|
|
||||||
|
|
||||||
public fun BytesBuffer.writeVarInt(value: Int): Unit = VarIntCodec.encode(this, value)
|
|
||||||
public fun BytesBuffer.readVarInt(): Int = VarIntCodec.decode(this)
|
|
||||||
|
|
||||||
public fun BytesBuffer.writeVarLong(value: Long): Unit = VarLongCodec.encode(this, value)
|
|
||||||
public fun BytesBuffer.readVarLong(): Long = VarLongCodec.decode(this)
|
|
||||||
|
|
||||||
public fun BytesBuffer.writeMcString(value: String): Unit = McStringCodec.encode(this, value)
|
|
||||||
public fun BytesBuffer.readMcString(): String = McStringCodec.decode(this)
|
|
||||||
|
|
||||||
public fun BytesBuffer.readPrefixedByteArray(): ByteArray {
|
|
||||||
val length = this.readVarInt()
|
|
||||||
val data = this.readBytes(length)
|
|
||||||
return data
|
|
||||||
}
|
|
||||||
|
|
||||||
public fun BytesBuffer.writePrefixedByteArray(data: ByteArray) {
|
|
||||||
this.writeVarInt(data.size)
|
|
||||||
this.writeBytes(data)
|
|
||||||
}
|
|
||||||
|
|
||||||
public fun BytesBuffer.writeOptionalPrefixedByteArray(data: ByteArray?) {
|
|
||||||
if (data != null) {
|
|
||||||
this.writeBoolean(true)
|
|
||||||
this.writeVarInt(data.size)
|
|
||||||
this.writeBytes(data)
|
|
||||||
} else this.writeBoolean(false)
|
|
||||||
}
|
|
||||||
|
|
||||||
public fun BytesBuffer.readPrefixedStringArray(): List<String> {
|
|
||||||
val length = readVarInt()
|
|
||||||
val list = ArrayList<String>(length)
|
|
||||||
repeat(length) { list.add(readMcString()) }
|
|
||||||
return list
|
|
||||||
}
|
|
||||||
|
|
||||||
public fun BytesBuffer.writePrefixedStringArray(value: List<String>) {
|
|
||||||
writeVarInt(value.size)
|
|
||||||
for (item in value) writeMcString(item)
|
|
||||||
}
|
|
||||||
|
|
||||||
public inline fun <T> BytesBuffer.readOptional(block: BytesBuffer.() -> T): T? {
|
|
||||||
val hasData = this.readBoolean()
|
|
||||||
return if (hasData) block.invoke(this) else null
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* buffer.writeOptional(value.someValue) { writeBlockPos(it) }
|
|
||||||
*/
|
|
||||||
public inline fun <T> BytesBuffer.writeOptional(value: T?, block: BytesBuffer.(T) -> Unit) {
|
|
||||||
if (value != null) {
|
|
||||||
this.writeBoolean(true)
|
|
||||||
block.invoke(this, value)
|
|
||||||
} else this.writeBoolean(false)
|
|
||||||
}
|
|
||||||
|
|
||||||
public inline fun <T> BytesBuffer.readPrefixed(reader: BytesBuffer.() -> T): List<T> {
|
|
||||||
val count = this.readVarInt()
|
|
||||||
val list = ArrayList<T>(count)
|
|
||||||
repeat(count) { _ -> list.add(this.reader()) }
|
|
||||||
return list
|
|
||||||
}
|
|
||||||
|
|
||||||
public inline fun <T> BytesBuffer.writePrefixed(list: List<T>, writer: BytesBuffer.(T) -> Unit) {
|
|
||||||
this.writeVarInt(list.size)
|
|
||||||
for (item in list) this.writer(item)
|
|
||||||
}
|
|
||||||
|
|
||||||
public fun BytesBuffer.readBitSet(): LongArray {
|
|
||||||
val count = this.readVarInt()
|
|
||||||
return LongArray(count) { this.readLong() }
|
|
||||||
}
|
|
||||||
|
|
||||||
public fun BytesBuffer.writeBitSet(data: LongArray) {
|
|
||||||
this.writeVarInt(data.size)
|
|
||||||
for (i in data.indices) this.writeLong(data[i])
|
|
||||||
}
|
|
||||||
|
|
||||||
public fun LongArray.countSetBits(): Int {
|
|
||||||
var count = 0
|
|
||||||
for (i in indices) count += this[i].countOneBits()
|
|
||||||
return count
|
|
||||||
}
|
|
||||||
|
|
||||||
public fun LongArray.getBit(bitIndex: Int): Boolean {
|
|
||||||
val longIndex = bitIndex shr 6
|
|
||||||
if (longIndex !in this.indices) return false
|
|
||||||
val bitOffset = bitIndex and 63
|
|
||||||
return (this[longIndex] and (1L shl bitOffset)) != 0L
|
|
||||||
}
|
|
||||||
|
|
||||||
public sealed interface IdSet {
|
|
||||||
public data class Tag(val tagName: String) : IdSet
|
|
||||||
public data class Entries(val ids: List<Int>) : IdSet
|
|
||||||
}
|
|
||||||
|
|
||||||
public fun BytesBuffer.readIdSet(): IdSet {
|
|
||||||
val type = this.readVarInt()
|
|
||||||
return if (type == 0) {
|
|
||||||
IdSet.Tag(tagName = this.readMcString())
|
|
||||||
} else {
|
|
||||||
val count = type - 1
|
|
||||||
val ids = ArrayList<Int>(count)
|
|
||||||
(0 until count).forEach { _ -> ids.add(this.readVarInt()) }
|
|
||||||
IdSet.Entries(ids)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public fun BytesBuffer.writeIdSet(idSet: IdSet) {
|
|
||||||
when (idSet) {
|
|
||||||
is IdSet.Tag -> {
|
|
||||||
this.writeVarInt(0)
|
|
||||||
this.writeMcString(idSet.tagName)
|
|
||||||
}
|
|
||||||
|
|
||||||
is IdSet.Entries -> {
|
|
||||||
this.writeVarInt(idSet.ids.size + 1)
|
|
||||||
for (id in idSet.ids) this.writeVarInt(id)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
/*
|
||||||
|
* Copyright © 2026 RTAkland
|
||||||
|
* Author: RTAkland
|
||||||
|
* Date: 2026/9/4
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
package cn.rtast.libmc.common.packet
|
||||||
|
|
||||||
|
import cn.rtast.libmc.common.stream.BytesBuffer
|
||||||
|
|
||||||
|
public interface Encoder<in T> {
|
||||||
|
public suspend fun encode(buffer: BytesBuffer, value: T)
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface Decoder<out T> {
|
||||||
|
public suspend fun decode(buffer: BytesBuffer): T
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface PacketCodec<T> : Encoder<T>, Decoder<T>
|
||||||
|
|
||||||
|
public suspend fun BytesBuffer.writeBuffer(source: BytesBuffer, length: Long = source.remaining) {
|
||||||
|
if (length <= 0) return
|
||||||
|
val bytes = source.readBytes(length.toInt())
|
||||||
|
this.writeBytes(bytes)
|
||||||
|
}
|
||||||
@@ -7,9 +7,8 @@
|
|||||||
|
|
||||||
package cn.rtast.libmc.common.packet
|
package cn.rtast.libmc.common.packet
|
||||||
|
|
||||||
import cn.rtast.libmc.common.BytesBuffer
|
import cn.rtast.libmc.common.stream.BytesBuffer
|
||||||
import cn.rtast.libmc.common.PacketCodec
|
import cn.rtast.libmc.common.primitives.writeVarInt
|
||||||
import cn.rtast.libmc.common.writeVarInt
|
|
||||||
import kotlin.reflect.KClass
|
import kotlin.reflect.KClass
|
||||||
|
|
||||||
public class PacketRegistry {
|
public class PacketRegistry {
|
||||||
@@ -29,10 +28,10 @@ public class PacketRegistry {
|
|||||||
register(id, T::class, codec)
|
register(id, T::class, codec)
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun decodePacket(packetId: Int, buffer: BytesBuffer): MinecraftPacket =
|
public suspend fun decodePacket(packetId: Int, buffer: BytesBuffer): MinecraftPacket =
|
||||||
idToCodec[packetId]?.decode(buffer) ?: UnknownPacket(packetId, buffer.readBytes(buffer.remaining.toInt()))
|
idToCodec[packetId]?.decode(buffer) ?: UnknownPacket(packetId, buffer.readBytes(buffer.remaining.toInt()))
|
||||||
|
|
||||||
public fun <T : MinecraftPacket> encodePacket(buffer: BytesBuffer, packet: T) {
|
public suspend fun <T : MinecraftPacket> encodePacket(buffer: BytesBuffer, packet: T) {
|
||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
val info = requireNotNull(classToInfo[packet::class]) {
|
val info = requireNotNull(classToInfo[packet::class]) {
|
||||||
"Unregistered Packet ${packet::class.simpleName}"
|
"Unregistered Packet ${packet::class.simpleName}"
|
||||||
|
|||||||
@@ -0,0 +1,33 @@
|
|||||||
|
/*
|
||||||
|
* Copyright © 2026 RTAkland
|
||||||
|
* Author: RTAkland
|
||||||
|
* Date: 2026/9/7
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
package cn.rtast.libmc.common.primitives
|
||||||
|
|
||||||
|
import cn.rtast.libmc.common.stream.BytesBuffer
|
||||||
|
|
||||||
|
public suspend fun BytesBuffer.readBitSet(): LongArray {
|
||||||
|
val count = this.readVarInt()
|
||||||
|
return LongArray(count) { this.readLong() }
|
||||||
|
}
|
||||||
|
|
||||||
|
public suspend fun BytesBuffer.writeBitSet(data: LongArray) {
|
||||||
|
this.writeVarInt(data.size)
|
||||||
|
for (i in data.indices) this.writeLong(data[i])
|
||||||
|
}
|
||||||
|
|
||||||
|
public fun LongArray.countSetBits(): Int {
|
||||||
|
var count = 0
|
||||||
|
for (i in indices) count += this[i].countOneBits()
|
||||||
|
return count
|
||||||
|
}
|
||||||
|
|
||||||
|
public fun LongArray.getBit(bitIndex: Int): Boolean {
|
||||||
|
val longIndex = bitIndex shr 6
|
||||||
|
if (longIndex !in this.indices) return false
|
||||||
|
val bitOffset = bitIndex and 63
|
||||||
|
return (this[longIndex] and (1L shl bitOffset)) != 0L
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
/*
|
||||||
|
* Copyright © 2026 RTAkland
|
||||||
|
* Author: RTAkland
|
||||||
|
* Date: 2026/9/7
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
package cn.rtast.libmc.common.primitives
|
||||||
|
|
||||||
|
import cn.rtast.libmc.common.stream.BytesBuffer
|
||||||
|
|
||||||
|
public sealed interface IdOrX<out T> {
|
||||||
|
public data class Inline<T>(val value: T) : IdOrX<T>
|
||||||
|
public data class Reference(val registryId: Int) : IdOrX<Nothing>
|
||||||
|
}
|
||||||
|
|
||||||
|
public suspend inline fun <T> BytesBuffer.writeIdOrX(value: IdOrX<T>, writeX: BytesBuffer.(T) -> Unit) {
|
||||||
|
when (value) {
|
||||||
|
is IdOrX.Inline -> {
|
||||||
|
this.writeVarInt(0)
|
||||||
|
this.writeX(value.value)
|
||||||
|
}
|
||||||
|
|
||||||
|
is IdOrX.Reference -> this.writeVarInt(value.registryId + 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public suspend inline fun <T> BytesBuffer.readIdOrX(readX: BytesBuffer.() -> T): IdOrX<T> {
|
||||||
|
val id = this.readVarInt()
|
||||||
|
return if (id == 0) IdOrX.Inline(this.readX()) else IdOrX.Reference(id - 1)
|
||||||
|
}
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
/*
|
||||||
|
* Copyright © 2026 RTAkland
|
||||||
|
* Author: RTAkland
|
||||||
|
* Date: 2026/9/7
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
package cn.rtast.libmc.common.primitives
|
||||||
|
|
||||||
|
import cn.rtast.libmc.common.stream.BytesBuffer
|
||||||
|
|
||||||
|
public sealed interface IdSet {
|
||||||
|
public data class Tag(val tagName: String) : IdSet
|
||||||
|
public data class Entries(val ids: List<Int>) : IdSet
|
||||||
|
}
|
||||||
|
|
||||||
|
public suspend fun BytesBuffer.readIdSet(): IdSet {
|
||||||
|
val type = this.readVarInt()
|
||||||
|
return if (type == 0) {
|
||||||
|
IdSet.Tag(tagName = this.readMcString())
|
||||||
|
} else {
|
||||||
|
val count = type - 1
|
||||||
|
val ids = ArrayList<Int>(count)
|
||||||
|
(0 until count).forEach { _ -> ids.add(this.readVarInt()) }
|
||||||
|
IdSet.Entries(ids)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public suspend fun BytesBuffer.writeIdSet(idSet: IdSet) {
|
||||||
|
when (idSet) {
|
||||||
|
is IdSet.Tag -> {
|
||||||
|
this.writeVarInt(0)
|
||||||
|
this.writeMcString(idSet.tagName)
|
||||||
|
}
|
||||||
|
|
||||||
|
is IdSet.Entries -> {
|
||||||
|
this.writeVarInt(idSet.ids.size + 1)
|
||||||
|
for (id in idSet.ids) this.writeVarInt(id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+28
@@ -0,0 +1,28 @@
|
|||||||
|
/*
|
||||||
|
* Copyright © 2026 RTAkland
|
||||||
|
* Author: RTAkland
|
||||||
|
* Date: 2026/9/7
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
package cn.rtast.libmc.common.primitives
|
||||||
|
|
||||||
|
import cn.rtast.libmc.common.stream.BytesBuffer
|
||||||
|
import cn.rtast.libmc.common.packet.PacketCodec
|
||||||
|
|
||||||
|
public object McStringCodec : PacketCodec<String> {
|
||||||
|
override suspend fun encode(buffer: BytesBuffer, value: String) {
|
||||||
|
val bytes = value.encodeToByteArray()
|
||||||
|
VarIntCodec.encode(buffer, bytes.size)
|
||||||
|
buffer.writeBytes(bytes)
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun decode(buffer: BytesBuffer): String {
|
||||||
|
val length = VarIntCodec.decode(buffer)
|
||||||
|
val bytes = buffer.readBytes(length)
|
||||||
|
return bytes.decodeToString()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public suspend fun BytesBuffer.writeMcString(value: String): Unit = McStringCodec.encode(this, value)
|
||||||
|
public suspend fun BytesBuffer.readMcString(): String = McStringCodec.decode(this)
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
/*
|
||||||
|
* Copyright © 2026 RTAkland
|
||||||
|
* Author: RTAkland
|
||||||
|
* Date: 2026/9/7
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
package cn.rtast.libmc.common.primitives
|
||||||
|
|
||||||
|
import cn.rtast.libmc.common.stream.BytesBuffer
|
||||||
|
|
||||||
|
public suspend inline fun <T> BytesBuffer.readOptional(block: BytesBuffer.() -> T): T? {
|
||||||
|
val hasData = this.readBoolean()
|
||||||
|
return if (hasData) block.invoke(this) else null
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* buffer.writeOptional(value.someValue) { writeBlockPos(it) }
|
||||||
|
*/
|
||||||
|
public suspend inline fun <T> BytesBuffer.writeOptional(value: T?, block: BytesBuffer.(T) -> Unit) {
|
||||||
|
if (value != null) {
|
||||||
|
this.writeBoolean(true)
|
||||||
|
block.invoke(this, value)
|
||||||
|
} else this.writeBoolean(false)
|
||||||
|
}
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
/*
|
||||||
|
* Copyright © 2026 RTAkland
|
||||||
|
* Author: RTAkland
|
||||||
|
* Date: 2026/9/7
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
package cn.rtast.libmc.common.primitives
|
||||||
|
|
||||||
|
import cn.rtast.libmc.common.stream.BytesBuffer
|
||||||
|
|
||||||
|
|
||||||
|
public suspend fun BytesBuffer.readPrefixedByteArray(): ByteArray {
|
||||||
|
val length = this.readVarInt()
|
||||||
|
val data = this.readBytes(length)
|
||||||
|
return data
|
||||||
|
}
|
||||||
|
|
||||||
|
public suspend fun BytesBuffer.writePrefixedByteArray(data: ByteArray) {
|
||||||
|
this.writeVarInt(data.size)
|
||||||
|
this.writeBytes(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
public suspend fun BytesBuffer.writeOptionalPrefixedByteArray(data: ByteArray?) {
|
||||||
|
if (data != null) {
|
||||||
|
this.writeBoolean(true)
|
||||||
|
this.writeVarInt(data.size)
|
||||||
|
this.writeBytes(data)
|
||||||
|
} else this.writeBoolean(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
public suspend fun BytesBuffer.readPrefixedStringArray(): List<String> {
|
||||||
|
val length = readVarInt()
|
||||||
|
val list = ArrayList<String>(length)
|
||||||
|
repeat(length) { list.add(readMcString()) }
|
||||||
|
return list
|
||||||
|
}
|
||||||
|
|
||||||
|
public suspend fun BytesBuffer.writePrefixedStringArray(value: List<String>) {
|
||||||
|
writeVarInt(value.size)
|
||||||
|
for (item in value) writeMcString(item)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public suspend inline fun <T> BytesBuffer.readPrefixed(reader: BytesBuffer.() -> T): List<T> {
|
||||||
|
val count = this.readVarInt()
|
||||||
|
val list = ArrayList<T>(count)
|
||||||
|
repeat(count) { _ -> list.add(this.reader()) }
|
||||||
|
return list
|
||||||
|
}
|
||||||
|
|
||||||
|
public suspend inline fun <T> BytesBuffer.writePrefixed(list: List<T>, writer: BytesBuffer.(T) -> Unit) {
|
||||||
|
this.writeVarInt(list.size)
|
||||||
|
for (item in list) this.writer(item)
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
/*
|
||||||
|
* Copyright © 2026 RTAkland
|
||||||
|
* Author: RTAkland
|
||||||
|
* Date: 2026/9/7
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
package cn.rtast.libmc.common.primitives
|
||||||
|
|
||||||
|
import cn.rtast.libmc.common.stream.BytesBuffer
|
||||||
|
import kotlin.uuid.Uuid
|
||||||
|
|
||||||
|
public suspend fun BytesBuffer.writeUuid(uuid: Uuid): Unit = uuid.toLongs { mostSignificantBits, leastSignificantBits ->
|
||||||
|
this.writeLong(mostSignificantBits)
|
||||||
|
this.writeLong(leastSignificantBits)
|
||||||
|
}
|
||||||
|
|
||||||
|
public suspend fun BytesBuffer.readUuid(): Uuid {
|
||||||
|
val most = this.readLong()
|
||||||
|
val least = this.readLong()
|
||||||
|
return Uuid.fromLongs(most, least)
|
||||||
|
}
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
/*
|
||||||
|
* Copyright © 2026 RTAkland
|
||||||
|
* Author: RTAkland
|
||||||
|
* Date: 2026/9/7
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
package cn.rtast.libmc.common.primitives
|
||||||
|
|
||||||
|
import cn.rtast.libmc.common.stream.BytesBuffer
|
||||||
|
import cn.rtast.libmc.common.packet.PacketCodec
|
||||||
|
|
||||||
|
public object VarIntCodec : PacketCodec<Int> {
|
||||||
|
override suspend fun encode(buffer: BytesBuffer, value: Int) {
|
||||||
|
var v = value
|
||||||
|
while (true) {
|
||||||
|
if ((v and 0x7F.inv()) == 0) {
|
||||||
|
buffer.writeByte(v.toByte())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
buffer.writeByte(((v and 0x7F) or 0x80).toByte())
|
||||||
|
v = v ushr 7
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun decode(buffer: BytesBuffer): Int {
|
||||||
|
var numRead = 0
|
||||||
|
var result = 0
|
||||||
|
var read: Byte
|
||||||
|
do {
|
||||||
|
read = buffer.readByte()
|
||||||
|
val value = (read.toInt() and 0x7F)
|
||||||
|
result = result or (value shl (7 * numRead))
|
||||||
|
numRead++
|
||||||
|
if (numRead > 5) throw IllegalArgumentException("VarInt is too big")
|
||||||
|
} while ((read.toInt() and 0x80) != 0)
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public suspend fun BytesBuffer.writeVarInt(value: Int): Unit = VarIntCodec.encode(this, value)
|
||||||
|
public suspend fun BytesBuffer.readVarInt(): Int = VarIntCodec.decode(this)
|
||||||
|
|
||||||
|
public suspend fun BytesBuffer.writeVarLong(value: Long): Unit = VarLongCodec.encode(this, value)
|
||||||
|
public suspend fun BytesBuffer.readVarLong(): Long = VarLongCodec.decode(this)
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
/*
|
||||||
|
* Copyright © 2026 RTAkland
|
||||||
|
* Author: RTAkland
|
||||||
|
* Date: 2026/9/7
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
package cn.rtast.libmc.common.primitives
|
||||||
|
|
||||||
|
import cn.rtast.libmc.common.stream.BytesBuffer
|
||||||
|
import cn.rtast.libmc.common.packet.PacketCodec
|
||||||
|
|
||||||
|
public object VarLongCodec : PacketCodec<Long> {
|
||||||
|
override suspend fun encode(buffer: BytesBuffer, value: Long) {
|
||||||
|
var v = value
|
||||||
|
while (true) {
|
||||||
|
if ((v and 0x7FL.inv()) == 0L) {
|
||||||
|
buffer.writeByte(v.toByte())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
buffer.writeByte(((v and 0x7F) or 0x80).toByte())
|
||||||
|
v = v ushr 7
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun decode(buffer: BytesBuffer): Long {
|
||||||
|
var numRead = 0
|
||||||
|
var result = 0L
|
||||||
|
var read: Byte
|
||||||
|
do {
|
||||||
|
read = buffer.readByte()
|
||||||
|
val value = (read.toLong() and 0x7F)
|
||||||
|
result = result or (value shl (7 * numRead))
|
||||||
|
numRead++
|
||||||
|
if (numRead > 10) throw IllegalArgumentException("VarLong is too big")
|
||||||
|
} while ((read.toInt() and 0x80) != 0)
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
/*
|
||||||
|
* Copyright © 2026 RTAkland
|
||||||
|
* Author: RTAkland
|
||||||
|
* Date: 2026/9/3
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
package cn.rtast.libmc.common.stream
|
||||||
|
|
||||||
|
public expect class BytesBuffer {
|
||||||
|
public constructor()
|
||||||
|
public constructor(bytes: ByteArray)
|
||||||
|
|
||||||
|
public suspend fun writeByte(value: Byte)
|
||||||
|
public suspend fun writeShort(value: Short, endian: ByteOrder = ByteOrder.BIG_ENDIAN)
|
||||||
|
public suspend fun writeInt(value: Int, endian: ByteOrder = ByteOrder.BIG_ENDIAN)
|
||||||
|
public suspend fun writeLong(value: Long, endian: ByteOrder = ByteOrder.BIG_ENDIAN)
|
||||||
|
public suspend fun writeDouble(value: Double, endian: ByteOrder = ByteOrder.BIG_ENDIAN)
|
||||||
|
public suspend fun writeFloat(value: Float, endian: ByteOrder = ByteOrder.BIG_ENDIAN)
|
||||||
|
public suspend fun writeBytes(bytes: ByteArray)
|
||||||
|
public suspend fun writeBoolean(value: Boolean)
|
||||||
|
|
||||||
|
public suspend fun readByte(): Byte
|
||||||
|
public suspend fun readUByte(): UByte
|
||||||
|
public suspend fun readShort(endian: ByteOrder = ByteOrder.BIG_ENDIAN): Short
|
||||||
|
public suspend fun readInt(endian: ByteOrder = ByteOrder.BIG_ENDIAN): Int
|
||||||
|
public suspend fun readLong(endian: ByteOrder = ByteOrder.BIG_ENDIAN): Long
|
||||||
|
public suspend fun readDouble(endian: ByteOrder = ByteOrder.BIG_ENDIAN): Double
|
||||||
|
public suspend fun readFloat(endian: ByteOrder = ByteOrder.BIG_ENDIAN): Float
|
||||||
|
public suspend fun readBytes(length: Int): ByteArray
|
||||||
|
public suspend fun readBoolean(): Boolean
|
||||||
|
public suspend fun readRemainingBytes(): ByteArray
|
||||||
|
|
||||||
|
public suspend fun toByteArray(): ByteArray
|
||||||
|
public suspend fun hasRemaining(): Boolean
|
||||||
|
public suspend fun close()
|
||||||
|
public val size: Int
|
||||||
|
public val remaining: Long
|
||||||
|
}
|
||||||
|
|
||||||
|
@Suppress("NOTHING_TO_INLINE")
|
||||||
|
public inline fun ByteArray.wrap(): BytesBuffer = BytesBuffer(this)
|
||||||
|
|
||||||
|
public suspend fun ReadChannel.readPacketFrame(): BytesBuffer {
|
||||||
|
val length = this.readVarInt()
|
||||||
|
return this.readBytes(length).wrap()
|
||||||
|
}
|
||||||
+1
-1
@@ -5,7 +5,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
package cn.rtast.libmc.common
|
package cn.rtast.libmc.common.stream
|
||||||
|
|
||||||
public enum class ByteOrder {
|
public enum class ByteOrder {
|
||||||
BIG_ENDIAN, LITTLE_ENDIAN
|
BIG_ENDIAN, LITTLE_ENDIAN
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
/*
|
||||||
|
* Copyright © 2026 RTAkland
|
||||||
|
* Author: RTAkland
|
||||||
|
* Date: 2026/9/3
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
package cn.rtast.libmc.common.stream
|
||||||
|
|
||||||
|
public expect open class ReadChannel() {
|
||||||
|
public open suspend fun readByte(): Byte
|
||||||
|
public open suspend fun readShort(endian: ByteOrder = ByteOrder.BIG_ENDIAN): Short
|
||||||
|
public open suspend fun readInt(endian: ByteOrder = ByteOrder.BIG_ENDIAN): Int
|
||||||
|
public open suspend fun readLong(endian: ByteOrder = ByteOrder.BIG_ENDIAN): Long
|
||||||
|
public open suspend fun readBytes(length: Int): ByteArray
|
||||||
|
public open suspend fun readFully(out: ByteArray, start: Int = 0, end: Int = out.size)
|
||||||
|
}
|
||||||
|
|
||||||
|
public expect open class WriteChannel() {
|
||||||
|
public open suspend fun writeFully(value: ByteArray, startIndex: Int = 0, endIndex: Int = value.size)
|
||||||
|
public open suspend fun flush()
|
||||||
|
}
|
||||||
|
|
||||||
|
public suspend fun ReadChannel.readVarInt(): Int {
|
||||||
|
var numRead = 0
|
||||||
|
var result = 0
|
||||||
|
var read: Byte
|
||||||
|
do {
|
||||||
|
read = this.readByte()
|
||||||
|
val value = (read.toInt() and 0x7F)
|
||||||
|
result = result or (value shl (7 * numRead))
|
||||||
|
numRead++
|
||||||
|
if (numRead > 5) throw IllegalArgumentException("VarInt is too big")
|
||||||
|
} while ((read.toInt() and 0x80) != 0)
|
||||||
|
return result
|
||||||
|
}
|
||||||
+4
-2
@@ -5,7 +5,9 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
package cn.rtast.libmc.common
|
package cn.rtast.libmc.common.stream
|
||||||
|
|
||||||
|
import cn.rtast.libmc.common.LibMCContext
|
||||||
|
|
||||||
public expect class Socket public constructor(host: String, port: Int, context: LibMCContext) {
|
public expect class Socket public constructor(host: String, port: Int, context: LibMCContext) {
|
||||||
public fun openReadChannel(): ReadChannel
|
public fun openReadChannel(): ReadChannel
|
||||||
@@ -14,6 +16,6 @@ public expect class Socket public constructor(host: String, port: Int, context:
|
|||||||
}
|
}
|
||||||
|
|
||||||
public expect class UdpSocket public constructor(host: String, port: Int, context: LibMCContext) {
|
public expect class UdpSocket public constructor(host: String, port: Int, context: LibMCContext) {
|
||||||
public fun sendAndReceive(data: ByteArray): ByteArray
|
public suspend fun sendAndReceive(data: ByteArray): ByteArray
|
||||||
public fun close()
|
public fun close()
|
||||||
}
|
}
|
||||||
+26
-24
@@ -4,8 +4,10 @@
|
|||||||
* Date: 2026/9/3
|
* Date: 2026/9/3
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package cn.rtast.libmc.common
|
package cn.rtast.libmc.common.stream
|
||||||
|
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
import java.io.ByteArrayOutputStream
|
import java.io.ByteArrayOutputStream
|
||||||
|
|
||||||
public actual class BytesBuffer {
|
public actual class BytesBuffer {
|
||||||
@@ -19,12 +21,12 @@ public actual class BytesBuffer {
|
|||||||
outStream.write(bytes)
|
outStream.write(bytes)
|
||||||
}
|
}
|
||||||
|
|
||||||
public actual fun writeByte(value: Byte) {
|
public actual suspend fun writeByte(value: Byte) {
|
||||||
readBuffer = null
|
readBuffer = null
|
||||||
outStream.write(value.toInt())
|
outStream.write(value.toInt())
|
||||||
}
|
}
|
||||||
|
|
||||||
public actual fun writeShort(value: Short, endian: ByteOrder) {
|
public actual suspend fun writeShort(value: Short, endian: ByteOrder) {
|
||||||
readBuffer = null
|
readBuffer = null
|
||||||
val v = value.toInt()
|
val v = value.toInt()
|
||||||
if (endian == ByteOrder.BIG_ENDIAN) {
|
if (endian == ByteOrder.BIG_ENDIAN) {
|
||||||
@@ -36,7 +38,7 @@ public actual class BytesBuffer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public actual fun writeInt(value: Int, endian: ByteOrder) {
|
public actual suspend fun writeInt(value: Int, endian: ByteOrder) {
|
||||||
readBuffer = null
|
readBuffer = null
|
||||||
if (endian == ByteOrder.BIG_ENDIAN) {
|
if (endian == ByteOrder.BIG_ENDIAN) {
|
||||||
outStream.write(value shr 24)
|
outStream.write(value shr 24)
|
||||||
@@ -51,7 +53,7 @@ public actual class BytesBuffer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public actual fun writeLong(value: Long, endian: ByteOrder) {
|
public actual suspend fun writeLong(value: Long, endian: ByteOrder) {
|
||||||
readBuffer = null
|
readBuffer = null
|
||||||
if (endian == ByteOrder.BIG_ENDIAN) {
|
if (endian == ByteOrder.BIG_ENDIAN) {
|
||||||
for (i in 56 downTo 0 step 8) outStream.write((value shr i).toInt())
|
for (i in 56 downTo 0 step 8) outStream.write((value shr i).toInt())
|
||||||
@@ -60,22 +62,22 @@ public actual class BytesBuffer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public actual fun writeDouble(value: Double, endian: ByteOrder) {
|
public actual suspend fun writeDouble(value: Double, endian: ByteOrder) {
|
||||||
writeLong(value.toRawBits(), endian)
|
writeLong(value.toRawBits(), endian)
|
||||||
}
|
}
|
||||||
|
|
||||||
public actual fun writeFloat(value: Float, endian: ByteOrder) {
|
public actual suspend fun writeFloat(value: Float, endian: ByteOrder) {
|
||||||
writeInt(value.toRawBits(), endian)
|
writeInt(value.toRawBits(), endian)
|
||||||
}
|
}
|
||||||
|
|
||||||
public actual fun writeBytes(bytes: ByteArray) {
|
public actual suspend fun writeBytes(bytes: ByteArray) {
|
||||||
readBuffer = null
|
readBuffer = null
|
||||||
outStream.write(bytes)
|
withContext(Dispatchers.IO) { outStream.write(bytes) }
|
||||||
}
|
}
|
||||||
|
|
||||||
public actual fun writeBoolean(value: Boolean): Unit = writeByte(if (value) 0x01 else 0x00)
|
public actual suspend fun writeBoolean(value: Boolean): Unit = writeByte(if (value) 0x01 else 0x00)
|
||||||
|
|
||||||
private fun ensureReadArray(): ByteArray {
|
private suspend fun ensureReadArray(): ByteArray {
|
||||||
var buf = readBuffer
|
var buf = readBuffer
|
||||||
if (buf == null) {
|
if (buf == null) {
|
||||||
buf = outStream.toByteArray()
|
buf = outStream.toByteArray()
|
||||||
@@ -84,26 +86,26 @@ public actual class BytesBuffer {
|
|||||||
return buf
|
return buf
|
||||||
}
|
}
|
||||||
|
|
||||||
public actual fun readByte(): Byte {
|
public actual suspend fun readByte(): Byte {
|
||||||
val array = ensureReadArray()
|
val array = ensureReadArray()
|
||||||
if (readOffset >= array.size) throw IndexOutOfBoundsException("Buffer underflow")
|
if (readOffset >= array.size) throw IndexOutOfBoundsException("Buffer underflow")
|
||||||
return array[readOffset++]
|
return array[readOffset++]
|
||||||
}
|
}
|
||||||
|
|
||||||
public actual fun readUByte(): UByte = this.readByte().toUByte()
|
public actual suspend fun readUByte(): UByte = this.readByte().toUByte()
|
||||||
public actual fun readShort(endian: ByteOrder): Short = readBytes(2).toShort(endian)
|
public actual suspend fun readShort(endian: ByteOrder): Short = readBytes(2).toShort(endian)
|
||||||
public actual fun readInt(endian: ByteOrder): Int = readBytes(4).toInt(endian)
|
public actual suspend fun readInt(endian: ByteOrder): Int = readBytes(4).toInt(endian)
|
||||||
public actual fun readLong(endian: ByteOrder): Long = readBytes(8).toLong(endian)
|
public actual suspend fun readLong(endian: ByteOrder): Long = readBytes(8).toLong(endian)
|
||||||
|
|
||||||
public actual fun readDouble(endian: ByteOrder): Double {
|
public actual suspend fun readDouble(endian: ByteOrder): Double {
|
||||||
return Double.fromBits(readLong(endian))
|
return Double.fromBits(readLong(endian))
|
||||||
}
|
}
|
||||||
|
|
||||||
public actual fun readFloat(endian: ByteOrder): Float {
|
public actual suspend fun readFloat(endian: ByteOrder): Float {
|
||||||
return Float.fromBits(readInt(endian))
|
return Float.fromBits(readInt(endian))
|
||||||
}
|
}
|
||||||
|
|
||||||
public actual fun readBytes(length: Int): ByteArray {
|
public actual suspend fun readBytes(length: Int): ByteArray {
|
||||||
val array = ensureReadArray()
|
val array = ensureReadArray()
|
||||||
if (readOffset + length > array.size) throw IndexOutOfBoundsException("Buffer underflow")
|
if (readOffset + length > array.size) throw IndexOutOfBoundsException("Buffer underflow")
|
||||||
val result = array.copyOfRange(readOffset, readOffset + length)
|
val result = array.copyOfRange(readOffset, readOffset + length)
|
||||||
@@ -111,9 +113,9 @@ public actual class BytesBuffer {
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
public actual fun readBoolean(): Boolean = this.readByte() != 0x00.toByte()
|
public actual suspend fun readBoolean(): Boolean = this.readByte() != 0x00.toByte()
|
||||||
|
|
||||||
public actual fun readRemainingBytes(): ByteArray {
|
public actual suspend fun readRemainingBytes(): ByteArray {
|
||||||
val array = ensureReadArray()
|
val array = ensureReadArray()
|
||||||
if (readOffset >= array.size) return byteArrayOf()
|
if (readOffset >= array.size) return byteArrayOf()
|
||||||
val result = array.copyOfRange(readOffset, array.size)
|
val result = array.copyOfRange(readOffset, array.size)
|
||||||
@@ -121,10 +123,10 @@ public actual class BytesBuffer {
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
public actual fun toByteArray(): ByteArray = outStream.toByteArray()
|
public actual suspend fun toByteArray(): ByteArray = outStream.toByteArray()
|
||||||
public actual fun hasRemaining(): Boolean = readOffset < ensureReadArray().size
|
public actual suspend fun hasRemaining(): Boolean = readOffset < ensureReadArray().size
|
||||||
|
|
||||||
public actual fun close(): Unit = outStream.close()
|
public actual suspend fun close(): Unit = withContext(Dispatchers.IO) { outStream.close() }
|
||||||
public actual val size: Int get() = outStream.size()
|
public actual val size: Int get() = outStream.size()
|
||||||
public actual val remaining: Long get() = (outStream.size() - readOffset).coerceAtLeast(0).toLong()
|
public actual val remaining: Long get() = (outStream.size() - readOffset).coerceAtLeast(0).toLong()
|
||||||
}
|
}
|
||||||
+9
-9
@@ -4,7 +4,7 @@
|
|||||||
* Date: 2026/9/3
|
* Date: 2026/9/3
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package cn.rtast.libmc.common
|
package cn.rtast.libmc.common.stream
|
||||||
|
|
||||||
import java.io.EOFException
|
import java.io.EOFException
|
||||||
import java.io.InputStream
|
import java.io.InputStream
|
||||||
@@ -17,7 +17,7 @@ public actual open class ReadChannel public actual constructor() {
|
|||||||
this._inputStream = inputStream
|
this._inputStream = inputStream
|
||||||
}
|
}
|
||||||
|
|
||||||
public actual open fun readFully(out: ByteArray, start: Int, end: Int) {
|
public actual open suspend fun readFully(out: ByteArray, start: Int, end: Int) {
|
||||||
var bytesRead = 0
|
var bytesRead = 0
|
||||||
val length = end - start
|
val length = end - start
|
||||||
while (bytesRead < length) {
|
while (bytesRead < length) {
|
||||||
@@ -27,21 +27,21 @@ public actual open class ReadChannel public actual constructor() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public actual open fun readByte(): Byte {
|
public actual open suspend fun readByte(): Byte {
|
||||||
val buf = ByteArray(1)
|
val buf = ByteArray(1)
|
||||||
readFully(buf, 0, 1)
|
readFully(buf, 0, 1)
|
||||||
return buf[0]
|
return buf[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
public actual open fun readBytes(length: Int): ByteArray {
|
public actual open suspend fun readBytes(length: Int): ByteArray {
|
||||||
val bytes = ByteArray(length)
|
val bytes = ByteArray(length)
|
||||||
readFully(bytes, 0, length)
|
readFully(bytes, 0, length)
|
||||||
return bytes
|
return bytes
|
||||||
}
|
}
|
||||||
|
|
||||||
public actual open fun readShort(endian: ByteOrder): Short = readBytes(2).toShort(endian)
|
public actual open suspend fun readShort(endian: ByteOrder): Short = readBytes(2).toShort(endian)
|
||||||
public actual open fun readInt(endian: ByteOrder): Int = readBytes(4).toInt(endian)
|
public actual open suspend fun readInt(endian: ByteOrder): Int = readBytes(4).toInt(endian)
|
||||||
public actual open fun readLong(endian: ByteOrder): Long = readBytes(8).toLong(endian)
|
public actual open suspend fun readLong(endian: ByteOrder): Long = readBytes(8).toLong(endian)
|
||||||
}
|
}
|
||||||
|
|
||||||
public actual open class WriteChannel public actual constructor() {
|
public actual open class WriteChannel public actual constructor() {
|
||||||
@@ -51,8 +51,8 @@ public actual open class WriteChannel public actual constructor() {
|
|||||||
_outputStream = outputStream
|
_outputStream = outputStream
|
||||||
}
|
}
|
||||||
|
|
||||||
public actual open fun writeFully(value: ByteArray, startIndex: Int, endIndex: Int): Unit =
|
public actual open suspend fun writeFully(value: ByteArray, startIndex: Int, endIndex: Int): Unit =
|
||||||
_outputStream.write(value, startIndex, endIndex - startIndex)
|
_outputStream.write(value, startIndex, endIndex - startIndex)
|
||||||
|
|
||||||
public actual open fun flush(): Unit = _outputStream.flush()
|
public actual open suspend fun flush(): Unit = _outputStream.flush()
|
||||||
}
|
}
|
||||||
+1
-1
@@ -5,7 +5,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
package cn.rtast.libmc.common
|
package cn.rtast.libmc.common.stream
|
||||||
|
|
||||||
internal fun ByteArray.toShort(endian: ByteOrder = ByteOrder.BIG_ENDIAN): Short {
|
internal fun ByteArray.toShort(endian: ByteOrder = ByteOrder.BIG_ENDIAN): Short {
|
||||||
val b1 = this[0].toInt() and 0xFF
|
val b1 = this[0].toInt() and 0xFF
|
||||||
+6
-4
@@ -4,8 +4,11 @@
|
|||||||
* Date: 2026/9/3
|
* Date: 2026/9/3
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package cn.rtast.libmc.common
|
package cn.rtast.libmc.common.stream
|
||||||
|
|
||||||
|
import cn.rtast.libmc.common.LibMCContext
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
import java.net.DatagramPacket
|
import java.net.DatagramPacket
|
||||||
import java.net.DatagramSocket
|
import java.net.DatagramSocket
|
||||||
import java.net.InetSocketAddress
|
import java.net.InetSocketAddress
|
||||||
@@ -25,13 +28,12 @@ public actual class UdpSocket public actual constructor(host: String, port: Int,
|
|||||||
connect(InetSocketAddress(host, port))
|
connect(InetSocketAddress(host, port))
|
||||||
}
|
}
|
||||||
|
|
||||||
public actual fun sendAndReceive(data: ByteArray): ByteArray {
|
public actual suspend fun sendAndReceive(data: ByteArray): ByteArray = withContext(Dispatchers.IO) {
|
||||||
socket.send(DatagramPacket(data, data.size))
|
socket.send(DatagramPacket(data, data.size))
|
||||||
|
|
||||||
val buf = ByteArray(2048)
|
val buf = ByteArray(2048)
|
||||||
val receivePacket = DatagramPacket(buf, buf.size)
|
val receivePacket = DatagramPacket(buf, buf.size)
|
||||||
socket.receive(receivePacket)
|
socket.receive(receivePacket)
|
||||||
return buf.copyOf(receivePacket.length)
|
return@withContext buf.copyOf(receivePacket.length)
|
||||||
}
|
}
|
||||||
|
|
||||||
public actual fun close(): Unit = socket.close()
|
public actual fun close(): Unit = socket.close()
|
||||||
+22
-22
@@ -4,7 +4,7 @@
|
|||||||
* Date: 2026/9/3
|
* Date: 2026/9/3
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package cn.rtast.libmc.common
|
package cn.rtast.libmc.common.stream
|
||||||
|
|
||||||
import io.ktor.utils.io.core.*
|
import io.ktor.utils.io.core.*
|
||||||
import kotlinx.io.*
|
import kotlinx.io.*
|
||||||
@@ -21,53 +21,53 @@ public actual class BytesBuffer {
|
|||||||
_delegateBuf = Buffer().apply { write(bytes) }
|
_delegateBuf = Buffer().apply { write(bytes) }
|
||||||
}
|
}
|
||||||
|
|
||||||
public actual fun writeByte(value: Byte): Unit = _delegateBuf.writeByte(value)
|
public actual suspend fun writeByte(value: Byte): Unit = _delegateBuf.writeByte(value)
|
||||||
public actual fun writeShort(value: Short, endian: ByteOrder) {
|
public actual suspend fun writeShort(value: Short, endian: ByteOrder) {
|
||||||
if (endian == ByteOrder.BIG_ENDIAN) _delegateBuf.writeShort(value)
|
if (endian == ByteOrder.BIG_ENDIAN) _delegateBuf.writeShort(value)
|
||||||
else _delegateBuf.writeShortLe(value)
|
else _delegateBuf.writeShortLe(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
public actual fun writeInt(value: Int, endian: ByteOrder) {
|
public actual suspend fun writeInt(value: Int, endian: ByteOrder) {
|
||||||
if (endian == ByteOrder.BIG_ENDIAN) _delegateBuf.writeInt(value)
|
if (endian == ByteOrder.BIG_ENDIAN) _delegateBuf.writeInt(value)
|
||||||
else _delegateBuf.writeIntLe(value)
|
else _delegateBuf.writeIntLe(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
public actual fun writeLong(value: Long, endian: ByteOrder) {
|
public actual suspend fun writeLong(value: Long, endian: ByteOrder) {
|
||||||
if (endian == ByteOrder.BIG_ENDIAN) _delegateBuf.writeLong(value)
|
if (endian == ByteOrder.BIG_ENDIAN) _delegateBuf.writeLong(value)
|
||||||
else _delegateBuf.writeLongLe(value)
|
else _delegateBuf.writeLongLe(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
public actual fun writeDouble(value: Double, endian: ByteOrder): Unit =
|
public actual suspend fun writeDouble(value: Double, endian: ByteOrder): Unit =
|
||||||
if (endian == ByteOrder.BIG_ENDIAN) _delegateBuf.writeDouble(value) else _delegateBuf.writeDoubleLe(value)
|
if (endian == ByteOrder.BIG_ENDIAN) _delegateBuf.writeDouble(value) else _delegateBuf.writeDoubleLe(value)
|
||||||
|
|
||||||
public actual fun writeFloat(value: Float, endian: ByteOrder): Unit =
|
public actual suspend fun writeFloat(value: Float, endian: ByteOrder): Unit =
|
||||||
if (endian == ByteOrder.BIG_ENDIAN) _delegateBuf.writeFloat(value) else _delegateBuf.writeFloatLe(value)
|
if (endian == ByteOrder.BIG_ENDIAN) _delegateBuf.writeFloat(value) else _delegateBuf.writeFloatLe(value)
|
||||||
|
|
||||||
public actual fun writeBytes(bytes: ByteArray): Unit = _delegateBuf.write(bytes)
|
public actual suspend fun writeBytes(bytes: ByteArray): Unit = _delegateBuf.write(bytes)
|
||||||
public actual fun writeBoolean(value: Boolean): Unit = _delegateBuf.writeByte(if (value) 0x01 else 0x00)
|
public actual suspend fun writeBoolean(value: Boolean): Unit = _delegateBuf.writeByte(if (value) 0x01 else 0x00)
|
||||||
|
|
||||||
public actual fun readByte(): Byte = _delegateBuf.readByte()
|
public actual suspend fun readByte(): Byte = _delegateBuf.readByte()
|
||||||
public actual fun readUByte(): UByte = this.readByte().toUByte()
|
public actual suspend fun readUByte(): UByte = this.readByte().toUByte()
|
||||||
public actual fun readShort(endian: ByteOrder): Short =
|
public actual suspend fun readShort(endian: ByteOrder): Short =
|
||||||
if (endian == ByteOrder.BIG_ENDIAN) _delegateBuf.readShort() else _delegateBuf.readShortLe()
|
if (endian == ByteOrder.BIG_ENDIAN) _delegateBuf.readShort() else _delegateBuf.readShortLe()
|
||||||
|
|
||||||
public actual fun readInt(endian: ByteOrder): Int =
|
public actual suspend fun readInt(endian: ByteOrder): Int =
|
||||||
if (endian == ByteOrder.BIG_ENDIAN) _delegateBuf.readInt() else _delegateBuf.readIntLe()
|
if (endian == ByteOrder.BIG_ENDIAN) _delegateBuf.readInt() else _delegateBuf.readIntLe()
|
||||||
|
|
||||||
public actual fun readLong(endian: ByteOrder): Long =
|
public actual suspend fun readLong(endian: ByteOrder): Long =
|
||||||
if (endian == ByteOrder.BIG_ENDIAN) _delegateBuf.readLong() else _delegateBuf.readLongLe()
|
if (endian == ByteOrder.BIG_ENDIAN) _delegateBuf.readLong() else _delegateBuf.readLongLe()
|
||||||
|
|
||||||
public actual fun readDouble(endian: ByteOrder): Double =
|
public actual suspend fun readDouble(endian: ByteOrder): Double =
|
||||||
if (endian == ByteOrder.BIG_ENDIAN) _delegateBuf.readDouble() else _delegateBuf.readDoubleLe()
|
if (endian == ByteOrder.BIG_ENDIAN) _delegateBuf.readDouble() else _delegateBuf.readDoubleLe()
|
||||||
|
|
||||||
public actual fun readFloat(endian: ByteOrder): Float =
|
public actual suspend fun readFloat(endian: ByteOrder): Float =
|
||||||
if (endian == ByteOrder.BIG_ENDIAN) _delegateBuf.readFloat() else _delegateBuf.readFloatLe()
|
if (endian == ByteOrder.BIG_ENDIAN) _delegateBuf.readFloat() else _delegateBuf.readFloatLe()
|
||||||
|
|
||||||
public actual fun readBytes(length: Int): ByteArray = _delegateBuf.readByteArray(length)
|
public actual suspend fun readBytes(length: Int): ByteArray = _delegateBuf.readByteArray(length)
|
||||||
public actual fun readBoolean(): Boolean = _delegateBuf.readByte() != 0x00.toByte()
|
public actual suspend fun readBoolean(): Boolean = _delegateBuf.readByte() != 0x00.toByte()
|
||||||
public actual fun readRemainingBytes(): ByteArray = this.toByteArray()
|
public actual suspend fun readRemainingBytes(): ByteArray = this.toByteArray()
|
||||||
|
|
||||||
public actual fun toByteArray(): ByteArray {
|
public actual suspend fun toByteArray(): ByteArray {
|
||||||
val copy = _delegateBuf.peek()
|
val copy = _delegateBuf.peek()
|
||||||
return try {
|
return try {
|
||||||
copy.readByteArray()
|
copy.readByteArray()
|
||||||
@@ -76,8 +76,8 @@ public actual class BytesBuffer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public actual fun hasRemaining(): Boolean = !_delegateBuf.exhausted()
|
public actual suspend fun hasRemaining(): Boolean = !_delegateBuf.exhausted()
|
||||||
public actual fun close(): Unit = _delegateBuf.close()
|
public actual suspend fun close(): Unit = _delegateBuf.close()
|
||||||
|
|
||||||
public actual val size: Int get() = _delegateBuf.size.toInt()
|
public actual val size: Int get() = _delegateBuf.size.toInt()
|
||||||
public actual val remaining: Long get() = _delegateBuf.remaining
|
public actual val remaining: Long get() = _delegateBuf.remaining
|
||||||
+11
-12
@@ -4,11 +4,10 @@
|
|||||||
* Date: 2026/9/3
|
* Date: 2026/9/3
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package cn.rtast.libmc.common
|
package cn.rtast.libmc.common.stream
|
||||||
|
|
||||||
import io.ktor.utils.io.*
|
import io.ktor.utils.io.*
|
||||||
import io.ktor.utils.io.bits.*
|
import io.ktor.utils.io.bits.*
|
||||||
import kotlinx.coroutines.runBlocking
|
|
||||||
|
|
||||||
public actual open class ReadChannel public actual constructor() {
|
public actual open class ReadChannel public actual constructor() {
|
||||||
|
|
||||||
@@ -18,18 +17,18 @@ public actual open class ReadChannel public actual constructor() {
|
|||||||
this._readChannel = readChannel
|
this._readChannel = readChannel
|
||||||
}
|
}
|
||||||
|
|
||||||
public actual open fun readByte(): Byte = runBlocking { _readChannel.readByte() }
|
public actual open suspend fun readByte(): Byte = _readChannel.readByte()
|
||||||
public actual open fun readBytes(length: Int): ByteArray = runBlocking { _readChannel.readByteArray(length) }
|
public actual open suspend fun readBytes(length: Int): ByteArray = _readChannel.readByteArray(length)
|
||||||
public actual open fun readFully(out: ByteArray, start: Int, end: Int): Unit =
|
public actual open suspend fun readFully(out: ByteArray, start: Int, end: Int): Unit =
|
||||||
runBlocking { _readChannel.readFully(out, start, end) }
|
_readChannel.readFully(out, start, end)
|
||||||
|
|
||||||
public actual open fun readShort(endian: ByteOrder): Short {
|
public actual open suspend fun readShort(endian: ByteOrder): Short {
|
||||||
val bytes = readBytes(2)
|
val bytes = readBytes(2)
|
||||||
val v = ((bytes[0].toInt() and 0xFF shl 8) or (bytes[1].toInt() and 0xFF)).toShort()
|
val v = ((bytes[0].toInt() and 0xFF shl 8) or (bytes[1].toInt() and 0xFF)).toShort()
|
||||||
return if (endian == ByteOrder.BIG_ENDIAN) v else v.reverseByteOrder()
|
return if (endian == ByteOrder.BIG_ENDIAN) v else v.reverseByteOrder()
|
||||||
}
|
}
|
||||||
|
|
||||||
public actual open fun readInt(endian: ByteOrder): Int {
|
public actual open suspend fun readInt(endian: ByteOrder): Int {
|
||||||
val bytes = readBytes(4)
|
val bytes = readBytes(4)
|
||||||
val v = (bytes[0].toInt() and 0xFF shl 24) or
|
val v = (bytes[0].toInt() and 0xFF shl 24) or
|
||||||
(bytes[1].toInt() and 0xFF shl 16) or
|
(bytes[1].toInt() and 0xFF shl 16) or
|
||||||
@@ -38,7 +37,7 @@ public actual open class ReadChannel public actual constructor() {
|
|||||||
return if (endian == ByteOrder.BIG_ENDIAN) v else v.reverseByteOrder()
|
return if (endian == ByteOrder.BIG_ENDIAN) v else v.reverseByteOrder()
|
||||||
}
|
}
|
||||||
|
|
||||||
public actual open fun readLong(endian: ByteOrder): Long {
|
public actual open suspend fun readLong(endian: ByteOrder): Long {
|
||||||
val bytes = readBytes(8)
|
val bytes = readBytes(8)
|
||||||
var v = 0L
|
var v = 0L
|
||||||
for (i in 0 until 8) {
|
for (i in 0 until 8) {
|
||||||
@@ -55,8 +54,8 @@ public actual open class WriteChannel public actual constructor() {
|
|||||||
_writeChannel = writeChannel
|
_writeChannel = writeChannel
|
||||||
}
|
}
|
||||||
|
|
||||||
public actual open fun writeFully(value: ByteArray, startIndex: Int, endIndex: Int): Unit =
|
public actual open suspend fun writeFully(value: ByteArray, startIndex: Int, endIndex: Int): Unit =
|
||||||
runBlocking { _writeChannel.writeFully(value, startIndex, endIndex) }
|
_writeChannel.writeFully(value, startIndex, endIndex)
|
||||||
|
|
||||||
public actual open fun flush(): Unit = runBlocking { _writeChannel.flush() }
|
public actual open suspend fun flush(): Unit = _writeChannel.flush()
|
||||||
}
|
}
|
||||||
+4
-3
@@ -4,8 +4,9 @@
|
|||||||
* Date: 2026/9/3
|
* Date: 2026/9/3
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package cn.rtast.libmc.common
|
package cn.rtast.libmc.common.stream
|
||||||
|
|
||||||
|
import cn.rtast.libmc.common.LibMCContext
|
||||||
import io.ktor.network.sockets.*
|
import io.ktor.network.sockets.*
|
||||||
import io.ktor.utils.io.core.*
|
import io.ktor.utils.io.core.*
|
||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.runBlocking
|
||||||
@@ -32,10 +33,10 @@ public actual class UdpSocket public actual constructor(host: String, port: Int,
|
|||||||
private val socket = runBlocking { aSocket(ctx._selectorManager).udp().bind() }
|
private val socket = runBlocking { aSocket(ctx._selectorManager).udp().bind() }
|
||||||
private val remoteAddress = InetSocketAddress(host, port)
|
private val remoteAddress = InetSocketAddress(host, port)
|
||||||
|
|
||||||
public actual fun sendAndReceive(data: ByteArray): ByteArray = runBlocking {
|
public actual suspend fun sendAndReceive(data: ByteArray): ByteArray {
|
||||||
val packet = buildPacket { writeFully(data) }
|
val packet = buildPacket { writeFully(data) }
|
||||||
socket.send(Datagram(packet, remoteAddress))
|
socket.send(Datagram(packet, remoteAddress))
|
||||||
socket.receive().packet.readByteArray()
|
return socket.receive().packet.readByteArray()
|
||||||
}
|
}
|
||||||
|
|
||||||
public actual fun close() {
|
public actual fun close() {
|
||||||
@@ -7,8 +7,8 @@
|
|||||||
|
|
||||||
package cn.rtast.libmc.mcping.bedrock
|
package cn.rtast.libmc.mcping.bedrock
|
||||||
|
|
||||||
import cn.rtast.libmc.common.BytesBuffer
|
import cn.rtast.libmc.common.stream.BytesBuffer
|
||||||
import cn.rtast.libmc.common.PacketCodec
|
import cn.rtast.libmc.common.packet.PacketCodec
|
||||||
import kotlin.random.Random
|
import kotlin.random.Random
|
||||||
|
|
||||||
private val RAKNET_MAGIC = byteArrayOf(
|
private val RAKNET_MAGIC = byteArrayOf(
|
||||||
@@ -33,14 +33,14 @@ internal data class BedrockRequestPacket(
|
|||||||
override val packetId: Byte = 0x01
|
override val packetId: Byte = 0x01
|
||||||
|
|
||||||
companion object Codec : PacketCodec<BedrockRequestPacket> {
|
companion object Codec : PacketCodec<BedrockRequestPacket> {
|
||||||
override fun encode(buffer: BytesBuffer, value: BedrockRequestPacket) {
|
override suspend fun encode(buffer: BytesBuffer, value: BedrockRequestPacket) {
|
||||||
buffer.writeByte(value.packetId)
|
buffer.writeByte(value.packetId)
|
||||||
buffer.writeLong(value.time)
|
buffer.writeLong(value.time)
|
||||||
buffer.writeBytes(value.magic)
|
buffer.writeBytes(value.magic)
|
||||||
buffer.writeLong(value.guid)
|
buffer.writeLong(value.guid)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun decode(buffer: BytesBuffer): BedrockRequestPacket = throw UnsupportedOperationException()
|
override suspend fun decode(buffer: BytesBuffer): BedrockRequestPacket = throw UnsupportedOperationException()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun equals(other: Any?): Boolean {
|
override fun equals(other: Any?): Boolean {
|
||||||
@@ -72,8 +72,8 @@ internal data class BedrockResponsePacket(
|
|||||||
) : MinecraftBedrockPacket {
|
) : MinecraftBedrockPacket {
|
||||||
|
|
||||||
companion object Codec : PacketCodec<BedrockResponsePacket> {
|
companion object Codec : PacketCodec<BedrockResponsePacket> {
|
||||||
override fun encode(buffer: BytesBuffer, value: BedrockResponsePacket) = throw UnsupportedOperationException()
|
override suspend fun encode(buffer: BytesBuffer, value: BedrockResponsePacket) = throw UnsupportedOperationException()
|
||||||
override fun decode(buffer: BytesBuffer): BedrockResponsePacket {
|
override suspend fun decode(buffer: BytesBuffer): BedrockResponsePacket {
|
||||||
val packetId = buffer.readByte()
|
val packetId = buffer.readByte()
|
||||||
if (packetId != 0x1C.toByte()) throw IllegalStateException("Expected pong id 0x1C, got $packetId")
|
if (packetId != 0x1C.toByte()) throw IllegalStateException("Expected pong id 0x1C, got $packetId")
|
||||||
val time = buffer.readLong()
|
val time = buffer.readLong()
|
||||||
|
|||||||
@@ -7,12 +7,12 @@
|
|||||||
|
|
||||||
package cn.rtast.libmc.mcping.bedrock
|
package cn.rtast.libmc.mcping.bedrock
|
||||||
|
|
||||||
import cn.rtast.libmc.common.BytesBuffer
|
import cn.rtast.libmc.common.stream.BytesBuffer
|
||||||
import cn.rtast.libmc.common.PacketCodec
|
import cn.rtast.libmc.common.packet.PacketCodec
|
||||||
import cn.rtast.libmc.common.UdpSocket
|
import cn.rtast.libmc.common.stream.UdpSocket
|
||||||
|
|
||||||
|
|
||||||
internal fun <T : MinecraftBedrockPacket> UdpSocket.sendPacket(packet: T, codec: PacketCodec<T>): ByteArray {
|
internal suspend fun <T : MinecraftBedrockPacket> UdpSocket.sendPacket(packet: T, codec: PacketCodec<T>): ByteArray {
|
||||||
val buf = BytesBuffer()
|
val buf = BytesBuffer()
|
||||||
codec.encode(buf, packet)
|
codec.encode(buf, packet)
|
||||||
return sendAndReceive(buf.toByteArray())
|
return sendAndReceive(buf.toByteArray())
|
||||||
|
|||||||
@@ -8,12 +8,12 @@
|
|||||||
package cn.rtast.libmc.mcping.bedrock
|
package cn.rtast.libmc.mcping.bedrock
|
||||||
|
|
||||||
import cn.rtast.libmc.common.LibMCContext
|
import cn.rtast.libmc.common.LibMCContext
|
||||||
import cn.rtast.libmc.common.UdpSocket
|
import cn.rtast.libmc.common.stream.UdpSocket
|
||||||
import cn.rtast.libmc.common.wrap
|
import cn.rtast.libmc.common.stream.wrap
|
||||||
import cn.rtast.libmc.mcping.PingResponse
|
import cn.rtast.libmc.mcping.PingResponse
|
||||||
import kotlin.time.Clock
|
import kotlin.time.Clock
|
||||||
|
|
||||||
internal fun pingBedrockServer(host: String, port: Int, context: LibMCContext): PingResponse {
|
internal suspend fun pingBedrockServer(host: String, port: Int, context: LibMCContext): PingResponse {
|
||||||
val socket = UdpSocket(host, port, context)
|
val socket = UdpSocket(host, port, context)
|
||||||
return try {
|
return try {
|
||||||
val sendTime = Clock.System.now().toEpochMilliseconds()
|
val sendTime = Clock.System.now().toEpochMilliseconds()
|
||||||
|
|||||||
@@ -7,10 +7,10 @@
|
|||||||
|
|
||||||
package cn.rtast.libmc.mcping.java
|
package cn.rtast.libmc.mcping.java
|
||||||
|
|
||||||
import cn.rtast.libmc.common.BytesBuffer
|
import cn.rtast.libmc.common.stream.BytesBuffer
|
||||||
import cn.rtast.libmc.common.McStringCodec
|
import cn.rtast.libmc.common.primitives.McStringCodec
|
||||||
import cn.rtast.libmc.common.PacketCodec
|
import cn.rtast.libmc.common.packet.PacketCodec
|
||||||
import cn.rtast.libmc.common.VarIntCodec
|
import cn.rtast.libmc.common.primitives.VarIntCodec
|
||||||
import cn.rtast.libmc.common.packet.MinecraftPacket
|
import cn.rtast.libmc.common.packet.MinecraftPacket
|
||||||
|
|
||||||
// ref https://minecraft.wiki/w/Java_Edition_protocol/Packets#Handshake
|
// ref https://minecraft.wiki/w/Java_Edition_protocol/Packets#Handshake
|
||||||
@@ -22,30 +22,30 @@ internal data class HandshakePacket(
|
|||||||
val nextState: Int,
|
val nextState: Int,
|
||||||
) : MinecraftPacket {
|
) : MinecraftPacket {
|
||||||
companion object Codec : PacketCodec<HandshakePacket> {
|
companion object Codec : PacketCodec<HandshakePacket> {
|
||||||
override fun encode(buffer: BytesBuffer, value: HandshakePacket) {
|
override suspend fun encode(buffer: BytesBuffer, value: HandshakePacket) {
|
||||||
VarIntCodec.encode(buffer, value.protocolVersion)
|
VarIntCodec.encode(buffer, value.protocolVersion)
|
||||||
McStringCodec.encode(buffer, value.serverAddress)
|
McStringCodec.encode(buffer, value.serverAddress)
|
||||||
buffer.writeShort(value.serverPort.toShort())
|
buffer.writeShort(value.serverPort.toShort())
|
||||||
VarIntCodec.encode(buffer, value.nextState)
|
VarIntCodec.encode(buffer, value.nextState)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun decode(buffer: BytesBuffer): HandshakePacket = throw UnsupportedOperationException()
|
override suspend fun decode(buffer: BytesBuffer): HandshakePacket = throw UnsupportedOperationException()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ref https://minecraft.wiki/w/Java_Edition_protocol/Packets#Status
|
// ref https://minecraft.wiki/w/Java_Edition_protocol/Packets#Status
|
||||||
internal data object StatusRequestPacket : MinecraftPacket, PacketCodec<StatusRequestPacket> {
|
internal data object StatusRequestPacket : MinecraftPacket, PacketCodec<StatusRequestPacket> {
|
||||||
override fun encode(buffer: BytesBuffer, value: StatusRequestPacket) {}
|
override suspend fun encode(buffer: BytesBuffer, value: StatusRequestPacket) {}
|
||||||
override fun decode(buffer: BytesBuffer): StatusRequestPacket = throw UnsupportedOperationException()
|
override suspend fun decode(buffer: BytesBuffer): StatusRequestPacket = throw UnsupportedOperationException()
|
||||||
}
|
}
|
||||||
|
|
||||||
internal data class PingPacket(val currentTime: Long) : MinecraftPacket {
|
internal data class PingPacket(val currentTime: Long) : MinecraftPacket {
|
||||||
companion object : PacketCodec<PingPacket> {
|
companion object : PacketCodec<PingPacket> {
|
||||||
override fun encode(buffer: BytesBuffer, value: PingPacket) {
|
override suspend fun encode(buffer: BytesBuffer, value: PingPacket) {
|
||||||
buffer.writeLong(value.currentTime)
|
buffer.writeLong(value.currentTime)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun decode(buffer: BytesBuffer): PingPacket {
|
override suspend fun decode(buffer: BytesBuffer): PingPacket {
|
||||||
return PingPacket(buffer.readLong())
|
return PingPacket(buffer.readLong())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,11 +8,15 @@
|
|||||||
package cn.rtast.libmc.mcping.java
|
package cn.rtast.libmc.mcping.java
|
||||||
|
|
||||||
import cn.rtast.libmc.common.*
|
import cn.rtast.libmc.common.*
|
||||||
|
import cn.rtast.libmc.common.primitives.McStringCodec
|
||||||
|
import cn.rtast.libmc.common.primitives.VarIntCodec
|
||||||
|
import cn.rtast.libmc.common.stream.Socket
|
||||||
|
import cn.rtast.libmc.common.stream.readPacketFrame
|
||||||
import cn.rtast.libmc.mcping.PingResponse
|
import cn.rtast.libmc.mcping.PingResponse
|
||||||
import cn.rtast.libmc.mcping.sendPacket
|
import cn.rtast.libmc.mcping.sendPacket
|
||||||
import kotlin.time.Clock
|
import kotlin.time.Clock
|
||||||
|
|
||||||
internal fun pingJavaServer(host: String, port: Int, context: LibMCContext): PingResponse {
|
internal suspend 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 receiveChannel = socket.openReadChannel()
|
||||||
val sendChannel = socket.openWriteChannel()
|
val sendChannel = socket.openWriteChannel()
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ import kotlin.jvm.JvmName
|
|||||||
import kotlin.jvm.JvmOverloads
|
import kotlin.jvm.JvmOverloads
|
||||||
|
|
||||||
@JvmOverloads
|
@JvmOverloads
|
||||||
public fun mcping(
|
public suspend fun mcping(
|
||||||
host: String,
|
host: String,
|
||||||
port: Int,
|
port: Int,
|
||||||
type: ServerType = ServerType.Java,
|
type: ServerType = ServerType.Java,
|
||||||
|
|||||||
@@ -7,15 +7,19 @@
|
|||||||
|
|
||||||
package cn.rtast.libmc.mcping
|
package cn.rtast.libmc.mcping
|
||||||
|
|
||||||
import cn.rtast.libmc.common.*
|
import cn.rtast.libmc.common.stream.BytesBuffer
|
||||||
|
import cn.rtast.libmc.common.primitives.VarIntCodec
|
||||||
|
import cn.rtast.libmc.common.stream.WriteChannel
|
||||||
import cn.rtast.libmc.common.packet.MinecraftPacket
|
import cn.rtast.libmc.common.packet.MinecraftPacket
|
||||||
|
import cn.rtast.libmc.common.packet.PacketCodec
|
||||||
|
import cn.rtast.libmc.common.packet.writeBuffer
|
||||||
|
|
||||||
public fun <T : MinecraftPacket> WriteChannel.sendPacket(packet: T, packetId: Int, codec: PacketCodec<T>) {
|
public suspend fun <T : MinecraftPacket> WriteChannel.sendPacket(packet: T, packetId: Int, codec: PacketCodec<T>) {
|
||||||
val bodyBuffer = BytesBuffer()
|
val bodyBuffer = BytesBuffer()
|
||||||
bodyBuffer.write(packetId, VarIntCodec)
|
VarIntCodec.encode(bodyBuffer, packetId)
|
||||||
codec.encode(bodyBuffer, packet)
|
codec.encode(bodyBuffer, packet)
|
||||||
val frameBuffer = BytesBuffer()
|
val frameBuffer = BytesBuffer()
|
||||||
frameBuffer.write(bodyBuffer.size, VarIntCodec)
|
VarIntCodec.encode(bodyBuffer, bodyBuffer.size)
|
||||||
frameBuffer.writeBuffer(bodyBuffer)
|
frameBuffer.writeBuffer(bodyBuffer)
|
||||||
val bytes = frameBuffer.toByteArray()
|
val bytes = frameBuffer.toByteArray()
|
||||||
this.writeFully(bytes, 0, bytes.size)
|
this.writeFully(bytes, 0, bytes.size)
|
||||||
|
|||||||
@@ -7,12 +7,12 @@
|
|||||||
|
|
||||||
package cn.rtast.libmc.nbt
|
package cn.rtast.libmc.nbt
|
||||||
|
|
||||||
import cn.rtast.libmc.common.ByteOrder
|
import cn.rtast.libmc.common.stream.ByteOrder
|
||||||
import cn.rtast.libmc.common.BytesBuffer
|
import cn.rtast.libmc.common.stream.BytesBuffer
|
||||||
|
|
||||||
public class BytesBufferNBTInput(override val order: ByteOrder, private val buffer: BytesBuffer) : NBTInput {
|
public class BytesBufferNBTInput(override val order: ByteOrder, private val buffer: BytesBuffer) : NBTInput {
|
||||||
override fun readByte(): Byte = buffer.readByte()
|
override suspend fun readByte(): Byte = buffer.readByte()
|
||||||
override fun readBytes(count: Int): ByteArray = buffer.readBytes(count)
|
override suspend fun readBytes(count: Int): ByteArray = buffer.readBytes(count)
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun BytesBuffer.toNBTInput(order: ByteOrder = ByteOrder.BIG_ENDIAN): BytesBufferNBTInput =
|
public fun BytesBuffer.toNBTInput(order: ByteOrder = ByteOrder.BIG_ENDIAN): BytesBufferNBTInput =
|
||||||
|
|||||||
@@ -7,17 +7,17 @@
|
|||||||
|
|
||||||
package cn.rtast.libmc.nbt
|
package cn.rtast.libmc.nbt
|
||||||
|
|
||||||
import cn.rtast.libmc.common.ByteOrder
|
import cn.rtast.libmc.common.stream.ByteOrder
|
||||||
import cn.rtast.libmc.common.BytesBuffer
|
import cn.rtast.libmc.common.stream.BytesBuffer
|
||||||
|
|
||||||
public class BytesBufferNBTOutput(
|
public class BytesBufferNBTOutput(
|
||||||
override val order: ByteOrder,
|
override val order: ByteOrder,
|
||||||
override val root: NBTTag.CompoundTag,
|
override val root: NBTTag.CompoundTag,
|
||||||
private val buffer: BytesBuffer,
|
private val buffer: BytesBuffer,
|
||||||
) : NBTOutput {
|
) : NBTOutput {
|
||||||
override fun writeByte(value: Byte): Unit = buffer.writeByte(value)
|
override suspend fun writeByte(value: Byte): Unit = buffer.writeByte(value)
|
||||||
override fun writeBytes(value: ByteArray): Unit = buffer.writeBytes(value)
|
override suspend fun writeBytes(value: ByteArray): Unit = buffer.writeBytes(value)
|
||||||
override fun toByteArray(): ByteArray = buffer.toByteArray()
|
override suspend fun toByteArray(): ByteArray = buffer.toByteArray()
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun BytesBuffer.toNBTOutput(
|
public fun BytesBuffer.toNBTOutput(
|
||||||
|
|||||||
@@ -7,33 +7,33 @@
|
|||||||
|
|
||||||
package cn.rtast.libmc.nbt
|
package cn.rtast.libmc.nbt
|
||||||
|
|
||||||
import cn.rtast.libmc.common.ByteOrder
|
import cn.rtast.libmc.common.stream.ByteOrder
|
||||||
|
|
||||||
public interface NBTInput {
|
public interface NBTInput {
|
||||||
public val order: ByteOrder
|
public val order: ByteOrder
|
||||||
|
|
||||||
public fun readByte(): Byte
|
public suspend fun readByte(): Byte
|
||||||
public fun readBytes(count: Int): ByteArray
|
public suspend fun readBytes(count: Int): ByteArray
|
||||||
|
|
||||||
public fun readLong(): Long = if (order == ByteOrder.BIG_ENDIAN) readLongBE() else readLongLE()
|
public suspend fun readLong(): Long = if (order == ByteOrder.BIG_ENDIAN) readLongBE() else readLongLE()
|
||||||
public fun readFloat(): Float = if (order == ByteOrder.BIG_ENDIAN) readFloatBE() else readFloatLE()
|
public suspend fun readFloat(): Float = if (order == ByteOrder.BIG_ENDIAN) readFloatBE() else readFloatLE()
|
||||||
public fun readDouble(): Double = if (order == ByteOrder.BIG_ENDIAN) readDoubleBE() else readDoubleLE()
|
public suspend fun readDouble(): Double = if (order == ByteOrder.BIG_ENDIAN) readDoubleBE() else readDoubleLE()
|
||||||
public fun readShort(): Short = if (order == ByteOrder.BIG_ENDIAN) readShortBE() else readShortLE()
|
public suspend fun readShort(): Short = if (order == ByteOrder.BIG_ENDIAN) readShortBE() else readShortLE()
|
||||||
public fun readInt(): Int = if (order == ByteOrder.BIG_ENDIAN) readIntBE() else readIntLE()
|
public suspend fun readInt(): Int = if (order == ByteOrder.BIG_ENDIAN) readIntBE() else readIntLE()
|
||||||
|
|
||||||
// big endian
|
// big endian
|
||||||
public fun readLongBE(): Long =
|
public suspend fun readLongBE(): Long =
|
||||||
(readIntBE().toLong() shl 32) or (readIntBE().toLong() and 0xFFFFFFFFL)
|
(readIntBE().toLong() shl 32) or (readIntBE().toLong() and 0xFFFFFFFFL)
|
||||||
|
|
||||||
public fun readFloatBE(): Float = Float.fromBits(readIntBE())
|
public suspend fun readFloatBE(): Float = Float.fromBits(readIntBE())
|
||||||
public fun readDoubleBE(): Double = Double.fromBits(readLongBE())
|
public suspend fun readDoubleBE(): Double = Double.fromBits(readLongBE())
|
||||||
public fun readShortBE(): Short {
|
public suspend fun readShortBE(): Short {
|
||||||
val b1 = readByte().toInt() and 0xFF
|
val b1 = readByte().toInt() and 0xFF
|
||||||
val b2 = readByte().toInt() and 0xFF
|
val b2 = readByte().toInt() and 0xFF
|
||||||
return ((b1 shl 8) or b2).toShort()
|
return ((b1 shl 8) or b2).toShort()
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun readIntBE(): Int {
|
public suspend fun readIntBE(): Int {
|
||||||
return ((readByte().toInt() and 0xFF) shl 24) or
|
return ((readByte().toInt() and 0xFF) shl 24) or
|
||||||
((readByte().toInt() and 0xFF) shl 16) or
|
((readByte().toInt() and 0xFF) shl 16) or
|
||||||
((readByte().toInt() and 0xFF) shl 8) or
|
((readByte().toInt() and 0xFF) shl 8) or
|
||||||
@@ -41,7 +41,7 @@ public interface NBTInput {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// little endian
|
// little endian
|
||||||
public fun readLongLE(): Long {
|
public suspend fun readLongLE(): Long {
|
||||||
return ((readByte().toInt() and 0xFF).toLong() shl 0) or
|
return ((readByte().toInt() and 0xFF).toLong() shl 0) or
|
||||||
((readByte().toInt() and 0xFF).toLong() shl 8) or
|
((readByte().toInt() and 0xFF).toLong() shl 8) or
|
||||||
((readByte().toInt() and 0xFF).toLong() shl 16) or
|
((readByte().toInt() and 0xFF).toLong() shl 16) or
|
||||||
@@ -52,14 +52,14 @@ public interface NBTInput {
|
|||||||
(readByte().toInt() and 0xFF).toLong()
|
(readByte().toInt() and 0xFF).toLong()
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun readFloatLE(): Float = Float.fromBits(readIntLE())
|
public suspend fun readFloatLE(): Float = Float.fromBits(readIntLE())
|
||||||
|
|
||||||
public fun readDoubleLE(): Double = Double.fromBits(readLongLE())
|
public suspend fun readDoubleLE(): Double = Double.fromBits(readLongLE())
|
||||||
|
|
||||||
public fun readShortLE(): Short =
|
public suspend fun readShortLE(): Short =
|
||||||
((readByte().toInt() and 0xFF) or (readByte().toInt() and 0xFF shl 8)).toShort()
|
((readByte().toInt() and 0xFF) or (readByte().toInt() and 0xFF shl 8)).toShort()
|
||||||
|
|
||||||
public fun readIntLE(): Int =
|
public suspend fun readIntLE(): Int =
|
||||||
((readByte().toInt() and 0xFF)) or
|
((readByte().toInt() and 0xFF)) or
|
||||||
((readByte().toInt() and 0xFF) shl 8) or
|
((readByte().toInt() and 0xFF) shl 8) or
|
||||||
((readByte().toInt() and 0xFF) shl 16) or
|
((readByte().toInt() and 0xFF) shl 16) or
|
||||||
|
|||||||
@@ -7,44 +7,44 @@
|
|||||||
|
|
||||||
package cn.rtast.libmc.nbt
|
package cn.rtast.libmc.nbt
|
||||||
|
|
||||||
import cn.rtast.libmc.common.ByteOrder
|
import cn.rtast.libmc.common.stream.ByteOrder
|
||||||
|
|
||||||
public interface NBTOutput {
|
public interface NBTOutput {
|
||||||
public val order: ByteOrder
|
public val order: ByteOrder
|
||||||
public val root: NBTTag.CompoundTag
|
public val root: NBTTag.CompoundTag
|
||||||
|
|
||||||
public fun writeByte(value: Byte)
|
public suspend fun writeByte(value: Byte)
|
||||||
public fun writeBytes(value: ByteArray)
|
public suspend fun writeBytes(value: ByteArray)
|
||||||
|
|
||||||
public fun writeShort(value: Short): Unit =
|
public suspend fun writeShort(value: Short): Unit =
|
||||||
if (order == ByteOrder.BIG_ENDIAN) writeShortBE(value) else writeShortLE(value)
|
if (order == ByteOrder.BIG_ENDIAN) writeShortBE(value) else writeShortLE(value)
|
||||||
|
|
||||||
public fun writeInt(value: Int): Unit =
|
public suspend fun writeInt(value: Int): Unit =
|
||||||
if (order == ByteOrder.BIG_ENDIAN) writeIntBE(value) else writeIntLE(value)
|
if (order == ByteOrder.BIG_ENDIAN) writeIntBE(value) else writeIntLE(value)
|
||||||
|
|
||||||
public fun writeLong(value: Long): Unit =
|
public suspend fun writeLong(value: Long): Unit =
|
||||||
if (order == ByteOrder.BIG_ENDIAN) writeLongBE(value) else writeLongLE(value)
|
if (order == ByteOrder.BIG_ENDIAN) writeLongBE(value) else writeLongLE(value)
|
||||||
|
|
||||||
public fun writeFloat(value: Float): Unit =
|
public suspend fun writeFloat(value: Float): Unit =
|
||||||
if (order == ByteOrder.BIG_ENDIAN) writeFloatBE(value) else writeFloatLE(value)
|
if (order == ByteOrder.BIG_ENDIAN) writeFloatBE(value) else writeFloatLE(value)
|
||||||
|
|
||||||
public fun writeDouble(value: Double): Unit =
|
public suspend fun writeDouble(value: Double): Unit =
|
||||||
if (order == ByteOrder.BIG_ENDIAN) writeDoubleBE(value) else writeDoubleLE(value)
|
if (order == ByteOrder.BIG_ENDIAN) writeDoubleBE(value) else writeDoubleLE(value)
|
||||||
|
|
||||||
// big endian
|
// big endian
|
||||||
public fun writeShortBE(value: Short) {
|
public suspend fun writeShortBE(value: Short) {
|
||||||
writeByte(((value.toInt() shr 8) and 0xFF).toByte())
|
writeByte(((value.toInt() shr 8) and 0xFF).toByte())
|
||||||
writeByte((value.toInt() and 0xFF).toByte())
|
writeByte((value.toInt() and 0xFF).toByte())
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun writeIntBE(value: Int) {
|
public suspend fun writeIntBE(value: Int) {
|
||||||
writeByte(((value shr 24) and 0xFF).toByte())
|
writeByte(((value shr 24) and 0xFF).toByte())
|
||||||
writeByte(((value shr 16) and 0xFF).toByte())
|
writeByte(((value shr 16) and 0xFF).toByte())
|
||||||
writeByte(((value shr 8) and 0xFF).toByte())
|
writeByte(((value shr 8) and 0xFF).toByte())
|
||||||
writeByte((value and 0xFF).toByte())
|
writeByte((value and 0xFF).toByte())
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun writeLongBE(value: Long) {
|
public suspend fun writeLongBE(value: Long) {
|
||||||
writeByte(((value shr 56).toInt() and 0xFF).toByte())
|
writeByte(((value shr 56).toInt() and 0xFF).toByte())
|
||||||
writeByte(((value shr 48).toInt() and 0xFF).toByte())
|
writeByte(((value shr 48).toInt() and 0xFF).toByte())
|
||||||
writeByte(((value shr 40).toInt() and 0xFF).toByte())
|
writeByte(((value shr 40).toInt() and 0xFF).toByte())
|
||||||
@@ -55,28 +55,28 @@ public interface NBTOutput {
|
|||||||
writeByte((value.toInt() and 0xFF).toByte())
|
writeByte((value.toInt() and 0xFF).toByte())
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun writeFloatBE(value: Float) {
|
public suspend fun writeFloatBE(value: Float) {
|
||||||
writeIntBE(value.toBits())
|
writeIntBE(value.toBits())
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun writeDoubleBE(value: Double) {
|
public suspend fun writeDoubleBE(value: Double) {
|
||||||
writeLongBE(value.toBits())
|
writeLongBE(value.toBits())
|
||||||
}
|
}
|
||||||
|
|
||||||
// Little Endian
|
// Little Endian
|
||||||
public fun writeShortLE(value: Short) {
|
public suspend fun writeShortLE(value: Short) {
|
||||||
writeByte((value.toInt() and 0xFF).toByte())
|
writeByte((value.toInt() and 0xFF).toByte())
|
||||||
writeByte(((value.toInt() shr 8) and 0xFF).toByte())
|
writeByte(((value.toInt() shr 8) and 0xFF).toByte())
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun writeIntLE(value: Int) {
|
public suspend fun writeIntLE(value: Int) {
|
||||||
writeByte((value and 0xFF).toByte())
|
writeByte((value and 0xFF).toByte())
|
||||||
writeByte(((value shr 8) and 0xFF).toByte())
|
writeByte(((value shr 8) and 0xFF).toByte())
|
||||||
writeByte(((value shr 16) and 0xFF).toByte())
|
writeByte(((value shr 16) and 0xFF).toByte())
|
||||||
writeByte(((value shr 24) and 0xFF).toByte())
|
writeByte(((value shr 24) and 0xFF).toByte())
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun writeLongLE(value: Long) {
|
public suspend fun writeLongLE(value: Long) {
|
||||||
writeByte(((value and 0xFF).toInt()).toByte())
|
writeByte(((value and 0xFF).toInt()).toByte())
|
||||||
writeByte((((value shr 8) and 0xFF).toInt()).toByte())
|
writeByte((((value shr 8) and 0xFF).toInt()).toByte())
|
||||||
writeByte((((value shr 16) and 0xFF).toInt()).toByte())
|
writeByte((((value shr 16) and 0xFF).toInt()).toByte())
|
||||||
@@ -87,10 +87,7 @@ public interface NBTOutput {
|
|||||||
writeByte((((value shr 56) and 0xFF).toInt()).toByte())
|
writeByte((((value shr 56) and 0xFF).toInt()).toByte())
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun writeFloatLE(value: Float): Unit = writeIntLE(value.toBits())
|
public suspend fun writeFloatLE(value: Float): Unit = writeIntLE(value.toBits())
|
||||||
|
public suspend fun writeDoubleLE(value: Double): Unit = writeLongLE(value.toBits())
|
||||||
public fun writeDoubleLE(value: Double): Unit = writeLongLE(value.toBits())
|
public suspend fun toByteArray(): ByteArray
|
||||||
|
|
||||||
|
|
||||||
public fun toByteArray(): ByteArray
|
|
||||||
}
|
}
|
||||||
@@ -7,13 +7,13 @@
|
|||||||
|
|
||||||
package cn.rtast.libmc.nbt
|
package cn.rtast.libmc.nbt
|
||||||
|
|
||||||
public fun NBTInput.readStringTag(): String {
|
public suspend fun NBTInput.readStringTag(): String {
|
||||||
val length = readShort().toInt() and 0xFFFF
|
val length = readShort().toInt() and 0xFFFF
|
||||||
val bytes = readBytes(length)
|
val bytes = readBytes(length)
|
||||||
return bytes.decodeToString()
|
return bytes.decodeToString()
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun NBTInput.readListTag(): NBTTag.ListTag {
|
public suspend fun NBTInput.readListTag(): NBTTag.ListTag {
|
||||||
val elementTypeId = readByte().toInt() and 0xFF
|
val elementTypeId = readByte().toInt() and 0xFF
|
||||||
val elementType = NBTType.fromID(elementTypeId)
|
val elementType = NBTType.fromID(elementTypeId)
|
||||||
val length = readInt()
|
val length = readInt()
|
||||||
@@ -22,7 +22,7 @@ public fun NBTInput.readListTag(): NBTTag.ListTag {
|
|||||||
return NBTTag.ListTag(elementType, list)
|
return NBTTag.ListTag(elementType, list)
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun NBTInput.readCompoundTag(): NBTTag.CompoundTag {
|
public suspend fun NBTInput.readCompoundTag(): NBTTag.CompoundTag {
|
||||||
val map = LinkedHashMap<String, NBTTag>()
|
val map = LinkedHashMap<String, NBTTag>()
|
||||||
while (true) {
|
while (true) {
|
||||||
val typeId = readByte().toInt() and 0xFF
|
val typeId = readByte().toInt() and 0xFF
|
||||||
@@ -35,7 +35,7 @@ public fun NBTInput.readCompoundTag(): NBTTag.CompoundTag {
|
|||||||
return NBTTag.CompoundTag(map)
|
return NBTTag.CompoundTag(map)
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun NBTInput.readTagPayload(type: NBTType): NBTTag =
|
public suspend fun NBTInput.readTagPayload(type: NBTType): NBTTag =
|
||||||
when (type) {
|
when (type) {
|
||||||
NBTType.Byte -> NBTTag.ByteTag(readByte())
|
NBTType.Byte -> NBTTag.ByteTag(readByte())
|
||||||
NBTType.Short -> NBTTag.ShortTag(readShort())
|
NBTType.Short -> NBTTag.ShortTag(readShort())
|
||||||
@@ -52,7 +52,7 @@ public fun NBTInput.readTagPayload(type: NBTType): NBTTag =
|
|||||||
NBTType.End -> error("TAG_End no payload")
|
NBTType.End -> error("TAG_End no payload")
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun NBTInput.readCompound(): NBTTag {
|
public suspend fun NBTInput.readCompound(): NBTTag {
|
||||||
val map = LinkedHashMap<String, NBTTag>()
|
val map = LinkedHashMap<String, NBTTag>()
|
||||||
while (true) {
|
while (true) {
|
||||||
val typeId = readByte().toInt()
|
val typeId = readByte().toInt()
|
||||||
@@ -67,7 +67,7 @@ public fun NBTInput.readCompound(): NBTTag {
|
|||||||
return NBTTag.ListTag(NBTType.Compound, map.values.toMutableList())
|
return NBTTag.ListTag(NBTType.Compound, map.values.toMutableList())
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun NBTInput.readRootCompound(): NBTCompound {
|
public suspend fun NBTInput.readRootCompound(): NBTCompound {
|
||||||
val rootType = NBTType.fromID(readByte().toInt())
|
val rootType = NBTType.fromID(readByte().toInt())
|
||||||
require(rootType == NBTType.Compound) { "Root tag must be TAG_Compound" }
|
require(rootType == NBTType.Compound) { "Root tag must be TAG_Compound" }
|
||||||
val nameLen = readShort().toInt() and 0xFFFF
|
val nameLen = readShort().toInt() and 0xFFFF
|
||||||
@@ -76,7 +76,7 @@ public fun NBTInput.readRootCompound(): NBTCompound {
|
|||||||
return NBTCompound(name, root)
|
return NBTCompound(name, root)
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun NBTInput.readNetworkCompound(): NBTCompound {
|
public suspend fun NBTInput.readNetworkCompound(): NBTCompound {
|
||||||
return when (val type = NBTType.fromID(readByte().toInt() and 0xFF)) {
|
return when (val type = NBTType.fromID(readByte().toInt() and 0xFF)) {
|
||||||
NBTType.Compound -> NBTCompound("", readCompoundTag())
|
NBTType.Compound -> NBTCompound("", readCompoundTag())
|
||||||
NBTType.String -> NBTCompound("", NBTTag.CompoundTag(linkedMapOf("text" to NBTTag.StringTag(readStringTag()))))
|
NBTType.String -> NBTCompound("", NBTTag.CompoundTag(linkedMapOf("text" to NBTTag.StringTag(readStringTag()))))
|
||||||
|
|||||||
@@ -8,13 +8,13 @@
|
|||||||
package cn.rtast.libmc.nbt
|
package cn.rtast.libmc.nbt
|
||||||
|
|
||||||
|
|
||||||
public fun NBTOutput.writeStringTag(value: String) {
|
public suspend fun NBTOutput.writeStringTag(value: String) {
|
||||||
val bytes = value.encodeToByteArray()
|
val bytes = value.encodeToByteArray()
|
||||||
writeShort(bytes.size.toShort())
|
writeShort(bytes.size.toShort())
|
||||||
writeBytes(bytes)
|
writeBytes(bytes)
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun NBTOutput.writeTagPayload(tag: NBTTag) {
|
public suspend fun NBTOutput.writeTagPayload(tag: NBTTag) {
|
||||||
when (tag) {
|
when (tag) {
|
||||||
is NBTTag.ByteTag -> writeByte(tag.value)
|
is NBTTag.ByteTag -> writeByte(tag.value)
|
||||||
is NBTTag.ShortTag -> writeShort(tag.value)
|
is NBTTag.ShortTag -> writeShort(tag.value)
|
||||||
@@ -56,14 +56,14 @@ public fun NBTOutput.writeTagPayload(tag: NBTTag) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun NBTOutput.writeRootNBTCompound(name: String = ""): ByteArray {
|
public suspend fun NBTOutput.writeRootNBTCompound(name: String = ""): ByteArray {
|
||||||
writeByte(NBTType.Compound.id)
|
writeByte(NBTType.Compound.id)
|
||||||
writeStringTag(name)
|
writeStringTag(name)
|
||||||
writeTagPayload(root)
|
writeTagPayload(root)
|
||||||
return toByteArray()
|
return toByteArray()
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun NBTOutput.writeNetworkCompound(compound: NBTCompound) {
|
public suspend fun NBTOutput.writeNetworkCompound(compound: NBTCompound) {
|
||||||
val compoundTag = compound.element as? NBTTag.CompoundTag
|
val compoundTag = compound.element as? NBTTag.CompoundTag
|
||||||
?: throw IllegalArgumentException("NBTCompound element must be an NBTTag.CompoundTag")
|
?: throw IllegalArgumentException("NBTCompound element must be an NBTTag.CompoundTag")
|
||||||
writeByte(NBTType.Compound.id)
|
writeByte(NBTType.Compound.id)
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
package test
|
package test
|
||||||
|
|
||||||
import cn.rtast.libmc.common.wrap
|
import cn.rtast.libmc.common.stream.wrap
|
||||||
import cn.rtast.libmc.nbt.NbtReader
|
import cn.rtast.libmc.nbt.NbtReader
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|||||||
@@ -0,0 +1,21 @@
|
|||||||
|
# libmc-protocol-encrypt
|
||||||
|
|
||||||
|
This module implemented `ProtocolCryptoContext` and provided a `DefaultProtocolCryptoContext`.
|
||||||
|
|
||||||
|
## Get started
|
||||||
|
|
||||||
|
> `Sha1`, `RSA1024`, `AES-128-CFB8` from `cryptography-kotlin`(and its based provider).
|
||||||
|
> `HTTP Client` from `ktor-client`
|
||||||
|
|
||||||
|
> Before start, you need to add a `ktor client engine` for your platform. For JVM, `ktor-client-okhttp`(JVM 1.8+)
|
||||||
|
> or `ktor-client-java`(JVM 11+), for Linux, use `ktor-client-curl`, for Windows, use `ktor-client-winhttp`,
|
||||||
|
> for Apple, use `ktor-client-darwin`
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
fun main() {
|
||||||
|
val cli = createMinecraftClient(
|
||||||
|
// ... other paramater
|
||||||
|
crypto = DefaultProtocolCryptoContext
|
||||||
|
)
|
||||||
|
}
|
||||||
|
```
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
|
||||||
|
|
||||||
|
kotlin {
|
||||||
|
explicitApi()
|
||||||
|
withSourcesJar()
|
||||||
|
|
||||||
|
linuxX64()
|
||||||
|
linuxArm64()
|
||||||
|
macosArm64()
|
||||||
|
mingwX64()
|
||||||
|
jvm { compilerOptions.jvmTarget = JvmTarget.JVM_1_8 }
|
||||||
|
|
||||||
|
sourceSets {
|
||||||
|
commonMain.dependencies {
|
||||||
|
api(project(":common"))
|
||||||
|
implementation(libs.cryptography.core)
|
||||||
|
implementation(libs.cryptography.provider.optimal)
|
||||||
|
implementation(libs.ktor.client.core)
|
||||||
|
}
|
||||||
|
|
||||||
|
jvmTest.dependencies {
|
||||||
|
implementation(libs.ktor.client.okhttp)
|
||||||
|
}
|
||||||
|
|
||||||
|
linuxTest.dependencies {
|
||||||
|
implementation(libs.ktor.client.curl)
|
||||||
|
}
|
||||||
|
|
||||||
|
mingwTest.dependencies {
|
||||||
|
implementation(libs.ktor.client.winhttp)
|
||||||
|
}
|
||||||
|
|
||||||
|
appleTest.dependencies {
|
||||||
|
implementation(libs.ktor.client.darwin)
|
||||||
|
}
|
||||||
|
|
||||||
|
commonTest.dependencies {
|
||||||
|
implementation(kotlin("test"))
|
||||||
|
implementation(project(":protocol"))
|
||||||
|
implementation(libs.kotlinx.coroutines.test)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+48
@@ -0,0 +1,48 @@
|
|||||||
|
/*
|
||||||
|
* Copyright © 2026 RTAkland
|
||||||
|
* Author: RTAkland
|
||||||
|
* Date: 2026/9/7
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
@file:OptIn(DelicateCryptographyApi::class)
|
||||||
|
|
||||||
|
package cn.rtast.libmc.protocol.crypto
|
||||||
|
|
||||||
|
import cn.rtast.libmc.common.crypto.NetworkCipher
|
||||||
|
import dev.whyoleg.cryptography.DelicateCryptographyApi
|
||||||
|
import dev.whyoleg.cryptography.algorithms.AES
|
||||||
|
|
||||||
|
public class AesCFB8Cipher(sharedKey: ByteArray) : NetworkCipher {
|
||||||
|
private val encryptIv = sharedKey.copyOf()
|
||||||
|
private val decryptIv = sharedKey.copyOf()
|
||||||
|
|
||||||
|
private val cipher = provider.get(AES.CFB8)
|
||||||
|
.keyDecoder()
|
||||||
|
.decodeFromByteArrayBlocking(AES.Key.Format.RAW, sharedKey)
|
||||||
|
.cipher()
|
||||||
|
|
||||||
|
override suspend fun encrypt(buffer: ByteArray, offset: Int, length: Int) {
|
||||||
|
val plaintext = buffer.copyOfRange(offset, offset + length)
|
||||||
|
val ciphertext = cipher.encryptWithIvBlocking(encryptIv, plaintext)
|
||||||
|
ciphertext.copyInto(buffer, destinationOffset = offset)
|
||||||
|
updateIv(encryptIv, ciphertext)
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun decrypt(buffer: ByteArray, offset: Int, length: Int) {
|
||||||
|
val ciphertext = buffer.copyOfRange(offset, offset + length)
|
||||||
|
val plaintext = cipher.decryptWithIvBlocking(decryptIv, ciphertext)
|
||||||
|
plaintext.copyInto(buffer, destinationOffset = offset)
|
||||||
|
updateIv(decryptIv, ciphertext)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun updateIv(iv: ByteArray, ciphertext: ByteArray) {
|
||||||
|
val len = ciphertext.size
|
||||||
|
if (len >= iv.size) {
|
||||||
|
ciphertext.copyInto(iv, destinationOffset = 0, startIndex = len - iv.size, endIndex = len)
|
||||||
|
} else {
|
||||||
|
iv.copyInto(iv, destinationOffset = 0, startIndex = len, endIndex = iv.size)
|
||||||
|
ciphertext.copyInto(iv, destinationOffset = iv.size - len)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+31
@@ -0,0 +1,31 @@
|
|||||||
|
/*
|
||||||
|
* Copyright © 2026 RTAkland
|
||||||
|
* Author: RTAkland
|
||||||
|
* Date: 2026/9/7
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
package cn.rtast.libmc.protocol.crypto
|
||||||
|
|
||||||
|
import cn.rtast.libmc.common.crypto.AuthenticationProvider
|
||||||
|
import cn.rtast.libmc.common.crypto.ProtocolContextBuilder
|
||||||
|
import cn.rtast.libmc.common.crypto.RSA1024Encryptor
|
||||||
|
import cn.rtast.libmc.common.crypto.Sha1Hasher
|
||||||
|
import io.ktor.client.*
|
||||||
|
import io.ktor.client.request.*
|
||||||
|
import io.ktor.http.*
|
||||||
|
|
||||||
|
private val httpClient = HttpClient()
|
||||||
|
|
||||||
|
public val DefaultProtocolCryptoContext: ProtocolContextBuilder.() -> Unit = {
|
||||||
|
rsaEncryptor = RSA1024Encryptor { key, data -> rsaEncrypt(key, data) }
|
||||||
|
sha1Hasher = Sha1Hasher { serverId, secretKey, publicKey -> minecraftServerIdHash(serverId, secretKey, publicKey) }
|
||||||
|
cipherFactory = { key -> AesCFB8Cipher(key) }
|
||||||
|
authProvider = AuthenticationProvider { url, accessToken, uuid, serverIdHash ->
|
||||||
|
val status = httpClient.post(url) {
|
||||||
|
headers { header("Content-Type", "application/json") }
|
||||||
|
setBody("{\"accessToken\":\"$accessToken\", \"selectedProfile\":\"$uuid\", \"serverId\":\"$serverIdHash\"}")
|
||||||
|
}.status
|
||||||
|
require(status == HttpStatusCode.NoContent)
|
||||||
|
}
|
||||||
|
}
|
||||||
+24
@@ -0,0 +1,24 @@
|
|||||||
|
/*
|
||||||
|
* Copyright © 2026 RTAkland
|
||||||
|
* Author: RTAkland
|
||||||
|
* Date: 2026/9/7
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
@file:OptIn(DelicateCryptographyApi::class)
|
||||||
|
|
||||||
|
package cn.rtast.libmc.protocol.crypto
|
||||||
|
|
||||||
|
import dev.whyoleg.cryptography.CryptographyProvider
|
||||||
|
import dev.whyoleg.cryptography.DelicateCryptographyApi
|
||||||
|
import dev.whyoleg.cryptography.algorithms.RSA
|
||||||
|
import dev.whyoleg.cryptography.algorithms.SHA1
|
||||||
|
|
||||||
|
internal val provider = CryptographyProvider.Default
|
||||||
|
|
||||||
|
public suspend fun rsaEncrypt(publicKeyBytes: ByteArray, data: ByteArray): ByteArray {
|
||||||
|
val provider = CryptographyProvider.Default
|
||||||
|
val rsa = provider.get(RSA.PKCS1)
|
||||||
|
val publicKey = rsa.publicKeyDecoder(SHA1).decodeFromByteArray(RSA.PublicKey.Format.DER, publicKeyBytes)
|
||||||
|
return publicKey.encryptor().encrypt(data)
|
||||||
|
}
|
||||||
+41
@@ -0,0 +1,41 @@
|
|||||||
|
/*
|
||||||
|
* Copyright © 2026 RTAkland
|
||||||
|
* Author: RTAkland
|
||||||
|
* Date: 2026/9/7
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
@file:OptIn(DelicateCryptographyApi::class)
|
||||||
|
|
||||||
|
package cn.rtast.libmc.protocol.crypto
|
||||||
|
|
||||||
|
import dev.whyoleg.cryptography.DelicateCryptographyApi
|
||||||
|
import dev.whyoleg.cryptography.algorithms.SHA1
|
||||||
|
|
||||||
|
public suspend fun minecraftServerIdHash(serverId: String, secretKey: ByteArray, publicKey: ByteArray): String {
|
||||||
|
val serverIdBytes = serverId.encodeToByteArray()
|
||||||
|
for (b in serverIdBytes) require((b.toInt() and 0xFF) <= 0x7F) { "serverId contains non-US-ASCII character" }
|
||||||
|
val data = serverIdBytes + secretKey + publicKey
|
||||||
|
val hash = provider.get(SHA1).hasher().hash(data)
|
||||||
|
return mcDigestToString(hash)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun mcDigestToString(digest: ByteArray): String {
|
||||||
|
val isNegative = (digest[0].toInt() and 0x80) != 0
|
||||||
|
val bytes = if (isNegative) twosComplement(digest) else digest
|
||||||
|
var hex = bytes.joinToString("") { (it.toInt() and 0xFF).toString(16).padStart(2, '0') }
|
||||||
|
hex = hex.trimStart('0')
|
||||||
|
if (hex.isEmpty()) hex = "0"
|
||||||
|
return if (isNegative) "-$hex" else hex
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun twosComplement(bytes: ByteArray): ByteArray {
|
||||||
|
val result = ByteArray(bytes.size)
|
||||||
|
var carry = 1
|
||||||
|
for (i in bytes.size - 1 downTo 0) {
|
||||||
|
val inverted = (bytes[i].toInt().inv() and 0xFF) + carry
|
||||||
|
result[i] = (inverted and 0xFF).toByte()
|
||||||
|
carry = inverted ushr 8
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
/*
|
||||||
|
* Copyright © 2026 RTAkland
|
||||||
|
* Author: RTAkland
|
||||||
|
* Date: 2026/9/7
|
||||||
|
*/
|
||||||
|
|
||||||
|
package test
|
||||||
|
|
||||||
|
import cn.rtast.libmc.protocol.client.createMinecraftClient
|
||||||
|
import cn.rtast.libmc.protocol.crypto.DefaultProtocolCryptoContext
|
||||||
|
import cn.rtast.libmc.protocol.packet.login.clientbound.ClientboundLoginSuccessPacket
|
||||||
|
import cn.rtast.libmc.protocol.packet.play.clientbound.ClientboundSystemChatMessagePacket
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import org.junit.Test
|
||||||
|
import java.io.File
|
||||||
|
import kotlin.uuid.Uuid
|
||||||
|
|
||||||
|
|
||||||
|
class TestJvmClient {
|
||||||
|
|
||||||
|
val accessToken = File("src/commonTest/resources/accessToken.txt").readText()
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `test default protocol context`() {
|
||||||
|
val cli = createMinecraftClient(
|
||||||
|
"127.0.0.1",
|
||||||
|
25565,
|
||||||
|
"RTAkland",
|
||||||
|
// generateOfflineUuid("RTAkland"),
|
||||||
|
Uuid.parse("bb033844-e68e-4909-a636-1a5d1821ddc4"),
|
||||||
|
// null,
|
||||||
|
accessToken,
|
||||||
|
crypto = DefaultProtocolCryptoContext
|
||||||
|
)
|
||||||
|
cli.on<ClientboundSystemChatMessagePacket> { println(it) }
|
||||||
|
cli.on<ClientboundLoginSuccessPacket> { println(it) }
|
||||||
|
cli.launch { cli.connect() }
|
||||||
|
while (true) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -14,7 +14,6 @@ kotlin {
|
|||||||
commonMain.dependencies {
|
commonMain.dependencies {
|
||||||
api(project(":common"))
|
api(project(":common"))
|
||||||
api(project(":nbt"))
|
api(project(":nbt"))
|
||||||
api(libs.kotlinx.coroutines)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
jvmMain.dependencies {
|
jvmMain.dependencies {
|
||||||
@@ -27,8 +26,7 @@ kotlin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
jvmTest.dependencies {
|
jvmTest.dependencies {
|
||||||
implementation(libs.ktor.client.core)
|
implementation(project(":protocol-encrypt"))
|
||||||
implementation(libs.ktor.client.okhttp)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+3
-3
@@ -7,8 +7,8 @@
|
|||||||
package cn.rtast.libmc.protocol.client
|
package cn.rtast.libmc.protocol.client
|
||||||
|
|
||||||
import cn.rtast.libmc.common.LibMCContext
|
import cn.rtast.libmc.common.LibMCContext
|
||||||
import cn.rtast.libmc.protocol.crypto.ProtocolContext
|
import cn.rtast.libmc.common.crypto.ProtocolContext
|
||||||
import cn.rtast.libmc.protocol.crypto.ProtocolContextBuilder
|
import cn.rtast.libmc.common.crypto.ProtocolContextBuilder
|
||||||
import cn.rtast.libmc.protocol.event.InternalPacketDispatcher
|
import cn.rtast.libmc.protocol.event.InternalPacketDispatcher
|
||||||
import cn.rtast.libmc.protocol.event.PacketEventDispatcher
|
import cn.rtast.libmc.protocol.event.PacketEventDispatcher
|
||||||
import cn.rtast.libmc.protocol.network.NetworkChannel
|
import cn.rtast.libmc.protocol.network.NetworkChannel
|
||||||
@@ -56,7 +56,7 @@ public class MinecraftClient internal constructor(
|
|||||||
override val coroutineContext: CoroutineContext
|
override val coroutineContext: CoroutineContext
|
||||||
get() = clientJob + ioDispatcher + CoroutineName("LibMC-MinecraftClient-$username")
|
get() = clientJob + ioDispatcher + CoroutineName("LibMC-MinecraftClient-$username")
|
||||||
|
|
||||||
public fun connect(protocolVersion: Int = 776) {
|
public suspend fun connect(protocolVersion: Int = 776) {
|
||||||
networkChannel.connect()
|
networkChannel.connect()
|
||||||
startListening()
|
startListening()
|
||||||
networkChannel.sendPacket(
|
networkChannel.sendPacket(
|
||||||
|
|||||||
@@ -1,13 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright © 2026 RTAkland
|
|
||||||
* Author: RTAkland
|
|
||||||
* Date: 2026/9/7
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
package cn.rtast.libmc.protocol.crypto
|
|
||||||
|
|
||||||
public interface NetworkCipher {
|
|
||||||
public fun encrypt(buffer: ByteArray, offset: Int, length: Int)
|
|
||||||
public fun decrypt(buffer: ByteArray, offset: Int, length: Int)
|
|
||||||
}
|
|
||||||
+6
-31
@@ -19,7 +19,7 @@ import cn.rtast.libmc.protocol.packet.play.serverbound.ServerboundConfigurationA
|
|||||||
import cn.rtast.libmc.protocol.packet.play.serverbound.ServerboundKeepAlivePlayPacket
|
import cn.rtast.libmc.protocol.packet.play.serverbound.ServerboundKeepAlivePlayPacket
|
||||||
import cn.rtast.libmc.protocol.packet.play.serverbound.ServerboundPongPlayPacket
|
import cn.rtast.libmc.protocol.packet.play.serverbound.ServerboundPongPlayPacket
|
||||||
import cn.rtast.libmc.protocol.protocol.state.ProtocolState
|
import cn.rtast.libmc.protocol.protocol.state.ProtocolState
|
||||||
import cn.rtast.libmc.protocol.session.AuthenticationProvider
|
import cn.rtast.libmc.common.crypto.AuthenticationProvider
|
||||||
import cn.rtast.libmc.protocol.util.generateRandom16Bytes
|
import cn.rtast.libmc.protocol.util.generateRandom16Bytes
|
||||||
|
|
||||||
public class InternalPacketDispatcher(
|
public class InternalPacketDispatcher(
|
||||||
@@ -31,19 +31,8 @@ public class InternalPacketDispatcher(
|
|||||||
public suspend fun handleIncomingPackets(packet: MinecraftPacket) {
|
public suspend fun handleIncomingPackets(packet: MinecraftPacket) {
|
||||||
this.dispatchEvent(packet)
|
this.dispatchEvent(packet)
|
||||||
when (packet) {
|
when (packet) {
|
||||||
is ClientboundLoginPacket -> this.handleLoginPackets(packet)
|
// login
|
||||||
is ClientboundConfigurationPacket -> this.handleConfigurationPackets(packet)
|
is ClientboundDisconnectLoginPacket -> client.close()
|
||||||
is ClientboundPlayPacket -> this.handlePlayPackets(packet)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private suspend fun handleLoginPackets(packet: ClientboundLoginPacket) {
|
|
||||||
when (packet) {
|
|
||||||
is ClientboundDisconnectLoginPacket -> {
|
|
||||||
println("Login denied: ${packet.reason}")
|
|
||||||
client.close()
|
|
||||||
}
|
|
||||||
|
|
||||||
is ClientboundSetCompressionPacket -> client.networkChannel.setCompression(packet.threshold)
|
is ClientboundSetCompressionPacket -> client.networkChannel.setCompression(packet.threshold)
|
||||||
is ClientboundLoginSuccessPacket -> {
|
is ClientboundLoginSuccessPacket -> {
|
||||||
client.networkChannel.sendPacket(ServerboundLoginAcknowledgedPacket)
|
client.networkChannel.sendPacket(ServerboundLoginAcknowledgedPacket)
|
||||||
@@ -67,13 +56,7 @@ public class InternalPacketDispatcher(
|
|||||||
client.session.enableEncryption(sharedSecret)
|
client.session.enableEncryption(sharedSecret)
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> {}
|
// configuration
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun handleConfigurationPackets(packet: ClientboundConfigurationPacket) {
|
|
||||||
when (packet) {
|
|
||||||
is ClientboundDisconnectConfigurationPacket -> println("Configuration disconnected: ${packet.reason}")
|
|
||||||
ClientboundFinishConfigurationPacket -> {
|
ClientboundFinishConfigurationPacket -> {
|
||||||
client.networkChannel.sendPacket(ServerboundAckFinishConfigurationPacket)
|
client.networkChannel.sendPacket(ServerboundAckFinishConfigurationPacket)
|
||||||
client.stateMachine.transitionTo(ProtocolState.PLAY)
|
client.stateMachine.transitionTo(ProtocolState.PLAY)
|
||||||
@@ -91,24 +74,16 @@ public class InternalPacketDispatcher(
|
|||||||
ServerboundSelectKnownPacksPacket(emptyList())
|
ServerboundSelectKnownPacksPacket(emptyList())
|
||||||
) // TODO empty resource packs list
|
) // TODO empty resource packs list
|
||||||
is ClientboundCodeOfConductPacket -> client.networkChannel.sendPacket(ServerboundAcceptCodeOfConductPacket)
|
is ClientboundCodeOfConductPacket -> client.networkChannel.sendPacket(ServerboundAcceptCodeOfConductPacket)
|
||||||
else -> {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun handlePlayPackets(packet: ClientboundPlayPacket) {
|
// play
|
||||||
when (packet) {
|
|
||||||
is ClientboundDisconnectPlayPacket -> client.close()
|
is ClientboundDisconnectPlayPacket -> client.close()
|
||||||
is ClientboundKeepAlivePlayPacket -> client.networkChannel.sendPacket(ServerboundKeepAlivePlayPacket(id = packet.id))
|
is ClientboundKeepAlivePlayPacket -> client.networkChannel.sendPacket(ServerboundKeepAlivePlayPacket(id = packet.id))
|
||||||
is ClientboundLoginPlayPacket -> println("Successfully joined world Entity ID: ${packet.entityId}")
|
|
||||||
is ClientboundPingPacket -> client.networkChannel.sendPacket(ServerboundPongPlayPacket(packet.id))
|
is ClientboundPingPacket -> client.networkChannel.sendPacket(ServerboundPongPlayPacket(packet.id))
|
||||||
is ClientboundPlayerChatMessagePacket -> println("[Player Chat Message] ${packet.message}")
|
|
||||||
ClientboundStartConfigurationPacket -> {
|
ClientboundStartConfigurationPacket -> {
|
||||||
client.networkChannel.sendPacket(ServerboundConfigurationAcknowledgedPacket)
|
client.networkChannel.sendPacket(ServerboundConfigurationAcknowledgedPacket)
|
||||||
client.stateMachine.transitionTo(ProtocolState.CONFIGURATION)
|
client.stateMachine.transitionTo(ProtocolState.CONFIGURATION)
|
||||||
}
|
}
|
||||||
|
else -> {}
|
||||||
is ClientboundSystemChatMessagePacket -> println("[System message] ${packet.content}")
|
|
||||||
else -> println(packet)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+8
-8
@@ -7,27 +7,27 @@
|
|||||||
|
|
||||||
package cn.rtast.libmc.protocol.network
|
package cn.rtast.libmc.protocol.network
|
||||||
|
|
||||||
import cn.rtast.libmc.common.ReadChannel
|
import cn.rtast.libmc.common.stream.ReadChannel
|
||||||
import cn.rtast.libmc.common.WriteChannel
|
import cn.rtast.libmc.common.stream.WriteChannel
|
||||||
import cn.rtast.libmc.protocol.crypto.NetworkCipher
|
import cn.rtast.libmc.common.crypto.NetworkCipher
|
||||||
|
|
||||||
internal class CipherReadChannel(
|
internal class CipherReadChannel(
|
||||||
private val delegate: ReadChannel,
|
private val delegate: ReadChannel,
|
||||||
private val crypto: NetworkCipher
|
private val crypto: NetworkCipher
|
||||||
) : ReadChannel() {
|
) : ReadChannel() {
|
||||||
override fun readFully(out: ByteArray, start: Int, end: Int) {
|
override suspend fun readFully(out: ByteArray, start: Int, end: Int) {
|
||||||
delegate.readFully(out, start, end)
|
delegate.readFully(out, start, end)
|
||||||
val length = end - start
|
val length = end - start
|
||||||
if (length > 0) crypto.decrypt(out, start, length)
|
if (length > 0) crypto.decrypt(out, start, length)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun readByte(): Byte {
|
override suspend fun readByte(): Byte {
|
||||||
val buf = ByteArray(1)
|
val buf = ByteArray(1)
|
||||||
readFully(buf, 0, 1)
|
readFully(buf, 0, 1)
|
||||||
return buf[0]
|
return buf[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun readBytes(length: Int): ByteArray {
|
override suspend fun readBytes(length: Int): ByteArray {
|
||||||
val bytes = ByteArray(length)
|
val bytes = ByteArray(length)
|
||||||
readFully(bytes, 0, length)
|
readFully(bytes, 0, length)
|
||||||
return bytes
|
return bytes
|
||||||
@@ -38,14 +38,14 @@ internal class CipherWriteChannel(
|
|||||||
private val delegate: WriteChannel,
|
private val delegate: WriteChannel,
|
||||||
private val crypto: NetworkCipher
|
private val crypto: NetworkCipher
|
||||||
) : WriteChannel() {
|
) : WriteChannel() {
|
||||||
override fun writeFully(value: ByteArray, startIndex: Int, endIndex: Int) {
|
override suspend fun writeFully(value: ByteArray, startIndex: Int, endIndex: Int) {
|
||||||
val length = endIndex - startIndex
|
val length = endIndex - startIndex
|
||||||
if (length <= 0) return
|
if (length <= 0) return
|
||||||
val encrypted = value.copyOfRange(startIndex, endIndex)
|
val encrypted = value.copyOfRange(startIndex, endIndex)
|
||||||
crypto.encrypt(encrypted, 0, length)
|
crypto.encrypt(encrypted, 0, length)
|
||||||
delegate.writeFully(encrypted, 0, length)
|
delegate.writeFully(encrypted, 0, length)
|
||||||
}
|
}
|
||||||
override fun flush() {
|
override suspend fun flush() {
|
||||||
delegate.flush()
|
delegate.flush()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+8
-3
@@ -7,9 +7,14 @@
|
|||||||
package cn.rtast.libmc.protocol.network
|
package cn.rtast.libmc.protocol.network
|
||||||
|
|
||||||
import cn.rtast.libmc.common.*
|
import cn.rtast.libmc.common.*
|
||||||
|
import cn.rtast.libmc.common.crypto.NetworkCipher
|
||||||
import cn.rtast.libmc.common.packet.MinecraftPacket
|
import cn.rtast.libmc.common.packet.MinecraftPacket
|
||||||
|
import cn.rtast.libmc.common.packet.writeBuffer
|
||||||
|
import cn.rtast.libmc.common.primitives.readVarInt
|
||||||
|
import cn.rtast.libmc.common.primitives.writeVarInt
|
||||||
|
import cn.rtast.libmc.common.stream.BytesBuffer
|
||||||
|
import cn.rtast.libmc.common.stream.wrap
|
||||||
import cn.rtast.libmc.protocol.client.ClientStateMachine
|
import cn.rtast.libmc.protocol.client.ClientStateMachine
|
||||||
import cn.rtast.libmc.protocol.crypto.NetworkCipher
|
|
||||||
import cn.rtast.libmc.protocol.protocol.GameProtocols
|
import cn.rtast.libmc.protocol.protocol.GameProtocols
|
||||||
import kotlin.concurrent.Volatile
|
import kotlin.concurrent.Volatile
|
||||||
|
|
||||||
@@ -33,7 +38,7 @@ internal class NetworkChannel(
|
|||||||
this.threshold = threshold
|
this.threshold = threshold
|
||||||
}
|
}
|
||||||
|
|
||||||
fun readNextPacket(): MinecraftPacket {
|
suspend fun readNextPacket(): MinecraftPacket {
|
||||||
val packetLength = session.readVarInt()
|
val packetLength = session.readVarInt()
|
||||||
val rawFrameBytes = session.readBytes(packetLength)
|
val rawFrameBytes = session.readBytes(packetLength)
|
||||||
val frameBuf = rawFrameBytes.wrap()
|
val frameBuf = rawFrameBytes.wrap()
|
||||||
@@ -49,7 +54,7 @@ internal class NetworkChannel(
|
|||||||
.decodePacket(packetId, payloadBuf)
|
.decodePacket(packetId, payloadBuf)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun sendPacket(packet: MinecraftPacket) {
|
suspend fun sendPacket(packet: MinecraftPacket) {
|
||||||
val uncompressedBodyBuf = BytesBuffer()
|
val uncompressedBodyBuf = BytesBuffer()
|
||||||
GameProtocols.serverboundGameProtocols
|
GameProtocols.serverboundGameProtocols
|
||||||
.getRegistry(stateMachine.currentState)
|
.getRegistry(stateMachine.currentState)
|
||||||
|
|||||||
+8
-8
@@ -7,10 +7,10 @@
|
|||||||
package cn.rtast.libmc.protocol.network
|
package cn.rtast.libmc.protocol.network
|
||||||
|
|
||||||
import cn.rtast.libmc.common.LibMCContext
|
import cn.rtast.libmc.common.LibMCContext
|
||||||
import cn.rtast.libmc.common.ReadChannel
|
import cn.rtast.libmc.common.stream.ReadChannel
|
||||||
import cn.rtast.libmc.common.Socket
|
import cn.rtast.libmc.common.stream.Socket
|
||||||
import cn.rtast.libmc.common.WriteChannel
|
import cn.rtast.libmc.common.stream.WriteChannel
|
||||||
import cn.rtast.libmc.protocol.crypto.NetworkCipher
|
import cn.rtast.libmc.common.crypto.NetworkCipher
|
||||||
|
|
||||||
internal class NetworkSession(
|
internal class NetworkSession(
|
||||||
private val host: String,
|
private val host: String,
|
||||||
@@ -41,17 +41,17 @@ internal class NetworkSession(
|
|||||||
this.writeChannel = CipherWriteChannel(currentWrite, cipher)
|
this.writeChannel = CipherWriteChannel(currentWrite, cipher)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun readByte(): Byte {
|
suspend fun readByte(): Byte {
|
||||||
val channel = requireNotNull(readChannel) { "ReadChannel not connected" }
|
val channel = requireNotNull(readChannel) { "ReadChannel not connected" }
|
||||||
return channel.readByte()
|
return channel.readByte()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun readBytes(length: Int): ByteArray {
|
suspend fun readBytes(length: Int): ByteArray {
|
||||||
val channel = requireNotNull(readChannel) { "ReadChannel not connected" }
|
val channel = requireNotNull(readChannel) { "ReadChannel not connected" }
|
||||||
return channel.readBytes(length)
|
return channel.readBytes(length)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun readVarInt(): Int {
|
suspend fun readVarInt(): Int {
|
||||||
var numRead = 0
|
var numRead = 0
|
||||||
var result = 0
|
var result = 0
|
||||||
var read: Byte
|
var read: Byte
|
||||||
@@ -65,7 +65,7 @@ internal class NetworkSession(
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
fun writeFully(data: ByteArray) {
|
suspend fun writeFully(data: ByteArray) {
|
||||||
val channel = requireNotNull(writeChannel) { "WriteChannel not connected" }
|
val channel = requireNotNull(writeChannel) { "WriteChannel not connected" }
|
||||||
channel.writeFully(data, 0, data.size)
|
channel.writeFully(data, 0, data.size)
|
||||||
channel.flush()
|
channel.flush()
|
||||||
|
|||||||
+6
-6
@@ -7,20 +7,20 @@
|
|||||||
|
|
||||||
package cn.rtast.libmc.protocol.packet.configuration
|
package cn.rtast.libmc.protocol.packet.configuration
|
||||||
|
|
||||||
import cn.rtast.libmc.common.BytesBuffer
|
import cn.rtast.libmc.common.stream.BytesBuffer
|
||||||
import cn.rtast.libmc.common.PacketCodec
|
import cn.rtast.libmc.common.packet.PacketCodec
|
||||||
import cn.rtast.libmc.common.readMcString
|
import cn.rtast.libmc.common.primitives.readMcString
|
||||||
import cn.rtast.libmc.common.writeMcString
|
import cn.rtast.libmc.common.primitives.writeMcString
|
||||||
|
|
||||||
public data class KnownPacks(val namespace: String, val id: String, val version: String) {
|
public data class KnownPacks(val namespace: String, val id: String, val version: String) {
|
||||||
internal companion object Codec : PacketCodec<KnownPacks> {
|
internal companion object Codec : PacketCodec<KnownPacks> {
|
||||||
override fun encode(buffer: BytesBuffer, value: KnownPacks) {
|
override suspend fun encode(buffer: BytesBuffer, value: KnownPacks) {
|
||||||
buffer.writeMcString(value.namespace)
|
buffer.writeMcString(value.namespace)
|
||||||
buffer.writeMcString(value.id)
|
buffer.writeMcString(value.id)
|
||||||
buffer.writeMcString(value.version)
|
buffer.writeMcString(value.version)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun decode(buffer: BytesBuffer): KnownPacks {
|
override suspend fun decode(buffer: BytesBuffer): KnownPacks {
|
||||||
val namespace = buffer.readMcString()
|
val namespace = buffer.readMcString()
|
||||||
val id = buffer.readMcString()
|
val id = buffer.readMcString()
|
||||||
val version = buffer.readMcString()
|
val version = buffer.readMcString()
|
||||||
|
|||||||
+9
-4
@@ -7,7 +7,12 @@
|
|||||||
|
|
||||||
package cn.rtast.libmc.protocol.packet.configuration.clientbound
|
package cn.rtast.libmc.protocol.packet.configuration.clientbound
|
||||||
|
|
||||||
import cn.rtast.libmc.common.*
|
import cn.rtast.libmc.common.packet.MinecraftPacket
|
||||||
|
import cn.rtast.libmc.common.packet.PacketCodec
|
||||||
|
import cn.rtast.libmc.common.primitives.readMcString
|
||||||
|
import cn.rtast.libmc.common.primitives.readUuid
|
||||||
|
import cn.rtast.libmc.common.primitives.readVarInt
|
||||||
|
import cn.rtast.libmc.common.stream.BytesBuffer
|
||||||
import cn.rtast.libmc.nbt.NBTCompound
|
import cn.rtast.libmc.nbt.NBTCompound
|
||||||
import cn.rtast.libmc.protocol.protocol.util.readNetworkNBTCompound
|
import cn.rtast.libmc.protocol.protocol.util.readNetworkNBTCompound
|
||||||
import kotlin.uuid.Uuid
|
import kotlin.uuid.Uuid
|
||||||
@@ -18,10 +23,10 @@ public data class ClientboundAddResourcePackPacket(
|
|||||||
val hash: String,
|
val hash: String,
|
||||||
val forced: Boolean,
|
val forced: Boolean,
|
||||||
val prompt: NBTCompound,
|
val prompt: NBTCompound,
|
||||||
) : ClientboundConfigurationPacket {
|
) : MinecraftPacket {
|
||||||
internal companion object Codec : PacketCodec<ClientboundAddResourcePackPacket> {
|
internal companion object Codec : PacketCodec<ClientboundAddResourcePackPacket> {
|
||||||
override fun encode(buffer: BytesBuffer, value: ClientboundAddResourcePackPacket) {}
|
override suspend fun encode(buffer: BytesBuffer, value: ClientboundAddResourcePackPacket) {}
|
||||||
override fun decode(buffer: BytesBuffer): ClientboundAddResourcePackPacket {
|
override suspend fun decode(buffer: BytesBuffer): ClientboundAddResourcePackPacket {
|
||||||
val uuid = buffer.readUuid()
|
val uuid = buffer.readUuid()
|
||||||
val url = buffer.readMcString()
|
val url = buffer.readMcString()
|
||||||
val hash = buffer.readMcString()
|
val hash = buffer.readMcString()
|
||||||
|
|||||||
+6
-5
@@ -7,11 +7,12 @@
|
|||||||
|
|
||||||
package cn.rtast.libmc.protocol.packet.configuration.clientbound
|
package cn.rtast.libmc.protocol.packet.configuration.clientbound
|
||||||
|
|
||||||
import cn.rtast.libmc.common.BytesBuffer
|
import cn.rtast.libmc.common.stream.BytesBuffer
|
||||||
import cn.rtast.libmc.common.PacketCodec
|
import cn.rtast.libmc.common.packet.MinecraftPacket
|
||||||
|
import cn.rtast.libmc.common.packet.PacketCodec
|
||||||
|
|
||||||
public data object ClientboundClearDialogPacket : ClientboundConfigurationPacket,
|
public data object ClientboundClearDialogPacket : MinecraftPacket,
|
||||||
PacketCodec<ClientboundClearDialogPacket> {
|
PacketCodec<ClientboundClearDialogPacket> {
|
||||||
override fun encode(buffer: BytesBuffer, value: ClientboundClearDialogPacket) {}
|
override suspend fun encode(buffer: BytesBuffer, value: ClientboundClearDialogPacket) {}
|
||||||
override fun decode(buffer: BytesBuffer): ClientboundClearDialogPacket = ClientboundClearDialogPacket
|
override suspend fun decode(buffer: BytesBuffer): ClientboundClearDialogPacket = ClientboundClearDialogPacket
|
||||||
}
|
}
|
||||||
+7
-6
@@ -7,14 +7,15 @@
|
|||||||
|
|
||||||
package cn.rtast.libmc.protocol.packet.configuration.clientbound
|
package cn.rtast.libmc.protocol.packet.configuration.clientbound
|
||||||
|
|
||||||
import cn.rtast.libmc.common.BytesBuffer
|
import cn.rtast.libmc.common.stream.BytesBuffer
|
||||||
import cn.rtast.libmc.common.PacketCodec
|
import cn.rtast.libmc.common.packet.MinecraftPacket
|
||||||
import cn.rtast.libmc.common.readMcString
|
import cn.rtast.libmc.common.packet.PacketCodec
|
||||||
|
import cn.rtast.libmc.common.primitives.readMcString
|
||||||
|
|
||||||
public data class ClientboundCodeOfConductPacket(val codeOfConduct: String) : ClientboundConfigurationPacket {
|
public data class ClientboundCodeOfConductPacket(val codeOfConduct: String) : MinecraftPacket {
|
||||||
internal companion object Codec : PacketCodec<ClientboundCodeOfConductPacket> {
|
internal companion object Codec : PacketCodec<ClientboundCodeOfConductPacket> {
|
||||||
override fun encode(buffer: BytesBuffer, value: ClientboundCodeOfConductPacket) {}
|
override suspend fun encode(buffer: BytesBuffer, value: ClientboundCodeOfConductPacket) {}
|
||||||
override fun decode(buffer: BytesBuffer): ClientboundCodeOfConductPacket {
|
override suspend fun decode(buffer: BytesBuffer): ClientboundCodeOfConductPacket {
|
||||||
return ClientboundCodeOfConductPacket(buffer.readMcString())
|
return ClientboundCodeOfConductPacket(buffer.readMcString())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
-12
@@ -1,12 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright © 2026 RTAkland
|
|
||||||
* Author: RTAkland
|
|
||||||
* Date: 2026/9/5
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
package cn.rtast.libmc.protocol.packet.configuration.clientbound
|
|
||||||
|
|
||||||
import cn.rtast.libmc.common.packet.MinecraftPacket
|
|
||||||
|
|
||||||
public sealed interface ClientboundConfigurationPacket : MinecraftPacket
|
|
||||||
+6
-5
@@ -7,15 +7,16 @@
|
|||||||
|
|
||||||
package cn.rtast.libmc.protocol.packet.configuration.clientbound
|
package cn.rtast.libmc.protocol.packet.configuration.clientbound
|
||||||
|
|
||||||
import cn.rtast.libmc.common.BytesBuffer
|
import cn.rtast.libmc.common.stream.BytesBuffer
|
||||||
import cn.rtast.libmc.common.PacketCodec
|
import cn.rtast.libmc.common.packet.MinecraftPacket
|
||||||
|
import cn.rtast.libmc.common.packet.PacketCodec
|
||||||
import cn.rtast.libmc.nbt.NBTCompound
|
import cn.rtast.libmc.nbt.NBTCompound
|
||||||
import cn.rtast.libmc.protocol.protocol.util.readNetworkNBTCompound
|
import cn.rtast.libmc.protocol.protocol.util.readNetworkNBTCompound
|
||||||
|
|
||||||
public data class ClientboundConfigurationShowDialogPacket(val dialog: NBTCompound) : ClientboundConfigurationPacket {
|
public data class ClientboundConfigurationShowDialogPacket(val dialog: NBTCompound) : MinecraftPacket {
|
||||||
internal companion object Codec : PacketCodec<ClientboundConfigurationShowDialogPacket> {
|
internal companion object Codec : PacketCodec<ClientboundConfigurationShowDialogPacket> {
|
||||||
override fun encode(buffer: BytesBuffer, value: ClientboundConfigurationShowDialogPacket) {}
|
override suspend fun encode(buffer: BytesBuffer, value: ClientboundConfigurationShowDialogPacket) {}
|
||||||
override fun decode(buffer: BytesBuffer): ClientboundConfigurationShowDialogPacket {
|
override suspend fun decode(buffer: BytesBuffer): ClientboundConfigurationShowDialogPacket {
|
||||||
return ClientboundConfigurationShowDialogPacket(buffer.readNetworkNBTCompound())
|
return ClientboundConfigurationShowDialogPacket(buffer.readNetworkNBTCompound())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+6
-5
@@ -7,15 +7,16 @@
|
|||||||
|
|
||||||
package cn.rtast.libmc.protocol.packet.configuration.clientbound
|
package cn.rtast.libmc.protocol.packet.configuration.clientbound
|
||||||
|
|
||||||
import cn.rtast.libmc.common.BytesBuffer
|
import cn.rtast.libmc.common.stream.BytesBuffer
|
||||||
import cn.rtast.libmc.common.PacketCodec
|
import cn.rtast.libmc.common.packet.MinecraftPacket
|
||||||
|
import cn.rtast.libmc.common.packet.PacketCodec
|
||||||
import cn.rtast.libmc.protocol.protocol.game.Identifier
|
import cn.rtast.libmc.protocol.protocol.game.Identifier
|
||||||
import cn.rtast.libmc.protocol.protocol.game.readIdentifier
|
import cn.rtast.libmc.protocol.protocol.game.readIdentifier
|
||||||
|
|
||||||
public data class ClientboundCookieRequestPacket(val key: Identifier) : ClientboundConfigurationPacket {
|
public data class ClientboundCookieRequestPacket(val key: Identifier) : MinecraftPacket {
|
||||||
internal companion object Codec : PacketCodec<ClientboundCookieRequestPacket> {
|
internal companion object Codec : PacketCodec<ClientboundCookieRequestPacket> {
|
||||||
override fun encode(buffer: BytesBuffer, value: ClientboundCookieRequestPacket) {}
|
override suspend fun encode(buffer: BytesBuffer, value: ClientboundCookieRequestPacket) {}
|
||||||
override fun decode(buffer: BytesBuffer): ClientboundCookieRequestPacket {
|
override suspend fun decode(buffer: BytesBuffer): ClientboundCookieRequestPacket {
|
||||||
return ClientboundCookieRequestPacket(key = buffer.readIdentifier())
|
return ClientboundCookieRequestPacket(key = buffer.readIdentifier())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-4
@@ -7,9 +7,9 @@
|
|||||||
|
|
||||||
package cn.rtast.libmc.protocol.packet.configuration.clientbound
|
package cn.rtast.libmc.protocol.packet.configuration.clientbound
|
||||||
|
|
||||||
import cn.rtast.libmc.common.BytesBuffer
|
import cn.rtast.libmc.common.stream.BytesBuffer
|
||||||
import cn.rtast.libmc.common.PacketCodec
|
|
||||||
import cn.rtast.libmc.common.packet.MinecraftPacket
|
import cn.rtast.libmc.common.packet.MinecraftPacket
|
||||||
|
import cn.rtast.libmc.common.packet.PacketCodec
|
||||||
import cn.rtast.libmc.protocol.protocol.game.Identifier
|
import cn.rtast.libmc.protocol.protocol.game.Identifier
|
||||||
import cn.rtast.libmc.protocol.protocol.game.readIdentifier
|
import cn.rtast.libmc.protocol.protocol.game.readIdentifier
|
||||||
|
|
||||||
@@ -18,8 +18,8 @@ public data class ClientboundCustomPayloadPacket(
|
|||||||
val data: ByteArray,
|
val data: ByteArray,
|
||||||
) : MinecraftPacket {
|
) : MinecraftPacket {
|
||||||
internal companion object Codec : PacketCodec<ClientboundCustomPayloadPacket> {
|
internal companion object Codec : PacketCodec<ClientboundCustomPayloadPacket> {
|
||||||
override fun encode(buffer: BytesBuffer, value: ClientboundCustomPayloadPacket) {}
|
override suspend fun encode(buffer: BytesBuffer, value: ClientboundCustomPayloadPacket) {}
|
||||||
override fun decode(buffer: BytesBuffer): ClientboundCustomPayloadPacket {
|
override suspend fun decode(buffer: BytesBuffer): ClientboundCustomPayloadPacket {
|
||||||
val channel = buffer.readIdentifier()
|
val channel = buffer.readIdentifier()
|
||||||
val data = buffer.readRemainingBytes()
|
val data = buffer.readRemainingBytes()
|
||||||
return ClientboundCustomPayloadPacket(channel, data)
|
return ClientboundCustomPayloadPacket(channel, data)
|
||||||
|
|||||||
+11
-7
@@ -7,18 +7,22 @@
|
|||||||
|
|
||||||
package cn.rtast.libmc.protocol.packet.configuration.clientbound
|
package cn.rtast.libmc.protocol.packet.configuration.clientbound
|
||||||
|
|
||||||
import cn.rtast.libmc.common.*
|
import cn.rtast.libmc.common.stream.BytesBuffer
|
||||||
|
import cn.rtast.libmc.common.packet.MinecraftPacket
|
||||||
|
import cn.rtast.libmc.common.packet.PacketCodec
|
||||||
|
import cn.rtast.libmc.common.primitives.readMcString
|
||||||
|
import cn.rtast.libmc.common.primitives.readVarInt
|
||||||
|
import cn.rtast.libmc.common.primitives.writeMcString
|
||||||
|
|
||||||
public data class ClientboundCustomReportDetailsPacket(val details: List<ReportDetail>) :
|
public data class ClientboundCustomReportDetailsPacket(val details: List<ReportDetail>) : MinecraftPacket {
|
||||||
ClientboundConfigurationPacket {
|
|
||||||
public data class ReportDetail(val title: String, val description: String) {
|
public data class ReportDetail(val title: String, val description: String) {
|
||||||
internal companion object Codec : PacketCodec<ReportDetail> {
|
internal companion object Codec : PacketCodec<ReportDetail> {
|
||||||
override fun encode(buffer: BytesBuffer, value: ReportDetail) {
|
override suspend fun encode(buffer: BytesBuffer, value: ReportDetail) {
|
||||||
buffer.writeMcString(value.title)
|
buffer.writeMcString(value.title)
|
||||||
buffer.writeMcString(value.description)
|
buffer.writeMcString(value.description)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun decode(buffer: BytesBuffer): ReportDetail {
|
override suspend fun decode(buffer: BytesBuffer): ReportDetail {
|
||||||
val title = buffer.readMcString()
|
val title = buffer.readMcString()
|
||||||
val description = buffer.readMcString()
|
val description = buffer.readMcString()
|
||||||
return ReportDetail(title, description)
|
return ReportDetail(title, description)
|
||||||
@@ -27,8 +31,8 @@ public data class ClientboundCustomReportDetailsPacket(val details: List<ReportD
|
|||||||
}
|
}
|
||||||
|
|
||||||
internal companion object Codec : PacketCodec<ClientboundCustomReportDetailsPacket> {
|
internal companion object Codec : PacketCodec<ClientboundCustomReportDetailsPacket> {
|
||||||
override fun encode(buffer: BytesBuffer, value: ClientboundCustomReportDetailsPacket) {}
|
override suspend fun encode(buffer: BytesBuffer, value: ClientboundCustomReportDetailsPacket) {}
|
||||||
override fun decode(buffer: BytesBuffer): ClientboundCustomReportDetailsPacket {
|
override suspend fun decode(buffer: BytesBuffer): ClientboundCustomReportDetailsPacket {
|
||||||
val detailCount = buffer.readVarInt()
|
val detailCount = buffer.readVarInt()
|
||||||
val details = ArrayList<ReportDetail>(detailCount)
|
val details = ArrayList<ReportDetail>(detailCount)
|
||||||
repeat(detailCount) { details.add(ReportDetail.decode(buffer)) }
|
repeat(detailCount) { details.add(ReportDetail.decode(buffer)) }
|
||||||
|
|||||||
+6
-5
@@ -7,15 +7,16 @@
|
|||||||
|
|
||||||
package cn.rtast.libmc.protocol.packet.configuration.clientbound
|
package cn.rtast.libmc.protocol.packet.configuration.clientbound
|
||||||
|
|
||||||
import cn.rtast.libmc.common.BytesBuffer
|
import cn.rtast.libmc.common.stream.BytesBuffer
|
||||||
import cn.rtast.libmc.common.PacketCodec
|
import cn.rtast.libmc.common.packet.MinecraftPacket
|
||||||
|
import cn.rtast.libmc.common.packet.PacketCodec
|
||||||
import cn.rtast.libmc.nbt.NBTCompound
|
import cn.rtast.libmc.nbt.NBTCompound
|
||||||
import cn.rtast.libmc.protocol.protocol.util.readNetworkNBTCompound
|
import cn.rtast.libmc.protocol.protocol.util.readNetworkNBTCompound
|
||||||
|
|
||||||
public data class ClientboundDisconnectConfigurationPacket(val reason: NBTCompound) : ClientboundConfigurationPacket {
|
public data class ClientboundDisconnectConfigurationPacket(val reason: NBTCompound) : MinecraftPacket {
|
||||||
internal companion object Codec : PacketCodec<ClientboundDisconnectConfigurationPacket> {
|
internal companion object Codec : PacketCodec<ClientboundDisconnectConfigurationPacket> {
|
||||||
override fun encode(buffer: BytesBuffer, value: ClientboundDisconnectConfigurationPacket) {}
|
override suspend fun encode(buffer: BytesBuffer, value: ClientboundDisconnectConfigurationPacket) {}
|
||||||
override fun decode(buffer: BytesBuffer): ClientboundDisconnectConfigurationPacket {
|
override suspend fun decode(buffer: BytesBuffer): ClientboundDisconnectConfigurationPacket {
|
||||||
return ClientboundDisconnectConfigurationPacket(reason = buffer.readNetworkNBTCompound())
|
return ClientboundDisconnectConfigurationPacket(reason = buffer.readNetworkNBTCompound())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+6
-5
@@ -7,13 +7,14 @@
|
|||||||
|
|
||||||
package cn.rtast.libmc.protocol.packet.configuration.clientbound
|
package cn.rtast.libmc.protocol.packet.configuration.clientbound
|
||||||
|
|
||||||
import cn.rtast.libmc.common.BytesBuffer
|
import cn.rtast.libmc.common.stream.BytesBuffer
|
||||||
import cn.rtast.libmc.common.PacketCodec
|
import cn.rtast.libmc.common.packet.MinecraftPacket
|
||||||
|
import cn.rtast.libmc.common.packet.PacketCodec
|
||||||
|
|
||||||
public data object ClientboundFinishConfigurationPacket : ClientboundConfigurationPacket,
|
public data object ClientboundFinishConfigurationPacket : MinecraftPacket,
|
||||||
PacketCodec<ClientboundFinishConfigurationPacket> {
|
PacketCodec<ClientboundFinishConfigurationPacket> {
|
||||||
override fun encode(buffer: BytesBuffer, value: ClientboundFinishConfigurationPacket) {}
|
override suspend fun encode(buffer: BytesBuffer, value: ClientboundFinishConfigurationPacket) {}
|
||||||
override fun decode(buffer: BytesBuffer): ClientboundFinishConfigurationPacket {
|
override suspend fun decode(buffer: BytesBuffer): ClientboundFinishConfigurationPacket {
|
||||||
return ClientboundFinishConfigurationPacket
|
return ClientboundFinishConfigurationPacket
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+6
-5
@@ -7,13 +7,14 @@
|
|||||||
|
|
||||||
package cn.rtast.libmc.protocol.packet.configuration.clientbound
|
package cn.rtast.libmc.protocol.packet.configuration.clientbound
|
||||||
|
|
||||||
import cn.rtast.libmc.common.BytesBuffer
|
import cn.rtast.libmc.common.stream.BytesBuffer
|
||||||
import cn.rtast.libmc.common.PacketCodec
|
import cn.rtast.libmc.common.packet.MinecraftPacket
|
||||||
|
import cn.rtast.libmc.common.packet.PacketCodec
|
||||||
|
|
||||||
public data class ClientboundKeepAliveConfigurationPacket(val id: Long) : ClientboundConfigurationPacket {
|
public data class ClientboundKeepAliveConfigurationPacket(val id: Long) : MinecraftPacket {
|
||||||
internal companion object Codec : PacketCodec<ClientboundKeepAliveConfigurationPacket> {
|
internal companion object Codec : PacketCodec<ClientboundKeepAliveConfigurationPacket> {
|
||||||
override fun encode(buffer: BytesBuffer, value: ClientboundKeepAliveConfigurationPacket) {}
|
override suspend fun encode(buffer: BytesBuffer, value: ClientboundKeepAliveConfigurationPacket) {}
|
||||||
override fun decode(buffer: BytesBuffer): ClientboundKeepAliveConfigurationPacket {
|
override suspend fun decode(buffer: BytesBuffer): ClientboundKeepAliveConfigurationPacket {
|
||||||
return ClientboundKeepAliveConfigurationPacket(buffer.readLong())
|
return ClientboundKeepAliveConfigurationPacket(buffer.readLong())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+6
-5
@@ -7,13 +7,14 @@
|
|||||||
|
|
||||||
package cn.rtast.libmc.protocol.packet.configuration.clientbound
|
package cn.rtast.libmc.protocol.packet.configuration.clientbound
|
||||||
|
|
||||||
import cn.rtast.libmc.common.BytesBuffer
|
import cn.rtast.libmc.common.stream.BytesBuffer
|
||||||
import cn.rtast.libmc.common.PacketCodec
|
import cn.rtast.libmc.common.packet.MinecraftPacket
|
||||||
|
import cn.rtast.libmc.common.packet.PacketCodec
|
||||||
|
|
||||||
public data class ClientboundPingConfigurationPacket(val id: Int) : ClientboundConfigurationPacket {
|
public data class ClientboundPingConfigurationPacket(val id: Int) : MinecraftPacket {
|
||||||
internal companion object Codec : PacketCodec<ClientboundPingConfigurationPacket> {
|
internal companion object Codec : PacketCodec<ClientboundPingConfigurationPacket> {
|
||||||
override fun encode(buffer: BytesBuffer, value: ClientboundPingConfigurationPacket) {}
|
override suspend fun encode(buffer: BytesBuffer, value: ClientboundPingConfigurationPacket) {}
|
||||||
override fun decode(buffer: BytesBuffer): ClientboundPingConfigurationPacket {
|
override suspend fun decode(buffer: BytesBuffer): ClientboundPingConfigurationPacket {
|
||||||
return ClientboundPingConfigurationPacket(id = buffer.readInt())
|
return ClientboundPingConfigurationPacket(id = buffer.readInt())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+7
-6
@@ -7,9 +7,10 @@
|
|||||||
|
|
||||||
package cn.rtast.libmc.protocol.packet.configuration.clientbound
|
package cn.rtast.libmc.protocol.packet.configuration.clientbound
|
||||||
|
|
||||||
import cn.rtast.libmc.common.BytesBuffer
|
import cn.rtast.libmc.common.stream.BytesBuffer
|
||||||
import cn.rtast.libmc.common.PacketCodec
|
import cn.rtast.libmc.common.packet.MinecraftPacket
|
||||||
import cn.rtast.libmc.common.readVarInt
|
import cn.rtast.libmc.common.packet.PacketCodec
|
||||||
|
import cn.rtast.libmc.common.primitives.readVarInt
|
||||||
import cn.rtast.libmc.protocol.protocol.game.Identifier
|
import cn.rtast.libmc.protocol.protocol.game.Identifier
|
||||||
import cn.rtast.libmc.protocol.protocol.game.readIdentifier
|
import cn.rtast.libmc.protocol.protocol.game.readIdentifier
|
||||||
import cn.rtast.libmc.protocol.protocol.game.registry.RegistryEntry
|
import cn.rtast.libmc.protocol.protocol.game.registry.RegistryEntry
|
||||||
@@ -20,10 +21,10 @@ public data class ClientboundRegistryDataPacket(
|
|||||||
*/
|
*/
|
||||||
val registryId: Identifier,
|
val registryId: Identifier,
|
||||||
val entries: List<RegistryEntry>,
|
val entries: List<RegistryEntry>,
|
||||||
) : ClientboundConfigurationPacket {
|
) : MinecraftPacket {
|
||||||
internal companion object Codec : PacketCodec<ClientboundRegistryDataPacket> {
|
internal companion object Codec : PacketCodec<ClientboundRegistryDataPacket> {
|
||||||
override fun encode(buffer: BytesBuffer, value: ClientboundRegistryDataPacket) {}
|
override suspend fun encode(buffer: BytesBuffer, value: ClientboundRegistryDataPacket) {}
|
||||||
override fun decode(buffer: BytesBuffer): ClientboundRegistryDataPacket {
|
override suspend fun decode(buffer: BytesBuffer): ClientboundRegistryDataPacket {
|
||||||
val id = buffer.readIdentifier()
|
val id = buffer.readIdentifier()
|
||||||
val entryCount = buffer.readVarInt()
|
val entryCount = buffer.readVarInt()
|
||||||
val entries = ArrayList<RegistryEntry>(entryCount)
|
val entries = ArrayList<RegistryEntry>(entryCount)
|
||||||
|
|||||||
+7
-6
@@ -7,15 +7,16 @@
|
|||||||
|
|
||||||
package cn.rtast.libmc.protocol.packet.configuration.clientbound
|
package cn.rtast.libmc.protocol.packet.configuration.clientbound
|
||||||
|
|
||||||
import cn.rtast.libmc.common.BytesBuffer
|
import cn.rtast.libmc.common.stream.BytesBuffer
|
||||||
import cn.rtast.libmc.common.PacketCodec
|
import cn.rtast.libmc.common.packet.MinecraftPacket
|
||||||
import cn.rtast.libmc.common.readUuid
|
import cn.rtast.libmc.common.packet.PacketCodec
|
||||||
|
import cn.rtast.libmc.common.primitives.readUuid
|
||||||
import kotlin.uuid.Uuid
|
import kotlin.uuid.Uuid
|
||||||
|
|
||||||
public data class ClientboundRemoveResourcePackPacket(val uuid: Uuid) : ClientboundConfigurationPacket {
|
public data class ClientboundRemoveResourcePackPacket(val uuid: Uuid) : MinecraftPacket {
|
||||||
internal companion object Codec : PacketCodec<ClientboundRemoveResourcePackPacket> {
|
internal companion object Codec : PacketCodec<ClientboundRemoveResourcePackPacket> {
|
||||||
override fun encode(buffer: BytesBuffer, value: ClientboundRemoveResourcePackPacket) {}
|
override suspend fun encode(buffer: BytesBuffer, value: ClientboundRemoveResourcePackPacket) {}
|
||||||
override fun decode(buffer: BytesBuffer): ClientboundRemoveResourcePackPacket {
|
override suspend fun decode(buffer: BytesBuffer): ClientboundRemoveResourcePackPacket {
|
||||||
val uuid = buffer.readUuid()
|
val uuid = buffer.readUuid()
|
||||||
return ClientboundRemoveResourcePackPacket(uuid)
|
return ClientboundRemoveResourcePackPacket(uuid)
|
||||||
}
|
}
|
||||||
|
|||||||
+6
-5
@@ -7,11 +7,12 @@
|
|||||||
|
|
||||||
package cn.rtast.libmc.protocol.packet.configuration.clientbound
|
package cn.rtast.libmc.protocol.packet.configuration.clientbound
|
||||||
|
|
||||||
import cn.rtast.libmc.common.BytesBuffer
|
import cn.rtast.libmc.common.stream.BytesBuffer
|
||||||
import cn.rtast.libmc.common.PacketCodec
|
import cn.rtast.libmc.common.packet.MinecraftPacket
|
||||||
|
import cn.rtast.libmc.common.packet.PacketCodec
|
||||||
|
|
||||||
public data object ClientboundResetChatPacket : ClientboundConfigurationPacket,
|
public data object ClientboundResetChatPacket : MinecraftPacket,
|
||||||
PacketCodec<ClientboundResetChatPacket> {
|
PacketCodec<ClientboundResetChatPacket> {
|
||||||
override fun encode(buffer: BytesBuffer, value: ClientboundResetChatPacket) {}
|
override suspend fun encode(buffer: BytesBuffer, value: ClientboundResetChatPacket) {}
|
||||||
override fun decode(buffer: BytesBuffer): ClientboundResetChatPacket = ClientboundResetChatPacket
|
override suspend fun decode(buffer: BytesBuffer): ClientboundResetChatPacket = ClientboundResetChatPacket
|
||||||
}
|
}
|
||||||
+7
-6
@@ -7,15 +7,16 @@
|
|||||||
|
|
||||||
package cn.rtast.libmc.protocol.packet.configuration.clientbound
|
package cn.rtast.libmc.protocol.packet.configuration.clientbound
|
||||||
|
|
||||||
import cn.rtast.libmc.common.BytesBuffer
|
import cn.rtast.libmc.common.stream.BytesBuffer
|
||||||
import cn.rtast.libmc.common.PacketCodec
|
import cn.rtast.libmc.common.packet.MinecraftPacket
|
||||||
import cn.rtast.libmc.common.readVarInt
|
import cn.rtast.libmc.common.packet.PacketCodec
|
||||||
|
import cn.rtast.libmc.common.primitives.readVarInt
|
||||||
import cn.rtast.libmc.protocol.packet.configuration.KnownPacks
|
import cn.rtast.libmc.protocol.packet.configuration.KnownPacks
|
||||||
|
|
||||||
public data class ClientboundSelectKnownPacksPacket(val knownPacks: List<KnownPacks>) : ClientboundConfigurationPacket {
|
public data class ClientboundSelectKnownPacksPacket(val knownPacks: List<KnownPacks>) : MinecraftPacket {
|
||||||
internal companion object Codec : PacketCodec<ClientboundSelectKnownPacksPacket> {
|
internal companion object Codec : PacketCodec<ClientboundSelectKnownPacksPacket> {
|
||||||
override fun encode(buffer: BytesBuffer, value: ClientboundSelectKnownPacksPacket) {}
|
override suspend fun encode(buffer: BytesBuffer, value: ClientboundSelectKnownPacksPacket) {}
|
||||||
override fun decode(buffer: BytesBuffer): ClientboundSelectKnownPacksPacket {
|
override suspend fun decode(buffer: BytesBuffer): ClientboundSelectKnownPacksPacket {
|
||||||
val packsCount = buffer.readVarInt()
|
val packsCount = buffer.readVarInt()
|
||||||
val packs = List(packsCount) { KnownPacks.decode(buffer) }
|
val packs = List(packsCount) { KnownPacks.decode(buffer) }
|
||||||
return ClientboundSelectKnownPacksPacket(packs)
|
return ClientboundSelectKnownPacksPacket(packs)
|
||||||
|
|||||||
+7
-6
@@ -7,15 +7,16 @@
|
|||||||
|
|
||||||
package cn.rtast.libmc.protocol.packet.configuration.clientbound
|
package cn.rtast.libmc.protocol.packet.configuration.clientbound
|
||||||
|
|
||||||
import cn.rtast.libmc.common.BytesBuffer
|
import cn.rtast.libmc.common.stream.BytesBuffer
|
||||||
import cn.rtast.libmc.common.PacketCodec
|
import cn.rtast.libmc.common.packet.MinecraftPacket
|
||||||
import cn.rtast.libmc.common.readVarInt
|
import cn.rtast.libmc.common.packet.PacketCodec
|
||||||
|
import cn.rtast.libmc.common.primitives.readVarInt
|
||||||
import cn.rtast.libmc.protocol.registry.report.ServerLink
|
import cn.rtast.libmc.protocol.registry.report.ServerLink
|
||||||
|
|
||||||
public data class ClientboundServerLinksPacket(val links: List<ServerLink>) : ClientboundConfigurationPacket {
|
public data class ClientboundServerLinksPacket(val links: List<ServerLink>) : MinecraftPacket {
|
||||||
internal companion object Codec : PacketCodec<ClientboundServerLinksPacket> {
|
internal companion object Codec : PacketCodec<ClientboundServerLinksPacket> {
|
||||||
override fun encode(buffer: BytesBuffer, value: ClientboundServerLinksPacket) {}
|
override suspend fun encode(buffer: BytesBuffer, value: ClientboundServerLinksPacket) {}
|
||||||
override fun decode(buffer: BytesBuffer): ClientboundServerLinksPacket {
|
override suspend fun decode(buffer: BytesBuffer): ClientboundServerLinksPacket {
|
||||||
val count = buffer.readVarInt()
|
val count = buffer.readVarInt()
|
||||||
val links = ArrayList<ServerLink>(count)
|
val links = ArrayList<ServerLink>(count)
|
||||||
repeat(count) { links.add(ServerLink.decode(buffer)) }
|
repeat(count) { links.add(ServerLink.decode(buffer)) }
|
||||||
|
|||||||
+7
-6
@@ -7,9 +7,10 @@
|
|||||||
|
|
||||||
package cn.rtast.libmc.protocol.packet.configuration.clientbound
|
package cn.rtast.libmc.protocol.packet.configuration.clientbound
|
||||||
|
|
||||||
import cn.rtast.libmc.common.BytesBuffer
|
import cn.rtast.libmc.common.stream.BytesBuffer
|
||||||
import cn.rtast.libmc.common.PacketCodec
|
import cn.rtast.libmc.common.packet.MinecraftPacket
|
||||||
import cn.rtast.libmc.common.readPrefixedByteArray
|
import cn.rtast.libmc.common.packet.PacketCodec
|
||||||
|
import cn.rtast.libmc.common.primitives.readPrefixedByteArray
|
||||||
import cn.rtast.libmc.protocol.protocol.game.Identifier
|
import cn.rtast.libmc.protocol.protocol.game.Identifier
|
||||||
import cn.rtast.libmc.protocol.protocol.game.readIdentifier
|
import cn.rtast.libmc.protocol.protocol.game.readIdentifier
|
||||||
|
|
||||||
@@ -19,10 +20,10 @@ public data class ClientboundStoreCookiePacket(
|
|||||||
* cookie
|
* cookie
|
||||||
*/
|
*/
|
||||||
val payload: ByteArray,
|
val payload: ByteArray,
|
||||||
) : ClientboundConfigurationPacket {
|
) : MinecraftPacket {
|
||||||
internal companion object Codec : PacketCodec<ClientboundStoreCookiePacket> {
|
internal companion object Codec : PacketCodec<ClientboundStoreCookiePacket> {
|
||||||
override fun encode(buffer: BytesBuffer, value: ClientboundStoreCookiePacket) {}
|
override suspend fun encode(buffer: BytesBuffer, value: ClientboundStoreCookiePacket) {}
|
||||||
override fun decode(buffer: BytesBuffer): ClientboundStoreCookiePacket {
|
override suspend fun decode(buffer: BytesBuffer): ClientboundStoreCookiePacket {
|
||||||
val key = buffer.readIdentifier()
|
val key = buffer.readIdentifier()
|
||||||
val payload = buffer.readPrefixedByteArray()
|
val payload = buffer.readPrefixedByteArray()
|
||||||
return ClientboundStoreCookiePacket(key, payload)
|
return ClientboundStoreCookiePacket(key, payload)
|
||||||
|
|||||||
+8
-7
@@ -7,15 +7,16 @@
|
|||||||
|
|
||||||
package cn.rtast.libmc.protocol.packet.configuration.clientbound
|
package cn.rtast.libmc.protocol.packet.configuration.clientbound
|
||||||
|
|
||||||
import cn.rtast.libmc.common.BytesBuffer
|
import cn.rtast.libmc.common.stream.BytesBuffer
|
||||||
import cn.rtast.libmc.common.PacketCodec
|
import cn.rtast.libmc.common.packet.MinecraftPacket
|
||||||
import cn.rtast.libmc.common.readMcString
|
import cn.rtast.libmc.common.packet.PacketCodec
|
||||||
import cn.rtast.libmc.common.readVarInt
|
import cn.rtast.libmc.common.primitives.readMcString
|
||||||
|
import cn.rtast.libmc.common.primitives.readVarInt
|
||||||
|
|
||||||
public data class ClientboundTransferPacket(val host: String, val port: Int) : ClientboundConfigurationPacket {
|
public data class ClientboundTransferPacket(val host: String, val port: Int) : MinecraftPacket {
|
||||||
internal companion object Codec : PacketCodec<ClientboundTransferPacket> {
|
internal companion object Codec : PacketCodec<ClientboundTransferPacket> {
|
||||||
override fun encode(buffer: BytesBuffer, value: ClientboundTransferPacket) {}
|
override suspend fun encode(buffer: BytesBuffer, value: ClientboundTransferPacket) {}
|
||||||
override fun decode(buffer: BytesBuffer): ClientboundTransferPacket {
|
override suspend fun decode(buffer: BytesBuffer): ClientboundTransferPacket {
|
||||||
val host = buffer.readMcString()
|
val host = buffer.readMcString()
|
||||||
val port = buffer.readVarInt()
|
val port = buffer.readVarInt()
|
||||||
return ClientboundTransferPacket(host, port)
|
return ClientboundTransferPacket(host, port)
|
||||||
|
|||||||
+7
-7
@@ -7,17 +7,17 @@
|
|||||||
|
|
||||||
package cn.rtast.libmc.protocol.packet.configuration.clientbound
|
package cn.rtast.libmc.protocol.packet.configuration.clientbound
|
||||||
|
|
||||||
import cn.rtast.libmc.common.BytesBuffer
|
import cn.rtast.libmc.common.stream.BytesBuffer
|
||||||
import cn.rtast.libmc.common.PacketCodec
|
import cn.rtast.libmc.common.packet.MinecraftPacket
|
||||||
import cn.rtast.libmc.common.readVarInt
|
import cn.rtast.libmc.common.packet.PacketCodec
|
||||||
|
import cn.rtast.libmc.common.primitives.readVarInt
|
||||||
import cn.rtast.libmc.protocol.protocol.game.Identifier
|
import cn.rtast.libmc.protocol.protocol.game.Identifier
|
||||||
import cn.rtast.libmc.protocol.protocol.game.readIdentifier
|
import cn.rtast.libmc.protocol.protocol.game.readIdentifier
|
||||||
|
|
||||||
public data class ClientboundUpdateEnabledFeaturesPacket(val features: List<Identifier>) :
|
public data class ClientboundUpdateEnabledFeaturesPacket(val features: List<Identifier>) : MinecraftPacket {
|
||||||
ClientboundConfigurationPacket {
|
|
||||||
internal companion object Codec : PacketCodec<ClientboundUpdateEnabledFeaturesPacket> {
|
internal companion object Codec : PacketCodec<ClientboundUpdateEnabledFeaturesPacket> {
|
||||||
override fun encode(buffer: BytesBuffer, value: ClientboundUpdateEnabledFeaturesPacket) {}
|
override suspend fun encode(buffer: BytesBuffer, value: ClientboundUpdateEnabledFeaturesPacket) {}
|
||||||
override fun decode(buffer: BytesBuffer): ClientboundUpdateEnabledFeaturesPacket {
|
override suspend fun decode(buffer: BytesBuffer): ClientboundUpdateEnabledFeaturesPacket {
|
||||||
val featureCount = buffer.readVarInt()
|
val featureCount = buffer.readVarInt()
|
||||||
val features = ArrayList<Identifier>(featureCount)
|
val features = ArrayList<Identifier>(featureCount)
|
||||||
repeat(featureCount) { features.add(buffer.readIdentifier()) }
|
repeat(featureCount) { features.add(buffer.readIdentifier()) }
|
||||||
|
|||||||
+12
-11
@@ -7,24 +7,25 @@
|
|||||||
|
|
||||||
package cn.rtast.libmc.protocol.packet.configuration.clientbound
|
package cn.rtast.libmc.protocol.packet.configuration.clientbound
|
||||||
|
|
||||||
import cn.rtast.libmc.common.BytesBuffer
|
import cn.rtast.libmc.common.stream.BytesBuffer
|
||||||
import cn.rtast.libmc.common.PacketCodec
|
import cn.rtast.libmc.common.packet.MinecraftPacket
|
||||||
import cn.rtast.libmc.common.readVarInt
|
import cn.rtast.libmc.common.packet.PacketCodec
|
||||||
import cn.rtast.libmc.common.writeVarInt
|
import cn.rtast.libmc.common.primitives.readVarInt
|
||||||
|
import cn.rtast.libmc.common.primitives.writeVarInt
|
||||||
import cn.rtast.libmc.protocol.protocol.game.Identifier
|
import cn.rtast.libmc.protocol.protocol.game.Identifier
|
||||||
import cn.rtast.libmc.protocol.protocol.game.readIdentifier
|
import cn.rtast.libmc.protocol.protocol.game.readIdentifier
|
||||||
import cn.rtast.libmc.protocol.protocol.game.writeIdentifier
|
import cn.rtast.libmc.protocol.protocol.game.writeIdentifier
|
||||||
|
|
||||||
public data class ClientboundUpdateTagsPacket(val registries: List<TaggedRegistry>) : ClientboundConfigurationPacket {
|
public data class ClientboundUpdateTagsPacket(val registries: List<TaggedRegistry>) : MinecraftPacket {
|
||||||
public data class TaggedRegistry(val registryId: Identifier, val tags: List<Tag>) {
|
public data class TaggedRegistry(val registryId: Identifier, val tags: List<Tag>) {
|
||||||
internal companion object Codec : PacketCodec<TaggedRegistry> {
|
internal companion object Codec : PacketCodec<TaggedRegistry> {
|
||||||
override fun encode(buffer: BytesBuffer, value: TaggedRegistry) {
|
override suspend fun encode(buffer: BytesBuffer, value: TaggedRegistry) {
|
||||||
buffer.writeIdentifier(value.registryId)
|
buffer.writeIdentifier(value.registryId)
|
||||||
buffer.writeVarInt(value.tags.size)
|
buffer.writeVarInt(value.tags.size)
|
||||||
value.tags.forEach { Tag.encode(buffer, it) }
|
value.tags.forEach { Tag.encode(buffer, it) }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun decode(buffer: BytesBuffer): TaggedRegistry {
|
override suspend fun decode(buffer: BytesBuffer): TaggedRegistry {
|
||||||
val id = buffer.readIdentifier()
|
val id = buffer.readIdentifier()
|
||||||
val tagCount = buffer.readVarInt()
|
val tagCount = buffer.readVarInt()
|
||||||
val tags = ArrayList<Tag>(tagCount)
|
val tags = ArrayList<Tag>(tagCount)
|
||||||
@@ -36,13 +37,13 @@ public data class ClientboundUpdateTagsPacket(val registries: List<TaggedRegistr
|
|||||||
|
|
||||||
public data class Tag(val name: Identifier, val entries: IntArray) {
|
public data class Tag(val name: Identifier, val entries: IntArray) {
|
||||||
internal companion object Codec : PacketCodec<Tag> {
|
internal companion object Codec : PacketCodec<Tag> {
|
||||||
override fun encode(buffer: BytesBuffer, value: Tag) {
|
override suspend fun encode(buffer: BytesBuffer, value: Tag) {
|
||||||
buffer.writeIdentifier(value.name)
|
buffer.writeIdentifier(value.name)
|
||||||
buffer.writeVarInt(value.entries.size)
|
buffer.writeVarInt(value.entries.size)
|
||||||
value.entries.forEach { buffer.writeVarInt(it) }
|
value.entries.forEach { buffer.writeVarInt(it) }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun decode(buffer: BytesBuffer): Tag {
|
override suspend fun decode(buffer: BytesBuffer): Tag {
|
||||||
val name = buffer.readIdentifier()
|
val name = buffer.readIdentifier()
|
||||||
val entrySize = buffer.readVarInt()
|
val entrySize = buffer.readVarInt()
|
||||||
val entries = ArrayList<Int>(entrySize)
|
val entries = ArrayList<Int>(entrySize)
|
||||||
@@ -68,8 +69,8 @@ public data class ClientboundUpdateTagsPacket(val registries: List<TaggedRegistr
|
|||||||
}
|
}
|
||||||
|
|
||||||
internal companion object Codec : PacketCodec<ClientboundUpdateTagsPacket> {
|
internal companion object Codec : PacketCodec<ClientboundUpdateTagsPacket> {
|
||||||
override fun encode(buffer: BytesBuffer, value: ClientboundUpdateTagsPacket) {}
|
override suspend fun encode(buffer: BytesBuffer, value: ClientboundUpdateTagsPacket) {}
|
||||||
override fun decode(buffer: BytesBuffer): ClientboundUpdateTagsPacket {
|
override suspend fun decode(buffer: BytesBuffer): ClientboundUpdateTagsPacket {
|
||||||
val registryCount = buffer.readVarInt()
|
val registryCount = buffer.readVarInt()
|
||||||
val registries = ArrayList<TaggedRegistry>(registryCount)
|
val registries = ArrayList<TaggedRegistry>(registryCount)
|
||||||
repeat(registryCount) { registries.add(TaggedRegistry.decode(buffer)) }
|
repeat(registryCount) { registries.add(TaggedRegistry.decode(buffer)) }
|
||||||
|
|||||||
+4
-4
@@ -7,13 +7,13 @@
|
|||||||
|
|
||||||
package cn.rtast.libmc.protocol.packet.configuration.serverbound
|
package cn.rtast.libmc.protocol.packet.configuration.serverbound
|
||||||
|
|
||||||
import cn.rtast.libmc.common.BytesBuffer
|
import cn.rtast.libmc.common.stream.BytesBuffer
|
||||||
import cn.rtast.libmc.common.PacketCodec
|
import cn.rtast.libmc.common.packet.PacketCodec
|
||||||
import cn.rtast.libmc.common.packet.MinecraftPacket
|
import cn.rtast.libmc.common.packet.MinecraftPacket
|
||||||
|
|
||||||
public data object ServerboundAcceptCodeOfConductPacket : MinecraftPacket,
|
public data object ServerboundAcceptCodeOfConductPacket : MinecraftPacket,
|
||||||
PacketCodec<ServerboundAcceptCodeOfConductPacket> {
|
PacketCodec<ServerboundAcceptCodeOfConductPacket> {
|
||||||
override fun encode(buffer: BytesBuffer, value: ServerboundAcceptCodeOfConductPacket) {}
|
override suspend fun encode(buffer: BytesBuffer, value: ServerboundAcceptCodeOfConductPacket) {}
|
||||||
override fun decode(buffer: BytesBuffer): ServerboundAcceptCodeOfConductPacket =
|
override suspend fun decode(buffer: BytesBuffer): ServerboundAcceptCodeOfConductPacket =
|
||||||
ServerboundAcceptCodeOfConductPacket
|
ServerboundAcceptCodeOfConductPacket
|
||||||
}
|
}
|
||||||
+4
-4
@@ -7,13 +7,13 @@
|
|||||||
|
|
||||||
package cn.rtast.libmc.protocol.packet.configuration.serverbound
|
package cn.rtast.libmc.protocol.packet.configuration.serverbound
|
||||||
|
|
||||||
import cn.rtast.libmc.common.BytesBuffer
|
import cn.rtast.libmc.common.stream.BytesBuffer
|
||||||
import cn.rtast.libmc.common.PacketCodec
|
import cn.rtast.libmc.common.packet.PacketCodec
|
||||||
import cn.rtast.libmc.common.packet.MinecraftPacket
|
import cn.rtast.libmc.common.packet.MinecraftPacket
|
||||||
|
|
||||||
public data object ServerboundAckFinishConfigurationPacket : MinecraftPacket,
|
public data object ServerboundAckFinishConfigurationPacket : MinecraftPacket,
|
||||||
PacketCodec<ServerboundAckFinishConfigurationPacket> {
|
PacketCodec<ServerboundAckFinishConfigurationPacket> {
|
||||||
override fun encode(buffer: BytesBuffer, value: ServerboundAckFinishConfigurationPacket) {}
|
override suspend fun encode(buffer: BytesBuffer, value: ServerboundAckFinishConfigurationPacket) {}
|
||||||
override fun decode(buffer: BytesBuffer): ServerboundAckFinishConfigurationPacket =
|
override suspend fun decode(buffer: BytesBuffer): ServerboundAckFinishConfigurationPacket =
|
||||||
throw UnsupportedOperationException()
|
throw UnsupportedOperationException()
|
||||||
}
|
}
|
||||||
+5
-5
@@ -7,16 +7,16 @@
|
|||||||
|
|
||||||
package cn.rtast.libmc.protocol.packet.configuration.serverbound
|
package cn.rtast.libmc.protocol.packet.configuration.serverbound
|
||||||
|
|
||||||
import cn.rtast.libmc.common.BytesBuffer
|
import cn.rtast.libmc.common.stream.BytesBuffer
|
||||||
import cn.rtast.libmc.common.PacketCodec
|
import cn.rtast.libmc.common.packet.PacketCodec
|
||||||
import cn.rtast.libmc.common.packet.MinecraftPacket
|
import cn.rtast.libmc.common.packet.MinecraftPacket
|
||||||
import cn.rtast.libmc.common.writeVarInt
|
import cn.rtast.libmc.common.primitives.writeVarInt
|
||||||
import cn.rtast.libmc.protocol.protocol.game.Identifier
|
import cn.rtast.libmc.protocol.protocol.game.Identifier
|
||||||
import cn.rtast.libmc.protocol.protocol.game.writeIdentifier
|
import cn.rtast.libmc.protocol.protocol.game.writeIdentifier
|
||||||
|
|
||||||
public data class ServerboundCookieResponsePacket(val key: Identifier, val payload: ByteArray?) : MinecraftPacket {
|
public data class ServerboundCookieResponsePacket(val key: Identifier, val payload: ByteArray?) : MinecraftPacket {
|
||||||
internal companion object Codec : PacketCodec<ServerboundCookieResponsePacket> {
|
internal companion object Codec : PacketCodec<ServerboundCookieResponsePacket> {
|
||||||
override fun encode(buffer: BytesBuffer, value: ServerboundCookieResponsePacket) {
|
override suspend fun encode(buffer: BytesBuffer, value: ServerboundCookieResponsePacket) {
|
||||||
buffer.writeIdentifier(value.key)
|
buffer.writeIdentifier(value.key)
|
||||||
if (value.payload != null) {
|
if (value.payload != null) {
|
||||||
buffer.writeBoolean(true)
|
buffer.writeBoolean(true)
|
||||||
@@ -25,7 +25,7 @@ public data class ServerboundCookieResponsePacket(val key: Identifier, val paylo
|
|||||||
} else buffer.writeBoolean(false)
|
} else buffer.writeBoolean(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun decode(buffer: BytesBuffer): ServerboundCookieResponsePacket =
|
override suspend fun decode(buffer: BytesBuffer): ServerboundCookieResponsePacket =
|
||||||
throw UnsupportedOperationException()
|
throw UnsupportedOperationException()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+4
-4
@@ -7,17 +7,17 @@
|
|||||||
|
|
||||||
package cn.rtast.libmc.protocol.packet.configuration.serverbound
|
package cn.rtast.libmc.protocol.packet.configuration.serverbound
|
||||||
|
|
||||||
import cn.rtast.libmc.common.BytesBuffer
|
import cn.rtast.libmc.common.stream.BytesBuffer
|
||||||
import cn.rtast.libmc.common.PacketCodec
|
import cn.rtast.libmc.common.packet.PacketCodec
|
||||||
import cn.rtast.libmc.common.packet.MinecraftPacket
|
import cn.rtast.libmc.common.packet.MinecraftPacket
|
||||||
|
|
||||||
public data class ServerboundKeepAliveConfigurationPacket(val id: Long) : MinecraftPacket {
|
public data class ServerboundKeepAliveConfigurationPacket(val id: Long) : MinecraftPacket {
|
||||||
internal companion object Codec : PacketCodec<ServerboundKeepAliveConfigurationPacket> {
|
internal companion object Codec : PacketCodec<ServerboundKeepAliveConfigurationPacket> {
|
||||||
override fun encode(buffer: BytesBuffer, value: ServerboundKeepAliveConfigurationPacket) {
|
override suspend fun encode(buffer: BytesBuffer, value: ServerboundKeepAliveConfigurationPacket) {
|
||||||
buffer.writeLong(value.id)
|
buffer.writeLong(value.id)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun decode(buffer: BytesBuffer): ServerboundKeepAliveConfigurationPacket =
|
override suspend fun decode(buffer: BytesBuffer): ServerboundKeepAliveConfigurationPacket =
|
||||||
throw UnsupportedOperationException()
|
throw UnsupportedOperationException()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+4
-4
@@ -7,17 +7,17 @@
|
|||||||
|
|
||||||
package cn.rtast.libmc.protocol.packet.configuration.serverbound
|
package cn.rtast.libmc.protocol.packet.configuration.serverbound
|
||||||
|
|
||||||
import cn.rtast.libmc.common.BytesBuffer
|
import cn.rtast.libmc.common.stream.BytesBuffer
|
||||||
import cn.rtast.libmc.common.PacketCodec
|
import cn.rtast.libmc.common.packet.PacketCodec
|
||||||
import cn.rtast.libmc.common.packet.MinecraftPacket
|
import cn.rtast.libmc.common.packet.MinecraftPacket
|
||||||
|
|
||||||
public data class ServerboundPongConfigurationPacket(val id: Int) : MinecraftPacket {
|
public data class ServerboundPongConfigurationPacket(val id: Int) : MinecraftPacket {
|
||||||
internal companion object Codec : PacketCodec<ServerboundPongConfigurationPacket> {
|
internal companion object Codec : PacketCodec<ServerboundPongConfigurationPacket> {
|
||||||
override fun encode(buffer: BytesBuffer, value: ServerboundPongConfigurationPacket) {
|
override suspend fun encode(buffer: BytesBuffer, value: ServerboundPongConfigurationPacket) {
|
||||||
buffer.writeInt(value.id)
|
buffer.writeInt(value.id)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun decode(buffer: BytesBuffer): ServerboundPongConfigurationPacket =
|
override suspend fun decode(buffer: BytesBuffer): ServerboundPongConfigurationPacket =
|
||||||
throw UnsupportedOperationException()
|
throw UnsupportedOperationException()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+5
-5
@@ -7,20 +7,20 @@
|
|||||||
|
|
||||||
package cn.rtast.libmc.protocol.packet.configuration.serverbound
|
package cn.rtast.libmc.protocol.packet.configuration.serverbound
|
||||||
|
|
||||||
import cn.rtast.libmc.common.BytesBuffer
|
import cn.rtast.libmc.common.stream.BytesBuffer
|
||||||
import cn.rtast.libmc.common.PacketCodec
|
import cn.rtast.libmc.common.packet.PacketCodec
|
||||||
import cn.rtast.libmc.common.packet.MinecraftPacket
|
import cn.rtast.libmc.common.packet.MinecraftPacket
|
||||||
import cn.rtast.libmc.common.writeVarInt
|
import cn.rtast.libmc.common.primitives.writeVarInt
|
||||||
import cn.rtast.libmc.protocol.packet.configuration.KnownPacks
|
import cn.rtast.libmc.protocol.packet.configuration.KnownPacks
|
||||||
|
|
||||||
public data class ServerboundSelectKnownPacksPacket(val knownPacks: List<KnownPacks>) : MinecraftPacket {
|
public data class ServerboundSelectKnownPacksPacket(val knownPacks: List<KnownPacks>) : MinecraftPacket {
|
||||||
internal companion object Codec : PacketCodec<ServerboundSelectKnownPacksPacket> {
|
internal companion object Codec : PacketCodec<ServerboundSelectKnownPacksPacket> {
|
||||||
override fun encode(buffer: BytesBuffer, value: ServerboundSelectKnownPacksPacket) {
|
override suspend fun encode(buffer: BytesBuffer, value: ServerboundSelectKnownPacksPacket) {
|
||||||
buffer.writeVarInt(value.knownPacks.size)
|
buffer.writeVarInt(value.knownPacks.size)
|
||||||
value.knownPacks.forEach { KnownPacks.encode(buffer, it) }
|
value.knownPacks.forEach { KnownPacks.encode(buffer, it) }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun decode(buffer: BytesBuffer): ServerboundSelectKnownPacksPacket =
|
override suspend fun decode(buffer: BytesBuffer): ServerboundSelectKnownPacksPacket =
|
||||||
throw UnsupportedOperationException()
|
throw UnsupportedOperationException()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+6
-6
@@ -7,11 +7,11 @@
|
|||||||
|
|
||||||
package cn.rtast.libmc.protocol.packet.handshake
|
package cn.rtast.libmc.protocol.packet.handshake
|
||||||
|
|
||||||
import cn.rtast.libmc.common.BytesBuffer
|
import cn.rtast.libmc.common.stream.BytesBuffer
|
||||||
import cn.rtast.libmc.common.PacketCodec
|
import cn.rtast.libmc.common.packet.PacketCodec
|
||||||
import cn.rtast.libmc.common.packet.MinecraftPacket
|
import cn.rtast.libmc.common.packet.MinecraftPacket
|
||||||
import cn.rtast.libmc.common.writeMcString
|
import cn.rtast.libmc.common.primitives.writeMcString
|
||||||
import cn.rtast.libmc.common.writeVarInt
|
import cn.rtast.libmc.common.primitives.writeVarInt
|
||||||
import cn.rtast.libmc.protocol.protocol.state.HandshakeIntent
|
import cn.rtast.libmc.protocol.protocol.state.HandshakeIntent
|
||||||
|
|
||||||
public data class ServerboundHandshakePacket(
|
public data class ServerboundHandshakePacket(
|
||||||
@@ -21,13 +21,13 @@ public data class ServerboundHandshakePacket(
|
|||||||
val intent: HandshakeIntent,
|
val intent: HandshakeIntent,
|
||||||
) : MinecraftPacket {
|
) : MinecraftPacket {
|
||||||
internal companion object Codec : PacketCodec<ServerboundHandshakePacket> {
|
internal companion object Codec : PacketCodec<ServerboundHandshakePacket> {
|
||||||
override fun encode(buffer: BytesBuffer, value: ServerboundHandshakePacket) {
|
override suspend fun encode(buffer: BytesBuffer, value: ServerboundHandshakePacket) {
|
||||||
buffer.writeVarInt(value.protocolVersion)
|
buffer.writeVarInt(value.protocolVersion)
|
||||||
buffer.writeMcString(value.serverAddress)
|
buffer.writeMcString(value.serverAddress)
|
||||||
buffer.writeShort(value.serverPort.toShort())
|
buffer.writeShort(value.serverPort.toShort())
|
||||||
buffer.writeVarInt(value.intent.intentID)
|
buffer.writeVarInt(value.intent.intentID)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun decode(buffer: BytesBuffer): ServerboundHandshakePacket = throw UnsupportedOperationException()
|
override suspend fun decode(buffer: BytesBuffer): ServerboundHandshakePacket = throw UnsupportedOperationException()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+7
-6
@@ -7,9 +7,10 @@
|
|||||||
|
|
||||||
package cn.rtast.libmc.protocol.packet.login.clientbound
|
package cn.rtast.libmc.protocol.packet.login.clientbound
|
||||||
|
|
||||||
import cn.rtast.libmc.common.BytesBuffer
|
import cn.rtast.libmc.common.stream.BytesBuffer
|
||||||
import cn.rtast.libmc.common.PacketCodec
|
import cn.rtast.libmc.common.packet.MinecraftPacket
|
||||||
import cn.rtast.libmc.common.readVarInt
|
import cn.rtast.libmc.common.packet.PacketCodec
|
||||||
|
import cn.rtast.libmc.common.primitives.readVarInt
|
||||||
import cn.rtast.libmc.protocol.protocol.game.Identifier
|
import cn.rtast.libmc.protocol.protocol.game.Identifier
|
||||||
import cn.rtast.libmc.protocol.protocol.game.readIdentifier
|
import cn.rtast.libmc.protocol.protocol.game.readIdentifier
|
||||||
|
|
||||||
@@ -17,10 +18,10 @@ public data class ClientboundCustomQueryPacket(
|
|||||||
val messageId: Int,
|
val messageId: Int,
|
||||||
val channel: Identifier,
|
val channel: Identifier,
|
||||||
val data: ByteArray,
|
val data: ByteArray,
|
||||||
) : ClientboundLoginPacket {
|
) : MinecraftPacket {
|
||||||
internal companion object Codec : PacketCodec<ClientboundCustomQueryPacket> {
|
internal companion object Codec : PacketCodec<ClientboundCustomQueryPacket> {
|
||||||
override fun encode(buffer: BytesBuffer, value: ClientboundCustomQueryPacket) {}
|
override suspend fun encode(buffer: BytesBuffer, value: ClientboundCustomQueryPacket) {}
|
||||||
override fun decode(buffer: BytesBuffer): ClientboundCustomQueryPacket {
|
override suspend fun decode(buffer: BytesBuffer): ClientboundCustomQueryPacket {
|
||||||
val messageId = buffer.readVarInt()
|
val messageId = buffer.readVarInt()
|
||||||
val channel = buffer.readIdentifier()
|
val channel = buffer.readIdentifier()
|
||||||
val data = buffer.readBytes(buffer.remaining.toInt())
|
val data = buffer.readBytes(buffer.remaining.toInt())
|
||||||
|
|||||||
+6
-5
@@ -7,15 +7,16 @@
|
|||||||
|
|
||||||
package cn.rtast.libmc.protocol.packet.login.clientbound
|
package cn.rtast.libmc.protocol.packet.login.clientbound
|
||||||
|
|
||||||
import cn.rtast.libmc.common.BytesBuffer
|
import cn.rtast.libmc.common.stream.BytesBuffer
|
||||||
import cn.rtast.libmc.common.PacketCodec
|
import cn.rtast.libmc.common.packet.MinecraftPacket
|
||||||
|
import cn.rtast.libmc.common.packet.PacketCodec
|
||||||
import cn.rtast.libmc.nbt.NBTCompound
|
import cn.rtast.libmc.nbt.NBTCompound
|
||||||
import cn.rtast.libmc.protocol.protocol.util.readNetworkNBTCompound
|
import cn.rtast.libmc.protocol.protocol.util.readNetworkNBTCompound
|
||||||
|
|
||||||
public data class ClientboundDisconnectLoginPacket(val reason: NBTCompound) : ClientboundLoginPacket {
|
public data class ClientboundDisconnectLoginPacket(val reason: NBTCompound) : MinecraftPacket {
|
||||||
internal companion object Codec : PacketCodec<ClientboundDisconnectLoginPacket> {
|
internal companion object Codec : PacketCodec<ClientboundDisconnectLoginPacket> {
|
||||||
override fun encode(buffer: BytesBuffer, value: ClientboundDisconnectLoginPacket) {}
|
override suspend fun encode(buffer: BytesBuffer, value: ClientboundDisconnectLoginPacket) {}
|
||||||
override fun decode(buffer: BytesBuffer): ClientboundDisconnectLoginPacket {
|
override suspend fun decode(buffer: BytesBuffer): ClientboundDisconnectLoginPacket {
|
||||||
return ClientboundDisconnectLoginPacket(reason = buffer.readNetworkNBTCompound())
|
return ClientboundDisconnectLoginPacket(reason = buffer.readNetworkNBTCompound())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+8
-7
@@ -7,10 +7,11 @@
|
|||||||
|
|
||||||
package cn.rtast.libmc.protocol.packet.login.clientbound
|
package cn.rtast.libmc.protocol.packet.login.clientbound
|
||||||
|
|
||||||
import cn.rtast.libmc.common.BytesBuffer
|
import cn.rtast.libmc.common.stream.BytesBuffer
|
||||||
import cn.rtast.libmc.common.PacketCodec
|
import cn.rtast.libmc.common.packet.MinecraftPacket
|
||||||
import cn.rtast.libmc.common.readMcString
|
import cn.rtast.libmc.common.packet.PacketCodec
|
||||||
import cn.rtast.libmc.common.readPrefixedByteArray
|
import cn.rtast.libmc.common.primitives.readMcString
|
||||||
|
import cn.rtast.libmc.common.primitives.readPrefixedByteArray
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ref: https://minecraft.wiki/w/Java_Edition_protocol/Packets#Encryption_Request
|
* ref: https://minecraft.wiki/w/Java_Edition_protocol/Packets#Encryption_Request
|
||||||
@@ -24,10 +25,10 @@ public data class ClientboundHelloPacket(
|
|||||||
* ref: https://minecraft.wiki/w/Java_Edition_protocol/Encryption#Authentication
|
* ref: https://minecraft.wiki/w/Java_Edition_protocol/Encryption#Authentication
|
||||||
*/
|
*/
|
||||||
val shouldAuthenticate: Boolean,
|
val shouldAuthenticate: Boolean,
|
||||||
) : ClientboundLoginPacket {
|
) : MinecraftPacket {
|
||||||
internal companion object Codec : PacketCodec<ClientboundHelloPacket> {
|
internal companion object Codec : PacketCodec<ClientboundHelloPacket> {
|
||||||
override fun encode(buffer: BytesBuffer, value: ClientboundHelloPacket) {}
|
override suspend fun encode(buffer: BytesBuffer, value: ClientboundHelloPacket) {}
|
||||||
override fun decode(buffer: BytesBuffer): ClientboundHelloPacket {
|
override suspend fun decode(buffer: BytesBuffer): ClientboundHelloPacket {
|
||||||
val serverId = buffer.readMcString()
|
val serverId = buffer.readMcString()
|
||||||
val publicKey = buffer.readPrefixedByteArray()
|
val publicKey = buffer.readPrefixedByteArray()
|
||||||
val verifyToken = buffer.readPrefixedByteArray()
|
val verifyToken = buffer.readPrefixedByteArray()
|
||||||
|
|||||||
-12
@@ -1,12 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright © 2026 RTAkland
|
|
||||||
* Author: RTAkland
|
|
||||||
* Date: 2026/9/5
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
package cn.rtast.libmc.protocol.packet.login.clientbound
|
|
||||||
|
|
||||||
import cn.rtast.libmc.common.packet.MinecraftPacket
|
|
||||||
|
|
||||||
public sealed interface ClientboundLoginPacket : MinecraftPacket
|
|
||||||
+7
-6
@@ -7,17 +7,18 @@
|
|||||||
|
|
||||||
package cn.rtast.libmc.protocol.packet.login.clientbound
|
package cn.rtast.libmc.protocol.packet.login.clientbound
|
||||||
|
|
||||||
import cn.rtast.libmc.common.BytesBuffer
|
import cn.rtast.libmc.common.stream.BytesBuffer
|
||||||
import cn.rtast.libmc.common.PacketCodec
|
import cn.rtast.libmc.common.packet.MinecraftPacket
|
||||||
import cn.rtast.libmc.common.readUuid
|
import cn.rtast.libmc.common.packet.PacketCodec
|
||||||
|
import cn.rtast.libmc.common.primitives.readUuid
|
||||||
import cn.rtast.libmc.protocol.session.GameProfile
|
import cn.rtast.libmc.protocol.session.GameProfile
|
||||||
import kotlin.uuid.Uuid
|
import kotlin.uuid.Uuid
|
||||||
|
|
||||||
public data class ClientboundLoginSuccessPacket(val gameProfile: GameProfile, val sessionId: Uuid) :
|
public data class ClientboundLoginSuccessPacket(val gameProfile: GameProfile, val sessionId: Uuid) :
|
||||||
ClientboundLoginPacket {
|
MinecraftPacket {
|
||||||
internal companion object Codec : PacketCodec<ClientboundLoginSuccessPacket> {
|
internal companion object Codec : PacketCodec<ClientboundLoginSuccessPacket> {
|
||||||
override fun encode(buffer: BytesBuffer, value: ClientboundLoginSuccessPacket) {}
|
override suspend fun encode(buffer: BytesBuffer, value: ClientboundLoginSuccessPacket) {}
|
||||||
override fun decode(buffer: BytesBuffer): ClientboundLoginSuccessPacket {
|
override suspend fun decode(buffer: BytesBuffer): ClientboundLoginSuccessPacket {
|
||||||
val gameProfile = GameProfile.decode(buffer)
|
val gameProfile = GameProfile.decode(buffer)
|
||||||
val sessionId = buffer.readUuid()
|
val sessionId = buffer.readUuid()
|
||||||
return ClientboundLoginSuccessPacket(gameProfile, sessionId)
|
return ClientboundLoginSuccessPacket(gameProfile, sessionId)
|
||||||
|
|||||||
+9
-8
@@ -7,18 +7,19 @@
|
|||||||
|
|
||||||
package cn.rtast.libmc.protocol.packet.login.clientbound
|
package cn.rtast.libmc.protocol.packet.login.clientbound
|
||||||
|
|
||||||
import cn.rtast.libmc.common.BytesBuffer
|
import cn.rtast.libmc.common.stream.BytesBuffer
|
||||||
import cn.rtast.libmc.common.PacketCodec
|
import cn.rtast.libmc.common.packet.MinecraftPacket
|
||||||
import cn.rtast.libmc.common.readVarInt
|
import cn.rtast.libmc.common.packet.PacketCodec
|
||||||
import cn.rtast.libmc.common.writeVarInt
|
import cn.rtast.libmc.common.primitives.readVarInt
|
||||||
|
import cn.rtast.libmc.common.primitives.writeVarInt
|
||||||
|
|
||||||
public data class ClientboundSetCompressionPacket(val threshold: Int) : ClientboundLoginPacket {
|
public data class ClientboundSetCompressionPacket(val threshold: Int) : MinecraftPacket {
|
||||||
internal companion object Codec : PacketCodec<ClientboundSetCompressionPacket> {
|
internal companion object Codec : PacketCodec<ClientboundSetCompressionPacket> {
|
||||||
override fun encode(buffer: BytesBuffer, value: ClientboundSetCompressionPacket) {
|
override suspend fun encode(buffer: BytesBuffer, value: ClientboundSetCompressionPacket) {
|
||||||
buffer.writeVarInt(value.threshold)
|
buffer.writeVarInt(value = value.threshold)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun decode(buffer: BytesBuffer): ClientboundSetCompressionPacket {
|
override suspend fun decode(buffer: BytesBuffer): ClientboundSetCompressionPacket {
|
||||||
return ClientboundSetCompressionPacket(buffer.readVarInt())
|
return ClientboundSetCompressionPacket(buffer.readVarInt())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+6
-6
@@ -7,20 +7,20 @@
|
|||||||
|
|
||||||
package cn.rtast.libmc.protocol.packet.login.serverbound
|
package cn.rtast.libmc.protocol.packet.login.serverbound
|
||||||
|
|
||||||
import cn.rtast.libmc.common.BytesBuffer
|
import cn.rtast.libmc.common.stream.BytesBuffer
|
||||||
import cn.rtast.libmc.common.PacketCodec
|
import cn.rtast.libmc.common.packet.PacketCodec
|
||||||
import cn.rtast.libmc.common.packet.MinecraftPacket
|
import cn.rtast.libmc.common.packet.MinecraftPacket
|
||||||
import cn.rtast.libmc.common.writeOptionalPrefixedByteArray
|
import cn.rtast.libmc.common.primitives.writeOptionalPrefixedByteArray
|
||||||
import cn.rtast.libmc.common.writeVarInt
|
import cn.rtast.libmc.common.primitives.writeVarInt
|
||||||
|
|
||||||
public data class ServerboundCustomQueryAnswerPacket(val messageId: Int, val data: ByteArray?) : MinecraftPacket {
|
public data class ServerboundCustomQueryAnswerPacket(val messageId: Int, val data: ByteArray?) : MinecraftPacket {
|
||||||
internal companion object Codec : PacketCodec<ServerboundCustomQueryAnswerPacket> {
|
internal companion object Codec : PacketCodec<ServerboundCustomQueryAnswerPacket> {
|
||||||
override fun encode(buffer: BytesBuffer, value: ServerboundCustomQueryAnswerPacket) {
|
override suspend fun encode(buffer: BytesBuffer, value: ServerboundCustomQueryAnswerPacket) {
|
||||||
buffer.writeVarInt(value.messageId)
|
buffer.writeVarInt(value.messageId)
|
||||||
buffer.writeOptionalPrefixedByteArray(value.data)
|
buffer.writeOptionalPrefixedByteArray(value.data)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun decode(buffer: BytesBuffer): ServerboundCustomQueryAnswerPacket =
|
override suspend fun decode(buffer: BytesBuffer): ServerboundCustomQueryAnswerPacket =
|
||||||
throw UnsupportedOperationException()
|
throw UnsupportedOperationException()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+5
-5
@@ -7,22 +7,22 @@
|
|||||||
|
|
||||||
package cn.rtast.libmc.protocol.packet.login.serverbound
|
package cn.rtast.libmc.protocol.packet.login.serverbound
|
||||||
|
|
||||||
import cn.rtast.libmc.common.BytesBuffer
|
import cn.rtast.libmc.common.stream.BytesBuffer
|
||||||
import cn.rtast.libmc.common.PacketCodec
|
import cn.rtast.libmc.common.packet.PacketCodec
|
||||||
import cn.rtast.libmc.common.packet.MinecraftPacket
|
import cn.rtast.libmc.common.packet.MinecraftPacket
|
||||||
import cn.rtast.libmc.common.writePrefixedByteArray
|
import cn.rtast.libmc.common.primitives.writePrefixedByteArray
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ref: https://minecraft.wiki/w/Java_Edition_protocol/Encryption
|
* ref: https://minecraft.wiki/w/Java_Edition_protocol/Encryption
|
||||||
*/
|
*/
|
||||||
public data class ServerboundKeyPacket(val sharedSecret: ByteArray, val verifyToken: ByteArray) : MinecraftPacket {
|
public data class ServerboundKeyPacket(val sharedSecret: ByteArray, val verifyToken: ByteArray) : MinecraftPacket {
|
||||||
internal companion object Codec : PacketCodec<ServerboundKeyPacket> {
|
internal companion object Codec : PacketCodec<ServerboundKeyPacket> {
|
||||||
override fun encode(buffer: BytesBuffer, value: ServerboundKeyPacket) {
|
override suspend fun encode(buffer: BytesBuffer, value: ServerboundKeyPacket) {
|
||||||
buffer.writePrefixedByteArray(value.sharedSecret)
|
buffer.writePrefixedByteArray(value.sharedSecret)
|
||||||
buffer.writePrefixedByteArray(value.verifyToken)
|
buffer.writePrefixedByteArray(value.verifyToken)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun decode(buffer: BytesBuffer): ServerboundKeyPacket =
|
override suspend fun decode(buffer: BytesBuffer): ServerboundKeyPacket =
|
||||||
throw UnsupportedOperationException()
|
throw UnsupportedOperationException()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+5
-4
@@ -7,12 +7,13 @@
|
|||||||
|
|
||||||
package cn.rtast.libmc.protocol.packet.login.serverbound
|
package cn.rtast.libmc.protocol.packet.login.serverbound
|
||||||
|
|
||||||
import cn.rtast.libmc.common.BytesBuffer
|
import cn.rtast.libmc.common.stream.BytesBuffer
|
||||||
import cn.rtast.libmc.common.PacketCodec
|
|
||||||
import cn.rtast.libmc.common.packet.MinecraftPacket
|
import cn.rtast.libmc.common.packet.MinecraftPacket
|
||||||
|
import cn.rtast.libmc.common.packet.PacketCodec
|
||||||
|
|
||||||
public data object ServerboundLoginAcknowledgedPacket : MinecraftPacket,
|
public data object ServerboundLoginAcknowledgedPacket : MinecraftPacket,
|
||||||
PacketCodec<ServerboundLoginAcknowledgedPacket> {
|
PacketCodec<ServerboundLoginAcknowledgedPacket> {
|
||||||
override fun encode(buffer: BytesBuffer, value: ServerboundLoginAcknowledgedPacket) {}
|
override suspend fun encode(buffer: BytesBuffer, value: ServerboundLoginAcknowledgedPacket) {}
|
||||||
override fun decode(buffer: BytesBuffer): ServerboundLoginAcknowledgedPacket = throw UnsupportedOperationException()
|
override suspend fun decode(buffer: BytesBuffer): ServerboundLoginAcknowledgedPacket =
|
||||||
|
throw UnsupportedOperationException()
|
||||||
}
|
}
|
||||||
+7
-6
@@ -7,20 +7,21 @@
|
|||||||
|
|
||||||
package cn.rtast.libmc.protocol.packet.login.serverbound
|
package cn.rtast.libmc.protocol.packet.login.serverbound
|
||||||
|
|
||||||
import cn.rtast.libmc.common.BytesBuffer
|
import cn.rtast.libmc.common.stream.BytesBuffer
|
||||||
import cn.rtast.libmc.common.PacketCodec
|
|
||||||
import cn.rtast.libmc.common.packet.MinecraftPacket
|
import cn.rtast.libmc.common.packet.MinecraftPacket
|
||||||
import cn.rtast.libmc.common.writeMcString
|
import cn.rtast.libmc.common.packet.PacketCodec
|
||||||
import cn.rtast.libmc.common.writeUuid
|
import cn.rtast.libmc.common.primitives.writeMcString
|
||||||
|
import cn.rtast.libmc.common.primitives.writeUuid
|
||||||
import kotlin.uuid.Uuid
|
import kotlin.uuid.Uuid
|
||||||
|
|
||||||
public data class ServerboundLoginStartPacket(val username: String, val playerUuid: Uuid) : MinecraftPacket {
|
public data class ServerboundLoginStartPacket(val username: String, val playerUuid: Uuid) : MinecraftPacket {
|
||||||
internal companion object Codec : PacketCodec<ServerboundLoginStartPacket> {
|
internal companion object Codec : PacketCodec<ServerboundLoginStartPacket> {
|
||||||
override fun encode(buffer: BytesBuffer, value: ServerboundLoginStartPacket) {
|
override suspend fun encode(buffer: BytesBuffer, value: ServerboundLoginStartPacket) {
|
||||||
buffer.writeMcString(value.username)
|
buffer.writeMcString(value.username)
|
||||||
buffer.writeUuid(value.playerUuid)
|
buffer.writeUuid(value.playerUuid)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun decode(buffer: BytesBuffer): ServerboundLoginStartPacket = throw UnsupportedOperationException()
|
override suspend fun decode(buffer: BytesBuffer): ServerboundLoginStartPacket =
|
||||||
|
throw UnsupportedOperationException()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+7
-6
@@ -7,17 +7,18 @@
|
|||||||
|
|
||||||
package cn.rtast.libmc.protocol.packet.play.clientbound
|
package cn.rtast.libmc.protocol.packet.play.clientbound
|
||||||
|
|
||||||
import cn.rtast.libmc.common.BytesBuffer
|
import cn.rtast.libmc.common.stream.BytesBuffer
|
||||||
import cn.rtast.libmc.common.PacketCodec
|
import cn.rtast.libmc.common.packet.MinecraftPacket
|
||||||
import cn.rtast.libmc.common.readVarInt
|
import cn.rtast.libmc.common.packet.PacketCodec
|
||||||
|
import cn.rtast.libmc.common.primitives.readVarInt
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ref: https://minecraft.wiki/w/Java_Edition_protocol/Packets#Acknowledge_Block_Change
|
* ref: https://minecraft.wiki/w/Java_Edition_protocol/Packets#Acknowledge_Block_Change
|
||||||
*/
|
*/
|
||||||
public data class ClientboundAcknowledgeBlockChangePacket(val sequenceId: Int) : ClientboundPlayPacket {
|
public data class ClientboundAcknowledgeBlockChangePacket(val sequenceId: Int) : MinecraftPacket {
|
||||||
internal companion object Codec : PacketCodec<ClientboundAcknowledgeBlockChangePacket> {
|
internal companion object Codec : PacketCodec<ClientboundAcknowledgeBlockChangePacket> {
|
||||||
override fun encode(buffer: BytesBuffer, value: ClientboundAcknowledgeBlockChangePacket) {}
|
override suspend fun encode(buffer: BytesBuffer, value: ClientboundAcknowledgeBlockChangePacket) {}
|
||||||
override fun decode(buffer: BytesBuffer): ClientboundAcknowledgeBlockChangePacket {
|
override suspend fun decode(buffer: BytesBuffer): ClientboundAcknowledgeBlockChangePacket {
|
||||||
return ClientboundAcknowledgeBlockChangePacket(buffer.readVarInt())
|
return ClientboundAcknowledgeBlockChangePacket(buffer.readVarInt())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loaded 100 of 296 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in New Issue
Block a user