Material counter and cleanup

This commit is contained in:
ForestOfLight
2025-03-11 02:13:16 -07:00
Unverified
parent 67e3f6fecc
commit 830b54e55a
5 changed files with 211 additions and 30 deletions
+73
View File
@@ -0,0 +1,73 @@
import { structureCollection } from '../classes/StructureCollection';
class MaterialCounter {
static getAll(name) {
const structure = structureCollection.get(name);
const materials = {};
for (const block of structure.getBlocks()) {
const typeId = block?.getItemStack()?.typeId.replace('minecraft:', '');
if (!typeId) continue;
if (!materials[typeId]) {
materials[typeId] = 0;
}
materials[typeId]++;
}
return materials;
}
static getLayer(name, layer) {
const structure = structureCollection.get(name);
const materials = {};
for (const block of structure.getLayerBlocks(layer)) {
const typeId = block?.getItemStack()?.typeId.replace('minecraft:', '');
if (!typeId) continue;
if (!materials[typeId]) {
materials[typeId] = 0;
}
materials[typeId]++;
}
return materials;
}
static getPrintable(name) {
const structure = structureCollection.get(name);
const materials = {};
for (const block of structure.getBlocks()) {
const itemStack = block?.getItemStack();
const typeId = itemStack?.typeId.replace('minecraft:', '');
if (!typeId) continue;
if (!materials[typeId]) {
materials[typeId] = { count: 0, maxStack: itemStack.maxAmount };
}
materials[typeId].count++;
}
let message = [];
for (const blockType in materials) {
let count = materials[blockType].count;
let countStr = '';
const maxStack = materials[blockType].maxStack;
const fullShulker = 27 * maxStack;
if (count >= fullShulker) {
countStr = `${Math.floor(count / fullShulker)} sb`;
}
if (count > fullShulker) {
countStr += ' + ';
}
count %= fullShulker;
if (count >= maxStack) {
countStr += `${Math.floor(count / maxStack)} stack`;
}
if (count > maxStack) {
countStr += ' + ';
}
count %= maxStack;
if (count > 0) {
countStr += count;
}
message.push(` ${blockType}: ${countStr}`);
}
return message.sort().join('\n');
}
}
export { MaterialCounter };
+2 -1
View File
@@ -1,4 +1,4 @@
import { MolangVariableMap, system, world } from "@minecraft/server"; import { system, world } from "@minecraft/server";
import { Vector } from "../lib/Vector"; import { Vector } from "../lib/Vector";
const drawFrequency = 8; const drawFrequency = 8;
@@ -17,6 +17,7 @@ export class Outliner {
this.dimension = world.getDimension(dimension); this.dimension = world.getDimension(dimension);
this.min = new Vector(min.x, min.y, min.z); this.min = new Vector(min.x, min.y, min.z);
this.max = new Vector(max.x, max.y, max.z); this.max = new Vector(max.x, max.y, max.z);
this.startDraw();
} }
startDraw() { startDraw() {
+68 -9
View File
@@ -8,12 +8,16 @@ export class Structure {
dimensionId: MinecraftDimensionTypes.overworld, dimensionId: MinecraftDimensionTypes.overworld,
location: { x: 0, y: 0, z: 0 }, location: { x: 0, y: 0, z: 0 },
rotation: 0, rotation: 0,
mirror: false mirror: false,
currentLayer: 0
}; };
constructor(structureName) { constructor(structureName) {
this.name = structureName; this.name = structureName;
this.#structure = world.structureManager.get(structureName); this.#structure = world.structureManager.get(structureName);
if (!this.#structure) {
throw new Error(`[StrucTool] Structure '${structureName}' not found.`);
}
this.#options = this.loadOptions(); this.#options = this.loadOptions();
} }
@@ -30,15 +34,47 @@ export class Structure {
world.setDynamicProperty(`structOptions:${this.name}`, JSON.stringify(this.#options)); world.setDynamicProperty(`structOptions:${this.name}`, JSON.stringify(this.#options));
} }
getName() {
return this.name;
}
getStructure() { getStructure() {
return this.#structure; return this.#structure;
} }
getOutlineLimits() { getLocation() {
return this.#options.location;
}
getHeight() {
return this.#structure.size.y;
}
getLayer() {
return this.#options.currentLayer;
}
*getBlocks() {
const max = this.#structure.size;
for (let x = 0; x < max.x; x++) {
for (let y = 0; y < max.y; y++) {
for (let z = 0; z < max.z; z++) {
yield this.#structure.getBlockPermutation({ x, y, z });
}
}
}
}
*getLayerBlocks(y) {
const max = this.#structure.size;
for (let x = 0; x < max.x; x++) {
for (let z = 0; z < max.z; z++) {
yield this.#structure.getBlockPermutation({ x, y, z });
}
}
}
getBlock(location) {
return this.#structure.getBlockPermutation(location);
}
getBounds() {
if (!this.#options.isPlaced) if (!this.#options.isPlaced)
throw new Error(`[StrucTool] Structure '${this.name}' is not placed.`); throw new Error(`[StrucTool] Structure '${this.name}' is not placed.`);
return { return {
@@ -55,6 +91,22 @@ export class Structure {
} }
} }
getLayeredBounds(useUnder = false) {
if (!this.#options.isPlaced)
throw new Error(`[StrucTool] Structure '${this.name}' is not placed.`);
if (useUnder) {
return {
min: { x: this.#options.location.x, y: this.#options.location.y, z: this.#options.location.z },
max: { x: this.#options.location.x + this.#structure.size.x, y: this.#options.location.y + this.#options.currentLayer, z: this.#options.location.z + this.#structure.size.z }
}
} else {
return {
min: { x: this.#options.location.x, y: this.#options.location.y + this.#options.currentLayer - 1,z: this.#options.location.z },
max: { x: this.#options.location.x + this.#structure.size.x, y: this.#options.location.y + this.#options.currentLayer, z: this.#options.location.z + this.#structure.size.z }
}
}
}
place(dimensionId, location) { place(dimensionId, location) {
this.#options = { this.#options = {
isPlaced: true, isPlaced: true,
@@ -62,8 +114,7 @@ export class Structure {
location: { x: Math.floor(location.x), y: Math.floor(location.y), z: Math.floor(location.z) }, location: { x: Math.floor(location.x), y: Math.floor(location.y), z: Math.floor(location.z) },
}; };
this.updateOptions(); this.updateOptions();
this.outliner = new Outliner(dimensionId, this.getOutlineLimits().min, this.getOutlineLimits().max); this.outliner = new Outliner(dimensionId, this.getBounds().min, this.getBounds().max);
this.outliner.startDraw();
} }
remove() { remove() {
@@ -72,6 +123,14 @@ export class Structure {
this.#options.isPlaced = false; this.#options.isPlaced = false;
this.updateOptions(); this.updateOptions();
this.outliner.stopDraw(); this.outliner.stopDraw();
delete this.outliner; }
setLayer(layer) {
if (layer < 1 || layer > this.#structure.size.y)
throw new Error(`[StrucTool] Structure '${this.name}' does not have layer ${layer}.`);
this.#options.currentLayer = layer;
this.updateOptions();
this.outliner.stopDraw();
this.outliner = new Outliner(this.#options.dimensionId, this.getLayeredBounds().min, this.getLayeredBounds().max);
} }
} }
+3 -11
View File
@@ -1,4 +1,3 @@
import { world } from '@minecraft/server';
import { Structure } from './Structure'; import { Structure } from './Structure';
class StructureCollection { class StructureCollection {
@@ -9,8 +8,9 @@ class StructureCollection {
} }
add(name) { add(name) {
const struct = world.structureManager.get(name); const structure = new Structure(name);
this.#structures[name] = new Structure(name, struct); this.#structures[name] = structure;
return structure;
} }
get(name) { get(name) {
@@ -26,14 +26,6 @@ class StructureCollection {
struct.remove(); struct.remove();
delete this.#structures[name]; delete this.#structures[name];
} }
place(name, dimensionId, location) {
const struct = this.get(name);
if (!struct) {
throw new Error(`Structure ${name} not found.`);
}
struct.place(dimensionId, location);
}
} }
export const structureCollection = new StructureCollection(); export const structureCollection = new StructureCollection();
+64 -8
View File
@@ -1,6 +1,8 @@
import { Command } from '../lib/canopy/CanopyExtension'; import { Command } from '../lib/canopy/CanopyExtension';
import { extension } from '../config'; import { extension } from '../config';
import { structureCollection } from '../classes/StructureCollection'; import { structureCollection } from '../classes/StructureCollection';
import { system } from '@minecraft/server';
import { MaterialCounter } from '../classes/MaterialCounter';
const structCmd = new Command({ const structCmd = new Command({
name: 'struct', name: 'struct',
@@ -8,35 +10,89 @@ const structCmd = new Command({
usage: 'struct', usage: 'struct',
callback: structCommand, callback: structCommand,
args: [ args: [
{ type: 'string', name: 'name' },
{ type: 'string', name: 'option' }, { type: 'string', name: 'option' },
{ type: 'string', name: 'name' } { type: 'string|number', name: 'arg3' }
] ]
}); });
extension.addCommand(structCmd); extension.addCommand(structCmd);
function structCommand(sender, args) { function structCommand(sender, args) {
const { option, name, structure } = args; const { option, name, arg3 } = args;
switch (option) { switch (option) {
case 'add': case 'add':
addStructure(sender, name, structure); addStructure(sender, name);
break; break;
case 'remove': case 'remove':
removeStructure(sender, name); removeStructure(sender, name);
break; break;
case 'place': case 'place':
structureCollection.place(name, sender.dimension.id, sender.location); placeStructure(sender, name);
break;
case 'layer':
setLayer(sender, name, arg3);
break;
case 'info':
printInfo(sender, name);
break; break;
default: default:
structCmd.sendUsage(sender); structCmd.sendUsage(sender);
} }
} }
function addStructure(sender, name, filename) { function addStructure(sender, name) {
structureCollection.add(name, filename); structureCollection.add(name);
sender.sendMessage({ text: `Added structure '${name}'` }); sender.sendMessage({ text: `§7Added structure '${name}'` });
} }
function removeStructure(sender, name) { function removeStructure(sender, name) {
structureCollection.remove(name); try {
structureCollection.remove(name);
} catch (e) {
sender.sendMessage({ text: `§cStructure '${name}' not found.` });
return;
}
sender.sendMessage({ text: `Removed structure '${name}'` }); sender.sendMessage({ text: `Removed structure '${name}'` });
} }
function placeStructure(sender, name) {
let structure;
try {
structure = structureCollection.get(name);
} catch (e) {
try {
structure = structureCollection.add(name);
} catch (e) {
sender.sendMessage({ text: `§cStructure '${name}' not found.` });
return;
}
}
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 location = structure.getLocation();
sender.sendMessage({ text: `§7Structure '${name}' at [${location.x} ${location.y} ${location.z}]` });
sender.sendMessage({ text: `§7Current Layer: ${structure.getLayer()}` });
sender.sendMessage({ text: `§7Materials: ${MaterialCounter.getPrintable(name)}` });
}