Block verifier correct

This commit is contained in:
ForestOfLight
2025-04-15 02:23:21 -07:00
Unverified
parent 567abd0f5f
commit 296af63134
7 changed files with 85 additions and 34 deletions
+2 -1
View File
@@ -3,5 +3,6 @@ export const BlockVerificationLevel = Object.freeze({
NoMatch: 1, NoMatch: 1,
TypeMatch: 2, TypeMatch: 2,
TypeAndStateMatch: 3, TypeAndStateMatch: 3,
Missing: 4 Missing: 4,
isAir: 5
}); });
+15 -9
View File
@@ -1,19 +1,20 @@
import { BlockVerificationLevel } from "./BlockVerificationLevel"; import { BlockVerificationLevel } from "./BlockVerificationLevel";
export class BlockVerifier { export class BlockVerifier {
constructor(block, structure) { constructor(block, instance) {
this.block = block; this.block = block;
this.blockLocationInStructure = structure.toStructureCoords(block.location); this.instance = instance;
this.structure = structure; this.blockLocationInStructure = instance.toStructureCoords(block.location);
} }
verify() { verify() {
const worldPermutation = this.block.permutation; const structPermutation = this.instance.getBlock(this.blockLocationInStructure);
const structPermutation = this.structure.getBlock(this.blockLocationInStructure); return this.evaluatePermutations(this.block.permutation, structPermutation);
return this.evaluatePermutations(worldPermutation, structPermutation);
} }
evaluatePermutations(worldPermutation, structPermutation) { evaluatePermutations(worldPermutation, structPermutation) {
if (this.isCorrectlyAir(worldPermutation, structPermutation))
return this.air();
if (this.isMissing(worldPermutation, structPermutation)) if (this.isMissing(worldPermutation, structPermutation))
return this.missing(); return this.missing();
if (this.isExactMatch(worldPermutation, structPermutation)) if (this.isExactMatch(worldPermutation, structPermutation))
@@ -23,6 +24,10 @@ export class BlockVerifier {
return this.matchingNone(); return this.matchingNone();
} }
isCorrectlyAir(worldPermutation, structPermutation) {
return worldPermutation.type.id === "minecraft:air" && structPermutation.type.id === "minecraft:air";
}
isMissing(worldPermutation, structPermutation) { isMissing(worldPermutation, structPermutation) {
return worldPermutation.type.id === "minecraft:air" && structPermutation.type.id !== "minecraft:air"; return worldPermutation.type.id === "minecraft:air" && structPermutation.type.id !== "minecraft:air";
} }
@@ -35,22 +40,23 @@ export class BlockVerifier {
return worldPermuation.matches(structurePermuation.type.id, structurePermuation.getAllStates()); return worldPermuation.matches(structurePermuation.type.id, structurePermuation.getAllStates());
} }
air() {
return BlockVerificationLevel.isAir;
}
missing() { missing() {
return BlockVerificationLevel.Missing; return BlockVerificationLevel.Missing;
} }
matchingPermutations() { matchingPermutations() {
console.warn(`Block ${this.block.typeId} matches structure block ${structPermutation.typeId}`);
return BlockVerificationLevel.TypeAndStateMatch; return BlockVerificationLevel.TypeAndStateMatch;
} }
matchingTypes() { matchingTypes() {
console.warn(`Block ${this.block.typeId} matches structure block ${structPermutation.typeId}`);
return BlockVerificationLevel.TypeMatch; return BlockVerificationLevel.TypeMatch;
} }
matchingNone() { matchingNone() {
console.warn(`Block ${this.block.typeId} does not match structure block ${structPermutation.typeId}`);
return BlockVerificationLevel.NoMatch; return BlockVerificationLevel.NoMatch;
} }
} }
+13 -2
View File
@@ -11,6 +11,7 @@ export class InstanceEditForm {
InstanceEditOptions.PreviousLayer, InstanceEditOptions.PreviousLayer,
InstanceEditOptions.SetLayer, InstanceEditOptions.SetLayer,
InstanceEditOptions.Move, InstanceEditOptions.Move,
InstanceEditOptions.Statistics,
InstanceEditOptions.RenameInstance, InstanceEditOptions.RenameInstance,
InstanceEditOptions.DisableInstance, InstanceEditOptions.DisableInstance,
], ],
@@ -93,6 +94,9 @@ export class InstanceEditForm {
case InstanceEditOptions.Move: case InstanceEditOptions.Move:
this.instance.move(this.player.dimension.id, this.player.location); this.instance.move(this.player.dimension.id, this.player.location);
break; break;
case InstanceEditOptions.Statistics:
this.statisticsForm();
break;
case InstanceEditOptions.MainMenu: case InstanceEditOptions.MainMenu:
new MenuForm(this.player, { jumpToInstance: false }); new MenuForm(this.player, { jumpToInstance: false });
break; break;
@@ -104,7 +108,8 @@ export class InstanceEditForm {
renameInstanceForm() { renameInstanceForm() {
InstanceEditFormBuilder.buildRenameInstance(this.instanceName).show(this.player).then((response) => { InstanceEditFormBuilder.buildRenameInstance(this.instanceName).show(this.player).then((response) => {
if (response.canceled) return; if (response.canceled)
return;
const newName = response.formValues[0]; const newName = response.formValues[0];
if (newName === '') { if (newName === '') {
this.player.sendMessage('§cInstance name cannot be empty.'); this.player.sendMessage('§cInstance name cannot be empty.');
@@ -122,9 +127,15 @@ export class InstanceEditForm {
setLayerForm() { setLayerForm() {
InstanceEditFormBuilder.buildSetLayer(this.instance.getBounds().max.y, this.instance.getLayer()).show(this.player).then((response) => { InstanceEditFormBuilder.buildSetLayer(this.instance.getBounds().max.y, this.instance.getLayer()).show(this.player).then((response) => {
if (response.canceled) return; if (response.canceled)
return;
const selectedLayer = response.formValues[0]; const selectedLayer = response.formValues[0];
this.instance.setLayer(parseInt(selectedLayer)); this.instance.setLayer(parseInt(selectedLayer));
}); });
} }
async statisticsForm() {
const form = await InstanceEditFormBuilder.buildStatistics(this.instance)
form.show(this.player);
}
} }
@@ -1,5 +1,7 @@
import { ActionFormData, ModalFormData } from '@minecraft/server-ui'; import { ActionFormData, ModalFormData } from '@minecraft/server-ui';
import { MenuFormBuilder } from './MenuFormBuilder'; import { MenuFormBuilder } from './MenuFormBuilder';
import { StructureVerifier } from './StructureVerifier';
import { BlockVerificationLevel } from './BlockVerificationLevel';
export class InstanceEditFormBuilder { export class InstanceEditFormBuilder {
static buildInstance(instance, options) { static buildInstance(instance, options) {
@@ -30,4 +32,24 @@ export class InstanceEditFormBuilder {
.slider("Layer", 0, maxLayer, 1, currentLayer) .slider("Layer", 0, maxLayer, 1, currentLayer)
.submitButton('Set Layer'); .submitButton('Set Layer');
} }
static async buildStatistics(instance) {
const buildStatisticsForm = new ActionFormData()
.title(MenuFormBuilder.menuTitle)
let message = '';
const structureVerifier = new StructureVerifier(instance);
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 += `§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)}%%)`;
}
} }
+2 -1
View File
@@ -9,5 +9,6 @@ export const InstanceEditOptions = Object.freeze({
NextLayer: 'Increase Layer', NextLayer: 'Increase Layer',
PreviousLayer: 'Decrease Layer', PreviousLayer: 'Decrease Layer',
SetLayer: 'Set Layer', SetLayer: 'Set Layer',
Move: 'Move Here' Move: 'Move Here',
Statistics: 'Statistics',
}); });
+4 -6
View File
@@ -92,12 +92,8 @@ export class StructureInstance {
*getBlocks() { *getBlocks() {
const max = this.#structure.size; const max = this.#structure.size;
for (let x = 0; x < max.x; x++) {
for (let y = 0; y < max.y; y++) { for (let y = 0; y < max.y; y++) {
for (let z = 0; z < max.z; z++) { yield * this.getLayerBlocks(y);
yield this.#structure.getBlockPermutation({ x, y, z });
}
}
} }
} }
@@ -105,7 +101,9 @@ export class StructureInstance {
const max = this.#structure.size; const max = this.#structure.size;
for (let x = 0; x < max.x; x++) { for (let x = 0; x < max.x; x++) {
for (let z = 0; z < max.z; z++) { for (let z = 0; z < max.z; z++) {
yield this.#structure.getBlockPermutation({ x, y, z }); const blockPermutation = this.#structure.getBlockPermutation({ x, y, z });
blockPermutation.location = { x, y, z };
yield blockPermutation;
} }
} }
} }
+26 -14
View File
@@ -1,43 +1,55 @@
import { BlockVerifier } from "./BlockVerifier"; import { BlockVerifier } from "./BlockVerifier";
import { BlockVerificationLevel } from "./BlockVerificationLevel"; import { BlockVerificationLevel } from "./BlockVerificationLevel";
import { system } from "@minecraft/server";
export class StructureVerifier { export class StructureVerifier {
constructor(stucture) { constructor(instance) {
this.structure = structure; this.instance = instance;
this.blockVerificationLevels = {}; this.blockVerificationLevels = {};
this.statistics = {}; this.statistics = {};
this.initStatistics(); this.initStatistics();
} }
verifyStructure() { async verifyStructure() {
system.runJob(this.verifyBlocks()); await this.runVerifier();
this.parseStatistics(); this.parseStatistics();
return this.statistics;
} }
*verifyBlocks() { async runVerifier() {
for (const block of this.structure.getBlocks()) { return new Promise((resolve) => {
this.blockVerificationLevels[block.location] = this.verifyBlock(block.location); this.verifyBlocks();
yield; 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) { verifyBlock(location) {
const worldBlock = this.structure.getDimension().getBlock(location); const worldBlock = this.instance.getDimension().getBlock(this.instance.toGlobalCoords(location));
if (!worldBlock) if (!worldBlock)
throw new Error(`Block at ${JSON.stringify(location)} could not be accessed.`); throw new Error(`Block at ${JSON.stringify(location)} could not be accessed.`);
const blockVerifier = new BlockVerifier(worldBlock, this.structure); const blockVerifier = new BlockVerifier(worldBlock, this.instance);
return blockVerifier.verify(); return blockVerifier.verify();
} }
initStatistics() { initStatistics() {
for (const verificationlevel of Object.keys(BlockVerificationLevel)) { for (const verificationlevel of Object.values(BlockVerificationLevel)) {
this.statistics[verificationlevel] = 0; this.statistics[verificationlevel] = 0;
} }
this.statistics.percentages = {};
this.statistics.correctlyAir = 0;
} }
parseStatistics() { parseStatistics() {
for (const blockVerificationLevel of Object.keys(this.statistics)) { for (const blockVerificationLevel of Object.values(BlockVerificationLevel)) {
this.parseStatistic(blockVerificationLevel); this.parseStatistic(blockVerificationLevel);
} }
} }
@@ -48,6 +60,6 @@ export class StructureVerifier {
this.statistics[verificationlevel]++; this.statistics[verificationlevel]++;
} }
} }
this.statistics.percentages[blockVerificationLevel] = this.statistics[blockVerificationLevel] / this.structure.getTotalVolume() * 100; this.statistics.percentages[blockVerificationLevel] = this.statistics[blockVerificationLevel] / (this.instance.getTotalVolume() - this.statistics.correctlyAir) * 100;
} }
} }