diff --git a/src/api/java/baritone/api/Settings.java b/src/api/java/baritone/api/Settings.java index a0d6360cd..60285ef3c 100644 --- a/src/api/java/baritone/api/Settings.java +++ b/src/api/java/baritone/api/Settings.java @@ -21,6 +21,7 @@ import baritone.api.utils.SettingsUtil; import net.minecraft.client.Minecraft; import net.minecraft.init.Blocks; import net.minecraft.item.Item; +import net.minecraft.util.EnumFacing; import net.minecraft.util.text.ITextComponent; import java.awt.*; @@ -566,6 +567,21 @@ public final class Settings { */ public final Setting exploreForBlocks = new Setting<>(true); + /** + * Don't consider the next layer in builder until the current one is done + */ + public final Setting buildInLayers = new Setting<>(false); + + /** + * How far to move before repeating the build. -1 for the size of the build in that axis. 0 to disable + */ + public final Setting buildRepeatDistance=new Setting<>(0); + + /** + * What direction te repeat the build in + */ + public final Setting buildRepeatDirection = new Setting<>(EnumFacing.NORTH); + /** * While mining, should it also consider dropped items of the correct type as a pathing destination (as well as ore blocks)? */ diff --git a/src/api/java/baritone/api/pathing/goals/GoalNear.java b/src/api/java/baritone/api/pathing/goals/GoalNear.java index 6befda6bc..4f75aba72 100644 --- a/src/api/java/baritone/api/pathing/goals/GoalNear.java +++ b/src/api/java/baritone/api/pathing/goals/GoalNear.java @@ -61,6 +61,6 @@ public class GoalNear implements Goal, IGoalRenderPos { ", y=" + y + ", z=" + z + ", rangeSq=" + rangeSq + - '}'; + "}"; } } diff --git a/src/api/java/baritone/api/pathing/goals/GoalStrictDirection.java b/src/api/java/baritone/api/pathing/goals/GoalStrictDirection.java new file mode 100644 index 000000000..749bed626 --- /dev/null +++ b/src/api/java/baritone/api/pathing/goals/GoalStrictDirection.java @@ -0,0 +1,76 @@ +/* + * 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.pathing.goals; + +import baritone.api.BaritoneAPI; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.math.BlockPos; + +/** + * Dig a tunnel in a certain direction, but if you have to deviate from the path, go back to where you started + */ +public class GoalStrictDirection implements Goal { + public final int x; + public final int y; + public final int z; + public final int dx; + public final int dz; + + public GoalStrictDirection(BlockPos origin, EnumFacing direction) { + x = origin.getX(); + y = origin.getY(); + z = origin.getZ(); + dx = direction.getXOffset(); + dz = direction.getZOffset(); + if (dx == 0 && dz == 0) { + throw new IllegalArgumentException(direction + ""); + } + } + + @Override + public boolean isInGoal(int x, int y, int z) { + return false; + } + + @Override + public double heuristic(int x, int y, int z) { + int distanceFromStartInDesiredDirection = (x - this.x) * dx + (z - this.z) * dz; + + int distanceFromStartInIncorrectDirection = Math.abs((x - this.x) * dz) + Math.abs((z - this.z) * dx); + + int verticalDistanceFromStart = Math.abs(y - this.y); + + // we want heuristic to decrease as desiredDirection increases + double heuristic = -distanceFromStartInDesiredDirection * 100; + + heuristic += distanceFromStartInIncorrectDirection * 1000; + heuristic += verticalDistanceFromStart * 1000; + return heuristic; + } + + @Override + public String toString() { + return "GoalStrictDirection{" + + "x=" + x + + ", y=" + y + + ", z=" + z + + ", dx=" + dx + + ", dz=" + dz + + "}"; + } +} diff --git a/src/api/java/baritone/api/utils/ISchematic.java b/src/api/java/baritone/api/utils/ISchematic.java index 1f2cd8742..821dc68c3 100644 --- a/src/api/java/baritone/api/utils/ISchematic.java +++ b/src/api/java/baritone/api/utils/ISchematic.java @@ -18,6 +18,7 @@ package baritone.api.utils; import net.minecraft.block.state.IBlockState; +import net.minecraft.util.EnumFacing; /** * Basic representation of a schematic. Provides the dimensions and @@ -44,6 +45,19 @@ public interface ISchematic { return x >= 0 && x < widthX() && y >= 0 && y < heightY() && z >= 0 && z < lengthZ(); } + default int size(EnumFacing.Axis axis) { + switch (axis) { + case X: + return widthX(); + case Y: + return heightY(); + case Z: + return lengthZ(); + default: + throw new UnsupportedOperationException(axis + ""); + } + } + /** * Returns the desired block state at a given (X, Y, Z) position relative to the origin (0, 0, 0). * diff --git a/src/api/java/baritone/api/utils/SettingsUtil.java b/src/api/java/baritone/api/utils/SettingsUtil.java index 85ee57b88..c3608ecae 100644 --- a/src/api/java/baritone/api/utils/SettingsUtil.java +++ b/src/api/java/baritone/api/utils/SettingsUtil.java @@ -20,6 +20,7 @@ package baritone.api.utils; import baritone.api.Settings; import net.minecraft.client.Minecraft; import net.minecraft.item.Item; +import net.minecraft.util.EnumFacing; import net.minecraft.util.ResourceLocation; import net.minecraft.util.registry.IRegistry; @@ -147,7 +148,8 @@ public class SettingsUtil { LONG(Long.class, Long::parseLong), ITEM_LIST(ArrayList.class, str -> Stream.of(str.split(",")).map(ResourceLocation::new).map(IRegistry.ITEM::get).collect(Collectors.toCollection(ArrayList::new)), list -> ((ArrayList) list).stream().map(IRegistry.ITEM::getKey).map(ResourceLocation::toString).collect(Collectors.joining(","))), - COLOR(Color.class, str -> new Color(Integer.parseInt(str.split(",")[0]), Integer.parseInt(str.split(",")[1]), Integer.parseInt(str.split(",")[2])), color -> color.getRed() + "," + color.getGreen() + "," + color.getBlue()); + COLOR(Color.class, str -> new Color(Integer.parseInt(str.split(",")[0]), Integer.parseInt(str.split(",")[1]), Integer.parseInt(str.split(",")[2])), color -> color.getRed() + "," + color.getGreen() + "," + color.getBlue()), + ENUMFACING(EnumFacing.class, EnumFacing::byName); Class klass; diff --git a/src/main/java/baritone/behavior/LookBehavior.java b/src/main/java/baritone/behavior/LookBehavior.java index e2cd39a09..d6833a58f 100644 --- a/src/main/java/baritone/behavior/LookBehavior.java +++ b/src/main/java/baritone/behavior/LookBehavior.java @@ -69,7 +69,7 @@ public final class LookBehavior extends Behavior implements ILookBehavior { float oldPitch = ctx.player().rotationPitch; float desiredPitch = this.target.getPitch(); ctx.player().rotationPitch = desiredPitch; - if (desiredPitch == oldPitch && Baritone.settings().freeLook.value) { + if (desiredPitch == oldPitch && !Baritone.settings().freeLook.value) { nudgeToLevel(); } this.target = null; diff --git a/src/main/java/baritone/cache/WorldScanner.java b/src/main/java/baritone/cache/WorldScanner.java index 7cdbe1e81..b3dc6664e 100644 --- a/src/main/java/baritone/cache/WorldScanner.java +++ b/src/main/java/baritone/cache/WorldScanner.java @@ -134,6 +134,7 @@ public enum WorldScanner implements IWorldScanner { } else { if (foundWithinY) { // have found within Y in this chunk, so don't need to consider outside Y + // TODO continue iteration to one more sorted Y coordinate block return true; } } diff --git a/src/main/java/baritone/pathing/movement/movements/MovementTraverse.java b/src/main/java/baritone/pathing/movement/movements/MovementTraverse.java index 285a1c959..045c988e7 100644 --- a/src/main/java/baritone/pathing/movement/movements/MovementTraverse.java +++ b/src/main/java/baritone/pathing/movement/movements/MovementTraverse.java @@ -30,10 +30,7 @@ import baritone.pathing.movement.Movement; import baritone.pathing.movement.MovementHelper; import baritone.pathing.movement.MovementState; import baritone.utils.BlockStateInterface; -import net.minecraft.block.Block; -import net.minecraft.block.BlockDoor; -import net.minecraft.block.BlockFenceGate; -import net.minecraft.block.BlockSlab; +import net.minecraft.block.*; import net.minecraft.block.state.IBlockState; import net.minecraft.fluid.WaterFluid; import net.minecraft.init.Blocks; @@ -154,6 +151,8 @@ public class MovementTraverse extends Movement { @Override public MovementState updateState(MovementState state) { super.updateState(state); + IBlockState pb0 = BlockStateInterface.get(ctx, positionsToBreak[0]); + IBlockState pb1 = BlockStateInterface.get(ctx, positionsToBreak[1]); if (state.getStatus() != MovementStatus.RUNNING) { // if the setting is enabled if (!Baritone.settings().walkWhileBreaking.value) { @@ -164,10 +163,10 @@ public class MovementTraverse extends Movement { return state; } // and if it's fine to walk into the blocks in front - if (MovementHelper.avoidWalkingInto(BlockStateInterface.get(ctx, positionsToBreak[0]))) { + if (MovementHelper.avoidWalkingInto(pb0)) { return state; } - if (MovementHelper.avoidWalkingInto(BlockStateInterface.get(ctx, positionsToBreak[1]))) { + if (MovementHelper.avoidWalkingInto(pb1)) { return state; } // and we aren't already pressed up against the block @@ -180,6 +179,10 @@ public class MovementTraverse extends Movement { // it's safe to do this since the two blocks we break (in a traverse) are right on top of each other and so will have the same yaw float yawToDest = RotationUtils.calcRotationFromVec3d(ctx.playerHead(), VecUtils.calculateBlockCenter(ctx.world(), dest), ctx.playerRotations()).getYaw(); float pitchToBreak = state.getTarget().getRotation().get().getPitch(); + if ((pb0.isFullCube() || pb0.getBlock() instanceof BlockAir && (pb1.isFullCube() || pb1.getBlock() instanceof BlockAir))) { + // in the meantime, before we're right up against the block, we can break efficiently at this angle + pitchToBreak = 26; + } state.setTarget(new MovementState.MovementTarget(new Rotation(yawToDest, pitchToBreak), true)); return state.setInput(Input.MOVE_FORWARD, true).setInput(Input.SPRINT, true); @@ -190,8 +193,6 @@ public class MovementTraverse extends Movement { Block fd = BlockStateInterface.get(ctx, src.down()).getBlock(); boolean ladder = fd == Blocks.LADDER || fd == Blocks.VINE; - IBlockState pb0 = BlockStateInterface.get(ctx, positionsToBreak[0]); - IBlockState pb1 = BlockStateInterface.get(ctx, positionsToBreak[1]); boolean door = pb0.getBlock() instanceof BlockDoor || pb1.getBlock() instanceof BlockDoor; if (door) { diff --git a/src/main/java/baritone/process/BuilderProcess.java b/src/main/java/baritone/process/BuilderProcess.java index 2eb10425a..f4280269e 100644 --- a/src/main/java/baritone/process/BuilderProcess.java +++ b/src/main/java/baritone/process/BuilderProcess.java @@ -62,10 +62,12 @@ public class BuilderProcess extends BaritoneProcessHelper implements IBuilderPro private HashSet incorrectPositions; private String name; + private ISchematic realSchematic; private ISchematic schematic; private Vec3i origin; private int ticks; private boolean paused; + private int layer; public BuilderProcess(Baritone baritone) { super(baritone); @@ -81,8 +83,10 @@ public class BuilderProcess extends BaritoneProcessHelper implements IBuilderPro public void build(String name, ISchematic schematic, Vec3i origin) { this.name = name; this.schematic = schematic; + this.realSchematic = null; this.origin = origin; this.paused = false; + this.layer = 0; } public void resume() { @@ -299,24 +303,66 @@ public class BuilderProcess extends BaritoneProcessHelper implements IBuilderPro @Override public PathingCommand onTick(boolean calcFailed, boolean isSafeToCancel) { - baritone.getInputOverrideHandler().clearAllKeys(); - if (paused) { - return new PathingCommand(null, PathingCommandType.REQUEST_PAUSE); - } - BuilderCalculationContext bcc = new BuilderCalculationContext(); - if (!recalc(bcc)) { - logDirect("Done building"); - onLostControl(); - return null; - } - trim(bcc); if (baritone.getInputOverrideHandler().isInputForcedDown(Input.CLICK_LEFT)) { ticks = 5; } else { ticks--; } - Optional> toBreak = toBreakNearPlayer(bcc); baritone.getInputOverrideHandler().clearAllKeys(); + if (paused) { + return new PathingCommand(null, PathingCommandType.REQUEST_PAUSE); + } + if (Baritone.settings().buildInLayers.value) { + if (realSchematic == null) { + realSchematic = schematic; + } + schematic = new ISchematic() { + @Override + public IBlockState desiredState(int x, int y, int z) { + return realSchematic.desiredState(x, y, z); + } + + @Override + public int widthX() { + return realSchematic.widthX(); + } + + @Override + public int heightY() { + return layer; + } + + @Override + public int lengthZ() { + return realSchematic.lengthZ(); + } + }; + } + BuilderCalculationContext bcc = new BuilderCalculationContext(); + if (!recalc(bcc)) { + if (Baritone.settings().buildInLayers.value && layer < realSchematic.heightY()) { + logDirect("Starting layer " + layer); + layer++; + return onTick(calcFailed, isSafeToCancel); + } + int distance = Baritone.settings().buildRepeatDistance.value; + EnumFacing direction = Baritone.settings().buildRepeatDirection.value; + if (distance == 0) { + logDirect("Done building"); + onLostControl(); + return null; + } + // build repeat time + if (distance == -1) { + distance = schematic.size(direction.getAxis()); + } + layer = 0; + origin = new BlockPos(origin).offset(direction, distance); + logDirect("Repeating build " + distance + " blocks to the " + direction + ", new origin is " + origin); + } + trim(bcc); + + Optional> toBreak = toBreakNearPlayer(bcc); if (toBreak.isPresent() && isSafeToCancel && ctx.player().onGround) { // we'd like to pause to break this block // only change look direction if it's safe (don't want to fuck up an in progress parkour for example @@ -558,6 +604,8 @@ public class BuilderProcess extends BaritoneProcessHelper implements IBuilderPro incorrectPositions = null; name = null; schematic = null; + realSchematic = null; + layer = 0; paused = false; } diff --git a/src/main/java/baritone/utils/ExampleBaritoneControl.java b/src/main/java/baritone/utils/ExampleBaritoneControl.java index e77c5e7cf..6908b3cb5 100644 --- a/src/main/java/baritone/utils/ExampleBaritoneControl.java +++ b/src/main/java/baritone/utils/ExampleBaritoneControl.java @@ -366,6 +366,11 @@ public class ExampleBaritoneControl extends Behavior implements Helper { logDirect("Baritone settings reset"); return true; } + if (msg.equals("tunnel")) { + customGoalProcess.setGoalAndPath(new GoalStrictDirection(ctx.playerFeet(), ctx.player().getHorizontalFacing())); + logDirect("tunneling"); + return true; + } if (msg.equals("render")) { BetterBlockPos pf = ctx.playerFeet(); Minecraft.getInstance().worldRenderer.markBlockRangeForRenderUpdate(pf.x - 500, pf.y - 500, pf.z - 500, pf.x + 500, pf.y + 500, pf.z + 500);