Refactoring StructureInstance
This commit is contained in:
@@ -1,191 +1,28 @@
|
||||
import { world } from "@minecraft/server";
|
||||
import { Vector } from "../lib/Vector";
|
||||
import { StructureOutliner } from "./StructureOutliner";
|
||||
import { StructureVerifier } from "./StructureVerifier";
|
||||
import { InstanceOptions } from "./InstanceOptions";
|
||||
import { Structure } from "./Structure";
|
||||
|
||||
export class StructureInstance {
|
||||
name;
|
||||
#structure;
|
||||
#options = {
|
||||
structureId: void 0,
|
||||
isEnabled: false,
|
||||
dimensionId: void 0,
|
||||
worldLocation: { x: 0, y: 0, z: 0 },
|
||||
rotation: 0,
|
||||
mirror: false,
|
||||
currentLayer: 0,
|
||||
verifier: {
|
||||
shouldRender: true,
|
||||
trackPlayerDistance: 5,
|
||||
intervalOrLifetime: 10
|
||||
}
|
||||
};
|
||||
outliner = void 0;
|
||||
options;
|
||||
structure = void 0;
|
||||
verifier = void 0;
|
||||
outliner = void 0;
|
||||
|
||||
constructor(instanceName, structureId) {
|
||||
this.name = instanceName;
|
||||
this.#structure = world.structureManager.get(structureId);
|
||||
if (!this.#structure)
|
||||
throw new Error(`[StrucTool] Structure '${structureId}' not found.`);
|
||||
this.#structure.saveToWorld();
|
||||
this.#options = this.loadOptions();
|
||||
this.#options.structureId = structureId;
|
||||
this.updateOptions();
|
||||
this.structure = new Structure(structureId);
|
||||
this.options = new InstanceOptions(instanceName, structureId);
|
||||
this.refreshBox();
|
||||
}
|
||||
|
||||
loadOptions() {
|
||||
try {
|
||||
return JSON.parse(world.getDynamicProperty(`structOptions:${this.name}`));
|
||||
} catch (e) {
|
||||
world.setDynamicProperty(`structOptions:${this.name}`, JSON.stringify(this.#options));
|
||||
}
|
||||
return this.#options;
|
||||
}
|
||||
|
||||
delete() {
|
||||
this.disable();
|
||||
world.setDynamicProperty(`structOptions:${this.name}`, void 0);
|
||||
this.#structure = void 0;
|
||||
this.#options = void 0;
|
||||
this.options.clear();
|
||||
delete this.options;
|
||||
delete this.structure;
|
||||
delete this.outliner;
|
||||
}
|
||||
|
||||
static parseOptions(instanceName) {
|
||||
const options = JSON.parse(world.getDynamicProperty(`structOptions:${instanceName}`));
|
||||
if (!options)
|
||||
throw new Error(`[StrucTool] Instance '${instanceName}' not found.`);
|
||||
return options;
|
||||
}
|
||||
|
||||
updateOptions() {
|
||||
world.setDynamicProperty(`structOptions:${this.name}`, JSON.stringify(this.#options));
|
||||
}
|
||||
|
||||
getStructure() {
|
||||
return this.#structure;
|
||||
}
|
||||
|
||||
getStructureId() {
|
||||
return this.#options.structureId;
|
||||
}
|
||||
|
||||
getLocation() {
|
||||
return { dimensionId: this.#options.dimensionId, location: this.#options.worldLocation };
|
||||
}
|
||||
|
||||
getHeight() {
|
||||
return this.#structure.size.y;
|
||||
}
|
||||
|
||||
getLayer() {
|
||||
return this.#options.currentLayer || 0;
|
||||
}
|
||||
|
||||
getDimension() {
|
||||
let dimension;
|
||||
try {
|
||||
dimension = world.getDimension(this.#options.dimensionId);
|
||||
} catch (e) {
|
||||
console.warn(`[StrucTool] Dimension '${this.#options.dimensionId}' not found. Defaulting to 'minecraft:overworld'.`);
|
||||
dimension = world.getDimension("minecraft:overworld");
|
||||
}
|
||||
return dimension;
|
||||
}
|
||||
|
||||
getBlock(structureLocation) {
|
||||
const blockPermutation = this.#structure.getBlockPermutation({ x: structureLocation.x, y: structureLocation.y, z: structureLocation.z });
|
||||
if (!blockPermutation)
|
||||
return void 0;
|
||||
blockPermutation.location = structureLocation;
|
||||
return blockPermutation;
|
||||
}
|
||||
|
||||
*getBlocks(locations = void 0) {
|
||||
if (locations === void 0) {
|
||||
for (let y = 0; y < this.#structure.size.y; y++) {
|
||||
yield * this.getLayerBlocks(y);
|
||||
}
|
||||
} else {
|
||||
for (const location of locations) {
|
||||
yield this.getBlock(location);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*getLayerBlocks(y) {
|
||||
for (let x = 0; x < this.#structure.size.x; x++) {
|
||||
for (let z = 0; z < this.#structure.size.z; z++) {
|
||||
yield this.getBlock({ x, y, z });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
getBounds() {
|
||||
return {
|
||||
min: new Vector(0, 0, 0),
|
||||
max: new Vector(this.#structure.size.x, this.#structure.size.y, this.#structure.size.z)
|
||||
};
|
||||
}
|
||||
|
||||
getLayeredBounds() {
|
||||
if (!this.#options.isEnabled)
|
||||
throw new Error(`[StrucTool] Instance '${this.name}' is not placed.`);
|
||||
return {
|
||||
min: new Vector(0, this.#options.currentLayer - 1, 0),
|
||||
max: new Vector(this.#structure.size.x, this.#options.currentLayer, this.#structure.size.z)
|
||||
};
|
||||
}
|
||||
|
||||
getTotalVolume() {
|
||||
return this.#structure.size.x * this.#structure.size.y * this.#structure.size.z;
|
||||
}
|
||||
|
||||
getActiveVolume() {
|
||||
if (!this.#options.isEnabled)
|
||||
return 0;
|
||||
if (this.#options.currentLayer === 0)
|
||||
return this.getTotalVolume();
|
||||
return this.#structure.size.x * this.#structure.size.z;
|
||||
}
|
||||
|
||||
rename(newName) {
|
||||
world.setDynamicProperty(`structOptions:${this.name}`, void 0);
|
||||
this.name = newName;
|
||||
world.setDynamicProperty(`structOptions:${this.name}`, JSON.stringify(this.#options));
|
||||
}
|
||||
|
||||
place(dimensionId, worldLocation) {
|
||||
this.move(dimensionId, worldLocation);
|
||||
this.enable();
|
||||
}
|
||||
|
||||
enable() {
|
||||
this.#options.isEnabled = true;
|
||||
this.updateOptions();
|
||||
this.refreshBox();
|
||||
}
|
||||
|
||||
disable() {
|
||||
this.#options.isEnabled = false;
|
||||
this.updateOptions();
|
||||
this.refreshBox();
|
||||
}
|
||||
|
||||
move(dimensionId, location) {
|
||||
this.#options.dimensionId = dimensionId;
|
||||
this.#options.worldLocation = { x: Math.floor(location.x), y: Math.floor(location.y), z: Math.floor(location.z) };
|
||||
this.updateOptions();
|
||||
this.refreshBox();
|
||||
}
|
||||
|
||||
setLayer(layer) {
|
||||
if (layer < 0 || layer > this.#structure.size.y)
|
||||
throw new Error(`[StrucTool] Layer ${layer} is out of bounds.`);
|
||||
this.#options.currentLayer = layer;
|
||||
this.updateOptions();
|
||||
this.refreshBox();
|
||||
delete this.verifier;
|
||||
}
|
||||
|
||||
refreshBox() {
|
||||
@@ -194,101 +31,174 @@ export class StructureInstance {
|
||||
if (!this.outliner)
|
||||
this.outliner = new StructureOutliner(this);
|
||||
if (!this.verifier)
|
||||
this.verifier = new StructureVerifier(this, { shouldRender: this.#options.verifier.shouldRender, trackPlayerDistance: this.#options.verifier.trackPlayerDistance });
|
||||
this.verifier = new StructureVerifier(this, { isEnabled: this.options.verifier.isEnabled, trackPlayerDistance: this.options.verifier.trackPlayerDistance });
|
||||
this.outliner.refresh();
|
||||
this.verifier.refresh();
|
||||
}
|
||||
|
||||
isLocationInStructure(dimensionId, structureLocation) {
|
||||
if (this.#options.dimensionId !== dimensionId)
|
||||
return false
|
||||
const { min, max } = this.getBounds();
|
||||
return structureLocation.x >= min.x && structureLocation.x < max.x
|
||||
&& structureLocation.y >= min.y && structureLocation.y < max.y
|
||||
&& structureLocation.z >= min.z && structureLocation.z < max.z;
|
||||
getStructureId() {
|
||||
return this.options.structureId;
|
||||
}
|
||||
|
||||
isLocationInLayer(dimensionId, structureLocation) {
|
||||
if (!this.#options.isEnabled || this.#options.dimensionId !== dimensionId)
|
||||
return false
|
||||
const { min, max } = this.getLayeredBounds(true);
|
||||
return structureLocation.x >= min.x && structureLocation.x < max.x
|
||||
&& structureLocation.y >= min.y && structureLocation.y < max.y
|
||||
&& structureLocation.z >= min.z && structureLocation.z < max.z;
|
||||
getLocation() {
|
||||
return { dimensionId: this.options.dimensionId, location: this.options.worldLocation };
|
||||
}
|
||||
|
||||
isLocationActive(dimensionId, structureLocation, { useLayers = true } = {}) {
|
||||
if (!this.#options.isEnabled || this.#options.dimensionId !== dimensionId)
|
||||
return false
|
||||
if (useLayers && this.#options.currentLayer !== 0)
|
||||
return this.isLocationInLayer(dimensionId, structureLocation);
|
||||
return this.isLocationInStructure(dimensionId, structureLocation);
|
||||
getDimension() {
|
||||
return this.options.getDimension();
|
||||
}
|
||||
|
||||
toGlobalCoords(structureLocation) {
|
||||
return new Vector(
|
||||
this.#options.worldLocation.x + structureLocation.x,
|
||||
this.#options.worldLocation.y + structureLocation.y,
|
||||
this.#options.worldLocation.z + structureLocation.z
|
||||
);
|
||||
getMaxLayer() {
|
||||
return this.structure.getHeight();
|
||||
}
|
||||
|
||||
toStructureCoords(worldLocation) {
|
||||
return new Vector(
|
||||
worldLocation.x - this.#options.worldLocation.x,
|
||||
worldLocation.y - this.#options.worldLocation.y,
|
||||
worldLocation.z - this.#options.worldLocation.z
|
||||
);
|
||||
getLayer() {
|
||||
return this.options.currentLayer;
|
||||
}
|
||||
|
||||
getBounds() {
|
||||
return {
|
||||
min: this.structure.getMin(),
|
||||
max: this.structure.getMax()
|
||||
}
|
||||
}
|
||||
|
||||
getActiveBounds() {
|
||||
if (!this.options.isEnabled)
|
||||
throw new Error(`[StrucTool] Instance '${this.options.instanceName}' is not placed.`);
|
||||
if (this.hasLayerSelected())
|
||||
return this.getLayeredBounds();
|
||||
return this.getBounds();
|
||||
}
|
||||
|
||||
getLayeredBounds() {
|
||||
if (!this.options.isEnabled)
|
||||
throw new Error(`[StrucTool] Instance '${this.options.instanceName}' is not placed.`);
|
||||
const min = this.structure.getMin();
|
||||
const max = this.structure.getMax();
|
||||
return {
|
||||
min: new Vector(min.x, this.options.currentLayer - 1, min.z),
|
||||
max: new Vector(max.x, this.options.currentLayer, max.z)
|
||||
};
|
||||
}
|
||||
|
||||
getBlock(structureLocation) {
|
||||
return this.structure.getBlock(structureLocation);
|
||||
}
|
||||
|
||||
getBlocks(structureLocations) {
|
||||
return this.structure.getBlocks(structureLocations);
|
||||
}
|
||||
|
||||
getLayerBlocks(layer) {
|
||||
return this.structure.getLayerBlocks(layer);
|
||||
}
|
||||
|
||||
getAllBlocks() {
|
||||
return this.structure.getAllBlocks();
|
||||
}
|
||||
|
||||
isLocationActive(dimensionId, structureLocation, { useActiveLayer = true } = {}) {
|
||||
if (!this.options.isEnabled || this.options.dimensionId !== dimensionId)
|
||||
return false;
|
||||
let bounds;
|
||||
if (useActiveLayer)
|
||||
bounds = this.getActiveBounds();
|
||||
else
|
||||
bounds = this.getBounds();
|
||||
return structureLocation.x >= bounds.min.x && structureLocation.x < bounds.max.x
|
||||
&& structureLocation.y >= bounds.min.y && structureLocation.y < bounds.max.y
|
||||
&& structureLocation.z >= bounds.min.z && structureLocation.z < bounds.max.z;
|
||||
}
|
||||
|
||||
isEnabled() {
|
||||
return this.#options.isEnabled;
|
||||
return this.options.isEnabled;
|
||||
}
|
||||
|
||||
hasLocation() {
|
||||
return this.#options.dimensionId && this.#options.worldLocation.x !== 0 && this.#options.worldLocation.y !== 0 && this.#options.worldLocation.z !== 0;
|
||||
}
|
||||
|
||||
isUsingLayers() {
|
||||
return this.hasLayers() && this.#options.currentLayer !== 0;
|
||||
return this.options.dimensionId && this.options.worldLocation.x !== 0 && this.options.worldLocation.y !== 0 && this.options.worldLocation.z !== 0;
|
||||
}
|
||||
|
||||
hasLayers() {
|
||||
return this.#structure.size.y > 1;
|
||||
return this.getMaxLayer() > 1;
|
||||
}
|
||||
|
||||
hasLayerSelected() {
|
||||
return this.hasLayers() && this.options.currentLayer !== 0;
|
||||
}
|
||||
|
||||
hasWholeStructureSelected() {
|
||||
return this.hasLocation() && this.options.currentLayer === 0;
|
||||
}
|
||||
|
||||
isAtMaxLayer() {
|
||||
return !this.hasLayers || this.#options.currentLayer >= this.#structure.size.y;
|
||||
return !this.hasLayers || this.options.currentLayer >= this.getMaxLayer();
|
||||
}
|
||||
|
||||
isAtMinLayer() {
|
||||
return !this.hasLayers || this.#options.currentLayer <= 0;
|
||||
return !this.hasLayers || this.options.currentLayer <= 0;
|
||||
}
|
||||
|
||||
enable() {
|
||||
this.options.enable();
|
||||
this.refreshBox();
|
||||
}
|
||||
|
||||
disable() {
|
||||
this.options.disable();
|
||||
this.refreshBox();
|
||||
}
|
||||
|
||||
rename(newName) {
|
||||
this.options.rename(newName);
|
||||
}
|
||||
|
||||
place(dimensionId, worldLocation) {
|
||||
this.move(dimensionId, worldLocation);
|
||||
this.enable();
|
||||
}
|
||||
|
||||
move(dimensionId, worldLocation) {
|
||||
this.options.move(dimensionId, worldLocation);
|
||||
this.refreshBox();
|
||||
}
|
||||
|
||||
setLayer(layer) {
|
||||
if (layer < 0 || layer > this.getMaxLayer())
|
||||
throw new Error(`[StrucTool] Layer ${layer} is out of bounds.`);
|
||||
this.options.setLayer(layer);
|
||||
this.refreshBox();
|
||||
}
|
||||
|
||||
setVerifierEnabled(enable) {
|
||||
this.options.setVerifierEnabled(enable);
|
||||
this.verifier.refresh();
|
||||
}
|
||||
|
||||
setVerifierDistance(distance) {
|
||||
this.options.setVerifierDistance(distance);
|
||||
this.verifier.refresh();
|
||||
}
|
||||
|
||||
increaseLayer() {
|
||||
if (this.isAtMaxLayer())
|
||||
this.setLayer(0);
|
||||
else
|
||||
this.setLayer(this.#options.currentLayer + 1);
|
||||
this.setLayer(this.options.currentLayer + 1);
|
||||
}
|
||||
|
||||
decreaseLayer() {
|
||||
if (this.isAtMinLayer())
|
||||
this.setLayer(this.#structure.size.y);
|
||||
this.setLayer(this.getMaxLayer());
|
||||
else
|
||||
this.setLayer(this.#options.currentLayer - 1);
|
||||
this.setLayer(this.options.currentLayer - 1);
|
||||
}
|
||||
|
||||
getDimension() {
|
||||
return world.getDimension(this.#options.dimensionId);
|
||||
toGlobalCoords(structureLocation) {
|
||||
return Vector.from(structureLocation).add(this.options.worldLocation);
|
||||
}
|
||||
|
||||
setVerifierOptions({ shouldRender, trackPlayerDistance, intervalOrLifetime }) {
|
||||
this.#options.verifier.shouldRender = shouldRender;
|
||||
this.#options.verifier.trackPlayerDistance = trackPlayerDistance;
|
||||
this.#options.verifier.intervalOrLifetime = intervalOrLifetime;
|
||||
this.updateOptions();
|
||||
this.verifier.setOptions(this.#options.verifier);
|
||||
this.verifier.refresh();
|
||||
toStructureCoords(worldLocation) {
|
||||
return Vector.from(worldLocation).subtract(this.options.worldLocation);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user