From 0d14bde5839887990236966bd5f09d46841c373f Mon Sep 17 00:00:00 2001 From: Brady Date: Wed, 7 Jun 2023 16:31:52 -0500 Subject: [PATCH 01/10] Working sphere/cylinder build commands for `#sel` --- .../api/schematic/CylinderSchematic.java | 50 ++++++++++++++++ .../api/schematic/SphereSchematic.java | 54 ++++++++++++++++++ .../baritone/command/defaults/SelCommand.java | 57 +++++++++++++++---- 3 files changed, 151 insertions(+), 10 deletions(-) create mode 100644 src/api/java/baritone/api/schematic/CylinderSchematic.java create mode 100644 src/api/java/baritone/api/schematic/SphereSchematic.java diff --git a/src/api/java/baritone/api/schematic/CylinderSchematic.java b/src/api/java/baritone/api/schematic/CylinderSchematic.java new file mode 100644 index 000000000..3ba8bc9b8 --- /dev/null +++ b/src/api/java/baritone/api/schematic/CylinderSchematic.java @@ -0,0 +1,50 @@ +/* + * This file is part of Baritone. + * + * Baritone is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Baritone is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Baritone. If not, see . + */ + +package baritone.api.schematic; + +import net.minecraft.block.state.IBlockState; + +/** + * @author Brady + */ +public class CylinderSchematic extends MaskSchematic { + + private final double cx, cz, rx, rz; + private final boolean filled; + + public CylinderSchematic(ISchematic schematic, boolean filled) { + super(schematic); + this.cx = schematic.widthX() / 2.0; + this.cz = schematic.lengthZ() / 2.0; + this.rx = this.cx * this.cx; + this.rz = this.cz * this.cz; + this.filled = filled; + } + + @Override + protected boolean partOfMask(int x, int y, int z, IBlockState currentState) { + double dx = Math.abs((x + 0.5) - this.cx); + double dz = Math.abs((z + 0.5) - this.cz); + return !this.outside(dx, dz) + && (this.filled || outside(dx + 1, dz) || outside(dx, dz + 1)); + } + + private boolean outside(double dx, double dz) { + return dx * dx / this.rx + dz * dz / this.rz > 1; + } +} diff --git a/src/api/java/baritone/api/schematic/SphereSchematic.java b/src/api/java/baritone/api/schematic/SphereSchematic.java new file mode 100644 index 000000000..0ca987760 --- /dev/null +++ b/src/api/java/baritone/api/schematic/SphereSchematic.java @@ -0,0 +1,54 @@ +/* + * This file is part of Baritone. + * + * Baritone is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Baritone is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Baritone. If not, see . + */ + +package baritone.api.schematic; + +import net.minecraft.block.state.IBlockState; +import net.minecraft.util.math.Vec3d; + +/** + * @author Brady + */ +public class SphereSchematic extends MaskSchematic { + + private final double cx, cy, cz, rx, ry, rz; + private final boolean filled; + + public SphereSchematic(ISchematic schematic, boolean filled) { + super(schematic); + this.cx = schematic.widthX() / 2.0; + this.cy = schematic.heightY() / 2.0; + this.cz = schematic.lengthZ() / 2.0; + this.rx = this.cx * this.cx; + this.ry = this.cy * this.cy; + this.rz = this.cz * this.cz; + this.filled = filled; + } + + @Override + protected boolean partOfMask(int x, int y, int z, IBlockState currentState) { + double dx = Math.abs((x + 0.5) - this.cx); + double dy = Math.abs((y + 0.5) - this.cy); + double dz = Math.abs((z + 0.5) - this.cz); + return !this.outside(dx, dy, dz) + && (this.filled || outside(dx + 1, dy, dz) || outside(dx, dy + 1, dz) || outside(dx, dy, dz + 1)); + } + + private boolean outside(double dx,double dy, double dz) { + return dx * dx / this.rx + dy * dy / this.ry + dz * dz / this.rz > 1; + } +} diff --git a/src/main/java/baritone/command/defaults/SelCommand.java b/src/main/java/baritone/command/defaults/SelCommand.java index 5677eec3c..dcdd05b74 100644 --- a/src/main/java/baritone/command/defaults/SelCommand.java +++ b/src/main/java/baritone/command/defaults/SelCommand.java @@ -117,7 +117,7 @@ public class SelCommand extends Command { logDirect("Undid pos2"); } } - } else if (action == Action.SET || action == Action.WALLS || action == Action.SHELL || action == Action.CLEARAREA || action == Action.REPLACE) { + } else if (action.isFillAction()) { BlockOptionalMeta type = action == Action.CLEARAREA ? new BlockOptionalMeta(Blocks.AIR) : args.getDatatypeFor(ForBlockOptionalMeta.INSTANCE); @@ -151,14 +151,10 @@ public class SelCommand extends Command { for (ISelection selection : selections) { Vec3i size = selection.size(); BetterBlockPos min = selection.min(); - ISchematic schematic = new FillSchematic(size.getX(), size.getY(), size.getZ(), type); - if (action == Action.WALLS) { - schematic = new WallsSchematic(schematic); - } else if (action == Action.SHELL) { - schematic = new ShellSchematic(schematic); - } else if (action == Action.REPLACE) { - schematic = new ReplaceSchematic(schematic, replaces); - } + ISchematic schematic = action.createFillMask( + new FillSchematic(size.getX(), size.getY(), size.getZ(), type), + replaces + ); composite.put(schematic, min.x - origin.x, min.y - origin.y, min.z - origin.z); } baritone.getBuilderProcess().build("Fill", composite, origin); @@ -254,7 +250,7 @@ public class SelCommand extends Command { if (args.hasAtMost(3)) { return args.tabCompleteDatatype(RelativeBlockPos.INSTANCE); } - } else if (action == Action.SET || action == Action.WALLS || action == Action.CLEARAREA || action == Action.REPLACE) { + } else if (action.isFillAction()) { if (args.hasExactlyOne() || action == Action.REPLACE) { while (args.has(2)) { args.get(); @@ -305,6 +301,10 @@ public class SelCommand extends Command { "> sel set/fill/s/f [block] - Completely fill all selections with a block.", "> sel walls/w [block] - Fill in the walls of the selection with a specified block.", "> sel shell/shl [block] - The same as walls, but fills in a ceiling and floor too.", + "> sel sphere/sph [block] - Fills the selection with a sphere bounded by the sides.", + "> sel hsphere/hsph [block] - The same as sphere, but hollow.", + "> sel cylinder/cyl [block] - Fills the selection with a cylinder bounded by the sides.", + "> sel hcylinder/hcyl [block] - The same as cylinder, but hollow.", "> sel cleararea/ca - Basically 'set air'.", "> sel replace/r - Replaces blocks with another block.", "> sel copy/cp - Copy the selected area relative to the specified or your position.", @@ -324,6 +324,10 @@ public class SelCommand extends Command { SET("set", "fill", "s", "f"), WALLS("walls", "w"), SHELL("shell", "shl"), + SPHERE("sphere", "sph"), + HSPHERE("hsphere", "hsph"), + CYLINDER("cylinder", "cyl"), + HCYLINDER("hcylinder", "hcyl"), CLEARAREA("cleararea", "ca"), REPLACE("replace", "r"), EXPAND("expand", "ex"), @@ -355,6 +359,39 @@ public class SelCommand extends Command { } return names.toArray(new String[0]); } + + public final boolean isFillAction() { + return this == SET + || this == WALLS + || this == SHELL + || this == SPHERE + || this == HSPHERE + || this == CYLINDER + || this == HCYLINDER + || this == CLEARAREA + || this == REPLACE; + } + + public final ISchematic createFillMask(ISchematic fill, BlockOptionalMetaLookup replaces) { + switch (this) { + case WALLS: + return new WallsSchematic(fill); + case SHELL: + return new ShellSchematic(fill); + case REPLACE: + return new ReplaceSchematic(fill, replaces); + case SPHERE: + return new SphereSchematic(fill, true); + case HSPHERE: + return new SphereSchematic(fill, false); + case CYLINDER: + return new CylinderSchematic(fill, true); + case HCYLINDER: + return new CylinderSchematic(fill, false); + } + // Silent fail + return fill; + } } enum TransformTarget { From 34abbfb5daced3623e9a2a17da8018042980d758 Mon Sep 17 00:00:00 2001 From: Brady Date: Wed, 7 Jun 2023 17:38:26 -0500 Subject: [PATCH 02/10] appease codacy --- .../api/schematic/CylinderSchematic.java | 19 +++++++------ .../api/schematic/SphereSchematic.java | 28 +++++++++++-------- .../baritone/command/defaults/SelCommand.java | 5 ++-- 3 files changed, 30 insertions(+), 22 deletions(-) diff --git a/src/api/java/baritone/api/schematic/CylinderSchematic.java b/src/api/java/baritone/api/schematic/CylinderSchematic.java index 3ba8bc9b8..75726348d 100644 --- a/src/api/java/baritone/api/schematic/CylinderSchematic.java +++ b/src/api/java/baritone/api/schematic/CylinderSchematic.java @@ -24,27 +24,30 @@ import net.minecraft.block.state.IBlockState; */ public class CylinderSchematic extends MaskSchematic { - private final double cx, cz, rx, rz; + private final double centerX; + private final double centerZ; + private final double radiusSqX; + private final double radiusSqZ; private final boolean filled; public CylinderSchematic(ISchematic schematic, boolean filled) { super(schematic); - this.cx = schematic.widthX() / 2.0; - this.cz = schematic.lengthZ() / 2.0; - this.rx = this.cx * this.cx; - this.rz = this.cz * this.cz; + this.centerX = schematic.widthX() / 2.0; + this.centerZ = schematic.lengthZ() / 2.0; + this.radiusSqX = this.centerX * this.centerX; + this.radiusSqZ = this.centerZ * this.centerZ; this.filled = filled; } @Override protected boolean partOfMask(int x, int y, int z, IBlockState currentState) { - double dx = Math.abs((x + 0.5) - this.cx); - double dz = Math.abs((z + 0.5) - this.cz); + double dx = Math.abs((x + 0.5) - this.centerX); + double dz = Math.abs((z + 0.5) - this.centerZ); return !this.outside(dx, dz) && (this.filled || outside(dx + 1, dz) || outside(dx, dz + 1)); } private boolean outside(double dx, double dz) { - return dx * dx / this.rx + dz * dz / this.rz > 1; + return dx * dx / this.radiusSqX + dz * dz / this.radiusSqZ > 1; } } diff --git a/src/api/java/baritone/api/schematic/SphereSchematic.java b/src/api/java/baritone/api/schematic/SphereSchematic.java index 0ca987760..1cf0a579f 100644 --- a/src/api/java/baritone/api/schematic/SphereSchematic.java +++ b/src/api/java/baritone/api/schematic/SphereSchematic.java @@ -18,37 +18,41 @@ package baritone.api.schematic; import net.minecraft.block.state.IBlockState; -import net.minecraft.util.math.Vec3d; /** * @author Brady */ public class SphereSchematic extends MaskSchematic { - private final double cx, cy, cz, rx, ry, rz; + private final double centerX; + private final double centerY; + private final double centerZ; + private final double radiusSqX; + private final double radiusSqY; + private final double radiusSqZ; private final boolean filled; public SphereSchematic(ISchematic schematic, boolean filled) { super(schematic); - this.cx = schematic.widthX() / 2.0; - this.cy = schematic.heightY() / 2.0; - this.cz = schematic.lengthZ() / 2.0; - this.rx = this.cx * this.cx; - this.ry = this.cy * this.cy; - this.rz = this.cz * this.cz; + this.centerX = schematic.widthX() / 2.0; + this.centerY = schematic.heightY() / 2.0; + this.centerZ = schematic.lengthZ() / 2.0; + this.radiusSqX = this.centerX * this.centerX; + this.radiusSqY = this.centerY * this.centerY; + this.radiusSqZ = this.centerZ * this.centerZ; this.filled = filled; } @Override protected boolean partOfMask(int x, int y, int z, IBlockState currentState) { - double dx = Math.abs((x + 0.5) - this.cx); - double dy = Math.abs((y + 0.5) - this.cy); - double dz = Math.abs((z + 0.5) - this.cz); + double dx = Math.abs((x + 0.5) - this.centerX); + double dy = Math.abs((y + 0.5) - this.centerY); + double dz = Math.abs((z + 0.5) - this.centerZ); return !this.outside(dx, dy, dz) && (this.filled || outside(dx + 1, dy, dz) || outside(dx, dy + 1, dz) || outside(dx, dy, dz + 1)); } private boolean outside(double dx,double dy, double dz) { - return dx * dx / this.rx + dy * dy / this.ry + dz * dz / this.rz > 1; + return dx * dx / this.radiusSqX + dy * dy / this.radiusSqY + dz * dz / this.radiusSqZ > 1; } } diff --git a/src/main/java/baritone/command/defaults/SelCommand.java b/src/main/java/baritone/command/defaults/SelCommand.java index dcdd05b74..40df5c294 100644 --- a/src/main/java/baritone/command/defaults/SelCommand.java +++ b/src/main/java/baritone/command/defaults/SelCommand.java @@ -388,9 +388,10 @@ public class SelCommand extends Command { return new CylinderSchematic(fill, true); case HCYLINDER: return new CylinderSchematic(fill, false); + default: + // Silent fail + return fill; } - // Silent fail - return fill; } } From b6c52cd8e1fd567afdefe428876f7ed0c2a7a4e4 Mon Sep 17 00:00:00 2001 From: Brady Date: Thu, 8 Jun 2023 11:52:13 -0500 Subject: [PATCH 03/10] Cache mask in a `boolean[][][]` --- .../api/schematic/CachedMaskSchematic.java | 53 +++++++++++++++++++ .../api/schematic/CylinderSchematic.java | 43 +++++++-------- .../api/schematic/SphereSchematic.java | 51 ++++++++---------- 3 files changed, 92 insertions(+), 55 deletions(-) create mode 100644 src/api/java/baritone/api/schematic/CachedMaskSchematic.java diff --git a/src/api/java/baritone/api/schematic/CachedMaskSchematic.java b/src/api/java/baritone/api/schematic/CachedMaskSchematic.java new file mode 100644 index 000000000..19bcf4e3a --- /dev/null +++ b/src/api/java/baritone/api/schematic/CachedMaskSchematic.java @@ -0,0 +1,53 @@ +/* + * This file is part of Baritone. + * + * Baritone is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Baritone is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Baritone. If not, see . + */ + +package baritone.api.schematic; + +import net.minecraft.block.state.IBlockState; + +/** + * @author Brady + */ +public abstract class CachedMaskSchematic extends MaskSchematic { + + /** + * Mask array with {@code y,z,x} indexing + */ + private final boolean[][][] mask; + + public CachedMaskSchematic(ISchematic schematic, StaticMaskFunction maskFunction) { + super(schematic); + this.mask = new boolean[schematic.heightY()][schematic.lengthZ()][schematic.widthX()]; + for (int y = 0; y < schematic.heightY(); y++) { + for (int z = 0; z < schematic.lengthZ(); z++) { + for (int x = 0; x < schematic.widthX(); x++) { + this.mask[y][z][x] = maskFunction.partOfMask(x, y, z); + } + } + } + } + + @Override + protected final boolean partOfMask(int x, int y, int z, IBlockState currentState) { + return this.mask[y][z][x]; + } + + @FunctionalInterface + public interface StaticMaskFunction { + boolean partOfMask(int x, int y, int z); + } +} diff --git a/src/api/java/baritone/api/schematic/CylinderSchematic.java b/src/api/java/baritone/api/schematic/CylinderSchematic.java index 75726348d..055f12875 100644 --- a/src/api/java/baritone/api/schematic/CylinderSchematic.java +++ b/src/api/java/baritone/api/schematic/CylinderSchematic.java @@ -17,37 +17,30 @@ package baritone.api.schematic; -import net.minecraft.block.state.IBlockState; - /** * @author Brady */ -public class CylinderSchematic extends MaskSchematic { - - private final double centerX; - private final double centerZ; - private final double radiusSqX; - private final double radiusSqZ; - private final boolean filled; +public final class CylinderSchematic extends CachedMaskSchematic { public CylinderSchematic(ISchematic schematic, boolean filled) { - super(schematic); - this.centerX = schematic.widthX() / 2.0; - this.centerZ = schematic.lengthZ() / 2.0; - this.radiusSqX = this.centerX * this.centerX; - this.radiusSqZ = this.centerZ * this.centerZ; - this.filled = filled; - } + super(schematic, new StaticMaskFunction() { - @Override - protected boolean partOfMask(int x, int y, int z, IBlockState currentState) { - double dx = Math.abs((x + 0.5) - this.centerX); - double dz = Math.abs((z + 0.5) - this.centerZ); - return !this.outside(dx, dz) - && (this.filled || outside(dx + 1, dz) || outside(dx, dz + 1)); - } + private final double centerX = schematic.widthX() / 2.0; + private final double centerZ = schematic.lengthZ() / 2.0; + private final double radiusSqX = this.centerX * this.centerX; + private final double radiusSqZ = this.centerZ * this.centerZ; - private boolean outside(double dx, double dz) { - return dx * dx / this.radiusSqX + dz * dz / this.radiusSqZ > 1; + @Override + public boolean partOfMask(int x, int y, int z) { + double dx = Math.abs((x + 0.5) - this.centerX); + double dz = Math.abs((z + 0.5) - this.centerZ); + return !this.outside(dx, dz) + && (filled || outside(dx + 1, dz) || outside(dx, dz + 1)); + } + + private boolean outside(double dx, double dz) { + return dx * dx / this.radiusSqX + dz * dz / this.radiusSqZ > 1; + } + }); } } diff --git a/src/api/java/baritone/api/schematic/SphereSchematic.java b/src/api/java/baritone/api/schematic/SphereSchematic.java index 1cf0a579f..987b87198 100644 --- a/src/api/java/baritone/api/schematic/SphereSchematic.java +++ b/src/api/java/baritone/api/schematic/SphereSchematic.java @@ -17,42 +17,33 @@ package baritone.api.schematic; -import net.minecraft.block.state.IBlockState; - /** * @author Brady */ -public class SphereSchematic extends MaskSchematic { - - private final double centerX; - private final double centerY; - private final double centerZ; - private final double radiusSqX; - private final double radiusSqY; - private final double radiusSqZ; - private final boolean filled; +public final class SphereSchematic extends CachedMaskSchematic { public SphereSchematic(ISchematic schematic, boolean filled) { - super(schematic); - this.centerX = schematic.widthX() / 2.0; - this.centerY = schematic.heightY() / 2.0; - this.centerZ = schematic.lengthZ() / 2.0; - this.radiusSqX = this.centerX * this.centerX; - this.radiusSqY = this.centerY * this.centerY; - this.radiusSqZ = this.centerZ * this.centerZ; - this.filled = filled; - } + super(schematic, new StaticMaskFunction() { - @Override - protected boolean partOfMask(int x, int y, int z, IBlockState currentState) { - double dx = Math.abs((x + 0.5) - this.centerX); - double dy = Math.abs((y + 0.5) - this.centerY); - double dz = Math.abs((z + 0.5) - this.centerZ); - return !this.outside(dx, dy, dz) - && (this.filled || outside(dx + 1, dy, dz) || outside(dx, dy + 1, dz) || outside(dx, dy, dz + 1)); - } + private final double centerX = schematic.widthX() / 2.0; + private final double centerY = schematic.heightY() / 2.0; + private final double centerZ = schematic.lengthZ() / 2.0; + private final double radiusSqX = this.centerX * this.centerX; + private final double radiusSqY = this.centerY * this.centerY; + private final double radiusSqZ = this.centerZ * this.centerZ; - private boolean outside(double dx,double dy, double dz) { - return dx * dx / this.radiusSqX + dy * dy / this.radiusSqY + dz * dz / this.radiusSqZ > 1; + @Override + public boolean partOfMask(int x, int y, int z) { + double dx = Math.abs((x + 0.5) - this.centerX); + double dy = Math.abs((y + 0.5) - this.centerY); + double dz = Math.abs((z + 0.5) - this.centerZ); + return !this.outside(dx, dy, dz) + && (filled || outside(dx + 1, dy, dz) || outside(dx, dy + 1, dz) || outside(dx, dy, dz + 1)); + } + + private boolean outside(double dx,double dy, double dz) { + return dx * dx / this.radiusSqX + dy * dy / this.radiusSqY + dz * dz / this.radiusSqZ > 1; + } + }); } } From a1b1ef88cf4d83ca027e05e589fc46ff148be634 Mon Sep 17 00:00:00 2001 From: Brady Date: Thu, 8 Jun 2023 15:46:32 -0500 Subject: [PATCH 04/10] Use a Supplier to mimic a switch expression --- .../baritone/command/defaults/SelCommand.java | 55 ++++++++++--------- 1 file changed, 28 insertions(+), 27 deletions(-) diff --git a/src/main/java/baritone/command/defaults/SelCommand.java b/src/main/java/baritone/command/defaults/SelCommand.java index 40df5c294..85b3e4307 100644 --- a/src/main/java/baritone/command/defaults/SelCommand.java +++ b/src/main/java/baritone/command/defaults/SelCommand.java @@ -50,6 +50,7 @@ import java.awt.*; import java.util.List; import java.util.*; import java.util.function.Function; +import java.util.function.UnaryOperator; import java.util.stream.Stream; public class SelCommand extends Command { @@ -121,7 +122,7 @@ public class SelCommand extends Command { BlockOptionalMeta type = action == Action.CLEARAREA ? new BlockOptionalMeta(Blocks.AIR) : args.getDatatypeFor(ForBlockOptionalMeta.INSTANCE); - BlockOptionalMetaLookup replaces = null; + BlockOptionalMetaLookup replaces; if (action == Action.REPLACE) { args.requireMin(1); List replacesList = new ArrayList<>(); @@ -133,6 +134,7 @@ public class SelCommand extends Command { replaces = new BlockOptionalMetaLookup(replacesList.toArray(new BlockOptionalMeta[0])); } else { args.requireMax(0); + replaces = null; } ISelection[] selections = manager.getSelections(); if (selections.length == 0) { @@ -151,10 +153,31 @@ public class SelCommand extends Command { for (ISelection selection : selections) { Vec3i size = selection.size(); BetterBlockPos min = selection.min(); - ISchematic schematic = action.createFillMask( - new FillSchematic(size.getX(), size.getY(), size.getZ(), type), - replaces - ); + + // Java 8 so no switch expressions 😿 + UnaryOperator create = fill -> { + switch (action) { + case WALLS: + return new WallsSchematic(fill); + case SHELL: + return new ShellSchematic(fill); + case REPLACE: + return new ReplaceSchematic(fill, replaces); + case SPHERE: + return new SphereSchematic(fill, true); + case HSPHERE: + return new SphereSchematic(fill, false); + case CYLINDER: + return new CylinderSchematic(fill, true); + case HCYLINDER: + return new CylinderSchematic(fill, false); + default: + // Silent fail + return fill; + } + }; + + ISchematic schematic = create.apply(new FillSchematic(size.getX(), size.getY(), size.getZ(), type)); composite.put(schematic, min.x - origin.x, min.y - origin.y, min.z - origin.z); } baritone.getBuilderProcess().build("Fill", composite, origin); @@ -371,28 +394,6 @@ public class SelCommand extends Command { || this == CLEARAREA || this == REPLACE; } - - public final ISchematic createFillMask(ISchematic fill, BlockOptionalMetaLookup replaces) { - switch (this) { - case WALLS: - return new WallsSchematic(fill); - case SHELL: - return new ShellSchematic(fill); - case REPLACE: - return new ReplaceSchematic(fill, replaces); - case SPHERE: - return new SphereSchematic(fill, true); - case HSPHERE: - return new SphereSchematic(fill, false); - case CYLINDER: - return new CylinderSchematic(fill, true); - case HCYLINDER: - return new CylinderSchematic(fill, false); - default: - // Silent fail - return fill; - } - } } enum TransformTarget { From 26574b4a9b23a67d1555b8717a084bcca51503b8 Mon Sep 17 00:00:00 2001 From: Brady Date: Thu, 8 Jun 2023 16:32:33 -0500 Subject: [PATCH 05/10] Add optional axis parameter for `#sel cyl` --- .../api/command/datatypes/ForAxis.java | 43 +++++++++++++++++++ .../api/schematic/CylinderSchematic.java | 32 +++++++++----- .../baritone/command/defaults/SelCommand.java | 25 ++++++++--- 3 files changed, 84 insertions(+), 16 deletions(-) create mode 100644 src/api/java/baritone/api/command/datatypes/ForAxis.java diff --git a/src/api/java/baritone/api/command/datatypes/ForAxis.java b/src/api/java/baritone/api/command/datatypes/ForAxis.java new file mode 100644 index 000000000..48efb39b7 --- /dev/null +++ b/src/api/java/baritone/api/command/datatypes/ForAxis.java @@ -0,0 +1,43 @@ +/* + * This file is part of Baritone. + * + * Baritone is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Baritone is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Baritone. If not, see . + */ + +package baritone.api.command.datatypes; + +import baritone.api.command.exception.CommandException; +import baritone.api.command.helpers.TabCompleteHelper; +import net.minecraft.util.EnumFacing; + +import java.util.Locale; +import java.util.stream.Stream; + +public enum ForAxis implements IDatatypeFor { + INSTANCE; + + @Override + public EnumFacing.Axis get(IDatatypeContext ctx) throws CommandException { + return EnumFacing.Axis.valueOf(ctx.getConsumer().getString().toUpperCase(Locale.US)); + } + + @Override + public Stream tabComplete(IDatatypeContext ctx) throws CommandException { + return new TabCompleteHelper() + .append(Stream.of(EnumFacing.Axis.values()) + .map(EnumFacing.Axis::getName).map(String::toLowerCase)) + .filterPrefix(ctx.getConsumer().getString()) + .stream(); + } +} diff --git a/src/api/java/baritone/api/schematic/CylinderSchematic.java b/src/api/java/baritone/api/schematic/CylinderSchematic.java index 055f12875..342c6e373 100644 --- a/src/api/java/baritone/api/schematic/CylinderSchematic.java +++ b/src/api/java/baritone/api/schematic/CylinderSchematic.java @@ -17,29 +17,39 @@ package baritone.api.schematic; +import net.minecraft.util.EnumFacing; + /** * @author Brady */ public final class CylinderSchematic extends CachedMaskSchematic { - public CylinderSchematic(ISchematic schematic, boolean filled) { + public CylinderSchematic(ISchematic schematic, boolean filled, EnumFacing.Axis alignment) { super(schematic, new StaticMaskFunction() { - private final double centerX = schematic.widthX() / 2.0; - private final double centerZ = schematic.lengthZ() / 2.0; - private final double radiusSqX = this.centerX * this.centerX; - private final double radiusSqZ = this.centerZ * this.centerZ; + private final double centerA = this.getA(schematic.widthX(), schematic.heightY()) / 2.0; + private final double centerB = this.getB(schematic.heightY(), schematic.lengthZ()) / 2.0; + private final double radiusSqA = this.centerA * this.centerA; + private final double radiusSqB = this.centerB * this.centerB; @Override public boolean partOfMask(int x, int y, int z) { - double dx = Math.abs((x + 0.5) - this.centerX); - double dz = Math.abs((z + 0.5) - this.centerZ); - return !this.outside(dx, dz) - && (filled || outside(dx + 1, dz) || outside(dx, dz + 1)); + double da = Math.abs((this.getA(x, y) + 0.5) - this.centerA); + double db = Math.abs((this.getB(y, z) + 0.5) - this.centerB); + return !this.outside(da, db) + && (filled || outside(da + 1, db) || outside(da, db + 1)); } - private boolean outside(double dx, double dz) { - return dx * dx / this.radiusSqX + dz * dz / this.radiusSqZ > 1; + private boolean outside(double da, double db) { + return da * da / this.radiusSqA + db * db / this.radiusSqB > 1; + } + + private int getA(int x, int y) { + return alignment == EnumFacing.Axis.X ? y : x; + } + + private int getB(int y, int z) { + return alignment == EnumFacing.Axis.Z ? y : z; } }); } diff --git a/src/main/java/baritone/command/defaults/SelCommand.java b/src/main/java/baritone/command/defaults/SelCommand.java index 85b3e4307..72c5cd1c0 100644 --- a/src/main/java/baritone/command/defaults/SelCommand.java +++ b/src/main/java/baritone/command/defaults/SelCommand.java @@ -21,6 +21,7 @@ import baritone.Baritone; import baritone.api.IBaritone; import baritone.api.command.Command; import baritone.api.command.argument.IArgConsumer; +import baritone.api.command.datatypes.ForAxis; import baritone.api.command.datatypes.ForBlockOptionalMeta; import baritone.api.command.datatypes.ForEnumFacing; import baritone.api.command.datatypes.RelativeBlockPos; @@ -122,7 +123,9 @@ public class SelCommand extends Command { BlockOptionalMeta type = action == Action.CLEARAREA ? new BlockOptionalMeta(Blocks.AIR) : args.getDatatypeFor(ForBlockOptionalMeta.INSTANCE); - BlockOptionalMetaLookup replaces; + + final BlockOptionalMetaLookup replaces; // Action.REPLACE + final EnumFacing.Axis alignment; // Action.(H)CYLINDER if (action == Action.REPLACE) { args.requireMin(1); List replacesList = new ArrayList<>(); @@ -132,9 +135,15 @@ public class SelCommand extends Command { } type = args.getDatatypeFor(ForBlockOptionalMeta.INSTANCE); replaces = new BlockOptionalMetaLookup(replacesList.toArray(new BlockOptionalMeta[0])); + alignment = null; + } else if (action == Action.CYLINDER || action == Action.HCYLINDER) { + args.requireMax(1); + alignment = args.hasAny() ? args.getDatatypeFor(ForAxis.INSTANCE) : EnumFacing.Axis.Y; + replaces = null; } else { args.requireMax(0); replaces = null; + alignment = null; } ISelection[] selections = manager.getSelections(); if (selections.length == 0) { @@ -168,9 +177,9 @@ public class SelCommand extends Command { case HSPHERE: return new SphereSchematic(fill, false); case CYLINDER: - return new CylinderSchematic(fill, true); + return new CylinderSchematic(fill, true, alignment); case HCYLINDER: - return new CylinderSchematic(fill, false); + return new CylinderSchematic(fill, false, alignment); default: // Silent fail return fill; @@ -279,6 +288,12 @@ public class SelCommand extends Command { args.get(); } return args.tabCompleteDatatype(ForBlockOptionalMeta.INSTANCE); + } else if (action == Action.CYLINDER || action == Action.HCYLINDER) { + if (args.hasExactly(2)) { + if (args.getDatatypeForOrNull(ForBlockOptionalMeta.INSTANCE) != null) { + return args.tabCompleteDatatype(ForAxis.INSTANCE); + } + } } } else if (action == Action.EXPAND || action == Action.CONTRACT || action == Action.SHIFT) { if (args.hasExactlyOne()) { @@ -326,8 +341,8 @@ public class SelCommand extends Command { "> sel shell/shl [block] - The same as walls, but fills in a ceiling and floor too.", "> sel sphere/sph [block] - Fills the selection with a sphere bounded by the sides.", "> sel hsphere/hsph [block] - The same as sphere, but hollow.", - "> sel cylinder/cyl [block] - Fills the selection with a cylinder bounded by the sides.", - "> sel hcylinder/hcyl [block] - The same as cylinder, but hollow.", + "> sel cylinder/cyl [block] - Fills the selection with a cylinder bounded by the sides, oriented about the given axis. (default=y)", + "> sel hcylinder/hcyl [block] - The same as cylinder, but hollow.", "> sel cleararea/ca - Basically 'set air'.", "> sel replace/r - Replaces blocks with another block.", "> sel copy/cp - Copy the selected area relative to the specified or your position.", From f232bbdb15cb6a07296b1a093a1213794e051e25 Mon Sep 17 00:00:00 2001 From: Brady Date: Thu, 8 Jun 2023 16:36:32 -0500 Subject: [PATCH 06/10] Clean up formatting --- .../baritone/api/schematic/CylinderSchematic.java | 8 ++++++-- .../java/baritone/api/schematic/SphereSchematic.java | 11 ++++++++--- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/src/api/java/baritone/api/schematic/CylinderSchematic.java b/src/api/java/baritone/api/schematic/CylinderSchematic.java index 342c6e373..29b5aa5b3 100644 --- a/src/api/java/baritone/api/schematic/CylinderSchematic.java +++ b/src/api/java/baritone/api/schematic/CylinderSchematic.java @@ -36,8 +36,12 @@ public final class CylinderSchematic extends CachedMaskSchematic { public boolean partOfMask(int x, int y, int z) { double da = Math.abs((this.getA(x, y) + 0.5) - this.centerA); double db = Math.abs((this.getB(y, z) + 0.5) - this.centerB); - return !this.outside(da, db) - && (filled || outside(da + 1, db) || outside(da, db + 1)); + if (this.outside(da, db)) { + return false; + } + return filled + || this.outside(da + 1, db) + || this.outside(da, db + 1); } private boolean outside(double da, double db) { diff --git a/src/api/java/baritone/api/schematic/SphereSchematic.java b/src/api/java/baritone/api/schematic/SphereSchematic.java index 987b87198..074e6ec51 100644 --- a/src/api/java/baritone/api/schematic/SphereSchematic.java +++ b/src/api/java/baritone/api/schematic/SphereSchematic.java @@ -37,11 +37,16 @@ public final class SphereSchematic extends CachedMaskSchematic { double dx = Math.abs((x + 0.5) - this.centerX); double dy = Math.abs((y + 0.5) - this.centerY); double dz = Math.abs((z + 0.5) - this.centerZ); - return !this.outside(dx, dy, dz) - && (filled || outside(dx + 1, dy, dz) || outside(dx, dy + 1, dz) || outside(dx, dy, dz + 1)); + if (this.outside(dx, dy, dz)) { + return false; + } + return filled + || this.outside(dx + 1, dy, dz) + || this.outside(dx, dy + 1, dz) + || this.outside(dx, dy, dz + 1); } - private boolean outside(double dx,double dy, double dz) { + private boolean outside(double dx, double dy, double dz) { return dx * dx / this.radiusSqX + dy * dy / this.radiusSqY + dz * dz / this.radiusSqZ > 1; } }); From 9729e63d980ace7038f2a79f78805b1fa21cc6c9 Mon Sep 17 00:00:00 2001 From: Brady Date: Fri, 9 Jun 2023 17:25:29 -0500 Subject: [PATCH 07/10] Create and utilize new `Mask` type Added factory method to `MaskSchematic` for creation using a `Mask` Sort-of mocks the schematic structure, without the block states ofc --- .../api/schematic/CachedMaskSchematic.java | 53 -------------- .../api/schematic/CylinderSchematic.java | 60 ---------------- .../baritone/api/schematic/MaskSchematic.java | 11 +++ .../api/schematic/SphereSchematic.java | 54 --------------- .../api/schematic/mask/AbstractMask.java | 49 +++++++++++++ .../baritone/api/schematic/mask/Mask.java | 41 +++++++++++ .../api/schematic/mask/PreComputedMask.java | 44 ++++++++++++ .../api/schematic/mask/StaticMask.java | 62 +++++++++++++++++ .../schematic/mask/shape/CylinderMask.java | 69 +++++++++++++++++++ .../api/schematic/mask/shape/SphereMask.java | 64 +++++++++++++++++ .../baritone/command/defaults/SelCommand.java | 10 +-- 11 files changed, 346 insertions(+), 171 deletions(-) delete mode 100644 src/api/java/baritone/api/schematic/CachedMaskSchematic.java delete mode 100644 src/api/java/baritone/api/schematic/CylinderSchematic.java delete mode 100644 src/api/java/baritone/api/schematic/SphereSchematic.java create mode 100644 src/api/java/baritone/api/schematic/mask/AbstractMask.java create mode 100644 src/api/java/baritone/api/schematic/mask/Mask.java create mode 100644 src/api/java/baritone/api/schematic/mask/PreComputedMask.java create mode 100644 src/api/java/baritone/api/schematic/mask/StaticMask.java create mode 100644 src/api/java/baritone/api/schematic/mask/shape/CylinderMask.java create mode 100644 src/api/java/baritone/api/schematic/mask/shape/SphereMask.java diff --git a/src/api/java/baritone/api/schematic/CachedMaskSchematic.java b/src/api/java/baritone/api/schematic/CachedMaskSchematic.java deleted file mode 100644 index 19bcf4e3a..000000000 --- a/src/api/java/baritone/api/schematic/CachedMaskSchematic.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * This file is part of Baritone. - * - * Baritone is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Baritone is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Baritone. If not, see . - */ - -package baritone.api.schematic; - -import net.minecraft.block.state.IBlockState; - -/** - * @author Brady - */ -public abstract class CachedMaskSchematic extends MaskSchematic { - - /** - * Mask array with {@code y,z,x} indexing - */ - private final boolean[][][] mask; - - public CachedMaskSchematic(ISchematic schematic, StaticMaskFunction maskFunction) { - super(schematic); - this.mask = new boolean[schematic.heightY()][schematic.lengthZ()][schematic.widthX()]; - for (int y = 0; y < schematic.heightY(); y++) { - for (int z = 0; z < schematic.lengthZ(); z++) { - for (int x = 0; x < schematic.widthX(); x++) { - this.mask[y][z][x] = maskFunction.partOfMask(x, y, z); - } - } - } - } - - @Override - protected final boolean partOfMask(int x, int y, int z, IBlockState currentState) { - return this.mask[y][z][x]; - } - - @FunctionalInterface - public interface StaticMaskFunction { - boolean partOfMask(int x, int y, int z); - } -} diff --git a/src/api/java/baritone/api/schematic/CylinderSchematic.java b/src/api/java/baritone/api/schematic/CylinderSchematic.java deleted file mode 100644 index 29b5aa5b3..000000000 --- a/src/api/java/baritone/api/schematic/CylinderSchematic.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * This file is part of Baritone. - * - * Baritone is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Baritone is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Baritone. If not, see . - */ - -package baritone.api.schematic; - -import net.minecraft.util.EnumFacing; - -/** - * @author Brady - */ -public final class CylinderSchematic extends CachedMaskSchematic { - - public CylinderSchematic(ISchematic schematic, boolean filled, EnumFacing.Axis alignment) { - super(schematic, new StaticMaskFunction() { - - private final double centerA = this.getA(schematic.widthX(), schematic.heightY()) / 2.0; - private final double centerB = this.getB(schematic.heightY(), schematic.lengthZ()) / 2.0; - private final double radiusSqA = this.centerA * this.centerA; - private final double radiusSqB = this.centerB * this.centerB; - - @Override - public boolean partOfMask(int x, int y, int z) { - double da = Math.abs((this.getA(x, y) + 0.5) - this.centerA); - double db = Math.abs((this.getB(y, z) + 0.5) - this.centerB); - if (this.outside(da, db)) { - return false; - } - return filled - || this.outside(da + 1, db) - || this.outside(da, db + 1); - } - - private boolean outside(double da, double db) { - return da * da / this.radiusSqA + db * db / this.radiusSqB > 1; - } - - private int getA(int x, int y) { - return alignment == EnumFacing.Axis.X ? y : x; - } - - private int getB(int y, int z) { - return alignment == EnumFacing.Axis.Z ? y : z; - } - }); - } -} diff --git a/src/api/java/baritone/api/schematic/MaskSchematic.java b/src/api/java/baritone/api/schematic/MaskSchematic.java index 229f58d5b..2853c6e58 100644 --- a/src/api/java/baritone/api/schematic/MaskSchematic.java +++ b/src/api/java/baritone/api/schematic/MaskSchematic.java @@ -17,6 +17,7 @@ package baritone.api.schematic; +import baritone.api.schematic.mask.Mask; import net.minecraft.block.state.IBlockState; import java.util.List; @@ -41,4 +42,14 @@ public abstract class MaskSchematic extends AbstractSchematic { public IBlockState desiredState(int x, int y, int z, IBlockState current, List approxPlaceable) { return schematic.desiredState(x, y, z, current, approxPlaceable); } + + public static MaskSchematic create(ISchematic schematic, Mask function) { + return new MaskSchematic(schematic) { + + @Override + protected boolean partOfMask(int x, int y, int z, IBlockState currentState) { + return function.partOfMask(x, y, z, currentState); + } + }; + } } diff --git a/src/api/java/baritone/api/schematic/SphereSchematic.java b/src/api/java/baritone/api/schematic/SphereSchematic.java deleted file mode 100644 index 074e6ec51..000000000 --- a/src/api/java/baritone/api/schematic/SphereSchematic.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * This file is part of Baritone. - * - * Baritone is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Baritone is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Baritone. If not, see . - */ - -package baritone.api.schematic; - -/** - * @author Brady - */ -public final class SphereSchematic extends CachedMaskSchematic { - - public SphereSchematic(ISchematic schematic, boolean filled) { - super(schematic, new StaticMaskFunction() { - - private final double centerX = schematic.widthX() / 2.0; - private final double centerY = schematic.heightY() / 2.0; - private final double centerZ = schematic.lengthZ() / 2.0; - private final double radiusSqX = this.centerX * this.centerX; - private final double radiusSqY = this.centerY * this.centerY; - private final double radiusSqZ = this.centerZ * this.centerZ; - - @Override - public boolean partOfMask(int x, int y, int z) { - double dx = Math.abs((x + 0.5) - this.centerX); - double dy = Math.abs((y + 0.5) - this.centerY); - double dz = Math.abs((z + 0.5) - this.centerZ); - if (this.outside(dx, dy, dz)) { - return false; - } - return filled - || this.outside(dx + 1, dy, dz) - || this.outside(dx, dy + 1, dz) - || this.outside(dx, dy, dz + 1); - } - - private boolean outside(double dx, double dy, double dz) { - return dx * dx / this.radiusSqX + dy * dy / this.radiusSqY + dz * dz / this.radiusSqZ > 1; - } - }); - } -} diff --git a/src/api/java/baritone/api/schematic/mask/AbstractMask.java b/src/api/java/baritone/api/schematic/mask/AbstractMask.java new file mode 100644 index 000000000..ce92af0ec --- /dev/null +++ b/src/api/java/baritone/api/schematic/mask/AbstractMask.java @@ -0,0 +1,49 @@ +/* + * This file is part of Baritone. + * + * Baritone is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Baritone is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Baritone. If not, see . + */ + +package baritone.api.schematic.mask; + +/** + * @author Brady + */ +public abstract class AbstractMask implements Mask { + + private final int widthX; + private final int heightY; + private final int lengthZ; + + public AbstractMask(int widthX, int heightY, int lengthZ) { + this.widthX = widthX; + this.heightY = heightY; + this.lengthZ = lengthZ; + } + + @Override + public int widthX() { + return this.widthX; + } + + @Override + public int heightY() { + return this.heightY; + } + + @Override + public int lengthZ() { + return this.lengthZ; + } +} diff --git a/src/api/java/baritone/api/schematic/mask/Mask.java b/src/api/java/baritone/api/schematic/mask/Mask.java new file mode 100644 index 000000000..540c2cee1 --- /dev/null +++ b/src/api/java/baritone/api/schematic/mask/Mask.java @@ -0,0 +1,41 @@ +/* + * This file is part of Baritone. + * + * Baritone is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Baritone is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Baritone. If not, see . + */ + +package baritone.api.schematic.mask; + +import net.minecraft.block.state.IBlockState; + +/** + * @author Brady + */ +public interface Mask { + + /** + * @param x The relative x position of the block + * @param y The relative y position of the block + * @param z The relative z position of the block + * @param currentState The current state of that block in the world, may be {@code null} + * @return Whether the given position is included in this mask + */ + boolean partOfMask(int x, int y, int z, IBlockState currentState); + + int widthX(); + + int heightY(); + + int lengthZ(); +} diff --git a/src/api/java/baritone/api/schematic/mask/PreComputedMask.java b/src/api/java/baritone/api/schematic/mask/PreComputedMask.java new file mode 100644 index 000000000..aed26cc94 --- /dev/null +++ b/src/api/java/baritone/api/schematic/mask/PreComputedMask.java @@ -0,0 +1,44 @@ +/* + * This file is part of Baritone. + * + * Baritone is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Baritone is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Baritone. If not, see . + */ + +package baritone.api.schematic.mask; + +/** + * @author Brady + */ +final class PreComputedMask extends AbstractMask implements StaticMask { + + private final boolean[][][] mask; + + public PreComputedMask(StaticMask mask) { + super(mask.widthX(), mask.heightY(), mask.lengthZ()); + + this.mask = new boolean[this.heightY()][this.lengthZ()][this.widthX()]; + for (int y = 0; y < this.heightY(); y++) { + for (int z = 0; z < this.lengthZ(); z++) { + for (int x = 0; x < this.widthX(); x++) { + this.mask[y][z][x] = mask.partOfMask(x, y, z); + } + } + } + } + + @Override + public boolean partOfMask(int x, int y, int z) { + return this.mask[y][z][x]; + } +} diff --git a/src/api/java/baritone/api/schematic/mask/StaticMask.java b/src/api/java/baritone/api/schematic/mask/StaticMask.java new file mode 100644 index 000000000..ef50a65cc --- /dev/null +++ b/src/api/java/baritone/api/schematic/mask/StaticMask.java @@ -0,0 +1,62 @@ +/* + * This file is part of Baritone. + * + * Baritone is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Baritone is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Baritone. If not, see . + */ + +package baritone.api.schematic.mask; + +import net.minecraft.block.state.IBlockState; + +/** + * A mask that is context-free. In other words, it doesn't require the current block state to determine if a relative + * position is a part of the mask. + * + * @author Brady + */ +public interface StaticMask extends Mask { + + /** + * Determines if a given relative coordinate is included in this mask, without the need for the current block state. + * + * @param x The relative x position of the block + * @param y The relative y position of the block + * @param z The relative z position of the block + * @return Whether the given position is included in this mask + */ + boolean partOfMask(int x, int y, int z); + + /** + * Implements the parent {@link Mask#partOfMask partOfMask function} by calling the static function + * provided in this functional interface without needing the {@link IBlockState} argument. This {@code default} + * implementation should NOT be overriden. + * + * @param x The relative x position of the block + * @param y The relative y position of the block + * @param z The relative z position of the block + * @param currentState The current state of that block in the world, may be {@code null} + * @return Whether the given position is included in this mask + */ + @Override + default boolean partOfMask(int x, int y, int z, IBlockState currentState) { + return this.partOfMask(x, y, z); + } + + /** + * Returns a pre-computed mask using {@code this} function, with the specified size parameters. + */ + default StaticMask compute() { + return new PreComputedMask(this); + } +} diff --git a/src/api/java/baritone/api/schematic/mask/shape/CylinderMask.java b/src/api/java/baritone/api/schematic/mask/shape/CylinderMask.java new file mode 100644 index 000000000..71b0d43c9 --- /dev/null +++ b/src/api/java/baritone/api/schematic/mask/shape/CylinderMask.java @@ -0,0 +1,69 @@ +/* + * This file is part of Baritone. + * + * Baritone is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Baritone is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Baritone. If not, see . + */ + +package baritone.api.schematic.mask.shape; + +import baritone.api.schematic.mask.AbstractMask; +import baritone.api.schematic.mask.StaticMask; +import net.minecraft.util.EnumFacing; + +/** + * @author Brady + */ +public final class CylinderMask extends AbstractMask implements StaticMask { + + private final double centerA; + private final double centerB; + private final double radiusSqA; + private final double radiusSqB; + private final boolean filled; + private final EnumFacing.Axis alignment; + + public CylinderMask(int widthX, int heightY, int lengthZ, boolean filled, EnumFacing.Axis alignment) { + super(widthX, heightY, lengthZ); + this.centerA = this.getA(widthX, heightY) / 2.0; + this.centerB = this.getB(heightY, lengthZ) / 2.0; + this.radiusSqA = (this.centerA - 1) * (this.centerA - 1); + this.radiusSqB = (this.centerB - 1) * (this.centerB - 1); + this.filled = filled; + this.alignment = alignment; + } + + @Override + public boolean partOfMask(int x, int y, int z) { + double da = Math.abs((this.getA(x, y) + 0.5) - this.centerA); + double db = Math.abs((this.getB(y, z) + 0.5) - this.centerB); + if (this.outside(da, db)) { + return false; + } + return this.filled + || this.outside(da + 1, db) + || this.outside(da, db + 1); + } + + private boolean outside(double da, double db) { + return da * da / this.radiusSqA + db * db / this.radiusSqB > 1; + } + + private int getA(int x, int y) { + return this.alignment == EnumFacing.Axis.X ? y : x; + } + + private int getB(int y, int z) { + return this.alignment == EnumFacing.Axis.Z ? y : z; + } +} diff --git a/src/api/java/baritone/api/schematic/mask/shape/SphereMask.java b/src/api/java/baritone/api/schematic/mask/shape/SphereMask.java new file mode 100644 index 000000000..d805c98a8 --- /dev/null +++ b/src/api/java/baritone/api/schematic/mask/shape/SphereMask.java @@ -0,0 +1,64 @@ +/* + * This file is part of Baritone. + * + * Baritone is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Baritone is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Baritone. If not, see . + */ + +package baritone.api.schematic.mask.shape; + +import baritone.api.schematic.mask.AbstractMask; +import baritone.api.schematic.mask.StaticMask; + +/** + * @author Brady + */ +public final class SphereMask extends AbstractMask implements StaticMask { + + private final double centerX; + private final double centerY; + private final double centerZ; + private final double radiusSqX; + private final double radiusSqY; + private final double radiusSqZ; + private final boolean filled; + + public SphereMask(int widthX, int heightY, int lengthZ, boolean filled) { + super(widthX, heightY, lengthZ); + this.centerX = widthX / 2.0; + this.centerY = heightY / 2.0; + this.centerZ = lengthZ / 2.0; + this.radiusSqX = this.centerX * this.centerX; + this.radiusSqY = this.centerY * this.centerY; + this.radiusSqZ = this.centerZ * this.centerZ; + this.filled = filled; + } + + @Override + public boolean partOfMask(int x, int y, int z) { + double dx = Math.abs((x + 0.5) - this.centerX); + double dy = Math.abs((y + 0.5) - this.centerY); + double dz = Math.abs((z + 0.5) - this.centerZ); + if (this.outside(dx, dy, dz)) { + return false; + } + return this.filled + || this.outside(dx + 1, dy, dz) + || this.outside(dx, dy + 1, dz) + || this.outside(dx, dy, dz + 1); + } + + private boolean outside(double dx, double dy, double dz) { + return dx * dx / this.radiusSqX + dy * dy / this.radiusSqY + dz * dz / this.radiusSqZ > 1; + } +} diff --git a/src/main/java/baritone/command/defaults/SelCommand.java b/src/main/java/baritone/command/defaults/SelCommand.java index 72c5cd1c0..e1d2082ff 100644 --- a/src/main/java/baritone/command/defaults/SelCommand.java +++ b/src/main/java/baritone/command/defaults/SelCommand.java @@ -32,6 +32,8 @@ import baritone.api.command.helpers.TabCompleteHelper; import baritone.api.event.events.RenderEvent; import baritone.api.event.listener.AbstractGameEventListener; import baritone.api.schematic.*; +import baritone.api.schematic.mask.shape.CylinderMask; +import baritone.api.schematic.mask.shape.SphereMask; import baritone.api.selection.ISelection; import baritone.api.selection.ISelectionManager; import baritone.api.utils.BetterBlockPos; @@ -173,13 +175,13 @@ public class SelCommand extends Command { case REPLACE: return new ReplaceSchematic(fill, replaces); case SPHERE: - return new SphereSchematic(fill, true); + return MaskSchematic.create(fill, new SphereMask(size.getX(), size.getY(), size.getZ(), true).compute()); case HSPHERE: - return new SphereSchematic(fill, false); + return MaskSchematic.create(fill, new SphereMask(size.getX(), size.getY(), size.getZ(), false).compute()); case CYLINDER: - return new CylinderSchematic(fill, true, alignment); + return MaskSchematic.create(fill, new CylinderMask(size.getX(), size.getY(), size.getZ(), true, alignment).compute()); case HCYLINDER: - return new CylinderSchematic(fill, false, alignment); + return MaskSchematic.create(fill, new CylinderMask(size.getX(), size.getY(), size.getZ(), false, alignment).compute()); default: // Silent fail return fill; From 94d757104b027c121ca2bc39f658b09e10ea28a5 Mon Sep 17 00:00:00 2001 From: Brady Date: Sun, 11 Jun 2023 11:24:31 -0500 Subject: [PATCH 08/10] Clean ups --- .../java/baritone/command/defaults/SelCommand.java | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/main/java/baritone/command/defaults/SelCommand.java b/src/main/java/baritone/command/defaults/SelCommand.java index e1d2082ff..0a11c86a8 100644 --- a/src/main/java/baritone/command/defaults/SelCommand.java +++ b/src/main/java/baritone/command/defaults/SelCommand.java @@ -167,6 +167,10 @@ public class SelCommand extends Command { // Java 8 so no switch expressions 😿 UnaryOperator create = fill -> { + final int w = fill.widthX(); + final int h = fill.heightY(); + final int l = fill.lengthZ(); + switch (action) { case WALLS: return new WallsSchematic(fill); @@ -175,13 +179,13 @@ public class SelCommand extends Command { case REPLACE: return new ReplaceSchematic(fill, replaces); case SPHERE: - return MaskSchematic.create(fill, new SphereMask(size.getX(), size.getY(), size.getZ(), true).compute()); + return MaskSchematic.create(fill, new SphereMask(w, h, l, true).compute()); case HSPHERE: - return MaskSchematic.create(fill, new SphereMask(size.getX(), size.getY(), size.getZ(), false).compute()); + return MaskSchematic.create(fill, new SphereMask(w, h, l, false).compute()); case CYLINDER: - return MaskSchematic.create(fill, new CylinderMask(size.getX(), size.getY(), size.getZ(), true, alignment).compute()); + return MaskSchematic.create(fill, new CylinderMask(w, h, l, true, alignment).compute()); case HCYLINDER: - return MaskSchematic.create(fill, new CylinderMask(size.getX(), size.getY(), size.getZ(), false, alignment).compute()); + return MaskSchematic.create(fill, new CylinderMask(w, h, l, false, alignment).compute()); default: // Silent fail return fill; From ffd00080f256e216238c7887c8549fd8bd8ae40f Mon Sep 17 00:00:00 2001 From: Brady Date: Sun, 11 Jun 2023 11:27:51 -0500 Subject: [PATCH 09/10] Mask binary operators --- .../baritone/api/schematic/mask/Mask.java | 19 +++++ .../api/schematic/mask/StaticMask.java | 20 ++++++ .../mask/operator/BinaryOperatorMask.java | 71 +++++++++++++++++++ .../api/schematic/mask/operator/NotMask.java | 56 +++++++++++++++ .../api/utils/BooleanBinaryOperator.java | 27 +++++++ .../api/utils/BooleanBinaryOperators.java | 38 ++++++++++ 6 files changed, 231 insertions(+) create mode 100644 src/api/java/baritone/api/schematic/mask/operator/BinaryOperatorMask.java create mode 100644 src/api/java/baritone/api/schematic/mask/operator/NotMask.java create mode 100644 src/api/java/baritone/api/utils/BooleanBinaryOperator.java create mode 100644 src/api/java/baritone/api/utils/BooleanBinaryOperators.java diff --git a/src/api/java/baritone/api/schematic/mask/Mask.java b/src/api/java/baritone/api/schematic/mask/Mask.java index 540c2cee1..7df6f8f04 100644 --- a/src/api/java/baritone/api/schematic/mask/Mask.java +++ b/src/api/java/baritone/api/schematic/mask/Mask.java @@ -17,6 +17,9 @@ package baritone.api.schematic.mask; +import baritone.api.schematic.mask.operator.BinaryOperatorMask; +import baritone.api.schematic.mask.operator.NotMask; +import baritone.api.utils.BooleanBinaryOperators; import net.minecraft.block.state.IBlockState; /** @@ -38,4 +41,20 @@ public interface Mask { int heightY(); int lengthZ(); + + default Mask not() { + return new NotMask(this); + } + + default Mask union(Mask other) { + return new BinaryOperatorMask(this, other, BooleanBinaryOperators.OR); + } + + default Mask intersection(Mask other) { + return new BinaryOperatorMask(this, other, BooleanBinaryOperators.AND); + } + + default Mask xor(Mask other) { + return new BinaryOperatorMask(this, other, BooleanBinaryOperators.XOR); + } } diff --git a/src/api/java/baritone/api/schematic/mask/StaticMask.java b/src/api/java/baritone/api/schematic/mask/StaticMask.java index ef50a65cc..220a94828 100644 --- a/src/api/java/baritone/api/schematic/mask/StaticMask.java +++ b/src/api/java/baritone/api/schematic/mask/StaticMask.java @@ -17,6 +17,9 @@ package baritone.api.schematic.mask; +import baritone.api.schematic.mask.operator.BinaryOperatorMask; +import baritone.api.schematic.mask.operator.NotMask; +import baritone.api.utils.BooleanBinaryOperators; import net.minecraft.block.state.IBlockState; /** @@ -53,6 +56,23 @@ public interface StaticMask extends Mask { return this.partOfMask(x, y, z); } + @Override + default StaticMask not() { + return new NotMask.Static(this); + } + + default StaticMask union(StaticMask other) { + return new BinaryOperatorMask.Static(this, other, BooleanBinaryOperators.OR); + } + + default StaticMask intersection(StaticMask other) { + return new BinaryOperatorMask.Static(this, other, BooleanBinaryOperators.AND); + } + + default StaticMask xor(StaticMask other) { + return new BinaryOperatorMask.Static(this, other, BooleanBinaryOperators.XOR); + } + /** * Returns a pre-computed mask using {@code this} function, with the specified size parameters. */ diff --git a/src/api/java/baritone/api/schematic/mask/operator/BinaryOperatorMask.java b/src/api/java/baritone/api/schematic/mask/operator/BinaryOperatorMask.java new file mode 100644 index 000000000..e591c7873 --- /dev/null +++ b/src/api/java/baritone/api/schematic/mask/operator/BinaryOperatorMask.java @@ -0,0 +1,71 @@ +/* + * This file is part of Baritone. + * + * Baritone is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Baritone is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Baritone. If not, see . + */ + +package baritone.api.schematic.mask.operator; + +import baritone.api.schematic.mask.AbstractMask; +import baritone.api.schematic.mask.Mask; +import baritone.api.schematic.mask.StaticMask; +import baritone.api.utils.BooleanBinaryOperator; +import net.minecraft.block.state.IBlockState; + +/** + * @author Brady + */ +public final class BinaryOperatorMask extends AbstractMask { + + private final Mask a; + private final Mask b; + private final BooleanBinaryOperator operator; + + public BinaryOperatorMask(Mask a, Mask b, BooleanBinaryOperator operator) { + super(a.widthX(), a.heightY(), a.lengthZ()); + this.a = a; + this.b = b; + this.operator = operator; + } + + @Override + public boolean partOfMask(int x, int y, int z, IBlockState currentState) { + return this.operator.applyAsBoolean( + this.a.partOfMask(x, y, z, currentState), + this.b.partOfMask(x, y, z, currentState) + ); + } + + public static final class Static extends AbstractMask implements StaticMask { + + private final StaticMask a; + private final StaticMask b; + private final BooleanBinaryOperator operator; + + public Static(StaticMask a, StaticMask b, BooleanBinaryOperator operator) { + super(a.widthX(), a.heightY(), a.lengthZ()); + this.a = a; + this.b = b; + this.operator = operator; + } + + @Override + public boolean partOfMask(int x, int y, int z) { + return this.operator.applyAsBoolean( + this.a.partOfMask(x, y, z), + this.b.partOfMask(x, y, z) + ); + } + } +} diff --git a/src/api/java/baritone/api/schematic/mask/operator/NotMask.java b/src/api/java/baritone/api/schematic/mask/operator/NotMask.java new file mode 100644 index 000000000..f9f770b82 --- /dev/null +++ b/src/api/java/baritone/api/schematic/mask/operator/NotMask.java @@ -0,0 +1,56 @@ +/* + * This file is part of Baritone. + * + * Baritone is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Baritone is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Baritone. If not, see . + */ + +package baritone.api.schematic.mask.operator; + +import baritone.api.schematic.mask.AbstractMask; +import baritone.api.schematic.mask.Mask; +import baritone.api.schematic.mask.StaticMask; +import net.minecraft.block.state.IBlockState; + +/** + * @author Brady + */ +public final class NotMask extends AbstractMask { + + private final Mask source; + + public NotMask(Mask source) { + super(source.widthX(), source.heightY(), source.lengthZ()); + this.source = source; + } + + @Override + public boolean partOfMask(int x, int y, int z, IBlockState currentState) { + return !this.source.partOfMask(x, y, z, currentState); + } + + public static final class Static extends AbstractMask implements StaticMask { + + private final StaticMask source; + + public Static(StaticMask source) { + super(source.widthX(), source.heightY(), source.lengthZ()); + this.source = source; + } + + @Override + public boolean partOfMask(int x, int y, int z) { + return !this.source.partOfMask(x, y, z); + } + } +} diff --git a/src/api/java/baritone/api/utils/BooleanBinaryOperator.java b/src/api/java/baritone/api/utils/BooleanBinaryOperator.java new file mode 100644 index 000000000..cfb85e644 --- /dev/null +++ b/src/api/java/baritone/api/utils/BooleanBinaryOperator.java @@ -0,0 +1,27 @@ +/* + * This file is part of Baritone. + * + * Baritone is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Baritone is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Baritone. If not, see . + */ + +package baritone.api.utils; + +/** + * @author Brady + */ +@FunctionalInterface +public interface BooleanBinaryOperator { + + boolean applyAsBoolean(boolean a, boolean b); +} diff --git a/src/api/java/baritone/api/utils/BooleanBinaryOperators.java b/src/api/java/baritone/api/utils/BooleanBinaryOperators.java new file mode 100644 index 000000000..11605c965 --- /dev/null +++ b/src/api/java/baritone/api/utils/BooleanBinaryOperators.java @@ -0,0 +1,38 @@ +/* + * This file is part of Baritone. + * + * Baritone is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Baritone is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Baritone. If not, see . + */ + +package baritone.api.utils; + +/** + * @author Brady + */ +public enum BooleanBinaryOperators implements BooleanBinaryOperator { + OR((a, b) -> a || b), + AND((a, b) -> a && b), + XOR((a, b) -> a ^ b); + + private final BooleanBinaryOperator op; + + BooleanBinaryOperators(BooleanBinaryOperator op) { + this.op = op; + } + + @Override + public boolean applyAsBoolean(boolean a, boolean b) { + return this.op.applyAsBoolean(a, b); + } +} From a09e63d6aa654b85b3dbc75ad1044e1e4d031b45 Mon Sep 17 00:00:00 2001 From: Brady Date: Sun, 11 Jun 2023 13:14:52 -0500 Subject: [PATCH 10/10] appease codacy --- src/main/java/baritone/command/defaults/SelCommand.java | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/main/java/baritone/command/defaults/SelCommand.java b/src/main/java/baritone/command/defaults/SelCommand.java index 0a11c86a8..fb3608e75 100644 --- a/src/main/java/baritone/command/defaults/SelCommand.java +++ b/src/main/java/baritone/command/defaults/SelCommand.java @@ -294,12 +294,9 @@ public class SelCommand extends Command { args.get(); } return args.tabCompleteDatatype(ForBlockOptionalMeta.INSTANCE); - } else if (action == Action.CYLINDER || action == Action.HCYLINDER) { - if (args.hasExactly(2)) { - if (args.getDatatypeForOrNull(ForBlockOptionalMeta.INSTANCE) != null) { - return args.tabCompleteDatatype(ForAxis.INSTANCE); - } - } + } else if (args.hasExactly(2) && (action == Action.CYLINDER || action == Action.HCYLINDER)) { + args.get(); + return args.tabCompleteDatatype(ForAxis.INSTANCE); } } else if (action == Action.EXPAND || action == Action.CONTRACT || action == Action.SHIFT) { if (args.hasExactlyOne()) {