Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Doors #1445

Closed
wants to merge 13 commits into from
26 changes: 17 additions & 9 deletions src/main/java/baritone/behavior/PathingBehavior.java
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@
import baritone.utils.PathRenderer;
import baritone.utils.PathingCommandContext;
import baritone.utils.pathing.Favoring;
import baritone.utils.pathing.SpaceRequest;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.Tuple;
import net.minecraft.util.math.BlockPos;

import java.util.ArrayList;
Expand Down Expand Up @@ -383,22 +386,27 @@ public BetterBlockPos pathStart() { // TODO move to a helper or util class
if (ctx.player().onGround) {
double playerX = ctx.player().posX;
double playerZ = ctx.player().posZ;
ArrayList<BetterBlockPos> closest = new ArrayList<>();
for (int dx = -1; dx <= 1; dx++) {
for (int dz = -1; dz <= 1; dz++) {
closest.add(new BetterBlockPos(feet.x + dx, feet.y, feet.z + dz));
}
}
closest.sort(Comparator.comparingDouble(pos -> ((pos.x + 0.5D) - playerX) * ((pos.x + 0.5D) - playerX) + ((pos.z + 0.5D) - playerZ) * ((pos.z + 0.5D) - playerZ)));
ArrayList<Tuple<BetterBlockPos, EnumFacing>> closest = new ArrayList<>();
// The North block needs its southern side clear
closest.add(new Tuple<>(feet.north(), EnumFacing.SOUTH));
closest.add(new Tuple<>(feet.east(), EnumFacing.WEST));
closest.add(new Tuple<>(feet.south(), EnumFacing.NORTH));
closest.add(new Tuple<>(feet.west(), EnumFacing.EAST));
closest.sort(Comparator.comparingDouble(n -> {
BetterBlockPos pos = n.getFirst();
return ((pos.x + 0.5D) - playerX) * ((pos.x + 0.5D) - playerX) + ((pos.z + 0.5D) - playerZ) * ((pos.z + 0.5D) - playerZ);
}));
for (int i = 0; i < 4; i++) {
BetterBlockPos possibleSupport = closest.get(i);
Tuple<BetterBlockPos, EnumFacing> possibleSupportTuple = closest.get(i);
EnumFacing possibleSupportSide = possibleSupportTuple.getSecond();
BetterBlockPos possibleSupport = possibleSupportTuple.getFirst();
double xDist = Math.abs((possibleSupport.x + 0.5D) - playerX);
double zDist = Math.abs((possibleSupport.z + 0.5D) - playerZ);
if (xDist > 0.8 && zDist > 0.8) {
// can't possibly be sneaking off of this one, we're too far away
continue;
}
if (MovementHelper.canWalkOn(ctx, possibleSupport.down()) && MovementHelper.canWalkThrough(ctx, possibleSupport) && MovementHelper.canWalkThrough(ctx, possibleSupport.up())) {
if (MovementHelper.canWalkOn(ctx, possibleSupport.down()) && MovementHelper.canWalkThrough(ctx, possibleSupport, SpaceRequest.fromFaces(possibleSupportSide)) && MovementHelper.canWalkThrough(ctx, possibleSupport.up(), SpaceRequest.fromFaces(possibleSupportSide))) {
// this is plausible
//logDebug("Faking path start assuming player is standing off the edge of a block");
return possibleSupport;
Expand Down
30 changes: 18 additions & 12 deletions src/main/java/baritone/pathing/movement/Movement.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
import baritone.api.utils.input.Input;
import baritone.behavior.PathingBehavior;
import baritone.utils.BlockStateInterface;
import baritone.utils.pathing.PositionalSpaceRequest;
import baritone.utils.pathing.SpaceRequest;
import net.minecraft.block.BlockLiquid;
import net.minecraft.entity.item.EntityFallingBlock;
import net.minecraft.util.EnumFacing;
Expand All @@ -47,9 +49,9 @@ public abstract class Movement implements IMovement, MovementHelper {
protected final BetterBlockPos dest;

/**
* The positions that need to be broken before this movement can ensue
* The movement space needed before this movement can ensue
*/
protected final BetterBlockPos[] positionsToBreak;
protected final PositionalSpaceRequest[] spaceRequests;

/**
* The position where we need to place a block before this movement can ensue
Expand All @@ -66,17 +68,17 @@ public abstract class Movement implements IMovement, MovementHelper {

private Boolean calculatedWhileLoaded;

protected Movement(IBaritone baritone, BetterBlockPos src, BetterBlockPos dest, BetterBlockPos[] toBreak, BetterBlockPos toPlace) {
protected Movement(IBaritone baritone, BetterBlockPos src, BetterBlockPos dest, PositionalSpaceRequest[] spaceRequested, BetterBlockPos toPlace) {
this.baritone = baritone;
this.ctx = baritone.getPlayerContext();
this.src = src;
this.dest = dest;
this.positionsToBreak = toBreak;
this.spaceRequests = spaceRequested;
this.positionToPlace = toPlace;
}

protected Movement(IBaritone baritone, BetterBlockPos src, BetterBlockPos dest, BetterBlockPos[] toBreak) {
this(baritone, src, dest, toBreak, null);
protected Movement(IBaritone baritone, BetterBlockPos src, BetterBlockPos dest, PositionalSpaceRequest[] spaceRequested) {
this(baritone, src, dest, spaceRequested, null);
}

public double getCost() throws NullPointerException {
Expand Down Expand Up @@ -157,11 +159,13 @@ protected boolean prepared(MovementState state) {
return true;
}
boolean somethingInTheWay = false;
for (BetterBlockPos blockPos : positionsToBreak) {
for (PositionalSpaceRequest request : spaceRequests) {
BetterBlockPos blockPos = request.getPos();
int spaceRequest = request.getRequest();
if (!ctx.world().getEntitiesWithinAABB(EntityFallingBlock.class, new AxisAlignedBB(0, 0, 0, 1, 1.1, 1).offset(blockPos)).isEmpty() && Baritone.settings().pauseMiningForFallingBlocks.value) {
return false;
}
if (!MovementHelper.canWalkThrough(ctx, blockPos) && !(BlockStateInterface.getBlock(ctx, blockPos) instanceof BlockLiquid)) { // can't break liquid, so don't try
if (!MovementHelper.canWalkThrough(ctx, blockPos, spaceRequest) && !(BlockStateInterface.getBlock(ctx, blockPos) instanceof BlockLiquid)) { // can't break liquid, so don't try
somethingInTheWay = true;
MovementHelper.switchToBestToolFor(ctx, BlockStateInterface.get(ctx, blockPos));
Optional<Rotation> reachable = RotationUtils.reachable(ctx.player(), blockPos, ctx.playerController().getBlockReachDistance());
Expand Down Expand Up @@ -264,8 +268,10 @@ public List<BlockPos> toBreak(BlockStateInterface bsi) {
return toBreakCached;
}
List<BlockPos> result = new ArrayList<>();
for (BetterBlockPos positionToBreak : positionsToBreak) {
if (!MovementHelper.canWalkThrough(bsi, positionToBreak.x, positionToBreak.y, positionToBreak.z)) {
for (PositionalSpaceRequest request : spaceRequests) {
BetterBlockPos positionToBreak = request.getPos();
int spaceRequest = request.getRequest();
if (!MovementHelper.canWalkThrough(bsi, positionToBreak.x, positionToBreak.y, positionToBreak.z, spaceRequest)) {
result.add(positionToBreak);
}
}
Expand All @@ -292,7 +298,7 @@ public List<BlockPos> toWalkInto(BlockStateInterface bsi) { // overridden by mov
return toWalkIntoCached;
}

public BlockPos[] toBreakAll() {
return positionsToBreak;
public PositionalSpaceRequest[] allSpaceRequests() {
return spaceRequests;
}
}
94 changes: 79 additions & 15 deletions src/main/java/baritone/pathing/movement/MovementHelper.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@
import baritone.pathing.movement.MovementState.MovementTarget;
import baritone.utils.BlockStateInterface;
import baritone.utils.ToolSet;
import baritone.utils.pathing.PositionalSpaceRequest;
import baritone.utils.pathing.SpaceRequest;
import net.minecraft.block.*;
import net.minecraft.block.properties.PropertyBool;
import net.minecraft.block.state.IBlockState;
Expand Down Expand Up @@ -76,15 +78,24 @@ static boolean avoidAdjacentBreaking(BlockStateInterface bsi, int x, int y, int
return block instanceof BlockLiquid;
}

static boolean canWalkThrough(IPlayerContext ctx, BetterBlockPos pos) {
return canWalkThrough(new BlockStateInterface(ctx), pos.x, pos.y, pos.z);
static boolean canWalkThrough(IPlayerContext ctx, PositionalSpaceRequest posReq) {
return canWalkThrough(ctx, posReq.getPos(), posReq.getRequest());
}

static boolean canWalkThrough(BlockStateInterface bsi, int x, int y, int z) {
return canWalkThrough(bsi, x, y, z, bsi.get0(x, y, z));
static boolean canWalkThrough(BlockStateInterface bsi, PositionalSpaceRequest posReq) {
BetterBlockPos pos = posReq.getPos();
return canWalkThrough(bsi, pos.x, pos.y, pos.z, posReq.getRequest());
}

static boolean canWalkThrough(BlockStateInterface bsi, int x, int y, int z, IBlockState state) {
static boolean canWalkThrough(IPlayerContext ctx, BetterBlockPos pos, int request) {
return canWalkThrough(new BlockStateInterface(ctx), pos.x, pos.y, pos.z, request);
}

static boolean canWalkThrough(BlockStateInterface bsi, int x, int y, int z, int request) {
return canWalkThrough(bsi, x, y, z, bsi.get0(x, y, z), request);
}

static boolean canWalkThrough(BlockStateInterface bsi, int x, int y, int z, IBlockState state, int request) {
Block block = state.getBlock();
if (block == Blocks.AIR) { // early return for most common case
return true;
Expand All @@ -95,11 +106,11 @@ static boolean canWalkThrough(BlockStateInterface bsi, int x, int y, int z, IBlo
if (Baritone.settings().blocksToAvoid.value.contains(block)) {
return false;
}
if (block instanceof BlockDoor || block instanceof BlockFenceGate) {
// Because there's no nice method in vanilla to check if a door is openable or not, we just have to assume
// that anything that isn't an iron door isn't openable, ignoring that some doors introduced in mods can't
// be opened by just interacting.
return block != Blocks.IRON_DOOR;
if (block instanceof BlockFenceGate) {
return true;
}
if (block instanceof BlockDoor) {
return doorCanFulfillRequest(bsi, x, y, z, state, request);
}
if (block == Blocks.CARPET) {
return canWalkOn(bsi, x, y - 1, z);
Expand Down Expand Up @@ -137,6 +148,59 @@ static boolean canWalkThrough(BlockStateInterface bsi, int x, int y, int z, IBlo
return block.isPassable(bsi.access, bsi.isPassableBlockPos.setPos(x, y, z));
}

static boolean doorCanFulfillRequest(BlockStateInterface bsi, int x, int y, int z, IBlockState state, int req) {
IBlockState lowerDoor;
IBlockState upperDoor;
if (state.getValue(BlockDoor.HALF) == BlockDoor.EnumDoorHalf.UPPER) {
upperDoor = state;
lowerDoor = bsi.get0(x, y - 1, z);
} else {
upperDoor = bsi.get0(x, y + 1, z);
lowerDoor = state;
}
if (upperDoor.getBlock() != lowerDoor.getBlock()) {
return false;
}

// Because there's no nice method in vanilla to check if a door is openable or not, we just have to assume
// that anything that isn't an iron door isn't openable, ignoring that some doors introduced in mods can't
// be opened by just interacting.
if (upperDoor.getBlock() == Blocks.IRON_DOOR) {
// We cannot change it
EnumFacing doorFacing = lowerDoor.getValue(BlockDoor.FACING).getOpposite();
if (lowerDoor.getValue(BlockDoor.OPEN)) {
BlockDoor.EnumHingePosition e = upperDoor.getValue(BlockDoor.HINGE);
switch (e) {
case LEFT:
doorFacing = doorFacing.rotateY();
break;
case RIGHT:
doorFacing = doorFacing.rotateYCCW();
break;
default:
return false;
}
}
return !SpaceRequest.requires(req, doorFacing);
} else {
// Can we make it work?
EnumFacing doorFacing = lowerDoor.getValue(BlockDoor.FACING).getOpposite();
if (SpaceRequest.requires(req, doorFacing)) {
BlockDoor.EnumHingePosition e = upperDoor.getValue(BlockDoor.HINGE);
switch (e) {
case LEFT:
return !SpaceRequest.requires(req, doorFacing.rotateY());
case RIGHT:
return !SpaceRequest.requires(req, doorFacing.rotateYCCW());
default:
return false;
}
} else {
return true;
}
}
}

/**
* canWalkThrough but also won't impede movement at all. so not including doors or fence gates (we'd have to right click),
* not including water, and not including ladders or vines or cobwebs (they slow us down)
Expand Down Expand Up @@ -373,13 +437,13 @@ static boolean canPlaceAgainst(BlockStateInterface bsi, int x, int y, int z, IBl
return state.isBlockNormalCube() || state.isFullBlock() || state.getBlock() == Blocks.GLASS || state.getBlock() == Blocks.STAINED_GLASS;
}

static double getMiningDurationTicks(CalculationContext context, int x, int y, int z, boolean includeFalling) {
return getMiningDurationTicks(context, x, y, z, context.get(x, y, z), includeFalling);
static double getMiningDurationTicks(CalculationContext context, int x, int y, int z, boolean includeFalling, int request) {
return getMiningDurationTicks(context, x, y, z, context.get(x, y, z), includeFalling, request);
}

static double getMiningDurationTicks(CalculationContext context, int x, int y, int z, IBlockState state, boolean includeFalling) {
static double getMiningDurationTicks(CalculationContext context, int x, int y, int z, IBlockState state, boolean includeFalling, int request) {
Block block = state.getBlock();
if (!canWalkThrough(context.bsi, x, y, z, state)) {
if (!canWalkThrough(context.bsi, x, y, z, state, request)) {
if (block instanceof BlockLiquid) {
return COST_INF;
}
Expand All @@ -400,7 +464,7 @@ static double getMiningDurationTicks(CalculationContext context, int x, int y, i
if (includeFalling) {
IBlockState above = context.get(x, y + 1, z);
if (above.getBlock() instanceof BlockFalling) {
result += getMiningDurationTicks(context, x, y + 1, z, above, true);
result += getMiningDurationTicks(context, x, y + 1, z, above, true, request);
}
}
return result;
Expand Down
Loading