Skip to content
This repository has been archived by the owner on Jan 28, 2024. It is now read-only.
/ nbt-blacksmith Public archive

A c++ library for parsing NBT tags (Minecraft)

License

Notifications You must be signed in to change notification settings

max-ishere/nbt-blacksmith

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

26 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

NBT Blacksmith

A C++ library for parsing, editing and serialising NBT data used in Java edition Minecraft.

I should warn you that this is not a finished library. Also I might rewrite it later but for now I stopped working on this

Documentation

Currently the only docs are in tests/README.org, I will be figuring out a way to generate a github.io soon probably.

That readme I mentioned is just a description of what tests do and I may get rid of it if that readme will prevent me from just rewriting the tests or changing my mind about which implementation seems more logical or intuituve.

Scope and purpose

All started with an idea to make a procedural world generator, but since minecraft uses the same format for all it’s files this became a general purpose parser for NBT.

In real use case just using this library is insufficient since it doesn’t handle compression which is present in almost all minecraft files. Thus you will need to use gzip or zlib for decompression purposes.

This library also doesn’t read data from the file directly and instead uses a custom implementation of stream to access data. This in my opinion is better than using fstream since you can parse anything you really want and you are not restricted to compression type, position of the data in the file and the way you save/retrieve data from the file (FILE* vs fstream vs iostream, etc). And there is a safeguard build into the stream implementation to prevent infinite recursion after you run out of data.

Currently the development has stopped and I am adding Google test to catch any bugs and I know there are many. After all the code is finished I will get to work on increasing performance and efficiency.

Prerequisites

You must have basic knowledge of C++ and some understanding of NBT.

Building the library

It is a CMake project so all you need is this line in the terminal:

# run this in the root of the project
$ cmake -S . -B build

You should see CMake build an object library and automatically run google test. There is no sample executable yet.

About NBT standart

Quote from Web Archieve: NBT specification by Notch:

NBT (Named Binary Tag) is a tag based binary format designed to carry large amounts of binary data with smaller amounts of additional data. An NBT file consists of a single GZIPped Named Tag of type TAG_Compound.

A Named Tag has the following format:

byte tagType
    TAG_String name
    [payload]
  

There were originally 10 data types, but since snapshot 12w07a, (release version 1.2.1)[fn:1] 2 more tags have beed added making 12 total. Here is a list of all the tags:

NameID
End of compoud0
Byte1
Short2
Int3
Long4
Float5
Double6
Byte Array7
String8
List9
Compound10
Int Array11
Long Array12

Where: ID is byte tagType from NBT specs above.

Implementation

If you spend some time reading the specs by Notch you will soon realize that there are 4 categories (kinds) of NBT tags[fn:2]:

Primitive
A non-array type
  • Byte
  • Short
  • Int
  • Long
  • Float
  • Double
  • String
Array
Mono-type non-recusrive array container
  • Byte Array
  • Int Array
  • Long Array
List
Potentially[fn:3] recursive and multi-type array container
Compound
Multitype potentially recursive container

Attempting to create an object of invalid tag (e.g. ArrayTag<unsigned int> instead of signed version) will result in undefined reference to [Kind]Tag::type().

Footnotes

[fn:1] Minecraft Wiki: Anvil file format.

[fn:2]End tag is excluded from the list since it is useless and dangerous to keep in memory as a class or struct, except for one case (list of end tags) where it is useless as a separate type either.

[fn:3] ListTag<ListTag<...> > is totally possible and in fact is part of minecraft files.

Even though the nested ListTag has a defined type, that type is undefined at a parent level (well, it is defined, but it’s a list, which is ambigious).

The above makes ListTag recursive and multitype.

About

A c++ library for parsing NBT tags (Minecraft)

Topics

Resources

License

Stars

Watchers

Forks