UNPKG

mc-anvil

Version:

A Typescript library for reading Minecraft Anvil format files and Minecraft NBT format files in the browser.

194 lines 7.57 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.NBTParser = exports.baseName = exports.parent = exports.findChildTagAtPath = exports.findCompoundListChildren = exports.findChildTagIndex = exports.findChildTag = exports.parseCompoundListIndex = exports.LIST_INDEX = void 0; const util_1 = require("../util"); const pako_1 = require("pako"); const types_1 = require("./types"); exports.LIST_INDEX = /^[\[][0-9]+[\]]$/; function parseCompoundListIndex(value) { if (value.match(exports.LIST_INDEX) !== null) return +value.slice(1, value.length - 1); return +value; } exports.parseCompoundListIndex = parseCompoundListIndex; function findChildTag(tag, f) { if (tag.type === types_1.TagType.COMPOUND) return tag.data.find(f); } exports.findChildTag = findChildTag; function findChildTagIndex(tag, f) { if (tag.type === types_1.TagType.COMPOUND) return tag.data.findIndex(f); } exports.findChildTagIndex = findChildTagIndex; function findCompoundListChildren(tag, f) { if (tag.type === types_1.TagType.LIST && tag.data.subType === types_1.TagType.COMPOUND) return tag.data.data.map(x => x.find(f)); } exports.findCompoundListChildren = findCompoundListChildren; function findChildTagAtPath(path, tag) { const p = path.split('/'); for (let i = 0; i < p.length; ++i) { if (!tag || !tag.type) return; if (tag.type === types_1.TagType.COMPOUND) tag = findChildTag(tag, x => x.name === p[i]); else if (tag.type === types_1.TagType.LIST && tag.data.subType === types_1.TagType.COMPOUND) { const data = tag.data.data[parseCompoundListIndex(p[i])]; tag = data ? { type: types_1.TagType.COMPOUND, name: "", data } : undefined; } } return tag; } exports.findChildTagAtPath = findChildTagAtPath; function parent(path) { const p = path.split("/"); return p.slice(0, p.length - 1).join("/"); } exports.parent = parent; function baseName(path) { const p = path.split("/"); return p[p.length - 1]; } exports.baseName = baseName; function tryInflate(buffer) { try { const b = pako_1.inflate(new Uint8Array(buffer)); if (!b) throw new Error("not compressed"); return b.buffer; } catch (e) { return buffer; } } class NBTParser extends util_1.ResizableBinaryWriter { constructor(data, verbose) { super(tryInflate(data)); this.tagReaders = new Map([ [types_1.TagType.END, () => null], [types_1.TagType.BYTE, this.getByte.bind(this)], [types_1.TagType.BYTE_ARRAY, this.getByteArrayTag.bind(this)], [types_1.TagType.SHORT, this.getShort.bind(this)], [types_1.TagType.INT, this.getInt.bind(this)], [types_1.TagType.INT_ARRAY, this.getIntArrayTag.bind(this)], [types_1.TagType.LONG, this.getInt64.bind(this)], [types_1.TagType.LONG_ARRAY, this.getLongArrayTag.bind(this)], [types_1.TagType.FLOAT, this.getFloat.bind(this)], [types_1.TagType.DOUBLE, this.getDouble.bind(this)], [types_1.TagType.STRING, this.getStringTag.bind(this)], [types_1.TagType.COMPOUND, this.getCompoundTag.bind(this)], [types_1.TagType.LIST, this.getListTag.bind(this)] ]); this.tagWriters = new Map([ [types_1.TagType.END, () => { }], [types_1.TagType.BYTE, this.setByte.bind(this)], [types_1.TagType.BYTE_ARRAY, this.setByteArrayTag.bind(this)], [types_1.TagType.SHORT, this.setShort.bind(this)], [types_1.TagType.INT, this.setInt.bind(this)], [types_1.TagType.INT_ARRAY, this.setIntArrayTag.bind(this)], [types_1.TagType.LONG, this.setInt64LE.bind(this)], [types_1.TagType.LONG_ARRAY, this.setLongArrayTag.bind(this)], [types_1.TagType.FLOAT, this.setFloat.bind(this)], [types_1.TagType.DOUBLE, this.setDouble.bind(this)], [types_1.TagType.STRING, this.setStringTag.bind(this)], [types_1.TagType.COMPOUND, this.setCompoundTag.bind(this)], [types_1.TagType.LIST, this.setListTag.bind(this)] ]); this.verbose = verbose; } getNumberArrayTag(reader) { const data = []; const length = this.getInt(); for (let i = 0; i < length; ++i) data.push(reader()); return data; } setNumberArrayTag(value, writer) { this.setInt(value.length); value.forEach(writer); } getByteArrayTag() { return this.getNumberArrayTag(this.getByte.bind(this)); } setByteArrayTag(value) { this.setNumberArrayTag(value, this.setByte.bind(this)); } getIntArrayTag() { return this.getNumberArrayTag(this.getInt.bind(this)); } setIntArrayTag(value) { this.setNumberArrayTag(value, this.setInt.bind(this)); } getLongArrayTag() { const length = this.getInt(); const r = this.view.buffer.slice(this.position, this.position + length * 8); this.position += length * 8; return r; } setLongArrayTag(value) { this.setInt(value.byteLength / 8); this.setArrayBuffer(value); } getStringTag() { const length = this.getUShort(); return this.getFixedLengthString(length); } setStringTag(value) { this.setUShort(value.length); this.setFixedLengthString(value); } getListTag() { const subType = this.getByte(); const length = this.getInt(); const reader = this.tagReaders.get(subType); const data = []; if (reader === undefined) throw new Error(`Invalid NBT tag ID ${subType} for list tag`); for (let i = 0; i < length; ++i) data.push(reader()); return { subType, data }; } setListTag(value) { const writer = this.tagWriters.get(value.subType); if (writer === undefined) throw new Error(`Invalid NBT tag ID ${value.subType} for list tag`); this.setByte(value.subType); this.setInt(value.data.length); value.data.forEach(writer); } getCompoundTag() { const tags = []; do { tags.push(this.getTag()); } while (tags[tags.length - 1].type !== types_1.TagType.END); return tags; } setCompoundTag(value) { var _a; value.forEach(this.setTag.bind(this)); if (((_a = value[value.length - 1]) === null || _a === void 0 ? void 0 : _a.type) !== types_1.TagType.END) this.setTag({ type: types_1.TagType.END, name: "", data: null }); } getTag() { const type = this.getByte(); const nameLength = type !== types_1.TagType.END ? this.getUShort() : 0; const name = this.getFixedLengthString(nameLength); const reader = this.tagReaders.get(type); if (reader === undefined) throw new Error(`Invalid NBT tag ID ${type}`); return { type, name, data: reader() }; } setTag(value) { const writer = this.tagWriters.get(value.type); if (writer === undefined) throw new Error(`Invalid NBT tag ID ${value.type}`); this.setByte(value.type); if (value.type !== types_1.TagType.END) this.setUShort(value.name.length); this.setFixedLengthString(value.name); writer(value.data); } } exports.NBTParser = NBTParser; //# sourceMappingURL=nbt.js.map