diff --git a/src/api/java/baritone/api/Settings.java b/src/api/java/baritone/api/Settings.java index d008007ce..43ace5e31 100644 --- a/src/api/java/baritone/api/Settings.java +++ b/src/api/java/baritone/api/Settings.java @@ -1550,6 +1550,11 @@ public final class Settings { */ public final Setting elytraChatSpam = new Setting<>(false); + /** + * Sneak when magma blocks are under feet + */ + public final Setting allowWalkOnMagmaBlocks = new Setting<>(false); + /** * A map of lowercase setting field names to their respective setting */ diff --git a/src/main/java/baritone/pathing/movement/CalculationContext.java b/src/main/java/baritone/pathing/movement/CalculationContext.java index ffd1a2fca..5dfc8b7d0 100644 --- a/src/main/java/baritone/pathing/movement/CalculationContext.java +++ b/src/main/java/baritone/pathing/movement/CalculationContext.java @@ -79,6 +79,7 @@ public class CalculationContext { public double backtrackCostFavoringCoefficient; public double jumpPenalty; public final double walkOnWaterOnePenalty; + public final boolean allowWalkOnMagmaBlocks; public final BetterWorldBorder worldBorder; public final PrecomputedData precomputedData; @@ -125,6 +126,7 @@ public class CalculationContext { this.backtrackCostFavoringCoefficient = Baritone.settings().backtrackCostFavoringCoefficient.value; this.jumpPenalty = Baritone.settings().jumpPenalty.value; this.walkOnWaterOnePenalty = Baritone.settings().walkOnWaterOnePenalty.value; + this.allowWalkOnMagmaBlocks = Baritone.settings().allowWalkOnMagmaBlocks.value; // why cache these things here, why not let the movements just get directly from settings? // 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. diff --git a/src/main/java/baritone/pathing/movement/MovementHelper.java b/src/main/java/baritone/pathing/movement/MovementHelper.java index b45e41a23..50734a367 100644 --- a/src/main/java/baritone/pathing/movement/MovementHelper.java +++ b/src/main/java/baritone/pathing/movement/MovementHelper.java @@ -52,6 +52,7 @@ import net.minecraft.world.phys.HitResult; import net.minecraft.world.phys.Vec3; import org.jetbrains.annotations.NotNull; +import java.util.ArrayList; import java.util.List; import java.util.Optional; @@ -387,7 +388,7 @@ public interface MovementHelper extends ActionCosts, Helper { static boolean avoidWalkingInto(BlockState state) { Block block = state.getBlock(); return !state.getFluidState().isEmpty() - || block == Blocks.MAGMA_BLOCK + || (block == Blocks.MAGMA_BLOCK && !Baritone.settings().allowWalkOnMagmaBlocks.value) || block == Blocks.CACTUS || block == Blocks.SWEET_BERRY_BUSH || block instanceof BaseFireBlock @@ -423,7 +424,7 @@ public interface MovementHelper extends ActionCosts, Helper { static Ternary canWalkOnBlockState(BlockState state) { Block block = state.getBlock(); - if (isBlockNormalCube(state) && block != Blocks.MAGMA_BLOCK && block != Blocks.BUBBLE_COLUMN && block != Blocks.HONEY_BLOCK) { + if (isBlockNormalCube(state) && (block != Blocks.MAGMA_BLOCK || Baritone.settings().allowWalkOnMagmaBlocks.value) && block != Blocks.BUBBLE_COLUMN && block != Blocks.HONEY_BLOCK) { return YES; } if (block instanceof AzaleaBlock) { @@ -859,4 +860,16 @@ public interface MovementHelper extends ActionCosts, Helper { b == Blocks.LAVA || b == Blocks.WATER; } + + static List steppingOnBlocks(IPlayerContext ctx) { + List blocks = new ArrayList<>(); + for (byte x = -1; x <= 1; x++) { + for (byte z = -1; z <= 1; z++) { + if (ctx.player().getBoundingBox().intersects(Vec3.atLowerCornerOf(ctx.player().blockPosition()).add(x, 0, z), Vec3.atLowerCornerOf(ctx.player().blockPosition()).add(x + 1, 1, z + 1))) { + blocks.add(new BetterBlockPos(ctx.player().getBlockX() + x, ctx.player().getBlockY() - 1, ctx.player().getBlockZ() + z)); + } + } + } + return blocks; + } } diff --git a/src/main/java/baritone/pathing/movement/movements/MovementAscend.java b/src/main/java/baritone/pathing/movement/movements/MovementAscend.java index 717cd2e70..2ecd9d723 100644 --- a/src/main/java/baritone/pathing/movement/movements/MovementAscend.java +++ b/src/main/java/baritone/pathing/movement/movements/MovementAscend.java @@ -131,8 +131,10 @@ public class MovementAscend extends Movement { } } else { // jumpingFromBottomSlab must be false - if (toPlace.getBlock() == Blocks.SOUL_SAND) { + if (toPlace.is(Blocks.SOUL_SAND)) { walk = WALK_ONE_OVER_SOUL_SAND_COST; + } else if (toPlace.is(Blocks.MAGMA_BLOCK)) { + walk = SNEAK_ONE_BLOCK_COST; } else { walk = Math.max(JUMP_ONE_BLOCK_COST, WALK_ONE_BLOCK_COST); } @@ -188,6 +190,9 @@ public class MovementAscend extends Movement { return state; } MovementHelper.moveTowards(ctx, state, dest); + + state.setInput(Input.SNEAK, Baritone.settings().allowWalkOnMagmaBlocks.value && jumpingOnto.is(Blocks.MAGMA_BLOCK)); + if (MovementHelper.isBottomSlab(jumpingOnto) && !MovementHelper.isBottomSlab(BlockStateInterface.get(ctx, src.below()))) { return state; // don't jump while walking from a non double slab into a bottom slab } diff --git a/src/main/java/baritone/pathing/movement/movements/MovementDescend.java b/src/main/java/baritone/pathing/movement/movements/MovementDescend.java index 0b84ef4db..3e860e301 100644 --- a/src/main/java/baritone/pathing/movement/movements/MovementDescend.java +++ b/src/main/java/baritone/pathing/movement/movements/MovementDescend.java @@ -17,6 +17,7 @@ package baritone.pathing.movement.movements; +import baritone.Baritone; import baritone.api.IBaritone; import baritone.api.pathing.movement.MovementStatus; import baritone.api.utils.BetterBlockPos; @@ -255,6 +256,9 @@ public class MovementDescend extends Movement { double x = ctx.player().position().x - (src.getX() + 0.5); double z = ctx.player().position().z - (src.getZ() + 0.5); double fromStart = Math.sqrt(x * x + z * z); + + state.setInput(Input.SNEAK, Baritone.settings().allowWalkOnMagmaBlocks.value && ctx.world().getBlockState(ctx.player().blockPosition().below()).is(Blocks.MAGMA_BLOCK)); + if (!playerFeet.equals(dest) || ab > 0.25) { if (numTicks++ < 20 && fromStart < 1.25) { MovementHelper.moveTowards(ctx, state, fakeDest); diff --git a/src/main/java/baritone/pathing/movement/movements/MovementDiagonal.java b/src/main/java/baritone/pathing/movement/movements/MovementDiagonal.java index cf387d5c9..e7d74f03e 100644 --- a/src/main/java/baritone/pathing/movement/movements/MovementDiagonal.java +++ b/src/main/java/baritone/pathing/movement/movements/MovementDiagonal.java @@ -118,6 +118,7 @@ public class MovementDiagonal extends Movement { BlockState destWalkOn; boolean descend = false; boolean frostWalker = false; + boolean sneaking = false; if (!MovementHelper.canWalkThrough(context, destX, y, destZ, destInto)) { ascend = true; if (!context.allowDiagonalAscend || !MovementHelper.canWalkThrough(context, x, y + 2, z) || !MovementHelper.canWalkOn(context, destX, y, destZ, destInto) || !MovementHelper.canWalkThrough(context, destX, y + 2, destZ)) { @@ -140,8 +141,11 @@ public class MovementDiagonal extends Movement { } double multiplier = WALK_ONE_BLOCK_COST; // For either possible soul sand, that affects half of our walking - if (destWalkOn.getBlock() == Blocks.SOUL_SAND) { + if (destWalkOn.is(Blocks.SOUL_SAND)) { multiplier += (WALK_ONE_OVER_SOUL_SAND_COST - WALK_ONE_BLOCK_COST) / 2; + } else if (context.allowWalkOnMagmaBlocks && destWalkOn.is(Blocks.MAGMA_BLOCK)) { + multiplier += (SNEAK_ONE_BLOCK_COST - WALK_ONE_BLOCK_COST) / 2; + sneaking = true; } else if (frostWalker) { // frostwalker lets us walk on water without the penalty } else if (destWalkOn.getBlock() == Blocks.WATER) { @@ -153,13 +157,16 @@ public class MovementDiagonal extends Movement { } if (fromDownBlock == Blocks.SOUL_SAND) { multiplier += (WALK_ONE_OVER_SOUL_SAND_COST - WALK_ONE_BLOCK_COST) / 2; + } else if (context.allowWalkOnMagmaBlocks && fromDownBlock.equals(Blocks.MAGMA_BLOCK)) { + multiplier += (SNEAK_ONE_BLOCK_COST - WALK_ONE_BLOCK_COST) / 2; + sneaking = true; } BlockState cuttingOver1 = context.get(x, y - 1, destZ); - if (cuttingOver1.getBlock() == Blocks.MAGMA_BLOCK || MovementHelper.isLava(cuttingOver1)) { + if ((!context.allowWalkOnMagmaBlocks && cuttingOver1.is(Blocks.MAGMA_BLOCK)) || MovementHelper.isLava(cuttingOver1)) { return; } BlockState cuttingOver2 = context.get(destX, y - 1, z); - if (cuttingOver2.getBlock() == Blocks.MAGMA_BLOCK || MovementHelper.isLava(cuttingOver2)) { + if ((!context.allowWalkOnMagmaBlocks && cuttingOver1.is(Blocks.MAGMA_BLOCK)) || MovementHelper.isLava(cuttingOver2)) { return; } boolean water = false; @@ -234,7 +241,7 @@ public class MovementDiagonal extends Movement { } } else { // only can sprint if not edging around - if (context.canSprint && !water) { + if (context.canSprint && !water && !sneaking) { // If we aren't edging around anything, and we aren't in water // We can sprint =D // Don't check for soul sand, since we can sprint on that too @@ -270,6 +277,7 @@ public class MovementDiagonal extends Movement { if (sprint()) { state.setInput(Input.SPRINT, true); } + state.setInput(Input.SNEAK, Baritone.settings().allowWalkOnMagmaBlocks.value && MovementHelper.steppingOnBlocks(ctx).stream().anyMatch(block -> ctx.world().getBlockState(block).is(Blocks.MAGMA_BLOCK))); MovementHelper.moveTowards(ctx, state, dest); return state; } diff --git a/src/main/java/baritone/pathing/movement/movements/MovementFall.java b/src/main/java/baritone/pathing/movement/movements/MovementFall.java index cb8711757..c537fc2ca 100644 --- a/src/main/java/baritone/pathing/movement/movements/MovementFall.java +++ b/src/main/java/baritone/pathing/movement/movements/MovementFall.java @@ -94,6 +94,11 @@ public class MovementFall extends Movement { 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))) { + 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) { diff --git a/src/main/java/baritone/pathing/movement/movements/MovementParkour.java b/src/main/java/baritone/pathing/movement/movements/MovementParkour.java index d1f56ed81..5ea1e4dcc 100644 --- a/src/main/java/baritone/pathing/movement/movements/MovementParkour.java +++ b/src/main/java/baritone/pathing/movement/movements/MovementParkour.java @@ -102,14 +102,14 @@ public class MovementParkour extends Movement { return; // can't jump out of water } int maxJump; - if (standingOn.getBlock() == Blocks.SOUL_SAND) { + if (context.allowWalkOnMagmaBlocks && standingOn.is(Blocks.MAGMA_BLOCK)) { + maxJump = 2; + } else if (standingOn.getBlock() == Blocks.SOUL_SAND) { maxJump = 2; // 1 block gap + } else if (context.canSprint) { + maxJump = 4; } else { - if (context.canSprint) { - maxJump = 4; - } else { - maxJump = 3; - } + maxJump = 3; } // check parkour jumps from smallest to largest for obstacles/walls and landing positions @@ -262,6 +262,10 @@ public class MovementParkour extends Movement { if (dist >= 4 || ascend) { state.setInput(Input.SPRINT, true); } + if (Baritone.settings().allowWalkOnMagmaBlocks.value && ctx.world().getBlockState(ctx.playerFeet().below()).is(Blocks.MAGMA_BLOCK)) { + state.setInput(Input.SNEAK, true); + } + MovementHelper.moveTowards(ctx, state, dest); if (ctx.playerFeet().equals(dest)) { Block d = BlockStateInterface.getBlock(ctx, dest); diff --git a/src/main/java/baritone/pathing/movement/movements/MovementPillar.java b/src/main/java/baritone/pathing/movement/movements/MovementPillar.java index a11086d5b..8007eb767 100644 --- a/src/main/java/baritone/pathing/movement/movements/MovementPillar.java +++ b/src/main/java/baritone/pathing/movement/movements/MovementPillar.java @@ -229,8 +229,7 @@ public class MovementPillar extends Movement { return state.setStatus(MovementStatus.UNREACHABLE); } - - state.setInput(Input.SNEAK, ctx.player().position().y > dest.getY() || ctx.player().position().y < src.getY() + 0.2D); // delay placement by 1 tick for ncp compatibility + state.setInput(Input.SNEAK, true); // since (lower down) we only right click once player.isSneaking, and that happens the tick after we request to sneak double diffX = ctx.player().position().x - (dest.getX() + 0.5); diff --git a/src/main/java/baritone/pathing/movement/movements/MovementTraverse.java b/src/main/java/baritone/pathing/movement/movements/MovementTraverse.java index cff8ee636..10711e2e2 100644 --- a/src/main/java/baritone/pathing/movement/movements/MovementTraverse.java +++ b/src/main/java/baritone/pathing/movement/movements/MovementTraverse.java @@ -85,6 +85,7 @@ public class MovementTraverse extends Movement { if (frostWalker || MovementHelper.canWalkOn(context, destX, y - 1, destZ, destOn)) { //this is a walk, not a bridge double WC = WALK_ONE_BLOCK_COST; boolean water = false; + boolean sneaking = false; if (MovementHelper.isWater(pb0) || MovementHelper.isWater(pb1)) { WC = context.waterWalkSpeed; water = true; @@ -98,6 +99,9 @@ public class MovementTraverse extends Movement { } if (srcDownBlock == Blocks.SOUL_SAND) { WC += (WALK_ONE_OVER_SOUL_SAND_COST - WALK_ONE_BLOCK_COST) / 2; + } else if (context.allowWalkOnMagmaBlocks && srcDownBlock.equals(Blocks.MAGMA_BLOCK)) { + sneaking = true; + WC += (SNEAK_ONE_BLOCK_COST - WALK_ONE_BLOCK_COST) / 2; } } double hardness1 = MovementHelper.getMiningDurationTicks(context, destX, y, destZ, pb1, false); @@ -106,7 +110,7 @@ public class MovementTraverse extends Movement { } double hardness2 = MovementHelper.getMiningDurationTicks(context, destX, y + 1, destZ, pb0, true); // only include falling on the upper block to break if (hardness1 == 0 && hardness2 == 0) { - if (!water && context.canSprint) { + if (!water && !sneaking && context.canSprint) { // If there's nothing in the way, and this isn't water, and we aren't sneak placing // We can sprint =D // Don't check for soul sand, since we can sprint on that too @@ -213,12 +217,12 @@ public class MovementTraverse extends Movement { .setInput(Input.SPRINT, true); } - //sneak may have been set to true in the PREPPING state while mining an adjacent block - state.setInput(Input.SNEAK, false); - Block fd = BlockStateInterface.get(ctx, src.below()).getBlock(); boolean ladder = fd == Blocks.LADDER || fd == Blocks.VINE; + //sneak may have been set to true in the PREPPING state while mining an adjacent block, but we still want it to be true if the player is about to go on magma + state.setInput(Input.SNEAK, Baritone.settings().allowWalkOnMagmaBlocks.value && MovementHelper.steppingOnBlocks(ctx).stream().anyMatch(block -> ctx.world().getBlockState(block).is(Blocks.MAGMA_BLOCK))); + if (pb0.getBlock() instanceof DoorBlock || pb1.getBlock() instanceof DoorBlock) { boolean notPassable = pb0.getBlock() instanceof DoorBlock && !MovementHelper.isDoorPassable(ctx, src, dest) || pb1.getBlock() instanceof DoorBlock && !MovementHelper.isDoorPassable(ctx, dest, src); boolean canOpen = !(Blocks.IRON_DOOR.equals(pb0.getBlock()) || Blocks.IRON_DOOR.equals(pb1.getBlock()));