diff --git a/src/api/java/baritone/api/utils/IPlayerContext.java b/src/api/java/baritone/api/utils/IPlayerContext.java index b461c389..8ce3271b 100644 --- a/src/api/java/baritone/api/utils/IPlayerContext.java +++ b/src/api/java/baritone/api/utils/IPlayerContext.java @@ -77,6 +77,10 @@ public interface IPlayerContext { return new Rotation(player().rotationYaw, player().rotationPitch); } + static double eyeHeight(boolean ifSneaking) { + return ifSneaking ? 1.54 : 1.62; + } + /** * Returns the block that the crosshair is currently placed over. Updated once per tick. * diff --git a/src/api/java/baritone/api/utils/RayTraceUtils.java b/src/api/java/baritone/api/utils/RayTraceUtils.java index 0fd1e4e0..4f763e39 100644 --- a/src/api/java/baritone/api/utils/RayTraceUtils.java +++ b/src/api/java/baritone/api/utils/RayTraceUtils.java @@ -40,7 +40,16 @@ public final class RayTraceUtils { * @return The calculated raytrace result */ public static RayTraceResult rayTraceTowards(Entity entity, Rotation rotation, double blockReachDistance) { - Vec3d start = entity.getPositionEyes(1.0F); + return rayTraceTowards(entity, rotation, blockReachDistance, false); + } + + public static RayTraceResult rayTraceTowards(Entity entity, Rotation rotation, double blockReachDistance, boolean wouldSneak) { + Vec3d start; + if (wouldSneak) { + start = inferSneakingEyePosition(entity); + } else { + start = entity.getPositionEyes(1.0F); // do whatever is correct + } Vec3d direction = RotationUtils.calcVec3dFromRotation(rotation); Vec3d end = start.add( direction.x * blockReachDistance, @@ -49,4 +58,8 @@ public final class RayTraceUtils { ); return entity.world.rayTraceBlocks(start, end, false, false, true); } + + public static Vec3d inferSneakingEyePosition(Entity entity) { + return new Vec3d(entity.posX, entity.posY + IPlayerContext.eyeHeight(true), entity.posZ); + } } diff --git a/src/api/java/baritone/api/utils/RotationUtils.java b/src/api/java/baritone/api/utils/RotationUtils.java index e19f531d..39e68fd4 100644 --- a/src/api/java/baritone/api/utils/RotationUtils.java +++ b/src/api/java/baritone/api/utils/RotationUtils.java @@ -140,6 +140,10 @@ public final class RotationUtils { return reachable(ctx.player(), pos, ctx.playerController().getBlockReachDistance()); } + public static Optional reachable(IPlayerContext ctx, BlockPos pos, boolean wouldSneak) { + return reachable(ctx.player(), pos, ctx.playerController().getBlockReachDistance(), wouldSneak); + } + /** * Determines if the specified entity is able to reach the center of any of the sides * of the specified block. It first checks if the block center is reachable, and if so, @@ -153,6 +157,10 @@ public final class RotationUtils { * @return The optional rotation */ public static Optional reachable(EntityPlayerSP entity, BlockPos pos, double blockReachDistance) { + return reachable(entity, pos, blockReachDistance, false); + } + + public static Optional reachable(EntityPlayerSP entity, BlockPos pos, double blockReachDistance, boolean wouldSneak) { IBaritone baritone = BaritoneAPI.getProvider().getBaritoneForPlayer(entity); if (baritone.getPlayerContext().isLookingAt(pos)) { /* @@ -165,9 +173,18 @@ public final class RotationUtils { * * or if you're a normal person literally all this does it ensure that we don't nudge the pitch to a normal level */ - return Optional.of(new Rotation(entity.rotationYaw, entity.rotationPitch + 0.0001F)); + Rotation hypothetical = new Rotation(entity.rotationYaw, entity.rotationPitch + 0.0001F); + if (wouldSneak) { + // the concern here is: what if we're looking at it now, but as soon as we start sneaking we no longer are + RayTraceResult result = RayTraceUtils.rayTraceTowards(entity, hypothetical, blockReachDistance, true); + if (result != null && result.typeOfHit == RayTraceResult.Type.BLOCK && result.getBlockPos().equals(pos)) { + return Optional.of(hypothetical); // yes, if we sneaked we would still be looking at the block + } + } else { + return Optional.of(hypothetical); + } } - Optional possibleRotation = reachableCenter(entity, pos, blockReachDistance); + Optional possibleRotation = reachableCenter(entity, pos, blockReachDistance, wouldSneak); //System.out.println("center: " + possibleRotation); if (possibleRotation.isPresent()) { return possibleRotation; @@ -179,7 +196,7 @@ public final class RotationUtils { double xDiff = aabb.minX * sideOffset.x + aabb.maxX * (1 - sideOffset.x); double yDiff = aabb.minY * sideOffset.y + aabb.maxY * (1 - sideOffset.y); double zDiff = aabb.minZ * sideOffset.z + aabb.maxZ * (1 - sideOffset.z); - possibleRotation = reachableOffset(entity, pos, new Vec3d(pos).add(xDiff, yDiff, zDiff), blockReachDistance); + possibleRotation = reachableOffset(entity, pos, new Vec3d(pos).add(xDiff, yDiff, zDiff), blockReachDistance, wouldSneak); if (possibleRotation.isPresent()) { return possibleRotation; } @@ -198,9 +215,10 @@ public final class RotationUtils { * @param blockReachDistance The block reach distance of the entity * @return The optional rotation */ - public static Optional reachableOffset(Entity entity, BlockPos pos, Vec3d offsetPos, double blockReachDistance) { - Rotation rotation = calcRotationFromVec3d(entity.getPositionEyes(1.0F), offsetPos, new Rotation(entity.rotationYaw, entity.rotationPitch)); - RayTraceResult result = RayTraceUtils.rayTraceTowards(entity, rotation, blockReachDistance); + public static Optional reachableOffset(Entity entity, BlockPos pos, Vec3d offsetPos, double blockReachDistance, boolean wouldSneak) { + Vec3d eyes = wouldSneak ? RayTraceUtils.inferSneakingEyePosition(entity) : entity.getPositionEyes(1.0F); + Rotation rotation = calcRotationFromVec3d(eyes, offsetPos, new Rotation(entity.rotationYaw, entity.rotationPitch)); + RayTraceResult result = RayTraceUtils.rayTraceTowards(entity, rotation, blockReachDistance, wouldSneak); //System.out.println(result); if (result != null && result.typeOfHit == RayTraceResult.Type.BLOCK) { if (result.getBlockPos().equals(pos)) { @@ -222,7 +240,7 @@ public final class RotationUtils { * @param blockReachDistance The block reach distance of the entity * @return The optional rotation */ - public static Optional reachableCenter(Entity entity, BlockPos pos, double blockReachDistance) { - return reachableOffset(entity, pos, VecUtils.calculateBlockCenter(entity.world, pos), blockReachDistance); + public static Optional reachableCenter(Entity entity, BlockPos pos, double blockReachDistance, boolean wouldSneak) { + return reachableOffset(entity, pos, VecUtils.calculateBlockCenter(entity.world, pos), blockReachDistance, wouldSneak); } } diff --git a/src/main/java/baritone/pathing/movement/Movement.java b/src/main/java/baritone/pathing/movement/Movement.java index ca4abe9e..c46b24de 100644 --- a/src/main/java/baritone/pathing/movement/Movement.java +++ b/src/main/java/baritone/pathing/movement/Movement.java @@ -177,7 +177,7 @@ public abstract class Movement implements IMovement, MovementHelper { //i'm doing it anyway //i dont care if theres snow in the way!!!!!!! //you dont own me!!!! - state.setTarget(new MovementState.MovementTarget(RotationUtils.calcRotationFromVec3d(ctx.player().getPositionEyes(1.0F), + state.setTarget(new MovementState.MovementTarget(RotationUtils.calcRotationFromVec3d(ctx.playerHead(), VecUtils.getBlockPosCenter(blockPos), ctx.playerRotations()), true) ); // don't check selectedblock on this one, this is a fallback when we can't see any face directly, it's intended to be breaking the "incorrect" block diff --git a/src/main/java/baritone/pathing/movement/MovementHelper.java b/src/main/java/baritone/pathing/movement/MovementHelper.java index 31a1de7a..7e1c567a 100644 --- a/src/main/java/baritone/pathing/movement/MovementHelper.java +++ b/src/main/java/baritone/pathing/movement/MovementHelper.java @@ -502,9 +502,9 @@ public interface MovementHelper extends ActionCosts, Helper { } - static PlaceResult attemptToPlaceABlock(MovementState state, IBaritone baritone, BlockPos placeAt, boolean preferDown) { + static PlaceResult attemptToPlaceABlock(MovementState state, IBaritone baritone, BlockPos placeAt, boolean preferDown, boolean wouldSneak) { IPlayerContext ctx = baritone.getPlayerContext(); - Optional direct = RotationUtils.reachable(ctx, placeAt); // we assume that if there is a block there, it must be replacable + Optional direct = RotationUtils.reachable(ctx, placeAt, wouldSneak); // we assume that if there is a block there, it must be replacable boolean found = false; if (direct.isPresent()) { state.setTarget(new MovementState.MovementTarget(direct.get(), true)); @@ -522,7 +522,7 @@ public interface MovementHelper extends ActionCosts, Helper { double faceY = (placeAt.getY() + against1.getY() + 0.5D) * 0.5D; double faceZ = (placeAt.getZ() + against1.getZ() + 1.0D) * 0.5D; Rotation place = RotationUtils.calcRotationFromVec3d(ctx.playerHead(), new Vec3d(faceX, faceY, faceZ), ctx.playerRotations()); - RayTraceResult res = RayTraceUtils.rayTraceTowards(ctx.player(), place, ctx.playerController().getBlockReachDistance()); + RayTraceResult res = RayTraceUtils.rayTraceTowards(ctx.player(), place, ctx.playerController().getBlockReachDistance(), wouldSneak); if (res != null && res.typeOfHit == RayTraceResult.Type.BLOCK && res.getBlockPos().equals(against1) && res.getBlockPos().offset(res.sideHit).equals(placeAt)) { state.setTarget(new MovementState.MovementTarget(place, true)); found = true; @@ -540,11 +540,17 @@ public interface MovementHelper extends ActionCosts, Helper { EnumFacing side = ctx.objectMouseOver().sideHit; // only way for selectedBlock.equals(placeAt) to be true is if it's replacable if (selectedBlock.equals(placeAt) || (MovementHelper.canPlaceAgainst(ctx, selectedBlock) && selectedBlock.offset(side).equals(placeAt))) { + if (wouldSneak) { + state.setInput(Input.SNEAK, true); + } ((Baritone) baritone).getInventoryBehavior().selectThrowawayForLocation(true, placeAt.getX(), placeAt.getY(), placeAt.getZ()); return PlaceResult.READY_TO_PLACE; } } if (found) { + if (wouldSneak) { + state.setInput(Input.SNEAK, true); + } ((Baritone) baritone).getInventoryBehavior().selectThrowawayForLocation(true, placeAt.getX(), placeAt.getY(), placeAt.getZ()); return PlaceResult.ATTEMPTING; } diff --git a/src/main/java/baritone/pathing/movement/movements/MovementAscend.java b/src/main/java/baritone/pathing/movement/movements/MovementAscend.java index 4f35ef8e..161ffdac 100644 --- a/src/main/java/baritone/pathing/movement/movements/MovementAscend.java +++ b/src/main/java/baritone/pathing/movement/movements/MovementAscend.java @@ -175,7 +175,7 @@ public class MovementAscend extends Movement { IBlockState jumpingOnto = BlockStateInterface.get(ctx, positionToPlace); if (!MovementHelper.canWalkOn(ctx, positionToPlace, jumpingOnto)) { ticksWithoutPlacement++; - if (MovementHelper.attemptToPlaceABlock(state, baritone, dest.down(), false) == PlaceResult.READY_TO_PLACE) { + if (MovementHelper.attemptToPlaceABlock(state, baritone, dest.down(), false, true) == PlaceResult.READY_TO_PLACE) { state.setInput(Input.SNEAK, true); if (ctx.player().isSneaking()) { state.setInput(Input.CLICK_RIGHT, true); diff --git a/src/main/java/baritone/pathing/movement/movements/MovementDescend.java b/src/main/java/baritone/pathing/movement/movements/MovementDescend.java index 67b7cd95..128d1bf9 100644 --- a/src/main/java/baritone/pathing/movement/movements/MovementDescend.java +++ b/src/main/java/baritone/pathing/movement/movements/MovementDescend.java @@ -224,7 +224,7 @@ public class MovementDescend extends Movement { double destZ = (src.getZ() + 0.5) * 0.17 + (dest.getZ() + 0.5) * 0.83; EntityPlayerSP player = ctx.player(); state.setTarget(new MovementState.MovementTarget( - new Rotation(RotationUtils.calcRotationFromVec3d(player.getPositionEyes(1.0F), + new Rotation(RotationUtils.calcRotationFromVec3d(ctx.playerHead(), new Vec3d(destX, dest.getY(), destZ), new Rotation(player.rotationYaw, player.rotationPitch)).getYaw(), player.rotationPitch), false diff --git a/src/main/java/baritone/pathing/movement/movements/MovementParkour.java b/src/main/java/baritone/pathing/movement/movements/MovementParkour.java index 3d3426da..b9a0fd44 100644 --- a/src/main/java/baritone/pathing/movement/movements/MovementParkour.java +++ b/src/main/java/baritone/pathing/movement/movements/MovementParkour.java @@ -250,7 +250,7 @@ public class MovementParkour extends Movement { } } else if (!ctx.playerFeet().equals(src)) { if (ctx.playerFeet().equals(src.offset(direction)) || ctx.player().posY - src.y > 0.0001) { - if (!MovementHelper.canWalkOn(ctx, dest.down()) && !ctx.player().onGround && MovementHelper.attemptToPlaceABlock(state, baritone, dest.down(), true) == PlaceResult.READY_TO_PLACE) { + if (!MovementHelper.canWalkOn(ctx, dest.down()) && !ctx.player().onGround && MovementHelper.attemptToPlaceABlock(state, baritone, dest.down(), true, false) == PlaceResult.READY_TO_PLACE) { // go in the opposite order to check DOWN before all horizontals -- down is preferable because you don't have to look to the side while in midair, which could mess up the trajectory state.setInput(Input.CLICK_RIGHT, true); } diff --git a/src/main/java/baritone/pathing/movement/movements/MovementPillar.java b/src/main/java/baritone/pathing/movement/movements/MovementPillar.java index f6f8fc0d..b9d59933 100644 --- a/src/main/java/baritone/pathing/movement/movements/MovementPillar.java +++ b/src/main/java/baritone/pathing/movement/movements/MovementPillar.java @@ -184,7 +184,7 @@ public class MovementPillar extends Movement { } boolean ladder = fromDown.getBlock() == Blocks.LADDER || fromDown.getBlock() == Blocks.VINE; boolean vine = fromDown.getBlock() == Blocks.VINE; - Rotation rotation = RotationUtils.calcRotationFromVec3d(ctx.player().getPositionEyes(1.0F), + Rotation rotation = RotationUtils.calcRotationFromVec3d(ctx.playerHead(), VecUtils.getBlockPosCenter(positionToPlace), new Rotation(ctx.player().rotationYaw, ctx.player().rotationPitch)); if (!ladder) { diff --git a/src/main/java/baritone/pathing/movement/movements/MovementTraverse.java b/src/main/java/baritone/pathing/movement/movements/MovementTraverse.java index 9990ed74..1ecf0f92 100644 --- a/src/main/java/baritone/pathing/movement/movements/MovementTraverse.java +++ b/src/main/java/baritone/pathing/movement/movements/MovementTraverse.java @@ -280,7 +280,7 @@ public class MovementTraverse extends Movement { } } double dist1 = Math.max(Math.abs(ctx.player().posX - (dest.getX() + 0.5D)), Math.abs(ctx.player().posZ - (dest.getZ() + 0.5D))); - PlaceResult p = MovementHelper.attemptToPlaceABlock(state, baritone, dest.down(), false); + PlaceResult p = MovementHelper.attemptToPlaceABlock(state, baritone, dest.down(), false, true); if ((p == PlaceResult.READY_TO_PLACE || dist1 < 0.6) && !Baritone.settings().assumeSafeWalk.value) { state.setInput(Input.SNEAK, true); } diff --git a/src/main/java/baritone/process/BackfillProcess.java b/src/main/java/baritone/process/BackfillProcess.java index f025c393..04b3ca78 100644 --- a/src/main/java/baritone/process/BackfillProcess.java +++ b/src/main/java/baritone/process/BackfillProcess.java @@ -75,7 +75,7 @@ public final class BackfillProcess extends BaritoneProcessHelper { baritone.getInputOverrideHandler().clearAllKeys(); for (BlockPos toPlace : toFillIn()) { MovementState fake = new MovementState(); - switch (MovementHelper.attemptToPlaceABlock(fake, baritone, toPlace, false)) { + switch (MovementHelper.attemptToPlaceABlock(fake, baritone, toPlace, false, false)) { case NO_OPTION: continue; case READY_TO_PLACE: diff --git a/src/main/java/baritone/process/FarmProcess.java b/src/main/java/baritone/process/FarmProcess.java index 00273a9f..a91fda60 100644 --- a/src/main/java/baritone/process/FarmProcess.java +++ b/src/main/java/baritone/process/FarmProcess.java @@ -232,7 +232,7 @@ public final class FarmProcess extends BaritoneProcessHelper implements IFarmPro both.addAll(openSoulsand); for (BlockPos pos : both) { boolean soulsand = openSoulsand.contains(pos); - Optional rot = RotationUtils.reachableOffset(ctx.player(), pos, new Vec3d(pos.getX() + 0.5, pos.getY() + 1, pos.getZ() + 0.5), ctx.playerController().getBlockReachDistance()); + Optional rot = RotationUtils.reachableOffset(ctx.player(), pos, new Vec3d(pos.getX() + 0.5, pos.getY() + 1, pos.getZ() + 0.5), ctx.playerController().getBlockReachDistance(), false); if (rot.isPresent() && isSafeToCancel && baritone.getInventoryBehavior().throwaway(true, soulsand ? this::isNetherWart : this::isPlantable)) { RayTraceResult result = RayTraceUtils.rayTraceTowards(ctx.player(), rot.get(), ctx.playerController().getBlockReachDistance()); if (result.typeOfHit == RayTraceResult.Type.BLOCK && result.sideHit == EnumFacing.UP) {