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 04:07:55 +00:00
2018-08-22 20:15:56 +00:00
import baritone.Baritone ;
2018-09-12 22:58:33 +00:00
import baritone.behavior.LookBehavior ;
import baritone.behavior.LookBehaviorUtils ;
2018-08-22 20:15:56 +00:00
import baritone.pathing.movement.MovementState.MovementStatus ;
import baritone.utils.* ;
2018-09-09 16:22:35 +00:00
import baritone.utils.pathing.BetterBlockPos ;
2018-08-28 21:56:21 +00:00
import net.minecraft.util.EnumFacing ;
2018-08-02 07:12:51 +00:00
import net.minecraft.util.math.BlockPos ;
2018-08-25 06:38:53 +00:00
import net.minecraft.util.math.RayTraceResult ;
2018-09-13 23:18:26 +00:00
import net.minecraft.world.chunk.EmptyChunk ;
2018-08-02 07:12:51 +00:00
2018-08-06 22:53:35 +00:00
import java.util.ArrayList ;
2018-08-26 20:48:08 +00:00
import java.util.Arrays ;
2018-08-25 23:30:12 +00:00
import java.util.List ;
2018-08-02 22:35:36 +00:00
import java.util.Optional ;
2018-08-22 20:15:56 +00:00
import static baritone.utils.InputOverrideHandler.Input ;
2018-08-06 00:37:42 +00:00
2018-08-05 03:01:38 +00:00
public abstract class Movement implements Helper , MovementHelper {
2018-08-03 07:51:10 +00:00
2018-08-28 21:56:21 +00:00
protected static final EnumFacing [ ] HORIZONTALS = { EnumFacing . NORTH , EnumFacing . SOUTH , EnumFacing . EAST , EnumFacing . WEST } ;
2018-08-04 22:17:53 +00:00
private MovementState currentState = new MovementState ( ) . setStatus ( MovementStatus . PREPPING ) ;
2018-08-07 21:14:36 +00:00
2018-09-09 16:22:35 +00:00
protected final BetterBlockPos src ;
2018-08-03 07:51:10 +00:00
2018-09-09 16:22:35 +00:00
protected final BetterBlockPos dest ;
2018-08-03 07:51:10 +00:00
2018-08-03 03:30:35 +00:00
/ * *
* The positions that need to be broken before this movement can ensue
* /
2018-08-07 21:14:36 +00:00
protected final BlockPos [ ] positionsToBreak ;
2018-08-03 07:51:10 +00:00
2018-08-03 03:30:35 +00:00
/ * *
2018-08-28 20:41:44 +00:00
* The position where we need to place a block before this movement can ensue
2018-08-03 03:30:35 +00:00
* /
2018-08-28 20:41:44 +00:00
protected final BlockPos positionToPlace ;
2018-08-02 07:12:51 +00:00
2018-08-25 06:38:53 +00:00
private boolean didBreakLastTick ;
2018-08-06 00:27:45 +00:00
private Double cost ;
2018-09-17 03:16:05 +00:00
public List < BlockPos > toBreakCached = null ;
public List < BlockPos > toPlaceCached = null ;
public List < BlockPos > toWalkIntoCached = null ;
private Boolean calculatedWhileLoaded ;
2018-09-09 16:22:35 +00:00
protected Movement ( BetterBlockPos src , BetterBlockPos dest , BlockPos [ ] toBreak , BlockPos toPlace ) {
2018-08-02 22:35:36 +00:00
this . src = src ;
this . dest = dest ;
2018-08-03 03:30:35 +00:00
this . positionsToBreak = toBreak ;
2018-08-28 20:41:44 +00:00
this . positionToPlace = toPlace ;
2018-08-02 14:59:51 +00:00
}
2018-09-09 16:22:35 +00:00
protected Movement ( BetterBlockPos src , BetterBlockPos dest , BlockPos [ ] toBreak ) {
2018-08-28 20:41:44 +00:00
this ( src , dest , toBreak , null ) ;
2018-08-02 07:12:51 +00:00
}
2018-08-07 21:36:32 +00:00
public double getCost ( CalculationContext context ) {
2018-08-06 00:27:45 +00:00
if ( cost = = null ) {
2018-09-17 00:49:19 +00:00
cost = calculateCost ( context ! = null ? context : new CalculationContext ( ) ) ;
2018-08-06 00:27:45 +00:00
}
return cost ;
}
2018-08-13 18:50:49 +00:00
protected abstract double calculateCost ( CalculationContext context ) ;
2018-08-06 00:27:45 +00:00
public double recalculateCost ( ) {
cost = null ;
return getCost ( null ) ;
}
2018-08-02 07:12:51 +00:00
2018-09-06 14:48:27 +00:00
protected void override ( double cost ) {
this . cost = cost ;
}
2018-09-02 21:12:33 +00:00
public double calculateCostWithoutCaching ( ) {
2018-09-03 16:15:18 +00:00
return calculateCost ( new CalculationContext ( ) ) ;
2018-09-02 21:12:33 +00:00
}
2018-08-05 03:01:38 +00:00
/ * *
* Handles the execution of the latest Movement
* State , and offers a Status to the calling class .
*
* @return Status
* /
2018-08-04 18:49:52 +00:00
public MovementStatus update ( ) {
2018-09-15 01:29:35 +00:00
player ( ) . capabilities . allowFlying = false ;
2018-08-04 22:17:53 +00:00
MovementState latestState = updateState ( currentState ) ;
2018-08-07 15:09:27 +00:00
if ( BlockStateInterface . isLiquid ( playerFeet ( ) ) ) {
latestState . setInput ( Input . JUMP , true ) ;
}
2018-08-21 23:19:20 +00:00
// If the movement target has to force the new rotations, or we aren't using silent move, then force the rotations
latestState . getTarget ( ) . getRotation ( ) . ifPresent ( rotation - >
LookBehavior . INSTANCE . updateTarget (
rotation ,
latestState . getTarget ( ) . hasToForceRotations ( ) ) ) ;
2018-08-06 04:42:17 +00:00
// TODO: calculate movement inputs from latestState.getGoal().position
// latestState.getTarget().position.ifPresent(null); NULL CONSUMER REALLY SHOULDN'T BE THE FINAL THING YOU SHOULD REALLY REPLACE THIS WITH ALMOST ACTUALLY ANYTHING ELSE JUST PLEASE DON'T LEAVE IT AS IT IS THANK YOU KANYE
2018-08-25 06:38:53 +00:00
this . didBreakLastTick = false ;
2018-08-07 21:14:36 +00:00
latestState . getInputStates ( ) . forEach ( ( input , forced ) - > {
2018-09-14 16:05:29 +00:00
if ( Baritone . settings ( ) . leftClickWorkaround . get ( ) ) {
RayTraceResult trace = mc . objectMouseOver ;
boolean isBlockTrace = trace ! = null & & trace . typeOfHit = = RayTraceResult . Type . BLOCK ;
boolean isLeftClick = forced & & input = = Input . CLICK_LEFT ;
// If we're forcing left click, we're in a gui screen, and we're looking
// at a block, break the block without a direct game input manipulation.
if ( mc . currentScreen ! = null & & isLeftClick & & isBlockTrace ) {
BlockBreakHelper . tryBreakBlock ( trace . getBlockPos ( ) , trace . sideHit ) ;
this . didBreakLastTick = true ;
return ;
}
2018-08-25 06:38:53 +00:00
}
2018-08-06 01:52:55 +00:00
Baritone . INSTANCE . getInputOverrideHandler ( ) . setInputForceState ( input , forced ) ;
} ) ;
2018-08-07 21:14:36 +00:00
latestState . getInputStates ( ) . replaceAll ( ( input , forced ) - > false ) ;
2018-08-25 06:38:53 +00:00
2018-09-08 04:32:25 +00:00
if ( ! this . didBreakLastTick ) {
2018-08-25 06:38:53 +00:00
BlockBreakHelper . stopBreakingBlock ( ) ;
2018-09-08 04:32:25 +00:00
}
2018-08-25 06:38:53 +00:00
2018-08-02 08:15:51 +00:00
currentState = latestState ;
2018-09-08 04:32:25 +00:00
if ( isFinished ( ) ) {
2018-08-06 01:17:54 +00:00
onFinish ( latestState ) ;
2018-09-08 04:32:25 +00:00
}
2018-08-04 22:17:53 +00:00
return currentState . getStatus ( ) ;
2018-08-02 08:15:51 +00:00
}
2018-08-12 04:27:46 +00:00
protected boolean prepared ( MovementState state ) {
2018-08-18 19:33:00 +00:00
if ( state . getStatus ( ) = = MovementStatus . WAITING ) {
return true ;
}
2018-08-12 15:17:23 +00:00
boolean somethingInTheWay = false ;
2018-08-06 04:42:17 +00:00
for ( BlockPos blockPos : positionsToBreak ) {
2018-08-07 01:18:16 +00:00
if ( ! MovementHelper . canWalkThrough ( blockPos ) ) {
2018-08-12 15:17:23 +00:00
somethingInTheWay = true ;
2018-08-06 00:50:59 +00:00
Optional < Rotation > reachable = LookBehaviorUtils . reachable ( blockPos ) ;
2018-08-06 04:42:17 +00:00
if ( reachable . isPresent ( ) ) {
2018-09-05 00:13:42 +00:00
MovementHelper . switchToBestToolFor ( BlockStateInterface . get ( blockPos ) ) ;
2018-08-21 22:52:09 +00:00
state . setTarget ( new MovementState . MovementTarget ( reachable . get ( ) , true ) ) . setInput ( Input . CLICK_LEFT , true ) ;
2018-08-06 00:37:42 +00:00
return false ;
2018-08-06 04:42:17 +00:00
}
2018-08-21 03:17:55 +00:00
//get rekt minecraft
//i'm doing it anyway
//i dont care if theres snow in the way!!!!!!!
//you dont own me!!!!
state . setTarget ( new MovementState . MovementTarget ( Utils . calcRotationFromVec3d ( mc . player . getPositionEyes ( 1 . 0F ) ,
2018-08-21 22:52:09 +00:00
Utils . getBlockPosCenter ( blockPos ) ) , true )
2018-08-21 03:17:55 +00:00
) . setInput ( InputOverrideHandler . Input . CLICK_LEFT , true ) ;
return false ;
2018-08-04 22:17:53 +00:00
}
2018-08-04 18:49:52 +00:00
}
2018-08-12 15:17:23 +00:00
if ( somethingInTheWay ) {
// There's a block or blocks that we can't walk through, but we have no target rotation to reach any
// So don't return true, actually set state to unreachable
state . setStatus ( MovementStatus . UNREACHABLE ) ;
return true ;
}
2018-08-04 22:17:53 +00:00
return true ;
2018-08-04 18:49:52 +00:00
}
2018-08-02 08:15:51 +00:00
public boolean isFinished ( ) {
2018-08-02 21:28:35 +00:00
return ( currentState . getStatus ( ) ! = MovementStatus . RUNNING
2018-08-06 00:37:42 +00:00
& & currentState . getStatus ( ) ! = MovementStatus . PREPPING
2018-08-02 21:28:35 +00:00
& & currentState . getStatus ( ) ! = MovementStatus . WAITING ) ;
2018-08-02 07:12:51 +00:00
}
2018-09-09 16:22:35 +00:00
public BetterBlockPos getSrc ( ) {
2018-08-02 18:12:56 +00:00
return src ;
2018-08-02 18:05:47 +00:00
}
2018-09-09 16:22:35 +00:00
public BetterBlockPos getDest ( ) {
2018-08-02 18:12:56 +00:00
return dest ;
2018-08-02 18:05:47 +00:00
}
2018-08-03 03:40:27 +00:00
/ * *
2018-08-06 01:17:54 +00:00
* Run cleanup on state finish and declare success .
2018-08-03 03:40:27 +00:00
* /
2018-08-06 01:17:54 +00:00
public void onFinish ( MovementState state ) {
2018-08-07 21:14:36 +00:00
state . getInputStates ( ) . replaceAll ( ( input , forced ) - > false ) ;
state . getInputStates ( ) . forEach ( ( input , forced ) - > Baritone . INSTANCE . getInputOverrideHandler ( ) . setInputForceState ( input , forced ) ) ;
2018-08-06 01:17:54 +00:00
}
2018-08-03 03:40:27 +00:00
2018-08-06 02:08:23 +00:00
public void cancel ( ) {
2018-08-07 21:14:36 +00:00
currentState . getInputStates ( ) . replaceAll ( ( input , forced ) - > false ) ;
currentState . getInputStates ( ) . forEach ( ( input , forced ) - > Baritone . INSTANCE . getInputOverrideHandler ( ) . setInputForceState ( input , forced ) ) ;
2018-08-06 02:08:23 +00:00
currentState . setStatus ( MovementStatus . CANCELED ) ;
}
2018-08-23 18:14:37 +00:00
public void reset ( ) {
currentState = new MovementState ( ) . setStatus ( MovementStatus . PREPPING ) ;
}
2018-08-07 00:34:49 +00:00
2018-08-17 20:17:16 +00:00
public double getTotalHardnessOfBlocksToBreak ( CalculationContext ctx ) {
2018-08-26 20:48:08 +00:00
if ( positionsToBreak . length = = 0 ) {
return 0 ;
2018-08-07 00:34:49 +00:00
}
2018-08-26 20:48:08 +00:00
if ( positionsToBreak . length = = 1 ) {
return MovementHelper . getMiningDurationTicks ( ctx , positionsToBreak [ 0 ] , true ) ;
2018-08-07 00:34:49 +00:00
}
2018-08-26 20:48:08 +00:00
int firstColumnX = positionsToBreak [ 0 ] . getX ( ) ;
int firstColumnZ = positionsToBreak [ 0 ] . getZ ( ) ;
int firstColumnMaxY = positionsToBreak [ 0 ] . getY ( ) ;
int firstColumnMaximalIndex = 0 ;
boolean hasSecondColumn = false ;
int secondColumnX = - 1 ;
int secondColumnZ = - 1 ;
int secondColumnMaxY = - 1 ;
int secondColumnMaximalIndex = - 1 ;
for ( int i = 0 ; i < positionsToBreak . length ; i + + ) {
BlockPos pos = positionsToBreak [ i ] ;
if ( pos . getX ( ) = = firstColumnX & & pos . getZ ( ) = = firstColumnZ ) {
if ( pos . getY ( ) > firstColumnMaxY ) {
firstColumnMaxY = pos . getY ( ) ;
firstColumnMaximalIndex = i ;
}
} else {
if ( ! hasSecondColumn | | ( pos . getX ( ) = = secondColumnX & & pos . getZ ( ) = = secondColumnZ ) ) {
if ( hasSecondColumn ) {
if ( pos . getY ( ) > secondColumnMaxY ) {
secondColumnMaxY = pos . getY ( ) ;
secondColumnMaximalIndex = i ;
}
} else {
hasSecondColumn = true ;
secondColumnX = pos . getX ( ) ;
secondColumnZ = pos . getZ ( ) ;
secondColumnMaxY = pos . getY ( ) ;
secondColumnMaximalIndex = i ;
}
} else {
throw new IllegalStateException ( " I literally have no idea " + Arrays . asList ( positionsToBreak ) ) ;
2018-08-07 00:34:49 +00:00
}
}
2018-08-26 20:48:08 +00:00
}
2018-08-07 00:34:49 +00:00
double sum = 0 ;
2018-08-26 20:48:08 +00:00
for ( int i = 0 ; i < positionsToBreak . length ; i + + ) {
sum + = MovementHelper . getMiningDurationTicks ( ctx , positionsToBreak [ i ] , firstColumnMaximalIndex = = i | | secondColumnMaximalIndex = = i ) ;
2018-08-07 00:34:49 +00:00
if ( sum > = COST_INF ) {
2018-08-26 20:48:08 +00:00
break ;
2018-08-07 00:34:49 +00:00
}
}
return sum ;
}
2018-08-02 07:12:51 +00:00
/ * *
2018-08-02 21:28:35 +00:00
* Calculate latest movement state .
2018-08-02 07:12:51 +00:00
* Gets called once a tick .
*
* @return
* /
2018-08-04 18:49:52 +00:00
public MovementState updateState ( MovementState state ) {
2018-08-18 19:36:40 +00:00
if ( ! prepared ( state ) ) {
2018-08-04 18:49:52 +00:00
return state . setStatus ( MovementStatus . PREPPING ) ;
2018-08-18 19:36:40 +00:00
} else if ( state . getStatus ( ) = = MovementStatus . PREPPING ) {
2018-08-06 01:00:36 +00:00
state . setStatus ( MovementStatus . WAITING ) ;
2018-08-06 00:37:42 +00:00
}
2018-08-26 07:53:50 +00:00
if ( state . getStatus ( ) = = MovementStatus . WAITING ) {
state . setStatus ( MovementStatus . RUNNING ) ;
}
2018-08-04 18:49:52 +00:00
return state ;
}
2018-08-06 22:53:35 +00:00
2018-08-26 15:12:57 +00:00
public BlockPos getDirection ( ) {
return getDest ( ) . subtract ( getSrc ( ) ) ;
}
2018-09-13 23:18:26 +00:00
public void checkLoadedChunk ( ) {
calculatedWhileLoaded = ! ( world ( ) . getChunk ( getDest ( ) ) instanceof EmptyChunk ) ;
}
public boolean calculatedWhileLoaded ( ) {
return calculatedWhileLoaded ;
}
2018-08-25 23:30:12 +00:00
public List < BlockPos > toBreak ( ) {
2018-08-06 23:09:28 +00:00
if ( toBreakCached ! = null ) {
return toBreakCached ;
}
2018-08-25 23:30:12 +00:00
List < BlockPos > result = new ArrayList < > ( ) ;
2018-08-07 00:34:49 +00:00
for ( BlockPos positionToBreak : positionsToBreak ) {
2018-08-07 01:18:16 +00:00
if ( ! MovementHelper . canWalkThrough ( positionToBreak ) ) {
2018-08-07 00:34:49 +00:00
result . add ( positionToBreak ) ;
2018-08-06 22:53:35 +00:00
}
}
2018-08-06 23:09:28 +00:00
toBreakCached = result ;
2018-08-06 22:53:35 +00:00
return result ;
}
2018-08-25 23:30:12 +00:00
public List < BlockPos > toPlace ( ) {
2018-08-06 23:09:28 +00:00
if ( toPlaceCached ! = null ) {
return toPlaceCached ;
}
2018-08-25 23:30:12 +00:00
List < BlockPos > result = new ArrayList < > ( ) ;
2018-08-28 20:41:44 +00:00
if ( positionToPlace ! = null & & ! MovementHelper . canWalkOn ( positionToPlace ) ) {
result . add ( positionToPlace ) ;
2018-08-06 22:53:35 +00:00
}
2018-08-06 23:09:28 +00:00
toPlaceCached = result ;
2018-08-06 22:53:35 +00:00
return result ;
}
2018-08-12 15:40:44 +00:00
2018-08-25 23:30:12 +00:00
public List < BlockPos > toWalkInto ( ) { // overridden by movementdiagonal
2018-08-12 15:40:44 +00:00
if ( toWalkIntoCached = = null ) {
toWalkIntoCached = new ArrayList < > ( ) ;
}
return toWalkIntoCached ;
}
2018-08-02 04:07:55 +00:00
}