@minecraft/creator-tools
Version:
Minecraft Creator Tools command line and libraries.
241 lines (240 loc) • 8.64 kB
JavaScript
"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;