Documentation Index
Fetch the complete documentation index at: https://mintlify.com/mojang/minecraft-creator-tools/llms.txt
Use this file to discover all available pages before exploring further.
The NbtBinary class provides functionality for reading and writing NBT (Named Binary Tag) format, which is used throughout Minecraft for structured data storage.
Overview
NBT is a binary format used in:
level.dat - World settings and metadata
- Block actors (tile entities) - Chests, signs, spawners, etc.
- Entities - Mobs, items, armor stands
- Structure files -
.mcstructure files
- Player data
Constructor
const nbt = new NbtBinary();
nbt.context = 'level.dat'; // Optional context for error messages
Loading NBT Data
fromBinary
(data: Uint8Array, littleEndian: boolean, isVarint: boolean, skipBytes?: number, stringsAreASCII?: boolean, processAsList?: boolean) => number
Parses NBT binary data.Parameters:
data - Binary data to parse
littleEndian - Use little-endian byte order (true for Bedrock)
isVarint - Use varint encoding for lengths
skipBytes - Number of bytes to skip at start (e.g., 8 for level.dat)
stringsAreASCII - Optimize for ASCII strings
processAsList - Parse as list of multiple root tags
Returns: Number of bytes readconst nbt = new NbtBinary();
const bytesRead = nbt.fromBinary(
fileBytes,
true, // littleEndian for Bedrock
false, // no varint
8 // skip 8-byte header in level.dat
);
Writing NBT Data
toBinary
() => Uint8Array | undefined
Serializes the NBT structure to binary format.const bytes = nbt.toBinary();
if (bytes) {
await file.setContent(bytes);
}
Accessing Data
Array of root tags. Most files have a single root.if (nbt.roots && nbt.roots.length > 0) {
const root = nbt.roots[0];
}
Convenience getter for the first root tag.const root = nbt.singleRoot;
if (root) {
const levelName = root.find('LevelName');
console.log(levelName?.valueAsString);
}
Creating NBT Structure
Creates or returns the single root compound tag.const root = nbt.ensureSingleRoot();
root.ensureTag('LevelName', NbtTagType.string).value = 'My World';
root.ensureTag('SpawnX', NbtTagType.int).value = 0;
root.ensureTag('SpawnY', NbtTagType.int).value = 100;
root.ensureTag('SpawnZ', NbtTagType.int).value = 0;
JSON Conversion
Converts NBT structure to JSON object.const json = nbt.getJson();
console.log(JSON.stringify(json, null, 2));
Converts NBT structure to JSON string.const jsonStr = nbt.getJsonString();
NbtBinaryTag
Individual NBT tags are represented by NbtBinaryTag:
Properties
Tag type (compound, list, int, string, etc.).
Tag name (empty for list children).
value
string | number | bigint | bigint[] | number[] | boolean | null
Tag value (type depends on tag type).
Methods
find
(name: string) => NbtBinaryTag | null
Recursively searches for a tag by name.const tag = root.find('LevelName');
if (tag) {
console.log(tag.valueAsString);
}
child
(name: string) => NbtBinaryTag | null
Gets a direct child tag by name.const abilities = root.child('abilities');
const mayFly = abilities?.child('mayfly');
ensureTag
(tagName: string, tagType: NbtTagType) => NbtBinaryTag
Gets or creates a tag.const levelName = root.ensureTag('LevelName', NbtTagType.string);
levelName.value = 'New Name';
addTag
(tagType: NbtTagType, tagName?: string) => NbtBinaryTag
Adds a new tag.const newTag = root.addTag(NbtTagType.int, 'MyValue');
newTag.value = 42;
removeTag
(tagName: string) => boolean
Removes a tag by name.root.removeTag('oldProperty');
Gets all child tags (excludes end tag).for (const child of root.getTagChildren()) {
console.log(`${child.name}: ${child.valueAsString}`);
}
Value Accessors
Gets value as string.const name = tag.valueAsString;
Gets value as integer.const x = tag.valueAsInt;
Gets value as bigint.const time = tag.valueAsBigInt;
Gets value as boolean.const enabled = tag.valueAsBoolean;
Gets list children as numeric array.const version = tag.valueAsNumericArray; // [1, 20, 0]
Parses string value as JSON.const layers = tag.valueAsJSONObject;
NBT Tag Types
enum NbtTagType {
end = 0, // End of compound
byte = 1, // 8-bit signed integer
short = 2, // 16-bit signed integer
int = 3, // 32-bit signed integer
long = 4, // 64-bit signed integer
float = 5, // 32-bit float
double = 6, // 64-bit float
byteArray = 7, // Array of bytes
string = 8, // UTF-8 string
list = 9, // List of tags (same type)
compound = 10, // Named tags
intArray = 11, // Array of ints
longArray = 12 // Array of longs
}
Example: Reading level.dat
import { NbtBinary, NbtTagType } from '@minecraft/creator-tools';
async function readLevelDat(file: IFile) {
await file.loadContent();
const bytes = file.content as Uint8Array;
const nbt = new NbtBinary();
nbt.context = 'level.dat';
// level.dat has 8-byte header before NBT data
nbt.fromBinary(bytes, true, false, 8);
const root = nbt.singleRoot;
if (!root) {
console.error('No root tag found');
return;
}
// Read basic properties
const levelName = root.find('LevelName')?.valueAsString;
const spawnX = root.find('SpawnX')?.valueAsInt;
const spawnY = root.find('SpawnY')?.valueAsInt;
const spawnZ = root.find('SpawnZ')?.valueAsInt;
const gameType = root.find('GameType')?.valueAsInt;
console.log(`World: ${levelName}`);
console.log(`Spawn: (${spawnX}, ${spawnY}, ${spawnZ})`);
console.log(`Game Type: ${gameType}`);
// Read experiments
const experiments = root.find('experiments');
if (experiments) {
const betaApis = experiments.child('gametest')?.valueAsBoolean;
console.log(`Beta APIs: ${betaApis}`);
}
}
Example: Modifying NBT
async function modifyLevelDat(file: IFile) {
await file.loadContent();
const bytes = file.content as Uint8Array;
const nbt = new NbtBinary();
nbt.fromBinary(bytes, true, false, 8);
const root = nbt.ensureSingleRoot();
// Modify properties
root.ensureTag('LevelName', NbtTagType.string).value = 'Modified World';
root.ensureTag('commandsEnabled', NbtTagType.byte).value = 1;
root.ensureTag('showcoordinates', NbtTagType.byte).value = 1;
// Enable experiment
const experiments = root.ensureTag('experiments', NbtTagType.compound);
experiments.ensureTag('gametest', NbtTagType.byte).value = 1;
// Save with 8-byte header
const nbtBytes = nbt.toBinary();
if (nbtBytes) {
const fullBytes = new Uint8Array(nbtBytes.length + 8);
fullBytes.set(nbtBytes, 8);
// Write header (version 10, length)
fullBytes[0] = 10; fullBytes[1] = 0; fullBytes[2] = 0; fullBytes[3] = 0;
fullBytes[4] = nbtBytes.length & 0xFF;
fullBytes[5] = (nbtBytes.length >> 8) & 0xFF;
fullBytes[6] = (nbtBytes.length >> 16) & 0xFF;
fullBytes[7] = (nbtBytes.length >> 24) & 0xFF;
file.setContent(fullBytes);
await file.saveContent();
}
}
Example: Reading Block Actor Data
function parseChestData(nbtBytes: Uint8Array) {
const nbt = new NbtBinary();
nbt.context = 'Chest';
nbt.fromBinary(nbtBytes, true, false, 0, true);
const root = nbt.singleRoot;
if (!root) return;
// Get chest position
const x = root.find('x')?.valueAsInt;
const y = root.find('y')?.valueAsInt;
const z = root.find('z')?.valueAsInt;
console.log(`Chest at (${x}, ${y}, ${z})`);
// Get items
const items = root.find('Items');
if (items) {
const itemList = items.getTagChildren();
console.log(`Contains ${itemList.length} items:`);
for (const item of itemList) {
const name = item.find('Name')?.valueAsString;
const count = item.find('Count')?.valueAsInt;
const slot = item.find('Slot')?.valueAsInt;
console.log(` Slot ${slot}: ${name} x${count}`);
}
}
}
Example: Creating NBT Structure
function createStructure() {
const nbt = new NbtBinary();
const root = nbt.ensureSingleRoot();
// Add basic types
root.ensureTag('name', NbtTagType.string).value = 'My Structure';
root.ensureTag('version', NbtTagType.int).value = 1;
root.ensureTag('size', NbtTagType.list).setListFromArray([16, 16, 16]);
// Add compound
const metadata = root.ensureTag('metadata', NbtTagType.compound);
metadata.ensureTag('author', NbtTagType.string).value = 'Player';
metadata.ensureTag('created', NbtTagType.long).value = BigInt(Date.now());
// Add list of compounds
const blocks = root.ensureTag('blocks', NbtTagType.list);
blocks.childTagType = NbtTagType.compound;
for (let i = 0; i < 10; i++) {
const block = blocks.addTag(NbtTagType.compound);
block.ensureTag('pos', NbtTagType.list).setListFromArray([i, 0, 0]);
block.ensureTag('state', NbtTagType.int).value = 0;
}
// Serialize
const bytes = nbt.toBinary();
return bytes;
}
Error Handling
The NBT classes implement IErrorable:
const nbt = new NbtBinary();
nbt.fromBinary(bytes, true, false, 8);
if (nbt.isInErrorState) {
console.error('NBT parsing errors:');
for (const error of nbt.errorMessages || []) {
console.error(` ${error.message}`);
if (error.context) {
console.error(` Context: ${error.context}`);
}
}
}