The NBTDoc format is a format for documenting NBT structures. It has many similarities to Rust's type definitions.
Symbol | Meaning |
---|---|
str |
literal |
A* | A zero or more times |
A+ | A one or more times |
A? | A zero or one times |
A | B | Either A or B |
[ A B C ] |
One of the literals A , B , or C |
[ A -Z ] |
Any literal from A to Z |
( A ) | General grouping |
NAME | A referenced token rule |
Name | A referenced parser rule |
\n | A line ending |
An NBTDoc file is made up of a list of compound definitions, enum definitions, module declarations,
use
clauses, and describes
clauses.
The Following Section describes syntax in two forms. the syntax preceded with SYNTAX (TOKEN) cannot have any whitespace or tokens in between the indiviual "rules". The syntax preceded with SYNTAX can have whitespace and standard comments (starting with //
, but not ///
, and going until the end of the line). The full file has this syntax:
SYNTAX
File:
(
CompoundDef
| EnumDef
| ModDecl
| UseClause
| DescribeClause
| InjectClause
)*
SYNTAX (TOKEN)
IDENT:
[A
-Z
a
-z
_
] [A
-Z
a
-z
0
-9
_
]*
An identifier is the main form of names in the NBTDoc format.
SYNTAX (TOKEN)
IDENT_PATH:
(::
)? ( IDENT |super
) (::
( IDENT |super
) )*
An identifier path is the way to reference items from another module. If it starts with ::
, the resultant path will start at the global root, not the "crate" root. When one of the parts of the path is super
, it will reference the parent module.
SYNTAX (TOKEN)
MINECRAFT_IDENT:
[a
-z
_
-
]*:
[a
-z
_
-
]* (/
[a
-z
_
-
]* )*
Minecraft identifiers are just namespaced paths, just like the namespaced resource path in minecraft
SYNTAX (TOKEN)
INTEGER:
0
|-
? [1
-9
] [0
-9
]*
A signed integer
SYNTAX (TOKEN)
FLOAT:
-
? [0
-9
]+ FLOAT_EXPONENT?
|-
? [0
-9
]*.
[0
-9
]+ FLOAT_EXPONENT?FLOAT_EXPONENT:
[e
E
] [-
+
]? [0
-9
]+
A signed floating point number
SYNTAX (TOKEN)
STRING:
"
( ~["
\
UNICODE_CC ] |\
[b
n
f
r
t
\
"
] )*"
A string literal. Cannot contain any control characters (UNICODE_CC). Can be escaped with a \
, and the valid escape characters are \b
, \n
, \f
, \r
, t
, \\
, \"
.
SYNTAX
DocComments:
DOC_COMMENT*SYNTAX (TOKEN)
DOC_COMMENT:
///
~[ \n ]* ( \n | EOF )
Doc comments are the way to attatch descriptions to parts of the format. Each doc comment takes up the whole line, and multiple will get concatenated together to make the description. Doc comments should use Markdown for syntax, but don't have to
SYNTAX
CompoundDef:
DocCommentscompound
IDENT ExtendClause?{
CompoundFields?}
ExtendClause:
extends
( IDENT_PATH | REGISTRY_INDEX )CompoundField:
DocComments KEY?
?:
FieldTypeCompoundFields:
CompoundField (,
CompoundField )*
Compound Definitions are the way to describe patterns of compound tags.
The compound itself can have doc comments, and each field can have doc comments.
The extends
clause is used to create inheritance, and it can be another named compound or a registry index.
Each key can be an identifer, or a string in the case that the NBT key cannot be expressed as an identifier.
SYNTAX
FieldType:
byte
IntRange[
]
UnsignedRange // Byte Array
|int
IntRange[
]
UnsignedRange // Int Array
|long
IntRange[
]
UnsignedRange // Long Array
|boolean
// Byte (0b or 1b)
|byte
IntRange // Byte
|short
IntRange // Short
|int
IntRange // Int
|long
IntRange // Long
|float
FloatRange // Float
|double
FloatRange // Double
|string
// String
|[
FieldType]
UnsignedRange // List
| RegistryIndex // Compound (dynamically indexed)
|id
(
MINECRAFT_IDENT)
// String (with id validation)
| IDENT_PATH // Compound or Enum
|(
( FieldType (|
FieldType )* )?)
// Union typeIntRange:
@
( INTEGER..
INTEGER?
|..
? INTEGER )UnsignedRange:
@
( (0
| [1
-9
] [0
-9
] * )..
(0
| ( [1
-9
] [0
-9
] * ) )?
|..
? (0
| [1
-9
][0
-9
] )* )
Field Types
The field types describes all of the available NBT types.
All of the array types have an integer range and a natural range. The integer is range is the range which all of the items
have to be within, and the natural range is the range of the length of the list.
The byte, short, int, long, float, and double all have their respective ranges that the value must be within.
The list type contains another field type, which is the lists item, and a natural range which the length of the list must be
within.
The dynamically indexed compound accesses the registry specified by the Minecraft identifier with the ID at the path
described in the square brackets.
The string with id validation must be a valid minecraft identifier and must be in the registry described by the Minecraft
identifier in the parenthesis.
The compound or enum is just the name of a compound or enum.
It can be defined in the current file or in another file, with it being accessed by the indentifier path.
If the item that the name points to is a compound, the value should be a compound, otherwise if the item is an enum,
the type of the value should be the type of the enum.
The union type allows for a field that can have different types. These types must be distinguishable.
If the union type has no field types inside of it, it signifies that the field does not exist.
Ranges
The ranges are almost identical to minecraft's range syntax.
They are preceded with an @
, and they can be in one of the four forms:
- VALUE_1
..
VALUE_2 - VALUE_1 <= x <= VALUE_2 - VALUE
..
- VALUE <= x ..
VALUE - x <= Value- VALUE - x = Value
Note that these ranges are always inclusive.
There are 3 types of ranges
- Integer ranges, where the values may be signed integers.
- Unsigned integer ranges, where the values may be unsigned integers.
- Float ranges, where the values may be signed floating point numbers.
SYNTAX
RegistryIndex:
MINECRAFT_IDENT[
FIELD_PATH]
SYNTAX (TOKEN)
FIELD_PATH:
FIELD_PATH_KEY (.
FIELD_PATH_KEY )*
Registry indexes are the way to get dynamic data. They can be used as a field value or in a compound's extends
clause.
When the field path key is super
the current tag's parent will be accessed.
SYNTAX
EnumDef:
DocCommentsenum
(
ENUM_TYPE)
IDENT{
EnumField (,
EnumField )*}
EnumField:
DocComments IDENT=
INTEGER | FLOAT | STRINGSYNTAX (TOKEN)
ENUM_TYPE:
byte
|short
|int
|long
|string
|float
|double
Enums are the primary way to associate limited data with understandable names. Each enum has a number of fields that the value must be one of. The data of the enum must match the type of the enum.
- byte - integer
- short - integer
- int - integer
- long - integer
- string - string
- float - float
- double - float
If a value has an invalid type it will not parse
SYNTAX
ModDecl:
mod
IDENT;
Module declarations describe what children modules this module has.
If this current file is a mod.nbtdoc
file, then the children will be accessed as siblings (in ./
).
If this file has another name (ex.nbtdoc
), then all of the children modules will be checked for in ./ex/
.
The name of the file is the identifier in the delcaration.
For a mod IDENT;
, if IDENT.nbtdoc
cannot be found, then the file IDENT/mod.nbtdoc
will be read from.
SYNTAX
UseClause:
export
?use
IDENT_PATH;
The use clause is the recommended way to import external names. The target must be a compound or an enum.
If the export
keyword is in front, then the imported name will be re-exported along with the rest of the names in this file. This is primarily useful for utility modules.
SYNTAX
DecribeClause:
IDENT_PATHdescribes
MINECRAFT_IDENT ([
MINECRAFT_IDENT (,
MINECRAFT_IDENT )*]
)?;
The describe clause is the way to interface between the compound definitions and registrys. The ident path is the name of the target item,which will be the one associated with the objects inside the registry specified by the Minecraft identifier outside the sqaure brackets. The Minecraft identifiers inside the square brackets will be mapped to the specified compound. If the square brackets and idenitifers inside of them are not present, the specified compound will be used as the default for the registry.
SYNTAX
InjectClause:
inject
( CompoundInject | EnumInject )CompoundInject:
compound
IDENT_PATH{
CompoundFields?}
EnumInject:
enum
(
ENUM_TYPE)
IDENT_PATH{
EnumField (,
EnumField )*}
The inject clause gives support for injecting data into other items. The specified fields will be inserted to the targeted item. The item targeted does not have to be loaded in yet, and injects will be loaded retroactively. If two injects target the same item, the order they will be applied is not defined, and modules should avoid injecting to the same place twice. The injected field will always overwrite the source field however.