Files
Construct-CN/packs/BP/scripts/classes/Structure/Structure.js
T
wed150 136d5ffa3b
/ build (push) Has been cancelled
Start working at 1.2.0
2026-08-26 09:54:39 +08:00

142 lines
4.2 KiB
JavaScript

import { world } from "@minecraft/server";
import { Vector } from "../../lib/Vector";
import { StructureNotFoundError } from "../Errors/StructureNotFoundError";
const NOT_LOADED = 0;
const NO_BLOCK = 1;
const SLOT_WIDTHS = [
{ maxSlot: 0xFF, ArrayType: Uint8Array },
{ maxSlot: 0xFFFF, ArrayType: Uint16Array },
{ maxSlot: 0xFFFFFFFF, ArrayType: Uint32Array },
];
export class Structure {
structureId;
#structure;
#size;
#paletteSlots;
#widthIndex = 0;
#palette = [void 0, void 0];
#slotsByKey = new Map();
constructor(structureId) {
this.structureId = structureId;
this.#structure = world.structureManager.get(structureId);
if (!this.#structure)
throw new StructureNotFoundError(structureId);
this.#structure.saveToWorld();
this.#size = { ...this.#structure.size };
this.#paletteSlots = new SLOT_WIDTHS[0].ArrayType(this.#size.x * this.#size.y * this.#size.z);
}
getHeight() {
return this.#size.y;
}
getMin() {
return { x: 0, y: 0, z: 0 };
}
getMax() {
return this.#size;
}
getBlock(structureLocation) {
const index = this.#toIndex(structureLocation);
if (index === void 0)
return this.#palette[this.#loadSlot(structureLocation)];
const slot = this.#paletteSlots[index];
if (slot !== NOT_LOADED)
return this.#palette[slot];
const loadedSlot = this.#loadSlot(structureLocation);
this.#paletteSlots[index] = loadedSlot;
return this.#palette[loadedSlot];
}
#toIndex(structureLocation) {
const x = Math.floor(structureLocation.x);
const y = Math.floor(structureLocation.y);
const z = Math.floor(structureLocation.z);
if (x < 0 || y < 0 || z < 0 || x >= this.#size.x || y >= this.#size.y || z >= this.#size.z)
return void 0;
return (y * this.#size.z + z) * this.#size.x + x;
}
#loadSlot(structureLocation) {
const blockPermutation = this.#structure.getBlockPermutation(structureLocation);
if (!blockPermutation)
return NO_BLOCK;
return this.#intern(blockPermutation, this.#structure.getIsWaterlogged(structureLocation));
}
#intern(blockPermutation, isWaterlogged) {
const typeId = blockPermutation.type.id;
const states = blockPermutation.getAllStates();
const key = `${typeId}|${isWaterlogged ? 1 : 0}|${JSON.stringify(states)}`;
const interned = this.#slotsByKey.get(key);
if (interned !== void 0)
return interned;
const slot = this.#palette.length;
this.#palette.push({
permutation: blockPermutation,
typeId,
states,
hasStates: Object.keys(states).length > 0,
isWaterlogged
});
this.#slotsByKey.set(key, slot);
if (slot > SLOT_WIDTHS[this.#widthIndex].maxSlot)
this.#widenPaletteSlots();
return slot;
}
#widenPaletteSlots() {
this.#widthIndex++;
this.#paletteSlots = new SLOT_WIDTHS[this.#widthIndex].ArrayType(this.#paletteSlots);
}
*getBlocks(locations) {
for (const location of locations) {
yield this.getBlock(location);
}
}
*getLayerBlocks(layer) {
for (let x = 0; x < this.#size.x; x++) {
for (let z = 0; z < this.#size.z; z++) {
yield this.getBlock({ x, y: layer, z });
}
}
}
*getAllBlocks() {
for (let y = 0; y < this.#size.y; y++) {
yield * this.getLayerBlocks(y);
}
}
getLayerLocations(layer) {
const locations = new Set();
for (let x = 0; x < this.#size.x; x++) {
for (let z = 0; z < this.#size.z; z++) {
locations.add(new Vector(x, layer, z));
}
}
return locations;
}
getAllLocations() {
const locations = new Set();
for (let y = 0; y < this.#size.y; y++) {
const layerLocations = this.getLayerLocations(y);
for (const location of layerLocations) {
locations.add(location);
}
}
return locations;
}
}