diff --git a/scripts/classes/BlockVerificationLevel.js b/scripts/classes/BlockVerificationLevel.js new file mode 100644 index 0000000..7e04270 --- /dev/null +++ b/scripts/classes/BlockVerificationLevel.js @@ -0,0 +1,7 @@ +export const BlockVerificationLevel = Object.freeze({ + Unknown: 0, + NoMatch: 1, + TypeMatch: 2, + TypeAndStateMatch: 3, + Missing: 4 +}); \ No newline at end of file diff --git a/scripts/classes/BlockVerifier.js b/scripts/classes/BlockVerifier.js new file mode 100644 index 0000000..9557c38 --- /dev/null +++ b/scripts/classes/BlockVerifier.js @@ -0,0 +1,56 @@ +import { BlockVerificationLevel } from "./BlockVerificationLevel"; + +export class BlockVerifier { + constructor(block, structure) { + this.block = block; + this.blockLocationInStructure = structure.toStructureCoords(block.location); + this.structure = structure; + } + + verify() { + const worldPermutation = this.block.permutation; + const structPermutation = this.structure.getBlock(this.blockLocationInStructure); + return this.evaluatePermutations(worldPermutation, structPermutation); + } + + evaluatePermutations(worldPermutation, structPermutation) { + if (this.isMissing(worldPermutation, structPermutation)) + return this.missing(); + if (this.isExactMatch(worldPermutation, structPermutation)) + return this.matchingPermutations(); + if (this.isTypeMatch(worldPermutation, structPermutation)) + return this.matchingTypes(); + return this.matchingNone(); + } + + 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(worldPermuation, structurePermuation) { + return worldPermuation.matches(structurePermuation.type.id, structurePermuation.getAllStates()); + } + + missing() { + return BlockVerificationLevel.Missing; + } + + matchingPermutations() { + console.warn(`Block ${this.block.typeId} matches structure block ${structPermutation.typeId}`); + return BlockVerificationLevel.TypeAndStateMatch; + } + + matchingTypes() { + console.warn(`Block ${this.block.typeId} matches structure block ${structPermutation.typeId}`); + return BlockVerificationLevel.TypeMatch; + } + + matchingNone() { + console.warn(`Block ${this.block.typeId} does not match structure block ${structPermutation.typeId}`); + return BlockVerificationLevel.NoMatch; + } +} \ No newline at end of file diff --git a/scripts/classes/StructureInstance.js b/scripts/classes/StructureInstance.js index 1b35582..41ba52b 100644 --- a/scripts/classes/StructureInstance.js +++ b/scripts/classes/StructureInstance.js @@ -75,6 +75,10 @@ export class StructureInstance { return this.#options.currentLayer || 0; } + getBlock(structureLocation) { + return this.#structure.getBlockPermutation(structureLocation); + } + *getBlocks() { const max = this.#structure.size; for (let x = 0; x < max.x; x++) { @@ -95,10 +99,6 @@ export class StructureInstance { } } - getBlock(structureLocation) { - return this.#structure.getBlockPermutation(structureLocation); - } - getBounds() { return { min: { x: 0, y: 0, z: 0 }, @@ -115,6 +115,10 @@ export class StructureInstance { }; } + getTotalVolume() { + return this.#structure.size.x * this.#structure.size.y * this.#structure.size.z; + } + rename(newName) { world.setDynamicProperty(`structOptions:${this.name}`, void 0); this.name = newName; @@ -241,4 +245,8 @@ export class StructureInstance { else this.setLayer(this.#options.currentLayer - 1); } + + getDimension() { + return world.getDimension(this.#options.dimensionId); + } } \ No newline at end of file diff --git a/scripts/classes/StructureVerifier.js b/scripts/classes/StructureVerifier.js new file mode 100644 index 0000000..38cb5c6 --- /dev/null +++ b/scripts/classes/StructureVerifier.js @@ -0,0 +1,53 @@ +import { BlockVerifier } from "./BlockVerifier"; +import { BlockVerificationLevel } from "./BlockVerificationLevel"; +import { system } from "@minecraft/server"; + +export class StructureVerifier { + constructor(stucture) { + this.structure = structure; + this.blockVerificationLevels = {}; + this.statistics = {}; + this.initStatistics(); + } + + verifyStructure() { + system.runJob(this.verifyBlocks()); + this.parseStatistics(); + } + + *verifyBlocks() { + for (const block of this.structure.getBlocks()) { + this.blockVerificationLevels[block.location] = this.verifyBlock(block.location); + yield; + } + } + + verifyBlock(location) { + const worldBlock = this.structure.getDimension().getBlock(location); + if (!worldBlock) + throw new Error(`Block at ${JSON.stringify(location)} could not be accessed.`); + const blockVerifier = new BlockVerifier(worldBlock, this.structure); + return blockVerifier.verify(); + } + + initStatistics() { + for (const verificationlevel of Object.keys(BlockVerificationLevel)) { + this.statistics[verificationlevel] = 0; + } + } + + parseStatistics() { + for (const blockVerificationLevel of Object.keys(this.statistics)) { + 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.structure.getTotalVolume() * 100; + } +} \ No newline at end of file