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.",