Type-safe Named Binary Tags (NBT) implementation in Kotlin for reading and writing files/streams with a simple and concise builder API.
This project is based on the original NBT specification by Notch (Wayback Machine) with the most recent additions by Mojang (Minecraft Wiki and Wiki.vg).
Maven:
<repositories>
<repository>
<id>jitpack.io</id>
<url>https://jitpack.io</url>
</repository>
</repositories>
<dependency>
<groupId>com.github.MrPNG</groupId>
<artifactId>KotlinNBT</artifactId>
<version>Tag</version>
</dependency>
Gradle Groovy:
repositories {
maven { url 'https://jitpack.io' }
}
dependencies {
implementation 'com.github.MrPNG:KotlinNBT:1.0.0'
}
Gradle Kotlin:
repositories {
maven("https://jitpack.io")
}
dependencies {
implementation("com.github.MrPNG:KotlinNBT:1.0.0")
}
The object NbtIO
is used similarly to javax.imageio.ImageIO
to read/write a NBT TagCompound
. The available
compression methods are: GZIP
, ZLIB
and NONE
(no compression).
val file = File("test.nbt")
val compression = NbtIO.Compression.GZIP
val tagCompound = NbtIO.read(file, compression)
val file = File("test.nbt")
val compression = NbtIO.Compression.GZIP
NbtIO.write(someTagCompound, file, compression)
val nbt = nbt("root") {
compound("testCompound") {
intArray["fibonacciWithoutZero"] = intArrayOf(1, 1, 2, 3, 5, 8, 13, 21)
}
list["testList"] = listOf(
compound {
string["firstString"] = "I'm the first String :)"
string["secondString"] = "I'm the second String, but order is not guaranteed :/"
int["justAnInteger"] = 1
}
)
long["timestamp"] = System.currentTimeMillis()
}
Using println(nbt)
will print a Kotlin-styled tree:
root: Compound = {
testCompound: Compound = {
fibonacciWithoutZero: IntArray = [1, 1, 2, 3, 5, 8, 13, 21]
},
testList: List<Compound> = [
Compound = {
firstString: String = "I'm the first String :)",
justAnInteger: Int = 1,
secondString: String = "I'm the second String, but order is not guaranteed :/"
}
],
timestamp: Long = 1591470914831L
}
Important: according to the NBT specification, the order of the displayed/read tags is not guaranteed. KotlinNBT
prints a TagCompound
using a schema based on the way NBTExplorer does it.
In the example above, the typed values can be obtained with type-safe accessors:
val fibonacci: IntArray = nbt["testCompound"].asTagCompound["fibonacciWithoutZero"].asIntArray
val message: String = nbt["testList"].asTagList[0].asTagCompound["firstString"].asString
val timestamp: Long = nbt["timestamp"].asLong
println(fibonacci.toList())
println(message)
println(timestamp)
prints
[1, 1, 2, 3, 5, 8, 13, 21]
I'm the first String :)
1591470914831
To check the tag types before accessing them (whether they exist or not), properties isTagX
can be used, where X
is
a tag type:
println(nbt["testCompound"].isTagCompound)
println(nbt["timestamp"].isTagFloat)
println(nbt["world"].isTagString)
prints
true
false
false
The provided Tag<T>.clone()
functions deep copy the tag (that is, the tag itself and its children are cloned
recursively) while keeping the type safety:
nbt.clone() // to keep the same name, "root"
nbt.clone("rootClone") // to change the root tag name
nbt["testList"]?.clone("actualList")
KotlinNBT is free and open-source for everyone to enjoy.
If you wish to support the continuous development of this and other projects, you can donate! Of course, I'm always providing support for anyone independently on the donations.
Everyone loves open-source <3