UNPKG

mcbe-leveldb-reader

Version:

Reads a MCBE LevelDB database from a .mcworld file. Can also extract all structure files from a world. Powered by Mojang's code from Mojang/minecraft-creator-tools.

93 lines 4.33 kB
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()); }); }; import LevelDb from "./LevelDb.js"; import * as NBT from "nbtify"; import { BlobReader, ZipReader, Uint8ArrayWriter } from "@zip.js/zip.js"; /** Extracts all LevelDB keys from a zipped `.mcworld` file. Also accepts the zipped "db" folder. */ export function readMcworld(mcworld) { return __awaiter(this, void 0, void 0, function* () { let folder = new ZipReader(new BlobReader(mcworld)); let fileEntries = yield folder.getEntries(); folder.close(); let inWorldFolder = fileEntries.some(entry => entry.filename == "levelname.txt"); let dbEntries = inWorldFolder ? fileEntries.filter(entry => entry.filename.startsWith("db/")) : fileEntries; let dbFiles = yield Promise.all(dbEntries.map(entry => zipEntryToFile(entry))); return yield readLevelDb(dbFiles); }); } /** Converts an Entry from zip.js into a File. */ export function zipEntryToFile(entry) { return __awaiter(this, void 0, void 0, function* () { return new File([yield entry.getData(new Uint8ArrayWriter())], entry.filename.slice(entry.filename.lastIndexOf("/") + 1)); }); } /** Reads a LevelDB database from all its files and returns an object with all keys. */ export function readLevelDb(dbFiles) { return __awaiter(this, void 0, void 0, function* () { let files = yield Promise.all(dbFiles.map((file) => __awaiter(this, void 0, void 0, function* () { let iFile = { content: yield file.bytes(), loadContent: () => new Date(), name: file.name, storageRelativePath: file.name, fullPath: file.name }; return iFile; // return new Proxy(iFile, { // get(target, prop, receiver) { // console.log(`Property accessed: ${String(prop)}`); // props.add(prop); // return Reflect.get(target, prop, receiver); // } // }); }))); let ldbFileArr = []; let logFileArr = []; let manifestFileArr = []; files.forEach(file => { if (file.name.startsWith("MANIFEST")) { manifestFileArr.push(file); } else if (file.name.endsWith("ldb")) { ldbFileArr.push(file); } else if (file.name.endsWith("log")) { logFileArr.push(file); } }); let levelDb = new LevelDb(ldbFileArr, logFileArr, manifestFileArr, "LlamaStructureReader"); yield levelDb.init(message => { console.debug(`LevelDB: ${message}`); }); return levelDb.keys; }); } /** Extracts structure files from a `.mcworld` file. */ export function extractStructureFilesFromMcworld(mcworld) { return __awaiter(this, void 0, void 0, function* () { let levelDbKeys = yield readMcworld(mcworld); let structures = new Map(); yield Promise.all(Object.entries(levelDbKeys).map((_a) => __awaiter(this, [_a], void 0, function* ([key, value]) { let strKey = key.toString(); if (strKey.startsWith("structuretemplate_")) { let structureName = strKey.replace(/^structuretemplate_/, ""); try { let structure = (yield NBT.read(value.value)).data; structures.set(structureName, structure); } catch (e) { console.error(`Failed reading structure NBT for ${structureName}: ${e}`); } } }))); return structures; }); } //# sourceMappingURL=main.js.map