Add packet codecs across Handshake, Login, Configuration, and Play stages
This commit is contained in:
261 files changed
+4387
-343
No files matched your search
@@ -21,6 +21,7 @@ public expect class BytesBuffer {
|
||||
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
|
||||
|
||||
@@ -9,18 +9,10 @@ package cn.rtast.libmc.common
|
||||
|
||||
public interface Encoder<in T> {
|
||||
public fun encode(buffer: BytesBuffer, value: T)
|
||||
|
||||
public fun encodeToByteArray(value: T): ByteArray {
|
||||
val buf = BytesBuffer()
|
||||
encode(buf, value)
|
||||
return buf.toByteArray()
|
||||
}
|
||||
}
|
||||
|
||||
public interface Decoder<out T> {
|
||||
public fun decode(buffer: BytesBuffer): T
|
||||
|
||||
public fun decodeFromByteArray(bytes: ByteArray): T = decode(bytes.wrap())
|
||||
}
|
||||
|
||||
public interface PacketCodec<T> : Encoder<T>, Decoder<T>
|
||||
|
||||
@@ -130,14 +130,6 @@ public fun BytesBuffer.writePrefixedByteArray(data: ByteArray) {
|
||||
this.writeBytes(data)
|
||||
}
|
||||
|
||||
public fun BytesBuffer.readOptionalPrefixedByteArray(): ByteArray? {
|
||||
val isPresent = this.readBoolean()
|
||||
return if (isPresent) {
|
||||
val length = this.readVarInt()
|
||||
this.readBytes(length)
|
||||
} else null
|
||||
}
|
||||
|
||||
public fun BytesBuffer.writeOptionalPrefixedByteArray(data: ByteArray?) {
|
||||
if (data != null) {
|
||||
this.writeBoolean(true)
|
||||
@@ -146,18 +138,6 @@ public fun BytesBuffer.writeOptionalPrefixedByteArray(data: ByteArray?) {
|
||||
} else this.writeBoolean(false)
|
||||
}
|
||||
|
||||
public fun BytesBuffer.readPrefixedVarIntArray(): List<Int> {
|
||||
val length = readVarInt()
|
||||
val list = ArrayList<Int>(length)
|
||||
repeat(length) { list.add(readVarInt()) }
|
||||
return list
|
||||
}
|
||||
|
||||
public fun BytesBuffer.writePrefixedVarIntArray(value: List<Int>) {
|
||||
writeVarInt(value.size)
|
||||
for (item in value) writeVarInt(item)
|
||||
}
|
||||
|
||||
public fun BytesBuffer.readPrefixedStringArray(): List<String> {
|
||||
val length = readVarInt()
|
||||
val list = ArrayList<String>(length)
|
||||
@@ -170,7 +150,83 @@ public fun BytesBuffer.writePrefixedStringArray(value: List<String>) {
|
||||
for (item in value) writeMcString(item)
|
||||
}
|
||||
|
||||
public inline fun <T> BytesBuffer.writePrefixedArray(value: List<T>, writeItem: BytesBuffer.(T) -> Unit) {
|
||||
writeVarInt(value.size)
|
||||
for (item in value) writeItem(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)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -90,6 +90,7 @@ public actual class BytesBuffer {
|
||||
return array[readOffset++]
|
||||
}
|
||||
|
||||
public actual fun readUByte(): UByte = this.readByte().toUByte()
|
||||
public actual fun readShort(endian: ByteOrder): Short = readBytes(2).toShort(endian)
|
||||
public actual fun readInt(endian: ByteOrder): Int = readBytes(4).toInt(endian)
|
||||
public actual fun readLong(endian: ByteOrder): Long = readBytes(8).toLong(endian)
|
||||
|
||||
@@ -47,6 +47,7 @@ public actual class BytesBuffer {
|
||||
public actual fun writeBoolean(value: Boolean): Unit = _delegateBuf.writeByte(if (value) 0x01 else 0x00)
|
||||
|
||||
public actual fun readByte(): Byte = _delegateBuf.readByte()
|
||||
public actual fun readUByte(): UByte = this.readByte().toUByte()
|
||||
public actual fun readShort(endian: ByteOrder): Short =
|
||||
if (endian == ByteOrder.BIG_ENDIAN) _delegateBuf.readShort() else _delegateBuf.readShortLe()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user