complete rename and init builder options
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"format_version": 2,
|
"format_version": 2,
|
||||||
"header": {
|
"header": {
|
||||||
"name": "StrucTool [BP] v1.0.0",
|
"name": "Construct [BP] v1.0.0",
|
||||||
"description": "Survival building extension for §l§aCanopy§r by §aForestOfLight§r.",
|
"description": "Survival building extension for §l§aCanopy§r by §aForestOfLight§r.",
|
||||||
"uuid": "8c0c0153-d8b9-482a-889f-aef922b8fe58",
|
"uuid": "8c0c0153-d8b9-482a-889f-aef922b8fe58",
|
||||||
"min_engine_version": [1, 21, 70],
|
"min_engine_version": [1, 21, 70],
|
||||||
@@ -33,7 +33,7 @@
|
|||||||
"version": "2.0.0-beta"
|
"version": "2.0.0-beta"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"uuid": "375ec465-3dc1-429f-8b4c-a337889e1ed4", // StrucTool RP
|
"uuid": "375ec465-3dc1-429f-8b4c-a337889e1ed4", // Construct RP
|
||||||
"version": [1, 0, 0]
|
"version": [1, 0, 0]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -36,12 +36,12 @@ export class BlockVerificationLevelRender {
|
|||||||
const frontFace = new Vector(0.5, 0.5, 1);
|
const frontFace = new Vector(0.5, 0.5, 1);
|
||||||
const backFace = new Vector(0.5, 0.5, 0);
|
const backFace = new Vector(0.5, 0.5, 0);
|
||||||
return [
|
return [
|
||||||
{ particleType: "structool:blockoverlay_xz", location: this.location.add(topFace) },
|
{ particleType: "construct:blockoverlay_xz", location: this.location.add(topFace) },
|
||||||
{ particleType: "structool:blockoverlay_xz", location: this.location.add(bottomFace) },
|
{ particleType: "construct:blockoverlay_xz", location: this.location.add(bottomFace) },
|
||||||
{ particleType: "structool:blockoverlay_yz", location: this.location.add(leftFace) },
|
{ particleType: "construct:blockoverlay_yz", location: this.location.add(leftFace) },
|
||||||
{ particleType: "structool:blockoverlay_yz", location: this.location.add(rightFace) },
|
{ particleType: "construct:blockoverlay_yz", location: this.location.add(rightFace) },
|
||||||
{ particleType: "structool:blockoverlay_xy", location: this.location.add(frontFace) },
|
{ particleType: "construct:blockoverlay_xy", location: this.location.add(frontFace) },
|
||||||
{ particleType: "structool:blockoverlay_xy", location: this.location.add(backFace) }
|
{ particleType: "construct:blockoverlay_xy", location: this.location.add(backFace) }
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,22 @@
|
|||||||
|
import { BuilderOptions } from "./BuilderOptions";
|
||||||
|
import { Builders } from "./Builders";
|
||||||
|
|
||||||
|
export class Builder {
|
||||||
|
constructor(playerId) {
|
||||||
|
this.playerId = playerId;
|
||||||
|
this.options = new BuilderOptions(playerId);
|
||||||
|
Builders.add(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
getOptionIds() {
|
||||||
|
return Object.keys(this.options.options).sort((a, b) => a.localeCompare(b));
|
||||||
|
}
|
||||||
|
|
||||||
|
getOption(id) {
|
||||||
|
return this.options.get(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
setOption(id, value) {
|
||||||
|
return this.options.setValue(id, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
import { BuilderFormBuilder } from "./BuilderFormBuilder";
|
||||||
|
import { Builders } from "./Builders";
|
||||||
|
|
||||||
|
export class BuilderForm {
|
||||||
|
constructor(player) {
|
||||||
|
this.player = player;
|
||||||
|
}
|
||||||
|
|
||||||
|
show() {
|
||||||
|
forceShow(this.player, BuilderFormBuilder.buildSettings(this.player)).then((response) => {
|
||||||
|
if (response.canceled) return;
|
||||||
|
this.applySettings(response.formValues);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
applySettings(formValues) {
|
||||||
|
const optionIds = Builders.get(this.player.id).getOptionIds();
|
||||||
|
for (let i = 0; i < optionIds.length; i++) {
|
||||||
|
const option = optionIds[i];
|
||||||
|
if (option.setValue(formValues[i]) && formValues[i] === true)
|
||||||
|
this.player.sendMessage(`§a${option.displayName} is enabled!§7 ${option.howToUse}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
import { ModalFormData } from "@minecraft/server-ui";
|
||||||
|
import { MenuFormBuilder } from "../MenuFormBuilder";
|
||||||
|
import { Builders } from "./Builders";
|
||||||
|
|
||||||
|
export class BuilderFormBuilder {
|
||||||
|
static buildSettings(player) {
|
||||||
|
const form = new ModalFormData()
|
||||||
|
.title(MenuFormBuilder.menuTitle);
|
||||||
|
const builder = Builders.get(player.id);
|
||||||
|
for (const optionId of builder.getOptionIds()) {
|
||||||
|
const option = builder.getOption(optionId);
|
||||||
|
form.toggle(`${option.displayName} - ${option.description}`, option.getValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
import { BuilderOptions } from "./BuilderOptions";
|
||||||
|
import { Option } from "../Option";
|
||||||
|
|
||||||
|
export class BuilderOption extends Option {
|
||||||
|
playerId;
|
||||||
|
identifier;
|
||||||
|
displayName;
|
||||||
|
description;
|
||||||
|
value;
|
||||||
|
#onEnable;
|
||||||
|
#onDisable;
|
||||||
|
#DP_NAMESPACE = "builderOptions";
|
||||||
|
|
||||||
|
constructor({ player, identifier, displayName, description, howToUse, onEnableCallback = () => {}, onDisableCallback = () => {} }) {
|
||||||
|
this.playerId = player.id;
|
||||||
|
this.identifier = identifier;
|
||||||
|
this.displayName = displayName;
|
||||||
|
this.description = description;
|
||||||
|
this.howToUse = howToUse;
|
||||||
|
this.#onEnable = onEnableCallback;
|
||||||
|
this.#onDisable = onDisableCallback;
|
||||||
|
BuilderOptions.add(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
save() {
|
||||||
|
this.saveToDP(this.#DP_NAMESPACE, `${this.playerId}:${this.identifier}`, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
load() {
|
||||||
|
this.loadFromDP(this.#DP_NAMESPACE, `${this.playerId}:${this.identifier}`);
|
||||||
|
this.value = this.value ?? false;
|
||||||
|
}
|
||||||
|
|
||||||
|
clear() {
|
||||||
|
this.clearDP(this.#DP_NAMESPACE, `${this.playerId}:${this.identifier}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
getValue() {
|
||||||
|
return this.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
setValue(value) {
|
||||||
|
if (value)
|
||||||
|
this.#onEnable();
|
||||||
|
else
|
||||||
|
this.#onDisable();
|
||||||
|
if (this.value !== value) {
|
||||||
|
this.value = value;
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
return void 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
import { world } from "@minecraft/server";
|
||||||
|
import { BuilderOption } from "./BuilderOption";
|
||||||
|
|
||||||
|
export class BuilderOptions {
|
||||||
|
playerId = void 0;
|
||||||
|
options = {};
|
||||||
|
|
||||||
|
constructor(playerId) {
|
||||||
|
this.playerId = playerId;
|
||||||
|
this.loadOptions();
|
||||||
|
}
|
||||||
|
|
||||||
|
loadOptions() {
|
||||||
|
const optionDPs = world.getDynamicPropertyIds().filter((id) => id.startsWith(`builderOptions:${this.playerId}:`));
|
||||||
|
for (const optionDP of optionDPs)
|
||||||
|
new BuilderOption(JSON.parse(world.getDynamicProperty(optionDP)));
|
||||||
|
}
|
||||||
|
|
||||||
|
add(builderOption) {
|
||||||
|
this.options[builderOption.identifer] = builderOption;
|
||||||
|
}
|
||||||
|
|
||||||
|
get(id) {
|
||||||
|
return this.options[id];
|
||||||
|
}
|
||||||
|
|
||||||
|
getValue(id) {
|
||||||
|
return this.options[id].getValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
setValue(id, value) {
|
||||||
|
return this.options[id].setValue(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
import { world } from "@minecraft/server";
|
||||||
|
import { Builder } from "./Builder";
|
||||||
|
|
||||||
|
export class Builders {
|
||||||
|
static builders = {};
|
||||||
|
|
||||||
|
add(playerId) {
|
||||||
|
this.builders[playerId] = new Builder(playerId);
|
||||||
|
}
|
||||||
|
|
||||||
|
remove(playerId) {
|
||||||
|
delete this.builders[playerId];
|
||||||
|
}
|
||||||
|
|
||||||
|
get(id) {
|
||||||
|
return this.builders[id];
|
||||||
|
}
|
||||||
|
|
||||||
|
onJoin(playerId) {
|
||||||
|
this.add(playerId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
world.afterEvents.playerJoin.subscribe((event) => Builders.onJoin(event.playerId));
|
||||||
|
world.beforeEvents.playerLeave.subscribe((event) => Builders.onLeave(event.player));
|
||||||
+40
-40
@@ -1,34 +1,34 @@
|
|||||||
import { structureCollection } from './StructureCollection';
|
import { structureCollection } from './StructureCollection';
|
||||||
import { MenuForm } from './MenuForm';
|
import { MenuForm } from '../MenuForm';
|
||||||
import { forceShow } from '../utils';
|
import { forceShow } from '../../utils';
|
||||||
import { InstanceEditButtons } from './enums/InstanceEditButtons';
|
import { InstanceButtons } from '../enums/InstanceButtons';
|
||||||
import { InstanceEditFormBuilder } from './InstanceEditFormBuilder';
|
import { InstanceFormBuilder } from './InstanceFormBuilder';
|
||||||
import { FormCancelationReason } from '@minecraft/server-ui';
|
import { FormCancelationReason } from '@minecraft/server-ui';
|
||||||
|
|
||||||
export class InstanceEditForm {
|
export class InstanceForm {
|
||||||
instanceName;
|
instanceName;
|
||||||
#buttons = {
|
#buttons = {
|
||||||
isEnabled: [
|
isEnabled: [
|
||||||
InstanceEditButtons.NextLayer,
|
InstanceButtons.NextLayer,
|
||||||
InstanceEditButtons.PreviousLayer,
|
InstanceButtons.PreviousLayer,
|
||||||
InstanceEditButtons.SetLayer,
|
InstanceButtons.SetLayer,
|
||||||
InstanceEditButtons.Move,
|
InstanceButtons.Move,
|
||||||
InstanceEditButtons.Statistics,
|
InstanceButtons.Statistics,
|
||||||
InstanceEditButtons.Settings,
|
InstanceButtons.Settings,
|
||||||
InstanceEditButtons.Rename,
|
InstanceButtons.Rename,
|
||||||
InstanceEditButtons.Disable,
|
InstanceButtons.Disable,
|
||||||
],
|
],
|
||||||
isNotEnabledAndIsNotPlaced: [
|
isNotEnabledAndIsNotPlaced: [
|
||||||
InstanceEditButtons.Place,
|
InstanceButtons.Place,
|
||||||
InstanceEditButtons.Rename
|
InstanceButtons.Rename
|
||||||
],
|
],
|
||||||
isNotEnabledButIsPlaced: [
|
isNotEnabledButIsPlaced: [
|
||||||
InstanceEditButtons.Enable,
|
InstanceButtons.Enable,
|
||||||
InstanceEditButtons.Rename
|
InstanceButtons.Rename
|
||||||
],
|
],
|
||||||
common: [
|
common: [
|
||||||
InstanceEditButtons.Delete,
|
InstanceButtons.Delete,
|
||||||
InstanceEditButtons.MainMenu
|
InstanceButtons.MainMenu
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -41,7 +41,7 @@ export class InstanceEditForm {
|
|||||||
|
|
||||||
show() {
|
show() {
|
||||||
const currentOptions = this.getActiveOptions();
|
const currentOptions = this.getActiveOptions();
|
||||||
forceShow(this.player, InstanceEditFormBuilder.buildInstance(this.instance, currentOptions)).then((response) => {
|
forceShow(this.player, InstanceFormBuilder.buildInstance(this.instance, currentOptions)).then((response) => {
|
||||||
if (response.canceled) return;
|
if (response.canceled) return;
|
||||||
this.handleOption(currentOptions[response.selection]);
|
this.handleOption(currentOptions[response.selection]);
|
||||||
});
|
});
|
||||||
@@ -59,48 +59,48 @@ export class InstanceEditForm {
|
|||||||
|
|
||||||
if (!this.instance.hasLayers())
|
if (!this.instance.hasLayers())
|
||||||
currentOptions = currentOptions.filter(option =>
|
currentOptions = currentOptions.filter(option =>
|
||||||
option !== InstanceEditButtons.SetLayer
|
option !== InstanceButtons.SetLayer
|
||||||
&& option !== InstanceEditButtons.NextLayer
|
&& option !== InstanceButtons.NextLayer
|
||||||
&& option !== InstanceEditButtons.PreviousLayer
|
&& option !== InstanceButtons.PreviousLayer
|
||||||
);
|
);
|
||||||
return currentOptions;
|
return currentOptions;
|
||||||
}
|
}
|
||||||
|
|
||||||
handleOption(option) {
|
handleOption(option) {
|
||||||
switch (option) {
|
switch (option) {
|
||||||
case InstanceEditButtons.Enable:
|
case InstanceButtons.Enable:
|
||||||
this.instance.enable();
|
this.instance.enable();
|
||||||
break;
|
break;
|
||||||
case InstanceEditButtons.Disable:
|
case InstanceButtons.Disable:
|
||||||
this.instance.disable();
|
this.instance.disable();
|
||||||
break;
|
break;
|
||||||
case InstanceEditButtons.Place:
|
case InstanceButtons.Place:
|
||||||
this.instance.place(this.player.dimension.id, this.player.location);
|
this.instance.place(this.player.dimension.id, this.player.location);
|
||||||
break;
|
break;
|
||||||
case InstanceEditButtons.Rename:
|
case InstanceButtons.Rename:
|
||||||
this.renameInstanceForm();
|
this.renameInstanceForm();
|
||||||
break;
|
break;
|
||||||
case InstanceEditButtons.Delete:
|
case InstanceButtons.Delete:
|
||||||
structureCollection.delete(this.instanceName);
|
structureCollection.delete(this.instanceName);
|
||||||
break;
|
break;
|
||||||
case InstanceEditButtons.NextLayer:
|
case InstanceButtons.NextLayer:
|
||||||
this.instance.increaseLayer();
|
this.instance.increaseLayer();
|
||||||
new InstanceEditForm(this.player, this.instanceName);
|
new InstanceForm(this.player, this.instanceName);
|
||||||
break;
|
break;
|
||||||
case InstanceEditButtons.PreviousLayer:
|
case InstanceButtons.PreviousLayer:
|
||||||
this.instance.decreaseLayer();
|
this.instance.decreaseLayer();
|
||||||
new InstanceEditForm(this.player, this.instanceName);
|
new InstanceForm(this.player, this.instanceName);
|
||||||
break;
|
break;
|
||||||
case InstanceEditButtons.Settings:
|
case InstanceButtons.Settings:
|
||||||
this.settingsForm();
|
this.settingsForm();
|
||||||
break;
|
break;
|
||||||
case InstanceEditButtons.Move:
|
case InstanceButtons.Move:
|
||||||
this.instance.move(this.player.dimension.id, this.player.location);
|
this.instance.move(this.player.dimension.id, this.player.location);
|
||||||
break;
|
break;
|
||||||
case InstanceEditButtons.Statistics:
|
case InstanceButtons.Statistics:
|
||||||
this.statisticsForm();
|
this.statisticsForm();
|
||||||
break;
|
break;
|
||||||
case InstanceEditButtons.MainMenu:
|
case InstanceButtons.MainMenu:
|
||||||
new MenuForm(this.player, { jumpToInstance: false });
|
new MenuForm(this.player, { jumpToInstance: false });
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@@ -110,7 +110,7 @@ export class InstanceEditForm {
|
|||||||
}
|
}
|
||||||
|
|
||||||
renameInstanceForm() {
|
renameInstanceForm() {
|
||||||
InstanceEditFormBuilder.buildRenameInstance(this.instanceName).show(this.player).then((response) => {
|
InstanceFormBuilder.buildRenameInstance(this.instanceName).show(this.player).then((response) => {
|
||||||
if (response.canceled)
|
if (response.canceled)
|
||||||
return;
|
return;
|
||||||
const newName = response.formValues[0];
|
const newName = response.formValues[0];
|
||||||
@@ -129,7 +129,7 @@ export class InstanceEditForm {
|
|||||||
}
|
}
|
||||||
|
|
||||||
setLayerForm() {
|
setLayerForm() {
|
||||||
InstanceEditFormBuilder.buildSetLayer(this.instance.getBounds().max.y, this.instance.getLayer()).show(this.player).then((response) => {
|
InstanceFormBuilder.buildSetLayer(this.instance.getBounds().max.y, this.instance.getLayer()).show(this.player).then((response) => {
|
||||||
if (response.canceled)
|
if (response.canceled)
|
||||||
return;
|
return;
|
||||||
this.instance.setLayer(parseInt(response.formValues[0]));
|
this.instance.setLayer(parseInt(response.formValues[0]));
|
||||||
@@ -137,7 +137,7 @@ export class InstanceEditForm {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async statisticsForm() {
|
async statisticsForm() {
|
||||||
const statsForm = await InstanceEditFormBuilder.buildStatistics(this.instance)
|
const statsForm = await InstanceFormBuilder.buildStatistics(this.instance)
|
||||||
statsForm.form.show(this.player).then((response) => {
|
statsForm.form.show(this.player).then((response) => {
|
||||||
if (response.canceled && response.cancelationReason === FormCancelationReason.UserBusy)
|
if (response.canceled && response.cancelationReason === FormCancelationReason.UserBusy)
|
||||||
this.player.sendMessage(statsForm.stats);
|
this.player.sendMessage(statsForm.stats);
|
||||||
@@ -145,7 +145,7 @@ export class InstanceEditForm {
|
|||||||
}
|
}
|
||||||
|
|
||||||
settingsForm() {
|
settingsForm() {
|
||||||
InstanceEditFormBuilder.buildSettings(this.instance).show(this.player).then((response) => {
|
InstanceFormBuilder.buildSettings(this.instance).show(this.player).then((response) => {
|
||||||
if (response.canceled)
|
if (response.canceled)
|
||||||
return;
|
return;
|
||||||
this.instance.setVerifierEnabled(response.formValues[0]);
|
this.instance.setVerifierEnabled(response.formValues[0]);
|
||||||
+3
-3
@@ -1,10 +1,10 @@
|
|||||||
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 { StructureVerifier } from './StructureVerifier';
|
||||||
import { StructureStatistics } from './StructureStatistics';
|
import { StructureStatistics } from './StructureStatistics';
|
||||||
import { TicksPerSecond } from '@minecraft/server';
|
import { TicksPerSecond } from '@minecraft/server';
|
||||||
|
|
||||||
export class InstanceEditFormBuilder {
|
export class InstanceFormBuilder {
|
||||||
static buildInstance(instance, options) {
|
static buildInstance(instance, options) {
|
||||||
const location = instance.getLocation();
|
const location = instance.getLocation();
|
||||||
const form = new ActionFormData()
|
const form = new ActionFormData()
|
||||||
@@ -41,7 +41,7 @@ export class InstanceEditFormBuilder {
|
|||||||
return new ModalFormData()
|
return new ModalFormData()
|
||||||
.title(MenuFormBuilder.menuTitle)
|
.title(MenuFormBuilder.menuTitle)
|
||||||
.label('Use the slider to select the layer. Use 0 for all layers.')
|
.label('Use the slider to select the layer. Use 0 for all layers.')
|
||||||
.toggle('Toggle block validation.', instance.options.verifier.isEnabled)
|
.toggle('Block Validation', instance.options.verifier.isEnabled)
|
||||||
.slider("Layer", 0, maxLayer, 1, currentLayer)
|
.slider("Layer", 0, maxLayer, 1, currentLayer)
|
||||||
.submitButton('§aApply');
|
.submitButton('§aApply');
|
||||||
}
|
}
|
||||||
+7
-15
@@ -1,7 +1,9 @@
|
|||||||
import { Vector } from "../lib/Vector";
|
import { Vector } from "../../lib/Vector";
|
||||||
import { world } from "@minecraft/server";
|
import { world } from "@minecraft/server";
|
||||||
|
import { Option } from "../Option";
|
||||||
|
|
||||||
export class InstanceOptions {
|
export class InstanceOptions extends Option {
|
||||||
|
#DP_NAMESPACE = "instanceOptions";
|
||||||
instanceName = void 0;
|
instanceName = void 0;
|
||||||
structureId = void 0;
|
structureId = void 0;
|
||||||
isEnabled = false;
|
isEnabled = false;
|
||||||
@@ -26,26 +28,16 @@ export class InstanceOptions {
|
|||||||
}
|
}
|
||||||
|
|
||||||
save() {
|
save() {
|
||||||
world.setDynamicProperty(`instanceOptions:${this.instanceName}`, JSON.stringify(this));
|
this.saveToDP(this.#DP_NAMESPACE, this.instanceName, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
load() {
|
load() {
|
||||||
try {
|
this.loadFromDP(this.#DP_NAMESPACE, this.instanceName);
|
||||||
const options = JSON.parse(world.getDynamicProperty(`instanceOptions:${this.instanceName}`));
|
|
||||||
if (options)
|
|
||||||
Object.assign(this, options);
|
|
||||||
else
|
|
||||||
throw new Error("Options not found");
|
|
||||||
} catch {
|
|
||||||
this.save();
|
|
||||||
const options = JSON.parse(world.getDynamicProperty(`instanceOptions:${this.instanceName}`) || "{}");
|
|
||||||
Object.assign(this, options);
|
|
||||||
}
|
|
||||||
this.worldLocation = Vector.from(this.worldLocation);
|
this.worldLocation = Vector.from(this.worldLocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
clear() {
|
clear() {
|
||||||
world.setDynamicProperty(`instanceOptions:${this.instanceName}`, void 0);
|
this.clearDP(this.#DP_NAMESPACE, this.instanceName);
|
||||||
}
|
}
|
||||||
|
|
||||||
getDimension() {
|
getDimension() {
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
import { forceShow } from '../utils';
|
import { forceShow } from '../utils';
|
||||||
import { structureCollection } from './StructureCollection';
|
import { structureCollection } from './StructureCollection';
|
||||||
import { MenuFormBuilder } from './MenuFormBuilder';
|
import { MenuFormBuilder } from './MenuFormBuilder';
|
||||||
import { InstanceEditForm } from './InstanceEditForm';
|
import { InstanceForm } from './InstanceForm';
|
||||||
|
|
||||||
export class MenuForm {
|
export class MenuForm {
|
||||||
constructor(player, { jumpToInstance = false, instanceName = void 0 } = {}) {
|
constructor(player, { jumpToInstance = false, instanceName = void 0 } = {}) {
|
||||||
@@ -14,14 +14,14 @@ export class MenuForm {
|
|||||||
if (!instanceName)
|
if (!instanceName)
|
||||||
instanceName = structureCollection.getStructure(this.player.dimension.id, this.player.location, { useActiveLayer: false })?.getName();
|
instanceName = structureCollection.getStructure(this.player.dimension.id, this.player.location, { useActiveLayer: false })?.getName();
|
||||||
if (structureCollection.get(instanceName)) {
|
if (structureCollection.get(instanceName)) {
|
||||||
new InstanceEditForm(this.player, instanceName);
|
new InstanceForm(this.player, instanceName);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
instanceName = await this.getInstanceNameFromForm();
|
instanceName = await this.getInstanceNameFromForm();
|
||||||
if (!instanceName)
|
if (!instanceName)
|
||||||
return;
|
return;
|
||||||
new InstanceEditForm(this.player, instanceName);
|
new InstanceForm(this.player, instanceName);
|
||||||
}
|
}
|
||||||
|
|
||||||
async getInstanceNameFromForm() {
|
async getInstanceNameFromForm() {
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { ActionFormData, ModalFormData } from '@minecraft/server-ui';
|
|||||||
import { structureCollection } from './StructureCollection';
|
import { structureCollection } from './StructureCollection';
|
||||||
|
|
||||||
export class MenuFormBuilder {
|
export class MenuFormBuilder {
|
||||||
static menuTitle = '§l§2StrucTool §8Menu';
|
static menuTitle = '§l§2Construct §8Menu';
|
||||||
|
|
||||||
static buildAllInstanceName() {
|
static buildAllInstanceName() {
|
||||||
const allInstanceNameForm = new ActionFormData()
|
const allInstanceNameForm = new ActionFormData()
|
||||||
|
|||||||
@@ -0,0 +1,25 @@
|
|||||||
|
import { world } from "@minecraft/server";
|
||||||
|
|
||||||
|
export class Option {
|
||||||
|
saveToDP(namespace, id, data) {
|
||||||
|
world.setDynamicProperty(`${namespace}:${id}`, JSON.stringify(data));
|
||||||
|
}
|
||||||
|
|
||||||
|
loadFromDP(namespace, id) {
|
||||||
|
try {
|
||||||
|
const options = JSON.parse(world.getDynamicProperty(`${namespace}:${id}`));
|
||||||
|
if (options)
|
||||||
|
Object.assign(this, options);
|
||||||
|
else
|
||||||
|
throw new Error("Options not found");
|
||||||
|
} catch {
|
||||||
|
this.saveToDP(namespace, id, {});
|
||||||
|
const options = JSON.parse(world.getDynamicProperty(`${namespace}:${id}`) || "{}");
|
||||||
|
Object.assign(this, options);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
clearDP(namespace, id) {
|
||||||
|
world.setDynamicProperty(`${namespace}:${id}`, void 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,7 +5,7 @@ export class Outliner {
|
|||||||
dimension;
|
dimension;
|
||||||
min = new Vector();
|
min = new Vector();
|
||||||
max = new Vector();
|
max = new Vector();
|
||||||
drawParticle = "structool:outline";
|
drawParticle = "construct:outline";
|
||||||
drawFrequency = 10;
|
drawFrequency = 10;
|
||||||
|
|
||||||
#drawParticles = [];
|
#drawParticles = [];
|
||||||
|
|||||||
+1
-1
@@ -9,7 +9,7 @@ export class Structure {
|
|||||||
this.structureId = structureId;
|
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 '${structureId}' not found.`);
|
throw new Error(`[Construct] Structure '${structureId}' not found.`);
|
||||||
this.#structure.saveToWorld();
|
this.#structure.saveToWorld();
|
||||||
}
|
}
|
||||||
|
|
||||||
+1
-1
@@ -17,7 +17,7 @@ class StructureCollection {
|
|||||||
structureId = InstanceOptions.getInstanceStrucetureId(instanceName);
|
structureId = InstanceOptions.getInstanceStrucetureId(instanceName);
|
||||||
this.structures[instanceName] = new StructureInstance(instanceName, structureId);
|
this.structures[instanceName] = new StructureInstance(instanceName, structureId);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
world.sendMessage(`§c[StrucTool] Error loading structure instance '${instanceName}'. It will be removed.`);
|
world.sendMessage(`§c[Construct] Error loading structure instance '${instanceName}'. It will be removed.`);
|
||||||
world.setDynamicProperty(id, void 0);
|
world.setDynamicProperty(id, void 0);
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
+5
-5
@@ -70,7 +70,7 @@ export class StructureInstance {
|
|||||||
|
|
||||||
getActiveBounds() {
|
getActiveBounds() {
|
||||||
if (!this.options.isEnabled)
|
if (!this.options.isEnabled)
|
||||||
throw new Error(`[StrucTool] Instance '${this.options.instanceName}' is not placed.`);
|
throw new Error(`[Construct] Instance '${this.options.instanceName}' is not placed.`);
|
||||||
if (this.hasLayerSelected())
|
if (this.hasLayerSelected())
|
||||||
return this.getLayerBounds(this.getLayer());
|
return this.getLayerBounds(this.getLayer());
|
||||||
return this.getBounds();
|
return this.getBounds();
|
||||||
@@ -78,7 +78,7 @@ export class StructureInstance {
|
|||||||
|
|
||||||
getLayerBounds(layer) {
|
getLayerBounds(layer) {
|
||||||
if (!this.options.isEnabled)
|
if (!this.options.isEnabled)
|
||||||
throw new Error(`[StrucTool] Instance '${this.options.instanceName}' is not placed.`);
|
throw new Error(`[Construct] Instance '${this.options.instanceName}' is not placed.`);
|
||||||
const min = this.structure.getMin();
|
const min = this.structure.getMin();
|
||||||
const max = this.structure.getMax();
|
const max = this.structure.getMax();
|
||||||
return {
|
return {
|
||||||
@@ -105,7 +105,7 @@ export class StructureInstance {
|
|||||||
|
|
||||||
getActiveBlocks() {
|
getActiveBlocks() {
|
||||||
if (!this.options.isEnabled)
|
if (!this.options.isEnabled)
|
||||||
throw new Error(`[StrucTool] Instance '${this.options.instanceName}' is not placed.`);
|
throw new Error(`[Construct] Instance '${this.options.instanceName}' is not placed.`);
|
||||||
if (this.hasLayerSelected())
|
if (this.hasLayerSelected())
|
||||||
return this.getLayerBlocks(this.getLayer());
|
return this.getLayerBlocks(this.getLayer());
|
||||||
return this.getAllBlocks();
|
return this.getAllBlocks();
|
||||||
@@ -126,7 +126,7 @@ export class StructureInstance {
|
|||||||
|
|
||||||
getAllActiveLocations() {
|
getAllActiveLocations() {
|
||||||
if (!this.options.isEnabled)
|
if (!this.options.isEnabled)
|
||||||
throw new Error(`[StrucTool] Instance '${this.options.instanceName}' is not placed.`);
|
throw new Error(`[Construct] Instance '${this.options.instanceName}' is not placed.`);
|
||||||
if (this.hasLayerSelected())
|
if (this.hasLayerSelected())
|
||||||
return this.structure.getLayerLocations(this.getLayer()-1);
|
return this.structure.getLayerLocations(this.getLayer()-1);
|
||||||
else
|
else
|
||||||
@@ -187,7 +187,7 @@ export class StructureInstance {
|
|||||||
|
|
||||||
setLayer(layer) {
|
setLayer(layer) {
|
||||||
if (layer < 0 || layer > this.getMaxLayer())
|
if (layer < 0 || layer > this.getMaxLayer())
|
||||||
throw new Error(`[StrucTool] Layer ${layer} is out of bounds.`);
|
throw new Error(`[Construct] Layer ${layer} is out of bounds.`);
|
||||||
this.options.setLayer(layer);
|
this.options.setLayer(layer);
|
||||||
this.refreshBox();
|
this.refreshBox();
|
||||||
}
|
}
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
export const InstanceEditButtons = Object.freeze({
|
export const InstanceButtons = Object.freeze({
|
||||||
Unknown: 'Unknown',
|
Unknown: 'Unknown',
|
||||||
MainMenu: '<<',
|
MainMenu: '<<',
|
||||||
Place: '§aPlace Instance',
|
Place: '§aPlace Instance',
|
||||||
@@ -6,9 +6,9 @@ import { MenuForm } from '../classes/MenuForm';
|
|||||||
const ACTION_ITEM = 'minecraft:paper';
|
const ACTION_ITEM = 'minecraft:paper';
|
||||||
|
|
||||||
const menuCmd = new Command({
|
const menuCmd = new Command({
|
||||||
name: 'structool',
|
name: 'construct',
|
||||||
description: { text: 'Opens the StrucTool Menu. Using a paper will also open the menu.' },
|
description: { text: 'Opens the Construct Menu. Using a paper will also open the menu.' },
|
||||||
usage: 'structool',
|
usage: 'construct',
|
||||||
callback: (sender) => openMenu(sender)
|
callback: (sender) => openMenu(sender)
|
||||||
});
|
});
|
||||||
extension.addCommand(menuCmd);
|
extension.addCommand(menuCmd);
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { CanopyExtension } from './lib/canopy/CanopyExtension';
|
|||||||
|
|
||||||
export const extension = new CanopyExtension({
|
export const extension = new CanopyExtension({
|
||||||
author: 'ForestOfLight',
|
author: 'ForestOfLight',
|
||||||
name: 'StrucTool',
|
name: 'Construct',
|
||||||
description: 'Survival building extension for §l§aCanopy§r!',
|
description: 'Make building structures in survival easier!',
|
||||||
version: '1.0.0'
|
version: '1.0.0'
|
||||||
});
|
});
|
||||||
@@ -1,76 +0,0 @@
|
|||||||
/**
|
|
||||||
* @license
|
|
||||||
* MIT License
|
|
||||||
*
|
|
||||||
* Copyright (c) 2024 ForestOfLight
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in all
|
|
||||||
* copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
* SOFTWARE.
|
|
||||||
*/
|
|
||||||
import { world } from '@minecraft/server';
|
|
||||||
|
|
||||||
class Rule {
|
|
||||||
#identifier;
|
|
||||||
#description;
|
|
||||||
#contingentRules;
|
|
||||||
#independentRules;
|
|
||||||
|
|
||||||
constructor({ identifier, description, contingentRules = [], independentRules = [], onEnableCallback = () => {}, onDisableCallback = () => {} }) {
|
|
||||||
this.#identifier = identifier;
|
|
||||||
this.#description = description;
|
|
||||||
this.#contingentRules = contingentRules;
|
|
||||||
this.#independentRules = independentRules;
|
|
||||||
this.onEnable = onEnableCallback;
|
|
||||||
this.onDisable = onDisableCallback;
|
|
||||||
}
|
|
||||||
|
|
||||||
getID() {
|
|
||||||
return this.#identifier;
|
|
||||||
}
|
|
||||||
|
|
||||||
getDescription() {
|
|
||||||
return this.#description;
|
|
||||||
}
|
|
||||||
|
|
||||||
getContigentRules() {
|
|
||||||
return this.#contingentRules;
|
|
||||||
}
|
|
||||||
|
|
||||||
getIndependentRules() {
|
|
||||||
return this.#independentRules;
|
|
||||||
}
|
|
||||||
|
|
||||||
getValue() {
|
|
||||||
const value = world.getDynamicProperty(this.#identifier);
|
|
||||||
if (String(value) === 'true')
|
|
||||||
return true;
|
|
||||||
if (['false', 'undefined'].includes(String(value)))
|
|
||||||
return false;
|
|
||||||
throw new Error(`Rule ${this.#identifier} has an invalid value: ${value} (${typeof value})`);
|
|
||||||
}
|
|
||||||
|
|
||||||
setValue(value) {
|
|
||||||
if (value === true)
|
|
||||||
this.onEnable();
|
|
||||||
else
|
|
||||||
this.onDisable();
|
|
||||||
world.setDynamicProperty(this.#identifier, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default Rule;
|
|
||||||
+6
-6
@@ -1,5 +1,4 @@
|
|||||||
import { Rule } from '../lib/canopy/CanopyExtension';
|
import { BuilderOption } from '../classes/Builder/BuilderOption';
|
||||||
import { extension } from '../config';
|
|
||||||
import { BlockPermutation, EntityComponentTypes, GameMode, ItemStack, system, world } from '@minecraft/server';
|
import { BlockPermutation, EntityComponentTypes, GameMode, ItemStack, system, world } from '@minecraft/server';
|
||||||
import { structureCollection } from '../classes/StructureCollection';
|
import { structureCollection } from '../classes/StructureCollection';
|
||||||
import { bannedBlocks, bannedToValidBlockMap, whitelistedBlockStates, resetToBlockStates, bannedDimensionBlocks, specialItemPlacementConversions,
|
import { bannedBlocks, bannedToValidBlockMap, whitelistedBlockStates, resetToBlockStates, bannedDimensionBlocks, specialItemPlacementConversions,
|
||||||
@@ -8,13 +7,14 @@ import { fetchMatchingItemSlot } from '../utils';
|
|||||||
|
|
||||||
const ACTION_SLOT = 35;
|
const ACTION_SLOT = 35;
|
||||||
|
|
||||||
const easyPlace = new Rule({
|
new BuilderOption({
|
||||||
identifier: 'easyPlace',
|
identifier: 'easyPlace',
|
||||||
description: { text: "Automatically places the correct block in a structure (paper named 'easyPlace' in bottom right inventory slot)." },
|
displayName: 'Easy Place',
|
||||||
|
description: 'Always place the correct block.',
|
||||||
|
howToUse: "Place blocks in a structure with a paper named 'Easy Place' in the bottom right slot of your inventory to always place the correct block.",
|
||||||
onEnableCallback: () => { world.beforeEvents.playerPlaceBlock.subscribe(onPlayerPlaceBlock); },
|
onEnableCallback: () => { world.beforeEvents.playerPlaceBlock.subscribe(onPlayerPlaceBlock); },
|
||||||
onDisableCallback: () => { world.beforeEvents.playerPlaceBlock.unsubscribe(onPlayerPlaceBlock); }
|
onDisableCallback: () => { world.beforeEvents.playerPlaceBlock.unsubscribe(onPlayerPlaceBlock); }
|
||||||
})
|
})
|
||||||
extension.addRule(easyPlace);
|
|
||||||
|
|
||||||
function onPlayerPlaceBlock(event) {
|
function onPlayerPlaceBlock(event) {
|
||||||
const { player, block, permutationBeingPlaced } = event;
|
const { player, block, permutationBeingPlaced } = event;
|
||||||
@@ -30,7 +30,7 @@ function hasActionItemInCorrectSlot(player) {
|
|||||||
if (!inventory)
|
if (!inventory)
|
||||||
return false;
|
return false;
|
||||||
const actionSlot = inventory.getSlot(ACTION_SLOT);
|
const actionSlot = inventory.getSlot(ACTION_SLOT);
|
||||||
return actionSlot.hasItem() && actionSlot.typeId === 'minecraft:paper' && actionSlot.nameTag === 'easyPlace';
|
return actionSlot.hasItem() && actionSlot.typeId === 'minecraft:paper' && actionSlot.nameTag === 'Easy Place';
|
||||||
}
|
}
|
||||||
|
|
||||||
function tryPlaceBlock(event, player, block, structureBlock) {
|
function tryPlaceBlock(event, player, block, structureBlock) {
|
||||||
+6
-6
@@ -1,18 +1,18 @@
|
|||||||
import { Rule } from '../lib/canopy/CanopyExtension';
|
import { BuilderOption } from '../classes/Builder/BuilderOption';
|
||||||
import { extension } from '../config';
|
|
||||||
import { BlockPermutation, EntityComponentTypes, EquipmentSlot, GameMode, ItemStack, system, world } from '@minecraft/server';
|
import { BlockPermutation, EntityComponentTypes, EquipmentSlot, GameMode, ItemStack, system, world } from '@minecraft/server';
|
||||||
import { bannedBlocks, bannedToValidBlockMap, whitelistedBlockStates, resetToBlockStates, bannedDimensionBlocks, specialItemPlacementConversions,
|
import { bannedBlocks, bannedToValidBlockMap, whitelistedBlockStates, resetToBlockStates, bannedDimensionBlocks, specialItemPlacementConversions,
|
||||||
blockIdToItemStackMap } from '../data';
|
blockIdToItemStackMap } from '../data';
|
||||||
import { Raycaster } from '../classes/Raycaster';
|
import { Raycaster } from '../classes/Raycaster';
|
||||||
|
|
||||||
let runner = void 0;
|
let runner = void 0;
|
||||||
const easyPlace = new Rule({
|
new BuilderOption({
|
||||||
identifier: 'fastEasyPlace',
|
identifier: 'fastEasyPlace',
|
||||||
description: { text: "Looking at a structure block with a paper named 'easyPlace' in your hand will place it." },
|
displayName: 'Fast Easy Place',
|
||||||
|
description: 'Place structure blocks just by looking at them.',
|
||||||
|
howToUse: "Look at structure blocks with a paper named 'Easy Place' in your hand to place them.",
|
||||||
onEnableCallback: () => { runner = system.runInterval(onTick, 2); },
|
onEnableCallback: () => { runner = system.runInterval(onTick, 2); },
|
||||||
onDisableCallback: () => { system.clearRun(runner); }
|
onDisableCallback: () => { system.clearRun(runner); }
|
||||||
})
|
})
|
||||||
extension.addRule(easyPlace);
|
|
||||||
|
|
||||||
function onTick() {
|
function onTick() {
|
||||||
for (const player of world.getAllPlayers()) {
|
for (const player of world.getAllPlayers()) {
|
||||||
@@ -35,7 +35,7 @@ function isHoldingActionItem(player) {
|
|||||||
const mainhandItemStack = player.getComponent(EntityComponentTypes.Equippable).getEquipment(EquipmentSlot.Mainhand);
|
const mainhandItemStack = player.getComponent(EntityComponentTypes.Equippable).getEquipment(EquipmentSlot.Mainhand);
|
||||||
if (!mainhandItemStack)
|
if (!mainhandItemStack)
|
||||||
return false;
|
return false;
|
||||||
return mainhandItemStack.typeId === 'minecraft:paper' && mainhandItemStack.nameTag === 'easyPlace';
|
return mainhandItemStack.typeId === 'minecraft:paper' && mainhandItemStack.nameTag === 'Easy Place';
|
||||||
}
|
}
|
||||||
|
|
||||||
function tryPlaceBlock(player, worldBlock, structureBlock) {
|
function tryPlaceBlock(player, worldBlock, structureBlock) {
|
||||||
+5
-5
@@ -1,10 +1,11 @@
|
|||||||
import { Rule } from '../lib/canopy/CanopyExtension';
|
import { BuilderOption } from '../classes/Builder/BuilderOption';
|
||||||
import { extension } from '../config';
|
|
||||||
import { world } from '@minecraft/server';
|
import { world } from '@minecraft/server';
|
||||||
|
|
||||||
const easyPlace = new Rule({
|
new BuilderOption({
|
||||||
identifier: 'materialGrabber',
|
identifier: 'materialGrabber',
|
||||||
description: { text: "Automatically grabs structure materials out of inventories. Use a paper named 'materialGrabber' to get started." },
|
displayName: 'Material Grabber',
|
||||||
|
description: 'Pulls structure items from inventories.',
|
||||||
|
howToUse: "Interact with inventories using a paper named 'Material Grabber' to pull structure items from them.",
|
||||||
onEnableCallback: () => {
|
onEnableCallback: () => {
|
||||||
world.beforeEvents.playerInteractWithBlock.subscribe(onPlayerInteract);
|
world.beforeEvents.playerInteractWithBlock.subscribe(onPlayerInteract);
|
||||||
world.beforeEvents.playerInteractWithEntity.subscribe(onPlayerInteract);
|
world.beforeEvents.playerInteractWithEntity.subscribe(onPlayerInteract);
|
||||||
@@ -14,7 +15,6 @@ const easyPlace = new Rule({
|
|||||||
world.beforeEvents.playerInteractWithEntity.unsubscribe(onPlayerInteract);
|
world.beforeEvents.playerInteractWithEntity.unsubscribe(onPlayerInteract);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
extension.addRule(easyPlace);
|
|
||||||
|
|
||||||
function onPlayerInteract(event) {
|
function onPlayerInteract(event) {
|
||||||
// get inventory
|
// get inventory
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"format_version": 2,
|
"format_version": 2,
|
||||||
"header": {
|
"header": {
|
||||||
"name": "StrucTool [RP] v1.0.0",
|
"name": "Construct [RP] v1.0.0",
|
||||||
"description": "Survival building extension for §l§aCanopy§r by §aForestOfLight§r.",
|
"description": "Survival building extension for §l§aCanopy§r by §aForestOfLight§r.",
|
||||||
"uuid": "375ec465-3dc1-429f-8b4c-a337889e1ed4",
|
"uuid": "375ec465-3dc1-429f-8b4c-a337889e1ed4",
|
||||||
"version": [1, 0, 0],
|
"version": [1, 0, 0],
|
||||||
@@ -16,7 +16,7 @@
|
|||||||
],
|
],
|
||||||
"dependencies": [
|
"dependencies": [
|
||||||
{
|
{
|
||||||
"uuid": "8c0c0153-d8b9-482a-889f-aef922b8fe58", // StrucTool BP
|
"uuid": "8c0c0153-d8b9-482a-889f-aef922b8fe58", // Construct BP
|
||||||
"version": [1, 0, 0]
|
"version": [1, 0, 0]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
"format_version": "1.10.0",
|
"format_version": "1.10.0",
|
||||||
"particle_effect": {
|
"particle_effect": {
|
||||||
"description": {
|
"description": {
|
||||||
"identifier": "structool:blockoverlay_xy",
|
"identifier": "construct:blockoverlay_xy",
|
||||||
"basic_render_parameters": {
|
"basic_render_parameters": {
|
||||||
"material": "particles_blend",
|
"material": "particles_blend",
|
||||||
"texture": "textures/particle/white"
|
"texture": "textures/particle/white"
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
"format_version": "1.10.0",
|
"format_version": "1.10.0",
|
||||||
"particle_effect": {
|
"particle_effect": {
|
||||||
"description": {
|
"description": {
|
||||||
"identifier": "structool:blockoverlay_xz",
|
"identifier": "construct:blockoverlay_xz",
|
||||||
"basic_render_parameters": {
|
"basic_render_parameters": {
|
||||||
"material": "particles_blend",
|
"material": "particles_blend",
|
||||||
"texture": "textures/particle/white"
|
"texture": "textures/particle/white"
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
"format_version": "1.10.0",
|
"format_version": "1.10.0",
|
||||||
"particle_effect": {
|
"particle_effect": {
|
||||||
"description": {
|
"description": {
|
||||||
"identifier": "structool:blockoverlay_yz",
|
"identifier": "construct:blockoverlay_yz",
|
||||||
"basic_render_parameters": {
|
"basic_render_parameters": {
|
||||||
"material": "particles_blend",
|
"material": "particles_blend",
|
||||||
"texture": "textures/particle/white"
|
"texture": "textures/particle/white"
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
"format_version": "1.10.0",
|
"format_version": "1.10.0",
|
||||||
"particle_effect": {
|
"particle_effect": {
|
||||||
"description": {
|
"description": {
|
||||||
"identifier": "structool:outline",
|
"identifier": "construct:outline",
|
||||||
"basic_render_parameters": {
|
"basic_render_parameters": {
|
||||||
"material": "particles_alpha",
|
"material": "particles_alpha",
|
||||||
"texture": "textures/particle/particles"
|
"texture": "textures/particle/particles"
|
||||||
|
|||||||
Reference in New Issue
Block a user