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 ;
2019-01-30 03:56:50 +00:00
import baritone.api.IBaritone ;
2018-09-25 01:32:39 +00:00
import baritone.api.pathing.movement.ActionCosts ;
2019-01-30 03:56:50 +00:00
import baritone.api.pathing.movement.MovementStatus ;
2018-11-10 03:12:36 +00:00
import baritone.api.utils.* ;
2018-11-13 17:50:29 +00:00
import baritone.api.utils.input.Input ;
2018-08-22 20:15:56 +00:00
import baritone.pathing.movement.MovementState.MovementTarget ;
2018-11-11 20:35:04 +00:00
import baritone.utils.BlockStateInterface ;
import baritone.utils.Helper ;
import baritone.utils.ToolSet ;
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 ;
2018-08-06 22:53:35 +00:00
import net.minecraft.client.entity.EntityPlayerSP ;
2018-08-02 17:49:31 +00:00
import net.minecraft.init.Blocks ;
2018-10-10 23:29:48 +00:00
import net.minecraft.item.ItemPickaxe ;
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 ;
2019-01-30 03:56:50 +00:00
import net.minecraft.util.math.RayTraceResult ;
import net.minecraft.util.math.Vec3d ;
import static baritone.pathing.movement.Movement.HORIZONTALS_BUT_ALSO_DOWN____SO_EVERY_DIRECTION_EXCEPT_UP ;
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-11-13 21:14:29 +00:00
static boolean avoidBreaking ( BlockStateInterface bsi , 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-11-11 20:35:04 +00:00
// call context.get directly with x,y,z. no need to make 5 new BlockPos for no reason
2018-11-13 21:14:29 +00:00
| | bsi . get0 ( x , y + 1 , z ) . getBlock ( ) instanceof BlockLiquid //don't break anything touching liquid on any side
| | bsi . get0 ( x + 1 , y , z ) . getBlock ( ) instanceof BlockLiquid
| | bsi . get0 ( x - 1 , y , z ) . getBlock ( ) instanceof BlockLiquid
| | bsi . get0 ( x , y , z + 1 ) . getBlock ( ) instanceof BlockLiquid
| | bsi . get0 ( x , y , z - 1 ) . getBlock ( ) instanceof BlockLiquid ;
2018-08-02 17:25:46 +00:00
}
2018-11-13 21:14:29 +00:00
static boolean canWalkThrough ( IPlayerContext ctx , BetterBlockPos pos ) {
return canWalkThrough ( new BlockStateInterface ( ctx ) , pos . x , pos . y , pos . z ) ;
2018-08-07 14:39:55 +00:00
}
2018-11-13 21:14:29 +00:00
static boolean canWalkThrough ( BlockStateInterface bsi , int x , int y , int z ) {
return canWalkThrough ( bsi , x , y , z , bsi . get0 ( x , y , z ) ) ;
2018-09-22 16:28:59 +00:00
}
2018-11-13 21:14:29 +00:00
static boolean canWalkThrough ( BlockStateInterface bsi , 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 ;
}
2019-02-24 21:43:53 +00:00
if ( block = = Blocks . FIRE | | block = = Blocks . TRIPWIRE | | block = = Blocks . WEB | | block = = Blocks . END_PORTAL | | block = = Blocks . COCOA | | block instanceof BlockSkull ) {
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-11-23 17:03:51 +00:00
if ( ! bsi . worldContainsLoadedChunk ( x , z ) ) {
2018-08-25 15:44:33 +00:00
return true ;
}
2018-09-22 16:17:28 +00:00
if ( snow ) {
2018-10-13 02:33:03 +00:00
// the check in BlockSnow.isPassable is layers < 5
// while actually, we want < 3 because 3 or greater makes it impassable in a 2 high ceiling
2018-11-26 23:32:28 +00:00
if ( state . getValue ( BlockSnow . LAYERS ) > = 3 ) {
return false ;
}
// ok, it's low enough we could walk through it, but is it supported?
return canWalkOn ( bsi , x , y - 1 , z ) ;
2018-09-22 16:17:28 +00:00
}
if ( trapdoor ) {
return ! state . getValue ( BlockTrapDoor . OPEN ) ; // see BlockTrapDoor.isPassable
}
throw new IllegalStateException ( ) ;
2018-08-25 15:44:33 +00:00
}
2018-11-01 22:36:32 +00:00
if ( 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-11-13 21:14:29 +00:00
IBlockState up = bsi . get0 ( 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 )
*
2018-12-04 00:47:40 +00:00
* @param context Calculation context to provide block state lookup
2018-12-04 22:38:08 +00:00
* @param x The block ' s x position
* @param y The block ' s y position
* @param z The block ' s z position
2018-12-04 00:47:40 +00:00
* @return Whether or not the block at the specified position
2018-09-06 14:48:27 +00:00
* /
2018-11-11 20:35:04 +00:00
static boolean fullyPassable ( CalculationContext context , int x , int y , int z ) {
return fullyPassable ( context . get ( x , y , z ) ) ;
2018-09-23 19:24:07 +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
2018-11-26 23:01:34 +00:00
| | block = = Blocks . COCOA
2018-09-06 14:48:27 +00:00
| | block instanceof BlockDoor
| | block instanceof BlockFenceGate
| | block instanceof BlockSnow
| | block instanceof BlockLiquid
| | block instanceof BlockTrapDoor
2019-02-24 21:43:53 +00:00
| | block instanceof BlockEndPortal
| | block instanceof BlockSkull ) {
2018-09-06 14:48:27 +00:00
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-12-04 23:00:45 +00:00
static boolean isReplacable ( int x , int y , int z , IBlockState state , BlockStateInterface bsi ) {
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 ( ) ;
2018-12-04 23:00:45 +00:00
if ( block = = Blocks . AIR | | isWater ( block ) ) {
// early return for common cases hehe
return true ;
}
2018-09-23 02:46:10 +00:00
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-12-04 23:00:45 +00:00
if ( ! bsi . worldContainsLoadedChunk ( x , z ) ) {
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-10-15 04:46:41 +00:00
return state . getMaterial ( ) . isReplaceable ( ) ;
2018-08-25 15:44:33 +00:00
}
2018-11-13 21:14:29 +00:00
static boolean isDoorPassable ( IPlayerContext ctx , 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
2018-11-13 21:14:29 +00:00
IBlockState state = BlockStateInterface . get ( ctx , 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 ) ;
}
2018-11-13 21:14:29 +00:00
static boolean isGatePassable ( IPlayerContext ctx , 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
2018-11-13 21:14:29 +00:00
IBlockState state = BlockStateInterface . get ( ctx , 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
2018-11-21 00:32:55 +00:00
return state . getValue ( BlockFenceGate . OPEN ) ;
2018-08-26 07:17:52 +00:00
}
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-10-27 23:18:03 +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
*
2018-12-04 22:38:08 +00:00
* @param bsi Block state provider
* @param x The block ' s x position
* @param y The block ' s y position
* @param z The block ' s z position
2018-12-04 00:47:40 +00:00
* @param state The state of the block at the specified location
* @return Whether or not the specified block can be walked on
2018-08-02 17:25:46 +00:00
* /
2018-11-13 21:14:29 +00:00
static boolean canWalkOn ( BlockStateInterface bsi , 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 ( ) ) {
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-11-01 22:36:32 +00:00
if ( 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-11-13 21:14:29 +00:00
Block up = bsi . get0 ( 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-11-01 22:36:32 +00:00
if ( 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
2018-11-01 22:36:32 +00:00
return isWater ( up ) & & ! Baritone . settings ( ) . assumeWalkOnWater . get ( ) ;
2018-09-04 20:57:56 +00:00
}
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
2018-11-01 22:36:32 +00:00
return isWater ( up ) ^ Baritone . settings ( ) . assumeWalkOnWater . get ( ) ;
2018-08-02 17:25:46 +00:00
}
2018-11-23 15:47:28 +00:00
if ( block = = Blocks . GLASS | | block = = Blocks . STAINED_GLASS ) {
2018-09-09 15:11:33 +00:00
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 ;
}
2018-10-27 23:18:03 +00:00
return block instanceof BlockStairs ;
2018-08-02 17:25:46 +00:00
}
2018-08-02 17:49:31 +00:00
2018-11-13 21:14:29 +00:00
static boolean canWalkOn ( IPlayerContext ctx , BetterBlockPos pos , IBlockState state ) {
return canWalkOn ( new BlockStateInterface ( ctx ) , pos . x , pos . y , pos . z , state ) ;
}
static boolean canWalkOn ( IPlayerContext ctx , BetterBlockPos pos ) {
return canWalkOn ( new BlockStateInterface ( ctx ) , pos . x , pos . y , pos . z ) ;
2018-09-22 16:28:59 +00:00
}
2018-11-13 21:14:29 +00:00
static boolean canWalkOn ( BlockStateInterface bsi , int x , int y , int z ) {
return canWalkOn ( bsi , x , y , z , bsi . get0 ( x , y , z ) ) ;
2018-09-22 16:28:59 +00:00
}
2018-11-13 21:14:29 +00:00
static boolean canPlaceAgainst ( BlockStateInterface bsi , int x , int y , int z ) {
return canPlaceAgainst ( bsi . get0 ( x , y , z ) ) ;
2018-08-07 02:48:09 +00:00
}
2018-11-13 21:14:29 +00:00
static boolean canPlaceAgainst ( BlockStateInterface bsi , BlockPos pos ) {
return canPlaceAgainst ( bsi . get0 ( pos . getX ( ) , pos . getY ( ) , pos . getZ ( ) ) ) ;
2018-09-23 02:46:10 +00:00
}
2018-11-13 21:14:29 +00:00
static boolean canPlaceAgainst ( IPlayerContext ctx , BlockPos pos ) {
return canPlaceAgainst ( new BlockStateInterface ( ctx ) , pos ) ;
2018-09-23 02:46:10 +00:00
}
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-23 02:46:10 +00:00
static double getMiningDurationTicks ( CalculationContext context , int x , int y , int z , boolean includeFalling ) {
2018-11-11 20:35:04 +00:00
return getMiningDurationTicks ( context , x , y , z , context . get ( x , y , z ) , includeFalling ) ;
2018-09-23 02:46:10 +00:00
}
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-12-21 05:22:18 +00:00
if ( ! canWalkThrough ( context . bsi , x , y , z , state ) ) {
2018-10-12 21:34:33 +00:00
if ( ! context . canBreakAt ( x , y , z ) ) {
2018-08-02 17:49:31 +00:00
return COST_INF ;
}
2018-12-21 05:22:18 +00:00
if ( avoidBreaking ( context . bsi , 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-12-21 05:22:18 +00:00
double strVsBlock = context . toolSet . 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-12-21 05:22:18 +00:00
result + = context . breakBlockAdditionalCost ;
2018-08-26 20:48:08 +00:00
if ( includeFalling ) {
2018-11-11 20:35:04 +00:00
IBlockState above = context . 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 ;
}
2018-08-04 02:14:50 +00:00
/ * *
* AutoTool for a specific block
*
2018-12-04 00:47:40 +00:00
* @param ctx The player context
2018-12-04 22:38:08 +00:00
* @param b the blockstate to mine
2018-08-04 02:14:50 +00:00
* /
2018-11-13 17:50:29 +00:00
static void switchToBestToolFor ( IPlayerContext ctx , IBlockState b ) {
switchToBestToolFor ( ctx , b , new ToolSet ( ctx . player ( ) ) ) ;
2018-08-04 02:14:50 +00:00
}
/ * *
* AutoTool for a specific block with precomputed ToolSet data
*
2018-12-04 00:47:40 +00:00
* @param ctx The player context
2018-12-04 22:38:08 +00:00
* @param b the blockstate to mine
* @param ts previously calculated ToolSet
2018-08-04 02:14:50 +00:00
* /
2018-11-13 17:50:29 +00:00
static void switchToBestToolFor ( IPlayerContext ctx , IBlockState b , ToolSet ts ) {
ctx . player ( ) . inventory . currentItem = ts . getBestSlot ( b . getBlock ( ) ) ;
2018-08-04 02:14:50 +00:00
}
2018-08-06 22:53:35 +00:00
2018-11-13 17:50:29 +00:00
static boolean throwaway ( IPlayerContext ctx , boolean select ) {
EntityPlayerSP p = ctx . player ( ) ;
2018-08-06 22:53:35 +00:00
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 ;
}
}
2018-10-10 23:29:48 +00:00
if ( Baritone . settings ( ) . acceptableThrowawayItems . get ( ) . contains ( p . inventory . offHandInventory . get ( 0 ) . getItem ( ) ) ) {
// main hand takes precedence over off hand
// that means that if we have block A selected in main hand and block B in off hand, right clicking places block B
// we've already checked above ^ and the main hand can't possible have an acceptablethrowawayitem
// so we need to select in the main hand something that doesn't right click
// so not a shovel, not a hoe, not a block, etc
for ( byte i = 0 ; i < 9 ; i + + ) {
ItemStack item = inv . get ( i ) ;
if ( item . isEmpty ( ) | | item . getItem ( ) instanceof ItemPickaxe ) {
if ( select ) {
p . inventory . currentItem = i ;
}
return true ;
}
}
}
2018-08-06 22:53:35 +00:00
return false ;
}
2018-11-13 17:50:29 +00:00
static void moveTowards ( IPlayerContext ctx , MovementState state , BlockPos pos ) {
2018-08-21 22:52:09 +00:00
state . setTarget ( new MovementTarget (
2019-02-14 05:11:13 +00:00
new Rotation ( RotationUtils . calcRotationFromVec3d ( ctx . playerHead ( ) ,
2018-10-14 05:55:30 +00:00
VecUtils . getBlockPosCenter ( pos ) ,
2019-02-14 05:11:13 +00:00
ctx . playerRotations ( ) ) . getYaw ( ) , ctx . player ( ) . rotationPitch ) ,
2018-08-21 22:52:09 +00:00
false
2018-11-13 17:50:29 +00:00
) ) . setInput ( Input . MOVE_FORWARD , true ) ;
2018-08-08 19:51:04 +00:00
}
2018-11-01 22:36:32 +00:00
/ * *
* Returns whether or not the specified block is
* water , regardless of whether or not it is flowing .
*
* @param b The block
* @return Whether or not the block is water
* /
static boolean isWater ( Block b ) {
return b = = Blocks . FLOWING_WATER | | b = = Blocks . WATER ;
}
/ * *
* Returns whether or not the block at the specified pos is
* water , regardless of whether or not it is flowing .
*
2018-11-13 21:14:29 +00:00
* @param ctx The player context
2018-11-14 21:24:44 +00:00
* @param bp The block pos
2018-11-01 22:36:32 +00:00
* @return Whether or not the block is water
* /
2018-11-13 21:14:29 +00:00
static boolean isWater ( IPlayerContext ctx , BlockPos bp ) {
return isWater ( BlockStateInterface . getBlock ( ctx , bp ) ) ;
2018-11-01 22:36:32 +00:00
}
static boolean isLava ( Block b ) {
return b = = Blocks . FLOWING_LAVA | | b = = Blocks . LAVA ;
}
/ * *
* Returns whether or not the specified pos has a liquid
*
2018-11-13 21:14:29 +00:00
* @param ctx The player context
2018-11-14 21:24:44 +00:00
* @param p The pos
2018-11-01 22:36:32 +00:00
* @return Whether or not the block is a liquid
* /
2018-11-13 21:14:29 +00:00
static boolean isLiquid ( IPlayerContext ctx , BlockPos p ) {
return BlockStateInterface . getBlock ( ctx , p ) instanceof BlockLiquid ;
2018-11-01 22:36:32 +00:00
}
static boolean isFlowing ( IBlockState state ) {
// Will be IFluidState in 1.13
return state . getBlock ( ) instanceof BlockLiquid
& & state . getValue ( BlockLiquid . LEVEL ) ! = 0 ;
}
2019-01-30 03:56:50 +00:00
static PlaceResult attemptToPlaceABlock ( MovementState state , IBaritone baritone , BlockPos placeAt , boolean preferDown ) {
IPlayerContext ctx = baritone . getPlayerContext ( ) ;
boolean found = false ;
for ( int i = 0 ; i < 5 ; i + + ) {
BlockPos against1 = placeAt . offset ( HORIZONTALS_BUT_ALSO_DOWN____SO_EVERY_DIRECTION_EXCEPT_UP [ i ] ) ;
if ( MovementHelper . canPlaceAgainst ( ctx , against1 ) ) {
//if (!((Baritone) baritone).getInventoryBehavior().selectThrowawayForLocation(placeAt.getX(), placeAt.getY(), placeAt.getZ())) { // get ready to place a throwaway block
if ( ! throwaway ( ctx , true ) ) {
Helper . HELPER . logDebug ( " bb pls get me some blocks. dirt or cobble " ) ;
state . setStatus ( MovementStatus . UNREACHABLE ) ;
return PlaceResult . NO_OPTION ;
}
double faceX = ( placeAt . getX ( ) + against1 . getX ( ) + 1 . 0D ) * 0 . 5D ;
double faceY = ( placeAt . getY ( ) + against1 . getY ( ) + 1 . 0D ) * 0 . 5D ;
double faceZ = ( placeAt . getZ ( ) + against1 . getZ ( ) + 1 . 0D ) * 0 . 5D ;
Rotation place = RotationUtils . calcRotationFromVec3d ( ctx . playerHead ( ) , new Vec3d ( faceX , faceY , faceZ ) , ctx . playerRotations ( ) ) ;
RayTraceResult res = RayTraceUtils . rayTraceTowards ( ctx . player ( ) , place , ctx . playerController ( ) . getBlockReachDistance ( ) ) ;
if ( res ! = null & & res . typeOfHit = = RayTraceResult . Type . BLOCK & & res . getBlockPos ( ) . equals ( against1 ) & & res . getBlockPos ( ) . offset ( res . sideHit ) . equals ( placeAt ) ) {
state . setTarget ( new MovementState . MovementTarget ( place , true ) ) ;
found = true ;
if ( ! preferDown ) {
// if preferDown is true, we want the last option
// if preferDown is false, we want the first
break ;
}
}
}
}
if ( ctx . getSelectedBlock ( ) . isPresent ( ) ) {
BlockPos selectedBlock = ctx . getSelectedBlock ( ) . get ( ) ;
EnumFacing side = ctx . objectMouseOver ( ) . sideHit ;
// only way for selectedBlock.equals(placeAt) to be true is if it's replacable
if ( selectedBlock . equals ( placeAt ) | | ( MovementHelper . canPlaceAgainst ( ctx , selectedBlock ) & & selectedBlock . offset ( side ) . equals ( placeAt ) ) ) {
return PlaceResult . READY_TO_PLACE ;
}
}
return found ? PlaceResult . ATTEMPTING : PlaceResult . NO_OPTION ;
}
enum PlaceResult {
READY_TO_PLACE , ATTEMPTING , NO_OPTION ;
}
2018-08-02 17:25:46 +00:00
}