An implementation of Minecraft's NBT format for kotlinx.serialization.
Technical information about NBT can be found here.
NbtTag
classes, with convenient builder DSLsNbt
and StringifiedNbt
are used to encode/decode @Serializable
data.
import net.benwoodworth.knbt.*
val nbt = Nbt {
variant = NbtVariant. // Java, Bedrock, BedrockNetwork
compression = NbtCompression. // None, Gzip, Zlib
//compressionLevel = null // in 0..9
//encodeDefaults = false
//ignoreUnknownKeys = false
//serializersModule = EmptySerializersModule
}
val snbt = StringifiedNbt {
//prettyPrint = false
//prettyPrintIndent = " "
//encodeDefaults = false
//ignoreUnknownKeys = false
//serializersModule = EmptySerializersModule
}
// ByteArray
byteArray = nbt.encodeToByteArray(data)
data = nbt.decodeFromByteArray(byteArray)
// NbtTag
nbtTag = nbt.encodeToNbtTag(data)
data = nbt.decodeFromNbtTag(nbtTag)
// Okio Sink/Source (Multiplatform)
nbt.encodeToSink(data, sink)
data = nbt.decodeFromSource(source)
// OutputStream/InputStream (JVM)
nbt.encodeToStream(data, outputStream)
data = nbt.decodeFromStream(inputStream)
// SNBT String
string = snbt.encodeToString(data)
data = snbt.decodeFromString(string)
Serializable classes will have their @SerialName
used for the root tag's name.
@Serializable
@SerialName("root")
class Example(val string: String, val int: Int)
// Serializes to: {root : {string : "Hello, world!", int : 42}}
nbt.encodeToNbtTag(Example(string = "Hello, World!", int = 42))
import kotlin.io.path.*
import net.benwoodworth.knbt.*
val file = Path("file.nbt")
val nbt = Nbt {
TODO()
}
// Read from file
val tag: NbtTag = file.inputStream().use { input ->
nbt.decodeFromStream(input)
}
// Write to file
file.outputStream().use { output ->
nbt.encodeToStream(tag, output)
}
sealed interface NbtTag
class NbtByte : NbtTag
class NbtShort : NbtTag
class NbtInt : NbtTag
class NbtLong : NbtTag
class NbtFloat : NbtTag
class NbtDouble : NbtTag
class NbtString : NbtTag
class NbtByteArray : NbtTag, List<Byte>
class NbtIntArray : NbtTag, List<Int>
class NbtLongArray : NbtTag, List<Long>
class NbtList<T : NbtTag> : NbtTag, List<T> // Only contains entries of a single type
class NbtCompound : NbtTag, Map<String, NbtTag>
NbtTag
sNbtTag
s can be created with constructors and builder functions:
val nbtByte = NbtByte(5)
val boolean = NbtByte(true)
val nbtIntArray = NbtIntArray(intArrayOf(1, 2, 3, 4, 5))
val nbtListOfStrings = buildNbtList {
add("these")
add("are")
add("strings")
}
val nbtCompound = buildNbtCompound {
put("int", 1)
put("string", ":)")
put("byteArray", byteArrayOf(1, 1, 2, 3, 5, 8))
putNbtList("floatList") {
add(3f)
add(1f)
add(4f)
}
}
Using the same version of kotlinx.serialization is recommended since parts of its API required for custom formats are still experimental, and newer versions may have binary-incompatible changes that could break knbt's implementation.
While in beta, all new minor releases (v0.#.0) will have breaking API/functionality changes. Read the release notes for information.
Replacement refactorings will be provided where possible for broken APIs. Change the minor version one at a time (e.g. 0.1.0 -> 0.2.0 -> 0.3.0) and apply quick fixes. Deprecated APIs will then be removed in 0.#.1 releases.
plugins {
kotlin("jvm") version "1.9.23" // or kotlin("multiplatform"), etc.
//kotlin("plugin.serialization") version "1.9.23"
}
repositories {
mavenCentral()
//maven("https://s01.oss.sonatype.org/content/repositories/snapshots/")
}
dependencies {
implementation("net.benwoodworth.knbt:knbt:$knbt_version")
//implementation("com.squareup.okio:okio:3.9.0")
}