2018-08-08 03:16:53 +00:00
/ *
* This file is part of Baritone .
*
* Baritone is free software : you can redistribute it and / or modify
2018-09-17 22:11:40 +00:00
* it under the terms of the GNU Lesser General Public License as published by
2018-08-08 03:16:53 +00:00
* the Free Software Foundation , either version 3 of the License , or
* ( at your option ) any later version .
*
2018-08-08 04:15:22 +00:00
* Baritone is distributed in the hope that it will be useful ,
2018-08-08 03:16:53 +00:00
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
2018-09-17 22:11:40 +00:00
* GNU Lesser General Public License for more details .
2018-08-08 03:16:53 +00:00
*
2018-09-17 22:11:40 +00:00
* You should have received a copy of the GNU Lesser General Public License
2018-08-08 03:16:53 +00:00
* along with Baritone . If not , see < https : //www.gnu.org/licenses/>.
* /
2018-08-22 20:15:56 +00:00
package baritone.pathing.movement.movements ;
2018-08-06 01:17:04 +00:00
2018-09-12 03:50:29 +00:00
import baritone.Baritone ;
2018-10-09 01:37:52 +00:00
import baritone.api.pathing.movement.MovementStatus ;
2018-10-14 05:55:30 +00:00
import baritone.api.utils.* ;
2018-10-09 01:37:52 +00:00
import baritone.pathing.movement.CalculationContext ;
import baritone.pathing.movement.Movement ;
import baritone.pathing.movement.MovementHelper ;
import baritone.pathing.movement.MovementState ;
2018-08-22 20:15:56 +00:00
import baritone.utils.BlockStateInterface ;
import baritone.utils.InputOverrideHandler ;
2018-08-26 07:17:52 +00:00
import net.minecraft.block.* ;
2018-08-06 01:17:04 +00:00
import net.minecraft.block.state.IBlockState ;
import net.minecraft.client.Minecraft ;
import net.minecraft.init.Blocks ;
2018-08-06 22:53:35 +00:00
import net.minecraft.util.EnumFacing ;
2018-08-06 01:17:04 +00:00
import net.minecraft.util.math.BlockPos ;
2018-08-06 22:53:35 +00:00
import net.minecraft.util.math.Vec3d ;
import java.util.Objects ;
2018-08-06 01:17:04 +00:00
public class MovementTraverse extends Movement {
2018-08-07 21:14:36 +00:00
/ * *
* Did we have to place a bridge block or was it always there
* /
private boolean wasTheBridgeBlockAlwaysThere = true ;
2018-08-06 01:17:04 +00:00
2018-09-09 16:22:35 +00:00
public MovementTraverse ( BetterBlockPos from , BetterBlockPos to ) {
2018-09-22 15:47:02 +00:00
super ( from , to , new BetterBlockPos [ ] { to . up ( ) , to } , to . down ( ) ) ;
2018-08-06 01:17:04 +00:00
}
2018-08-23 18:14:37 +00:00
@Override
public void reset ( ) {
super . reset ( ) ;
wasTheBridgeBlockAlwaysThere = true ;
}
2018-08-06 01:17:04 +00:00
@Override
2018-08-07 21:36:32 +00:00
protected double calculateCost ( CalculationContext context ) {
2018-09-23 05:00:28 +00:00
return cost ( context , src . x , src . y , src . z , dest . x , dest . z ) ;
}
public static double cost ( CalculationContext context , int x , int y , int z , int destX , int destZ ) {
IBlockState pb0 = BlockStateInterface . get ( destX , y + 1 , destZ ) ;
IBlockState pb1 = BlockStateInterface . get ( destX , y , destZ ) ;
IBlockState destOn = BlockStateInterface . get ( destX , y - 1 , destZ ) ;
Block srcDown = BlockStateInterface . getBlock ( x , y - 1 , z ) ;
if ( MovementHelper . canWalkOn ( destX , y - 1 , destZ , destOn ) ) { //this is a walk, not a bridge
2018-08-17 19:24:40 +00:00
double WC = WALK_ONE_BLOCK_COST ;
2018-10-01 17:05:04 +00:00
boolean water = false ;
2018-08-17 19:24:40 +00:00
if ( BlockStateInterface . isWater ( pb0 . getBlock ( ) ) | | BlockStateInterface . isWater ( pb1 . getBlock ( ) ) ) {
2018-10-01 21:26:55 +00:00
WC = context . waterWalkSpeed ( ) ;
2018-10-01 17:05:04 +00:00
water = true ;
2018-08-17 19:24:40 +00:00
} else {
2018-09-04 23:19:10 +00:00
if ( destOn . getBlock ( ) = = Blocks . SOUL_SAND ) {
2018-08-17 19:24:40 +00:00
WC + = ( WALK_ONE_OVER_SOUL_SAND_COST - WALK_ONE_BLOCK_COST ) / 2 ;
}
2018-09-04 23:19:10 +00:00
if ( srcDown = = Blocks . SOUL_SAND ) {
2018-08-17 19:24:40 +00:00
WC + = ( WALK_ONE_OVER_SOUL_SAND_COST - WALK_ONE_BLOCK_COST ) / 2 ;
}
2018-08-13 14:05:28 +00:00
}
2018-09-23 05:00:28 +00:00
double hardness1 = MovementHelper . getMiningDurationTicks ( context , destX , y + 1 , destZ , pb0 , true ) ;
2018-08-28 19:39:58 +00:00
if ( hardness1 > = COST_INF ) {
return COST_INF ;
}
2018-09-23 05:00:28 +00:00
double hardness2 = MovementHelper . getMiningDurationTicks ( context , destX , y , destZ , pb1 , false ) ;
2018-08-28 19:39:58 +00:00
if ( hardness1 = = 0 & & hardness2 = = 0 ) {
2018-10-01 17:05:04 +00:00
if ( ! water & & context . canSprint ( ) ) {
// If there's nothing in the way, and this isn't water, and we aren't sneak placing
2018-08-25 23:30:12 +00:00
// We can sprint =D
2018-10-01 17:05:04 +00:00
// Don't check for soul sand, since we can sprint on that too
WC * = SPRINT_MULTIPLIER ;
2018-08-13 20:40:50 +00:00
}
2018-08-06 01:17:04 +00:00
return WC ;
}
2018-09-04 23:19:10 +00:00
if ( srcDown = = Blocks . LADDER | | srcDown = = Blocks . VINE ) {
hardness1 * = 5 ;
hardness2 * = 5 ;
}
2018-08-28 19:39:58 +00:00
return WC + hardness1 + hardness2 ;
2018-08-06 01:17:04 +00:00
} else { //this is a bridge, so we need to place a block
2018-09-03 16:15:18 +00:00
if ( srcDown = = Blocks . LADDER | | srcDown = = Blocks . VINE ) {
2018-08-06 01:17:04 +00:00
return COST_INF ;
}
2018-09-23 05:00:28 +00:00
if ( destOn . getBlock ( ) . equals ( Blocks . AIR ) | | MovementHelper . isReplacable ( destX , y - 1 , destZ , destOn ) ) {
2018-08-28 19:53:01 +00:00
boolean throughWater = BlockStateInterface . isWater ( pb0 . getBlock ( ) ) | | BlockStateInterface . isWater ( pb1 . getBlock ( ) ) ;
if ( BlockStateInterface . isWater ( destOn . getBlock ( ) ) & & throughWater ) {
return COST_INF ;
}
2018-10-12 21:34:33 +00:00
if ( ! context . canPlaceThrowawayAt ( destX , y - 1 , destZ ) ) {
2018-08-11 22:03:14 +00:00
return COST_INF ;
}
2018-09-23 05:00:28 +00:00
double hardness1 = MovementHelper . getMiningDurationTicks ( context , destX , y , destZ , pb0 , false ) ;
if ( hardness1 > = COST_INF ) {
return COST_INF ;
}
double hardness2 = MovementHelper . getMiningDurationTicks ( context , destX , y + 1 , destZ , pb1 , true ) ;
2018-10-01 21:26:55 +00:00
double WC = throughWater ? context . waterWalkSpeed ( ) : WALK_ONE_BLOCK_COST ;
2018-08-28 21:56:21 +00:00
for ( int i = 0 ; i < 4 ; i + + ) {
2018-09-23 05:00:28 +00:00
int againstX = destX + HORIZONTALS [ i ] . getXOffset ( ) ;
int againstZ = destZ + HORIZONTALS [ i ] . getZOffset ( ) ;
if ( againstX = = x & & againstZ = = z ) {
2018-08-28 21:56:21 +00:00
continue ;
}
2018-09-23 05:00:28 +00:00
if ( MovementHelper . canPlaceAgainst ( againstX , y - 1 , againstZ ) ) {
return WC + context . placeBlockCost ( ) + hardness1 + hardness2 ;
2018-08-06 01:17:04 +00:00
}
}
2018-09-03 16:15:18 +00:00
if ( srcDown = = Blocks . SOUL_SAND | | ( srcDown instanceof BlockSlab & & ! ( ( BlockSlab ) srcDown ) . isDouble ( ) ) ) {
return COST_INF ; // can't sneak and backplace against soul sand or half slabs =/
2018-08-13 14:07:42 +00:00
}
2018-09-12 02:05:45 +00:00
if ( srcDown = = Blocks . FLOWING_WATER | | srcDown = = Blocks . WATER ) {
return COST_INF ; // this is obviously impossible
}
2018-08-06 01:17:04 +00:00
WC = WC * SNEAK_ONE_BLOCK_COST / WALK_ONE_BLOCK_COST ; //since we are placing, we are sneaking
2018-09-23 05:00:28 +00:00
return WC + context . placeBlockCost ( ) + hardness1 + hardness2 ;
2018-08-06 01:17:04 +00:00
}
return COST_INF ;
2018-08-25 23:30:12 +00:00
// Out.log("Can't walk on " + Baritone.get(positionsToPlace[0]).getBlock());
2018-08-06 01:17:04 +00:00
}
}
@Override
public MovementState updateState ( MovementState state ) {
super . updateState ( state ) ;
2018-10-09 00:57:22 +00:00
if ( state . getStatus ( ) ! = MovementStatus . RUNNING ) {
2018-09-14 23:45:51 +00:00
// if the setting is enabled
if ( ! Baritone . settings ( ) . walkWhileBreaking . get ( ) ) {
return state ;
}
// and if we're prepping (aka mining the block in front)
2018-10-09 00:57:22 +00:00
if ( state . getStatus ( ) ! = MovementStatus . PREPPING ) {
2018-09-14 23:45:51 +00:00
return state ;
}
// and if it's fine to walk into the blocks in front
if ( MovementHelper . avoidWalkingInto ( BlockStateInterface . get ( positionsToBreak [ 0 ] ) . getBlock ( ) ) ) {
return state ;
}
if ( MovementHelper . avoidWalkingInto ( BlockStateInterface . get ( positionsToBreak [ 1 ] ) . getBlock ( ) ) ) {
return state ;
}
// and we aren't already pressed up against the block
double dist = Math . max ( Math . abs ( player ( ) . posX - ( dest . getX ( ) + 0 . 5D ) ) , Math . abs ( player ( ) . posZ - ( dest . getZ ( ) + 0 . 5D ) ) ) ;
if ( dist < 0 . 83 ) {
return state ;
}
// combine the yaw to the center of the destination, and the pitch to the specific block we're trying to break
// it's safe to do this since the two blocks we break (in a traverse) are right on top of each other and so will have the same yaw
2018-10-14 05:55:30 +00:00
float yawToDest = RotationUtils . calcRotationFromVec3d ( playerHead ( ) , VecUtils . calculateBlockCenter ( dest ) ) . getYaw ( ) ;
2018-09-25 14:39:59 +00:00
float pitchToBreak = state . getTarget ( ) . getRotation ( ) . get ( ) . getPitch ( ) ;
2018-09-14 23:45:51 +00:00
state . setTarget ( new MovementState . MovementTarget ( new Rotation ( yawToDest , pitchToBreak ) , true ) ) ;
return state . setInput ( InputOverrideHandler . Input . MOVE_FORWARD , true ) ;
2018-09-08 04:32:25 +00:00
}
2018-09-14 23:45:51 +00:00
//sneak may have been set to true in the PREPPING state while mining an adjacent block
2018-09-04 23:19:10 +00:00
state . setInput ( InputOverrideHandler . Input . SNEAK , false ) ;
2018-08-06 22:53:35 +00:00
Block fd = BlockStateInterface . get ( src . down ( ) ) . getBlock ( ) ;
boolean ladder = fd instanceof BlockLadder | | fd instanceof BlockVine ;
2018-08-15 06:49:08 +00:00
IBlockState pb0 = BlockStateInterface . get ( positionsToBreak [ 0 ] ) ;
IBlockState pb1 = BlockStateInterface . get ( positionsToBreak [ 1 ] ) ;
2018-08-26 07:17:52 +00:00
boolean door = pb0 . getBlock ( ) instanceof BlockDoor | | pb1 . getBlock ( ) instanceof BlockDoor ;
2018-08-15 06:49:08 +00:00
if ( door ) {
boolean isDoorActuallyBlockingUs = false ;
2018-08-26 07:17:52 +00:00
if ( pb0 . getBlock ( ) instanceof BlockDoor & & ! MovementHelper . isDoorPassable ( src , dest ) ) {
2018-08-15 06:49:08 +00:00
isDoorActuallyBlockingUs = true ;
} else if ( pb1 . getBlock ( ) instanceof BlockDoor & & ! MovementHelper . isDoorPassable ( dest , src ) ) {
isDoorActuallyBlockingUs = true ;
}
2018-10-27 21:41:25 +00:00
if ( isDoorActuallyBlockingUs & & ! ( Blocks . IRON_DOOR . equals ( pb0 . getBlock ( ) ) | | Blocks . IRON_DOOR . equals ( pb1 . getBlock ( ) ) ) ) {
return state . setTarget ( new MovementState . MovementTarget ( RotationUtils . calcRotationFromVec3d ( playerHead ( ) , VecUtils . calculateBlockCenter ( positionsToBreak [ 0 ] ) ) , true ) )
. setInput ( InputOverrideHandler . Input . CLICK_RIGHT , true ) ;
2018-08-15 06:49:08 +00:00
}
}
2018-08-25 23:30:12 +00:00
2018-08-26 07:17:52 +00:00
if ( pb0 . getBlock ( ) instanceof BlockFenceGate | | pb1 . getBlock ( ) instanceof BlockFenceGate ) {
BlockPos blocked = null ;
if ( ! MovementHelper . isGatePassable ( positionsToBreak [ 0 ] , src . up ( ) ) ) {
blocked = positionsToBreak [ 0 ] ;
} else if ( ! MovementHelper . isGatePassable ( positionsToBreak [ 1 ] , src ) ) {
blocked = positionsToBreak [ 1 ] ;
}
if ( blocked ! = null ) {
2018-10-14 05:55:30 +00:00
return state . setTarget ( new MovementState . MovementTarget ( RotationUtils . calcRotationFromVec3d ( playerHead ( ) , VecUtils . calculateBlockCenter ( blocked ) ) , true ) )
2018-09-17 17:17:42 +00:00
. setInput ( InputOverrideHandler . Input . CLICK_RIGHT , true ) ;
2018-08-26 07:17:52 +00:00
}
}
2018-08-28 20:41:44 +00:00
boolean isTheBridgeBlockThere = MovementHelper . canWalkOn ( positionToPlace ) | | ladder ;
2018-08-06 22:53:35 +00:00
BlockPos whereAmI = playerFeet ( ) ;
if ( whereAmI . getY ( ) ! = dest . getY ( ) & & ! ladder ) {
2018-09-11 20:45:43 +00:00
logDebug ( " Wrong Y coordinate " ) ;
2018-08-06 22:53:35 +00:00
if ( whereAmI . getY ( ) < dest . getY ( ) ) {
state . setInput ( InputOverrideHandler . Input . JUMP , true ) ;
}
return state ;
}
2018-08-25 23:30:12 +00:00
2018-08-06 22:53:35 +00:00
if ( isTheBridgeBlockThere ) {
if ( playerFeet ( ) . equals ( dest ) ) {
2018-10-09 00:57:22 +00:00
return state . setStatus ( MovementStatus . SUCCESS ) ;
2018-08-06 22:53:35 +00:00
}
2018-08-26 15:12:57 +00:00
if ( wasTheBridgeBlockAlwaysThere & & ! BlockStateInterface . isLiquid ( playerFeet ( ) ) ) {
state . setInput ( InputOverrideHandler . Input . SPRINT , true ) ;
2018-08-06 22:53:35 +00:00
}
2018-08-18 03:46:53 +00:00
Block destDown = BlockStateInterface . get ( dest . down ( ) ) . getBlock ( ) ;
2018-09-04 23:19:10 +00:00
if ( whereAmI . getY ( ) ! = dest . getY ( ) & & ladder & & ( destDown instanceof BlockVine | | destDown instanceof BlockLadder ) ) {
2018-08-18 03:46:53 +00:00
new MovementPillar ( dest . down ( ) , dest ) . updateState ( state ) ; // i'm sorry
return state ;
}
2018-08-08 19:51:04 +00:00
MovementHelper . moveTowards ( state , positionsToBreak [ 0 ] ) ;
2018-08-06 23:58:06 +00:00
return state ;
2018-08-06 22:53:35 +00:00
} else {
wasTheBridgeBlockAlwaysThere = false ;
2018-08-28 21:56:21 +00:00
for ( int i = 0 ; i < 4 ; i + + ) {
BlockPos against1 = dest . offset ( HORIZONTALS [ i ] ) ;
if ( against1 . equals ( src ) ) {
continue ;
}
against1 = against1 . down ( ) ;
2018-08-28 22:01:24 +00:00
if ( MovementHelper . canPlaceAgainst ( against1 ) ) {
2018-08-11 22:03:14 +00:00
if ( ! MovementHelper . throwaway ( true ) ) { // get ready to place a throwaway block
2018-09-11 20:45:43 +00:00
logDebug ( " bb pls get me some blocks. dirt or cobble " ) ;
2018-10-09 00:57:22 +00:00
return state . setStatus ( MovementStatus . UNREACHABLE ) ;
2018-08-06 22:53:35 +00:00
}
2018-09-12 03:50:29 +00:00
if ( ! Baritone . settings ( ) . assumeSafeWalk . get ( ) ) {
state . setInput ( InputOverrideHandler . Input . SNEAK , true ) ;
}
2018-09-03 16:15:18 +00:00
Block standingOn = BlockStateInterface . get ( playerFeet ( ) . down ( ) ) . getBlock ( ) ;
if ( standingOn . equals ( Blocks . SOUL_SAND ) | | standingOn instanceof BlockSlab ) { // see issue #118
2018-09-01 19:47:43 +00:00
double dist = Math . max ( Math . abs ( dest . getX ( ) + 0 . 5 - player ( ) . posX ) , Math . abs ( dest . getZ ( ) + 0 . 5 - player ( ) . posZ ) ) ;
if ( dist < 0 . 85 ) { // 0.5 + 0.3 + epsilon
MovementHelper . moveTowards ( state , dest ) ;
2018-09-17 17:17:42 +00:00
return state . setInput ( InputOverrideHandler . Input . MOVE_FORWARD , false )
. setInput ( InputOverrideHandler . Input . MOVE_BACK , true ) ;
2018-09-01 19:47:43 +00:00
}
}
state . setInput ( InputOverrideHandler . Input . MOVE_BACK , false ) ;
2018-08-06 22:53:35 +00:00
double faceX = ( dest . getX ( ) + against1 . getX ( ) + 1 . 0D ) * 0 . 5D ;
double faceY = ( dest . getY ( ) + against1 . getY ( ) ) * 0 . 5D ;
double faceZ = ( dest . getZ ( ) + against1 . getZ ( ) + 1 . 0D ) * 0 . 5D ;
2018-10-14 05:55:30 +00:00
state . setTarget ( new MovementState . MovementTarget ( RotationUtils . calcRotationFromVec3d ( playerHead ( ) , new Vec3d ( faceX , faceY , faceZ ) , playerRotations ( ) ) , true ) ) ;
2018-08-06 22:53:35 +00:00
EnumFacing side = Minecraft . getMinecraft ( ) . objectMouseOver . sideHit ;
2018-10-27 21:41:25 +00:00
if ( Objects . equals ( RayTraceUtils . getSelectedBlock ( ) . orElse ( null ) , against1 ) & & ( Minecraft . getMinecraft ( ) . player . isSneaking ( ) | | Baritone . settings ( ) . assumeSafeWalk . get ( ) ) & & RayTraceUtils . getSelectedBlock ( ) . get ( ) . offset ( side ) . equals ( positionToPlace ) ) {
return state . setInput ( InputOverrideHandler . Input . CLICK_RIGHT , true ) ;
2018-08-06 22:53:35 +00:00
}
2018-10-15 22:39:01 +00:00
//System.out.println("Trying to look at " + against1 + ", actually looking at" + RayTraceUtils.getSelectedBlock());
2018-08-25 23:30:12 +00:00
return state . setInput ( InputOverrideHandler . Input . CLICK_LEFT , true ) ;
2018-08-06 01:52:55 +00:00
}
2018-08-06 22:53:35 +00:00
}
2018-09-12 03:50:29 +00:00
if ( ! Baritone . settings ( ) . assumeSafeWalk . get ( ) ) {
state . setInput ( InputOverrideHandler . Input . SNEAK , true ) ;
}
2018-08-06 22:53:35 +00:00
if ( whereAmI . equals ( dest ) ) {
2018-08-25 23:30:12 +00:00
// If we are in the block that we are trying to get to, we are sneaking over air and we need to place a block beneath us against the one we just walked off of
2018-08-07 21:14:36 +00:00
// Out.log(from + " " + to + " " + faceX + "," + faceY + "," + faceZ + " " + whereAmI);
2018-08-11 22:03:14 +00:00
if ( ! MovementHelper . throwaway ( true ) ) { // get ready to place a throwaway block
2018-09-11 20:45:43 +00:00
logDebug ( " bb pls get me some blocks. dirt or cobble " ) ;
2018-10-09 00:57:22 +00:00
return state . setStatus ( MovementStatus . UNREACHABLE ) ;
2018-08-06 22:53:35 +00:00
}
double faceX = ( dest . getX ( ) + src . getX ( ) + 1 . 0D ) * 0 . 5D ;
double faceY = ( dest . getY ( ) + src . getY ( ) - 1 . 0D ) * 0 . 5D ;
double faceZ = ( dest . getZ ( ) + src . getZ ( ) + 1 . 0D ) * 0 . 5D ;
2018-08-07 21:14:36 +00:00
// faceX, faceY, faceZ is the middle of the face between from and to
BlockPos goalLook = src . down ( ) ; // this is the block we were just standing on, and the one we want to place against
2018-08-06 01:52:55 +00:00
2018-10-14 05:55:30 +00:00
Rotation backToFace = RotationUtils . calcRotationFromVec3d ( playerHead ( ) , new Vec3d ( faceX , faceY , faceZ ) , playerRotations ( ) ) ;
2018-10-05 20:49:47 +00:00
float pitch = backToFace . getPitch ( ) ;
double dist = Math . max ( Math . abs ( player ( ) . posX - faceX ) , Math . abs ( player ( ) . posZ - faceZ ) ) ;
if ( dist < 0 . 29 ) {
2018-10-14 05:55:30 +00:00
float yaw = RotationUtils . calcRotationFromVec3d ( VecUtils . getBlockPosCenter ( dest ) , playerHead ( ) , playerRotations ( ) ) . getYaw ( ) ;
2018-10-05 20:49:47 +00:00
state . setTarget ( new MovementState . MovementTarget ( new Rotation ( yaw , pitch ) , true ) ) ;
state . setInput ( InputOverrideHandler . Input . MOVE_BACK , true ) ;
} else {
state . setTarget ( new MovementState . MovementTarget ( backToFace , true ) ) ;
}
2018-08-06 22:53:35 +00:00
state . setInput ( InputOverrideHandler . Input . SNEAK , true ) ;
2018-10-14 05:55:30 +00:00
if ( Objects . equals ( RayTraceUtils . getSelectedBlock ( ) . orElse ( null ) , goalLook ) ) {
2018-09-17 17:17:42 +00:00
return state . setInput ( InputOverrideHandler . Input . CLICK_RIGHT , true ) ; // wait to right click until we are able to place
2018-08-06 22:53:35 +00:00
}
2018-08-07 21:14:36 +00:00
// Out.log("Trying to look at " + goalLook + ", actually looking at" + Baritone.whatAreYouLookingAt());
2018-09-02 20:34:15 +00:00
return state . setInput ( InputOverrideHandler . Input . CLICK_LEFT , true ) ;
2018-08-06 22:53:35 +00:00
} else {
2018-08-08 19:51:04 +00:00
MovementHelper . moveTowards ( state , positionsToBreak [ 0 ] ) ;
2018-08-06 23:58:06 +00:00
return state ;
2018-08-07 21:14:36 +00:00
// TODO MovementManager.moveTowardsBlock(to); // move towards not look at because if we are bridging for a couple blocks in a row, it is faster if we dont spin around and walk forwards then spin around and place backwards for every block
2018-08-06 22:53:35 +00:00
}
2018-08-06 01:17:04 +00:00
}
}
2018-09-04 23:19:10 +00:00
2018-10-07 01:39:30 +00:00
@Override
public boolean safeToCancel ( MovementState state ) {
// if we're in the process of breaking blocks before walking forwards
// or if this isn't a sneak place (the block is already there)
// then it's safe to cancel this
2018-10-09 00:57:22 +00:00
return state . getStatus ( ) ! = MovementStatus . RUNNING | | MovementHelper . canWalkOn ( dest . down ( ) ) ;
2018-10-07 01:39:30 +00:00
}
2018-09-04 23:19:10 +00:00
@Override
protected boolean prepared ( MovementState state ) {
if ( playerFeet ( ) . equals ( src ) | | playerFeet ( ) . equals ( src . down ( ) ) ) {
Block block = BlockStateInterface . getBlock ( src . down ( ) ) ;
if ( block = = Blocks . LADDER | | block = = Blocks . VINE ) {
state . setInput ( InputOverrideHandler . Input . SNEAK , true ) ;
}
}
return super . prepared ( state ) ;
}
2018-08-06 01:17:04 +00:00
}