Fix set compresion, added nbt and snbt(wip) lib

This commit is contained in:
2026-09-05 16:35:55 +08:00
parent 60324028ee
commit 5e6e0ca5b9
56 files changed
+1064 -544

No files matched your search

+1 -1
View File
@@ -14,7 +14,7 @@ kotlin {
sourceSets {
commonMain.dependencies {
implementation(project(":common"))
api(project(":common"))
}
jvmMain.dependencies {
@@ -0,0 +1,19 @@
/*
* Copyright © 2026 RTAkland
* Author: RTAkland
* Date: 2026/9/5
*/
package cn.rtast.libmc.nbt
import cn.rtast.libmc.common.ByteOrder
import cn.rtast.libmc.common.BytesBuffer
public class BytesBufferNBTInput(override val order: ByteOrder, private val buffer: BytesBuffer) : NBTInput {
override fun readByte(): Byte = buffer.readByte()
override fun readBytes(count: Int): ByteArray = buffer.readBytes(count)
}
public fun BytesBuffer.toNBTInput(order: ByteOrder = ByteOrder.BIG_ENDIAN): BytesBufferNBTInput =
BytesBufferNBTInput(order, this)
@@ -0,0 +1,27 @@
/*
* Copyright © 2026 RTAkland
* Author: RTAkland
* Date: 2026/9/5
*/
package cn.rtast.libmc.nbt
import cn.rtast.libmc.common.ByteOrder
import cn.rtast.libmc.common.BytesBuffer
public class BytesBufferNBTOutput(
override val order: ByteOrder,
override val root: NBTTag.CompoundTag,
private val buffer: BytesBuffer,
) : NBTOutput {
override fun writeByte(value: Byte): Unit = buffer.writeByte(value)
override fun writeBytes(value: ByteArray): Unit = buffer.writeBytes(value)
override fun toByteArray(): ByteArray = buffer.toByteArray()
}
public fun BytesBuffer.toNBTOutput(
root: NBTTag.CompoundTag,
order: ByteOrder = ByteOrder.BIG_ENDIAN,
): BytesBufferNBTOutput =
BytesBufferNBTOutput(order, root, this)
@@ -0,0 +1,14 @@
/*
* Copyright © 2026 RTAkland
* Author: RTAkland
* Date: 2026/1/27
*/
package cn.rtast.libmc.nbt
public enum class CompressionType(internal val compressor: NbtCompressor?) {
Zlib(NbtCompressor.ZlibCompressor),
Gzip(NbtCompressor.GZipCompressor),
Raw(null)
}
@@ -0,0 +1,10 @@
/*
* Copyright © 2026 RTAkland
* Author: RTAkland
* Date: 2026/9/5
*/
package cn.rtast.libmc.nbt
public data class NBTCompound(val root: String, val element: NBTTag)
@@ -0,0 +1,83 @@
/*
* Copyright © 2026 RTAkland
* Author: RTAkland
* Date: 2026/1/25
*/
package cn.rtast.libmc.nbt
@DslMarker
public annotation class NbtDsl
@NbtDsl
public class CompoundBuilder {
private val tags = mutableMapOf<String, NBTTag>()
public infix fun String.byte(value: Byte) {
tags[this] = NBTTag.ByteTag(value)
}
public infix fun String.short(value: Short) {
tags[this] = NBTTag.ShortTag(value)
}
public infix fun String.int(value: Int) {
tags[this] = NBTTag.IntTag(value)
}
public infix fun String.long(value: Long) {
tags[this] = NBTTag.LongTag(value)
}
public infix fun String.float(value: Float) {
tags[this] = NBTTag.FloatTag(value)
}
public infix fun String.double(value: Double) {
tags[this] = NBTTag.DoubleTag(value)
}
public infix fun String.byteArray(value: ByteArray) {
tags[this] = NBTTag.ByteArrayTag(value)
}
public infix fun String.intArray(value: IntArray) {
tags[this] = NBTTag.IntArrayTag(value)
}
public infix fun String.longArray(value: LongArray) {
tags[this] = NBTTag.LongArrayTag(value)
}
public infix fun String.string(value: String) {
tags[this] = NBTTag.StringTag(value)
}
public infix fun String.compound(block: CompoundBuilder.() -> Unit) {
tags[this] = nbtCompound(block)
}
@Suppress("FunctionName")
private fun _list(
elementType: NBTType,
block: NBTListBuilder.() -> Unit,
): NBTTag.ListTag {
val builder = NBTListBuilder(elementType)
builder.block()
return builder.build()
}
public fun String.list(elementType: NBTType, block: NBTListBuilder.() -> Unit) {
tags[this] = _list(elementType, block)
}
public fun build(): NBTTag.CompoundTag = NBTTag.CompoundTag(tags)
}
public fun nbtCompound(block: CompoundBuilder.() -> Unit): NBTTag.CompoundTag {
val builder = CompoundBuilder()
builder.block()
return builder.build()
}
@@ -0,0 +1,67 @@
/*
* Copyright © 2026 RTAkland
* Author: RTAkland
* Date: 2026/1/25
*/
package cn.rtast.libmc.nbt
import cn.rtast.libmc.common.ByteOrder
public interface NBTInput {
public val order: ByteOrder
public fun readByte(): Byte
public fun readBytes(count: Int): ByteArray
public fun readLong(): Long = if (order == ByteOrder.BIG_ENDIAN) readLongBE() else readLongLE()
public fun readFloat(): Float = if (order == ByteOrder.BIG_ENDIAN) readFloatBE() else readFloatLE()
public fun readDouble(): Double = if (order == ByteOrder.BIG_ENDIAN) readDoubleBE() else readDoubleLE()
public fun readShort(): Short = if (order == ByteOrder.BIG_ENDIAN) readShortBE() else readShortLE()
public fun readInt(): Int = if (order == ByteOrder.BIG_ENDIAN) readIntBE() else readIntLE()
// big endian
public fun readLongBE(): Long =
(readIntBE().toLong() shl 32) or (readIntBE().toLong() and 0xFFFFFFFFL)
public fun readFloatBE(): Float = Float.fromBits(readIntBE())
public fun readDoubleBE(): Double = Double.fromBits(readLongBE())
public fun readShortBE(): Short {
val b1 = readByte().toInt() and 0xFF
val b2 = readByte().toInt() and 0xFF
return ((b1 shl 8) or b2).toShort()
}
public fun readIntBE(): Int {
return ((readByte().toInt() and 0xFF) shl 24) or
((readByte().toInt() and 0xFF) shl 16) or
((readByte().toInt() and 0xFF) shl 8) or
(readByte().toInt() and 0xFF)
}
// little endian
public fun readLongLE(): Long {
return ((readByte().toInt() and 0xFF).toLong() shl 0) or
((readByte().toInt() and 0xFF).toLong() shl 8) or
((readByte().toInt() and 0xFF).toLong() shl 16) or
((readByte().toInt() and 0xFF).toLong() shl 24) or
((readByte().toInt() and 0xFF).toLong() shl 32) or
((readByte().toInt() and 0xFF).toLong() shl 40) or
((readByte().toInt() and 0xFF).toLong() shl 48) or
(readByte().toInt() and 0xFF).toLong()
}
public fun readFloatLE(): Float = Float.fromBits(readIntLE())
public fun readDoubleLE(): Double = Double.fromBits(readLongLE())
public fun readShortLE(): Short =
((readByte().toInt() and 0xFF) or (readByte().toInt() and 0xFF shl 8)).toShort()
public fun readIntLE(): Int =
((readByte().toInt() and 0xFF)) or
((readByte().toInt() and 0xFF) shl 8) or
((readByte().toInt() and 0xFF) shl 16) or
((readByte().toInt() and 0xFF) shl 24)
}
@@ -0,0 +1,67 @@
/*
* Copyright © 2026 RTAkland
* Author: RTAkland
* Date: 2026/1/25
*/
package cn.rtast.libmc.nbt
@NbtDsl
public class NBTListBuilder(
private val elementType: NBTType,
) {
private val elements = mutableListOf<NBTTag>()
private fun checkType(expected: NBTType) =
require(elementType == expected) { "TAG_List element type must same: expected $elementType, got $expected" }
public fun byte(value: Byte) {
checkType(NBTType.Byte)
elements += NBTTag.ByteTag(value)
}
public fun short(value: Short) {
checkType(NBTType.Short)
elements += NBTTag.ShortTag(value)
}
public fun int(value: Int) {
checkType(NBTType.Int)
elements += NBTTag.IntTag(value)
}
public fun long(value: Long) {
checkType(NBTType.Long)
elements += NBTTag.LongTag(value)
}
public fun float(value: Float) {
checkType(NBTType.Float)
elements += NBTTag.FloatTag(value)
}
public fun double(value: Double) {
checkType(NBTType.Double)
elements += NBTTag.DoubleTag(value)
}
public fun string(value: String) {
checkType(NBTType.String)
elements += NBTTag.StringTag(value)
}
public fun compound(block: CompoundBuilder.() -> Unit) {
checkType(NBTType.Compound)
elements += nbtCompound(block)
}
public fun list(elementType: NBTType, block: NBTListBuilder.() -> Unit) {
checkType(NBTType.List)
val builder = NBTListBuilder(elementType)
builder.block()
elements += builder.build()
}
public fun build(): NBTTag.ListTag = NBTTag.ListTag(elementType, elements)
}
@@ -0,0 +1,96 @@
/*
* Copyright © 2026 RTAkland
* Author: RTAkland
* Date: 2026/1/25
*/
package cn.rtast.libmc.nbt
import cn.rtast.libmc.common.ByteOrder
public interface NBTOutput {
public val order: ByteOrder
public val root: NBTTag.CompoundTag
public fun writeByte(value: Byte)
public fun writeBytes(value: ByteArray)
public fun writeShort(value: Short): Unit =
if (order == ByteOrder.BIG_ENDIAN) writeShortBE(value) else writeShortLE(value)
public fun writeInt(value: Int): Unit =
if (order == ByteOrder.BIG_ENDIAN) writeIntBE(value) else writeIntLE(value)
public fun writeLong(value: Long): Unit =
if (order == ByteOrder.BIG_ENDIAN) writeLongBE(value) else writeLongLE(value)
public fun writeFloat(value: Float): Unit =
if (order == ByteOrder.BIG_ENDIAN) writeFloatBE(value) else writeFloatLE(value)
public fun writeDouble(value: Double): Unit =
if (order == ByteOrder.BIG_ENDIAN) writeDoubleBE(value) else writeDoubleLE(value)
// big endian
public fun writeShortBE(value: Short) {
writeByte(((value.toInt() shr 8) and 0xFF).toByte())
writeByte((value.toInt() and 0xFF).toByte())
}
public fun writeIntBE(value: Int) {
writeByte(((value shr 24) and 0xFF).toByte())
writeByte(((value shr 16) and 0xFF).toByte())
writeByte(((value shr 8) and 0xFF).toByte())
writeByte((value and 0xFF).toByte())
}
public fun writeLongBE(value: Long) {
writeByte(((value shr 56).toInt() and 0xFF).toByte())
writeByte(((value shr 48).toInt() and 0xFF).toByte())
writeByte(((value shr 40).toInt() and 0xFF).toByte())
writeByte(((value shr 32).toInt() and 0xFF).toByte())
writeByte(((value shr 24).toInt() and 0xFF).toByte())
writeByte(((value shr 16).toInt() and 0xFF).toByte())
writeByte(((value shr 8).toInt() and 0xFF).toByte())
writeByte((value.toInt() and 0xFF).toByte())
}
public fun writeFloatBE(value: Float) {
writeIntBE(value.toBits())
}
public fun writeDoubleBE(value: Double) {
writeLongBE(value.toBits())
}
// Little Endian
public fun writeShortLE(value: Short) {
writeByte((value.toInt() and 0xFF).toByte())
writeByte(((value.toInt() shr 8) and 0xFF).toByte())
}
public fun writeIntLE(value: Int) {
writeByte((value and 0xFF).toByte())
writeByte(((value shr 8) and 0xFF).toByte())
writeByte(((value shr 16) and 0xFF).toByte())
writeByte(((value shr 24) and 0xFF).toByte())
}
public fun writeLongLE(value: Long) {
writeByte(((value and 0xFF).toInt()).toByte())
writeByte((((value shr 8) and 0xFF).toInt()).toByte())
writeByte((((value shr 16) and 0xFF).toInt()).toByte())
writeByte((((value shr 24) and 0xFF).toInt()).toByte())
writeByte((((value shr 32) and 0xFF).toInt()).toByte())
writeByte((((value shr 40) and 0xFF).toInt()).toByte())
writeByte((((value shr 48) and 0xFF).toInt()).toByte())
writeByte((((value shr 56) and 0xFF).toInt()).toByte())
}
public fun writeFloatLE(value: Float): Unit = writeIntLE(value.toBits())
public fun writeDoubleLE(value: Double): Unit = writeLongLE(value.toBits())
public fun toByteArray(): ByteArray
}
@@ -0,0 +1,82 @@
/*
* Copyright © 2026 RTAkland
* Author: RTAkland
* Date: 2026/1/25
*/
package cn.rtast.libmc.nbt
public fun NBTInput.readStringTag(): String {
val length = readShort().toInt() and 0xFFFF
val bytes = readBytes(length)
return bytes.decodeToString()
}
public fun NBTInput.readListTag(): NBTTag.ListTag {
val elementTypeId = readByte().toInt() and 0xFF
val elementType = NBTType.fromId(elementTypeId)
val length = readInt()
val list = ArrayList<NBTTag>(length)
repeat(length) { list += readTagPayload(elementType) }
return NBTTag.ListTag(elementType, list)
}
public fun NBTInput.readCompoundTag(): NBTTag.CompoundTag {
val map = LinkedHashMap<String, NBTTag>()
while (true) {
val typeId = readByte().toInt() and 0xFF
if (typeId == 0) break // TAG_End
val name = readStringTag()
val type = NBTType.fromId(typeId)
val payload = readTagPayload(type)
map[name] = payload
}
return NBTTag.CompoundTag(map)
}
public fun NBTInput.readTagPayload(type: NBTType): NBTTag =
when (type) {
NBTType.Byte -> NBTTag.ByteTag(readByte())
NBTType.Short -> NBTTag.ShortTag(readShort())
NBTType.Int -> NBTTag.IntTag(readInt())
NBTType.Long -> NBTTag.LongTag(readLong())
NBTType.Float -> NBTTag.FloatTag(readFloat())
NBTType.Double -> NBTTag.DoubleTag(readDouble())
NBTType.String -> NBTTag.StringTag(readStringTag())
NBTType.ByteArray -> NBTTag.ByteArrayTag(readBytes(readInt()))
NBTType.IntArray -> NBTTag.IntArrayTag(IntArray(readInt()) { readInt() })
NBTType.LongArray -> NBTTag.LongArrayTag(LongArray(readInt()) { readLong() })
NBTType.List -> readListTag()
NBTType.Compound -> readCompoundTag()
NBTType.End -> error("TAG_End no payload")
}
public fun NBTInput.readCompound(): NBTTag {
val map = LinkedHashMap<String, NBTTag>()
while (true) {
val typeId = readByte().toInt()
val type = NBTType.fromId(typeId)
if (type == NBTType.End) break
val nameLen = readShort().toInt() and 0xFFFF
val nameBytes = readBytes(nameLen)
val name = nameBytes.decodeToString()
val value = readTagPayload(type)
map[name] = value
}
return NBTTag.ListTag(NBTType.Compound, map.values.toMutableList())
}
public fun NBTInput.readRootCompound(): NBTCompound {
val rootType = NBTType.fromId(readByte().toInt())
require(rootType == NBTType.Compound) { "Root tag must be TAG_Compound" }
val nameLen = readShort().toInt() and 0xFFFF
val name = readBytes(nameLen).decodeToString()
val root = readCompound()
return NBTCompound(name, root)
}
public fun NBTInput.readNetworkCompound(): NBTCompound {
val root = readCompound()
return NBTCompound("", root)
}
@@ -0,0 +1,77 @@
/*
* Copyright © 2026 RTAkland
* Author: RTAkland
* Date: 2026/1/25
*/
package cn.rtast.libmc.nbt
public sealed class NBTTag(public val type: NBTType) {
public data class ByteTag(val value: Byte) : NBTTag(NBTType.Byte)
public data class ShortTag(val value: Short) : NBTTag(NBTType.Short)
public data class IntTag(val value: Int) : NBTTag(NBTType.Int)
public data class LongTag(val value: Long) : NBTTag(NBTType.Long)
public data class FloatTag(val value: Float) : NBTTag(NBTType.Float)
public data class DoubleTag(val value: Double) : NBTTag(NBTType.Double)
public data class StringTag(val value: String) : NBTTag(NBTType.String)
public data class CompoundTag(val value: MutableMap<String, NBTTag>) : NBTTag(NBTType.Compound)
public data class ListTag(val elementType: NBTType, val value: MutableList<NBTTag>) : NBTTag(NBTType.List) {
public val length: Int get() = value.size
}
public data class IntArrayTag(val value: IntArray) : NBTTag(NBTType.IntArray) {
public val length: Int get() = value.size
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other == null || this::class != other::class) return false
other as IntArrayTag
if (!value.contentEquals(other.value)) return false
if (length != other.length) return false
return true
}
override fun hashCode(): Int {
var result = value.contentHashCode()
result = 31 * result + length
return result
}
}
public data class LongArrayTag(val value: LongArray) : NBTTag(NBTType.LongArray) {
public val length: Int get() = value.size
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other == null || this::class != other::class) return false
other as LongArrayTag
if (!value.contentEquals(other.value)) return false
if (length != other.length) return false
return true
}
override fun hashCode(): Int {
var result = value.contentHashCode()
result = 31 * result + length
return result
}
}
public data class ByteArrayTag(val value: ByteArray) : NBTTag(NBTType.ByteArray) {
public val length: Int get() = value.size
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other == null || this::class != other::class) return false
other as ByteArrayTag
if (!value.contentEquals(other.value)) return false
if (length != other.length) return false
return true
}
override fun hashCode(): Int {
var result = value.contentHashCode()
result = 31 * result + length
return result
}
}
}
@@ -0,0 +1,20 @@
/*
* Copyright © 2026 RTAkland
* Author: RTAkland
* Date: 2026/1/25
*/
package cn.rtast.libmc.nbt
public enum class NBTType(public val id: Byte) {
End(0), Byte(1), Short(2), Int(3),
Long(4), Float(5), Double(6), ByteArray(7),
String(8), List(9), Compound(10),
IntArray(11), LongArray(12);
public companion object {
public fun fromId(id: Int): NBTType =
entries.firstOrNull { it.id.toInt() == id } ?: error("Unknown NBT type id: $id")
}
}
@@ -0,0 +1,64 @@
/*
* Copyright © 2026 RTAkland
* Author: RTAkland
* Date: 2026/1/25
*/
package cn.rtast.libmc.nbt
public fun NBTOutput.writeStringTag(value: String) {
val bytes = value.encodeToByteArray()
writeShort(bytes.size.toShort())
writeBytes(bytes)
}
public fun NBTOutput.writeTagPayload(tag: NBTTag) {
when (tag) {
is NBTTag.ByteTag -> writeByte(tag.value)
is NBTTag.ShortTag -> writeShort(tag.value)
is NBTTag.IntTag -> writeInt(tag.value)
is NBTTag.LongTag -> writeLong(tag.value)
is NBTTag.FloatTag -> writeInt(tag.value.toBits())
is NBTTag.DoubleTag -> writeLong(tag.value.toBits())
is NBTTag.StringTag -> writeStringTag(tag.value)
is NBTTag.ByteArrayTag -> {
writeInt(tag.length)
writeBytes(tag.value)
}
is NBTTag.IntArrayTag -> {
writeInt(tag.length)
tag.value.forEach { writeInt(it) }
}
is NBTTag.LongArrayTag -> {
writeInt(tag.length)
tag.value.forEach { writeLong(it) }
}
is NBTTag.ListTag -> {
writeByte(tag.elementType.id)
writeInt(tag.length)
tag.value.forEach { writeTagPayload(it) }
}
is NBTTag.CompoundTag -> {
for ((name, value) in tag.value) {
writeByte(value.type.id)
writeStringTag(name)
writeTagPayload(value)
}
writeByte(NBTType.End.id)
}
}
}
public fun NBTOutput.writeRootNBTCompound(name: String = ""): ByteArray {
writeByte(NBTType.Compound.id)
writeStringTag(name)
writeTagPayload(root)
return toByteArray()
}
@@ -0,0 +1,28 @@
/*
* Copyright © 2026 RTAkland
* Author: RTAkland
* Date: 2026/1/25
*/
package cn.rtast.libmc.nbt
import cn.rtast.libmc.common.gzipCompress
import cn.rtast.libmc.common.gzipDecompress
import cn.rtast.libmc.common.zlibCompress
import cn.rtast.libmc.common.zlibDecompress
public sealed interface NbtCompressor {
public fun compress(input: ByteArray): ByteArray
public fun decompress(input: ByteArray): ByteArray
public object GZipCompressor : NbtCompressor {
override fun compress(input: ByteArray): ByteArray = input.gzipCompress()
override fun decompress(input: ByteArray): ByteArray = input.gzipDecompress()
}
public object ZlibCompressor : NbtCompressor {
override fun compress(input: ByteArray): ByteArray = input.zlibCompress()
override fun decompress(input: ByteArray): ByteArray = input.zlibDecompress()
}
}
@@ -1,95 +0,0 @@
/*
* Copyright © 2026 RTAkland
* Author: RTAkland
* Date: 2026/9/4
*/
package cn.rtast.libmc.nbt
import cn.rtast.libmc.common._Buffer
import cn.rtast.libmc.common.readVarInt
public class NbtReader(
private val buffer: _Buffer,
private val variant: NbtVariant = NbtVariant.JAVA,
) {
private fun readShort(): Short = buffer.readShort(variant.order)
private fun readInt(): Int = buffer.readInt(variant.order)
private fun readLong(): Long = buffer.readLong(variant.order)
private fun readFloat(): Float = Float.fromBits(readInt())
private fun readDouble(): Double = Double.fromBits(readLong())
private fun readString(): String {
val length = if (variant.isNetwork) buffer.readVarInt() else readShort().toInt() and 0xFFFF
if (length == 0) return ""
return buffer.readBytes(length).decodeToString()
}
private fun readTagType(): Byte = if (variant.isNetwork) buffer.readVarInt().toByte() else buffer.readByte()
public fun readRoot(): Pair<String, NbtCompound> {
val type = readTagType()
require(type == NBTType.COMPOUND) { "Expected Compound Tag (10), got $type" }
val name = readString()
val root = readCompound()
return name to root
}
private fun readCompound(): NbtCompound {
val map = mutableMapOf<String, NBTElement>()
while (true) {
val type = readTagType()
if (type == NBTType.END) break
val name = readString()
map[name] = readPayload(type)
}
return NbtCompound(map)
}
private fun readList(): NbtList {
val elementType = readTagType()
val size = if (variant.isNetwork) buffer.readVarInt() else readInt()
if (size <= 0) return NbtList(elementType, emptyList())
val list = mutableListOf<NBTElement>()
(0 until size).forEach { _ -> list.add(readPayload(elementType)) }
return NbtList(elementType, list)
}
private fun readPayload(type: Byte): NBTElement {
return when (type) {
NBTType.BYTE -> NbtByte(buffer.readByte())
NBTType.SHORT -> NbtShort(readShort())
NBTType.INT -> {
val value = if (variant.isNetwork) buffer.readVarInt().decodeZigZag() else readInt()
NbtInt(value)
}
NBTType.LONG -> NbtLong(readLong())
NBTType.FLOAT -> NbtFloat(readFloat())
NBTType.DOUBLE -> NbtDouble(readDouble())
NBTType.BYTE_ARRAY -> {
val len = if (variant.isNetwork) buffer.readVarInt() else readInt()
NbtByteArray(buffer.readBytes(len))
}
NBTType.STRING -> NbtString(readString())
NBTType.LIST -> readList()
NBTType.COMPOUND -> readCompound()
NBTType.INT_ARRAY -> {
val len = if (variant.isNetwork) buffer.readVarInt() else readInt()
val array = IntArray(len) { readInt() }
NbtIntArray(array)
}
NBTType.LONG_ARRAY -> {
val len = if (variant.isNetwork) buffer.readVarInt() else readInt()
val array = LongArray(len) { readLong() }
NbtLongArray(array)
}
else -> throw IllegalArgumentException("Unknown Tag type: $type")
}
}
}
@@ -1,66 +0,0 @@
/*
* Copyright © 2026 RTAkland
* Author: RTAkland
* Date: 2026/9/4
*/
package cn.rtast.libmc.nbt
public sealed interface NBTElement {
public val typeId: NBTTypeID
}
public data class NbtByte(val value: Byte) : NBTElement {
override val typeId: NBTTypeID = NBTType.BYTE
}
public data class NbtShort(val value: Short) : NBTElement {
override val typeId: NBTTypeID = NBTType.SHORT
}
public data class NbtInt(val value: Int) : NBTElement {
override val typeId: NBTTypeID = NBTType.INT
}
public data class NbtLong(val value: Long) : NBTElement {
override val typeId: NBTTypeID = NBTType.LONG
}
public data class NbtFloat(val value: Float) : NBTElement {
override val typeId: NBTTypeID = NBTType.FLOAT
}
public data class NbtDouble(val value: Double) : NBTElement {
override val typeId: NBTTypeID = NBTType.DOUBLE
}
public data class NbtByteArray(val value: ByteArray) : NBTElement {
override val typeId: NBTTypeID = NBTType.BYTE_ARRAY
override fun equals(other: Any?): Boolean = other is NbtByteArray && value.contentEquals(other.value)
override fun hashCode(): Int = value.contentHashCode()
}
public data class NbtString(val value: String) : NBTElement {
override val typeId: NBTTypeID = NBTType.STRING
}
public data class NbtList(val elementType: Byte, val elements: List<NBTElement>) : NBTElement {
override val typeId: NBTTypeID = NBTType.LIST
}
public data class NbtCompound(val map: Map<String, NBTElement>) : NBTElement {
override val typeId: NBTTypeID = NBTType.COMPOUND
}
public data class NbtIntArray(val value: IntArray) : NBTElement {
override val typeId: NBTTypeID = NBTType.INT_ARRAY
override fun equals(other: Any?): Boolean = other is NbtIntArray && value.contentEquals(other.value)
override fun hashCode(): Int = value.contentHashCode()
}
public data class NbtLongArray(val value: LongArray) : NBTElement {
override val typeId: NBTTypeID = NBTType.LONG_ARRAY
override fun equals(other: Any?): Boolean = other is NbtLongArray && value.contentEquals(other.value)
override fun hashCode(): Int = value.contentHashCode()
}
@@ -1,26 +0,0 @@
/*
* Copyright © 2026 RTAkland
* Author: RTAkland
* Date: 2026/9/4
*/
package cn.rtast.libmc.nbt
public typealias NBTTypeID = Byte
public object NBTType {
public const val END: NBTTypeID = 0
public const val BYTE: NBTTypeID = 1
public const val SHORT: NBTTypeID = 2
public const val INT: NBTTypeID = 3
public const val LONG: NBTTypeID = 4
public const val FLOAT: NBTTypeID = 5
public const val DOUBLE: NBTTypeID = 6
public const val BYTE_ARRAY: NBTTypeID = 7
public const val STRING: NBTTypeID = 8
public const val LIST: NBTTypeID = 9
public const val COMPOUND: NBTTypeID = 10
public const val INT_ARRAY: NBTTypeID = 11
public const val LONG_ARRAY: NBTTypeID = 12
}
@@ -1,19 +0,0 @@
/*
* Copyright © 2026 RTAkland
* Author: RTAkland
* Date: 2026/9/4
*/
package cn.rtast.libmc.nbt
import cn.rtast.libmc.common.ByteOrder
public enum class NbtVariant(
public val order: ByteOrder,
public val isNetwork: Boolean,
) {
JAVA(ByteOrder.BIG_ENDIAN, isNetwork = false),
BEDROCK_DISK(ByteOrder.LITTLE_ENDIAN, isNetwork = false),
BEDROCK_NETWORK(ByteOrder.LITTLE_ENDIAN, isNetwork = true)
}
@@ -1,11 +0,0 @@
/*
* Copyright © 2026 RTAkland
* Author: RTAkland
* Date: 2026/9/4
*/
package cn.rtast.libmc.nbt
internal fun Int.decodeZigZag(): Int = (this ushr 1) xor -(this and 1)
internal fun Int.encodeZigZag(): Int = (this shl 1) xor (this shr 31)