@minecraft/creator-tools
Version:
Minecraft Creator Tools command line and libraries.
325 lines (322 loc) • 14.3 kB
JavaScript
"use strict";
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const NbtBinaryTag_1 = __importStar(require("./NbtBinaryTag"));
const Utilities_1 = __importDefault(require("./../core/Utilities"));
const Log_1 = __importDefault(require("../core/Log"));
const DataUtilities_1 = __importDefault(require("../core/DataUtilities"));
class NbtBinary {
roots = null;
context;
isInErrorState;
errorMessages;
static MAX_ARRAY_LENGTH = 10_000_000;
static MAX_STRING_LENGTH = 1_000_000;
get singleRoot() {
if (this.roots === null) {
return null;
}
if (this.roots.length === 0) {
return null;
}
if (this.roots.length !== 1) {
this._pushError("Unexpectedly did not find a single root (" + this.roots.length + ")");
}
return this.roots[0];
}
_pushError(message, contextIn) {
this.isInErrorState = true;
if (this.errorMessages === undefined) {
this.errorMessages = [];
}
let contextOut = undefined;
if (contextIn) {
contextOut = this.context ? this.context + "-" + contextIn : contextIn;
}
else {
contextOut = this.context;
}
Log_1.default.error(message + (contextOut ? " " + contextOut : ""));
this.errorMessages.push({
message: message,
context: contextOut,
});
}
_getVarInt(data, index) {
let bytesRead = 0;
let result = 0;
let currentByte = 0;
do {
currentByte = data[index];
const currentByteVal = currentByte & 0b01111111;
result |= currentByteVal << (7 * bytesRead);
bytesRead++;
if (bytesRead > 5) {
throw new Error("VarInt is unexpectedly large");
}
} while ((currentByte & 0b10000000) !== 0);
return {
value: result,
bytesRead: bytesRead,
};
}
getJsonString() {
return JSON.stringify(this.getJson());
}
getJson() {
if (this.roots === null) {
return {};
}
if (this.roots.length === 1) {
return this.roots[0].getJson();
}
throw new Error("Unexpected multiple roots.");
}
toBinary() {
if (this.roots === undefined || this.roots === null) {
return undefined;
}
let byteSize = 0;
for (let i = 0; i < this.roots.length; i++) {
byteSize += this.roots[i].getByteSize();
}
const ab = new ArrayBuffer(byteSize);
const bytes = new Uint8Array(ab);
let bytesWrittenAll = 0;
for (let i = 0; i < this.roots.length; i++) {
bytesWrittenAll += this.roots[i].writeBytes(bytes, bytesWrittenAll, true);
}
Log_1.default.assert(bytesWrittenAll === byteSize, "Unexpectedly did not write full NBT.");
return bytes;
}
ensureSingleRoot() {
if (this.roots) {
if (this.roots.length !== 1) {
throw new Error("Unexpected root count.");
}
return this.roots[0];
}
this.roots = [];
this.roots.push(new NbtBinaryTag_1.default(NbtBinaryTag_1.NbtTagType.compound, "", false));
return this.roots[0];
}
fromBinary(data, littleEndian, isVarint, skipBytes, stringsAreASCII, processAsList) {
const tagStack = [];
const listCountStack = [];
const listTypeStack = [];
this.roots = [];
let i = 0;
if (skipBytes !== undefined) {
i = skipBytes;
}
if (!stringsAreASCII) {
stringsAreASCII = false;
}
while (i < data.length) {
let tagType = NbtBinaryTag_1.NbtTagType.unknown;
let name = "";
let isListChild = false;
if (tagStack.length === 0 || tagStack[tagStack.length - 1].type !== NbtBinaryTag_1.NbtTagType.list) {
tagType = data[i++];
if (tagType > 13 && tagType !== 99) {
this._pushError("Unexpected NBT tag type: " + tagType);
}
if (tagType !== NbtBinaryTag_1.NbtTagType.end) {
let nameLength = 0;
if (isVarint) {
const result = this._getVarInt(data, i);
nameLength = result.value;
i += result.bytesRead;
}
else {
nameLength = data[i++];
nameLength += data[i++] * 256;
}
if (nameLength < 0 || nameLength > NbtBinary.MAX_STRING_LENGTH) {
this._pushError("Invalid NBT name length: " + nameLength);
return 0;
}
for (let j = 0; j < nameLength; j++) {
if (i >= data.length) {
this._pushError("Unexpected end of data while reading NBT name");
return 0;
}
name += String.fromCharCode(data[i++]);
}
}
else if (tagStack.length === 0) {
break;
}
} // we're in list sub tag parsing mode
else {
tagType = listTypeStack[tagStack.length - 1];
isListChild = true;
}
const activeTag = new NbtBinaryTag_1.default(tagType, name, isListChild);
if (tagStack.length === 0) {
this.roots.push(activeTag);
} // if (activeTag.type !== NbtTagType.end)
else {
const parentTag = tagStack[tagStack.length - 1];
if (parentTag.type === NbtBinaryTag_1.NbtTagType.list &&
(parentTag.childTagType === undefined || parentTag.childTagType === NbtBinaryTag_1.NbtTagType.unknown)) {
parentTag.childTagType = activeTag.type;
}
parentTag.childrenWithEnd.push(activeTag);
}
if (tagStack.length > 0 && tagStack[tagStack.length - 1].type === NbtBinaryTag_1.NbtTagType.list) {
listCountStack[tagStack.length - 1]--;
if (listCountStack[tagStack.length - 1] === 0) {
tagStack.pop();
}
}
if (activeTag.type === NbtBinaryTag_1.NbtTagType.compound) {
tagStack.push(activeTag);
}
else if (activeTag.type === NbtBinaryTag_1.NbtTagType.end) {
tagStack.pop();
if (tagStack.length === 0 && !processAsList) {
break;
}
}
else if (activeTag.type === NbtBinaryTag_1.NbtTagType.byte) {
activeTag.value = DataUtilities_1.default.getSignedByte(data[i++]);
}
else if (activeTag.type === NbtBinaryTag_1.NbtTagType.byteArray) {
const arrayLength = DataUtilities_1.default.getSignedInteger(data[i++], data[i++], data[i++], data[i++], littleEndian);
if (arrayLength < 0 || arrayLength > NbtBinary.MAX_ARRAY_LENGTH || i + arrayLength > data.length) {
this._pushError("Invalid NBT byteArray length: " + arrayLength);
return 0;
}
const numberArray = [];
for (let j = 0; j < arrayLength; j++) {
numberArray.push(DataUtilities_1.default.getSignedByte(data[i++]));
}
activeTag.value = numberArray;
}
else if (activeTag.type === NbtBinaryTag_1.NbtTagType.list) {
activeTag.type = NbtBinaryTag_1.NbtTagType.list;
tagStack.push(activeTag);
listTypeStack[tagStack.length - 1] = data[i++];
listCountStack[tagStack.length - 1] = DataUtilities_1.default.getSignedInteger(data[i++], data[i++], data[i++], data[i++], littleEndian);
}
else if (activeTag.type === NbtBinaryTag_1.NbtTagType.intArray) {
const arrayLength = DataUtilities_1.default.getSignedInteger(data[i++], data[i++], data[i++], data[i++], littleEndian);
if (arrayLength < 0 || arrayLength > NbtBinary.MAX_ARRAY_LENGTH || i + arrayLength * 4 > data.length) {
this._pushError("Invalid NBT intArray length: " + arrayLength);
return 0;
}
const numberArray = [];
for (let j = 0; j < arrayLength; j++) {
numberArray.push(DataUtilities_1.default.getSignedInteger(data[i++], data[i++], data[i++], data[i++], littleEndian));
}
activeTag.value = numberArray;
}
else if (activeTag.type === NbtBinaryTag_1.NbtTagType.longArray) {
const arrayLength = DataUtilities_1.default.getSignedInteger(data[i++], data[i++], data[i++], data[i++], littleEndian);
if (arrayLength < 0 || arrayLength > NbtBinary.MAX_ARRAY_LENGTH || i + arrayLength * 8 > data.length) {
this._pushError("Invalid NBT longArray length: " + arrayLength);
return 0;
}
const numberArray = [];
for (let j = 0; j < arrayLength; j++) {
numberArray.push(DataUtilities_1.default.getSignedLong(data[i++], data[i++], data[i++], data[i++], data[i++], data[i++], data[i++], data[i++], littleEndian));
}
activeTag.value = numberArray;
}
else if (activeTag.type === NbtBinaryTag_1.NbtTagType.short) {
activeTag.value = DataUtilities_1.default.getSignedShort(data[i++], data[i++], littleEndian);
}
else if (activeTag.type === NbtBinaryTag_1.NbtTagType.int) {
activeTag.value = DataUtilities_1.default.getSignedInteger(data[i++], data[i++], data[i++], data[i++], littleEndian);
}
else if (activeTag.type === NbtBinaryTag_1.NbtTagType.float) {
activeTag.value = DataUtilities_1.default.getFloat(data[i++], data[i++], data[i++], data[i++], littleEndian);
}
else if (activeTag.type === NbtBinaryTag_1.NbtTagType.double) {
activeTag.value = DataUtilities_1.default.getSignedDouble(data[i++], data[i++], data[i++], data[i++], data[i++], data[i++], data[i++], data[i++], littleEndian);
}
else if (activeTag.type === NbtBinaryTag_1.NbtTagType.long) {
activeTag.value = DataUtilities_1.default.getSignedLong(data[i++], data[i++], data[i++], data[i++], data[i++], data[i++], data[i++], data[i++], littleEndian);
}
else if (activeTag.type === NbtBinaryTag_1.NbtTagType.string) {
let stringLength = 0;
if (isVarint) {
const result = this._getVarInt(data, i);
stringLength = result.value;
i += result.bytesRead;
}
else {
stringLength = DataUtilities_1.default.getUnsignedShort(data[i++], data[i++], littleEndian);
}
const view = new DataView(data.buffer);
let str;
if (stringsAreASCII) {
str = Utilities_1.default.readStringASCIIBuffer(data, i, stringLength);
}
else {
str = Utilities_1.default.getString(view, i, stringLength, "UTF8");
}
if (str === undefined) {
throw new Error("Unexpectedly could not read a string.");
}
activeTag.value = str;
i += stringLength;
Log_1.default.assert(i <= data.length, "NBTFB");
/*
let valueString = "";
for (let j=0; j<stringLength; j++)
{
valueString += String.fromCharCode(data[i++]);
}
activeTag.value = valueString;*/
}
else {
Log_1.default.unexpectedError("Unsupported NBT tag type '" + activeTag.type + "'");
}
}
let bytesRead = i;
if (skipBytes !== undefined) {
bytesRead -= skipBytes;
}
return bytesRead;
}
}
exports.default = NbtBinary;