@minecraft/creator-tools
Version:
Minecraft Creator Tools command line and libraries.
361 lines (359 loc) • 17.4 kB
JavaScript
"use strict";
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
Object.defineProperty(exports, "__esModule", { value: true });
const BlockCube_1 = require("./BlockCube");
const NbtBinary_1 = require("./NbtBinary");
const NbtBinaryTag_1 = require("./NbtBinaryTag");
const MinecraftUtilities_1 = require("./MinecraftUtilities");
const Block_1 = require("./Block");
const Entity_1 = require("./Entity");
const Log_1 = require("../core/Log");
const Database_1 = require("./Database");
const EntityInventoryComponent_1 = require("./components/EntityInventoryComponent");
class Structure {
constructor() {
this._blockPalette = [];
this.defaultBlockPersistenceVersion = 17879555;
}
get cube() {
return this._cube;
}
set cube(newCube) {
this._cube = newCube;
}
get entities() {
return this._entities;
}
shallowCopyFrom(structure) {
this.cube = structure.cube;
this._entities = structure.entities;
this.originX = structure.originX;
this.originY = structure.originY;
this.originZ = structure.originZ;
}
createNbt() {
if (this._cube === undefined) {
return;
}
const nbt = new NbtBinary_1.default();
const root = nbt.ensureSingleRoot();
root.addTag(NbtBinaryTag_1.NbtTagType.int, "format_version").value = 1;
const sizeList = root.addTag(NbtBinaryTag_1.NbtTagType.list, "size");
sizeList.childTagType = NbtBinaryTag_1.NbtTagType.unknown;
sizeList.addTag(NbtBinaryTag_1.NbtTagType.int).value = this._cube.maxX;
sizeList.addTag(NbtBinaryTag_1.NbtTagType.int).value = this._cube.maxY;
sizeList.addTag(NbtBinaryTag_1.NbtTagType.int).value = this._cube.maxZ;
const structure = root.addTag(NbtBinaryTag_1.NbtTagType.compound, "structure");
const blockIndices = structure.addTag(NbtBinaryTag_1.NbtTagType.list, "block_indices");
const primaryLayer = blockIndices.addTag(NbtBinaryTag_1.NbtTagType.list);
const secondaryLayer = blockIndices.addTag(NbtBinaryTag_1.NbtTagType.list);
const blockPalette = {};
const paletteBlocks = [];
for (let x = 0; x < this._cube.maxX; x++) {
for (let y = 0; y < this._cube.maxY; y++) {
for (let z = 0; z < this._cube.maxZ; z++) {
const block = this._cube.x(x).y(y).z(z);
const blockFingerprint = block.toString();
let paletteId = blockPalette[blockFingerprint];
if (block.typeName == null || block.typeName === "air") {
paletteId = -1;
}
else if (paletteId == null) {
paletteId = paletteBlocks.length;
blockPalette[blockFingerprint] = paletteId;
paletteBlocks.push(block);
}
primaryLayer.addTag(NbtBinaryTag_1.NbtTagType.int).value = paletteId;
secondaryLayer.addTag(NbtBinaryTag_1.NbtTagType.int).value = block.extraLiquidDepth;
}
}
}
/*const entities = */ structure.addTag(NbtBinaryTag_1.NbtTagType.list, "entities");
if (this._entities !== undefined) {
}
const palette = structure.addTag(NbtBinaryTag_1.NbtTagType.compound, "palette");
structure.addTag(NbtBinaryTag_1.NbtTagType.end);
const paletteDefault = palette.addTag(NbtBinaryTag_1.NbtTagType.compound, "default");
palette.addTag(NbtBinaryTag_1.NbtTagType.end);
const blockStates = paletteDefault.addTag(NbtBinaryTag_1.NbtTagType.list, "block_palette");
for (let i = 0; i < paletteBlocks.length; i++) {
const block = paletteBlocks[i];
if (block.typeName == null) {
throw new Error("Unexpected palette block.");
}
const blockState = blockStates.addTag(NbtBinaryTag_1.NbtTagType.compound);
blockState.addTag(NbtBinaryTag_1.NbtTagType.string, "name").value = block.typeName;
const blockStateStates = blockState.addTag(NbtBinaryTag_1.NbtTagType.compound, "states");
for (const propertyName in block.properties) {
const blockProperty = block.getProperty(propertyName);
const propType = blockProperty.nbtType;
const value = blockProperty.value;
if (value === undefined) {
blockStateStates.addTag(propType, propertyName).value = null;
}
else {
blockStateStates.addTag(propType, propertyName).value = value;
}
}
let version = block.persistenceVersion;
if (version <= 0) {
version = this.defaultBlockPersistenceVersion;
}
blockState.addTag(NbtBinaryTag_1.NbtTagType.int, "version").value = version;
blockState.addTag(NbtBinaryTag_1.NbtTagType.end);
}
// TODO: add block_position_data here to paletteDefault;
const blockPositionData = paletteDefault.addTag(NbtBinaryTag_1.NbtTagType.compound, "block_position_data");
blockPositionData.addTag(NbtBinaryTag_1.NbtTagType.end);
paletteDefault.addTag(NbtBinaryTag_1.NbtTagType.end);
if (this.originX !== undefined && this.originY !== undefined && this.originZ !== undefined) {
const structureOrigin = root.addTag(NbtBinaryTag_1.NbtTagType.list, "structure_world_origin");
structureOrigin.addTag(NbtBinaryTag_1.NbtTagType.int).value = this.originX;
structureOrigin.addTag(NbtBinaryTag_1.NbtTagType.int).value = this.originY;
structureOrigin.addTag(NbtBinaryTag_1.NbtTagType.int).value = this.originZ;
}
root.addTag(NbtBinaryTag_1.NbtTagType.end);
return nbt;
}
loadFromSnbtText(text) {
let structure = null;
const content = MinecraftUtilities_1.default.fixupJson(text);
try {
// temporarily putting back in the safe code.
structure = JSON.stringify(content); // eval('(' + content + ')');
}
catch (e) {
throw new Error("Error processing SNBT.");
}
if (structure === null || structure === undefined) {
throw new Error("Could not create SNBT.");
}
}
loadFromSnbt(content) {
if (content.size === null ||
content.size === undefined ||
content.size.length !== 3 ||
content.data === undefined) {
throw new Error("Unexpected structure to Snbt file.");
}
if (this._cube === undefined) {
this._cube = new BlockCube_1.default();
}
this._cube.setMaxDimensions(content.size[0], content.size[1], content.size[2]);
for (let i = 0; i < content.data.length; i++) {
const block = content.data[i];
if (block.pos === undefined || block.pos.length !== 3 || block.state === undefined) {
throw new Error("Unexpected format for a block in an Snbt");
}
const targetBlock = this._cube.x(block.pos[0]).y(block.pos[1]).z(block.pos[2]);
let blockTypeId = block.state;
const firstCurly = blockTypeId.indexOf("{");
if (firstCurly >= 0) {
if (blockTypeId[blockTypeId.length - 1] !== "}") {
throw new Error("Unexpected property found.");
}
const props = blockTypeId.substring(firstCurly + 1, blockTypeId.length - 1).split(",");
for (const prop of props) {
const propArr = prop.split(":");
if (propArr.length === 2) {
targetBlock.ensureProperty(propArr[0]).value = propArr[1];
}
else {
throw new Error("Unexpected property found.");
}
}
blockTypeId = blockTypeId.substring(0, firstCurly);
}
targetBlock.typeName = blockTypeId;
}
}
async loadFromNbtBytes(bytes) {
const tag = new NbtBinary_1.default();
tag.fromBinary(bytes, true, false);
this.nbt = tag;
await this.loadFromNbt(tag);
}
getMCStructureBytes() {
if (this.originX === undefined) {
this.originX = 10;
}
if (this.originY === undefined) {
this.originY = 10;
}
if (this.originZ === undefined) {
this.originZ = 10;
}
const nbt = this.createNbt();
if (nbt !== undefined) {
const bytes = nbt.toBinary();
return bytes;
}
Log_1.default.fail("Could not create MC Structure bytes for updated.");
return undefined;
}
async loadFromNbt(binary) {
const cube = new BlockCube_1.default();
const root = binary.singleRoot;
if (root === null) {
return;
}
const paletteTag = root.find("block_palette");
const indicesTag = root.find("block_indices");
const sizeTag = root.find("size");
if (paletteTag === null ||
sizeTag === null ||
indicesTag === null ||
sizeTag.getTagChildren().length !== 3 ||
indicesTag.getTagChildren().length !== 2) {
return;
}
const sizeTagChildren = sizeTag.getTagChildren();
const indicesChildren = indicesTag.getTagChildren();
const paletteTagChildren = paletteTag.getTagChildren();
cube.setMaxDimensions(sizeTagChildren[0].value, sizeTagChildren[1].value, sizeTagChildren[2].value);
this._blockPalette = [];
for (let i = 0; i < paletteTagChildren.length; i++) {
const state = paletteTagChildren[i];
const name = state.getProperty("name");
const states = state.getProperty("states");
const version = state.getProperty("version");
if (name != null && states != null && version != null) {
const block = new Block_1.default(name.value);
this._blockPalette.push(block);
const statesChildren = states.getTagChildren();
for (let j = 0; j < statesChildren.length; j++) {
const state = statesChildren[j];
const blockProp = block.ensureProperty(state.name);
blockProp.nbtType = state.type;
if (state.value === null) {
blockProp.value = undefined;
}
else {
blockProp.value = state.value;
}
}
block.persistenceVersion = version.value;
this.defaultBlockPersistenceVersion = block.persistenceVersion;
}
}
const blockRefs = indicesChildren[0].getTagChildren();
let i = 0;
for (let x = 0; x < cube.maxX; x++) {
for (let y = 0; y < cube.maxY; y++) {
for (let z = 0; z < cube.maxZ; z++) {
const blockRefNum = blockRefs[i].value;
const block = cube.x(x).y(y).z(z);
if (blockRefNum === -1) {
block.typeName = "minecraft:air";
}
else {
block.applyFrom(this._blockPalette[blockRefNum]);
}
block.extraLiquidDepth = -1;
i++;
}
}
}
const waterLevels = indicesChildren[1].getTagChildren();
i = 0;
for (let x = 0; x < cube.maxX; x++) {
for (let y = 0; y < cube.maxY; y++) {
for (let z = 0; z < cube.maxZ; z++) {
const secondaryBlockIndex = waterLevels[i].value;
if (secondaryBlockIndex !== -1) {
const block = cube.x(x).y(y).z(z);
const secondaryBlock = this._blockPalette[secondaryBlockIndex];
if (secondaryBlock.shortTypeName === "water") {
block.extraLiquidDepth = secondaryBlock.getPropertyNumber("liquid_depth", -1);
}
}
i++;
}
}
}
const entities = root.find("entities");
this._entities = [];
if (entities !== null) {
await Database_1.default.loadUx();
if (Database_1.default.uxCatalog !== undefined) {
const entitiesChildren = entities.getTagChildren();
for (let i = 0; i < entitiesChildren.length; i++) {
const entityTag = entitiesChildren[i];
const entity = new Entity_1.default();
const entityTagChildren = entityTag.getTagChildren();
for (let j = 0; j < entityTagChildren.length; j++) {
const entityPropertyTag = entityTagChildren[j];
if (entityPropertyTag.name === "definitions") {
entity.loadDefinitionsFromNbtTag(entityPropertyTag);
}
else if (entityPropertyTag.name === "identifier") {
Log_1.default.assert(entityPropertyTag.type === NbtBinaryTag_1.NbtTagType.string, "Expected string type");
entity.typeId = entityPropertyTag.valueAsString;
}
else if (entityPropertyTag.name === "Attributes") {
entity.loadAttributeComponentsFromNbtTag(entityPropertyTag);
}
else if (entityPropertyTag.name === "Rotation") {
entity.loadRotationFromNbtTag(entityPropertyTag);
}
else if (entityPropertyTag.name === "Tags") {
entity.loadTagsFromNbtTag(entityPropertyTag);
}
else if (entityPropertyTag.name === "ChestItems") {
const inventoryComponent = entity.ensureDataComponent("inventory", new EntityInventoryComponent_1.default());
inventoryComponent.loadFromNbtTag(entityPropertyTag);
}
else if (entityPropertyTag.name === "Armor") {
const inventoryComponent = entity.ensureDataComponent("armor_inventory", new EntityInventoryComponent_1.default());
inventoryComponent.loadFromNbtTag(entityPropertyTag);
}
else if (entityPropertyTag.name === "Mainhand") {
const subElement = entityPropertyTag.getTagChildren();
if (subElement.length === 1) {
const inventoryComponent = entity.ensureDataComponent("mainhand", new EntityInventoryComponent_1.default());
inventoryComponent.loadFromNbtTag(entityPropertyTag);
}
}
else if (entityPropertyTag.name === "Offhand") {
const subElement = entityPropertyTag.getTagChildren();
if (subElement.length === 1) {
const inventoryComponent = entity.ensureDataComponent("offhand", new EntityInventoryComponent_1.default());
inventoryComponent.loadFromNbtTag(entityPropertyTag);
}
}
else if (entityPropertyTag.name === "Pos") {
entity.loadLocationFromNbtTag(entityPropertyTag);
}
else if (entityPropertyTag.value === null) {
const prop = entity.ensureComponentProperty(entityPropertyTag.name);
prop.load();
prop.value = undefined;
}
else {
const prop = entity.ensureComponentProperty(entityPropertyTag.name);
prop.load();
prop.value = entityPropertyTag.value;
}
}
this._entities.push(entity);
}
}
}
const structureOrigin = root.find("structure_world_origin");
if (structureOrigin !== null && structureOrigin.getTagChildren().length === 3) {
const structuresOriginChildren = structureOrigin.getTagChildren();
this.originX = structuresOriginChildren[0].valueAsInt;
this.originY = structuresOriginChildren[1].valueAsInt;
this.originZ = structuresOriginChildren[2].valueAsInt;
}
else {
this.originX = undefined;
this.originY = undefined;
this.originZ = undefined;
}
this._cube = cube;
}
}
exports.default = Structure;
//# sourceMappingURL=../maps/minecraft/Structure.js.map