diff --git a/src/api/java/baritone/api/schematic/AbstractSchematic.java b/src/api/java/baritone/api/schematic/AbstractSchematic.java new file mode 100644 index 00000000..3b6bb41c --- /dev/null +++ b/src/api/java/baritone/api/schematic/AbstractSchematic.java @@ -0,0 +1,30 @@ +package baritone.api.schematic; + +import baritone.api.utils.ISchematic; + +public abstract class AbstractSchematic implements ISchematic { + protected int x; + protected int y; + protected int z; + + public AbstractSchematic(int x, int y, int z) { + this.x = x; + this.y = y; + this.z = z; + } + + @Override + public int widthX() { + return x; + } + + @Override + public int heightY() { + return y; + } + + @Override + public int lengthZ() { + return z; + } +} diff --git a/src/api/java/baritone/api/schematic/CompositeSchematic.java b/src/api/java/baritone/api/schematic/CompositeSchematic.java new file mode 100644 index 00000000..56c49b80 --- /dev/null +++ b/src/api/java/baritone/api/schematic/CompositeSchematic.java @@ -0,0 +1,61 @@ +package baritone.api.schematic; + +import baritone.api.utils.ISchematic; +import net.minecraft.block.state.IBlockState; + +import java.util.ArrayList; +import java.util.List; + +public class CompositeSchematic extends AbstractSchematic { + private final List<CompositeSchematicEntry> schematics; + private CompositeSchematicEntry[] schematicArr; + + private void recalcArr() { + schematicArr = schematics.toArray(new CompositeSchematicEntry[0]); + + for (CompositeSchematicEntry entry : schematicArr) { + this.x = Math.max(x, entry.x + entry.schematic.widthX()); + this.y = Math.max(y, entry.y + entry.schematic.heightY()); + this.z = Math.max(z, entry.z + entry.schematic.lengthZ()); + } + } + + public CompositeSchematic(int x, int y, int z) { + super(x, y, z); + schematics = new ArrayList<>(); + recalcArr(); + } + + public void put(ISchematic extra, int x, int y, int z) { + schematics.add(new CompositeSchematicEntry(extra, x, y, z)); + recalcArr(); + } + + private CompositeSchematicEntry getSchematic(int x, int y, int z, IBlockState currentState) { + for (CompositeSchematicEntry entry : schematicArr) { + if (x >= entry.x && y >= entry.y && z >= entry.z && + entry.schematic.inSchematic(x - entry.x, y - entry.y, z - entry.z, currentState)) { + return entry; + } + } + + return null; + } + + @Override + public boolean inSchematic(int x, int y, int z, IBlockState currentState) { + CompositeSchematicEntry entry = getSchematic(x, y, z, currentState); + return entry != null && entry.schematic.inSchematic(x - entry.x, y - entry.y, z - entry.z, currentState); + } + + @Override + public IBlockState desiredState(int x, int y, int z, IBlockState current) { + CompositeSchematicEntry entry = getSchematic(x, y, z, current); + + if (entry == null) { + throw new IllegalStateException("couldn't find schematic for this position"); + } + + return entry.schematic.desiredState(x - entry.x, y - entry.y, z - entry.z, current); + } +} diff --git a/src/api/java/baritone/api/schematic/CompositeSchematicEntry.java b/src/api/java/baritone/api/schematic/CompositeSchematicEntry.java new file mode 100644 index 00000000..c34cd112 --- /dev/null +++ b/src/api/java/baritone/api/schematic/CompositeSchematicEntry.java @@ -0,0 +1,17 @@ +package baritone.api.schematic; + +import baritone.api.utils.ISchematic; + +public class CompositeSchematicEntry { + public final ISchematic schematic; + public final int x; + public final int y; + public final int z; + + public CompositeSchematicEntry(ISchematic schematic, int x, int y, int z) { + this.schematic = schematic; + this.x = x; + this.y = y; + this.z = z; + } +} diff --git a/src/api/java/baritone/api/schematic/FillBomSchematic.java b/src/api/java/baritone/api/schematic/FillBomSchematic.java new file mode 100644 index 00000000..b7536e81 --- /dev/null +++ b/src/api/java/baritone/api/schematic/FillBomSchematic.java @@ -0,0 +1,26 @@ +package baritone.api.schematic; + +import baritone.api.utils.BlockOptionalMeta; +import net.minecraft.block.state.IBlockState; + +public class FillBomSchematic extends AbstractSchematic { + private final BlockOptionalMeta bom; + + public FillBomSchematic(int x, int y, int z, BlockOptionalMeta bom) { + super(x, y, z); + this.bom = bom; + } + + public BlockOptionalMeta getBom() { + return bom; + } + + @Override + public IBlockState desiredState(int x, int y, int z, IBlockState current) { + if (bom.matches(current)) { + return current; + } + + return bom.getAnyBlockState(); + } +} diff --git a/src/api/java/baritone/api/schematic/MaskSchematic.java b/src/api/java/baritone/api/schematic/MaskSchematic.java new file mode 100644 index 00000000..033e390c --- /dev/null +++ b/src/api/java/baritone/api/schematic/MaskSchematic.java @@ -0,0 +1,25 @@ +package baritone.api.schematic; + +import baritone.api.utils.ISchematic; +import net.minecraft.block.state.IBlockState; + +public abstract class MaskSchematic extends AbstractSchematic { + private final ISchematic schematic; + + public MaskSchematic(ISchematic schematic) { + super(schematic.widthX(), schematic.heightY(), schematic.lengthZ()); + this.schematic = schematic; + } + + protected abstract boolean partOfMask(int x, int y, int z, IBlockState currentState); + + @Override + public boolean inSchematic(int x, int y, int z, IBlockState currentState) { + return schematic.inSchematic(x, y, z, currentState) && partOfMask(x, y, z, currentState); + } + + @Override + public IBlockState desiredState(int x, int y, int z, IBlockState current) { + return schematic.desiredState(x, y, z, current); + } +} diff --git a/src/api/java/baritone/api/schematic/ShellSchematic.java b/src/api/java/baritone/api/schematic/ShellSchematic.java new file mode 100644 index 00000000..2c94fa9f --- /dev/null +++ b/src/api/java/baritone/api/schematic/ShellSchematic.java @@ -0,0 +1,14 @@ +package baritone.api.schematic; + +import baritone.api.utils.ISchematic; +import net.minecraft.block.state.IBlockState; + +public class ShellSchematic extends MaskSchematic { + public ShellSchematic(ISchematic schematic) { + super(schematic); + } + + protected boolean partOfMask(int x, int y, int z, IBlockState currentState) { + return x == 0 || y == 0 || z == 0 || x == widthX() - 1 || y == heightY() - 1 || z == lengthZ() - 1; + } +} diff --git a/src/api/java/baritone/api/schematic/WallsSchematic.java b/src/api/java/baritone/api/schematic/WallsSchematic.java new file mode 100644 index 00000000..8091944e --- /dev/null +++ b/src/api/java/baritone/api/schematic/WallsSchematic.java @@ -0,0 +1,14 @@ +package baritone.api.schematic; + +import baritone.api.utils.ISchematic; +import net.minecraft.block.state.IBlockState; + +public class WallsSchematic extends MaskSchematic { + public WallsSchematic(ISchematic schematic) { + super(schematic); + } + + protected boolean partOfMask(int x, int y, int z, IBlockState currentState) { + return x == 0 || z == 0 || x == widthX() - 1 || z == lengthZ() - 1; + } +} diff --git a/src/api/java/baritone/api/utils/BlockOptionalMeta.java b/src/api/java/baritone/api/utils/BlockOptionalMeta.java index 90d163d8..bd17307c 100644 --- a/src/api/java/baritone/api/utils/BlockOptionalMeta.java +++ b/src/api/java/baritone/api/utils/BlockOptionalMeta.java @@ -31,7 +31,6 @@ import net.minecraft.block.BlockDoublePlant; import net.minecraft.block.BlockFence; import net.minecraft.block.BlockFire; import net.minecraft.block.BlockGrass; -import net.minecraft.block.BlockHorizontal; import net.minecraft.block.BlockLeaves; import net.minecraft.block.BlockLever; import net.minecraft.block.BlockLog; @@ -323,4 +322,12 @@ public final class BlockOptionalMeta { //noinspection deprecation return Block.getBlockFromItem(stack.getItem()).getStateFromMeta(stack.getMetadata()); } + + public IBlockState getAnyBlockState() { + if (blockstates.size() > 0) { + return blockstates.iterator().next(); + } + + return null; + } } diff --git a/src/api/java/baritone/api/utils/command/defaults/SelCommand.java b/src/api/java/baritone/api/utils/command/defaults/SelCommand.java index ef66be5e..c696bd72 100644 --- a/src/api/java/baritone/api/utils/command/defaults/SelCommand.java +++ b/src/api/java/baritone/api/utils/command/defaults/SelCommand.java @@ -19,15 +19,25 @@ package baritone.api.utils.command.defaults; import baritone.api.Settings; import baritone.api.event.events.RenderEvent; +import baritone.api.schematic.CompositeSchematic; +import baritone.api.schematic.FillBomSchematic; +import baritone.api.schematic.ShellSchematic; +import baritone.api.schematic.WallsSchematic; +import baritone.api.selection.ISelection; import baritone.api.utils.BetterBlockPos; +import baritone.api.utils.BlockOptionalMeta; import baritone.api.utils.IRenderer; +import baritone.api.utils.ISchematic; import baritone.api.utils.command.Command; +import baritone.api.utils.command.datatypes.ForBlockOptionalMeta; import baritone.api.utils.command.datatypes.RelativeBlockPos; import baritone.api.utils.command.exception.CommandInvalidStateException; import baritone.api.utils.command.exception.CommandInvalidTypeException; import baritone.api.utils.command.helpers.arguments.ArgConsumer; import baritone.api.utils.command.helpers.tabcomplete.TabCompleteHelper; +import net.minecraft.init.Blocks; import net.minecraft.util.math.AxisAlignedBB; +import net.minecraft.util.math.Vec3i; import java.awt.Color; import java.util.HashSet; @@ -75,6 +85,46 @@ public class SelCommand extends Command { "Removed %d selections", baritone.getSelectionManager().removeAllSelections().length )); + } else { + BlockOptionalMeta type = action == Action.CLEARAREA + ? new BlockOptionalMeta(Blocks.AIR) + : args.getDatatypeFor(ForBlockOptionalMeta.class); + args.requireMax(0); + ISelection[] selections = baritone.getSelectionManager().getSelections(); + + if (selections.length == 0) { + throw new CommandInvalidStateException("No selections"); + } + + BetterBlockPos origin = selections[0].min(); + CompositeSchematic composite = new CompositeSchematic(0, 0, 0); + + for (ISelection selection : selections) { + BetterBlockPos min = selection.min(); + origin = new BetterBlockPos( + Math.min(origin.x, min.x), + Math.min(origin.y, min.y), + Math.min(origin.z, min.z) + ); + } + + for (ISelection selection : selections) { + Vec3i size = selection.size(); + BetterBlockPos min = selection.min(); + + ISchematic schematic = new FillBomSchematic(size.getX(), size.getY(), size.getZ(), type); + + if (action == Action.WALLS) { + schematic = new WallsSchematic(schematic); + } else if (action == Action.SHELL) { + schematic = new ShellSchematic(schematic); + } + + composite.put(schematic, min.x - origin.x, min.y - origin.y, min.z - origin.z); + } + + baritone.getBuilderProcess().build("Fill", composite, origin); + logDirect("Filling now"); } } @@ -112,7 +162,11 @@ public class SelCommand extends Command { enum Action { POS1("pos1", "p1"), POS2("pos2", "p2"), - CLEAR("clear", "c"); + CLEAR("clear", "c"), + SET("set", "fill", "s", "f"), + WALLS("walls", "w"), + SHELL("shell", "sh"), + CLEARAREA("cleararea", "ca"); private final String[] names;