form start
This commit is contained in:
@@ -0,0 +1,116 @@
|
||||
import { structureCollection } from './StructureCollection';
|
||||
import { MenuForm } from '../classes/MenuForm';
|
||||
import { ActionFormData } from '@minecraft/server-ui';
|
||||
import { InstanceEditOptions } from './InstanceEditOptions';
|
||||
|
||||
export class InstanceEditForm {
|
||||
instanceName;
|
||||
options = {
|
||||
isPlaced: [
|
||||
InstanceEditOptions.NextLayer,
|
||||
InstanceEditOptions.PreviousLayer,
|
||||
InstanceEditOptions.SetLayer,
|
||||
InstanceEditOptions.Move,
|
||||
InstanceEditOptions.Rotate,
|
||||
InstanceEditOptions.Mirror,
|
||||
InstanceEditOptions.RemovePlacement,
|
||||
],
|
||||
notPlaced: [
|
||||
InstanceEditOptions.PlaceInstance
|
||||
],
|
||||
common: [
|
||||
InstanceEditOptions.MaterialsList,
|
||||
InstanceEditOptions.RenameInstance,
|
||||
InstanceEditOptions.DeleteInstance,
|
||||
InstanceEditOptions.MainMenu
|
||||
]
|
||||
}
|
||||
|
||||
constructor(player, instanceName) {
|
||||
this.player = player;
|
||||
this.instanceName = instanceName;
|
||||
this.instance = structureCollection.get(this.instanceName);
|
||||
this.show();
|
||||
}
|
||||
|
||||
show() {
|
||||
const form = this.buildInstanceForm();
|
||||
form.show(this.player).then((response) => {
|
||||
if (response.canceled) return;
|
||||
let selectedOption;
|
||||
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);
|
||||
});
|
||||
}
|
||||
|
||||
buildInstanceForm() {
|
||||
const instanceOptions = this.instance.isPlaced() ? this.options.isPlaced : this.options.notPlaced;
|
||||
const form = new ActionFormData()
|
||||
.title('§l§2StrucTool §8Menu')
|
||||
.body(`Instance: §2${this.instanceName}`)
|
||||
instanceOptions.forEach(option => {
|
||||
form.button(`${option}`);
|
||||
});
|
||||
this.options.common.forEach(option => {
|
||||
form.button(`${option}`);
|
||||
});
|
||||
return form;
|
||||
}
|
||||
|
||||
handleOption(option) {
|
||||
switch (option) {
|
||||
case InstanceEditOptions.PlaceInstance:
|
||||
this.instance.place(this.player.dimension.id, this.player.location);
|
||||
break;
|
||||
case InstanceEditOptions.RemovePlacement:
|
||||
this.instance.removePlacement();
|
||||
break;
|
||||
case InstanceEditOptions.RenameInstance:
|
||||
this.renameInstanceForm();
|
||||
break;
|
||||
case InstanceEditOptions.DeleteInstance:
|
||||
this.structureCollection.remove(this.instanceName);
|
||||
break;
|
||||
case InstanceEditOptions.NextLayer:
|
||||
this.instance.setLayer(this.instance.getLayer() + 1);
|
||||
new InstanceEditForm(this.player, this.instanceName);
|
||||
break;
|
||||
case InstanceEditOptions.PreviousLayer:
|
||||
this.instance.setLayer(this.instance.getLayer() - 1);
|
||||
new InstanceEditForm(this.player, this.instanceName);
|
||||
break;
|
||||
case InstanceEditOptions.SetLayer:
|
||||
this.setLayerForm();
|
||||
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:
|
||||
this.instance.move(this.player.dimension.id, this.player.location);
|
||||
break;
|
||||
case InstanceEditOptions.MaterialsList:
|
||||
this.player.sendMessage('§cMaterial list not implemented yet.');
|
||||
break;
|
||||
case InstanceEditOptions.MainMenu:
|
||||
new MenuForm(this.player);
|
||||
break;
|
||||
default:
|
||||
this.player.sendMessage(`§cUnknown option: ${option}`);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
renameInstanceForm() {
|
||||
|
||||
}
|
||||
|
||||
setLayerForm() {
|
||||
// should have a toggle for if it should layer the structure or notw
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
import { ActionFormData, ModalFormData } from '@minecraft/server-ui';
|
||||
|
||||
export class InstanceEditFormBuilder {
|
||||
static buildRenameInstance() {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
export const InstanceEditOptions = Object.freeze({
|
||||
Unknown: "unknown",
|
||||
MainMenu: 'Back to Main Menu',
|
||||
PlaceInstance: 'Place Instance',
|
||||
RemovePlacement: 'Remove Placement',
|
||||
RenameInstance: 'Rename Instance',
|
||||
DeleteInstance: '§cDelete Instance',
|
||||
NextLayer: 'Increase Layer',
|
||||
PreviousLayer: 'Decrease Layer',
|
||||
SetLayer: 'Set Layer',
|
||||
Move: 'Move Here',
|
||||
Rotate: 'Rotate',
|
||||
Mirror: 'Mirror',
|
||||
MaterialsList: 'Get Materials List',
|
||||
});
|
||||
@@ -0,0 +1,79 @@
|
||||
import { forceShow } from '../utils';
|
||||
import { structureCollection } from './StructureCollection';
|
||||
import { MenuFormBuilder } from './MenuFormBuilder';
|
||||
import { InstanceEditForm } from './InstanceEditForm';
|
||||
|
||||
export class MenuForm {
|
||||
constructor(player) {
|
||||
this.player = player;
|
||||
this.show();
|
||||
}
|
||||
|
||||
async show() {
|
||||
let instanceName = this.getInstanceFromLocation();
|
||||
if (!instanceName)
|
||||
instanceName = await this.getInstanceNameFromForm();
|
||||
if (!instanceName)
|
||||
return;
|
||||
new InstanceEditForm(this.player, instanceName);
|
||||
}
|
||||
|
||||
getInstanceFromLocation() {
|
||||
const locatedStructures = structureCollection.getStructuresAtLocation(this.player.location);
|
||||
if (locatedStructures.length === 0)
|
||||
return void 0;
|
||||
const structure = locatedStructures[0];
|
||||
return structure.instanceName;
|
||||
}
|
||||
|
||||
async getInstanceNameFromForm() {
|
||||
try {
|
||||
return forceShow(this.player, MenuFormBuilder.buildAllInstanceNameForm()).then((response) => {
|
||||
if (response.canceled) return;
|
||||
const selectedInstanceName = structureCollection.getInstanceNames()[response.selection];
|
||||
return selectedInstanceName || this.createNewInstance();
|
||||
});
|
||||
} catch (e) {
|
||||
if (e.message === 'Menu timed out.') {
|
||||
this.player.sendMessage('§8Menu timed out.');
|
||||
return;
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
async createNewInstance() {
|
||||
return MenuFormBuilder.buildNewInstanceForm().show(this.player).then(async (response) => {
|
||||
if (response.canceled)
|
||||
return;
|
||||
const instanceName = response.formValues[0];
|
||||
if (instanceName === '')
|
||||
return void 0;
|
||||
const structureId = await this.getStructureId();
|
||||
if (!structureId)
|
||||
return;
|
||||
structureCollection.add(instanceName, structureId);
|
||||
return instanceName;
|
||||
});
|
||||
}
|
||||
|
||||
async getStructureId() {
|
||||
return MenuFormBuilder.buildAllStructuresForm().show(this.player).then((response) => {
|
||||
if (response.canceled)
|
||||
return;
|
||||
const selectedStructureId = structureCollection.getWorldStructureIds()[response.selection];
|
||||
return selectedStructureId || this.getOtherStructureId();
|
||||
});
|
||||
}
|
||||
|
||||
getOtherStructureId() {
|
||||
return MenuFormBuilder.buildOtherStructureForm().show(this.player).then((response) => {
|
||||
if (response.canceled)
|
||||
return;
|
||||
const structureId = response.formValues[0];
|
||||
if (structureId === '')
|
||||
return void 0;
|
||||
return structureId;
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
import { ActionFormData, ModalFormData } from '@minecraft/server-ui';
|
||||
import { structureCollection } from './StructureCollection';
|
||||
|
||||
export class MenuFormBuilder {
|
||||
static menuTitle = '§l§2StrucTool §8Menu';
|
||||
|
||||
static buildAllInstanceNameForm() {
|
||||
const allInstanceNameForm = new ActionFormData()
|
||||
.title(this.menuTitle)
|
||||
.body('Select an instance:');
|
||||
structureCollection.getInstanceNames().forEach(instanceName => {
|
||||
allInstanceNameForm.button(`§2${instanceName}`);
|
||||
});
|
||||
allInstanceNameForm.button('Create New Instance');
|
||||
return allInstanceNameForm;
|
||||
}
|
||||
|
||||
static buildNewInstanceForm() {
|
||||
return new ModalFormData()
|
||||
.title(this.menuTitle)
|
||||
.textField('Enter a name for the new instance:', 'example_instance')
|
||||
.submitButton('Submit');
|
||||
}
|
||||
|
||||
static buildAllStructuresForm() {
|
||||
const allStructuresForm = new ActionFormData()
|
||||
.title(this.menuTitle)
|
||||
.body('Select a structure:');
|
||||
structureCollection.getWorldStructureIds().forEach(structureId => {
|
||||
const structureName = structureId.replace('mystructure:', '');
|
||||
allStructuresForm.button(`§2${structureName}`);
|
||||
});
|
||||
allStructuresForm.button('Other');
|
||||
return allStructuresForm;
|
||||
}
|
||||
|
||||
static buildOtherStructureForm() {
|
||||
return new ModalFormData()
|
||||
.title(this.menuTitle)
|
||||
.textField('Enter the Structure ID:', 'example_structure')
|
||||
.submitButton('Submit');
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,3 @@
|
||||
import { world } from "@minecraft/server";
|
||||
import { structureCollection } from "./StructureCollection";
|
||||
|
||||
export class Raycaster {
|
||||
|
||||
@@ -1,37 +1,41 @@
|
||||
import { Structure } from './Structure';
|
||||
import { StructureInstance } from './StructureInstance';
|
||||
import { world } from '@minecraft/server';
|
||||
|
||||
class StructureCollection {
|
||||
#structures;
|
||||
structures;
|
||||
|
||||
constructor() {
|
||||
this.#structures = {};
|
||||
this.structures = {};
|
||||
}
|
||||
|
||||
add(name) {
|
||||
if (this.#structures[name]) {
|
||||
throw new Error(`Structure ${name} already exists.`);
|
||||
}
|
||||
const structure = new Structure(name);
|
||||
this.#structures[name] = structure;
|
||||
add(instanceName, structureId) {
|
||||
if (this.structures[instanceName])
|
||||
throw new Error(`Instance ${instanceName} already exists.`);
|
||||
const structure = new StructureInstance(instanceName, structureId);
|
||||
this.structures[instanceName] = structure;
|
||||
return structure;
|
||||
}
|
||||
|
||||
get(name) {
|
||||
const structure = this.#structures[name];
|
||||
get(instanceName) {
|
||||
const structure = this.structures[instanceName];
|
||||
if (!structure) {
|
||||
throw new Error(`Structure ${name} not found.`);
|
||||
throw new Error(`Instance ${instanceName} not found.`);
|
||||
}
|
||||
return structure;
|
||||
}
|
||||
|
||||
remove(name) {
|
||||
const struct = this.get(name);
|
||||
struct.remove();
|
||||
delete this.#structures[name];
|
||||
remove(instanceName) {
|
||||
const struct = this.get(instanceName);
|
||||
struct.removePlacement();
|
||||
delete this.structures[instanceName];
|
||||
}
|
||||
|
||||
getInstanceNames() {
|
||||
return Object.keys(this.structures);
|
||||
}
|
||||
|
||||
getStructuresAtLocation(location) {
|
||||
return Object.values(this.#structures).filter(structure => structure.isLocationActive(structure.toStructureCoords(location)));
|
||||
return Object.values(this.structures).filter(structure => structure.isLocationActive(structure.toStructureCoords(location)));
|
||||
}
|
||||
|
||||
fetchStructureBlock(location) {
|
||||
@@ -41,6 +45,21 @@ class StructureCollection {
|
||||
const structure = locatedStructures[0];
|
||||
return structure.getBlock(structure.toStructureCoords(location));
|
||||
}
|
||||
|
||||
getWorldStructureIds() {
|
||||
return world.structureManager.getWorldStructureIds()
|
||||
.filter(id => id.startsWith('mystructure:'))
|
||||
.map(id => id.replace('mystructure:', ''));
|
||||
}
|
||||
|
||||
rename(instanceName, newName) {
|
||||
const structure = this.get(instanceName);
|
||||
if (this.structures[newName])
|
||||
throw new Error(`Instance ${newName} already exists.`);
|
||||
this.structures[newName] = structure;
|
||||
delete this.structures[instanceName];
|
||||
structure.name = newName;
|
||||
}
|
||||
}
|
||||
|
||||
export const structureCollection = new StructureCollection();
|
||||
@@ -1,7 +1,7 @@
|
||||
import { world } from "@minecraft/server";
|
||||
import { Outliner } from "./Outliner";
|
||||
|
||||
export class Structure {
|
||||
export class StructureInstance {
|
||||
#structure;
|
||||
#options = {
|
||||
isPlaced: false,
|
||||
@@ -12,13 +12,15 @@ export class Structure {
|
||||
currentLayer: 0
|
||||
};
|
||||
|
||||
constructor(structureName) {
|
||||
this.name = structureName;
|
||||
this.#structure = world.structureManager.get(structureName);
|
||||
constructor(instanceName, structureId) {
|
||||
this.name = instanceName;
|
||||
this.structureId = structureId;
|
||||
this.#structure = world.structureManager.get(structureId);
|
||||
if (!this.#structure) {
|
||||
throw new Error(`[StrucTool] Structure '${structureName}' not found.`);
|
||||
throw new Error(`[StrucTool] Structure '${this.structureId}' not found.`);
|
||||
}
|
||||
this.#options = this.loadOptions();
|
||||
this.#options.isPlaced = false;
|
||||
}
|
||||
|
||||
loadOptions() {
|
||||
@@ -39,7 +41,7 @@ export class Structure {
|
||||
}
|
||||
|
||||
getLocation() {
|
||||
return this.#options.worldLocation;
|
||||
return { dimensionId: this.#options.dimensionId, location: this.#options.worldLocation };
|
||||
}
|
||||
|
||||
getHeight() {
|
||||
@@ -47,7 +49,7 @@ export class Structure {
|
||||
}
|
||||
|
||||
getLayer() {
|
||||
return this.#options.currentLayer;
|
||||
return this.#options.currentLayer || 0;
|
||||
}
|
||||
|
||||
*getBlocks() {
|
||||
@@ -83,7 +85,7 @@ export class Structure {
|
||||
|
||||
getLayeredBounds() {
|
||||
if (!this.#options.isPlaced)
|
||||
throw new Error(`[StrucTool] Structure '${this.name}' is not placed.`);
|
||||
throw new Error(`[StrucTool] Instance '${this.name}' is not placed.`);
|
||||
return {
|
||||
min: { x: 0, y: this.#options.currentLayer - 1, z: 0 },
|
||||
max: { x: this.#structure.size.x, y: this.#options.currentLayer, z: this.#structure.size.z }
|
||||
@@ -91,31 +93,44 @@ export class Structure {
|
||||
}
|
||||
|
||||
place(dimensionId, worldLocation) {
|
||||
this.#options = {
|
||||
isPlaced: true,
|
||||
dimensionId,
|
||||
worldLocation: { x: Math.floor(worldLocation.x), y: Math.floor(worldLocation.y), z: Math.floor(worldLocation.z) },
|
||||
};
|
||||
this.updateOptions();
|
||||
this.outliner = new Outliner(dimensionId, this.toGlobalCoords(this.getBounds().min), this.toGlobalCoords(this.getBounds().max));
|
||||
this.#options.isPlaced = true;
|
||||
this.move(dimensionId, worldLocation);
|
||||
}
|
||||
|
||||
remove() {
|
||||
removePlacement() {
|
||||
if (!this.#options.isPlaced)
|
||||
throw new Error(`[StrucTool] Structure '${this.name}' is not placed.`);
|
||||
throw new Error(`[StrucTool] Instance '${this.name}' is not placed.`);
|
||||
this.#options.isPlaced = false;
|
||||
this.updateOptions();
|
||||
this.outliner.stopDraw();
|
||||
}
|
||||
|
||||
move(dimensionId, location) {
|
||||
if (!this.#options.isPlaced)
|
||||
throw new Error(`[StrucTool] Instance '${this.name}' is not placed.`);
|
||||
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();
|
||||
}
|
||||
|
||||
setLayer(layer) {
|
||||
if (layer < 1 || layer > this.#structure.size.y)
|
||||
throw new Error(`[StrucTool] Structure '${this.name}' does not have layer ${layer}.`);
|
||||
throw new Error(`[StrucTool] Instance '${this.name}' of '${this.structureId}' does not have layer ${layer}.`);
|
||||
this.#options.currentLayer = layer;
|
||||
this.updateOptions();
|
||||
this.outliner.stopDraw();
|
||||
const { min, max } = this.getLayeredBounds();
|
||||
this.outliner = new Outliner(this.#options.dimensionId, this.toGlobalCoords(min), this.toGlobalCoords(max));
|
||||
this.refreshOutliner();
|
||||
}
|
||||
|
||||
refreshOutliner() {
|
||||
if (this.outliner)
|
||||
this.outliner.stopDraw();
|
||||
if (this.#options.currentLayer > 0) {
|
||||
const { min, max } = this.getLayeredBounds();
|
||||
this.outliner = new Outliner(this.#options.dimensionId, this.toGlobalCoords(min), this.toGlobalCoords(max));
|
||||
} else {
|
||||
this.outliner = new Outliner(dimensionId, this.toGlobalCoords(this.getBounds().min), this.toGlobalCoords(this.getBounds().max));
|
||||
}
|
||||
}
|
||||
|
||||
isLocationInStructure(structureLocation) {
|
||||
@@ -155,4 +170,8 @@ export class Structure {
|
||||
z: worldLocation.z - this.#options.worldLocation.z
|
||||
};
|
||||
}
|
||||
|
||||
isPlaced() {
|
||||
return this.#options.isPlaced;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user