init: remove old files
/ build (push) Has been cancelled

This commit is contained in:
2026-08-26 13:49:37 +08:00 Unverified
parent 136d5ffa3b
commit eb50a01901
12 changed files with 0 additions and 744 deletions
BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 49 KiB

@@ -1,27 +0,0 @@
import { world, system } from '@minecraft/server';
import { MENU_ITEM } from '../consts';
import { MenuForm } from './MenuForm';
import { structureCollection } from './Structure/StructureCollection';
import { Builders } from './Builder/Builders';
world.beforeEvents.itemUse.subscribe((event) => {
if (!event.source || event.itemStack?.typeId !== MENU_ITEM) return;
event.cancel = true;
const builder = Builders.get(event.source.id);
system.run(() => {
if (builder.isFlexibleInstanceMoving())
return;
openMenu(event.source, event);
});
});
function openMenu(player, event = void 0) {
const options = { jumpToInstance: true };
if (event) {
const instanceNames = structureCollection.getInstanceNames();
const instanceName = event.itemStack?.nameTag;
if (instanceNames.includes(instanceName))
options.instanceName = instanceName;
}
new MenuForm(player, options);
}
-123
View File
@@ -1,123 +0,0 @@
import { MolangVariableMap, system, TicksPerSecond } from "@minecraft/server";
import { Vector } from "../lib/Vector";
export class Outliner {
dimension;
min = new Vector();
max = new Vector();
drawParticle = "construct:outline";
drawFrequency;
particleLifetime;
#drawParticles = [];
#runner = void 0;
constructor(dimension, min, max, drawFrequency = 10, particleLifetime = 20) {
this.dimension = dimension;
this.min = Vector.from(min);
this.max = Vector.from(max);
this.drawFrequency = drawFrequency;
this.particleLifetime = particleLifetime;
this.vertices = this.getVertices(min, max);
}
startDraw() {
this.#runner = system.runInterval(() => this.draw(), this.drawFrequency);
}
stopDraw() {
if (!this.#runner)
return;
system.clearRun(this.#runner);
this.#runner = void 0;
}
draw() {
this.drawParticles(this.getVerticeParticles(), () => {
return { red: 1, green: 1, blue: 1, alpha: 1 }
});
this.drawParticles(this.getCubiodEdgeParticles(), this.getNextParticleColor.bind(this));
}
drawParticles(particleLocations, colorCallback) {
this.#drawParticles.length = 0;
this.#drawParticles.push(...particleLocations);
for (const [particleType, location] of this.#drawParticles) {
const molang = new MolangVariableMap();
molang.setColorRGBA("dot_color", colorCallback());
const lifetimeSeconds = this.particleLifetime / TicksPerSecond;
molang.setFloat("lifetime", lifetimeSeconds);
try {
this.dimension.spawnParticle(particleType, location, molang);
} catch (e) {
/* pass */
}
}
}
getVertices(min, max) {
return [
new Vector(min.x, min.y, min.z),
new Vector(max.x, min.y, min.z),
new Vector(min.x, max.y, min.z),
new Vector(max.x, max.y, min.z),
new Vector(min.x, min.y, max.z),
new Vector(max.x, min.y, max.z),
new Vector(min.x, max.y, max.z),
new Vector(max.x, max.y, max.z)
];
}
setVertices(dimension, min, max) {
this.dimension = dimension;
this.min = Vector.from(min);
this.max = Vector.from(max);
this.vertices = this.getVertices(min, max);
}
getVerticeParticles() {
return this.vertices.map((v) => [this.drawParticle, v]);
}
getCubiodEdgeParticles() {
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] = [this.vertices[edge[0]], this.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 edgePoints.map((v) => [this.drawParticle, v]);
}
addStandaloneParticles(locations) {
for (const location of locations)
this.vertices.push(Vector.from(location));
}
getNextParticleColor() {
if (this.lastWasBlack) {
this.lastWasBlack = false;
return { red: 0.93333333, green: 0.77647059, blue: 0.13333333, alpha: 1 };
} else {
this.lastWasBlack = true;
return { red: 0.09019608, green: 0.09019608, blue: 0.09019608, alpha: 1 };
}
}
}
@@ -1,86 +0,0 @@
import { MolangVariableMap } from "@minecraft/server";
import { BlockVerificationLevel } from "../Enums/BlockVerificationLevel";
import { Vector } from "../../lib/Vector";
export class BlockVerificationLevelRender {
opacity = 0.2;
lifetimeSeconds = 0;
constructor(dimensionLocation, verificationLevel, lifetimeSeconds = 5) {
this.dimension = dimensionLocation.dimension;
this.location = Vector.from(dimensionLocation.location);
this.verificationLevel = verificationLevel;
this.lifetimeSeconds = lifetimeSeconds;
this.renderBlock();
}
renderBlock() {
const sizeScalar = this.verificationLevelToSizeScalar();
for (const particle of this.getBlockParticles(sizeScalar)) {
const color = this.getRGBAMolang();
if (!color)
return;
color.setFloat("lifetime", this.lifetimeSeconds);
color.setFloat("width", 0.5*sizeScalar);
color.setFloat("height", 0.5*sizeScalar);
try {
this.dimension.spawnParticle(particle.particleType, particle.location, color);
} catch {
/* pass */
}
}
}
getBlockParticles(sizeScalar = 1) {
const bottomFace = new Vector(0.5, 0, 0.5);
const topFace = new Vector(0.5, 1, 0.5);
const leftFace = new Vector(1, 0.5, 0.5);
const rightFace = new Vector(0, 0.5, 0.5);
const frontFace = new Vector(0.5, 0.5, 1);
const backFace = new Vector(0.5, 0.5, 0);
const center = new Vector(0.5, 0.5, 0.5);
return [
{ particleType: "construct:blockoverlay_xz", location: this.location.add(center).add(topFace.subtract(center).multiply(sizeScalar)) },
{ particleType: "construct:blockoverlay_xz", location: this.location.add(center).add(bottomFace.subtract(center).multiply(sizeScalar)) },
{ particleType: "construct:blockoverlay_yz", location: this.location.add(center).add(leftFace.subtract(center).multiply(sizeScalar)) },
{ particleType: "construct:blockoverlay_yz", location: this.location.add(center).add(rightFace.subtract(center).multiply(sizeScalar)) },
{ particleType: "construct:blockoverlay_xy", location: this.location.add(center).add(frontFace.subtract(center).multiply(sizeScalar)) },
{ particleType: "construct:blockoverlay_xy", location: this.location.add(center).add(backFace.subtract(center).multiply(sizeScalar)) }
];
}
getRGBAMolang() {
const rgb = this.verificationLevelToRGB();
if (!rgb) return;
rgb.alpha = this.opacity;
const molang = new MolangVariableMap();
molang.setColorRGBA("face_color", rgb);
return molang;
}
verificationLevelToRGB() {
switch (this.verificationLevel) {
case BlockVerificationLevel.NoMatch:
return { red: 1, green: 0, blue: 0};
case BlockVerificationLevel.TypeMatch:
return { red: 1, green: 1, blue: 0};
case BlockVerificationLevel.Missing:
return { red: 0, green: 0, blue: 1};
default:
return void 0;
}
}
verificationLevelToSizeScalar() {
switch (this.verificationLevel) {
case BlockVerificationLevel.NoMatch:
return 1.01;
case BlockVerificationLevel.TypeMatch:
return 1.01;
case BlockVerificationLevel.Missing:
return 0.90;
default:
return 1.00;
}
}
}
@@ -1,54 +0,0 @@
import { StructureNotFoundError } from '../Errors/StructureNotFoundError';
import { Outliner } from '../Outliner';
export class StructureOutliner {
constructor(instance) {
this.instance = instance;
this.pullInstanceData();
this.outliner = new Outliner(this.dimension, this.bounds.min, this.bounds.max);
}
pullInstanceData() {
try {
this.dimension = this.instance.getDimension();
this.bounds = this.instance.getBounds();
this.bounds.min = this.instance.toGlobalCoords(this.bounds.min);
this.bounds.max = this.instance.toGlobalCoords(this.bounds.max);
} catch (error) {
if (error instanceof StructureNotFoundError)
this.outliner.stopDraw();
else
throw error;
}
}
refresh() {
this.pullInstanceData();
this.refreshDraw();
}
refreshDraw() {
this.outliner.stopDraw();
if (!this.instance.isEnabled())
return;
if (this.instance.hasLayerSelected())
this.layeredDraw();
else
this.boxDraw();
this.outliner.startDraw();
}
boxDraw() {
this.outliner.setVertices(this.dimension, this.bounds.min, this.bounds.max);
}
layeredDraw() {
const { min, max } = this.instance.getLayerBounds(this.instance.getLayer());
this.outliner.setVertices(this.dimension, this.instance.toGlobalCoords(min), this.instance.toGlobalCoords(max));
this.outliner.addStandaloneParticles(this.getCornerVertices());
}
getCornerVertices() {
return this.outliner.getVertices(this.bounds.min, this.bounds.max);
}
}
@@ -1,117 +0,0 @@
import { TicksPerSecond } from "@minecraft/server";
import { BlockVerificationLevelRender } from "./BlockVerificationLevelRender";
import { system } from "@minecraft/server";
const RENDER_LIFETIME_FACTOR_TICKS = 1;
export class VerificationRenderer {
instance;
lastRenderedChunk;
bounds;
shortestDimension;
#runner;
#renderQueue = [];
constructor(instance) {
this.instance = instance;
this.lastRenderedChunk = 0;
}
startContinuousRendering() {
this.#runner = system.runInterval(() => {
if (this.#renderQueue.length === 0)
this.prepareRenderQueue();
this.renderNextChunk();
}, RENDER_LIFETIME_FACTOR_TICKS);
}
stopContinuousRendering() {
if (!this.#runner)
return;
system.clearRun(this.#runner);
this.#runner = void 0;
this.#renderQueue = [];
}
refresh() {
this.stopContinuousRendering();
if (!this.instance.isEnabled() || !this.instance.options.verifier.isEnabled)
return;
this.startContinuousRendering();
}
prepareRenderQueue() {
this.#renderQueue = [];
const bounds = this.instance.getActiveBounds();
for (let y = bounds.min.y; y < bounds.max.y; y++) {
this.prepareRenderQueueLayer(bounds, y);
}
this.lastRenderedChunk = 0;
}
prepareRenderQueueLayer(bounds, y) {
if (bounds.max.x < bounds.max.z) {
for (let z = bounds.min.z; z < bounds.max.z; z++) {
for (let x = bounds.min.x; x < bounds.max.x; x++) {
this.#renderQueue.push({ x, y, z });
}
}
} else {
for (let x = bounds.min.x; x < bounds.max.x; x++) {
for (let z = bounds.min.z; z < bounds.max.z; z++) {
this.#renderQueue.push({ x, y, z });
}
}
}
}
renderNextChunk() {
if (this.shouldUseLargeStructureRendering())
this.renderNextChunkForLargeStructure();
else
this.renderNextChunkForSmallStructure();
}
renderNextChunkForLargeStructure() {
const bounds = this.instance.getActiveBounds();
const shortestSideLength = Math.min(bounds.max.x, bounds.max.z);
const maxChunk = (bounds.min.volume(bounds.max) / shortestSideLength) / (bounds.max.y - bounds.min.y);
const lifetime = (maxChunk * RENDER_LIFETIME_FACTOR_TICKS) / TicksPerSecond;
const verificationLevels = this.instance.verifier.getLastVerificationLevels();
const dimension = this.instance.getDimension();
const chunk = this.#renderQueue.splice(0, shortestSideLength);
for (const location of chunk) {
const verificationLevel = verificationLevels[JSON.stringify(location)];
if (!verificationLevel)
continue;
const dimensionLocation = {
dimension: dimension,
location: this.instance.toGlobalCoords(location)
};
new BlockVerificationLevelRender(dimensionLocation, verificationLevel, lifetime);
}
}
renderNextChunkForSmallStructure() {
const bounds = this.instance.getActiveBounds();
const lifetime = (bounds.max.x * (bounds.max.y - bounds.min.y) * bounds.max.z * RENDER_LIFETIME_FACTOR_TICKS) / TicksPerSecond;
const verificationLevels = this.instance.verifier.getLastVerificationLevels();
const dimension = this.instance.getDimension();
for (const location of this.#renderQueue.splice(0, 1)) {
const verificationLevel = verificationLevels[JSON.stringify(location)];
if (!verificationLevel)
continue;
const dimensionLocation = {
dimension: dimension,
location: this.instance.toGlobalCoords(location)
};
new BlockVerificationLevelRender(dimensionLocation, verificationLevel, lifetime);
}
}
shouldUseLargeStructureRendering() {
const bounds = this.instance.getActiveBounds();
const maxVolume = 343;
return this.instance.hasLayerSelected() || bounds.min.volume(bounds.max) > maxVolume;
}
}
@@ -1,118 +0,0 @@
import { InstanceExistsError } from '../Errors/InstanceExistsError';
import { InstanceNotFoundError } from '../Errors/InstanceNotFoundError';
import { StructureNotFoundError } from '../Errors/StructureNotFoundError';
import { InstanceOptions } from '../Instance/InstanceOptions';
import { StructureInstance } from '../Instance/StructureInstance';
import { InvalidStructureError, world } from '@minecraft/server';
class StructureCollection {
structures;
constructor() {
this.structures = {};
}
loadExistingInstances() {
world.getDynamicPropertyIds().filter(id => id.startsWith('instanceOptions:')).forEach(id => {
const instanceName = id.replace('instanceOptions:', '');
let structureId;
try {
structureId = InstanceOptions.getInstanceStructureId(instanceName);
this.structures[instanceName] = new StructureInstance(instanceName, structureId);
} catch (e) {
world.sendMessage(`§c[Construct] Error loading structure instance '${instanceName}'. It will be removed.`);
world.setDynamicProperty(id, void 0);
throw e;
}
});
}
add(instanceName, structureId) {
if (this.structures[instanceName])
throw new InstanceExistsError(instanceName);
const structure = new StructureInstance(instanceName, structureId);
this.structures[instanceName] = structure;
return structure;
}
get(instanceName) {
const structure = this.structures[instanceName];
if (!structure)
throw new InstanceNotFoundError(instanceName);
return structure;
}
has(instanceName) {
return Boolean(this.structures[instanceName]);
}
delete(instanceName) {
const struct = this.get(instanceName);
struct.delete();
delete this.structures[instanceName];
}
getInstanceNames() {
return Object.keys(this.structures);
}
getStructures(dimensionId, location, options = {}) {
return Object.values(this.structures).filter(structure => {
try {
return structure.isLocationActive(dimensionId, structure.toStructureCoords(location), options)
} catch (error) {
if (error instanceof StructureNotFoundError || error instanceof InvalidStructureError) {
this.delete(structure.name);
return false;
} else {
throw error;
}
}
});
}
getStructure(dimensionId, location, options = {}) {
return this.getStructures(dimensionId, location, options)[0];
}
fetchStructureBlock(dimensionId, location) {
const structure = this.getStructure(dimensionId, location);
if (!structure)
return void 0;
return structure.getBlock(structure.toStructureCoords(location));
}
getWorldStructureIds() {
const structureManager = world.structureManager;
const packIds = [...new Set(structureManager.getPackStructureIds()
.map(id => id.replace('mystructure:', '')))
];
const packIdSet = new Set(packIds);
let worldStructureIds = [];
try {
worldStructureIds = structureManager.getWorldStructureIds()
.filter(id => id.startsWith('mystructure:'))
.map(id => id.replace('mystructure:', ''))
.filter(id => !packIdSet.has(id));
} catch (error) {
console.warn('Failed to fetch world structure IDs. They will be ignored. Error:', error);
}
return [...packIds, ...worldStructureIds];
}
rename(instanceName, newName) {
const structure = this.get(instanceName);
if (this.structures[newName])
throw new InstanceExistsError(newName);
structure.rename(newName);
this.structures[newName] = structure;
delete this.structures[instanceName];
structure.name = newName;
}
}
export const structureCollection = new StructureCollection();
world.afterEvents.worldLoad.subscribe(() => {
structureCollection.loadExistingInstances();
});
@@ -1,68 +0,0 @@
import { BlockVerificationLevel } from '../Enums/BlockVerificationLevel.js';
export class StructureStatistics {
constructor(instance, verification) {
this.instance = instance;
this.verification = verification;
this.parse();
}
init() {
this.statistics = {};
for (const verificationLevel of Object.values(BlockVerificationLevel))
this.statistics[verificationLevel] = 0;
this.statistics.correctlyAir = 0;
}
parse() {
this.init();
for (const blockVerificationLevel of Object.values(BlockVerificationLevel))
this.parseStatistic(blockVerificationLevel);
}
parseStatistic(blockVerificationLevel) {
for (const [location, verificationLevel] of Object.entries(this.verification)) {
if (location === 'correctlyAir')
continue;
if (blockVerificationLevel === verificationLevel)
this.statistics[verificationLevel]++;
}
}
getNonAirBlocks() {
const activeBounds = this.instance.getActiveBounds();
return activeBounds.min.volume(activeBounds.max) - this.verification.correctlyAir;
}
getStat(blockVerificationLevel) {
return { num: this.statistics[blockVerificationLevel], percent: this.statistics[blockVerificationLevel] / (this.getNonAirBlocks()) * 100 };
}
getSkipped() {
return this.statistics[BlockVerificationLevel.Skipped] || 0;
}
getMessage() {
const message = { rawtext: [] };
message.rawtext.push({ translate: 'construct.structure.statistics.header', with: [this.instance.getName()] });
if (this.instance.hasLayerSelected())
message.rawtext.push({ translate: 'construct.instance.materials.layer', with: [String(this.instance.getLayer())] });
message.rawtext.push({ rawtext: [
{ text: '\n' },
{ translate: 'construct.structure.statistics.blocks', with: [String(this.getNonAirBlocks())] },
{ text: '\n' }
]});
const skipped = this.getSkipped();
if (skipped > 0)
message.rawtext.push({ rawtext: [{ translate: 'construct.structure.statistics.skipped', with: [String(skipped)] }, { text: '\n' }] });
message.rawtext.push({ rawtext: [{ translate: 'construct.structure.statistics.correct', with: [this.formatStat(this.getStat(BlockVerificationLevel.Match))] }, { text: '\n' }] });
message.rawtext.push({ rawtext: [{ translate: 'construct.structure.statistics.stateincorrect', with: [this.formatStat(this.getStat(BlockVerificationLevel.TypeMatch))] }, { text: '\n' }] });
message.rawtext.push({ rawtext: [{ translate: 'construct.structure.statistics.incorrect', with: [this.formatStat(this.getStat(BlockVerificationLevel.NoMatch))] }, { text: '\n' }] });
message.rawtext.push({ rawtext: [{ translate: 'construct.structure.statistics.missing', with: [this.formatStat(this.getStat(BlockVerificationLevel.Missing))] }, { text: '\n' }] });
return message;
}
formatStat(stat) {
return `${stat.num} (${stat.percent.toFixed(2)}%%)`;
}
}
@@ -1,43 +0,0 @@
import { BlockVerificationLevel } from "../Enums/BlockVerificationLevel";
export class BlockVerifier {
constructor(block, instance) {
this.block = block;
this.instance = instance;
this.blockLocationInStructure = instance.toStructureCoords(block.location);
}
verify() {
const structPermutation = this.instance.getBlock(this.blockLocationInStructure);
return this.evaluatePermutations(this.block.permutation, structPermutation);
}
evaluatePermutations(worldPermutation, structPermutation) {
if (this.isCorrectlyAir(worldPermutation, structPermutation))
return BlockVerificationLevel.Air;
if (this.isMissing(worldPermutation, structPermutation))
return BlockVerificationLevel.Missing;
if (this.isExactMatch(worldPermutation, structPermutation))
return BlockVerificationLevel.Match;
if (this.isTypeMatch(worldPermutation, structPermutation))
return BlockVerificationLevel.TypeMatch;
return BlockVerificationLevel.NoMatch;
}
isCorrectlyAir(worldPermutation, structPermutation) {
return worldPermutation.type.id === "minecraft:air" && structPermutation.type.id === "minecraft:air";
}
isMissing(worldPermutation, structPermutation) {
return worldPermutation.type.id === "minecraft:air" && structPermutation.type.id !== "minecraft:air";
}
isTypeMatch(worldPermuation, structurePermuation) {
return worldPermuation.type.id === structurePermuation.type.id;
}
isExactMatch(worldPermutation, structurePermutation) {
return worldPermutation.matches(structurePermutation.type.id, structurePermutation.getAllStates())
&& this.block.isWaterlogged === structurePermutation.isWaterlogged;
}
}
@@ -1,36 +0,0 @@
{
"format_version": "1.10.0",
"particle_effect": {
"description": {
"identifier": "construct:blockoverlay_xy",
"basic_render_parameters": {
"material": "particles_blend",
"texture": "textures/particle/white"
}
},
"components": {
"minecraft:emitter_rate_instant": {
"num_particles": 1
},
"minecraft:emitter_lifetime_once": {
"active_time": 1
},
"minecraft:emitter_shape_point": {},
"minecraft:particle_lifetime_expression": {
"max_lifetime": "variable.lifetime"
},
"minecraft:particle_appearance_billboard": {
"size": ["variable.width", "variable.height"],
"facing_camera_mode": "emitter_transform_xy"
},
"minecraft:particle_appearance_tinting": {
"color": [
"variable.face_color.r",
"variable.face_color.g",
"variable.face_color.b",
"variable.face_color.a"
]
}
}
}
}
@@ -1,36 +0,0 @@
{
"format_version": "1.10.0",
"particle_effect": {
"description": {
"identifier": "construct:blockoverlay_xz",
"basic_render_parameters": {
"material": "particles_blend",
"texture": "textures/particle/white"
}
},
"components": {
"minecraft:emitter_rate_instant": {
"num_particles": 1
},
"minecraft:emitter_lifetime_once": {
"active_time": 1
},
"minecraft:emitter_shape_point": {},
"minecraft:particle_lifetime_expression": {
"max_lifetime": "variable.lifetime"
},
"minecraft:particle_appearance_billboard": {
"size": ["variable.width", "variable.height"],
"facing_camera_mode": "emitter_transform_xz"
},
"minecraft:particle_appearance_tinting": {
"color": [
"variable.face_color.r",
"variable.face_color.g",
"variable.face_color.b",
"variable.face_color.a"
]
}
}
}
}
@@ -1,36 +0,0 @@
{
"format_version": "1.10.0",
"particle_effect": {
"description": {
"identifier": "construct:blockoverlay_yz",
"basic_render_parameters": {
"material": "particles_blend",
"texture": "textures/particle/white"
}
},
"components": {
"minecraft:emitter_rate_instant": {
"num_particles": 1
},
"minecraft:emitter_lifetime_once": {
"active_time": 1
},
"minecraft:emitter_shape_point": {},
"minecraft:particle_lifetime_expression": {
"max_lifetime": "variable.lifetime"
},
"minecraft:particle_appearance_billboard": {
"size": ["variable.width", "variable.height"],
"facing_camera_mode": "emitter_transform_yz"
},
"minecraft:particle_appearance_tinting": {
"color": [
"variable.face_color.r",
"variable.face_color.g",
"variable.face_color.b",
"variable.face_color.a"
]
}
}
}
}