Form complete but not error handled

This commit is contained in:
ForestOfLight
2025-04-13 01:11:23 -07:00
Unverified
parent 6ced22b57b
commit 373b3df853
11 changed files with 225 additions and 117 deletions
+4 -6
View File
@@ -30,13 +30,11 @@ Removes a structure.
## Roadmap ## Roadmap
- [ ] place structure using form **(in progress)** - [x] Form to manage structure
- [x] easyPlace rule - [x] easyPlace rule
- [x] Make a viewable material list - [ ] Automatic material gathering from inventories
- [ ] Make automatic material gathering from inventories - [ ] Structure movement & rotation
- [ ] structure movement & rotation - [ ] More litematica features!
- [ ] structuraMode & holoprintMode rules for ease of use
- [ ] more litematica features!
## Issues & Suggestions ## Issues & Suggestions
+12 -2
View File
@@ -2,6 +2,8 @@ import { system, world } from '@minecraft/server';
import { Raycaster } from '../classes/Raycaster'; import { Raycaster } from '../classes/Raycaster';
class BlockInfo { class BlockInfo {
static shownToLastTick = new Set();
static onTick() { static onTick() {
for (const player of world.getAllPlayers()) { for (const player of world.getAllPlayers()) {
if (!player) if (!player)
@@ -12,16 +14,24 @@ class BlockInfo {
static showStructureBlockInfo(player) { static showStructureBlockInfo(player) {
const block = Raycaster.getTargetedStructureBlock(player, { isFirst: true, collideWithWorldBlocks: true }); const block = Raycaster.getTargetedStructureBlock(player, { isFirst: true, collideWithWorldBlocks: true });
if (!block && this.shownToLastTick.has(player.id)) {
player.onScreenDisplay.setActionBar({ text: 'Structure:\n§7None' });
this.shownToLastTick.delete(player.id);
}
if (!block) if (!block)
return; return;
player.onScreenDisplay.setActionBar({ text: this.getFormattedBlockInfo(block.permutation) }); player.onScreenDisplay.setActionBar({ text: this.getFormattedBlockInfo(block.permutation) });
this.shownToLastTick.add(player.id);
} }
static getFormattedBlockInfo(block) { static getFormattedBlockInfo(block) {
const header = 'Structure:\n'
if (!block)
return header + '§7Unknown';
const states = block.getAllStates(); const states = block.getAllStates();
if (Object.keys(states).length === 0) if (Object.keys(states).length === 0)
return `Structure:\n§a${block.type.id}`; return header + `§a${block.type.id}`;
return `Structure:\n§a${block.type.id}\n§7${this.getFormattedStates(states)}`; return header + `§a${block.type.id}\n§7${this.getFormattedStates(states)}`;
} }
static getFormattedStates(states) { static getFormattedStates(states) {
+53 -35
View File
@@ -1,27 +1,28 @@
import { structureCollection } from './StructureCollection'; import { structureCollection } from './StructureCollection';
import { MenuForm } from '../classes/MenuForm'; import { MenuForm } from '../classes/MenuForm';
import { ActionFormData } from '@minecraft/server-ui';
import { InstanceEditOptions } from './InstanceEditOptions'; import { InstanceEditOptions } from './InstanceEditOptions';
import { InstanceEditFormBuilder } from './InstanceEditFormBuilder'; import { InstanceEditFormBuilder } from './InstanceEditFormBuilder';
export class InstanceEditForm { export class InstanceEditForm {
instanceName; instanceName;
options = { #buttons = {
isPlaced: [ isEnabled: [
InstanceEditOptions.NextLayer, InstanceEditOptions.NextLayer,
InstanceEditOptions.PreviousLayer, InstanceEditOptions.PreviousLayer,
InstanceEditOptions.SetLayer, InstanceEditOptions.SetLayer,
InstanceEditOptions.Move, InstanceEditOptions.Move,
InstanceEditOptions.Rotate, InstanceEditOptions.RenameInstance,
InstanceEditOptions.Mirror, InstanceEditOptions.DisableInstance,
InstanceEditOptions.RemovePlacement,
], ],
notPlaced: [ isNotEnabledAndIsNotPlaced: [
InstanceEditOptions.PlaceInstance InstanceEditOptions.PlaceInstance,
InstanceEditOptions.RenameInstance
],
isNotEnabledButIsPlaced: [
InstanceEditOptions.EnableInstance,
InstanceEditOptions.RenameInstance
], ],
common: [ common: [
InstanceEditOptions.MaterialsList,
InstanceEditOptions.RenameInstance,
InstanceEditOptions.DeleteInstance, InstanceEditOptions.DeleteInstance,
InstanceEditOptions.MainMenu InstanceEditOptions.MainMenu
] ]
@@ -35,57 +36,65 @@ export class InstanceEditForm {
} }
show() { show() {
const currentOptions = this.instance.isPlaced() ? this.options.isPlaced : this.options.notPlaced; const currentOptions = this.getActiveOptions();
InstanceEditFormBuilder.buildInstance(this.instanceName, currentOptions, this.options.common).show(this.player).then((response) => { InstanceEditFormBuilder.buildInstance(this.instance, currentOptions).show(this.player).then((response) => {
if (response.canceled) return; if (response.canceled) return;
let selectedOption; this.handleOption(currentOptions[response.selection]);
if (this.instance.isPlaced())
selectedOption = this.options.isPlaced[response.selection] || this.options.common[response.selection-this.options.isPlaced.length];
else
selectedOption = this.options.notPlaced[response.selection] || this.options.common[response.selection-this.options.notPlaced.length];
this.handleOption(selectedOption);
}); });
} }
getActiveOptions() {
let currentOptions = [];
if (this.instance.isEnabled())
currentOptions = this.#buttons.isEnabled;
else if (this.instance.hasLocation())
currentOptions = this.#buttons.isNotEnabledButIsPlaced;
else
currentOptions = this.#buttons.isNotEnabledAndIsNotPlaced;
currentOptions = currentOptions.concat(this.#buttons.common);
if (!this.instance.hasLayers())
currentOptions = currentOptions.filter(option =>
option !== InstanceEditOptions.SetLayer
&& option !== InstanceEditOptions.NextLayer
&& option !== InstanceEditOptions.PreviousLayer
);
return currentOptions;
}
handleOption(option) { handleOption(option) {
switch (option) { switch (option) {
case InstanceEditOptions.EnableInstance:
this.instance.enable();
break;
case InstanceEditOptions.DisableInstance:
this.instance.disable();
break;
case InstanceEditOptions.PlaceInstance: case InstanceEditOptions.PlaceInstance:
this.instance.place(this.player.dimension.id, this.player.location); this.instance.place(this.player.dimension.id, this.player.location);
break; break;
case InstanceEditOptions.RemovePlacement:
this.instance.removePlacement();
break;
case InstanceEditOptions.RenameInstance: case InstanceEditOptions.RenameInstance:
this.renameInstanceForm(); this.renameInstanceForm();
break; break;
case InstanceEditOptions.DeleteInstance: case InstanceEditOptions.DeleteInstance:
this.structureCollection.remove(this.instanceName); structureCollection.delete(this.instanceName);
break; break;
case InstanceEditOptions.NextLayer: case InstanceEditOptions.NextLayer:
this.instance.setLayer(this.instance.getLayer() + 1); this.instance.increaseLayer();
new InstanceEditForm(this.player, this.instanceName); new InstanceEditForm(this.player, this.instanceName);
break; break;
case InstanceEditOptions.PreviousLayer: case InstanceEditOptions.PreviousLayer:
this.instance.setLayer(this.instance.getLayer() - 1); this.instance.decreaseLayer();
new InstanceEditForm(this.player, this.instanceName); new InstanceEditForm(this.player, this.instanceName);
break; break;
case InstanceEditOptions.SetLayer: case InstanceEditOptions.SetLayer:
this.setLayerForm(); this.setLayerForm();
break; break;
case InstanceEditOptions.Rotate:
this.player.sendMessage('§cRotating not implemented yet.');
break;
case InstanceEditOptions.Mirror:
this.player.sendMessage('§cMirroring not implemented yet.');
break;
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.MaterialsList:
this.player.sendMessage('§cMaterial list not implemented yet.');
break;
case InstanceEditOptions.MainMenu: case InstanceEditOptions.MainMenu:
new MenuForm(this.player); new MenuForm(this.player, { jumpToInstance: false });
break; break;
default: default:
this.player.sendMessage(`§cUnknown option: ${option}`); this.player.sendMessage(`§cUnknown option: ${option}`);
@@ -94,7 +103,16 @@ export class InstanceEditForm {
} }
renameInstanceForm() { renameInstanceForm() {
InstanceEditFormBuilder.buildRenameInstance(this.instanceName).show(this.player).then((response) => {
if (response.canceled) return;
const newName = response.formValues[0];
if (newName === '') {
this.player.sendMessage('§cInstance name cannot be empty.');
return;
}
structureCollection.rename(this.instanceName, newName);
this.instanceName = newName;
});
} }
setLayerForm() { setLayerForm() {
+9 -8
View File
@@ -2,23 +2,24 @@ import { ActionFormData, ModalFormData } from '@minecraft/server-ui';
import { MenuFormBuilder } from './MenuFormBuilder'; import { MenuFormBuilder } from './MenuFormBuilder';
export class InstanceEditFormBuilder { export class InstanceEditFormBuilder {
static buildInstance(instanceName, currentOptions, commonOptions) { static buildInstance(instance, options) {
const location = instance.getLocation();
const form = new ActionFormData() const form = new ActionFormData()
.title(MenuFormBuilder.menuTitle) .title(MenuFormBuilder.menuTitle)
.body(`Instance: §2${instanceName}`) let body = `Instance: §2${instance.name}\n`;
currentOptions.forEach(option => { if (instance.hasLocation())
form.button(`${option}`); body += `§7(${location.location.x} ${location.location.y} ${location.location.z} in ${location.dimensionId})\n`;
}); form.body(body);
commonOptions.forEach(option => { options.forEach(option => {
form.button(`${option}`); form.button(`${option}`);
}); });
return form; return form;
} }
static buildRenameInstance() { static buildRenameInstance(currentName) {
return new ModalFormData() return new ModalFormData()
.title(MenuFormBuilder.menuTitle) .title(MenuFormBuilder.menuTitle)
.textField('Enter a new name for the instance:', 'example_instance') .textField('Enter a new name for the instance:', currentName)
.submitButton('Rename'); .submitButton('Rename');
} }
+6 -8
View File
@@ -1,15 +1,13 @@
export const InstanceEditOptions = Object.freeze({ export const InstanceEditOptions = Object.freeze({
Unknown: "unknown", Unknown: 'Unknown',
MainMenu: 'Back to Main Menu', MainMenu: '<<',
PlaceInstance: 'Place Instance', PlaceInstance: '§aPlace Instance',
RemovePlacement: 'Remove Placement', EnableInstance: '§aEnable Instance',
DisableInstance: '§cDisable Instance',
RenameInstance: 'Rename Instance', RenameInstance: 'Rename Instance',
DeleteInstance: '§cDelete Instance', DeleteInstance: '§cDelete Instance',
NextLayer: 'Increase Layer', NextLayer: 'Increase Layer',
PreviousLayer: 'Decrease Layer', PreviousLayer: 'Decrease Layer',
SetLayer: 'Set Layer', SetLayer: 'Set Layer',
Move: 'Move Here', Move: 'Move Here'
Rotate: 'Rotate',
Mirror: 'Mirror',
MaterialsList: 'Get Materials List',
}); });
+15 -9
View File
@@ -4,26 +4,32 @@ import { MenuFormBuilder } from './MenuFormBuilder';
import { InstanceEditForm } from './InstanceEditForm'; import { InstanceEditForm } from './InstanceEditForm';
export class MenuForm { export class MenuForm {
constructor(player) { constructor(player, { jumpToInstance = true } = {}) {
this.player = player; this.player = player;
this.show(); this.show(jumpToInstance);
} }
async show() { async show(jumpToInstance = true) {
let instanceName = this.getInstanceFromLocation(); let instanceName;
if (!instanceName) if (jumpToInstance) {
instanceName = await this.getInstanceNameFromForm(); instanceName = this.getInstanceNameAtLocation();
if (instanceName) {
new InstanceEditForm(this.player, instanceName);
return;
}
}
instanceName = await this.getInstanceNameFromForm();
if (!instanceName) if (!instanceName)
return; return;
new InstanceEditForm(this.player, instanceName); new InstanceEditForm(this.player, instanceName);
} }
getInstanceFromLocation() { getInstanceNameAtLocation() {
const locatedStructures = structureCollection.getStructuresAtLocation(this.player.location); const locatedStructures = structureCollection.getStructures(this.player.dimension.id, this.player.location, { useLayers: false });
if (locatedStructures.length === 0) if (locatedStructures.length === 0)
return void 0; return void 0;
const structure = locatedStructures[0]; const structure = locatedStructures[0];
return structure.instanceName; return structure.name;
} }
async getInstanceNameFromForm() { async getInstanceNameFromForm() {
+4 -3
View File
@@ -1,4 +1,5 @@
import { structureCollection } from "./StructureCollection"; import { structureCollection } from "./StructureCollection";
import { world } from "@minecraft/server";
export class Raycaster { export class Raycaster {
static STEP_SIZE = 0.2; static STEP_SIZE = 0.2;
@@ -9,12 +10,10 @@ export class Raycaster {
let location = startLocation; let location = startLocation;
let distance = 0; let distance = 0;
while (distance < maxDistance) { while (distance < maxDistance) {
const locatedStructures = structureCollection.getStructuresAtLocation(location); const locatedStructures = structureCollection.getStructures(dimension.id, location);
if (locatedStructures.length !== 0) { if (locatedStructures.length !== 0) {
const structure = locatedStructures[0]; const structure = locatedStructures[0];
const block = structure.getBlock(structure.toStructureCoords(location)); const block = structure.getBlock(structure.toStructureCoords(location));
if (collideWithWorldBlocks && !dimension.getBlock(location)?.isAir)
break;
if (block?.type.id !== 'minecraft:air') { if (block?.type.id !== 'minecraft:air') {
blocks.push({ blocks.push({
permutation: block, permutation: block,
@@ -23,6 +22,8 @@ export class Raycaster {
if (getFirst) if (getFirst)
break; break;
} }
if (collideWithWorldBlocks && !dimension.getBlock(location)?.isAir)
break;
} }
location = { location = {
x: location.x + (direction.x*this.STEP_SIZE), x: location.x + (direction.x*this.STEP_SIZE),
+26 -6
View File
@@ -8,6 +8,21 @@ class StructureCollection {
this.structures = {}; this.structures = {};
} }
loadExistingStructures() {
world.getDynamicPropertyIds().filter(id => id.startsWith('structOptions:')).forEach(id => {
const instanceName = id.replace('structOptions:', '');
let structureId;
try {
structureId = StructureInstance.parseOptions(instanceName).structureId;
this.structures[instanceName] = new StructureInstance(instanceName, structureId);
} catch (e) {
world.sendMessage(`§c[StrucTool] Error loading structure instance '${instanceName}'. It will be removed.`);
world.setDynamicProperty(id, void 0);
throw e;
}
});
}
add(instanceName, structureId) { add(instanceName, structureId) {
if (this.structures[instanceName]) if (this.structures[instanceName])
throw new Error(`Instance ${instanceName} already exists.`); throw new Error(`Instance ${instanceName} already exists.`);
@@ -24,9 +39,9 @@ class StructureCollection {
return structure; return structure;
} }
remove(instanceName) { delete(instanceName) {
const struct = this.get(instanceName); const struct = this.get(instanceName);
struct.removePlacement(); struct.delete();
delete this.structures[instanceName]; delete this.structures[instanceName];
} }
@@ -34,12 +49,12 @@ class StructureCollection {
return Object.keys(this.structures); return Object.keys(this.structures);
} }
getStructuresAtLocation(location) { getStructures(dimensionId, location, options = {}) {
return Object.values(this.structures).filter(structure => structure.isLocationActive(structure.toStructureCoords(location))); return Object.values(this.structures).filter(structure => structure.isLocationActive(dimensionId, structure.toStructureCoords(location), options));
} }
fetchStructureBlock(location) { fetchStructureBlock(dimensionId, location) {
const locatedStructures = this.getStructuresAtLocation(location); const locatedStructures = this.getStructures(dimensionId, location);
if (locatedStructures.length === 0) if (locatedStructures.length === 0)
return void 0; return void 0;
const structure = locatedStructures[0]; const structure = locatedStructures[0];
@@ -56,6 +71,7 @@ class StructureCollection {
const structure = this.get(instanceName); const structure = this.get(instanceName);
if (this.structures[newName]) if (this.structures[newName])
throw new Error(`Instance ${newName} already exists.`); throw new Error(`Instance ${newName} already exists.`);
structure.rename(newName);
this.structures[newName] = structure; this.structures[newName] = structure;
delete this.structures[instanceName]; delete this.structures[instanceName];
structure.name = newName; structure.name = newName;
@@ -63,3 +79,7 @@ class StructureCollection {
} }
export const structureCollection = new StructureCollection(); export const structureCollection = new StructureCollection();
world.afterEvents.worldLoad.subscribe(() => {
structureCollection.loadExistingStructures();
});
+89 -27
View File
@@ -2,10 +2,12 @@ import { world } from "@minecraft/server";
import { Outliner } from "./Outliner"; import { Outliner } from "./Outliner";
export class StructureInstance { export class StructureInstance {
name;
#structure; #structure;
#options = { #options = {
isPlaced: false, structureId: void 0,
dimensionId: 'minecraft:overworld', isEnabled: false,
dimensionId: void 0,
worldLocation: { x: 0, y: 0, z: 0 }, worldLocation: { x: 0, y: 0, z: 0 },
rotation: 0, rotation: 0,
mirror: false, mirror: false,
@@ -14,13 +16,14 @@ export class StructureInstance {
constructor(instanceName, structureId) { constructor(instanceName, structureId) {
this.name = instanceName; this.name = instanceName;
this.structureId = structureId;
this.#structure = world.structureManager.get(structureId); this.#structure = world.structureManager.get(structureId);
if (!this.#structure) { if (!this.#structure)
throw new Error(`[StrucTool] Structure '${this.structureId}' not found.`); throw new Error(`[StrucTool] Structure '${structureId}' not found.`);
}
this.#options = this.loadOptions(); this.#options = this.loadOptions();
this.#options.isPlaced = false; this.#options.structureId = structureId;
if (this.#options.isEnabled)
this.refreshOutliner();
this.updateOptions();
} }
loadOptions() { loadOptions() {
@@ -32,6 +35,21 @@ export class StructureInstance {
return this.#options; return this.#options;
} }
delete() {
this.disable();
world.setDynamicProperty(`structOptions:${this.name}`, void 0);
this.#structure = void 0;
this.#options = void 0;
delete this.outliner;
}
static parseOptions(instanceName) {
const options = JSON.parse(world.getDynamicProperty(`structOptions:${instanceName}`));
if (!options)
throw new Error(`[StrucTool] Instance '${instanceName}' not found.`);
return options;
}
updateOptions() { updateOptions() {
world.setDynamicProperty(`structOptions:${this.name}`, JSON.stringify(this.#options)); world.setDynamicProperty(`structOptions:${this.name}`, JSON.stringify(this.#options));
} }
@@ -84,7 +102,7 @@ export class StructureInstance {
} }
getLayeredBounds() { getLayeredBounds() {
if (!this.#options.isPlaced) if (!this.#options.isEnabled)
throw new Error(`[StrucTool] Instance '${this.name}' is not placed.`); throw new Error(`[StrucTool] Instance '${this.name}' is not placed.`);
return { return {
min: { x: 0, y: this.#options.currentLayer - 1, z: 0 }, min: { x: 0, y: this.#options.currentLayer - 1, z: 0 },
@@ -92,22 +110,30 @@ export class StructureInstance {
}; };
} }
place(dimensionId, worldLocation) { rename(newName) {
this.#options.isPlaced = true; world.setDynamicProperty(`structOptions:${this.name}`, void 0);
this.move(dimensionId, worldLocation); this.name = newName;
world.setDynamicProperty(`structOptions:${this.name}`, JSON.stringify(this.#options));
} }
removePlacement() { place(dimensionId, worldLocation) {
if (!this.#options.isPlaced) this.move(dimensionId, worldLocation);
throw new Error(`[StrucTool] Instance '${this.name}' is not placed.`); this.enable();
this.#options.isPlaced = false; }
enable() {
this.#options.isEnabled = true;
this.updateOptions();
this.refreshOutliner();
}
disable() {
this.#options.isEnabled = false;
this.updateOptions(); this.updateOptions();
this.outliner.stopDraw(); this.outliner.stopDraw();
} }
move(dimensionId, location) { move(dimensionId, location) {
if (!this.#options.isPlaced)
throw new Error(`[StrucTool] Instance '${this.name}' is not placed.`);
this.#options.dimensionId = dimensionId; this.#options.dimensionId = dimensionId;
this.#options.worldLocation = { x: Math.floor(location.x), y: Math.floor(location.y), z: Math.floor(location.z) }; this.#options.worldLocation = { x: Math.floor(location.x), y: Math.floor(location.y), z: Math.floor(location.z) };
this.updateOptions(); this.updateOptions();
@@ -116,13 +142,15 @@ export class StructureInstance {
setLayer(layer) { setLayer(layer) {
if (layer < 0 || layer > this.#structure.size.y) if (layer < 0 || layer > this.#structure.size.y)
throw new Error(`[StrucTool] Instance '${this.name}' of '${this.structureId}' does not have layer ${layer}.`); throw new Error(`[StrucTool] Layer ${layer} is out of bounds.`);
this.#options.currentLayer = layer; this.#options.currentLayer = layer;
this.updateOptions(); this.updateOptions();
this.refreshOutliner(); this.refreshOutliner();
} }
refreshOutliner() { refreshOutliner() {
if (!this.#options.isEnabled)
return;
if (this.outliner) if (this.outliner)
this.outliner.stopDraw(); this.outliner.stopDraw();
if (this.#options.currentLayer > 0) { if (this.#options.currentLayer > 0) {
@@ -133,26 +161,30 @@ export class StructureInstance {
} }
} }
isLocationInStructure(structureLocation) { isLocationInStructure(dimensionId, structureLocation) {
if (this.#options.dimensionId !== dimensionId)
return false
const { min, max } = this.getBounds(); const { min, max } = this.getBounds();
return structureLocation.x >= min.x && structureLocation.x < max.x return structureLocation.x >= min.x && structureLocation.x < max.x
&& structureLocation.y >= min.y && structureLocation.y < max.y && structureLocation.y >= min.y && structureLocation.y < max.y
&& structureLocation.z >= min.z && structureLocation.z < max.z; && structureLocation.z >= min.z && structureLocation.z < max.z;
} }
isLocationInLayer(structureLocation) { isLocationInLayer(dimensionId, structureLocation) {
if (!this.#options.isEnabled || this.#options.dimensionId !== dimensionId)
return false
const { min, max } = this.getLayeredBounds(true); const { min, max } = this.getLayeredBounds(true);
return structureLocation.x >= min.x && structureLocation.x < max.x return structureLocation.x >= min.x && structureLocation.x < max.x
&& structureLocation.y >= min.y && structureLocation.y < max.y && structureLocation.y >= min.y && structureLocation.y < max.y
&& structureLocation.z >= min.z && structureLocation.z < max.z; && structureLocation.z >= min.z && structureLocation.z < max.z;
} }
isLocationActive(structureLocation) { isLocationActive(dimensionId, structureLocation, { useLayers = true } = {}) {
if (!this.#options.isPlaced) if (!this.#options.isEnabled || this.#options.dimensionId !== dimensionId)
return false return false
if (this.#options.currentLayer > 0) if (useLayers && this.#options.currentLayer !== 0)
return this.isLocationInLayer(structureLocation); return this.isLocationInLayer(dimensionId, structureLocation);
return this.isLocationInStructure(structureLocation); return this.isLocationInStructure(dimensionId, structureLocation);
} }
toGlobalCoords(structureLocation) { toGlobalCoords(structureLocation) {
@@ -171,7 +203,37 @@ export class StructureInstance {
}; };
} }
isPlaced() { isEnabled() {
return this.#options.isPlaced; return this.#options.isEnabled;
}
hasLocation() {
return this.#options.dimensionId && this.#options.worldLocation.x !== 0 && this.#options.worldLocation.y !== 0 && this.#options.worldLocation.z !== 0;
}
hasLayers() {
return this.#structure.size.y > 1;
}
isAtMaxLayer() {
return !this.hasLayers || this.#options.currentLayer >= this.#structure.size.y;
}
isAtMinLayer() {
return !this.hasLayers || this.#options.currentLayer <= 0;
}
increaseLayer() {
if (this.isAtMaxLayer())
this.setLayer(0);
else
this.setLayer(this.#options.currentLayer + 1);
}
decreaseLayer() {
if (this.isAtMinLayer())
this.setLayer(this.#structure.size.y);
else
this.setLayer(this.#options.currentLayer - 1);
} }
} }
+1 -9
View File
@@ -18,7 +18,7 @@ extension.addRule(easyPlace);
function onPlayerPlaceBlock(event) { function onPlayerPlaceBlock(event) {
const { player, block } = event; const { player, block } = event;
if (!player || !block || !hasActionItemInCorrectSlot(player)) return; if (!player || !block || !hasActionItemInCorrectSlot(player)) return;
const structureBlock = fetchStructureBlock(block.location); const structureBlock = structureCollection.fetchStructureBlock(block.dimension.id, block.location);
if (!structureBlock) if (!structureBlock)
return; return;
tryPlaceBlock(event, player, block, structureBlock); tryPlaceBlock(event, player, block, structureBlock);
@@ -32,14 +32,6 @@ function hasActionItemInCorrectSlot(player) {
return actionSlot.hasItem() && actionSlot.typeId === 'minecraft:paper' && actionSlot.nameTag === 'easyPlace'; return actionSlot.hasItem() && actionSlot.typeId === 'minecraft:paper' && actionSlot.nameTag === 'easyPlace';
} }
function fetchStructureBlock(location) {
const locatedStructures = structureCollection.getStructuresAtLocation(location);
if (locatedStructures.length === 0)
return void 0;
const structure = locatedStructures[0];
return structure.getBlock(structure.toStructureCoords(location));
}
function tryPlaceBlock(event, player, block, structureBlock) { function tryPlaceBlock(event, player, block, structureBlock) {
if (isBannedBlock(player, structureBlock)) return; if (isBannedBlock(player, structureBlock)) return;
structureBlock = tryConvertBannedToValidBlock(structureBlock); structureBlock = tryConvertBannedToValidBlock(structureBlock);
+5 -3
View File
@@ -8,7 +8,7 @@ import { Raycaster } from '../classes/Raycaster';
let runner = void 0; let runner = void 0;
const easyPlace = new Rule({ const easyPlace = new Rule({
identifier: 'fastEasyPlace', identifier: 'fastEasyPlace',
description: { text: "Looking at structure blocks with paper named 'easyPlace' in your hand will place them." }, description: { text: "Looking at structure blocks with a paper named 'easyPlace' in your hand will place them." },
onEnableCallback: () => { runner = system.runInterval(onTick, 2); }, onEnableCallback: () => { runner = system.runInterval(onTick, 2); },
onDisableCallback: () => { system.clearRun(runner); } onDisableCallback: () => { system.clearRun(runner); }
}) })
@@ -39,7 +39,7 @@ function isHoldingActionItem(player) {
} }
function tryPlaceBlock(player, worldBlock, structureBlock) { function tryPlaceBlock(player, worldBlock, structureBlock) {
if (isBannedBlock(player, structureBlock) || !locationIsPlaceable(worldBlock)) return; if (isBannedBlock(player, structureBlock) || !locationIsPlaceable(player, worldBlock)) return;
structureBlock = tryConvertBannedToValidBlock(structureBlock); structureBlock = tryConvertBannedToValidBlock(structureBlock);
if (player.getGameMode() === GameMode.creative) { if (player.getGameMode() === GameMode.creative) {
placeBlock(worldBlock, structureBlock); placeBlock(worldBlock, structureBlock);
@@ -49,11 +49,13 @@ function tryPlaceBlock(player, worldBlock, structureBlock) {
} }
} }
function locationIsPlaceable(worldBlock) { function locationIsPlaceable(player, worldBlock) {
return worldBlock.isAir; return worldBlock.isAir;
} }
function isBannedBlock(player, structureBlock) { function isBannedBlock(player, structureBlock) {
if (!structureBlock)
return true;
const blockId = structureBlock.type.id.replace('minecraft:', ''); const blockId = structureBlock.type.id.replace('minecraft:', '');
if (bannedBlocks.includes(blockId)) if (bannedBlocks.includes(blockId))
return true; return true;