UNPKG

mc-anvil

Version:

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

174 lines 8.98 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.BlockDataParser = exports.paletteBlockList = exports.paletteAsList = exports.paletteNameList = exports.blockTypeID = exports.block = exports.blockTypeString = void 0; const MD5 = require("crypto-js/md5"); const queryz_1 = require("queryz"); const nbt_1 = require("../nbt"); const nbt_2 = require("../nbt/nbt"); const util_1 = require("../util"); const chunk_1 = require("./chunk"); function blockTypeString(t) { var _a, _b; const name = ((_a = t.find(x => x.name.toLowerCase() === "name")) === null || _a === void 0 ? void 0 : _a.data) || ""; const properties = (((_b = t.find(x => x.name.toLowerCase() === "properties")) === null || _b === void 0 ? void 0 : _b.data) || []) .filter(x => x.type === nbt_1.TagType.STRING) .sort((a, b) => a.name.localeCompare(b.name)) .map(x => `${x.name}:${x.data}`); return `${name}(${properties.join(",")})`; } exports.blockTypeString = blockTypeString; function block(t) { var _a, _b; const name = ((_a = t.find(x => x.name.toLowerCase() === "name")) === null || _a === void 0 ? void 0 : _a.data) || ""; const properties = {}; (((_b = t.find(x => x.name.toLowerCase() === "properties")) === null || _b === void 0 ? void 0 : _b.data) || []) .filter(x => x.type === nbt_1.TagType.STRING) .forEach(x => { properties[x.name] = x.data; }); return { name, properties }; } exports.block = block; function blockTypeID(t) { const w = MD5(blockTypeString(t)).words; return w[0]; } exports.blockTypeID = blockTypeID; function paletteNameList(palette) { return palette.data.data.map(x => { var _a; return (((_a = x.find(x => x.name.toLowerCase() === "name")) === null || _a === void 0 ? void 0 : _a.data) || ""); }); } exports.paletteNameList = paletteNameList; function paletteAsList(palette) { return palette.data.data.map(block); } exports.paletteAsList = paletteAsList; function paletteBlockList(palette) { return palette.data.data.map(blockTypeString); } exports.paletteBlockList = paletteBlockList; class BlockDataParser extends util_1.BitParser { constructor(blockStates, palette) { const d = new util_1.BinaryParser(blockStates.data); const b = new BigUint64Array(d.remainingLength() / 8); for (let i = 0; i < b.length; ++i) b[i] = d.getUInt64LE(); super(b.buffer); this.palette = palette; this.paletteNames = paletteNameList(this.palette); this.blockTypeStringMap = null; this.blockTypeIDMap = null; this.blockTypeIDToStringMap = null; } static writeBlockStates(states, palette) { const blocks = states.map(state => palette ? blockTypeString(palette.data.data[state]) : "" + state); const new_id_map = new Map([...new Set(blocks)].map((x, i) => [x, i])); const palette_map = new Map(palette === null || palette === void 0 ? void 0 : palette.data.data.map(x => [blockTypeString(x), x])); const new_palette = palette ? [...new Set(blocks)].sort((a, b) => new_id_map.get(a) - new_id_map.get(b)).map(block => palette_map.get(block)) : undefined; palette = palette && new_palette ? Object.assign(Object.assign({}, palette), { data: Object.assign(Object.assign({}, palette.data), { data: new_palette }) }) : palette; if (palette) states = blocks.map(block => new_id_map.get(block)); const paletteSize = (palette === null || palette === void 0 ? void 0 : palette.data.data.length) === undefined ? Math.max(...states) : palette.data.data.length - 1; const l = Math.floor(Math.log2(paletteSize || 1)) + 1; const length = l < 4 ? 4 : l; const c = Math.floor(64 / length); const toSkip = 64 % c; const r = new ArrayBuffer(8 * Math.ceil(states.length / c)); const d = new util_1.BitParser(r); let workingList = []; for (let i = 0; i < states.length; ++i) { if (c > 0 && c < Infinity && i % c === 0) { if (workingList.length > 0) d.setBits(toSkip, 0); for (let i = workingList.length - 1; i >= 0; --i) d.setBits(length, workingList[i]); workingList = []; } workingList.push(states[i]); } if (workingList.length > 0) d.setBits(toSkip, 0); for (let i = 0; i < c - workingList.length; ++i) d.setBits(length, 0); for (let i = workingList.length - 1; i >= 0; --i) d.setBits(length, workingList[i]); return [r, palette]; } getBlocksGenericOriginal(f, limit) { const paletteSize = this.palette.data.data.length; const toRead = paletteSize ? Math.ceil(Math.log2(paletteSize)) : 0; const total = limit || chunk_1.Chunk.BLOCKS_PER_CHUNK; const r = []; for (let i = 0; i < total; ++i) r.push(f(this.getBits(toRead))); return r; } getBlocksGeneric(f, limit) { const paletteSize = this.palette.data.data.length; const l = Math.floor(Math.log2((paletteSize - 1) || 1)) + 1; const toRead = paletteSize ? (l < 4 ? 4 : l) : 0; const r = []; const skipIndex = Math.floor(64 / toRead); const toSkip = 64 % toRead; const total = limit || (this.view.byteLength / 8 * skipIndex); let workingList = []; for (let i = 0; i < total; ++i) { if (skipIndex > 0 && skipIndex < Infinity && i % skipIndex === 0) { this.getBits(toSkip); for (let i = workingList.length - 1; i >= 0; --i) r.push(f(workingList[i])); workingList = []; } workingList.push(this.getBits(toRead)); } for (let i = workingList.length - 1; i >= 0; --i) r.push(f(workingList[i])); if (total > chunk_1.Chunk.BLOCKS_PER_CHUNK) return r.slice(0, chunk_1.Chunk.BLOCKS_PER_CHUNK); return r; } getBlockTypeIDMap() { this.blockTypeIDMap = queryz_1.associateBy(this.palette.data.data, x => { var _a; return (((_a = x.find(x => x.name.toLowerCase() === "name")) === null || _a === void 0 ? void 0 : _a.data) || ""); }, blockTypeID); } getBlockTypeStringMap() { this.blockTypeStringMap = queryz_1.associateBy(this.palette.data.data, x => { var _a; return (((_a = x.find(x => x.name.toLowerCase() === "name")) === null || _a === void 0 ? void 0 : _a.data) || ""); }, blockTypeString); } getBlockTypeIDToStringMap() { this.blockTypeIDToStringMap = queryz_1.associateBy(this.palette.data.data, blockTypeID, blockTypeString); } getRawBlocks(original, limit) { return original ? this.getBlocksGenericOriginal(x => x, limit) : this.getBlocksGeneric(x => x, limit); } getBlocks(original, limit) { return original ? this.getBlocksGenericOriginal(x => this.palette.data.data[x], limit) : this.getBlocksGeneric(x => this.palette.data.data[x], limit); } getBlockTypeNames(original, limit) { if (this.blockTypeStringMap === null) this.getBlockTypeStringMap(); return original ? this.getBlocksGenericOriginal(x => { var _a; return (_a = this.blockTypeStringMap) === null || _a === void 0 ? void 0 : _a.get(this.paletteNames[x]); }, limit) : this.getBlocksGeneric(x => { var _a; return (_a = this.blockTypeStringMap) === null || _a === void 0 ? void 0 : _a.get(this.paletteNames[x]); }, limit); } getBlockTypeIDs(original, limit) { if (this.blockTypeIDMap === null) this.getBlockTypeIDMap(); return original ? this.getBlocksGenericOriginal(x => { var _a; return (_a = this.blockTypeIDMap) === null || _a === void 0 ? void 0 : _a.get(this.paletteNames[x]); }, limit) : this.getBlocksGeneric(x => { var _a; return (_a = this.blockTypeIDMap) === null || _a === void 0 ? void 0 : _a.get(this.paletteNames[x]); }, limit); } blockStateFromHash(hash) { var _a; if (this.blockTypeIDToStringMap === null) this.getBlockTypeIDToStringMap(); return ((_a = this.blockTypeIDToStringMap) === null || _a === void 0 ? void 0 : _a.get(hash)) || ""; } findBlocksByName(name) { var _a, _b; const blocks = this.getRawBlocks(); const nameIndex = (_b = (_a = nbt_2.findCompoundListChildren(this.palette, x => x.name.toLowerCase() === "name")) === null || _a === void 0 ? void 0 : _a.map((x, i) => ({ x, i })).find(x => { var _a; return ((_a = x.x) === null || _a === void 0 ? void 0 : _a.data) === name; })) === null || _b === void 0 ? void 0 : _b.i; return blocks.map((x, i) => ({ x, i })).filter(x => x.x === nameIndex).map(x => x.i); } } exports.BlockDataParser = BlockDataParser; //# sourceMappingURL=block.js.map