From f3dcdb217f10ff4beaa2e1123f952ad85ea581f8 Mon Sep 17 00:00:00 2001 From: ForestOfLight Date: Tue, 15 Apr 2025 09:35:12 -0700 Subject: [PATCH 1/4] Add BP assets --- StrucTool [BP]/manifest.json | 6 +- StrucTool [BP]/scripts/classes/Outliner.js | 4 +- StrucTool [BP]/scripts/commands/struct.js | 115 ------------------ .../scripts/rules/showStructBlockInfo.js | 0 StrucTool [RP]/manifest.json | 31 +++++ .../particles/blockoverlay.particle.json | 31 +++++ .../particles/outline.particle.json | 37 ++++++ StrucTool [RP]/textures/particle/white.png | Bin 0 -> 83 bytes 8 files changed, 106 insertions(+), 118 deletions(-) delete mode 100644 StrucTool [BP]/scripts/commands/struct.js delete mode 100644 StrucTool [BP]/scripts/rules/showStructBlockInfo.js create mode 100644 StrucTool [RP]/manifest.json create mode 100644 StrucTool [RP]/particles/blockoverlay.particle.json create mode 100644 StrucTool [RP]/particles/outline.particle.json create mode 100644 StrucTool [RP]/textures/particle/white.png diff --git a/StrucTool [BP]/manifest.json b/StrucTool [BP]/manifest.json index 901fa1c..c0c3d71 100644 --- a/StrucTool [BP]/manifest.json +++ b/StrucTool [BP]/manifest.json @@ -1,7 +1,7 @@ { "format_version": 2, "header": { - "name": "StrucTool", + "name": "StrucTool [BP] v1.0.0", "description": "Survival building extension for §l§aCanopy§r by §aForestOfLight§r.", "uuid": "8c0c0153-d8b9-482a-889f-aef922b8fe58", "min_engine_version": [1, 21, 70], @@ -32,6 +32,10 @@ "module_name": "@minecraft/server-ui", "version": "2.0.0-beta" }, + { + "uuid": "375ec465-3dc1-429f-8b4c-a337889e1ed4", // StrucTool RP + "version": [1, 0, 0] + }, { "uuid": "bcf34368-ed0c-4cf7-938e-582cccf9950d", // Canopy RP "version": [1, 0, 3] diff --git a/StrucTool [BP]/scripts/classes/Outliner.js b/StrucTool [BP]/scripts/classes/Outliner.js index 08d8821..cb40faa 100644 --- a/StrucTool [BP]/scripts/classes/Outliner.js +++ b/StrucTool [BP]/scripts/classes/Outliner.js @@ -6,8 +6,8 @@ export class Outliner { dimension; min = new Vector(); max = new Vector(); - drawParticle = "minecraft:villager_happy"; - drawFrequency = 8; + drawParticle = "structool:outline"; + drawFrequency = 20; #drawParticles = []; #runner = null; diff --git a/StrucTool [BP]/scripts/commands/struct.js b/StrucTool [BP]/scripts/commands/struct.js deleted file mode 100644 index 320f4af..0000000 --- a/StrucTool [BP]/scripts/commands/struct.js +++ /dev/null @@ -1,115 +0,0 @@ -import { Command } from '../lib/canopy/CanopyExtension'; -import { extension } from '../config'; -import { structureCollection } from '../classes/StructureCollection'; -import { MaterialCounter } from '../classes/MaterialCounter'; - -const structCmd = new Command({ - name: 'struct', - description: { text: 'Manages current StrucTool structures.' }, - usage: 'struct [args...]', - callback: structCommand, - args: [ - { type: 'string', name: 'name' }, - { type: 'string', name: 'option' }, - { type: 'string|number', name: 'arg3' } - ] -}); -extension.addCommand(structCmd); - -function structCommand(sender, args) { - const { name, option, arg3 } = args; - switch (option) { - case 'add': - addStructure(sender, name); - break; - case 'remove': - removeStructure(sender, name); - break; - case 'place': - placeStructure(sender, name); - break; - case 'layer': - setLayer(sender, name, arg3); - break; - case 'info': - printInfo(sender, name); - break; - default: - structCmd.sendUsage(sender); - } -} - -function addStructure(sender, name) { - try { - structureCollection.add(name, name); - } catch (e) { - if (e.message.includes('already exists')) { - sender.sendMessage({ text: `§cStructure '${name}' already exists.` }); - return; - } else { - sender.sendMessage({ text: `§cFailed to add structure '${name}'.` }); - throw e; - } - } - sender.sendMessage({ text: `§7Added structure '${name}'` }); -} - -function removeStructure(sender, name) { - try { - structureCollection.remove(name); - } catch (e) { - sender.sendMessage({ text: `§cStructure '${name}' not found.` }); - return; - } - sender.sendMessage({ text: `Removed structure '${name}'` }); -} - -function placeStructure(sender, name) { - let structure; - try { - structure = structureCollection.get(name); - } catch (e) { - try { - structure = structureCollection.add(name, name); - } catch (e) { - if (e.message.includes('already exists')) { - sender.sendMessage({ text: `§cStructure '${name}' already exists.` }); - return; - } else if (e.message.includes('not found')) { - sender.sendMessage({ text: `§cStructure '${name}' not found.` }); - return; - } else { - sender.sendMessage({ text: `§cFailed to place structure '${name}'.` }); - throw e; - } - } - } - structure.place(sender.dimension.id, sender.location); - sender.sendMessage({ text: `§7Placed structure '${name}'.` }); -} - -function setLayer(sender, name, layer) { - let structure; - try { - structure = structureCollection.get(name); - } catch (e) { - sender.sendMessage({ text: `§cStructure '${name}' not found.` }); - return; - } - structure.setLayer(layer); - sender.sendMessage({ text: `§7Set layer of structure '${name}' to ${layer}.` }); -} - -function printInfo(sender, name) { - let structure; - try { - structure = structureCollection.get(name); - } catch (e) { - sender.sendMessage({ text: `§cStructure '${name}' not found.` }); - return; - } - const { dimensionId, location } = structure.getLocation(); - sender.sendMessage({ text: `§7Structure '${name}' at [${location.x} ${location.y} ${location.z}] in '${dimensionId}'` }); - sender.sendMessage({ text: `§7Current Layer: ${structure.getLayer()}` }); - sender.sendMessage({ text: `§7Materials: ${MaterialCounter.getPrintable(name)}` }); -} \ No newline at end of file diff --git a/StrucTool [BP]/scripts/rules/showStructBlockInfo.js b/StrucTool [BP]/scripts/rules/showStructBlockInfo.js deleted file mode 100644 index e69de29..0000000 diff --git a/StrucTool [RP]/manifest.json b/StrucTool [RP]/manifest.json new file mode 100644 index 0000000..6ab353c --- /dev/null +++ b/StrucTool [RP]/manifest.json @@ -0,0 +1,31 @@ +{ + "format_version": 2, + "header": { + "name": "StrucTool [RP] v1.0.0", + "description": "Survival building extension for §l§aCanopy§r by §aForestOfLight§r.", + "uuid": "375ec465-3dc1-429f-8b4c-a337889e1ed4", + "version": [1, 0, 0], + "min_engine_version": [1,17,0] + }, + "modules": [ + { + "type": "resources", + "uuid": "7f6b23df-a583-476b-b0e4-87457e65f7c0", + "version": [1, 0, 0] + } + ], + "dependencies": [ + { + "uuid": "8c0c0153-d8b9-482a-889f-aef922b8fe58", // StrucTool BP + "version": [1, 0, 0] + }, + { + "uuid": "7f6b23df-a583-476b-b0e4-87457e65f7c0", // Canopy BP + "version": [1, 3, 9] + } + ], + "metadata": { + "authors": [ "ForestOfLight" ], + "license": "MIT" + } + } \ No newline at end of file diff --git a/StrucTool [RP]/particles/blockoverlay.particle.json b/StrucTool [RP]/particles/blockoverlay.particle.json new file mode 100644 index 0000000..1694375 --- /dev/null +++ b/StrucTool [RP]/particles/blockoverlay.particle.json @@ -0,0 +1,31 @@ +{ + "format_version": "1.10.0", + "particle_effect": { + "description": { + "identifier": "structool:blockoverlay", + "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": 1 + }, + "minecraft:particle_appearance_billboard": { + "size": [0.5, 0.5], + "facing_camera_mode": "emitter_transform_xz" + }, + "minecraft:particle_appearance_tinting": { + "color": [1, 0, 0, 0.5] + } + } + } +} \ No newline at end of file diff --git a/StrucTool [RP]/particles/outline.particle.json b/StrucTool [RP]/particles/outline.particle.json new file mode 100644 index 0000000..cd22a71 --- /dev/null +++ b/StrucTool [RP]/particles/outline.particle.json @@ -0,0 +1,37 @@ +{ + "format_version": "1.10.0", + "particle_effect": { + "description": { + "identifier": "structool:outline", + "basic_render_parameters": { + "material": "particles_blend", + "texture": "textures/particle/particles" + } + }, + "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": 1 + }, + "minecraft:particle_appearance_billboard": { + "size": [0.2, 0.2], + "facing_camera_mode": "rotate_xyz", + "uv": { + "texture_width": 16, + "texture_height": 16, + "uv": [6, 11], + "uv_size": [1, 1] + } + }, + "minecraft:particle_appearance_tinting": { + "color": [0, 0.66667, 0, 1] + } + } + } +} \ No newline at end of file diff --git a/StrucTool [RP]/textures/particle/white.png b/StrucTool [RP]/textures/particle/white.png new file mode 100644 index 0000000000000000000000000000000000000000..9f34bbd46e054cedccb074d041ba826c5436defb GIT binary patch literal 83 zcmeAS@N?(olHy`uVBq!ia0vp^j3CUx1|;Q0k92}K#X;^)4C~IxyaaN1JzX3_B*K$_ d{Qv*Io`Lf>^IukH*Hb_V22WQ%mvv4FO#rl#6#)PM literal 0 HcmV?d00001 From 962154feec5b16fa5233ed60be9f55d76e980a5d Mon Sep 17 00:00:00 2001 From: ForestOfLight Date: Tue, 15 Apr 2025 09:46:15 -0700 Subject: [PATCH 2/4] here, try this runVerifier --- .../scripts/classes/StructureVerifier.js | 32 ++++++++++++++++--- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/StrucTool [BP]/scripts/classes/StructureVerifier.js b/StrucTool [BP]/scripts/classes/StructureVerifier.js index 10ad29a..f583d8c 100644 --- a/StrucTool [BP]/scripts/classes/StructureVerifier.js +++ b/StrucTool [BP]/scripts/classes/StructureVerifier.js @@ -17,21 +17,45 @@ export class StructureVerifier { async runVerifier() { return new Promise((resolve) => { - this.verifyBlocks(); - resolve(); + system.runJob(this.verifyBlocks); + const checker = system.runInterval(() => { + if (this.isComplete) { + system.clearRun(checker); + resolve(); + } + }, 1); }); } - - verifyBlocks() { + + *verifyBlocks() { for (const block of this.instance.getBlocks()) { const verificationLevel = this.verifyBlock(block.location); if (verificationLevel !== BlockVerificationLevel.isAir) this.blockVerificationLevels[JSON.stringify(block.location)] = verificationLevel; else this.statistics.correctlyAir++; + yield; } + 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.isAir) + // 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) From 1243cb7d8b10ce6fa61d4cb59404c715104b2bc1 Mon Sep 17 00:00:00 2001 From: ForestOfLight Date: Tue, 15 Apr 2025 11:57:52 -0700 Subject: [PATCH 3/4] VerificationRenderer --- .../scripts/classes/BlockVerificationLevel.js | 4 +- .../classes/BlockVerificationLevelRender.js | 59 +++++++++++++++++++ .../scripts/classes/BlockVerifier.js | 30 ++-------- .../classes/InstanceEditFormBuilder.js | 4 +- .../scripts/classes/StructureVerifier.js | 14 ++++- .../particles/blockoverlay_xy.particle.json | 31 ++++++++++ ...cle.json => blockoverlay_xz.particle.json} | 4 +- .../particles/blockoverlay_yz.particle.json | 31 ++++++++++ 8 files changed, 143 insertions(+), 34 deletions(-) create mode 100644 StrucTool [BP]/scripts/classes/BlockVerificationLevelRender.js create mode 100644 StrucTool [RP]/particles/blockoverlay_xy.particle.json rename StrucTool [RP]/particles/{blockoverlay.particle.json => blockoverlay_xz.particle.json} (89%) create mode 100644 StrucTool [RP]/particles/blockoverlay_yz.particle.json diff --git a/StrucTool [BP]/scripts/classes/BlockVerificationLevel.js b/StrucTool [BP]/scripts/classes/BlockVerificationLevel.js index cdc5a32..b5beb5a 100644 --- a/StrucTool [BP]/scripts/classes/BlockVerificationLevel.js +++ b/StrucTool [BP]/scripts/classes/BlockVerificationLevel.js @@ -2,7 +2,7 @@ export const BlockVerificationLevel = Object.freeze({ Unknown: 0, NoMatch: 1, TypeMatch: 2, - TypeAndStateMatch: 3, + Match: 3, Missing: 4, - isAir: 5 + Air: 5 }); \ No newline at end of file diff --git a/StrucTool [BP]/scripts/classes/BlockVerificationLevelRender.js b/StrucTool [BP]/scripts/classes/BlockVerificationLevelRender.js new file mode 100644 index 0000000..598150f --- /dev/null +++ b/StrucTool [BP]/scripts/classes/BlockVerificationLevelRender.js @@ -0,0 +1,59 @@ +import { MolangVariableMap } from "@minecraft/server"; +import { BlockVerificationLevel } from "./BlockVerificationLevel"; +import { Vector } from "../lib/Vector"; + +export class BlockVerificationLevelRender { + opacity = 0.5; + + constructor(dimension, globalLocation, verificationLevel) { + this.dimension = dimension; + this.location = new Vector(globalLocation.x, globalLocation.y, globalLocation.z); + this.verificationLevel = verificationLevel; + this.renderBlock(); + } + + renderBlock() { + for (const [key, value] of Object.entries(this.getParticleLocations())) { + this.dimension.spawnParticle(key, value, this.getRGBAMolang()); + } + } + + 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), + } + } + + getRGBAMolang() { + const rgb = this.verificationLevelToRGB(); + if (!rgb) return; + rgb.alpha = this.opacity; + return new MolangVariableMap().setColorRGBA("minecraft:particle_appearance_tinting", rgb); + } + + verificationLevelToRGB() { + switch (this.verificationLevel) { + case BlockVerificationLevel.NoMatch: + return [1, 0, 0]; + case BlockVerificationLevel.TypeMatch: + return [1, 1, 0]; + case BlockVerificationLevel.Match: + return [0, 1, 0]; + case BlockVerificationLevel.Missing: + return [0, 0, 1]; + default: + return void 0; + } + } +} \ No newline at end of file diff --git a/StrucTool [BP]/scripts/classes/BlockVerifier.js b/StrucTool [BP]/scripts/classes/BlockVerifier.js index 5ac24e9..2f2859c 100644 --- a/StrucTool [BP]/scripts/classes/BlockVerifier.js +++ b/StrucTool [BP]/scripts/classes/BlockVerifier.js @@ -14,14 +14,14 @@ export class BlockVerifier { evaluatePermutations(worldPermutation, structPermutation) { if (this.isCorrectlyAir(worldPermutation, structPermutation)) - return this.air(); + return BlockVerificationLevel.Air; if (this.isMissing(worldPermutation, structPermutation)) - return this.missing(); + return BlockVerificationLevel.Missing; if (this.isExactMatch(worldPermutation, structPermutation)) - return this.matchingPermutations(); + return BlockVerificationLevel.Match; if (this.isTypeMatch(worldPermutation, structPermutation)) - return this.matchingTypes(); - return this.matchingNone(); + return BlockVerificationLevel.TypeMatch; + return BlockVerificationLevel.NoMatch; } isCorrectlyAir(worldPermutation, structPermutation) { @@ -39,24 +39,4 @@ export class BlockVerifier { isExactMatch(worldPermuation, structurePermuation) { return worldPermuation.matches(structurePermuation.type.id, structurePermuation.getAllStates()); } - - air() { - return BlockVerificationLevel.isAir; - } - - missing() { - return BlockVerificationLevel.Missing; - } - - matchingPermutations() { - return BlockVerificationLevel.TypeAndStateMatch; - } - - matchingTypes() { - return BlockVerificationLevel.TypeMatch; - } - - matchingNone() { - return BlockVerificationLevel.NoMatch; - } } \ No newline at end of file diff --git a/StrucTool [BP]/scripts/classes/InstanceEditFormBuilder.js b/StrucTool [BP]/scripts/classes/InstanceEditFormBuilder.js index 3564309..b9463f9 100644 --- a/StrucTool [BP]/scripts/classes/InstanceEditFormBuilder.js +++ b/StrucTool [BP]/scripts/classes/InstanceEditFormBuilder.js @@ -37,11 +37,11 @@ export class InstanceEditFormBuilder { const buildStatisticsForm = new ActionFormData() .title(MenuFormBuilder.menuTitle) let message = ''; - const structureVerifier = new StructureVerifier(instance); + 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.TypeAndStateMatch)}\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`; diff --git a/StrucTool [BP]/scripts/classes/StructureVerifier.js b/StrucTool [BP]/scripts/classes/StructureVerifier.js index f583d8c..2642127 100644 --- a/StrucTool [BP]/scripts/classes/StructureVerifier.js +++ b/StrucTool [BP]/scripts/classes/StructureVerifier.js @@ -1,11 +1,17 @@ import { BlockVerifier } from "./BlockVerifier"; import { BlockVerificationLevel } from "./BlockVerificationLevel"; +import { BlockVerificationLevelRender } from "./BlockVerificationLevelRender"; export class StructureVerifier { - constructor(instance) { + shouldRender; + isComplete; + + constructor(instance, { shouldRender = false } = {}) { this.instance = instance; this.blockVerificationLevels = {}; this.statistics = {}; + this.shouldRender = shouldRender; + this.isComplete = false; this.initStatistics(); } @@ -30,10 +36,12 @@ export class StructureVerifier { *verifyBlocks() { for (const block of this.instance.getBlocks()) { const verificationLevel = this.verifyBlock(block.location); - if (verificationLevel !== BlockVerificationLevel.isAir) + if (verificationLevel !== BlockVerificationLevel.Air) 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; } this.isComplete = true; @@ -49,7 +57,7 @@ export class StructureVerifier { // verifyBlocks() { // for (const block of this.instance.getBlocks()) { // const verificationLevel = this.verifyBlock(block.location); - // if (verificationLevel !== BlockVerificationLevel.isAir) + // if (verificationLevel !== BlockVerificationLevel.Air) // this.blockVerificationLevels[JSON.stringify(block.location)] = verificationLevel; // else // this.statistics.correctlyAir++; diff --git a/StrucTool [RP]/particles/blockoverlay_xy.particle.json b/StrucTool [RP]/particles/blockoverlay_xy.particle.json new file mode 100644 index 0000000..1f625e3 --- /dev/null +++ b/StrucTool [RP]/particles/blockoverlay_xy.particle.json @@ -0,0 +1,31 @@ +{ + "format_version": "1.10.0", + "particle_effect": { + "description": { + "identifier": "structool: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": 1 + }, + "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] + } + } + } +} \ No newline at end of file diff --git a/StrucTool [RP]/particles/blockoverlay.particle.json b/StrucTool [RP]/particles/blockoverlay_xz.particle.json similarity index 89% rename from StrucTool [RP]/particles/blockoverlay.particle.json rename to StrucTool [RP]/particles/blockoverlay_xz.particle.json index 1694375..9bf3bbe 100644 --- a/StrucTool [RP]/particles/blockoverlay.particle.json +++ b/StrucTool [RP]/particles/blockoverlay_xz.particle.json @@ -2,7 +2,7 @@ "format_version": "1.10.0", "particle_effect": { "description": { - "identifier": "structool:blockoverlay", + "identifier": "structool:blockoverlay_xz", "basic_render_parameters": { "material": "particles_blend", "texture": "textures/particle/white" @@ -24,7 +24,7 @@ "facing_camera_mode": "emitter_transform_xz" }, "minecraft:particle_appearance_tinting": { - "color": [1, 0, 0, 0.5] + "color": [0, 0, 0, 0.5] } } } diff --git a/StrucTool [RP]/particles/blockoverlay_yz.particle.json b/StrucTool [RP]/particles/blockoverlay_yz.particle.json new file mode 100644 index 0000000..bd471e5 --- /dev/null +++ b/StrucTool [RP]/particles/blockoverlay_yz.particle.json @@ -0,0 +1,31 @@ +{ + "format_version": "1.10.0", + "particle_effect": { + "description": { + "identifier": "structool: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": 1 + }, + "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] + } + } + } +} \ No newline at end of file From 72e9b65d3859a8a6866509e3d021bfb56a26e90f Mon Sep 17 00:00:00 2001 From: ForestOfLight Date: Tue, 15 Apr 2025 19:29:43 -0700 Subject: [PATCH 4/4] 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" + ] } } }