Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 31 additions & 35 deletions src/main/java/baritone/pathing/movement/MovementHelper.java
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
import net.minecraft.world.level.block.piston.MovingPistonBlock;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.properties.BooleanProperty;
import net.minecraft.world.level.block.state.properties.DoorHingeSide;
import net.minecraft.world.level.block.state.properties.Half;
import net.minecraft.world.level.block.state.properties.SlabType;
import net.minecraft.world.level.block.state.properties.StairsShape;
Expand All @@ -52,6 +53,7 @@
import net.minecraft.world.phys.Vec3;

import java.util.*;
import java.util.stream.Stream;

import static baritone.api.utils.RotationUtils.DEG_TO_RAD_F;
import static baritone.pathing.movement.Movement.HORIZONTALS_BUT_ALSO_DOWN_____SO_EVERY_DIRECTION_EXCEPT_UP;
Expand Down Expand Up @@ -153,11 +155,10 @@ static Ternary canWalkThroughBlockState(BlockState state) {
if (Baritone.settings().blocksToAvoid.value.contains(block)) {
return NO;
}
if (block instanceof DoorBlock || block instanceof FenceGateBlock) {
// TODO this assumes that all doors in all mods are openable
if (block == Blocks.IRON_DOOR) {
return NO;
}
if (block instanceof DoorBlock) {
return DoorBlock.isWoodenDoor(state) ? YES : NO;
}
if (block instanceof FenceGateBlock) {
return YES;
}
if (block instanceof CarpetBlock) {
Expand Down Expand Up @@ -331,17 +332,14 @@ static boolean isReplaceable(int x, int y, int z, BlockState state, BlockStateIn
return state.getMaterial().isReplaceable();
}

static boolean isDoorPassable(IPlayerContext ctx, BlockPos doorPos, BlockPos playerPos) {
if (playerPos.equals(doorPos)) {
return false;
}

BlockState state = BlockStateInterface.get(ctx, doorPos);
if (!(state.getBlock() instanceof DoorBlock)) {
return true;
}
static boolean isDoorPassable(BlockState state, Direction side) {
boolean open = state.getValue(DoorBlock.OPEN);
Direction closedFacing = state.getValue(HorizontalDirectionalBlock.FACING);
Direction openFacing = state.getValue(DoorBlock.HINGE) == DoorHingeSide.LEFT
? closedFacing.getClockWise()
: closedFacing.getCounterClockWise();

return isHorizontalBlockPassable(doorPos, state, playerPos, DoorBlock.OPEN);
return side != (open ? openFacing : closedFacing);
}

static boolean isGatePassable(IPlayerContext ctx, BlockPos gatePos, BlockPos playerPos) {
Expand All @@ -357,26 +355,6 @@ static boolean isGatePassable(IPlayerContext ctx, BlockPos gatePos, BlockPos pla
return state.getValue(FenceGateBlock.OPEN);
}

static boolean isHorizontalBlockPassable(BlockPos blockPos, BlockState blockState, BlockPos playerPos, BooleanProperty propertyOpen) {
if (playerPos.equals(blockPos)) {
return false;
}

Direction.Axis facing = blockState.getValue(HorizontalDirectionalBlock.FACING).getAxis();
boolean open = blockState.getValue(propertyOpen);

Direction.Axis playerFacing;
if (playerPos.north().equals(blockPos) || playerPos.south().equals(blockPos)) {
playerFacing = Direction.Axis.Z;
} else if (playerPos.east().equals(blockPos) || playerPos.west().equals(blockPos)) {
playerFacing = Direction.Axis.X;
} else {
return true;
}

return (facing == playerFacing) == open;
}

static boolean avoidWalkingInto(BlockState state) {
Block block = state.getBlock();
return !state.getFluidState().isEmpty()
Expand Down Expand Up @@ -787,6 +765,24 @@ static boolean isBlockNormalCube(BlockState state) {
return false;
}

static boolean openDoors(IPlayerContext ctx, MovementState state, BetterBlockPos from, BetterBlockPos to) {
Direction direction = Stream.of(Direction.values())
.filter(d -> from.relative(d).equals(to))
.findFirst()
.get();

for (BetterBlockPos pos : new BetterBlockPos[]{from, to, from.above(), to.above()}) {
Direction side = pos.equals(to) || pos.equals(to.above()) ? direction : direction.getOpposite();
BlockState door = BlockStateInterface.get(ctx, pos);
if (DoorBlock.isWoodenDoor(door) && !isDoorPassable(door, side)) {
state.setTarget(new MovementState.MovementTarget(RotationUtils.calcRotationFromVec3d(ctx.playerHead(), VecUtils.calculateBlockCenter(ctx.world(), pos), ctx.playerRotations()), true))
.setInput(Input.CLICK_RIGHT, true);
return false;
}
}
return true;
}

static PlaceResult attemptToPlaceABlock(MovementState state, IBaritone baritone, BlockPos placeAt, boolean preferDown, boolean wouldSneak) {
IPlayerContext ctx = baritone.getPlayerContext();
Optional<Rotation> direct = RotationUtils.reachable(ctx, placeAt, wouldSneak); // we assume that if there is a block there, it must be replacable
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,10 @@ public MovementState updateState(MovementState state) {
return state.setStatus(MovementStatus.SUCCESS);
}

if (!MovementHelper.openDoors(ctx, state, src.above(), dest)) {
return state;
}

BlockState jumpingOnto = BlockStateInterface.get(ctx, positionToPlace);
if (!MovementHelper.canWalkOn(ctx, positionToPlace, jumpingOnto)) {
ticksWithoutPlacement++;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,11 @@ public MovementState updateState(MovementState state) {
// System.out.println(player().position().y + " " + playerFeet.getY() + " " + (player().position().y - playerFeet.getY()));
}*/
}

if (!MovementHelper.openDoors(ctx, state, src, dest.above())) {
return state;
}

if (safeMode()) {
double destX = (src.getX() + 0.5) * 0.17 + (dest.getX() + 0.5) * 0.83;
double destZ = (src.getZ() + 0.5) * 0.17 + (dest.getZ() + 0.5) * 0.83;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,15 +29,20 @@
import baritone.utils.BlockStateInterface;
import baritone.utils.pathing.MutableMoveResult;
import com.google.common.collect.ImmutableSet;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import net.minecraft.client.player.LocalPlayer;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.core.Vec3i;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.DoorBlock;
import net.minecraft.world.level.block.HorizontalDirectionalBlock;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.properties.DoorHingeSide;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

public class MovementDiagonal extends Movement {

Expand Down Expand Up @@ -109,7 +114,8 @@ protected Set<BetterBlockPos> calculateValidPositions() {
}

public static void cost(CalculationContext context, int x, int y, int z, int destX, int destZ, MutableMoveResult res) {
if (!MovementHelper.canWalkThrough(context, destX, y + 1, destZ)) {
BlockState destIntoUpper = context.get(destX, y + 1, destZ);
if (!MovementHelper.canWalkThrough(context, destX, y + 1, destZ, destIntoUpper)) {
return;
}
BlockState destInto = context.get(destX, y, destZ);
Expand Down Expand Up @@ -139,6 +145,10 @@ public static void cost(CalculationContext context, int x, int y, int z, int des
}
frostWalker &= !context.assumeWalkOnWater; // do this after checking for descends because jesus can't prevent the water from freezing, it just prevents us from relying on the water freezing
}
BlockState startState = context.get(x, y, z);
if (isBlockingDoor(startState, x, z, destX, destZ) || isBlockingDoor(ascend ? destIntoUpper : destInto, destX, destZ, x, y)) {
return; // Easier to just traverse instead
}
double multiplier = WALK_ONE_BLOCK_COST;
// For either possible soul sand, that affects half of our walking
if (destWalkOn.is(Blocks.SOUL_SAND)) {
Expand Down Expand Up @@ -166,11 +176,10 @@ public static void cost(CalculationContext context, int x, int y, int z, int des
return;
}
BlockState cuttingOver2 = context.get(destX, y - 1, z);
if ((!context.allowWalkOnMagmaBlocks && cuttingOver1.is(Blocks.MAGMA_BLOCK)) || MovementHelper.isLava(cuttingOver2)) {
if ((!context.allowWalkOnMagmaBlocks && cuttingOver2.is(Blocks.MAGMA_BLOCK)) || MovementHelper.isLava(cuttingOver2)) {
return;
}
boolean water = false;
BlockState startState = context.get(x, y, z);
Block startIn = startState.getBlock();
if (MovementHelper.isWater(startState) || MovementHelper.isWater(destInto)) {
if (ascend) {
Expand All @@ -191,6 +200,8 @@ public static void cost(CalculationContext context, int x, int y, int z, int des
boolean BTop = MovementHelper.canWalkThrough(context, destX, y + 2, z);
boolean BMid = MovementHelper.canWalkThrough(context, destX, y + 1, z);
boolean BLow = MovementHelper.canWalkThrough(context, destX, y, z, pb2);
ALow &= !isBlockingDoor(pb0, x, destZ, destX, z);
BLow &= !isBlockingDoor(pb2, destX, z, x, destZ);
if ((!(ATop && AMid && ALow) && !(BTop && BMid && BLow)) // no option
|| MovementHelper.avoidWalkingInto(pb0) // bad
|| MovementHelper.avoidWalkingInto(pb2) // bad
Expand All @@ -208,6 +219,8 @@ public static void cost(CalculationContext context, int x, int y, int z, int des
}
double optionA = MovementHelper.getMiningDurationTicks(context, x, y, destZ, pb0, false);
double optionB = MovementHelper.getMiningDurationTicks(context, destX, y, z, pb2, false);
optionA += isBlockingDoor(pb0, x, destZ, destX, z) ? 1 : 0;
optionB += isBlockingDoor(pb2, destX, z, x, destZ) ? 1 : 0;
if (optionA != 0 && optionB != 0) {
// check these one at a time -- if pb0 and pb2 were nonzero, we already know that (optionA != 0 && optionB != 0)
// so no need to check pb1 as well, might as well return early here
Expand Down Expand Up @@ -271,6 +284,20 @@ public MovementState updateState(MovementState state) {
} else if (!playerInValidPosition() && !(MovementHelper.isLiquid(ctx, src) && getValidPositions().contains(ctx.playerFeet().above()))) {
return state.setStatus(MovementStatus.UNREACHABLE);
}

if (!isBlockingDoor(BlockStateInterface.get(ctx, new BetterBlockPos(src.x, src.y, dest.z)), src.x, dest.z, dest.x, src.z)
&& (!MovementHelper.openDoors(ctx, state, src, new BetterBlockPos(src.x, src.y, dest.z))
|| !MovementHelper.openDoors(ctx, state, new BetterBlockPos(src.x, dest.y, dest.z), dest)
)) {
return state;
}
if (!isBlockingDoor(BlockStateInterface.get(ctx, new BetterBlockPos(dest.x, src.y, src.z)), dest.x, src.z, src.x, dest.z)
&& (!MovementHelper.openDoors(ctx, state, src, new BetterBlockPos(dest.x, src.y, src.z))
|| !MovementHelper.openDoors(ctx, state, new BetterBlockPos(dest.x, dest.y, src.z), dest)
)) {
return state;
}

if (dest.y > src.y && ctx.player().position().y < src.y + 0.1 && ctx.player().horizontalCollision) {
state.setInput(Input.JUMP, true);
}
Expand Down Expand Up @@ -328,4 +355,32 @@ public List<BlockPos> toWalkInto(BlockStateInterface bsi) {
toWalkIntoCached = result;
return toWalkIntoCached;
}

/**
* We can always pass wooden doors in src or dest and we can also pass
* wooden doors in the A or B columns, unless their hinge points towards
* the other column.
* This function checks whether {@code other} is the diagonal neighbor of
* {@code door} in the direction of the hinge of {@code state}.
*/
private static boolean isBlockingDoor(BlockState state, int doorX, int doorZ, int otherX, int otherZ) {
if (!(state.getBlock() instanceof DoorBlock)) {
return false;
}

Vec3i offset = state.getValue(HorizontalDirectionalBlock.FACING).getNormal();
int ox = offset.getX();
int oz = offset.getZ();

int nbrX, nbrZ;
if (state.getValue(DoorBlock.HINGE) == DoorHingeSide.LEFT) {
nbrX = doorX - ox + oz;
nbrZ = doorZ - oz - ox;
} else {
nbrX = doorX - ox - oz;
nbrZ = doorZ - oz + ox;
}

return nbrX == otherX && nbrZ == otherZ;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,11 @@ public MovementState updateState(MovementState state) {
}
}
}

if (!MovementHelper.openDoors(ctx, state, src, new BetterBlockPos(dest.x, src.y, dest.z))) {
return state;
}

if (targetRotation != null) {
state.setTarget(new MovementTarget(targetRotation, true));
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,9 @@ public MovementState updateState(MovementState state) {
logDebug("sorry");
return state.setStatus(MovementStatus.UNREACHABLE);
}
if (!MovementHelper.openDoors(ctx, state, src, src.relative(direction))) {
return state;
}
if (dist >= 4 || ascend) {
state.setInput(Input.SPRINT, true);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.CarpetBlock;
import net.minecraft.world.level.block.DoorBlock;
import net.minecraft.world.level.block.FenceGateBlock;
import net.minecraft.world.level.block.LadderBlock;
import net.minecraft.world.level.block.SlabBlock;
Expand Down Expand Up @@ -223,14 +222,8 @@ public MovementState updateState(MovementState state) {
//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()));

if (notPassable && canOpen) {
return state.setTarget(new MovementState.MovementTarget(RotationUtils.calcRotationFromVec3d(ctx.playerHead(), VecUtils.calculateBlockCenter(ctx.world(), positionsToBreak[0]), ctx.playerRotations()), true))
.setInput(Input.CLICK_RIGHT, true);
}
if (!MovementHelper.openDoors(ctx, state, src, dest)) {
return state;
}

if (pb0.getBlock() instanceof FenceGateBlock || pb1.getBlock() instanceof FenceGateBlock) {
Expand Down
13 changes: 13 additions & 0 deletions src/main/java/baritone/pathing/path/PathExecutor.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import baritone.pathing.movement.CalculationContext;
import baritone.pathing.movement.Movement;
import baritone.pathing.movement.MovementHelper;
import baritone.pathing.movement.MovementState;
import baritone.pathing.movement.movements.*;
import baritone.utils.BlockStateInterface;
import net.minecraft.core.BlockPos;
Expand Down Expand Up @@ -466,6 +467,18 @@ private boolean shouldSprintNextTick() {
return true;
}
clearKeys();
// we are not ticking the movement, so we gotta do this ourselves
BetterBlockPos src = current.getSrc();
BetterBlockPos dest = current.getDest();
MovementState fakeState = new MovementState();
if (!MovementHelper.openDoors(ctx, fakeState, src, new BetterBlockPos(dest.x, src.y, dest.z))) {
boolean forceRotations = fakeState.getTarget().hasToForceRotations();
fakeState.getTarget().getRotation().ifPresent(rotation ->
behavior.baritone.getLookBehavior().updateTarget(rotation, forceRotations));
fakeState.getInputStates().forEach(behavior.baritone.getInputOverrideHandler()::setInputForceState);
fakeState.getInputStates().clear();
return true;
}
behavior.baritone.getLookBehavior().updateTarget(RotationUtils.calcRotationFromVec3d(ctx.playerHead(), data.getA(), ctx.playerRotations()), false);
behavior.baritone.getInputOverrideHandler().setInputForceState(Input.MOVE_FORWARD, true);
return true;
Expand Down