From 72e9b65d3859a8a6866509e3d021bfb56a26e90f Mon Sep 17 00:00:00 2001 From: ForestOfLight Date: Tue, 15 Apr 2025 19:29:43 -0700 Subject: [PATCH] Verification with block rendering and all --- .../classes/BlockVerificationLevelRender.js | 64 +++++----- .../scripts/classes/BlockVerifier.js | 2 +- .../scripts/classes/InstanceEditForm.js | 10 +- .../classes/InstanceEditFormBuilder.js | 23 ++-- StrucTool [BP]/scripts/classes/Outliner.js | 42 +++++-- .../scripts/classes/StructureInstance.js | 31 ++++- .../scripts/classes/StructureOutliner.js | 1 - .../scripts/classes/StructureStatistics.js | 64 ++++++++++ .../scripts/classes/StructureVerifier.js | 112 ++++++++---------- .../{ => enums}/BlockVerificationLevel.js | 3 +- .../{ => enums}/InstanceEditOptions.js | 0 StrucTool [BP]/structures/xmas.mcstructure | Bin 0 -> 29231 bytes .../particles/blockoverlay_xy.particle.json | 9 +- .../particles/blockoverlay_xz.particle.json | 9 +- .../particles/blockoverlay_yz.particle.json | 9 +- .../particles/outline.particle.json | 9 +- 16 files changed, 251 insertions(+), 137 deletions(-) create mode 100644 StrucTool [BP]/scripts/classes/StructureStatistics.js rename StrucTool [BP]/scripts/classes/{ => enums}/BlockVerificationLevel.js (83%) rename StrucTool [BP]/scripts/classes/{ => enums}/InstanceEditOptions.js (100%) create mode 100644 StrucTool [BP]/structures/xmas.mcstructure diff --git a/StrucTool [BP]/scripts/classes/BlockVerificationLevelRender.js b/StrucTool [BP]/scripts/classes/BlockVerificationLevelRender.js index 598150f..33ed279 100644 --- a/StrucTool [BP]/scripts/classes/BlockVerificationLevelRender.js +++ b/StrucTool [BP]/scripts/classes/BlockVerificationLevelRender.js @@ -1,57 +1,67 @@ import { MolangVariableMap } from "@minecraft/server"; -import { BlockVerificationLevel } from "./BlockVerificationLevel"; +import { BlockVerificationLevel } from "./enums/BlockVerificationLevel"; import { Vector } from "../lib/Vector"; export class BlockVerificationLevelRender { - opacity = 0.5; + opacity = 0.2; + lifetime = 0; - constructor(dimension, globalLocation, verificationLevel) { - this.dimension = dimension; - this.location = new Vector(globalLocation.x, globalLocation.y, globalLocation.z); + constructor(dimensionLocation, verificationLevel, lifetime = 5) { + this.dimension = dimensionLocation.dimension; + this.location = new Vector(dimensionLocation.location.x, dimensionLocation.location.y, dimensionLocation.location.z); this.verificationLevel = verificationLevel; + this.lifetime = lifetime; this.renderBlock(); } renderBlock() { - for (const [key, value] of Object.entries(this.getParticleLocations())) { - this.dimension.spawnParticle(key, value, this.getRGBAMolang()); + for (const particleLocation of this.getParticleLocations()) { + const color = this.getRGBAMolang(); + if (!color) + return; + color.setFloat("lifetime", this.lifetime); + try { + this.dimension.spawnParticle(particleLocation.particleType, particleLocation.location, color); + } catch { + /* pass */ + } } } getParticleLocations() { - const bottomFace = new Vector(0, 0, 0); - const topFace = new Vector(0, 1, 0); - const leftFace = new Vector(0.5, 0.5, 0); - const rightFace = new Vector(-0.5, 0.5, 0); - const frontFace = new Vector(0, 0.5, 0.5); - const backFace = new Vector(0, 0.5, -0.5); - return { - "structool:blockerlay_xz": this.location.add(topFace), - "structool:blockerlay_xz": this.location.add(bottomFace), - "structool:blockerlay_yz": this.location.add(leftFace), - "structool:blockerlay_yz": this.location.add(rightFace), - "structool:blockerlay_xy": this.location.add(frontFace), - "structool:blockerlay_xy": this.location.add(backFace), - } + 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); + return [ + { particleType: "structool:blockoverlay_xz", location: this.location.add(topFace) }, + { particleType: "structool:blockoverlay_xz", location: this.location.add(bottomFace) }, + { particleType: "structool:blockoverlay_yz", location: this.location.add(leftFace) }, + { particleType: "structool:blockoverlay_yz", location: this.location.add(rightFace) }, + { particleType: "structool:blockoverlay_xy", location: this.location.add(frontFace) }, + { particleType: "structool:blockoverlay_xy", location: this.location.add(backFace) } + ]; } getRGBAMolang() { const rgb = this.verificationLevelToRGB(); if (!rgb) return; rgb.alpha = this.opacity; - return new MolangVariableMap().setColorRGBA("minecraft:particle_appearance_tinting", rgb); + const molang = new MolangVariableMap(); + molang.setColorRGBA("face_color", rgb); + return molang; } verificationLevelToRGB() { switch (this.verificationLevel) { case BlockVerificationLevel.NoMatch: - return [1, 0, 0]; + return { red: 1, green: 0, blue: 0}; case BlockVerificationLevel.TypeMatch: - return [1, 1, 0]; - case BlockVerificationLevel.Match: - return [0, 1, 0]; + return { red: 1, green: 1, blue: 0}; case BlockVerificationLevel.Missing: - return [0, 0, 1]; + return { red: 0, green: 0, blue: 1}; default: return void 0; } diff --git a/StrucTool [BP]/scripts/classes/BlockVerifier.js b/StrucTool [BP]/scripts/classes/BlockVerifier.js index 2f2859c..81b9a4e 100644 --- a/StrucTool [BP]/scripts/classes/BlockVerifier.js +++ b/StrucTool [BP]/scripts/classes/BlockVerifier.js @@ -1,4 +1,4 @@ -import { BlockVerificationLevel } from "./BlockVerificationLevel"; +import { BlockVerificationLevel } from "./enums/BlockVerificationLevel"; export class BlockVerifier { constructor(block, instance) { diff --git a/StrucTool [BP]/scripts/classes/InstanceEditForm.js b/StrucTool [BP]/scripts/classes/InstanceEditForm.js index 928a281..0a87d14 100644 --- a/StrucTool [BP]/scripts/classes/InstanceEditForm.js +++ b/StrucTool [BP]/scripts/classes/InstanceEditForm.js @@ -1,7 +1,8 @@ import { structureCollection } from './StructureCollection'; import { MenuForm } from '../classes/MenuForm'; -import { InstanceEditOptions } from './InstanceEditOptions'; +import { InstanceEditOptions } from './enums/InstanceEditOptions'; import { InstanceEditFormBuilder } from './InstanceEditFormBuilder'; +import { FormCancelationReason } from '@minecraft/server-ui'; export class InstanceEditForm { instanceName; @@ -135,7 +136,10 @@ export class InstanceEditForm { } async statisticsForm() { - const form = await InstanceEditFormBuilder.buildStatistics(this.instance) - form.show(this.player); + const statsForm = await InstanceEditFormBuilder.buildStatistics(this.instance) + statsForm.form.show(this.player).then((response) => { + if (response.canceled && response.cancelationReason === FormCancelationReason.UserBusy) + this.player.sendMessage(statsForm.stats); + }); } } \ No newline at end of file diff --git a/StrucTool [BP]/scripts/classes/InstanceEditFormBuilder.js b/StrucTool [BP]/scripts/classes/InstanceEditFormBuilder.js index b9463f9..c98d61a 100644 --- a/StrucTool [BP]/scripts/classes/InstanceEditFormBuilder.js +++ b/StrucTool [BP]/scripts/classes/InstanceEditFormBuilder.js @@ -1,7 +1,7 @@ import { ActionFormData, ModalFormData } from '@minecraft/server-ui'; import { MenuFormBuilder } from './MenuFormBuilder'; import { StructureVerifier } from './StructureVerifier'; -import { BlockVerificationLevel } from './BlockVerificationLevel'; +import { StructureStatistics } from './StructureStatistics'; export class InstanceEditFormBuilder { static buildInstance(instance, options) { @@ -36,20 +36,11 @@ export class InstanceEditFormBuilder { static async buildStatistics(instance) { const buildStatisticsForm = new ActionFormData() .title(MenuFormBuilder.menuTitle) - let message = ''; - const structureVerifier = new StructureVerifier(instance, { shouldRender: true }); - const statistics = await structureVerifier.verifyStructure(); - message += `§fStatistics for §a${instance.name}§f:\n`; - message += `§7Blocks: §2${instance.getTotalVolume() - statistics.correctlyAir}\n`; - message += `§7Correct: §a${this.getFormattedStatistic(statistics, BlockVerificationLevel.Match)}\n`; - message += `§7Block State Incorrect: §e${this.getFormattedStatistic(statistics, BlockVerificationLevel.TypeMatch)}\n`; - message += `§7Incorrect: §c${this.getFormattedStatistic(statistics, BlockVerificationLevel.NoMatch)}\n`; - message += `§7Missing: §c${this.getFormattedStatistic(statistics, BlockVerificationLevel.Missing)}\n`; - buildStatisticsForm.body(message); - return buildStatisticsForm; - } - - static getFormattedStatistic(statistics, blockVerificationLevel) { - return `${statistics[blockVerificationLevel]} (${statistics.percentages[blockVerificationLevel].toFixed(2)}%%)`; + const structureVerifier = new StructureVerifier(instance); + const verification = await structureVerifier.verifyStructure(); + const statistics = new StructureStatistics(instance, verification); + const statsMessage = statistics.getMessage(); + buildStatisticsForm.body(statsMessage); + return { form: buildStatisticsForm, stats: statsMessage }; } } \ No newline at end of file diff --git a/StrucTool [BP]/scripts/classes/Outliner.js b/StrucTool [BP]/scripts/classes/Outliner.js index cb40faa..817604a 100644 --- a/StrucTool [BP]/scripts/classes/Outliner.js +++ b/StrucTool [BP]/scripts/classes/Outliner.js @@ -1,23 +1,21 @@ -import { system, world } from "@minecraft/server"; +import { MolangVariableMap, system, world } from "@minecraft/server"; import { Vector } from "../lib/Vector"; - export class Outliner { dimension; min = new Vector(); max = new Vector(); drawParticle = "structool:outline"; - drawFrequency = 20; + drawFrequency = 10; #drawParticles = []; - #runner = null; + #runner = void 0; constructor(dimension, min, max) { this.dimension = dimension; this.min = new Vector(min.x, min.y, min.z); this.max = new Vector(max.x, max.y, max.z); this.vertices = this.getVertices(min, max); - this.startDraw(); } startDraw() { @@ -25,18 +23,28 @@ export class Outliner { } stopDraw() { + if (!this.#runner) + return; system.clearRun(this.#runner); + this.#runner = void 0; } draw() { - this.#drawParticles.length = 0; - this.#drawParticles.push(...this.getVerticeParticleLocations()); - this.#drawParticles.push(...this.getCubiodParticleLocations()); + 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()); try { - this.dimension.spawnParticle(particleType, location); - } catch { + this.dimension.spawnParticle(particleType, location, molang); + } catch (e) { /* pass */ } } @@ -62,11 +70,11 @@ export class Outliner { this.vertices = this.getVertices(min, max); } - getVerticeParticleLocations() { + getVerticeParticles() { return this.vertices.map((v) => [this.drawParticle, v]); } - getCubiodParticleLocations() { + getCubiodEdgeParticles() { const edges = [ [0, 1], [0, 2], @@ -97,4 +105,14 @@ export class Outliner { for (const location of locations) this.vertices.push(new Vector(location.x, location.y, location.z)); } + + getNextParticleColor() { + if (this.lastWasBlack) { + this.lastWasBlack = false; + return { red: 1, green: 1, blue: 0, alpha: 1 }; + } else { + this.lastWasBlack = true; + return { red: 0.15, green: 0.15, blue: 0.15, alpha: 1 }; + } + } } \ No newline at end of file diff --git a/StrucTool [BP]/scripts/classes/StructureInstance.js b/StrucTool [BP]/scripts/classes/StructureInstance.js index 82e3fc7..a507dae 100644 --- a/StrucTool [BP]/scripts/classes/StructureInstance.js +++ b/StrucTool [BP]/scripts/classes/StructureInstance.js @@ -1,6 +1,7 @@ import { world } from "@minecraft/server"; import { Outliner } from "./Outliner"; import { StructureOutliner } from "./StructureOutliner"; +import { StructureVerifier } from "./StructureVerifier"; export class StructureInstance { name; @@ -15,6 +16,7 @@ export class StructureInstance { currentLayer: 0 }; outliner = void 0; + verifier = void 0; constructor(instanceName, structureId) { this.name = instanceName; @@ -25,7 +27,7 @@ export class StructureInstance { this.#options = this.loadOptions(); this.#options.structureId = structureId; this.updateOptions(); - this.outliner = new StructureOutliner(this); + this.refreshBox(); } loadOptions() { @@ -102,6 +104,8 @@ export class StructureInstance { for (let x = 0; x < max.x; x++) { for (let z = 0; z < max.z; z++) { const blockPermutation = this.#structure.getBlockPermutation({ x, y, z }); + if (!blockPermutation) + yield void 0; blockPermutation.location = { x, y, z }; yield blockPermutation; } @@ -128,6 +132,14 @@ export class StructureInstance { 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; @@ -142,20 +154,20 @@ export class StructureInstance { enable() { this.#options.isEnabled = true; this.updateOptions(); - this.refreshOutliner(); + this.refreshBox(); } disable() { this.#options.isEnabled = false; this.updateOptions(); - this.refreshOutliner(); + 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.refreshOutliner(); + this.refreshBox(); } setLayer(layer) { @@ -163,11 +175,18 @@ export class StructureInstance { throw new Error(`[StrucTool] Layer ${layer} is out of bounds.`); this.#options.currentLayer = layer; this.updateOptions(); - this.refreshOutliner(); + this.refreshBox(); } - refreshOutliner() { + refreshBox() { + if (!this.hasLocation()) + return; + if (!this.outliner) + this.outliner = new StructureOutliner(this); + if (!this.verifier) + this.verifier = new StructureVerifier(this, { shouldRender: true }); this.outliner.refresh(); + this.verifier.refresh(); } isLocationInStructure(dimensionId, structureLocation) { diff --git a/StrucTool [BP]/scripts/classes/StructureOutliner.js b/StrucTool [BP]/scripts/classes/StructureOutliner.js index 2d7bda7..a11cbc6 100644 --- a/StrucTool [BP]/scripts/classes/StructureOutliner.js +++ b/StrucTool [BP]/scripts/classes/StructureOutliner.js @@ -5,7 +5,6 @@ export class StructureOutliner { this.instance = instance; this.pullInstanceData(); this.outliner = new Outliner(this.dimension, this.bounds.min, this.bounds.max); - this.refresh(); } pullInstanceData() { diff --git a/StrucTool [BP]/scripts/classes/StructureStatistics.js b/StrucTool [BP]/scripts/classes/StructureStatistics.js new file mode 100644 index 0000000..d1612d4 --- /dev/null +++ b/StrucTool [BP]/scripts/classes/StructureStatistics.js @@ -0,0 +1,64 @@ +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 verificationlevel of Object.values(this.verification)) { + if (blockVerificationLevel === verificationlevel) { + this.statistics[verificationlevel]++; + } + } + } + + getNonAirBlocks() { + return this.instance.getActiveVolume() - 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() { + let message = ''; + message += `§fStatistics for §a${this.instance.name}§f:`; + if (this.instance.isUsingLayers()) + message += ` §7(layer ${this.instance.getLayer()})`; + message += `\n§7Blocks: §2${this.getNonAirBlocks()}\n`; + const skipped = this.getSkipped(); + if (skipped > 0) + message += `§c[!] This analysis skipped ${skipped} blocks.\n`; + message += `§7Correct: §a${this.formatStat(this.getStat(BlockVerificationLevel.Match))}\n`; + message += `§7Block State Incorrect: §e${this.formatStat(this.getStat(BlockVerificationLevel.TypeMatch))}\n`; + message += `§7Incorrect: §c${this.formatStat(this.getStat(BlockVerificationLevel.NoMatch))}\n`; + message += `§7Missing: §3${this.formatStat(this.getStat(BlockVerificationLevel.Missing))}\n`; + return message; + } + + formatStat(stat) { + return `${stat.num} (${stat.percent.toFixed(2)}%%)`; + } +} \ No newline at end of file diff --git a/StrucTool [BP]/scripts/classes/StructureVerifier.js b/StrucTool [BP]/scripts/classes/StructureVerifier.js index 2642127..1d9d712 100644 --- a/StrucTool [BP]/scripts/classes/StructureVerifier.js +++ b/StrucTool [BP]/scripts/classes/StructureVerifier.js @@ -1,97 +1,85 @@ import { BlockVerifier } from "./BlockVerifier"; -import { BlockVerificationLevel } from "./BlockVerificationLevel"; +import { BlockVerificationLevel } from "./enums/BlockVerificationLevel"; import { BlockVerificationLevelRender } from "./BlockVerificationLevelRender"; +import { system, TicksPerSecond } from "@minecraft/server"; export class StructureVerifier { shouldRender; isComplete; + interval = 5*20; + #runner; constructor(instance, { shouldRender = false } = {}) { + this.shouldRender = shouldRender; this.instance = instance; - this.blockVerificationLevels = {}; - this.statistics = {}; + this.interval = Math.max(instance.getActiveVolume() / 50, 20); + } + + startContinuousVerification() { + this.#runner = system.runInterval(() => { + this.verifyStructure(); + }, this.interval); + } + + stopContinuousVerification() { + if (!this.#runner) + return; + system.clearRun(this.#runner); + this.#runner = void 0; + } + + refresh() { + this.stopContinuousVerification(); + if (!this.instance.isEnabled()) + return; + this.startContinuousVerification(); + } + + init(shouldRender) { + this.blockVerificationLevels = { correctlyAir: 0 }; this.shouldRender = shouldRender; this.isComplete = false; - this.initStatistics(); } async verifyStructure() { - await this.runVerifier(); - this.parseStatistics(); - return this.statistics; - } - - async runVerifier() { + this.init(this.shouldRender); return new Promise((resolve) => { - system.runJob(this.verifyBlocks); + if (this.instance.isUsingLayers()) + system.runJob(this.verifyBlocks(this.instance.getLayerBlocks(this.instance.getLayer()-1))); + else + system.runJob(this.verifyBlocks(this.instance.getBlocks())); const checker = system.runInterval(() => { if (this.isComplete) { system.clearRun(checker); - resolve(); + resolve(this.blockVerificationLevels); } }, 1); }); } - *verifyBlocks() { - for (const block of this.instance.getBlocks()) { + *verifyBlocks(blocks) { + for (const block of blocks) { const verificationLevel = this.verifyBlock(block.location); - if (verificationLevel !== BlockVerificationLevel.Air) + if (verificationLevel === BlockVerificationLevel.Air) { + this.blockVerificationLevels.correctlyAir++; + } else { this.blockVerificationLevels[JSON.stringify(block.location)] = verificationLevel; - else - this.statistics.correctlyAir++; - if (this.shouldRender) - new BlockVerificationLevelRender(this.instance.getDimension(), this.instance.toGlobalCoords(block.location), verificationLevel); - yield; + if (this.shouldRender) { + const dimensionLocation = { dimension: this.instance.getDimension(), location: this.instance.toGlobalCoords(block.location) }; + new BlockVerificationLevelRender(dimensionLocation, verificationLevel, this.interval/TicksPerSecond); + } + } + yield void 0; } this.isComplete = true; } - // async runVerifier() { - // return new Promise((resolve) => { - // this.verifyBlocks(); - // resolve(); - // }); - // } - - // verifyBlocks() { - // for (const block of this.instance.getBlocks()) { - // const verificationLevel = this.verifyBlock(block.location); - // if (verificationLevel !== BlockVerificationLevel.Air) - // this.blockVerificationLevels[JSON.stringify(block.location)] = verificationLevel; - // else - // this.statistics.correctlyAir++; - // } - // } - verifyBlock(location) { const worldBlock = this.instance.getDimension().getBlock(this.instance.toGlobalCoords(location)); - if (!worldBlock) - throw new Error(`Block at ${JSON.stringify(location)} could not be accessed.`); + if (!worldBlock) { + return BlockVerificationLevel.Skipped; + } const blockVerifier = new BlockVerifier(worldBlock, this.instance); return blockVerifier.verify(); } - - initStatistics() { - for (const verificationlevel of Object.values(BlockVerificationLevel)) { - this.statistics[verificationlevel] = 0; - } - this.statistics.percentages = {}; - this.statistics.correctlyAir = 0; - } - - parseStatistics() { - for (const blockVerificationLevel of Object.values(BlockVerificationLevel)) { - this.parseStatistic(blockVerificationLevel); - } - } - - parseStatistic(blockVerificationLevel) { - for (const verificationlevel of Object.values(this.blockVerificationLevels)) { - if (blockVerificationLevel === verificationlevel) { - this.statistics[verificationlevel]++; - } - } - this.statistics.percentages[blockVerificationLevel] = this.statistics[blockVerificationLevel] / (this.instance.getTotalVolume() - this.statistics.correctlyAir) * 100; - } } \ No newline at end of file diff --git a/StrucTool [BP]/scripts/classes/BlockVerificationLevel.js b/StrucTool [BP]/scripts/classes/enums/BlockVerificationLevel.js similarity index 83% rename from StrucTool [BP]/scripts/classes/BlockVerificationLevel.js rename to StrucTool [BP]/scripts/classes/enums/BlockVerificationLevel.js index b5beb5a..fad3307 100644 --- a/StrucTool [BP]/scripts/classes/BlockVerificationLevel.js +++ b/StrucTool [BP]/scripts/classes/enums/BlockVerificationLevel.js @@ -4,5 +4,6 @@ export const BlockVerificationLevel = Object.freeze({ TypeMatch: 2, Match: 3, Missing: 4, - Air: 5 + Air: 5, + Skipped: 6 }); \ No newline at end of file diff --git a/StrucTool [BP]/scripts/classes/InstanceEditOptions.js b/StrucTool [BP]/scripts/classes/enums/InstanceEditOptions.js similarity index 100% rename from StrucTool [BP]/scripts/classes/InstanceEditOptions.js rename to StrucTool [BP]/scripts/classes/enums/InstanceEditOptions.js diff --git a/StrucTool [BP]/structures/xmas.mcstructure b/StrucTool [BP]/structures/xmas.mcstructure new file mode 100644 index 0000000000000000000000000000000000000000..0c4dde892003f1e52577e5796d58016b617caae7 GIT binary patch literal 29231 zcmeHQ+j84B5QQQqmXz4JIM-gL4}Ix#`<6$~v@?B3o0;^TLyNG@F->Yn%C_=7{g{48 zKcIim?xD5R76XWoOt*Ck%)pDw?g4mqaj`9%6Qzdx>bNM+<2t&~WtA5BKq)oeQC0d; z4~JBKP5A-kSCl7XRn_HuTF*;8-cv_eF+GdYJV~dz8s8&@;UACaYe&KeP&PA0>qcY;IM$~~kUS^cnCFn_;F8y^_p|2kXI4vbu!g+ENP+@Dsv9$>k@1hOI*5(Z;6eSM) z2Ol7#ye=-f`Xmm=1tgC_#jTUXfnPbH{FEzOO4v)xEnz-sGw_eI13q3C2hXUV^Ey3= zhjorK!^Z~)q=&pNnRt9=th3pquW!6f#{RGCB0ko|3CD&_+TumxAwF=waGeVr7c7}8 zv(D`%p2xRqZ0aTZ#`7BVjwtc^hcx|e#s>OrZPHHSnd{%A#Eb{7vo!ThyuR0e-+1Qy zee1XvnAz9XM^9q==tD=Yf9Y=-53-%hu6~IJzhaHr&K*}QU`|N3{&jfQR(Joa^r2bq zwtLu%X5eQ&+)KMnz|Ctyif2vsGLLwg6?~v=_gZoT6*D6{H z9CM#hA2Qc1s{eYE=||gyd~|&6WSqdJ3!BdgGfp@Td?d#TbR{0Ie@GuJ#xv*dTi@1~+u-}!uwTvngne(ug{-rV zloAhq#eRZ)pewmzL)w{mecvbg#*=fu>t%UPNPnB;+E2hA#|TRorzT$C z>%VV2*K^#(cK8(;`+#dt;TY(Wi~$KutbfLayh&nA#$_zTP9L8?!CXUH&j9;S`qWmI zzB2n!M@E7kCzSEI1@ytE@P|!u8~2-a*fS0ln*^OcKhFj{nQ%|&BiYWgzOZdLwzh4a z!<;vK$uR(5Y?~Q_;{|g=85w;zgD^Hr{`{*;vK}O3NNj3u?>;y)fGy7s^EqYR)Hh=U z*df^&kiM{$WgM9Os3W_QYoCCBkj;MC&V4TI(0=<2G=IeNXGnp8z(8OiFc26B3NIYn$M~<(NR)d=Fw4FtKk!Msnaqkq9iT#w5GQY;hjLYJVZms?LI~G zCL{Y0ZzNItE~Th>lTu67==th3OV?ddy_jiwDN}r*9qfE2aA!r9R;N0NPRck>$>SZ) zdn#-_O)UPNWpRGC^0#B2Ux~5Ic}7(hAGMPm$uTJ8>U0`s(P^9=KTtn%>XHgNKMaMdycE;?D zxo}NME(VI|T9S#`#H_pSWD~OgvCYEAX-?vew)|!gIrB8kaL&Z(_y4P@J?@ zqlapiW?5WD@l{$4)Rkj!>4Eck5*?K(z0<9qg(x3v7EjNJ4;rGKqGLwVs-4j)#2r?0 zX-_Eikonpt88Ce<|iuI`OXUe@uR*d&KW_w;DVk|CVJ@;;upJ zRbAxz18tej)xX{hiDm56XvY?9&J+a!M16R`!%S8J$dHnLQn9~an^OM8k zYB1Vc9n?S3rRj+}U$iese0y~sS3_EPU(-M1q2aGu8h$=Lt~BlP)Vwd6KhP@|@xMyR zW&tkAW?|Uix=1#wX4v3w^~vVr>Ge1t4IApkIICvZto|43_~q&uXuB%2Br3|3_PFNl KkC;0Wu+?8Zf8gB! literal 0 HcmV?d00001 diff --git a/StrucTool [RP]/particles/blockoverlay_xy.particle.json b/StrucTool [RP]/particles/blockoverlay_xy.particle.json index 1f625e3..541e12a 100644 --- a/StrucTool [RP]/particles/blockoverlay_xy.particle.json +++ b/StrucTool [RP]/particles/blockoverlay_xy.particle.json @@ -17,14 +17,19 @@ }, "minecraft:emitter_shape_point": {}, "minecraft:particle_lifetime_expression": { - "max_lifetime": 1 + "max_lifetime": "variable.lifetime" }, "minecraft:particle_appearance_billboard": { "size": [0.5, 0.5], "facing_camera_mode": "emitter_transform_xy" }, "minecraft:particle_appearance_tinting": { - "color": [0, 0, 0, 0.5] + "color": [ + "variable.face_color.r", + "variable.face_color.g", + "variable.face_color.b", + "variable.face_color.a" + ] } } } diff --git a/StrucTool [RP]/particles/blockoverlay_xz.particle.json b/StrucTool [RP]/particles/blockoverlay_xz.particle.json index 9bf3bbe..4140060 100644 --- a/StrucTool [RP]/particles/blockoverlay_xz.particle.json +++ b/StrucTool [RP]/particles/blockoverlay_xz.particle.json @@ -17,14 +17,19 @@ }, "minecraft:emitter_shape_point": {}, "minecraft:particle_lifetime_expression": { - "max_lifetime": 1 + "max_lifetime": "variable.lifetime" }, "minecraft:particle_appearance_billboard": { "size": [0.5, 0.5], "facing_camera_mode": "emitter_transform_xz" }, "minecraft:particle_appearance_tinting": { - "color": [0, 0, 0, 0.5] + "color": [ + "variable.face_color.r", + "variable.face_color.g", + "variable.face_color.b", + "variable.face_color.a" + ] } } } diff --git a/StrucTool [RP]/particles/blockoverlay_yz.particle.json b/StrucTool [RP]/particles/blockoverlay_yz.particle.json index bd471e5..76b4ef5 100644 --- a/StrucTool [RP]/particles/blockoverlay_yz.particle.json +++ b/StrucTool [RP]/particles/blockoverlay_yz.particle.json @@ -17,14 +17,19 @@ }, "minecraft:emitter_shape_point": {}, "minecraft:particle_lifetime_expression": { - "max_lifetime": 1 + "max_lifetime": "variable.lifetime" }, "minecraft:particle_appearance_billboard": { "size": [0.5, 0.5], "facing_camera_mode": "emitter_transform_yz" }, "minecraft:particle_appearance_tinting": { - "color": [0, 0, 0, 0.5] + "color": [ + "variable.face_color.r", + "variable.face_color.g", + "variable.face_color.b", + "variable.face_color.a" + ] } } } diff --git a/StrucTool [RP]/particles/outline.particle.json b/StrucTool [RP]/particles/outline.particle.json index cd22a71..7fd6ad6 100644 --- a/StrucTool [RP]/particles/outline.particle.json +++ b/StrucTool [RP]/particles/outline.particle.json @@ -4,7 +4,7 @@ "description": { "identifier": "structool:outline", "basic_render_parameters": { - "material": "particles_blend", + "material": "particles_alpha", "texture": "textures/particle/particles" } }, @@ -30,7 +30,12 @@ } }, "minecraft:particle_appearance_tinting": { - "color": [0, 0.66667, 0, 1] + "color": [ + "variable.dot_color.r", + "variable.dot_color.g", + "variable.dot_color.b", + "variable.dot_color.a" + ] } } }