Validation of an NBT tag comes in two steps. The first step is to traverse through the compounds until you reach the correct tag, then for the second step verify that the data is valid based on the compound.
Traversal of the resultant data structure is designed to be much easier than that of mc-nbt-paths
.
The way the library references other items is through the get_compound
, get_enum
, and get_module
methods on Root
.
To use those functions, just pass in the Index<CompoundTag>
, Index<EnumItem>
, or Index<Module>
respectively.
If you are using the serialized data structure, just index the array compound_arena
, enum_arena
, or module_arena
respectively.
The fields of a compound tag are stored in an enum called NbtValue
. The only types that can be traversed further is the
Compound
type, the List
type, the Index
type, and the Or
type.
- For the
Compound
type, the field is just anotherIndex<CompoundTag>
or a registry reference, which points to another compound. If the field is not present in the compound, then check the compound in thesupers
field, and repeat until there are nosupers
.- If the
supers
field isCompound
, just get the compound specified by the index - If the
supers
field isRegistry
, follow the steps specified for theIndex
type below.
- If the
- For the
List
type, the item type is just in the fieldvalue_type
- For the
Index
type, to get the next item, access the registry specified bytarget
with the value of the NBT atpath
.- To traverse the NBT value in accordance to
path
, for each element inpath
:- if the variant is
Super
, go to the parent of the current tag. - if the variant is
Child(v)
, go to the child of the current tag namedv
.
- if the variant is
- Note that you cannot go into lists through
Child
, as there is no way to get the index. When going up withSuper
, go up to the next compound. - When you find the value that contains the id, use
Root::get_regitry_item
to get the next index. If that NBT value is not present, you must use the registry default if it exists. Note that if this is directly inside anOr
type, and the field is not present, it counts as a failure for theOr
.
- To traverse the NBT value in accordance to
- For the
Or
type, check eachNbtValue
in order. If one succeeds, use that entry.
Repeat this for each part of the path, and at the end you should be at the correct tag. The validator should create an error if it needs to traverse an untraversable tag. Once it reaches the end, it may proceed onto the value validation.
Given an NbtValue
which is the type you are validating the tag against:
-
Check that the type of the tag is correct. The list of
NbtValue
variants to NBT types is as followsNbtValue
VariantNBT Type Boolean
TagByte
Byte
TagByte
Short
TagShort
Int
TagInt
Long
TagLong
Float
TagFloat
Double
TagDouble
String
TagString
ByteArray
TagByteArray
IntArray
TagIntArray
LongArray
TagLongArray
Compound
TagCompound
Enum
Based on type of enum List
TagList
Index
TagCompound
Id
TagString
Or
Based on entries - For
Enum
, get theEnumItem.et
. The variant directly corresponds to the nbt value type - For
Or
, test each type. If none match, then the type doesn't match. If multiple types match, you will have to validate for each of those types.
- For
-
Based on the type. All ranges are top inclusive
Boolean
: Test that the value is either1b
,0b
,true
orfalse
.Byte
: Test that the value is within the range and optionally that it is nottrue
orfalse
.Short
,Int
,Long
,Float
,Double
,String
: Test that the value is within the range.ByteArray
,IntArray
,LongArray
: Test that the all of the values is within the value range, and that the length is within the length range.Compound
: Test that the fields of the value match the specified compound's fields. After all of the fields in the compound have been checked, check all of the fields in thesupers
compound that are not in the original compound. Repeat this as many times as nescessary until there are no more parent compounds.Enum
: Test that the value is one of the values listed in the enum.List
: Test that the all of the entries of the value match the specified value type and that the length of the list is within the range.Index
: Test that the compound pointed to by theIndex
type matches the value.Id
: Test that the value is a valid ID of the specified target registry.Or
: Test that at least one of the entries matches the value.
When traversing through the serialized form of the data, refer to the TypeScript definition file for
the details of the actual format. Most of the data is the same, except that using the Index
struct needs to be done
manually. Also note that the generic type of Index<T>
is erased when serializing data, although it should not be ambigious
to know which arena to use, based on the context of the structure. Another caveat of using the JSON serialized data in a
language that does not support 64 bit integers is the loss of precision for i64
ranges and enums.