UNPKG

mc-anvil

Version:

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

93 lines 5.95 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.nbtTagReducer = exports.deleteChild = exports.transformTag = exports.NBTActions = void 0; const nbt_1 = require("./nbt"); const types_1 = require("./types"); var NBTActions; (function (NBTActions) { NBTActions["NBT_DELETE_TAG"] = "NBT_DELETE_TAG"; NBTActions["NBT_ADD_TAG"] = "NBT_ADD_TAG"; NBTActions["NBT_EDIT_TAG"] = "NBT_EDIT_TAG"; NBTActions["NBT_ADD_COMPOUND_LIST_ITEM"] = "NBT_ADD_COMPOUND_LIST_ITEM"; })(NBTActions = exports.NBTActions || (exports.NBTActions = {})); ; function transformTag(tag, path, transform) { var _a; if (path[0] === '/') path = path.slice(1); const p = path.split("/"); if (p.length === 1 && p[0] === "") return transform(tag); if (tag.type === types_1.TagType.COMPOUND) { let children = [...tag.data]; if (children[children.length - 1].type === types_1.TagType.END) children = children.slice(0, children.length - 1); if (children.find(x => x.name === p[0]) !== undefined) children.forEach((child, i) => { if (child.name === p[0]) children[i] = transformTag(child, p.slice(1).join("/"), transform); }); else { const nTag = ((_a = p[1]) === null || _a === void 0 ? void 0 : _a.match(nbt_1.LIST_INDEX)) ? { type: types_1.TagType.LIST, name: p[0], data: { subType: types_1.TagType.COMPOUND, data: [] } } : { type: types_1.TagType.COMPOUND, name: p[0], data: [{ type: types_1.TagType.END, name: "", data: null }] }; children.push(transformTag(nTag, p.slice(1).join("/"), transform)); } return Object.assign(Object.assign({}, tag), { data: [...children, { type: types_1.TagType.END, name: "", data: null }] }); } else if (tag.type === types_1.TagType.LIST && tag.data.subType === types_1.TagType.COMPOUND) { const index = nbt_1.parseCompoundListIndex(p[0]); const data = [...tag.data.data]; if (index >= data.length) for (let i = data.length; i < index; ++i) data.push([{ type: types_1.TagType.END, name: "", data: null }]); return Object.assign(Object.assign({}, tag), { data: Object.assign(Object.assign({}, tag.data), { data: [ ...data.slice(0, index), transformTag({ type: types_1.TagType.COMPOUND, name: "", data: data[index] || [{ type: types_1.TagType.END, name: "", data: null }] }, p.slice(1).join("/"), transform).data, ...data.slice(index + 1) ] }) }); } throw new Error(`${tag.name} is not a compound or list tag, and cannot have children at ${path}.`); } exports.transformTag = transformTag; function deleteChild(tag, name) { if (tag.type === types_1.TagType.COMPOUND) return Object.assign(Object.assign({}, tag), { data: tag.data.filter(x => x.name !== name) }); else if (tag.type === types_1.TagType.LIST) { const index = nbt_1.parseCompoundListIndex(name); return Object.assign(Object.assign({}, tag), { data: Object.assign(Object.assign({}, tag.data), { data: tag.data.data.filter((_, i) => i !== index) }) }); } throw new Error(`Cannot delete child ${name} from non-container tag of type ${tag.type}.`); } exports.deleteChild = deleteChild; function ensureEndTag(tags) { if (tags[tags.length - 1].type === types_1.TagType.END) return tags; return [...tags, { type: types_1.TagType.END, name: "", data: null }]; } function nbtTagReducer(tag, action) { var _a; switch (action.type) { case NBTActions.NBT_DELETE_TAG: if (nbt_1.findChildTagAtPath(action.path, tag) === undefined) throw new Error(`Unable to delete ${action.path}: tag not found.`); else if (!action.recursive && ((_a = nbt_1.findChildTagAtPath(action.path, tag)) === null || _a === void 0 ? void 0 : _a.type) === types_1.TagType.COMPOUND) throw new Error(`Deletion of compound tag with name ${tag.name} requires the recursive flag.`); return transformTag(tag, nbt_1.parent(action.path), tag => deleteChild(tag, nbt_1.baseName(action.path))); case NBTActions.NBT_ADD_TAG: if (!action.recursive && nbt_1.findChildTagAtPath(action.path, tag) === undefined) throw new Error(`Unable to add a child to non-existent tag ${action.path} without the recursive flag set.`); else if (!action.overwrite && nbt_1.findChildTagAtPath(action.path + "/" + action.tag.name, tag) !== undefined) throw new Error(`A child tag already exists at ${action.path}/${action.tag.name}; use the overwrite flag to replace.`); return transformTag(tag, `${action.path}/${action.tag.name}`, () => action.tag); case NBTActions.NBT_ADD_COMPOUND_LIST_ITEM: if (!action.recursive && nbt_1.findChildTagAtPath(action.path, tag) === undefined) throw new Error(`Unable to add a child to non-existent tag ${action.path} without the recursive flag set.`); else if (!action.overwrite && nbt_1.findChildTagAtPath(`${action.path}/[${action.index}]`, tag) !== undefined) throw new Error(`A child tag already exists at ${action.path}/[${action.index}]; use the overwrite flag to replace.`); return transformTag(tag, `${action.path}/[${action.index}]`, () => ({ type: types_1.TagType.COMPOUND, name: "", data: ensureEndTag(action.tags) })); case NBTActions.NBT_EDIT_TAG: if (nbt_1.findChildTagAtPath(action.path, tag) === undefined) throw new Error(`Unable to edit non-existent tag ${action.path}.`); return transformTag(transformTag(tag, nbt_1.parent(action.path), tag => deleteChild(tag, nbt_1.baseName(action.path))), action.path, () => action.tag); } } exports.nbtTagReducer = nbtTagReducer; //# sourceMappingURL=reducer.js.map