UNPKG

mc-anvil

Version:

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

144 lines 6.51 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.SaveParser = exports.parseRegionName = exports.isValidRegionFileName = void 0; const JSZip = require("jszip"); const queryz_1 = require("queryz"); const __1 = require(".."); const REGION_FORMAT_FILE_NAME = /^r[\.]([\-]?[0-9,]+)[\.]([\-]?[0-9,]+)[\.]mca$/g; function isValidRegionFileName(name) { return name.match(REGION_FORMAT_FILE_NAME) !== null; } exports.isValidRegionFileName = isValidRegionFileName; function parseRegionName(name) { if (!isValidRegionFileName(name)) throw new Error(`${name} is not a valid region file name; expected r.<x>.<z>.mca`); const m = name.matchAll(REGION_FORMAT_FILE_NAME).next(); return { x: +m.value[1], z: +m.value[2] }; } exports.parseRegionName = parseRegionName; function writeDirectoryToZip(d, z, path, overrideMap) { return __awaiter(this, void 0, void 0, function* () { return new Promise((resolve, reject) => { d.createReader().readEntries(entries => Promise.all(entries.map(e => { const thispath = `${path}/${e.name}`; if (overrideMap === null || overrideMap === void 0 ? void 0 : overrideMap.has(thispath)) return new Promise(resolve => { z.file(thispath, overrideMap.get(thispath)); resolve(); }); return e.isDirectory ? writeDirectoryToZip(e, z, thispath, overrideMap) : new Promise((resolve, reject) => e.file(f => { f.arrayBuffer().then(a => { z.file(thispath, a); resolve(); }).catch(reject); })); })).then(() => resolve()).catch(reject), reject); }); }); } class SaveParser { constructor(root) { this.cachedRegions = new Map([]); this.dirtyRegions = new Map([]); this.root = root; } getRegions() { return __awaiter(this, void 0, void 0, function* () { const allEntries = []; const readEntriesRecursively = (directory) => (new Promise((resolve, reject) => { const reader = directory.createReader(); const readBatch = () => { reader.readEntries(entries => { if (entries.length === 0) { resolve(); return; } allEntries.push(...entries .filter(x => x.isFile && isValidRegionFileName(x.name)) .map(x => (Object.assign(Object.assign({}, parseRegionName(x.name)), { file: x })))); readBatch(); }, error => reject(error)); }; readBatch(); })); return new Promise((resolve, reject) => { this.root.getDirectory("region", undefined, (regionDirectory) => { readEntriesRecursively(regionDirectory).then(() => { resolve(allEntries); }).catch(reject); }, reject); }); }); } getLevel() { return __awaiter(this, void 0, void 0, function* () { return new Promise((resolve, reject) => { this.root.getFile("level.dat", undefined, resolve, reject); }); }); } getRegionFileContainingCoordinate(coordinate) { return __awaiter(this, void 0, void 0, function* () { if (this.cachedRegions.size === 0) this.cachedRegions = queryz_1.associateBy(yield this.getRegions(), x => `${x.x},${x.z}`, x => x); const x = Math.floor(coordinate[0] / 512); const z = Math.floor(coordinate[2] / 512); return this.cachedRegions.get(`${x},${z}`); }); } getAnvilParserByCoordinate(coordinate) { return __awaiter(this, void 0, void 0, function* () { const region = yield this.getRegionFileContainingCoordinate(coordinate); if (!region) return; const x = region.x; const z = region.z; return new Promise((resolve, reject) => { if (this.dirtyRegions.get(`${x},${z}`)) resolve(this.dirtyRegions.get(`${x},${z}`)); region.file.file(f => f.arrayBuffer().then(xx => { const parser = new __1.AnvilParser(xx); this.dirtyRegions.set(`${x},${z}`, parser); resolve(parser); }).catch(reject), reject); }); }); } setBlock(coordinates, name, properties) { var _a; return __awaiter(this, void 0, void 0, function* () { (_a = (yield this.getAnvilParserByCoordinate(coordinates))) === null || _a === void 0 ? void 0 : _a.setBlock(coordinates, name, properties); }); } getBlock(coordinates) { var _a; return __awaiter(this, void 0, void 0, function* () { return (_a = (yield this.getAnvilParserByCoordinate(coordinates))) === null || _a === void 0 ? void 0 : _a.getBlock(coordinates); }); } asZip() { return __awaiter(this, void 0, void 0, function* () { const dirtyRegions = [...this.dirtyRegions.keys()]; const zip = new JSZip(); const overrideMap = new Map(dirtyRegions.map(key => [ `/region/r.${key.replace(/,/g, '.')}.mca`, this.dirtyRegions.get(key).buffer() ])); yield writeDirectoryToZip(this.root, zip, "", overrideMap); return zip; }); } } exports.SaveParser = SaveParser; //# sourceMappingURL=save.js.map