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 ;
2018-08-02 17:25:46 +00:00
2018-08-22 20:15:56 +00:00
import baritone.Baritone ;
2018-09-12 22:58:33 +00:00
import baritone.behavior.LookBehaviorUtils ;
2018-08-22 20:15:56 +00:00
import baritone.pathing.movement.MovementState.MovementTarget ;
import baritone.pathing.movement.movements.MovementDescend ;
import baritone.pathing.movement.movements.MovementFall ;
import baritone.utils.* ;
2018-09-09 16:22:35 +00:00
import baritone.utils.pathing.BetterBlockPos ;
2018-08-02 17:25:46 +00:00
import net.minecraft.block.* ;
2018-08-26 07:17:52 +00:00
import net.minecraft.block.properties.PropertyBool ;
2018-08-02 17:25:46 +00:00
import net.minecraft.block.state.IBlockState ;
import net.minecraft.client.Minecraft ;
2018-08-06 22:53:35 +00:00
import net.minecraft.client.entity.EntityPlayerSP ;
2018-08-04 02:14:50 +00:00
import net.minecraft.entity.Entity ;
2018-08-02 17:49:31 +00:00
import net.minecraft.init.Blocks ;
2018-08-06 22:53:35 +00:00
import net.minecraft.item.ItemStack ;
2018-08-25 22:24:00 +00:00
import net.minecraft.util.EnumFacing ;
2018-08-06 22:53:35 +00:00
import net.minecraft.util.NonNullList ;
2018-08-02 17:25:46 +00:00
import net.minecraft.util.math.BlockPos ;
2018-08-04 02:14:50 +00:00
import net.minecraft.util.math.RayTraceResult ;
2018-08-25 15:44:33 +00:00
import net.minecraft.world.chunk.EmptyChunk ;
2018-08-02 17:25:46 +00:00
2018-08-06 07:21:47 +00:00
import java.util.Optional ;
2018-08-02 17:25:46 +00:00
/ * *
* Static helpers for cost calculation
*
* @author leijurv
* /
2018-08-04 02:14:50 +00:00
public interface MovementHelper extends ActionCosts , Helper {
2018-08-03 07:51:10 +00:00
2018-09-23 02:13:59 +00:00
static boolean avoidBreaking ( BetterBlockPos pos , IBlockState state ) {
return avoidBreaking ( pos . x , pos . y , pos . z , state ) ;
}
static boolean avoidBreaking ( int x , int y , int z , IBlockState state ) {
2018-08-17 19:24:40 +00:00
Block b = state . getBlock ( ) ;
2018-09-09 15:57:20 +00:00
return b = = Blocks . ICE // ice becomes water, and water can mess up the path
2018-08-18 04:02:41 +00:00
| | b instanceof BlockSilverfish // obvious reasons
2018-09-09 15:57:20 +00:00
// call BlockStateInterface.get directly with x,y,z. no need to make 5 new BlockPos for no reason
2018-09-09 20:19:48 +00:00
| | BlockStateInterface . get ( x , y + 1 , z ) . getBlock ( ) instanceof BlockLiquid //don't break anything touching liquid on any side
| | BlockStateInterface . get ( x + 1 , y , z ) . getBlock ( ) instanceof BlockLiquid
| | BlockStateInterface . get ( x - 1 , y , z ) . getBlock ( ) instanceof BlockLiquid
| | BlockStateInterface . get ( x , y , z + 1 ) . getBlock ( ) instanceof BlockLiquid
| | BlockStateInterface . get ( x , y , z - 1 ) . getBlock ( ) instanceof BlockLiquid ;
2018-08-02 17:25:46 +00:00
}
/ * *
* Can I walk through this block ? e . g . air , saplings , torches , etc
*
* @param pos
* @return
* /
2018-09-22 16:17:28 +00:00
static boolean canWalkThrough ( BetterBlockPos pos ) {
return canWalkThrough ( pos . x , pos . y , pos . z , BlockStateInterface . get ( pos ) ) ;
2018-08-07 14:39:55 +00:00
}
2018-09-22 16:17:28 +00:00
static boolean canWalkThrough ( BetterBlockPos pos , IBlockState state ) {
return canWalkThrough ( pos . x , pos . y , pos . z , state ) ;
}
2018-09-22 16:28:59 +00:00
static boolean canWalkThrough ( int x , int y , int z ) {
return canWalkThrough ( x , y , z , BlockStateInterface . get ( x , y , z ) ) ;
}
2018-09-22 16:17:28 +00:00
static boolean canWalkThrough ( int x , int y , int z , IBlockState state ) {
2018-08-02 17:25:46 +00:00
Block block = state . getBlock ( ) ;
2018-09-22 18:23:26 +00:00
if ( block = = Blocks . AIR ) { // early return for most common case
2018-09-06 14:48:27 +00:00
return true ;
}
2018-09-09 15:11:33 +00:00
if ( block = = Blocks . FIRE | | block = = Blocks . TRIPWIRE | | block = = Blocks . WEB | | block = = Blocks . END_PORTAL ) {
2018-08-02 17:25:46 +00:00
return false ;
}
2018-08-26 07:17:52 +00:00
if ( block instanceof BlockDoor | | block instanceof BlockFenceGate ) {
2018-09-17 22:46:23 +00:00
// 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 ;
2018-08-25 15:44:33 +00:00
}
2018-09-22 16:17:28 +00:00
boolean snow = block instanceof BlockSnow ;
boolean trapdoor = block instanceof BlockTrapDoor ;
if ( snow | | trapdoor ) {
// we've already checked doors and fence gates
// so the only remaining dynamic isPassables are snow and trapdoor
2018-08-25 15:44:33 +00:00
// if they're cached as a top block, we don't know their metadata
// default to true (mostly because it would otherwise make long distance pathing through snowy biomes impossible)
2018-09-22 16:17:28 +00:00
if ( mc . world . getChunk ( x > > 4 , z > > 4 ) instanceof EmptyChunk ) {
2018-08-25 15:44:33 +00:00
return true ;
}
2018-09-22 16:17:28 +00:00
if ( snow ) {
return state . getValue ( BlockSnow . LAYERS ) < 5 ; // see BlockSnow.isPassable
}
if ( trapdoor ) {
return ! state . getValue ( BlockTrapDoor . OPEN ) ; // see BlockTrapDoor.isPassable
}
throw new IllegalStateException ( ) ;
2018-08-25 15:44:33 +00:00
}
2018-08-28 18:57:31 +00:00
if ( BlockStateInterface . isFlowing ( state ) ) {
2018-08-02 17:55:26 +00:00
return false ; // Don't walk through flowing liquids
2018-08-02 17:25:46 +00:00
}
2018-08-28 18:57:31 +00:00
if ( block instanceof BlockLiquid ) {
2018-08-28 19:30:08 +00:00
if ( Baritone . settings ( ) . assumeWalkOnWater . get ( ) ) {
return false ;
}
2018-09-22 16:17:28 +00:00
IBlockState up = BlockStateInterface . get ( x , y + 1 , z ) ;
2018-08-28 18:57:31 +00:00
if ( up . getBlock ( ) instanceof BlockLiquid | | up . getBlock ( ) instanceof BlockLilyPad ) {
return false ;
}
2018-09-22 15:47:02 +00:00
return block = = Blocks . WATER | | block = = Blocks . FLOWING_WATER ;
2018-08-28 18:57:31 +00:00
}
2018-09-22 16:17:28 +00:00
// every block that overrides isPassable with anything more complicated than a "return true;" or "return false;"
// has already been accounted for above
// therefore it's safe to not construct a blockpos from our x, y, z ints and instead just pass null
return block . isPassable ( null , null ) ;
2018-08-02 17:25:46 +00:00
}
2018-09-06 14:48:27 +00:00
/ * *
* 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 )
*
* @return
* /
static boolean fullyPassable ( BlockPos pos ) {
2018-09-22 16:17:28 +00:00
return fullyPassable ( BlockStateInterface . get ( pos ) ) ;
2018-09-06 14:48:27 +00:00
}
2018-09-22 16:17:28 +00:00
static boolean fullyPassable ( IBlockState state ) {
2018-09-06 14:48:27 +00:00
Block block = state . getBlock ( ) ;
2018-09-22 18:23:26 +00:00
if ( block = = Blocks . AIR ) { // early return for most common case
2018-09-06 14:48:27 +00:00
return true ;
}
2018-09-11 13:37:08 +00:00
// exceptions - blocks that are isPassable true, but we can't actually jump through
2018-09-06 14:48:27 +00:00
if ( block = = Blocks . FIRE
| | block = = Blocks . TRIPWIRE
| | block = = Blocks . WEB
| | block = = Blocks . VINE
| | block = = Blocks . LADDER
| | block instanceof BlockDoor
| | block instanceof BlockFenceGate
| | block instanceof BlockSnow
| | block instanceof BlockLiquid
| | block instanceof BlockTrapDoor
| | block instanceof BlockEndPortal ) {
return false ;
}
2018-09-22 16:17:28 +00:00
// door, fence gate, liquid, trapdoor have been accounted for, nothing else uses the world or pos parameters
return block . isPassable ( null , null ) ;
2018-09-06 14:48:27 +00:00
}
2018-08-25 15:44:33 +00:00
static boolean isReplacable ( BlockPos pos , IBlockState state ) {
2018-09-23 02:46:10 +00:00
return isReplacable ( pos . getX ( ) , pos . getY ( ) , pos . getZ ( ) , state ) ;
}
static boolean isReplacable ( int x , int y , int z , IBlockState state ) {
2018-08-25 15:44:33 +00:00
// for MovementTraverse and MovementAscend
// block double plant defaults to true when the block doesn't match, so don't need to check that case
// all other overrides just return true or false
// the only case to deal with is snow
/ *
* public boolean isReplaceable ( IBlockAccess worldIn , BlockPos pos )
* {
* return ( ( Integer ) worldIn . getBlockState ( pos ) . getValue ( LAYERS ) ) . intValue ( ) = = 1 ;
* }
* /
2018-09-23 02:46:10 +00:00
Block block = state . getBlock ( ) ;
if ( block instanceof BlockSnow ) {
2018-08-25 15:44:33 +00:00
// as before, default to true (mostly because it would otherwise make long distance pathing through snowy biomes impossible)
2018-09-23 02:46:10 +00:00
if ( mc . world . getChunk ( x > > 4 , z > > 4 ) instanceof EmptyChunk ) {
2018-08-25 15:44:33 +00:00
return true ;
}
2018-09-23 02:46:10 +00:00
return state . getValue ( BlockSnow . LAYERS ) = = 1 ;
}
if ( block instanceof BlockDoublePlant ) {
BlockDoublePlant . EnumPlantType kek = state . getValue ( BlockDoublePlant . VARIANT ) ;
return kek = = BlockDoublePlant . EnumPlantType . FERN | | kek = = BlockDoublePlant . EnumPlantType . GRASS ;
2018-08-25 15:44:33 +00:00
}
2018-09-23 02:46:10 +00:00
return state . getBlock ( ) . isReplaceable ( null , null ) ;
2018-08-25 15:44:33 +00:00
}
2018-08-15 06:49:08 +00:00
static boolean isDoorPassable ( BlockPos doorPos , BlockPos playerPos ) {
2018-09-08 04:32:25 +00:00
if ( playerPos . equals ( doorPos ) ) {
2018-08-15 06:49:08 +00:00
return false ;
2018-09-08 04:32:25 +00:00
}
2018-08-25 22:24:00 +00:00
IBlockState state = BlockStateInterface . get ( doorPos ) ;
2018-09-08 04:32:25 +00:00
if ( ! ( state . getBlock ( ) instanceof BlockDoor ) ) {
2018-08-25 22:24:00 +00:00
return true ;
2018-09-08 04:32:25 +00:00
}
2018-08-25 22:24:00 +00:00
2018-08-26 07:17:52 +00:00
return isHorizontalBlockPassable ( doorPos , state , playerPos , BlockDoor . OPEN ) ;
}
static boolean isGatePassable ( BlockPos gatePos , BlockPos playerPos ) {
2018-09-08 04:32:25 +00:00
if ( playerPos . equals ( gatePos ) ) {
2018-08-26 07:17:52 +00:00
return false ;
2018-09-08 04:32:25 +00:00
}
2018-08-26 07:17:52 +00:00
IBlockState state = BlockStateInterface . get ( gatePos ) ;
2018-09-08 04:32:25 +00:00
if ( ! ( state . getBlock ( ) instanceof BlockFenceGate ) ) {
2018-08-26 07:17:52 +00:00
return true ;
2018-09-08 04:32:25 +00:00
}
2018-08-26 07:17:52 +00:00
return isHorizontalBlockPassable ( gatePos , state , playerPos , BlockFenceGate . OPEN ) ;
}
static boolean isHorizontalBlockPassable ( BlockPos blockPos , IBlockState blockState , BlockPos playerPos , PropertyBool propertyOpen ) {
2018-09-08 04:32:25 +00:00
if ( playerPos . equals ( blockPos ) ) {
2018-08-26 07:17:52 +00:00
return false ;
2018-09-08 04:32:25 +00:00
}
2018-08-26 07:17:52 +00:00
EnumFacing . Axis facing = blockState . getValue ( BlockHorizontal . FACING ) . getAxis ( ) ;
boolean open = blockState . getValue ( propertyOpen ) ;
2018-08-25 22:24:00 +00:00
EnumFacing . Axis playerFacing ;
2018-08-26 07:17:52 +00:00
if ( playerPos . north ( ) . equals ( blockPos ) | | playerPos . south ( ) . equals ( blockPos ) ) {
2018-08-25 22:24:00 +00:00
playerFacing = EnumFacing . Axis . Z ;
2018-08-26 07:17:52 +00:00
} else if ( playerPos . east ( ) . equals ( blockPos ) | | playerPos . west ( ) . equals ( blockPos ) ) {
2018-08-25 22:24:00 +00:00
playerFacing = EnumFacing . Axis . X ;
2018-08-15 06:49:08 +00:00
} else {
return true ;
}
2018-08-26 15:12:57 +00:00
return facing = = playerFacing = = open ;
2018-08-15 06:49:08 +00:00
}
2018-08-03 20:31:33 +00:00
static boolean avoidWalkingInto ( Block block ) {
2018-09-12 01:33:03 +00:00
return block instanceof BlockLiquid
| | block instanceof BlockDynamicLiquid
2018-09-09 15:11:33 +00:00
| | block = = Blocks . MAGMA
| | block = = Blocks . CACTUS
| | block = = Blocks . FIRE
| | block = = Blocks . END_PORTAL
| | block = = Blocks . WEB ;
2018-08-02 17:25:46 +00:00
}
/ * *
* Can I walk on this block without anything weird happening like me falling
* through ? Includes water because we know that we automatically jump on
2018-08-17 19:24:40 +00:00
* water
2018-08-02 17:25:46 +00:00
*
* @return
* /
2018-09-22 16:28:59 +00:00
static boolean canWalkOn ( int x , int y , int z , IBlockState state ) {
2018-08-02 17:25:46 +00:00
Block block = state . getBlock ( ) ;
2018-09-09 15:11:33 +00:00
if ( block = = Blocks . AIR | | block = = Blocks . MAGMA ) {
2018-09-22 18:23:26 +00:00
// early return for most common case (air)
// plus magma, which is a normal cube but it hurts you
2018-09-03 16:15:18 +00:00
return false ;
}
2018-09-09 15:11:33 +00:00
if ( state . isBlockNormalCube ( ) ) {
if ( BlockStateInterface . isLava ( block ) | | BlockStateInterface . isWater ( block ) ) {
throw new IllegalStateException ( ) ;
}
2018-08-17 23:46:02 +00:00
return true ;
}
2018-09-09 15:11:33 +00:00
if ( block = = Blocks . LADDER | | ( block = = Blocks . VINE & & Baritone . settings ( ) . allowVines . get ( ) ) ) { // TODO reconsider this
2018-09-01 20:20:27 +00:00
return true ;
}
2018-09-09 15:11:33 +00:00
if ( block = = Blocks . FARMLAND | | block = = Blocks . GRASS_PATH ) {
2018-09-03 16:15:18 +00:00
return true ;
2018-08-06 02:09:29 +00:00
}
2018-09-09 15:11:33 +00:00
if ( block = = Blocks . ENDER_CHEST | | block = = Blocks . CHEST ) {
2018-09-03 18:27:59 +00:00
return true ;
}
2018-08-06 21:32:54 +00:00
if ( BlockStateInterface . isWater ( block ) ) {
2018-09-22 15:47:02 +00:00
// since this is called literally millions of times per second, the benefit of not allocating millions of useless "pos.up()"
// BlockPos s that we'd just garbage collect immediately is actually noticeable. I don't even think its a decrease in readability
2018-09-22 16:28:59 +00:00
Block up = BlockStateInterface . get ( x , y + 1 , z ) . getBlock ( ) ;
2018-09-22 15:47:02 +00:00
if ( up = = Blocks . WATERLILY ) {
2018-08-28 19:30:08 +00:00
return true ;
}
2018-09-15 15:00:24 +00:00
if ( BlockStateInterface . isFlowing ( state ) | | block = = Blocks . FLOWING_WATER ) {
2018-09-04 20:57:56 +00:00
// the only scenario in which we can walk on flowing water is if it's under still water with jesus off
return BlockStateInterface . isWater ( up ) & & ! Baritone . settings ( ) . assumeWalkOnWater . get ( ) ;
}
2018-08-28 19:53:01 +00:00
// if assumeWalkOnWater is on, we can only walk on water if there isn't water above it
// if assumeWalkOnWater is off, we can only walk on water if there is water above it
return BlockStateInterface . isWater ( up ) ^ Baritone . settings ( ) . assumeWalkOnWater . get ( ) ;
2018-08-02 17:25:46 +00:00
}
2018-09-09 15:11:33 +00:00
if ( block instanceof BlockGlass | | block instanceof BlockStainedGlass ) {
return true ;
}
if ( block instanceof BlockSlab ) {
if ( ! Baritone . settings ( ) . allowWalkOnBottomSlab . get ( ) ) {
if ( ( ( BlockSlab ) block ) . isDouble ( ) ) {
return true ;
}
return state . getValue ( BlockSlab . HALF ) ! = BlockSlab . EnumBlockHalf . BOTTOM ;
}
return true ;
}
if ( block instanceof BlockStairs ) {
return true ;
2018-08-11 22:03:14 +00:00
}
2018-09-09 15:11:33 +00:00
return false ;
2018-08-02 17:25:46 +00:00
}
2018-08-02 17:49:31 +00:00
2018-09-22 16:28:59 +00:00
static boolean canWalkOn ( BetterBlockPos pos , IBlockState state ) {
return canWalkOn ( pos . x , pos . y , pos . z , state ) ;
}
2018-09-22 15:47:02 +00:00
static boolean canWalkOn ( BetterBlockPos pos ) {
2018-09-22 16:28:59 +00:00
return canWalkOn ( pos . x , pos . y , pos . z , BlockStateInterface . get ( pos ) ) ;
}
static boolean canWalkOn ( int x , int y , int z ) {
return canWalkOn ( x , y , z , BlockStateInterface . get ( x , y , z ) ) ;
2018-08-07 02:48:09 +00:00
}
2018-09-23 02:46:10 +00:00
static boolean canPlaceAgainst ( int x , int y , int z ) {
return canPlaceAgainst ( BlockStateInterface . get ( x , y , z ) ) ;
}
2018-08-28 22:01:24 +00:00
static boolean canPlaceAgainst ( BlockPos pos ) {
2018-09-23 02:46:10 +00:00
return canPlaceAgainst ( BlockStateInterface . get ( pos ) ) ;
}
static boolean canPlaceAgainst ( IBlockState state ) {
2018-08-28 22:01:24 +00:00
// TODO isBlockNormalCube isn't the best check for whether or not we can place a block against it. e.g. glass isn't normalCube but we can place against it
return state . isBlockNormalCube ( ) ;
}
2018-09-22 16:17:28 +00:00
static double getMiningDurationTicks ( CalculationContext context , BetterBlockPos position , boolean includeFalling ) {
2018-08-07 01:18:16 +00:00
IBlockState state = BlockStateInterface . get ( position ) ;
2018-09-23 02:13:59 +00:00
return getMiningDurationTicks ( context , position . x , position . y , position . z , state , includeFalling ) ;
2018-08-17 19:24:40 +00:00
}
2018-09-22 16:17:28 +00:00
static double getMiningDurationTicks ( CalculationContext context , BetterBlockPos position , IBlockState state , boolean includeFalling ) {
2018-09-23 02:13:59 +00:00
return getMiningDurationTicks ( context , position . x , position . y , position . z , state , includeFalling ) ;
}
2018-09-23 02:46:10 +00:00
static double getMiningDurationTicks ( CalculationContext context , int x , int y , int z , boolean includeFalling ) {
return getMiningDurationTicks ( context , x , y , z , BlockStateInterface . get ( x , y , z ) , includeFalling ) ;
}
2018-09-23 02:13:59 +00:00
static double getMiningDurationTicks ( CalculationContext context , int x , int y , int z , IBlockState state , boolean includeFalling ) {
2018-08-07 01:18:16 +00:00
Block block = state . getBlock ( ) ;
2018-09-23 02:13:59 +00:00
if ( ! canWalkThrough ( x , y , z , state ) ) {
2018-08-17 20:17:16 +00:00
if ( ! context . allowBreak ( ) ) {
2018-08-02 17:49:31 +00:00
return COST_INF ;
}
2018-09-23 02:13:59 +00:00
if ( avoidBreaking ( x , y , z , state ) ) {
2018-08-14 00:15:59 +00:00
return COST_INF ;
}
2018-09-23 18:37:39 +00:00
if ( block instanceof BlockLiquid ) {
return COST_INF ;
}
2018-08-17 20:17:16 +00:00
double m = Blocks . CRAFTING_TABLE . equals ( block ) ? 10 : 1 ; // TODO see if this is still necessary. it's from MineBot when we wanted to penalize breaking its crafting table
2018-09-08 00:00:36 +00:00
double strVsBlock = context . getToolSet ( ) . getStrVsBlock ( state ) ;
2018-09-22 16:34:42 +00:00
if ( strVsBlock < = 0 ) {
2018-09-08 00:00:36 +00:00
return COST_INF ;
2018-09-08 04:32:25 +00:00
}
2018-09-08 00:00:36 +00:00
double result = m / strVsBlock ;
2018-08-26 20:48:08 +00:00
if ( includeFalling ) {
2018-09-23 02:13:59 +00:00
IBlockState above = BlockStateInterface . get ( x , y + 1 , z ) ;
2018-08-26 20:48:08 +00:00
if ( above . getBlock ( ) instanceof BlockFalling ) {
2018-09-23 02:13:59 +00:00
result + = getMiningDurationTicks ( context , x , y + 1 , z , above , true ) ;
2018-08-26 20:48:08 +00:00
}
}
return result ;
2018-08-02 17:49:31 +00:00
}
2018-08-26 20:48:08 +00:00
return 0 ; // we won't actually mine it, so don't check fallings above
2018-08-02 17:49:31 +00:00
}
2018-08-04 02:14:50 +00:00
2018-09-03 16:50:26 +00:00
static boolean isBottomSlab ( IBlockState state ) {
return state . getBlock ( ) instanceof BlockSlab
& & ! ( ( BlockSlab ) state . getBlock ( ) ) . isDouble ( )
& & state . getValue ( BlockSlab . HALF ) = = BlockSlab . EnumBlockHalf . BOTTOM ;
}
static boolean isBottomSlab ( BlockPos pos ) {
return isBottomSlab ( BlockStateInterface . get ( pos ) ) ;
}
2018-08-04 02:14:50 +00:00
/ * *
* The entity the player is currently looking at
*
2018-08-06 07:21:47 +00:00
* @return the entity object
2018-08-04 02:14:50 +00:00
* /
2018-08-06 07:21:47 +00:00
static Optional < Entity > whatEntityAmILookingAt ( ) {
2018-08-04 02:14:50 +00:00
if ( mc . objectMouseOver ! = null & & mc . objectMouseOver . typeOfHit = = RayTraceResult . Type . ENTITY ) {
2018-08-06 07:21:47 +00:00
return Optional . of ( mc . objectMouseOver . entityHit ) ;
2018-08-04 02:14:50 +00:00
}
2018-08-06 07:21:47 +00:00
return Optional . empty ( ) ;
2018-08-04 02:14:50 +00:00
}
/ * *
* AutoTool
* /
static void switchToBestTool ( ) {
2018-08-06 21:32:54 +00:00
LookBehaviorUtils . getSelectedBlock ( ) . ifPresent ( pos - > {
2018-08-06 07:21:47 +00:00
IBlockState state = BlockStateInterface . get ( pos ) ;
if ( state . getBlock ( ) . equals ( Blocks . AIR ) ) {
return ;
}
switchToBestToolFor ( state ) ;
} ) ;
2018-08-04 02:14:50 +00:00
}
/ * *
* AutoTool for a specific block
*
* @param b the blockstate to mine
* /
static void switchToBestToolFor ( IBlockState b ) {
switchToBestToolFor ( b , new ToolSet ( ) ) ;
}
/ * *
* AutoTool for a specific block with precomputed ToolSet data
*
* @param b the blockstate to mine
* @param ts previously calculated ToolSet
* /
static void switchToBestToolFor ( IBlockState b , ToolSet ts ) {
2018-08-06 07:21:47 +00:00
mc . player . inventory . currentItem = ts . getBestSlot ( b ) ;
2018-08-04 02:14:50 +00:00
}
2018-08-06 22:53:35 +00:00
2018-08-11 22:03:14 +00:00
static boolean throwaway ( boolean select ) {
2018-08-06 22:53:35 +00:00
EntityPlayerSP p = Minecraft . getMinecraft ( ) . player ;
NonNullList < ItemStack > inv = p . inventory . mainInventory ;
for ( byte i = 0 ; i < 9 ; i + + ) {
ItemStack item = inv . get ( i ) ;
2018-08-17 20:17:16 +00:00
// this usage of settings() is okay because it's only called once during pathing
// (while creating the CalculationContext at the very beginning)
// and then it's called during execution
// since this function is never called during cost calculation, we don't need to migrate
// acceptableThrowawayItems to the CalculationContext
if ( Baritone . settings ( ) . acceptableThrowawayItems . get ( ) . contains ( item . getItem ( ) ) ) {
2018-08-11 22:03:14 +00:00
if ( select ) {
p . inventory . currentItem = i ;
}
2018-08-06 22:53:35 +00:00
return true ;
}
}
return false ;
}
2018-08-14 18:25:30 +00:00
static void moveTowards ( MovementState state , BlockPos pos ) {
2018-08-21 22:52:09 +00:00
state . setTarget ( new MovementTarget (
new Rotation ( Utils . calcRotationFromVec3d ( mc . player . getPositionEyes ( 1 . 0F ) ,
Utils . getBlockPosCenter ( pos ) ,
new Rotation ( mc . player . rotationYaw , mc . player . rotationPitch ) ) . getFirst ( ) , mc . player . rotationPitch ) ,
false
) ) . setInput ( InputOverrideHandler . Input . MOVE_FORWARD , true ) ;
2018-08-08 19:51:04 +00:00
}
2018-09-09 16:22:35 +00:00
static Movement generateMovementFallOrDescend ( BetterBlockPos pos , BetterBlockPos dest , CalculationContext calcContext ) {
2018-09-23 05:00:28 +00:00
2018-08-13 15:28:43 +00:00
2018-09-22 16:28:59 +00:00
int x = dest . x ;
int y = dest . y ;
int z = dest . z ;
if ( ! canWalkThrough ( x , y - 2 , z ) ) {
2018-08-26 15:31:03 +00:00
//if B in the diagram aren't air
//have to do a descend, because fall is impossible
//this doesn't guarantee descend is possible, it just guarantees fall is impossible
return new MovementDescend ( pos , dest . down ( ) ) ; // standard move out by 1 and descend by 1
2018-09-09 17:27:47 +00:00
// we can't cost shortcut descend because !canWalkThrough doesn't mean canWalkOn
2018-08-07 13:16:38 +00:00
}
2018-08-26 15:31:03 +00:00
2018-08-07 13:16:38 +00:00
// we're clear for a fall 2
// let's see how far we can fall
for ( int fallHeight = 3 ; true ; fallHeight + + ) {
2018-09-22 16:28:59 +00:00
int newY = y - fallHeight ;
if ( newY < 0 ) {
2018-08-20 14:11:15 +00:00
// when pathing in the end, where you could plausibly fall into the void
// this check prevents it from getting the block at y=-1 and crashing
2018-08-07 13:16:38 +00:00
break ;
}
2018-09-22 16:28:59 +00:00
IBlockState ontoBlock = BlockStateInterface . get ( x , newY , z ) ;
2018-09-18 03:25:52 +00:00
if ( ontoBlock . getBlock ( ) = = Blocks . WATER ) {
2018-09-22 16:28:59 +00:00
return new MovementFall ( pos , new BetterBlockPos ( x , newY , z ) ) ;
2018-08-07 13:16:38 +00:00
}
2018-09-22 16:28:59 +00:00
if ( canWalkThrough ( x , newY , z , ontoBlock ) ) {
2018-08-07 14:39:55 +00:00
continue ;
}
2018-09-22 16:28:59 +00:00
if ( ! canWalkOn ( x , newY , z , ontoBlock ) ) {
2018-09-17 00:49:19 +00:00
break ;
}
if ( ( calcContext . hasWaterBucket ( ) & & fallHeight < = calcContext . maxFallHeightBucket ( ) + 1 ) | | fallHeight < = calcContext . maxFallHeightNoWater ( ) + 1 ) {
// fallHeight = 4 means onto.up() is 3 blocks down, which is the max
2018-09-22 16:28:59 +00:00
return new MovementFall ( pos , new BetterBlockPos ( x , newY + 1 , z ) ) ;
2018-09-17 00:49:19 +00:00
} else {
return null ;
2018-08-07 13:16:38 +00:00
}
}
return null ;
}
2018-08-02 17:25:46 +00:00
}