/KotlinNBT

NBT parser written in Kotlin with a builder API and type safety

Primary LanguageKotlinMIT LicenseMIT

Build Status Kotlin JitPack License: MIT Donation

KotlinNBT

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).

Installation

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")
}

Usage

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).

Reading from file

val file = File("test.nbt")
val compression = NbtIO.Compression.GZIP

val tagCompound = NbtIO.read(file, compression)

Writing to file

val file = File("test.nbt")
val compression = NbtIO.Compression.GZIP

NbtIO.write(someTagCompound, file, compression)

NBT builder

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.

Type safety

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

Cloning tags

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")

Donate

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