Add and remove structure with outline

This commit is contained in:
ForestOfLight
2025-03-10 23:16:42 -07:00
Unverified
parent f52f82b867
commit 67e3f6fecc
12 changed files with 369 additions and 153 deletions
+82
View File
@@ -0,0 +1,82 @@
import { MolangVariableMap, system, world } from "@minecraft/server";
import { Vector } from "../lib/Vector";
const drawFrequency = 8;
const drawParticle = "minecraft:villager_happy";
export class Outliner {
dimension;
min = new Vector();
max = new Vector();
#shouldDraw = true;
#drawParticles = [];
#runner = null;
constructor(dimension, min, max) {
this.dimension = world.getDimension(dimension);
this.min = new Vector(min.x, min.y, min.z);
this.max = new Vector(max.x, max.y, max.z);
}
startDraw() {
this.#shouldDraw = true;
this.#runner = system.runInterval(() => this.draw(), drawFrequency);
}
stopDraw() {
system.clearRun(this.#runner);
this.shouldDraw = false;
}
draw() {
if (!this.#shouldDraw) return;
this.#drawParticles.length = 0;
this.#drawParticles.push(...this.getCubiodParticleLocations());
for (const [particleType, location] of this.#drawParticles) {
try {
this.dimension.spawnParticle(particleType, location);
} catch {
/* pass */
}
}
}
getCubiodParticleLocations() {
const vertices = [
new Vector(this.min.x, this.min.y, this.min.z),
new Vector(this.max.x, this.min.y, this.min.z),
new Vector(this.min.x, this.max.y, this.min.z),
new Vector(this.max.x, this.max.y, this.min.z),
new Vector(this.min.x, this.min.y, this.max.z),
new Vector(this.max.x, this.min.y, this.max.z),
new Vector(this.min.x, this.max.y, this.max.z),
new Vector(this.max.x, this.max.y, this.max.z)
];
const edges = [
[0, 1],
[0, 2],
[0, 4],
[1, 3],
[1, 5],
[2, 3],
[2, 6],
[3, 7],
[4, 5],
[4, 6],
[5, 7],
[6, 7]
];
const edgePoints = [];
for (const edge of edges) {
const [startVertex, endVertex] = [vertices[edge[0]], vertices[edge[1]]];
const resolution = Math.min(Math.floor(endVertex.subtract(startVertex).length), 16);
for (let i = 1; i < resolution; i++) {
const t = i / resolution;
edgePoints.push(startVertex.lerp(endVertex, t));
}
}
return vertices.concat(edgePoints).map((v) => [drawParticle, v]);
}
}
+77
View File
@@ -0,0 +1,77 @@
import { MinecraftDimensionTypes, world } from "@minecraft/server";
import { Outliner } from "./Outliner";
export class Structure {
#structure;
#options = {
isPlaced: false,
dimensionId: MinecraftDimensionTypes.overworld,
location: { x: 0, y: 0, z: 0 },
rotation: 0,
mirror: false
};
constructor(structureName) {
this.name = structureName;
this.#structure = world.structureManager.get(structureName);
this.#options = this.loadOptions();
}
loadOptions() {
try {
return JSON.parse(world.getDynamicProperty(`structOptions:${this.name}`));
} catch (e) {
world.setDynamicProperty(`structOptions:${this.name}`, JSON.stringify(this.#options));
}
return this.#options;
}
updateOptions() {
world.setDynamicProperty(`structOptions:${this.name}`, JSON.stringify(this.#options));
}
getName() {
return this.name;
}
getStructure() {
return this.#structure;
}
getOutlineLimits() {
if (!this.#options.isPlaced)
throw new Error(`[StrucTool] Structure '${this.name}' is not placed.`);
return {
min: {
x: this.#options.location.x,
y: this.#options.location.y,
z: this.#options.location.z
},
max: {
x: this.#options.location.x + this.#structure.size.x,
y: this.#options.location.y + this.#structure.size.y,
z: this.#options.location.z + this.#structure.size.z
}
}
}
place(dimensionId, location) {
this.#options = {
isPlaced: true,
dimensionId,
location: { x: Math.floor(location.x), y: Math.floor(location.y), z: Math.floor(location.z) },
};
this.updateOptions();
this.outliner = new Outliner(dimensionId, this.getOutlineLimits().min, this.getOutlineLimits().max);
this.outliner.startDraw();
}
remove() {
if (!this.#options.isPlaced)
throw new Error(`[StrucTool] Structure '${this.name}' is not placed.`);
this.#options.isPlaced = false;
this.updateOptions();
this.outliner.stopDraw();
delete this.outliner;
}
}
+39
View File
@@ -0,0 +1,39 @@
import { world } from '@minecraft/server';
import { Structure } from './Structure';
class StructureCollection {
#structures;
constructor() {
this.#structures = {};
}
add(name) {
const struct = world.structureManager.get(name);
this.#structures[name] = new Structure(name, struct);
}
get(name) {
const structure = this.#structures[name];
if (!structure) {
throw new Error(`Structure ${name} not found.`);
}
return structure;
}
remove(name) {
const struct = this.get(name);
struct.remove();
delete this.#structures[name];
}
place(name, dimensionId, location) {
const struct = this.get(name);
if (!struct) {
throw new Error(`Structure ${name} not found.`);
}
struct.place(dimensionId, location);
}
}
export const structureCollection = new StructureCollection();