diff --git a/src/api/java/baritone/api/Settings.java b/src/api/java/baritone/api/Settings.java index 43ace5e31..dbf2e849d 100644 --- a/src/api/java/baritone/api/Settings.java +++ b/src/api/java/baritone/api/Settings.java @@ -147,12 +147,6 @@ public final class Settings { */ public final Setting strictLiquidCheck = new Setting<>(false); - /** - * Allow Baritone to fall arbitrary distances and place a water bucket beneath it. - * Reliability: questionable. - */ - public final Setting allowWaterBucketFall = new Setting<>(true); - /** * Allow Baritone to assume it can walk on still water just like any other block. * This functionality is assumed to be provided by a separate library that might have imported Baritone. @@ -550,17 +544,17 @@ public final class Settings { public final Setting pathingMapLoadFactor = new Setting<>(0.75f); /** - * How far are you allowed to fall onto solid ground (without a water bucket)? + * How far are you allowed to fall onto solid ground (without clutching)? * 3 won't deal any damage. But if you just want to get down the mountain quickly and you have * Feather Falling IV, you might set it a bit higher, like 4 or 5. */ - public final Setting maxFallHeightNoWater = new Setting<>(3); + public final Setting maxFallHeightNoClutch = new Setting<>(3); /** - * How far are you allowed to fall onto solid ground (with a water bucket)? + * How far are you allowed to fall onto solid ground (while clutching)? * It's not that reliable, so I've set it below what would kill an unarmored player (23) */ - public final Setting maxFallHeightBucket = new Setting<>(20); + public final Setting maxFallHeightClutch = new Setting<>(20); /** * Is it okay to sprint through a descend followed by a diagonal? diff --git a/src/api/java/baritone/api/pathing/movement/ActionCosts.java b/src/api/java/baritone/api/pathing/movement/ActionCosts.java index 691d73b4d..c9ca41e9e 100644 --- a/src/api/java/baritone/api/pathing/movement/ActionCosts.java +++ b/src/api/java/baritone/api/pathing/movement/ActionCosts.java @@ -17,6 +17,8 @@ package baritone.api.pathing.movement; +import baritone.api.utils.Pair; + public interface ActionCosts { /** @@ -76,10 +78,15 @@ static double velocity(int ticks) { return (Math.pow(0.98, ticks) - 1) * -3.92; } - static double oldFormula(double ticks) { - return -3.92 * (99 - 49.5 * (Math.pow(0.98, ticks) + 1) - ticks); + static double velocity(int ticks, double distanceMultiplier, double startingVelocity) { + double velocity = startingVelocity; + for (int i = 0; i < ticks; i++) { + velocity = 0.98 * (velocity + distanceMultiplier); + } + return velocity; } + static double distanceToTicks(double distance) { if (distance == 0) { return 0; // Avoid 0/0 NaN @@ -95,4 +102,47 @@ static double distanceToTicks(double distance) { tickCount++; } } + + static double distanceToTicks(double distance, double distanceMultiplier, double startingVelocity) { + if (distance == 0) { + return 0d; // Avoid 0/0 NaN + } + double tmpDistance = distance; + int tickCount = 0; + while (true) { + double velocity = velocity(tickCount, distanceMultiplier, startingVelocity); + if (tmpDistance <= velocity) { + return tickCount + tmpDistance / velocity; + } + tmpDistance -= velocity; + tickCount++; + } + } + + static Pair distanceToTicks(double distance, double endBlockHeight, double endBlockSpeedMultiplier, double startingVelocity) { + if (distance == 0) { + return new Pair<>(0d, startingVelocity); + } + double tmpDistance = distance; + int tickCount = 0; + boolean firstTick = true; + while (true) { + double velocity; + if (tmpDistance < endBlockHeight) { + if (firstTick) { + firstTick = false; + velocity = velocity(tickCount, 0.08d, startingVelocity) * endBlockSpeedMultiplier; + } else { + velocity = 0.0784d * endBlockSpeedMultiplier; + } + } else { + velocity = velocity(tickCount, 0.08d, startingVelocity); + } + if (tmpDistance <= velocity) { + return new Pair<>(tickCount + tmpDistance / velocity, velocity); + } + tmpDistance -= velocity; + tickCount++; + } + } } diff --git a/src/api/java/baritone/api/utils/RayTraceUtils.java b/src/api/java/baritone/api/utils/RayTraceUtils.java index ed544302d..1c982957a 100644 --- a/src/api/java/baritone/api/utils/RayTraceUtils.java +++ b/src/api/java/baritone/api/utils/RayTraceUtils.java @@ -50,7 +50,7 @@ public static HitResult rayTraceTowards(Entity entity, Rotation rotation, double if (wouldSneak) { start = inferSneakingEyePosition(entity); } else { - start = entity.getEyePosition(1.0F); // do whatever is correct + start = entity.getEyePosition(); } Vec3 direction = RotationUtils.calcLookDirectionFromRotation(rotation); diff --git a/src/api/java/baritone/api/utils/RotationUtils.java b/src/api/java/baritone/api/utils/RotationUtils.java index bfab3fa87..7933822e6 100644 --- a/src/api/java/baritone/api/utils/RotationUtils.java +++ b/src/api/java/baritone/api/utils/RotationUtils.java @@ -186,6 +186,7 @@ public static Optional reachable(IPlayerContext ctx, BlockPos pos, dou * * or if you're a normal person literally all this does it ensure that we don't nudge the pitch to a normal level */ + // TODO This is a very hacky solution. Rotation hypothetical = ctx.playerRotations().add(new Rotation(0, 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 diff --git a/src/main/java/baritone/behavior/InventoryBehavior.java b/src/main/java/baritone/behavior/InventoryBehavior.java index 43a553d4d..1f1aef38c 100644 --- a/src/main/java/baritone/behavior/InventoryBehavior.java +++ b/src/main/java/baritone/behavior/InventoryBehavior.java @@ -167,17 +167,21 @@ public boolean hasGenericThrowaway() { return false; } - public boolean selectThrowawayForLocation(boolean select, int x, int y, int z) { + public boolean selectThrowawayForLocation(boolean select, int x, int y, int z, Item customItem) { BlockState maybe = baritone.getBuilderProcess().placeAt(x, y, z, baritone.bsi.get0(x, y, z)); - if (maybe != null && throwaway(select, stack -> stack.getItem() instanceof BlockItem && maybe.equals(((BlockItem) stack.getItem()).getBlock().getStateForPlacement(new BlockPlaceContext(new UseOnContext(ctx.world(), ctx.player(), InteractionHand.MAIN_HAND, stack, new BlockHitResult(new Vec3(ctx.player().position().x, ctx.player().position().y, ctx.player().position().z), Direction.UP, ctx.playerFeet(), false)) {}))))) { + if (maybe != null && throwaway(select, stack -> stack.getItem() instanceof BlockItem && maybe.equals(((BlockItem) stack.getItem()).getBlock().getStateForPlacement(new BlockPlaceContext(ctx.player(), InteractionHand.MAIN_HAND, stack, new BlockHitResult(new Vec3(ctx.player().position().x, ctx.player().position().y, ctx.player().position().z), Direction.UP, ctx.playerFeet(), false)))))) { return true; // gotem } if (maybe != null && throwaway(select, stack -> stack.getItem() instanceof BlockItem && ((BlockItem) stack.getItem()).getBlock().equals(maybe.getBlock()))) { return true; } - for (Item item : Baritone.settings().acceptableThrowawayItems.value) { - if (throwaway(select, stack -> item.equals(stack.getItem()))) { - return true; + if (customItem != null) { + return throwaway(select, stack -> stack.is(customItem)); + } else { + for (Item item : Baritone.settings().acceptableThrowawayItems.value) { + if (throwaway(select, stack -> item.equals(stack.getItem()))) { + return true; + } } } return false; @@ -225,8 +229,7 @@ public boolean throwaway(boolean select, Predicate desired, b for (int i = 9; i < 36; i++) { if (desired.test(inv.get(i))) { if (select) { - requestSwapWithHotBar(i, 7); - p.getInventory().selected = 7; + requestSwapWithHotBar(i, p.getInventory().selected); } return true; } diff --git a/src/main/java/baritone/pathing/clutch/Clutch.java b/src/main/java/baritone/pathing/clutch/Clutch.java new file mode 100644 index 000000000..f0c81fa40 --- /dev/null +++ b/src/main/java/baritone/pathing/clutch/Clutch.java @@ -0,0 +1,109 @@ +/* + * 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.pathing.clutch; + +import baritone.Baritone; +import baritone.api.IBaritone; +import baritone.api.pathing.movement.ActionCosts; +import baritone.api.utils.BetterBlockPos; +import baritone.api.utils.IPlayerContext; +import baritone.api.utils.Pair; +import baritone.pathing.movement.CalculationContext; +import baritone.pathing.movement.MovementHelper; +import baritone.pathing.movement.MovementState; +import baritone.utils.pathing.MutableClutchResult; +import net.minecraft.core.BlockPos; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.Vec3; +import net.minecraft.world.phys.shapes.Shapes; +import net.minecraft.world.phys.shapes.VoxelShape; + +public abstract class Clutch { + private final double costMultiplier; + + protected Clutch(double costMultiplier) { + this.costMultiplier = costMultiplier; + } + + protected Clutch() { + this(1d); + } + + public final ItemStack getClutchingItem(CalculationContext context) { // We could return the slot instead of the item + for (int slot = 0; slot < (Baritone.settings().allowInventory.value ? 36 : 9); slot++) { + ItemStack item = context.getBaritone().getPlayerContext().player().getInventory().items.get(slot); + if (isAcceptedItem(item.getItem())) { + return item; + } + } + return null; + } + + public abstract boolean isAcceptedItem(Item item); + + public abstract boolean compare(BlockState state); + + public boolean isSolid(CalculationContext context) { + return false; + } + + public boolean isPlaceable(CalculationContext context, int x, int y, int z, BlockState block) { + return MovementHelper.canPlaceAgainst(context.bsi, x, y, z, block); + } + + public boolean clutch(IBaritone baritone, MovementState state, BlockPos dest, MutableClutchResult result) { + return ClutchUtils.blockClutch(baritone, state, dest, result, true); + } + + public boolean hasClutched(IPlayerContext ctx, BetterBlockPos dest, BlockState destState) { + VoxelShape shape = destState.getCollisionShape(ctx.world(), dest); + if (shape.isEmpty()) { + return ctx.player().getBoundingBox().intersects(dest.x, dest.y, dest.z, dest.x + 1, dest.y + 1, dest.z + 1); + } else { + return ctx.player().getBoundingBox().intersects( + dest.x + shape.bounds().minX, dest.x + shape.bounds().minY, dest.x + shape.bounds().minZ, + dest.x + shape.bounds().maxX, dest.x + shape.bounds().maxY, dest.x + shape.bounds().maxZ); + } + } + + public boolean isFinished(IPlayerContext ctx, MovementState state, MutableClutchResult result) { + return true; + } + + public float getFallDamage(int fallDamage) { + return 0f; + } + + public Pair getCost(double distance, double endBlockHeight, double velocity) { + return ActionCosts.distanceToTicks(distance, endBlockHeight, costMultiplier, velocity); + } + + public double getAdditionalCost() { + return 0d; + } + + public boolean slowsOnTopBlock() { + return true; + } + + public boolean topBlockPriority() { + return true; + } +} diff --git a/src/main/java/baritone/pathing/clutch/ClutchUtils.java b/src/main/java/baritone/pathing/clutch/ClutchUtils.java new file mode 100644 index 000000000..9ee54b9a9 --- /dev/null +++ b/src/main/java/baritone/pathing/clutch/ClutchUtils.java @@ -0,0 +1,66 @@ +/* + * 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.pathing.clutch; + +import baritone.api.IBaritone; +import baritone.api.utils.input.Input; +import baritone.pathing.clutch.clutches.*; +import baritone.pathing.movement.MovementHelper; +import baritone.pathing.movement.MovementState; +import baritone.utils.pathing.MutableClutchResult; +import net.minecraft.core.BlockPos; +import net.minecraft.world.entity.player.Inventory; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.Items; + +public interface ClutchUtils { + // This list holds the order to try the clutches in. More convenient clutches should go further up. + Clutch[] CLUTCHES = new Clutch[]{ + WaterClutch.INSTANCE, + LavaClutch.INSTANCE, + PowderedSnowClutch.INSTANCE, + TwistingVineClutch.INSTANCE, + SweetBerryClutch.INSTANCE, + VineClutch.INSTANCE, + LadderClutch.INSTANCE, + ScaffoldingClutch.INSTANCE, + SlimeClutch.INSTANCE, + HayBaleClutch.INSTANCE, + CobwebClutch.INSTANCE, + BlockClutch.INSTANCE, + }; + ItemStack STACK_EMPTY_BUCKET = new ItemStack(Items.BUCKET); + + static boolean blockClutch(IBaritone baritone, MovementState state, BlockPos dest, MutableClutchResult result, boolean allowDown) { + if (MovementHelper.attemptToPlaceABlock(state, baritone, dest, allowDown, true, true, result.item.getItem()) == MovementHelper.PlaceResult.READY_TO_PLACE) { + state.setInput(Input.CLICK_RIGHT, true); + return true; + } else { + return false; + } + } + + static boolean bucketPickup(MovementState state, Inventory inventory) { + int slot = inventory.findSlotMatchingItem(STACK_EMPTY_BUCKET); + if (Inventory.isHotbarSlot(slot)) { + inventory.selected = slot; + state.setInput(Input.CLICK_RIGHT, true); + } + return slot == -1; + } +} diff --git a/src/main/java/baritone/pathing/clutch/clutches/BlockClutch.java b/src/main/java/baritone/pathing/clutch/clutches/BlockClutch.java new file mode 100644 index 000000000..86bd7930a --- /dev/null +++ b/src/main/java/baritone/pathing/clutch/clutches/BlockClutch.java @@ -0,0 +1,51 @@ +/* + * 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.pathing.clutch.clutches; + +import baritone.pathing.clutch.Clutch; +import baritone.pathing.movement.CalculationContext; +import net.minecraft.world.item.BlockItem; +import net.minecraft.world.item.Item; +import net.minecraft.world.level.block.state.BlockState; + +public class BlockClutch extends Clutch { + public static final BlockClutch INSTANCE = new BlockClutch(); + + private BlockClutch() {} + + @Override + public boolean isAcceptedItem(Item item) { + return item instanceof BlockItem blockItem && + !blockItem.getBlock().defaultBlockState().getCollisionShape(null, null).isEmpty(); + } + + @Override + public boolean compare(BlockState state) { + return !state.getCollisionShape(null, null).isEmpty(); + } + + @Override + public boolean isSolid(CalculationContext context) { + return true; + } + + @Override + public float getFallDamage(int fallDamage) { + return fallDamage; + } +} diff --git a/src/main/java/baritone/pathing/clutch/clutches/CobwebClutch.java b/src/main/java/baritone/pathing/clutch/clutches/CobwebClutch.java new file mode 100644 index 000000000..f4898df6f --- /dev/null +++ b/src/main/java/baritone/pathing/clutch/clutches/CobwebClutch.java @@ -0,0 +1,42 @@ +/* + * 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.pathing.clutch.clutches; + +import baritone.pathing.clutch.Clutch; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.Items; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.state.BlockState; + +public class CobwebClutch extends Clutch { + public static final CobwebClutch INSTANCE = new CobwebClutch(); + + private CobwebClutch() { + super(0.05d); + } + + @Override + public boolean compare(BlockState state) { + return state.is(Blocks.COBWEB); + } + + @Override + public boolean isAcceptedItem(Item item) { + return item.equals(Items.COBWEB); + } +} diff --git a/src/main/java/baritone/pathing/clutch/clutches/HayBaleClutch.java b/src/main/java/baritone/pathing/clutch/clutches/HayBaleClutch.java new file mode 100644 index 000000000..9fb103a23 --- /dev/null +++ b/src/main/java/baritone/pathing/clutch/clutches/HayBaleClutch.java @@ -0,0 +1,51 @@ +/* + * 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.pathing.clutch.clutches; + +import baritone.pathing.clutch.Clutch; +import baritone.pathing.movement.CalculationContext; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.Items; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.state.BlockState; + +public class HayBaleClutch extends Clutch { + public static final HayBaleClutch INSTANCE = new HayBaleClutch(); + + private HayBaleClutch() {} + + @Override + public boolean isAcceptedItem(Item item) { + return item.equals(Items.HAY_BLOCK); + } + + @Override + public boolean compare(BlockState state) { + return state.is(Blocks.HAY_BLOCK); + } + + @Override + public boolean isSolid(CalculationContext context) { + return true; + } + + @Override + public float getFallDamage(int fallDamage) { + return fallDamage * 0.2f; + } +} diff --git a/src/main/java/baritone/pathing/clutch/clutches/LadderClutch.java b/src/main/java/baritone/pathing/clutch/clutches/LadderClutch.java new file mode 100644 index 000000000..711e17fb0 --- /dev/null +++ b/src/main/java/baritone/pathing/clutch/clutches/LadderClutch.java @@ -0,0 +1,67 @@ +/* + * 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.pathing.clutch.clutches; + +import baritone.api.IBaritone; +import baritone.api.utils.BetterBlockPos; +import baritone.api.utils.IPlayerContext; +import baritone.pathing.clutch.ClutchUtils; +import baritone.pathing.movement.CalculationContext; +import baritone.pathing.clutch.Clutch; +import baritone.pathing.movement.MovementHelper; +import baritone.pathing.movement.MovementState; +import baritone.utils.pathing.MutableClutchResult; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.Items; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.state.BlockState; + +public class LadderClutch extends Clutch { + public static final LadderClutch INSTANCE = new LadderClutch(); + + @Override + public boolean isAcceptedItem(Item item) { + return item.equals(Items.LADDER); + } + + @Override + public boolean compare(BlockState state) { + return state.is(Blocks.LADDER); + } + + @Override + public boolean isPlaceable(CalculationContext context, int x, int y, int z, BlockState block) { + return MovementHelper.canPlaceAgainst(context.bsi, x, y, z, block) && + (context.get(x - 1, y + 1, z).isFaceSturdy(context.bsi.access, new BetterBlockPos(x - 1, y + 1, z), Direction.EAST) || + context.get(x + 1, y + 1, z).isFaceSturdy(context.bsi.access, new BetterBlockPos(x + 1, y + 1, z), Direction.WEST) || + context.get(x, y + 1, z - 1).isFaceSturdy(context.bsi.access, new BetterBlockPos(x, y + 1, z - 1), Direction.SOUTH) || + context.get(x, y + 1, z + 1).isFaceSturdy(context.bsi.access, new BetterBlockPos(x, y + 1, z + 1), Direction.NORTH)); + } + + @Override + public boolean clutch(IBaritone baritone, MovementState state, BlockPos dest, MutableClutchResult result) { + return ClutchUtils.blockClutch(baritone, state, dest, result, false); + } + + @Override + public boolean hasClutched(IPlayerContext ctx, BetterBlockPos dest, BlockState destState) { + return ctx.player().getBoundingBox().intersects(dest.x, dest.y, dest.z, dest.x + 1, dest.y + 1, dest.z + 1); + } +} diff --git a/src/main/java/baritone/pathing/clutch/clutches/LavaClutch.java b/src/main/java/baritone/pathing/clutch/clutches/LavaClutch.java new file mode 100644 index 000000000..05f9d281f --- /dev/null +++ b/src/main/java/baritone/pathing/clutch/clutches/LavaClutch.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.pathing.clutch.clutches; + +import baritone.api.utils.IPlayerContext; +import baritone.pathing.clutch.Clutch; +import baritone.pathing.clutch.ClutchUtils; +import baritone.pathing.movement.CalculationContext; +import baritone.pathing.movement.MovementState; +import baritone.utils.pathing.MutableClutchResult; +import net.minecraft.world.effect.MobEffects; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.Items; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.material.LavaFluid; + +public class LavaClutch extends Clutch { + public static final LavaClutch INSTANCE = new LavaClutch(); + + private LavaClutch() {} + + @Override + public boolean isAcceptedItem(Item item) { + return item.equals(Items.LAVA_BUCKET); + } + + @Override + public boolean compare(BlockState state) { + return state.getFluidState().getType() instanceof LavaFluid; + } + + @Override + public boolean isPlaceable(CalculationContext context, int x, int y, int z, BlockState block) { + return (!context.considerPotionEffects || context.activeEffects.containsKey(MobEffects.FIRE_RESISTANCE)) && + super.isPlaceable(context, x, y, z, block); + } + + @Override + public boolean isFinished(IPlayerContext ctx, MovementState state, MutableClutchResult result) { + return ClutchUtils.bucketPickup(state, ctx.player().getInventory()); + } + + @Override + public boolean topBlockPriority() { + return false; + } +} diff --git a/src/main/java/baritone/pathing/clutch/clutches/PowderedSnowClutch.java b/src/main/java/baritone/pathing/clutch/clutches/PowderedSnowClutch.java new file mode 100644 index 000000000..a44cec48a --- /dev/null +++ b/src/main/java/baritone/pathing/clutch/clutches/PowderedSnowClutch.java @@ -0,0 +1,58 @@ +/* + * 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.pathing.clutch.clutches; + +import baritone.api.utils.IPlayerContext; +import baritone.pathing.clutch.ClutchUtils; +import baritone.pathing.clutch.Clutch; +import baritone.pathing.movement.CalculationContext; +import baritone.pathing.movement.MovementState; +import baritone.utils.pathing.MutableClutchResult; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.Items; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.state.BlockState; + +public class PowderedSnowClutch extends Clutch { + public static final PowderedSnowClutch INSTANCE = new PowderedSnowClutch(); + + @Override + public boolean isAcceptedItem(Item item) { + return item.equals(Items.POWDER_SNOW_BUCKET); + } + + @Override + public boolean compare(BlockState state) { + return state.is(Blocks.POWDER_SNOW); + } + + @Override + public boolean isSolid(CalculationContext context) { + return context.getBaritone().getPlayerContext().player().getInventory().getArmor(3).is(Items.LEATHER_BOOTS); + } + + @Override + public boolean isFinished(IPlayerContext ctx, MovementState state, MutableClutchResult result) { + return ClutchUtils.bucketPickup(state, ctx.player().getInventory()); + } + + @Override + public boolean slowsOnTopBlock() { + return false; + } +} \ No newline at end of file diff --git a/src/main/java/baritone/pathing/clutch/clutches/ScaffoldingClutch.java b/src/main/java/baritone/pathing/clutch/clutches/ScaffoldingClutch.java new file mode 100644 index 000000000..494cf1eae --- /dev/null +++ b/src/main/java/baritone/pathing/clutch/clutches/ScaffoldingClutch.java @@ -0,0 +1,55 @@ +/* + * 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.pathing.clutch.clutches; + +import baritone.api.utils.BetterBlockPos; +import baritone.api.utils.IPlayerContext; +import baritone.api.utils.input.Input; +import baritone.pathing.clutch.Clutch; +import baritone.pathing.movement.MovementState; +import baritone.utils.pathing.MutableClutchResult; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.Items; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.shapes.VoxelShape; + +public class ScaffoldingClutch extends Clutch { + public static final ScaffoldingClutch INSTANCE = new ScaffoldingClutch(); + + @Override + public boolean isAcceptedItem(Item item) { + return item.equals(Items.SCAFFOLDING); + } + + @Override + public boolean compare(BlockState state) { + return state.is(Blocks.SCAFFOLDING); + } + + @Override + public boolean isFinished(IPlayerContext ctx, MovementState state, MutableClutchResult result) { + state.setInput(Input.SNEAK, true); + return ctx.world().getBlockState(ctx.playerFeet()).is(Blocks.SCAFFOLDING); + } + + @Override + public boolean hasClutched(IPlayerContext ctx, BetterBlockPos dest, BlockState destState) { + return ctx.player().getBoundingBox().intersects(dest.x, dest.y, dest.z, dest.x + 1, dest.y + 2, dest.z + 1); + } +} diff --git a/src/main/java/baritone/pathing/clutch/clutches/SlimeClutch.java b/src/main/java/baritone/pathing/clutch/clutches/SlimeClutch.java new file mode 100644 index 000000000..4bfba4ff6 --- /dev/null +++ b/src/main/java/baritone/pathing/clutch/clutches/SlimeClutch.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.pathing.clutch.clutches; + +import baritone.api.utils.BetterBlockPos; +import baritone.api.utils.IPlayerContext; +import baritone.api.utils.input.Input; +import baritone.pathing.clutch.Clutch; +import baritone.pathing.movement.CalculationContext; +import baritone.pathing.movement.MovementState; +import baritone.utils.pathing.MutableClutchResult; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.Items; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.shapes.VoxelShape; + +public class SlimeClutch extends Clutch { + public static final SlimeClutch INSTANCE = new SlimeClutch(); + + private boolean onGround = false; + + private SlimeClutch() {} + + @Override + public boolean isAcceptedItem(Item item) { + return item.equals(Items.SLIME_BLOCK); + } + + @Override + public boolean compare(BlockState state) { + return state.is(Blocks.SLIME_BLOCK); + } + + @Override + public boolean isSolid(CalculationContext context) { + return true; + } + + @Override + public boolean isFinished(IPlayerContext ctx, MovementState state, MutableClutchResult result) { + state.setInput(Input.SNEAK, false); + state.setInput(Input.JUMP, true); + if (onGround) { + onGround = false; + return true; + } + onGround = ctx.player().isOnGround(); + return false; + } + + @Override + public double getAdditionalCost() { + return 13.0182684d; + } + + @Override + public boolean hasClutched(IPlayerContext ctx, BetterBlockPos dest, BlockState destState) { + return ctx.player().getBoundingBox().intersects(dest.x, dest.y, dest.z, dest.x + 1, dest.y + 2, dest.z + 1); + } +} diff --git a/src/main/java/baritone/pathing/clutch/clutches/SweetBerryClutch.java b/src/main/java/baritone/pathing/clutch/clutches/SweetBerryClutch.java new file mode 100644 index 000000000..880b476af --- /dev/null +++ b/src/main/java/baritone/pathing/clutch/clutches/SweetBerryClutch.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.pathing.clutch.clutches; + +import baritone.pathing.clutch.Clutch; +import baritone.pathing.movement.CalculationContext; +import net.minecraft.tags.BlockTags; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.Items; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.state.BlockState; + +public class SweetBerryClutch extends Clutch { + public static final SweetBerryClutch INSTANCE = new SweetBerryClutch(); + + private SweetBerryClutch() { + super(0.75d); + } + + @Override + public boolean isAcceptedItem(Item item) { + return item.equals(Items.SWEET_BERRIES); + } + + @Override + public boolean compare(BlockState state) { + return state.is(Blocks.SWEET_BERRY_BUSH); + } + + @Override + public boolean isPlaceable(CalculationContext context, int x, int y, int z, BlockState block) { + return block.is(BlockTags.DIRT) || block.is(Blocks.FARMLAND); + } +} diff --git a/src/main/java/baritone/pathing/clutch/clutches/TwistingVineClutch.java b/src/main/java/baritone/pathing/clutch/clutches/TwistingVineClutch.java new file mode 100644 index 000000000..70e1f7da7 --- /dev/null +++ b/src/main/java/baritone/pathing/clutch/clutches/TwistingVineClutch.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.pathing.clutch.clutches; + +import baritone.pathing.clutch.Clutch; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.Items; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.state.BlockState; + +public class TwistingVineClutch extends Clutch { + public static final TwistingVineClutch INSTANCE = new TwistingVineClutch(); + + @Override + public boolean isAcceptedItem(Item item) { + return item.equals(Items.TWISTING_VINES); + } + + @Override + public boolean compare(BlockState state) { + return state.is(Blocks.TWISTING_VINES); + } +} diff --git a/src/main/java/baritone/pathing/clutch/clutches/VineClutch.java b/src/main/java/baritone/pathing/clutch/clutches/VineClutch.java new file mode 100644 index 000000000..d5c90fa81 --- /dev/null +++ b/src/main/java/baritone/pathing/clutch/clutches/VineClutch.java @@ -0,0 +1,86 @@ +/* + * 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.pathing.clutch.clutches; + +import baritone.api.IBaritone; +import baritone.api.utils.BetterBlockPos; +import baritone.api.utils.IPlayerContext; +import baritone.pathing.clutch.ClutchUtils; +import baritone.pathing.movement.CalculationContext; +import baritone.pathing.clutch.Clutch; +import baritone.pathing.movement.MovementState; +import baritone.utils.pathing.MutableClutchResult; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.Items; +import net.minecraft.world.level.BlockGetter; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.VineBlock; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.shapes.VoxelShape; + +public class VineClutch extends Clutch { + public static final VineClutch INSTANCE = new VineClutch(); + + @Override + public boolean isAcceptedItem(Item item) { + return item.equals(Items.VINE); + } + + @Override + public boolean compare(BlockState state) { + return state.is(Blocks.VINE); + } + + // Had to yoink this out of VineBlock since it was private + private boolean canSupportAtFace(BlockGetter level, BlockPos pos, Direction direction) { + if (direction == Direction.DOWN) { + return false; + } else { + if (VineBlock.isAcceptableNeighbour(level, pos, direction)) { + return true; + } else if (direction.getAxis() == Direction.Axis.Y) { + return false; + } else { + // Will never use this + BlockState lv3 = level.getBlockState(pos.above()); + return lv3.is(Blocks.VINE) && lv3.getValue(VineBlock.PROPERTY_BY_DIRECTION.get(direction)); + } + } + } + + @Override + public boolean isPlaceable(CalculationContext context, int x, int y, int z, BlockState block) { + return super.isPlaceable(context, x, y, z, block) && + (canSupportAtFace(context.bsi.access, new BetterBlockPos(x - 1, y + 1, z), Direction.WEST) || + canSupportAtFace(context.bsi.access, new BetterBlockPos(x + 1, y + 1, z), Direction.EAST) || + canSupportAtFace(context.bsi.access, new BetterBlockPos(x, y + 1, z - 1), Direction.NORTH) || + canSupportAtFace(context.bsi.access, new BetterBlockPos(x, y + 1, z + 1), Direction.SOUTH)); + } + + @Override + public boolean clutch(IBaritone baritone, MovementState state, BlockPos dest, MutableClutchResult result) { + return ClutchUtils.blockClutch(baritone, state, dest, result, false); + } + + @Override + public boolean hasClutched(IPlayerContext ctx, BetterBlockPos dest, BlockState destState) { + return ctx.player().getBoundingBox().intersects(dest.x, dest.y, dest.z, dest.x + 1, dest.y + 1, dest.z + 1); + } +} diff --git a/src/main/java/baritone/pathing/clutch/clutches/WaterClutch.java b/src/main/java/baritone/pathing/clutch/clutches/WaterClutch.java new file mode 100644 index 000000000..a2bdd67b6 --- /dev/null +++ b/src/main/java/baritone/pathing/clutch/clutches/WaterClutch.java @@ -0,0 +1,73 @@ +/* + * 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.pathing.clutch.clutches; + +import baritone.api.utils.BetterBlockPos; +import baritone.api.utils.IPlayerContext; +import baritone.pathing.clutch.ClutchUtils; +import baritone.pathing.movement.CalculationContext; +import baritone.pathing.clutch.Clutch; +import baritone.pathing.movement.MovementState; +import baritone.utils.pathing.MutableClutchResult; +import net.minecraft.core.Direction; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.Items; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.SimpleWaterloggedBlock; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.material.WaterFluid; +import net.minecraft.world.phys.shapes.VoxelShape; + +public class WaterClutch extends Clutch { + private static final double WATER_HEIGHT = 0.875d; // TODO confirm if this value is accurate + public static final WaterClutch INSTANCE = new WaterClutch(); + + private WaterClutch() {} + + @Override + public boolean isAcceptedItem(Item item) { + return item.equals(Items.WATER_BUCKET) || + item.equals(Items.AXOLOTL_BUCKET) || + item.equals(Items.COD_BUCKET) || + item.equals(Items.TROPICAL_FISH_BUCKET) || + item.equals(Items.SALMON_BUCKET) || + item.equals(Items.TADPOLE_BUCKET); + } + + @Override + public boolean compare(BlockState state) { + return state.getFluidState().getType() instanceof WaterFluid; + } + @Override + public boolean isPlaceable(CalculationContext context, int x, int y, int z, BlockState block) { + VoxelShape shape = block.getCollisionShape(context.world, new BetterBlockPos(x, y, z)); + return super.isPlaceable(context, x, y, z, block) && + (!(block.getBlock() instanceof SimpleWaterloggedBlock) ^ (shape.isEmpty() || shape.bounds().maxY < WATER_HEIGHT)) && + context.world.dimension() != Level.NETHER; + } + + @Override + public boolean isFinished(IPlayerContext ctx, MovementState state, MutableClutchResult result) { + return ClutchUtils.bucketPickup(state, ctx.player().getInventory()); + } + + @Override + public boolean topBlockPriority() { + return false; + } +} diff --git a/src/main/java/baritone/pathing/movement/CalculationContext.java b/src/main/java/baritone/pathing/movement/CalculationContext.java index 5dfc8b7d0..18c53a127 100644 --- a/src/main/java/baritone/pathing/movement/CalculationContext.java +++ b/src/main/java/baritone/pathing/movement/CalculationContext.java @@ -27,9 +27,8 @@ import baritone.utils.pathing.BetterWorldBorder; import net.minecraft.client.player.LocalPlayer; import net.minecraft.core.BlockPos; -import net.minecraft.world.entity.player.Inventory; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.Items; +import net.minecraft.world.effect.MobEffect; +import net.minecraft.world.effect.MobEffectInstance; import net.minecraft.world.item.enchantment.EnchantmentHelper; import net.minecraft.world.item.enchantment.Enchantments; import net.minecraft.world.level.Level; @@ -38,6 +37,7 @@ import java.util.ArrayList; import java.util.List; +import java.util.Map; import static baritone.api.pathing.movement.ActionCosts.COST_INF; @@ -46,19 +46,16 @@ * @since 8/7/2018 */ public class CalculationContext { - - private static final ItemStack STACK_BUCKET_WATER = new ItemStack(Items.WATER_BUCKET); - public final boolean safeForThreadedUse; public final IBaritone baritone; public final Level world; public final WorldData worldData; public final BlockStateInterface bsi; public final ToolSet toolSet; - public final boolean hasWaterBucket; + public final boolean allowPlace; public final boolean hasThrowaway; public final boolean canSprint; - protected final double placeBlockCost; // protected because you should call the function instead + public double placeBlockCost; public final boolean allowBreak; public final List allowBreakAnyway; public final boolean allowParkour; @@ -72,8 +69,8 @@ public class CalculationContext { public final boolean allowDiagonalAscend; public final boolean allowDownward; public int minFallHeight; - public int maxFallHeightNoWater; - public final int maxFallHeightBucket; + public int maxFallHeightNoClutch; + public final int maxFallHeightClutch; public final double waterWalkSpeed; public final double breakBlockAdditionalCost; public double backtrackCostFavoringCoefficient; @@ -81,6 +78,8 @@ public class CalculationContext { public final double walkOnWaterOnePenalty; public final boolean allowWalkOnMagmaBlocks; public final BetterWorldBorder worldBorder; + public final boolean considerPotionEffects; + public final Map activeEffects; public final PrecomputedData precomputedData; @@ -97,8 +96,8 @@ public CalculationContext(IBaritone baritone, boolean forUseOnAnotherThread) { this.worldData = (WorldData) baritone.getPlayerContext().worldData(); this.bsi = new BlockStateInterface(baritone.getPlayerContext(), forUseOnAnotherThread); this.toolSet = new ToolSet(player); - this.hasThrowaway = Baritone.settings().allowPlace.value && ((Baritone) baritone).getInventoryBehavior().hasGenericThrowaway(); - this.hasWaterBucket = Baritone.settings().allowWaterBucketFall.value && Inventory.isHotbarSlot(player.getInventory().findSlotMatchingItem(STACK_BUCKET_WATER)) && world.dimension() != Level.NETHER; + this.allowPlace = Baritone.settings().allowPlace.value; + this.hasThrowaway = ((Baritone) baritone).getInventoryBehavior().hasGenericThrowaway(); this.canSprint = Baritone.settings().allowSprint.value && player.getFoodData().getFoodLevel() > 6; this.placeBlockCost = Baritone.settings().blockPlacementPenalty.value; this.allowBreak = Baritone.settings().allowBreak.value; @@ -114,8 +113,8 @@ public CalculationContext(IBaritone baritone, boolean forUseOnAnotherThread) { this.allowDiagonalAscend = Baritone.settings().allowDiagonalAscend.value; this.allowDownward = Baritone.settings().allowDownward.value; this.minFallHeight = 3; // Minimum fall height used by MovementFall - this.maxFallHeightNoWater = Baritone.settings().maxFallHeightNoWater.value; - this.maxFallHeightBucket = Baritone.settings().maxFallHeightBucket.value; + this.maxFallHeightNoClutch = Baritone.settings().maxFallHeightNoClutch.value; + this.maxFallHeightClutch = Baritone.settings().maxFallHeightClutch.value; int depth = EnchantmentHelper.getDepthStrider(player); if (depth > 3) { depth = 3; @@ -131,6 +130,8 @@ public CalculationContext(IBaritone baritone, boolean forUseOnAnotherThread) { // because if some movements are calculated one way and others are calculated another way, // then you get a wildly inconsistent path that isn't optimal for either scenario. this.worldBorder = new BetterWorldBorder(world.getWorldBorder()); + this.considerPotionEffects = Baritone.settings().considerPotionEffects.value; + this.activeEffects = Map.copyOf(player.getActiveEffectsMap()); } public final IBaritone getBaritone() { @@ -154,7 +155,7 @@ public Block getBlock(int x, int y, int z) { } public double costOfPlacingAt(int x, int y, int z, BlockState current) { - if (!hasThrowaway) { // only true if allowPlace is true, see constructor + if (!allowPlace || !hasThrowaway) { return COST_INF; } if (isPossiblyProtected(x, y, z)) { @@ -182,10 +183,6 @@ public double breakCostMultiplierAt(int x, int y, int z, BlockState current) { return 1; } - public double placeBucketCost() { - return placeBlockCost; // shrug - } - public boolean isPossiblyProtected(int x, int y, int z) { // TODO more protection logic here; see #220 return false; diff --git a/src/main/java/baritone/pathing/movement/MovementHelper.java b/src/main/java/baritone/pathing/movement/MovementHelper.java index c01fd40e6..8583abfc7 100644 --- a/src/main/java/baritone/pathing/movement/MovementHelper.java +++ b/src/main/java/baritone/pathing/movement/MovementHelper.java @@ -31,6 +31,7 @@ import baritone.utils.ToolSet; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; +import net.minecraft.world.item.Item; import net.minecraft.util.Mth; import net.minecraft.world.item.enchantment.EnchantmentHelper; import net.minecraft.world.level.block.*; @@ -63,7 +64,6 @@ * @author leijurv */ public interface MovementHelper extends ActionCosts, Helper { - static boolean avoidBreaking(BlockStateInterface bsi, int x, int y, int z, BlockState state) { if (!bsi.worldBorder.canPlaceAt(x, z)) { return true; @@ -584,7 +584,7 @@ static boolean canPlaceAgainst(BlockStateInterface bsi, int x, int y, int z, Blo // can we look at the center of a side face of this block and likely be able to place? // (thats how this check is used) // therefore dont include weird things that we technically could place against (like carpet) but practically can't - return isBlockNormalCube(state) || state.getBlock() == Blocks.GLASS || state.getBlock() instanceof StainedGlassBlock; + return isBlockNormalCube(state) || state.is(Blocks.GLASS) || state.getBlock() instanceof StainedGlassBlock || state.is(Blocks.FARMLAND); } static double getMiningDurationTicks(CalculationContext context, int x, int y, int z, boolean includeFalling) { @@ -778,18 +778,18 @@ static boolean isBlockNormalCube(BlockState state) { return false; } - static PlaceResult attemptToPlaceABlock(MovementState state, IBaritone baritone, BlockPos placeAt, boolean preferDown, boolean wouldSneak) { + static PlaceResult attemptToPlaceABlock(MovementState state, IBaritone baritone, BlockPos placeAt, boolean allowDown, boolean preferDown, boolean wouldSneak, Item customItem) { IPlayerContext ctx = baritone.getPlayerContext(); - Optional direct = RotationUtils.reachable(ctx, placeAt, wouldSneak); // 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 replaceable boolean found = false; if (direct.isPresent()) { state.setTarget(new MovementTarget(direct.get(), true)); found = true; } - for (int i = 0; i < 5; i++) { + for (int i = 0; i < (allowDown ? 5 : 4); i++) { BlockPos against1 = placeAt.relative(HORIZONTALS_BUT_ALSO_DOWN_____SO_EVERY_DIRECTION_EXCEPT_UP[i]); if (MovementHelper.canPlaceAgainst(ctx, against1)) { - if (!((Baritone) baritone).getInventoryBehavior().selectThrowawayForLocation(false, placeAt.getX(), placeAt.getY(), placeAt.getZ())) { // get ready to place a throwaway block + if (!((Baritone) baritone).getInventoryBehavior().selectThrowawayForLocation(false, placeAt.getX(), placeAt.getY(), placeAt.getZ(), customItem)) { // get ready to place a throwaway block Helper.HELPER.logDebug("bb pls get me some blocks. dirt, netherrack, cobble"); state.setStatus(MovementStatus.UNREACHABLE); return PlaceResult.NO_OPTION; @@ -800,13 +800,14 @@ static PlaceResult attemptToPlaceABlock(MovementState state, IBaritone baritone, Rotation place = RotationUtils.calcRotationFromVec3d(wouldSneak ? RayTraceUtils.inferSneakingEyePosition(ctx.player()) : ctx.playerHead(), new Vec3(faceX, faceY, faceZ), ctx.playerRotations()); Rotation actual = baritone.getLookBehavior().getAimProcessor().peekRotation(place); HitResult res = RayTraceUtils.rayTraceTowards(ctx.player(), actual, ctx.playerController().getBlockReachDistance(), wouldSneak); - if (res != null && res.getType() == HitResult.Type.BLOCK && ((BlockHitResult) res).getBlockPos().equals(against1) && ((BlockHitResult) res).getBlockPos().relative(((BlockHitResult) res).getDirection()).equals(placeAt)) { + if (res.getType() == HitResult.Type.BLOCK && + ((BlockHitResult) res).getBlockPos().equals(against1) && + ((BlockHitResult) res).getBlockPos().relative(((BlockHitResult) res).getDirection()).equals(placeAt)) { state.setTarget(new MovementTarget(place, true)); found = true; - if (!preferDown) { - // if preferDown is true, we want the last option - // if preferDown is false, we want the first + if (!allowDown || !preferDown) { + // if preferDown is true, we want the last option. Otherwise, we want the first. break; } } @@ -820,7 +821,7 @@ static PlaceResult attemptToPlaceABlock(MovementState state, IBaritone baritone, if (wouldSneak) { state.setInput(Input.SNEAK, true); } - ((Baritone) baritone).getInventoryBehavior().selectThrowawayForLocation(true, placeAt.getX(), placeAt.getY(), placeAt.getZ()); + ((Baritone) baritone).getInventoryBehavior().selectThrowawayForLocation(true, placeAt.getX(), placeAt.getY(), placeAt.getZ(), customItem); return PlaceResult.READY_TO_PLACE; } } @@ -828,14 +829,14 @@ static PlaceResult attemptToPlaceABlock(MovementState state, IBaritone baritone, if (wouldSneak) { state.setInput(Input.SNEAK, true); } - ((Baritone) baritone).getInventoryBehavior().selectThrowawayForLocation(true, placeAt.getX(), placeAt.getY(), placeAt.getZ()); + ((Baritone) baritone).getInventoryBehavior().selectThrowawayForLocation(true, placeAt.getX(), placeAt.getY(), placeAt.getZ(), customItem); return PlaceResult.ATTEMPTING; } return PlaceResult.NO_OPTION; } enum PlaceResult { - READY_TO_PLACE, ATTEMPTING, NO_OPTION; + READY_TO_PLACE, ATTEMPTING, NO_OPTION } static boolean isTransparent(Block b) { diff --git a/src/main/java/baritone/pathing/movement/movements/MovementAscend.java b/src/main/java/baritone/pathing/movement/movements/MovementAscend.java index 2ecd9d723..4fb77ed75 100644 --- a/src/main/java/baritone/pathing/movement/movements/MovementAscend.java +++ b/src/main/java/baritone/pathing/movement/movements/MovementAscend.java @@ -176,7 +176,7 @@ public MovementState updateState(MovementState state) { BlockState jumpingOnto = BlockStateInterface.get(ctx, positionToPlace); if (!MovementHelper.canWalkOn(ctx, positionToPlace, jumpingOnto)) { ticksWithoutPlacement++; - if (MovementHelper.attemptToPlaceABlock(state, baritone, dest.below(), false, true) == PlaceResult.READY_TO_PLACE) { + if (MovementHelper.attemptToPlaceABlock(state, baritone, dest.below(), true, false, true, null) == PlaceResult.READY_TO_PLACE) { state.setInput(Input.SNEAK, true); if (ctx.player().isCrouching()) { 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 3e860e301..ba6248b87 100644 --- a/src/main/java/baritone/pathing/movement/movements/MovementDescend.java +++ b/src/main/java/baritone/pathing/movement/movements/MovementDescend.java @@ -19,28 +19,32 @@ import baritone.Baritone; import baritone.api.IBaritone; +import baritone.api.pathing.movement.ActionCosts; import baritone.api.pathing.movement.MovementStatus; import baritone.api.utils.BetterBlockPos; +import baritone.api.utils.Pair; import baritone.api.utils.RotationUtils; import baritone.api.utils.input.Input; -import baritone.pathing.movement.CalculationContext; -import baritone.pathing.movement.Movement; -import baritone.pathing.movement.MovementHelper; -import baritone.pathing.movement.MovementState; +import baritone.pathing.clutch.Clutch; +import baritone.pathing.clutch.ClutchUtils; +import baritone.pathing.movement.*; import baritone.utils.BlockStateInterface; +import baritone.utils.pathing.MutableClutchResult; import baritone.utils.pathing.MutableMoveResult; import com.google.common.collect.ImmutableSet; +import net.minecraft.client.player.LocalPlayer; import net.minecraft.core.BlockPos; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.FallingBlock; +import net.minecraft.world.effect.MobEffects; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.block.*; import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.properties.BlockStateProperties; import net.minecraft.world.phys.Vec3; +import net.minecraft.world.phys.shapes.VoxelShape; import java.util.Set; public class MovementDescend extends Movement { - private int numTicks = 0; public boolean forceSafeMode = false; @@ -110,13 +114,10 @@ public static void cost(CalculationContext context, int x, int y, int z, int des BlockState below = context.get(destX, y - 2, destZ); if (!MovementHelper.canWalkOn(context, destX, y - 2, destZ, below)) { - dynamicFallCost(context, x, y, z, destX, destZ, totalCost, below, res); + dynamicFallCost(context, x, y, z, destX, destZ, totalCost, below, res, null); return; } - if (destDown.getBlock() == Blocks.LADDER || destDown.getBlock() == Blocks.VINE) { - return; - } if (MovementHelper.canUseFrostWalker(context, destDown)) { // no need to check assumeWalkOnWater return; // the water will freeze when we try to walk into it } @@ -134,92 +135,133 @@ public static void cost(CalculationContext context, int x, int y, int z, int des res.cost = totalCost; } - public static boolean dynamicFallCost(CalculationContext context, int x, int y, int z, int destX, int destZ, double frontBreak, BlockState below, MutableMoveResult res) { + public static void dynamicFallCost(CalculationContext context, int x, int y, int z, int destX, int destZ, double frontBreak, BlockState below, MutableMoveResult res, MutableClutchResult clutchRes) { if (frontBreak != 0 && context.get(destX, y + 2, destZ).getBlock() instanceof FallingBlock) { // if frontBreak is 0 we can actually get through this without updating the falling block and making it actually fall // but if frontBreak is nonzero, we're breaking blocks in front, so don't let anything fall through this column, // and potentially replace the water we're going to fall into - return false; + return; } if (!MovementHelper.canWalkThrough(context, destX, y - 2, destZ, below)) { - return false; + return; } - double costSoFar = 0; + LocalPlayer player = context.getBaritone().getPlayerContext().player(); + if (context.considerPotionEffects && context.activeEffects.containsKey(MobEffects.LEVITATION)) { + return; + } + double tentativeCost = WALK_OFF_BLOCK_COST + frontBreak; + double aboveBlockCost = -1d; + boolean aboveBlockPriority = true; + double velocity = 0d; int effectiveStartHeight = y; - for (int fallHeight = 3; true; fallHeight++) { - int newY = y - fallHeight; - if (newY < context.world.getMinBuildHeight()) { - // when pathing in the end, where you could plausibly fall into the void - // this check prevents it from getting the block at y=(below whatever the minimum height is) and crashing - return false; - } - boolean reachedMinimum = fallHeight >= context.minFallHeight; + int newY; + for (int fallHeight = context.minFallHeight; (newY = y - fallHeight) >= context.world.getMinBuildHeight(); fallHeight++) { BlockState ontoBlock = context.get(destX, newY, destZ); - int unprotectedFallHeight = fallHeight - (y - effectiveStartHeight); // equal to fallHeight - y + effectiveFallHeight, which is equal to -newY + effectiveFallHeight, which is equal to effectiveFallHeight - newY - double tentativeCost = WALK_OFF_BLOCK_COST + FALL_N_BLOCKS_COST[unprotectedFallHeight] + frontBreak + costSoFar; - if (reachedMinimum && MovementHelper.isWater(ontoBlock)) { - if (!MovementHelper.canWalkThrough(context, destX, newY, destZ, ontoBlock)) { - return false; - } - if (context.assumeWalkOnWater) { - return false; // TODO fix - } - if (MovementHelper.isFlowing(destX, newY, destZ, ontoBlock, context.bsi)) { - return false; // TODO flowing check required here? - } - if (!MovementHelper.canWalkOn(context, destX, newY - 1, destZ)) { - // we could punch right through the water into something else - return false; + if (MovementHelper.canWalkThrough(context, destX, newY, destZ, ontoBlock)) { + if (aboveBlockCost != -1d) { + tentativeCost += aboveBlockCost; + aboveBlockCost = -1d; + aboveBlockPriority = true; } - // found a fall into water - res.x = destX; - res.y = newY; - res.z = destZ; - res.cost = tentativeCost;// TODO incorporate water swim up cost? - return false; + continue; } - if (reachedMinimum && context.allowFallIntoLava && MovementHelper.isLava(ontoBlock)) { - // found a fall into lava + int unprotectedFallHeight = effectiveStartHeight - 1 - newY; + if (context.considerPotionEffects && context.activeEffects.containsKey(MobEffects.SLOW_FALLING)) { + res.cost = tentativeCost + ActionCosts.distanceToTicks(unprotectedFallHeight, 0.01d, velocity); res.x = destX; - res.y = newY; + res.y = newY + 1; res.z = destZ; - res.cost = tentativeCost; - return false; - } - if (unprotectedFallHeight <= 11 && (ontoBlock.getBlock() == Blocks.VINE || ontoBlock.getBlock() == Blocks.LADDER)) { - // if fall height is greater than or equal to 11, we don't actually grab on to vines or ladders. the more you know - // this effectively "resets" our falling speed - costSoFar += FALL_N_BLOCKS_COST[unprotectedFallHeight - 1];// we fall until the top of this block (not including this block) - costSoFar += LADDER_DOWN_ONE_COST; - effectiveStartHeight = newY; - continue; + break; } - if (MovementHelper.canWalkThrough(context, destX, newY, destZ, ontoBlock)) { - continue; - } - if (!MovementHelper.canWalkOn(context, destX, newY, destZ, ontoBlock)) { - return false; + VoxelShape shape = ontoBlock.getCollisionShape(context.bsi.access, new BetterBlockPos(destX, newY, destZ)); + if (unprotectedFallHeight + (!shape.isEmpty() && shape.bounds().maxY < 1 ? 1 : 0) <= context.maxFallHeightNoClutch && // Minecraft will round fall damage up + MovementHelper.canWalkOn(context, destX, newY, destZ, ontoBlock)) { + // fallHeight = 4 means onto.up() is 3 blocks down, which is the max + double newCost = tentativeCost + ActionCosts.distanceToTicks(unprotectedFallHeight, 0.08d, velocity); + if (newCost < res.cost) { + res.cost = newCost; + res.x = destX; + res.y = newY + 1; + res.z = destZ; + } + break; } - if (MovementHelper.isBottomSlab(ontoBlock)) { - return false; // falling onto a half slab is really glitchy, and can cause more fall damage than we'd expect + BlockState aboveBlock = context.get(destX, newY + 1, destZ); + Clutch nonSolidClutchBlock = null; + if (unprotectedFallHeight > context.maxFallHeightNoClutch) { + for (Clutch clutch : ClutchUtils.CLUTCHES) { + if (clutch.compare(ontoBlock) && + clutch.getFallDamage(unprotectedFallHeight) <= context.maxFallHeightNoClutch) { + if (clutch.isSolid(context)) { + double newCost = tentativeCost + clutch.getCost(unprotectedFallHeight, 1d, velocity).first() + clutch.getAdditionalCost(); + if (newCost < res.cost) { + res.cost = newCost; + res.x = destX; + res.y = newY + 1;// this is the block we're falling onto, so dest is +1 + res.z = destZ; + if (clutchRes != null) { + clutchRes.clutch = clutch; + } + } + } else { + nonSolidClutchBlock = clutch; + } + break; + } + } } - if (reachedMinimum && unprotectedFallHeight <= context.maxFallHeightNoWater + 1) { - // fallHeight = 4 means onto.up() is 3 blocks down, which is the max - res.x = destX; - res.y = newY + 1; - res.z = destZ; - res.cost = tentativeCost; - return false; + if (unprotectedFallHeight - 1 <= context.maxFallHeightClutch && + context.allowPlace && + !context.isPossiblyProtected(destX, newY + 1, destZ) && + context.worldBorder.canPlaceAt(destX, destZ) && + MovementHelper.isReplaceable(destX, newY + 1, destZ, aboveBlock, context.bsi) && + !aboveBlock.hasProperty(BlockStateProperties.DOUBLE_BLOCK_HALF)) { + for (Clutch clutch : ClutchUtils.CLUTCHES) { + ItemStack item = clutch.getClutchingItem(context); + if (clutch.getFallDamage(unprotectedFallHeight - 1) <= context.maxFallHeightNoClutch && + clutch.isPlaceable(context, destX, newY, destZ, ontoBlock) && + item != null) { + double newCost = tentativeCost + context.placeBlockCost; + if (clutch.isSolid(context)) { + newCost += ActionCosts.distanceToTicks(unprotectedFallHeight, 0.08d, velocity) + clutch.getAdditionalCost(); + } else if (MovementHelper.canWalkOn(context, destX, newY, destZ, ontoBlock)) { + newCost += clutch.getCost(unprotectedFallHeight, 1d, velocity).first(); + } else { + continue; + } + if (newCost < res.cost) { + res.cost = newCost; + res.x = destX; + res.y = newY + 2; + res.z = destZ; + if (clutchRes != null) { + clutchRes.clutch = clutch; + clutchRes.item = item; + } + } + break; + } + } } - if (reachedMinimum && context.hasWaterBucket && unprotectedFallHeight <= context.maxFallHeightBucket + 1) { - res.x = destX; - res.y = newY + 1;// this is the block we're falling onto, so dest is +1 - res.z = destZ; - res.cost = tentativeCost + context.placeBucketCost(); - return true; - } else { - return false; + if (nonSolidClutchBlock != null) { + Pair fallCostAndVelocity = nonSolidClutchBlock.getCost(unprotectedFallHeight, 1d, velocity); + if (aboveBlockCost != -1d && aboveBlockPriority) { + tentativeCost += aboveBlockCost; + aboveBlockCost = fallCostAndVelocity.first(); + } else { + tentativeCost += fallCostAndVelocity.first(); + aboveBlockCost = nonSolidClutchBlock.slowsOnTopBlock() ? fallCostAndVelocity.first() : -1d; + } + aboveBlockPriority = nonSolidClutchBlock.topBlockPriority(); + if (res.cost > tentativeCost) { + velocity = fallCostAndVelocity.second(); + effectiveStartHeight = newY; + continue; + } else { + break; + } } + break; } } diff --git a/src/main/java/baritone/pathing/movement/movements/MovementFall.java b/src/main/java/baritone/pathing/movement/movements/MovementFall.java index c537fc2ca..a94038742 100644 --- a/src/main/java/baritone/pathing/movement/movements/MovementFall.java +++ b/src/main/java/baritone/pathing/movement/movements/MovementFall.java @@ -24,36 +24,28 @@ import baritone.api.utils.RotationUtils; import baritone.api.utils.VecUtils; import baritone.api.utils.input.Input; -import baritone.pathing.movement.CalculationContext; -import baritone.pathing.movement.Movement; -import baritone.pathing.movement.MovementHelper; -import baritone.pathing.movement.MovementState; +import baritone.pathing.movement.*; import baritone.pathing.movement.MovementState.MovementTarget; +import baritone.utils.pathing.MutableClutchResult; import baritone.utils.pathing.MutableMoveResult; + import java.util.HashSet; import java.util.Optional; import java.util.Set; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.core.Vec3i; -import net.minecraft.world.entity.player.Inventory; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.Items; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.LadderBlock; import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.material.WaterFluid; import net.minecraft.world.phys.Vec3; public class MovementFall extends Movement { - - private static final ItemStack STACK_BUCKET_WATER = new ItemStack(Items.WATER_BUCKET); - private static final ItemStack STACK_BUCKET_EMPTY = new ItemStack(Items.BUCKET); + private final MutableMoveResult moveResult = new MutableMoveResult(); + private final MutableClutchResult clutchResult = new MutableClutchResult(); public MovementFall(IBaritone baritone, BetterBlockPos src, BetterBlockPos dest) { - super(baritone, src, dest, MovementFall.buildPositionsToBreak(src, dest)); + super(baritone, src, dest, MovementFall.buildPositionsToBreak(src, dest)); // TODO add `toPlace` smh } @Override @@ -76,10 +68,9 @@ protected Set calculateValidPositions() { return set; } - private boolean willPlaceBucket() { + private void updateClutch() { CalculationContext context = new CalculationContext(baritone); - MutableMoveResult result = new MutableMoveResult(); - return MovementDescend.dynamicFallCost(context, src.x, src.y, src.z, dest.x, dest.z, 0, context.get(dest.x, src.y - 2, dest.z), result); + MovementDescend.dynamicFallCost(context, src.x, src.y, src.z, dest.x, dest.z, 0, context.get(dest.x, src.y - 2, dest.z), moveResult, clutchResult); } @Override @@ -91,53 +82,29 @@ public MovementState updateState(MovementState state) { BlockPos playerFeet = ctx.playerFeet(); Rotation toDest = RotationUtils.calcRotationFromVec3d(ctx.playerHead(), VecUtils.getBlockPosCenter(dest), ctx.playerRotations()); - Rotation targetRotation = null; BlockState destState = ctx.world().getBlockState(dest); - Block destBlock = destState.getBlock(); - - if (ctx.world().getBlockState(dest.below()).is(Blocks.MAGMA_BLOCK) && MovementHelper.steppingOnBlocks(ctx).stream().allMatch(block -> MovementHelper.canWalkThrough(ctx, block))) { + BetterBlockPos blockDest = dest.below(); + BlockState blockDestState = ctx.world().getBlockState(blockDest); + if (ctx.world().getBlockState(dest.below()).is(Blocks.MAGMA_BLOCK) && + MovementHelper.steppingOnBlocks(ctx).stream().allMatch(block -> MovementHelper.canWalkThrough(ctx, block))) { state.setInput(Input.SNEAK, true); } - - boolean isWater = destState.getFluidState().getType() instanceof WaterFluid; - if (!isWater && willPlaceBucket() && !playerFeet.equals(dest)) { - if (!Inventory.isHotbarSlot(ctx.player().getInventory().findSlotMatchingItem(STACK_BUCKET_WATER)) || ctx.world().dimension() == Level.NETHER) { - return state.setStatus(MovementStatus.UNREACHABLE); - } - - if (ctx.player().position().y - dest.getY() < ctx.playerController().getBlockReachDistance() && !ctx.player().isOnGround()) { - ctx.player().getInventory().selected = ctx.player().getInventory().findSlotMatchingItem(STACK_BUCKET_WATER); - - targetRotation = new Rotation(toDest.getYaw(), 90.0F); - - if (ctx.isLookingAt(dest) || ctx.isLookingAt(dest.below())) { - state.setInput(Input.CLICK_RIGHT, true); - } - } - } - if (targetRotation != null) { - state.setTarget(new MovementTarget(targetRotation, true)); - } else { - state.setTarget(new MovementTarget(toDest, false)); + updateClutch(); + if (moveResult.cost >= COST_INF) { + return state.setStatus(MovementStatus.UNREACHABLE); } - if (playerFeet.equals(dest) && (ctx.player().position().y - playerFeet.getY() < 0.094 || isWater)) { // 0.094 because lilypads - if (isWater) { // only match water, not flowing water (which we cannot pick up with a bucket) - if (Inventory.isHotbarSlot(ctx.player().getInventory().findSlotMatchingItem(STACK_BUCKET_EMPTY))) { - ctx.player().getInventory().selected = ctx.player().getInventory().findSlotMatchingItem(STACK_BUCKET_EMPTY); - if (ctx.player().getDeltaMovement().y >= 0) { - return state.setInput(Input.CLICK_RIGHT, true); - } else { - return state; - } - } else { - if (ctx.player().getDeltaMovement().y >= 0) { - return state.setStatus(MovementStatus.SUCCESS); - } // don't else return state; we need to stay centered because this water might be flowing under the surface - } - } else { + if (clutchResult.clutch != null) { + if (clutchResult.item != null && !clutchResult.clutch.compare(blockDestState)) { + clutchResult.clutch.clutch(baritone, state, blockDest, clutchResult); + } + if (clutchResult.clutch.hasClutched(ctx, dest, destState) && clutchResult.clutch.isFinished(ctx, state, clutchResult)) { + clutchResult.reset(); return state.setStatus(MovementStatus.SUCCESS); } + } else if (playerFeet.equals(dest)) { + return state.setStatus(MovementStatus.SUCCESS); } + state.setTarget(new MovementTarget(toDest, false)); Vec3 destCenter = VecUtils.getBlockPosCenter(dest); // we are moving to the 0.5 center not the edge (like if we were falling on a ladder) if (Math.abs(ctx.player().position().x + ctx.player().getDeltaMovement().x - destCenter.x) > 0.1 || Math.abs(ctx.player().position().z + ctx.player().getDeltaMovement().z - destCenter.z) > 0.1) { if (!ctx.player().isOnGround() && Math.abs(ctx.player().getDeltaMovement().y) > 0.4) { @@ -156,11 +123,8 @@ public MovementState updateState(MovementState state) { state.setInput(Input.SNEAK, false); } } - if (targetRotation == null) { - Vec3 destCenterOffset = new Vec3(destCenter.x + 0.125 * avoid.getX(), destCenter.y, destCenter.z + 0.125 * avoid.getZ()); - state.setTarget(new MovementTarget(RotationUtils.calcRotationFromVec3d(ctx.playerHead(), destCenterOffset, ctx.playerRotations()), false)); - } - return state; + Vec3 destCenterOffset = new Vec3(destCenter.x + 0.125 * avoid.getX(), destCenter.y, destCenter.z + 0.125 * avoid.getZ()); + return state.setTarget(new MovementTarget(RotationUtils.calcRotationFromVec3d(ctx.playerHead(), destCenterOffset, ctx.playerRotations()), true)); } private Direction avoid() { diff --git a/src/main/java/baritone/pathing/movement/movements/MovementParkour.java b/src/main/java/baritone/pathing/movement/movements/MovementParkour.java index 5ea1e4dcc..490c0bbfa 100644 --- a/src/main/java/baritone/pathing/movement/movements/MovementParkour.java +++ b/src/main/java/baritone/pathing/movement/movements/MovementParkour.java @@ -73,6 +73,10 @@ public static void cost(CalculationContext context, int x, int y, int z, Directi // most common case at the top -- the adjacent block isn't air return; } + BlockState current = context.get(x, y, z); + if (current.is(Blocks.SWEET_BERRY_BUSH) || current.is(Blocks.COBWEB) || current.is(Blocks.HONEY_BLOCK)) { + return; + } BlockState adj = context.get(x + xDiff, y - 1, z + zDiff); if (MovementHelper.canWalkOn(context, x + xDiff, y - 1, z + zDiff, adj)) { // don't parkour if we could just traverse (for now) // second most common case -- we could just traverse not parkour @@ -283,7 +287,7 @@ public MovementState updateState(MovementState state) { && ((Baritone) baritone).getInventoryBehavior().hasGenericThrowaway() && !MovementHelper.canWalkOn(ctx, dest.below()) && !ctx.player().isOnGround() - && MovementHelper.attemptToPlaceABlock(state, baritone, dest.below(), true, false) == PlaceResult.READY_TO_PLACE + && MovementHelper.attemptToPlaceABlock(state, baritone, dest.below(), true, true, false, null) == 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 8007eb767..e7b0d0c5f 100644 --- a/src/main/java/baritone/pathing/movement/movements/MovementPillar.java +++ b/src/main/java/baritone/pathing/movement/movements/MovementPillar.java @@ -225,7 +225,7 @@ public MovementState updateState(MovementState state) { return state; } else { // Get ready to place a throwaway block - if (!((Baritone) baritone).getInventoryBehavior().selectThrowawayForLocation(true, src.x, src.y, src.z)) { + if (!((Baritone) baritone).getInventoryBehavior().selectThrowawayForLocation(true, src.x, src.y, src.z, null)) { return state.setStatus(MovementStatus.UNREACHABLE); } diff --git a/src/main/java/baritone/pathing/movement/movements/MovementTraverse.java b/src/main/java/baritone/pathing/movement/movements/MovementTraverse.java index 156da1adb..5f3b5da9e 100644 --- a/src/main/java/baritone/pathing/movement/movements/MovementTraverse.java +++ b/src/main/java/baritone/pathing/movement/movements/MovementTraverse.java @@ -300,7 +300,7 @@ public MovementState updateState(MovementState state) { } } double dist1 = Math.max(Math.abs(ctx.player().position().x - (dest.getX() + 0.5D)), Math.abs(ctx.player().position().z - (dest.getZ() + 0.5D))); - PlaceResult p = MovementHelper.attemptToPlaceABlock(state, baritone, dest.below(), false, !Baritone.settings().assumeSafeWalk.value); + PlaceResult p = MovementHelper.attemptToPlaceABlock(state, baritone, dest.below(), true, false, !Baritone.settings().assumeSafeWalk.value, null); 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 af191ae1e..5e4ec19a0 100644 --- a/src/main/java/baritone/process/BackfillProcess.java +++ b/src/main/java/baritone/process/BackfillProcess.java @@ -73,7 +73,7 @@ public PathingCommand onTick(boolean calcFailed, boolean isSafeToCancel) { baritone.getInputOverrideHandler().clearAllKeys(); for (BlockPos toPlace : toFillIn()) { MovementState fake = new MovementState(); - switch (MovementHelper.attemptToPlaceABlock(fake, baritone, toPlace, false, false)) { + switch (MovementHelper.attemptToPlaceABlock(fake, baritone, toPlace, true, false, false, null)) { case NO_OPTION: continue; case READY_TO_PLACE: diff --git a/src/main/java/baritone/process/BuilderProcess.java b/src/main/java/baritone/process/BuilderProcess.java index b99d41e0a..6cd39d888 100644 --- a/src/main/java/baritone/process/BuilderProcess.java +++ b/src/main/java/baritone/process/BuilderProcess.java @@ -1146,14 +1146,14 @@ public double costOfPlacingAt(int x, int y, int z, BlockState current) { // i'm such an idiot that i just tried to copy and paste the epic gamer moment emoji too // get added to unicode when? } - if (!hasThrowaway) { + if (!(allowPlace && hasThrowaway)) { return COST_INF; } // we want it to be something that we don't have // even more of a pain to place something wrong return placeBlockCost * 1.5 * Baritone.settings().placeIncorrectBlockPenaltyMultiplier.value; } else { - if (hasThrowaway) { + if (allowPlace && hasThrowaway) { return placeBlockCost; } else { return COST_INF; diff --git a/src/main/java/baritone/process/ElytraProcess.java b/src/main/java/baritone/process/ElytraProcess.java index e6d7ee34a..95597c6ee 100644 --- a/src/main/java/baritone/process/ElytraProcess.java +++ b/src/main/java/baritone/process/ElytraProcess.java @@ -446,7 +446,8 @@ public WalkOffCalculationContext(IBaritone baritone) { super(baritone, true); this.allowFallIntoLava = true; this.minFallHeight = 8; - this.maxFallHeightNoWater = 10000; + this.maxFallHeightNoClutch = 10000; + this.placeBlockCost = COST_INF; } @Override @@ -458,11 +459,6 @@ public double costOfPlacingAt(int x, int y, int z, BlockState current) { public double breakCostMultiplierAt(int x, int y, int z, BlockState current) { return COST_INF; } - - @Override - public double placeBucketCost() { - return COST_INF; - } } private static boolean isInBounds(BlockPos pos) { diff --git a/src/main/java/baritone/utils/pathing/MutableClutchResult.java b/src/main/java/baritone/utils/pathing/MutableClutchResult.java new file mode 100644 index 000000000..09ea29f05 --- /dev/null +++ b/src/main/java/baritone/utils/pathing/MutableClutchResult.java @@ -0,0 +1,35 @@ +/* + * 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.utils.pathing; + +import baritone.pathing.clutch.Clutch; +import net.minecraft.world.item.ItemStack; + +public final class MutableClutchResult { + public Clutch clutch; + public ItemStack item; + + public MutableClutchResult() { + reset(); + } + + public void reset() { + clutch = null; + item = null; + } +} diff --git a/src/main/java/baritone/utils/pathing/MutableMoveResult.java b/src/main/java/baritone/utils/pathing/MutableMoveResult.java index 17fc6ee2d..0d71ce39d 100644 --- a/src/main/java/baritone/utils/pathing/MutableMoveResult.java +++ b/src/main/java/baritone/utils/pathing/MutableMoveResult.java @@ -35,7 +35,7 @@ public MutableMoveResult() { reset(); } - public final void reset() { + public void reset() { x = 0; y = 0; z = 0;