UNPKG

@minecraft/creator-tools

Version:

Minecraft Creator Tools command line and libraries.

241 lines (240 loc) 8.64 kB
"use strict"; // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const BlockVolumePlane_1 = __importDefault(require("./BlockVolumePlane")); const ste_events_1 = require("ste-events"); const Entity_1 = __importDefault(require("./Entity")); const Log_1 = __importDefault(require("../core/Log")); class BlockVolume { _maxX = 1; _maxY = 1; _maxZ = 1; _onMaxDimensionsChanged = new ste_events_1.EventDispatcher(); _onBlockTypeChanged = new ste_events_1.EventDispatcher(); _onBlockPropertyChanged = new ste_events_1.EventDispatcher(); _columns; _entities = []; get onMaxDimensionsChanged() { return this._onMaxDimensionsChanged.asEvent(); } get onBlockTypeChanged() { return this._onBlockTypeChanged.asEvent(); } get onBlockPropertyChanged() { return this._onBlockPropertyChanged.asEvent(); } get columns() { if (this._columns === undefined) { this._columns = this._generateColumnInfo(); } return this._columns; } get maxX() { return this._maxX; } get maxY() { return this._maxY; } get maxZ() { return this._maxZ; } set maxX(newMaxX) { this._maxX = newMaxX; this._onMaxDimensionsChanged.dispatch(this, "x"); } set maxY(newMaxY) { this._maxY = newMaxY; this._onMaxDimensionsChanged.dispatch(this, "y"); } set maxZ(newMaxZ) { this._maxZ = newMaxZ; this._onMaxDimensionsChanged.dispatch(this, "z"); } setMaxDimensions(newMaxX, newMaxY, newMaxZ) { this._maxX = newMaxX; this._maxY = newMaxY; this._maxZ = newMaxZ; this._onMaxDimensionsChanged.dispatch(this, "xyz"); } planes; constructor() { this.planes = []; } spawnEntity(entityTypeId, location) { const e = new Entity_1.default(); return e; } getBlock(location) { Log_1.default.assert(location.x >= 0 && location.x <= this.maxX && location.y >= 0 && location.x <= this.maxY && location.z >= 0 && location.z <= this.maxZ, "Block location not within bounds."); return this.x(location.x).y(location.y).z(location.z); } getCommandList(fromX, fromY, fromZ) { const commands = []; for (let x = 0; x < this.maxX; x++) { for (let y = 0; y < this.maxY; y++) { for (let z = 0; z < this.maxZ; z++) { const block = this.x(x).y(y).z(z); if (!block.isEmpty) { commands.push("setblock ~" + (fromX + x) + " ~" + (fromY + y) + " ~" + (fromZ + z) + " " + block.typeName); } } } } return commands; } _generateColumnInfo() { const newColumns = new Array(this.maxZ); for (let z = 0; z < this.maxY; z++) { newColumns[z] = new Array(this.maxX); for (let x = 0; x < this.maxX; x++) { const blockX = this.x(x); let foundOpaqueTop = false; let foundContiguousTop = false; let opaqueTop = 0; let contiguousTop = 0; let top = 0; for (let y = 0; z < this.maxY; y++) { const block = blockX.y(y).z(z); if (!block.isEmpty && block.isOpaque && !foundOpaqueTop) { opaqueTop++; } else if (!block.isEmpty) { if (!foundContiguousTop) { contiguousTop++; } top = y; if (!block.isOpaque) { foundOpaqueTop = true; } } else { foundOpaqueTop = true; foundContiguousTop = true; } } newColumns[x][z] = { contiguousHeight: contiguousTop, height: top, opaqueHeight: opaqueTop, }; } } return newColumns; } _notifyBlockTypeChanged(block) { this._columns = undefined; this._onBlockTypeChanged.dispatch(this, block); } _notifyBlockPropertyChanged(block) { this._onBlockPropertyChanged.dispatch(this, block); } x(int) { if (int > this.maxX) { throw new Error("Value exceeds maximum X"); } while (int >= this.planes.length) { const newX = this.planes.length; this.planes[newX] = new BlockVolumePlane_1.default(this, newX); } return this.planes[int]; } fillEmpty(blockTypeId, xFrom, yFrom, zFrom, xTo, yTo, zTo) { for (let x = xFrom; x <= xTo; x++) { for (let y = yFrom; y <= yTo; y++) { let block = this.x(x).y(y).z(zFrom); block.typeName = blockTypeId; block = this.x(x).y(y).z(zTo); block.typeName = blockTypeId; } } for (let y = yFrom; y <= yTo; y++) { for (let z = zFrom + 1; z < zTo; z++) { let block = this.x(xFrom).y(y).z(z); block.typeName = blockTypeId; block = this.x(xTo).y(y).z(z); block.typeName = blockTypeId; } } } fill(blockTypeId, xFrom, yFrom, zFrom, xTo, yTo, zTo) { for (let x = xFrom; x <= xTo; x++) { for (let y = yFrom; y <= yTo; y++) { for (let z = zFrom; z <= zTo; z++) { const block = this.x(x).y(y).z(z); block.typeName = blockTypeId; } } } } fillY(blockTypeId, y) { for (let x = 0; x < this.maxX; x++) { const zSlice = this.x(x).y(y); for (let z = 0; z < this.maxZ; z++) { const block = zSlice.z(z); block.typeName = blockTypeId; } } } /** * Resizes the volume to new dimensions, preserving existing block data * within the overlapping region. Growth fills with air; blocks outside * shrunken bounds are discarded. Corner-anchored (origin stays at 0,0,0). */ resize(newMaxX, newMaxY, newMaxZ) { const oldMaxX = this._maxX; const oldMaxY = this._maxY; const oldMaxZ = this._maxZ; const oldPlanes = this.planes; // Create fresh planes array this.planes = []; this._maxX = newMaxX; this._maxY = newMaxY; this._maxZ = newMaxZ; // Copy blocks from old data where coordinates exist in both old and new bounds const copyX = Math.min(oldMaxX, newMaxX); const copyY = Math.min(oldMaxY, newMaxY); const copyZ = Math.min(oldMaxZ, newMaxZ); for (let xI = 0; xI < copyX; xI++) { if (xI >= oldPlanes.length) { break; } const oldPlane = oldPlanes[xI]; for (let yI = 0; yI < copyY; yI++) { if (yI >= oldPlane.lines.length) { break; } const oldLine = oldPlane.lines[yI]; for (let zI = 0; zI < copyZ; zI++) { if (zI >= oldLine.blocks.length) { break; } const oldBlock = oldLine.blocks[zI]; if (oldBlock && !oldBlock.isEmpty) { const newBlock = this.x(xI).y(yI).z(zI); newBlock.typeName = oldBlock.typeName; if (oldBlock.properties) { for (const key in oldBlock.properties) { const prop = oldBlock.properties[key]; if (prop && prop.value !== undefined) { newBlock.ensureProperty(key).value = prop.value; } } } } } } } this._columns = undefined; this._onMaxDimensionsChanged.dispatch(this, "xyz"); } } exports.default = BlockVolume;