8000 GitHub - uinnn/nbt: Compact, low-memory footprint and efficient NBT implementation
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

uinnn/nbt

Repository files navigation

Named Binary Tag (NBT) Implementation in Kotlin

Introduction

Enhanced Named Binary Tag implementation writen in Kotlin.

Features

  • Support for Varied Data Types: Primitive and complex types.

  • Custom Type Creation: Easily create new types as you need.

  • Optimized Memory Utilization: Uses specialized types to decrease memory usage.

  • Compact Design: This is designed to be simple, so, is simple.

  • Multiple Compression: Various compressions formats. GZIP, ZIP, ZLIB, ZSTD, NONE.

  • Kotlin Serialization: Implementation of Kotlinx Serialization as NBT

Future features

  • Interoperability: Ability to interoperate with this NBT implementation to Minecraft NBT
  • SNBT Support: Support for SNBT (Stringified Named Binary Tag)

How to use

NBT is stored in jitpack repository, so all you need is here:

repositories {
  maven("https://jitpack.io")
}

dependencies {
  implementation("com.github.uinnn:nbt:1.0.1")
}

Minecraft NBT Overview

The Minecraft NBT is very nice for their use, perhaps some bad things, it fit in their purpose, but we can always made things bett 9751 er! Minecraft NBT overview:

  1. Empty
  2. Byte
  3. Short
  4. Int
  5. Long
  6. Float
  7. Double
  8. ByteArray
  9. String
  10. List
  11. Compound
  12. IntArray
  13. LongArray - Introduced in version 1.13+

Extended NBT Types

In addition to these previous NBT provided by Minecraft, this implementation introduces 15 new types:

  1. Char: Simple Char.
  2. Boolean: Minecraft uses a Byte Tag to store boolean, in this implementation, we use a Byte too, but, with support to get the 8 bits of the byte, making possible to store 8 boolean in one Boolean Tag. Optimizing this way 8x more memory
  3. ArraySet: A Set implementation using an array.
  4. HashSet: A Set implementation using hashes
  5. ShortArray: Simple ShortArray.
  6. FloatArray: Simple FloatArray.
  7. DoubleArray: Simple DoubleArray.
  8. CharArray: Simple CharArray.
  9. BooleanArray: Default BooleanArray Type. Stores 1 boolean per byte
  10. PackedBooleanArray: Packed BooleanArray Type. Stores up to 8 boolean per byte, similar to BitSet
  11. UUID: Simple UUID.
  12. 24 Bits: An 24 bits (3 bytes) stored integer.
  13. 40 Bits: An 40 bits (5 bytes) stored long.
  14. 48 Bits: An 48 bits (6 bytes) stored long.
  15. 56 Bits: An 56 bits (7 bytes) stored long.

Advantages Over Minecraft NBT Implementation

Inline Classes

We use Kotlin inline classes, so no more extra memory allocation.

Buffered Implementation

Arrays Type (ShortArray, IntArray, LongArray, etc...) is firstly buffered to ByteArray and them serialized, this enhances overall performance and makes the compression algorithms better.

FastUtil

We use FastUtil collection types, enhancing more the performance.


Usage

Simple overall usage

  val compound = compound {
    set("Name", "Test")
    set("Version", "1.12")
    set("Patch", 7)
    // multiple booleans
    set("Available", true, false, false)
    set("Authors", tagListOf("uin", "other"))
  }
  
  // write
  TagIO.writeStream(stream, compound)
  TagIO.writeFile(file, compound)
  
  // read
  val loaded = TagIO.readStream(stream)
  val loaded = TagIO.readFile(file)
  
  val name = compound.string("Name")
  val version = compound.string("Version", default = "1.0")
  val authors = compound.stringList("Authors")

  // getting multiple booleans
  val available = compound.booleanTag("Available")
  val availableForWindows = available[0]
  val availableForLinux = available[1]
  val availableForMac = available[2]

  // usage with Kotlinx Serialization
  @Serializable
  data class A(val value: Int, val value2: String)
  
  @Serializable
  data class B(val a: A, val b: A)
  
  val a = A(1, "a")
  val b = A(2, "b")
  
  val encoded = TagIO.encodeToBytes(B(a, b))
  val decoded = TagIO.decodeFromBytes<B>(encoded)
  
  println(decoded) // B(a=A(value=1, value2="a"), b=A(value=2, value2="b"))
  
  // other encode functions
  TagIO.encodeToStream(stream, a)
  TagIO.encodeToFile(file, a)

Creating a custom type

In this example we gonna create a UUID NBT type!

// don't forget to set as inline class!
@JvmInline
value class UUIDTag(val value: UUID) : Tag {
  
  // this allows we get any value in the tag if we don't know the type
  override val genericValue get() = value
  
  // the type of this tag
  override val type get() = Type
  
  // the write function is used to save tag value to data output
  override fun write(data: DataOutput) {
    data.writeLong(value.mostSignificantBits)
    data.writeLong(value.leastSignificantBits)
  }
  
  // creates a copy of the tag, in some cases this can be useful
  // but not for this example
  override fun copy(): UUIDTag = this
  
  override fun toString() = value.toString()
  
  // we also need to create a type to loading them back.
  object Type : TagType<UUIDTag>() {
    override fun load(data: DataInput): UUIDTag {
      return UUIDTag(UUID(data.readLong(), data.readLong()))
    }
  }
}

// registering the type
TagTypes.registerType(UUIDTag.Type)

About

Compact, low-memory footprint and efficient NBT implementation

Resources

Stars

Watchers

Forks

Packages

No packages published

Languages

0