2018-08-28 18:43:28 +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-28 18:43:28 +00:00
* the Free Software Foundation , either version 3 of the License , or
* ( at your option ) any later version .
*
* Baritone is distributed in the hope that it will be useful ,
* 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-28 18:43:28 +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-28 18:43:28 +00:00
* along with Baritone . If not , see < https : //www.gnu.org/licenses/>.
* /
2018-11-04 05:11:52 +00:00
package baritone.process ;
2018-08-28 18:28:36 +00:00
2018-09-15 17:34:02 +00:00
import baritone.Baritone ;
2018-10-26 04:21:42 +00:00
import baritone.api.pathing.goals.* ;
2018-11-04 05:11:52 +00:00
import baritone.api.process.IMineProcess ;
import baritone.api.process.PathingCommand ;
import baritone.api.process.PathingCommandType ;
2018-10-26 04:21:42 +00:00
import baritone.api.utils.RotationUtils ;
2018-09-11 17:28:03 +00:00
import baritone.cache.CachedChunk ;
import baritone.cache.ChunkPacker ;
import baritone.cache.WorldProvider ;
import baritone.cache.WorldScanner ;
2018-10-26 04:21:42 +00:00
import baritone.pathing.movement.MovementHelper ;
2018-11-04 05:11:52 +00:00
import baritone.utils.BaritoneProcessHelper ;
2018-08-28 18:43:28 +00:00
import baritone.utils.BlockStateInterface ;
2018-09-12 22:53:29 +00:00
import baritone.utils.Helper ;
2018-09-12 22:12:06 +00:00
import net.minecraft.block.Block ;
2018-09-16 20:00:44 +00:00
import net.minecraft.init.Blocks ;
2018-09-17 21:22:45 +00:00
import net.minecraft.item.Item ;
import net.minecraft.item.ItemStack ;
2018-08-28 18:43:28 +00:00
import net.minecraft.util.math.BlockPos ;
import net.minecraft.world.chunk.EmptyChunk ;
2018-09-17 21:22:45 +00:00
import java.util.* ;
2018-08-28 18:43:28 +00:00
import java.util.stream.Collectors ;
/ * *
* Mine blocks of a certain type
*
* @author leijurv
* /
2018-11-04 05:11:52 +00:00
public final class MineProcess extends BaritoneProcessHelper implements IMineProcess {
private static final int ORE_LOCATIONS_COUNT = 64 ;
2018-09-12 22:53:29 +00:00
2018-09-12 22:12:06 +00:00
private List < Block > mining ;
2018-10-26 03:08:52 +00:00
private List < BlockPos > knownOreLocations ;
2018-10-26 04:21:42 +00:00
private BlockPos branchPoint ;
2018-10-26 03:08:52 +00:00
private int desiredQuantity ;
2018-11-04 05:11:52 +00:00
private int tickCount ;
2018-08-28 18:43:28 +00:00
2018-11-04 05:11:52 +00:00
public MineProcess ( Baritone baritone ) {
2018-11-04 18:29:22 +00:00
super ( baritone , 0 ) ;
2018-10-28 01:45:17 +00:00
}
2018-09-17 03:16:05 +00:00
2018-09-14 16:21:52 +00:00
@Override
2018-11-04 05:11:52 +00:00
public boolean isActive ( ) {
return mining ! = null ;
}
@Override
2018-11-05 22:19:50 +00:00
public PathingCommand onTick ( boolean calcFailed , boolean isSafeToCancel ) {
2018-10-26 03:08:52 +00:00
if ( desiredQuantity > 0 ) {
2018-09-17 21:22:45 +00:00
Item item = mining . get ( 0 ) . getItemDropped ( mining . get ( 0 ) . getDefaultState ( ) , new Random ( ) , 0 ) ;
int curr = player ( ) . inventory . mainInventory . stream ( ) . filter ( stack - > item . equals ( stack . getItem ( ) ) ) . mapToInt ( ItemStack : : getCount ) . sum ( ) ;
System . out . println ( " Currently have " + curr + " " + item ) ;
2018-10-26 03:08:52 +00:00
if ( curr > = desiredQuantity ) {
2018-09-17 21:22:45 +00:00
logDirect ( " Have " + curr + " " + item . getItemStackDisplayName ( new ItemStack ( item , 1 ) ) ) ;
cancel ( ) ;
2018-11-04 05:11:52 +00:00
return null ;
2018-09-17 21:22:45 +00:00
}
}
2018-11-05 22:19:50 +00:00
if ( calcFailed ) {
logDirect ( " Unable to find any path to " + mining + " , canceling Mine " ) ;
cancel ( ) ;
return null ;
}
2018-09-15 17:34:02 +00:00
int mineGoalUpdateInterval = Baritone . settings ( ) . mineGoalUpdateInterval . get ( ) ;
2018-11-04 05:11:52 +00:00
if ( mineGoalUpdateInterval ! = 0 & & tickCount + + % mineGoalUpdateInterval = = 0 ) { // big brain
2018-11-04 18:29:22 +00:00
baritone . getExecutor ( ) . execute ( this : : rescan ) ;
2018-09-15 17:34:02 +00:00
}
2018-10-26 04:21:42 +00:00
if ( Baritone . settings ( ) . legitMine . get ( ) ) {
addNearby ( ) ;
}
2018-11-04 05:11:52 +00:00
Goal goal = updateGoal ( ) ;
if ( goal = = null ) {
// none in range
// maybe say something in chat? (ahem impact)
cancel ( ) ;
return null ;
}
return new PathingCommand ( goal , PathingCommandType . REVALIDATE_GOAL_AND_PATH ) ;
2018-09-04 22:33:38 +00:00
}
2018-11-04 05:11:52 +00:00
@Override
public void onLostControl ( ) {
mine ( 0 , ( Block [ ] ) null ) ;
}
2018-11-04 18:29:22 +00:00
@Override
public String displayName ( ) {
return " Mine " + mining ;
}
2018-11-04 05:11:52 +00:00
private Goal updateGoal ( ) {
2018-10-26 03:08:52 +00:00
List < BlockPos > locs = knownOreLocations ;
2018-10-10 23:40:33 +00:00
if ( ! locs . isEmpty ( ) ) {
2018-11-04 05:11:52 +00:00
List < BlockPos > locs2 = prune ( new ArrayList < > ( locs ) , mining , ORE_LOCATIONS_COUNT ) ;
2018-10-26 04:21:42 +00:00
// can't reassign locs, gotta make a new var locs2, because we use it in a lambda right here, and variables you use in a lambda must be effectively final
2018-11-04 05:11:52 +00:00
Goal goal = new GoalComposite ( locs2 . stream ( ) . map ( loc - > coalesce ( loc , locs2 ) ) . toArray ( Goal [ ] : : new ) ) ;
2018-11-04 03:25:09 +00:00
knownOreLocations = locs2 ;
2018-11-04 05:11:52 +00:00
return goal ;
2018-10-26 04:21:42 +00:00
}
// we don't know any ore locations at the moment
if ( ! Baritone . settings ( ) . legitMine . get ( ) ) {
2018-11-04 05:11:52 +00:00
return null ;
2018-10-26 04:21:42 +00:00
}
// only in non-Xray mode (aka legit mode) do we do this
if ( branchPoint = = null ) {
int y = Baritone . settings ( ) . legitMineYLevel . get ( ) ;
2018-11-04 18:29:22 +00:00
if ( ! baritone . getPathingBehavior ( ) . isPathing ( ) & & playerFeet ( ) . y = = y ) {
2018-10-26 04:21:42 +00:00
// cool, path is over and we are at desired y
branchPoint = playerFeet ( ) ;
} else {
2018-11-04 05:11:52 +00:00
return new GoalYLevel ( y ) ;
2018-10-26 04:21:42 +00:00
}
}
if ( playerFeet ( ) . equals ( branchPoint ) ) {
// TODO mine 1x1 shafts to either side
branchPoint = branchPoint . north ( 10 ) ;
2018-10-10 23:40:33 +00:00
}
2018-11-04 05:11:52 +00:00
return new GoalBlock ( branchPoint ) ;
2018-10-10 23:40:33 +00:00
}
private void rescan ( ) {
if ( mining = = null ) {
return ;
2018-09-15 19:56:35 +00:00
}
2018-10-26 04:21:42 +00:00
if ( Baritone . settings ( ) . legitMine . get ( ) ) {
return ;
}
2018-11-04 05:11:52 +00:00
List < BlockPos > locs = searchWorld ( mining , ORE_LOCATIONS_COUNT ) ;
2018-09-04 22:03:59 +00:00
if ( locs . isEmpty ( ) ) {
2018-09-11 20:45:43 +00:00
logDebug ( " No locations for " + mining + " known, cancelling " ) ;
2018-11-04 05:11:52 +00:00
cancel ( ) ;
2018-09-04 22:03:59 +00:00
return ;
}
2018-10-26 03:08:52 +00:00
knownOreLocations = locs ;
2018-09-04 22:03:59 +00:00
}
2018-10-26 03:08:52 +00:00
private static Goal coalesce ( BlockPos loc , List < BlockPos > locs ) {
2018-10-12 03:36:18 +00:00
if ( ! Baritone . settings ( ) . forceInternalMining . get ( ) ) {
return new GoalTwoBlocks ( loc ) ;
}
boolean upwardGoal = locs . contains ( loc . up ( ) ) | | ( Baritone . settings ( ) . internalMiningAirException . get ( ) & & BlockStateInterface . getBlock ( loc . up ( ) ) = = Blocks . AIR ) ;
boolean downwardGoal = locs . contains ( loc . down ( ) ) | | ( Baritone . settings ( ) . internalMiningAirException . get ( ) & & BlockStateInterface . getBlock ( loc . up ( ) ) = = Blocks . AIR ) ;
if ( upwardGoal ) {
if ( downwardGoal ) {
2018-09-16 20:00:44 +00:00
return new GoalTwoBlocks ( loc ) ;
2018-10-12 03:36:18 +00:00
} else {
return new GoalBlock ( loc ) ;
2018-09-16 20:00:44 +00:00
}
2018-10-12 03:36:18 +00:00
} else {
if ( downwardGoal ) {
return new GoalBlock ( loc . down ( ) ) ;
2018-09-16 20:00:44 +00:00
} else {
2018-10-12 03:36:18 +00:00
return new GoalTwoBlocks ( loc ) ;
2018-09-16 20:00:44 +00:00
}
2018-10-12 03:36:18 +00:00
}
}
2018-11-04 05:11:52 +00:00
public static List < BlockPos > searchWorld ( List < Block > mining , int max ) {
2018-09-04 15:50:42 +00:00
List < BlockPos > locs = new ArrayList < > ( ) ;
2018-09-12 22:12:06 +00:00
List < Block > uninteresting = new ArrayList < > ( ) ;
2018-09-04 22:08:21 +00:00
//long b = System.currentTimeMillis();
2018-09-12 22:12:06 +00:00
for ( Block m : mining ) {
if ( CachedChunk . BLOCKS_TO_KEEP_TRACK_OF . contains ( m ) ) {
2018-09-24 23:45:41 +00:00
locs . addAll ( WorldProvider . INSTANCE . getCurrentWorld ( ) . getCachedWorld ( ) . getLocationsOf ( ChunkPacker . blockToString ( m ) , 1 , 1 ) ) ;
2018-09-04 22:03:59 +00:00
} else {
uninteresting . add ( m ) ;
}
2018-09-04 15:50:42 +00:00
}
2018-09-04 22:08:21 +00:00
//System.out.println("Scan of cached chunks took " + (System.currentTimeMillis() - b) + "ms");
2018-09-16 20:28:16 +00:00
if ( locs . isEmpty ( ) ) {
uninteresting = mining ;
}
2018-09-04 22:08:21 +00:00
if ( ! uninteresting . isEmpty ( ) ) {
//long before = System.currentTimeMillis();
2018-10-14 04:27:11 +00:00
locs . addAll ( WorldScanner . INSTANCE . scanChunkRadius ( uninteresting , max , 10 , 26 ) ) ;
2018-09-04 22:08:21 +00:00
//System.out.println("Scan of loaded chunks took " + (System.currentTimeMillis() - before) + "ms");
}
2018-09-15 19:56:35 +00:00
return prune ( locs , mining , max ) ;
}
2018-10-26 04:21:42 +00:00
public void addNearby ( ) {
BlockPos playerFeet = playerFeet ( ) ;
int searchDist = 4 ; //why four? idk
for ( int x = playerFeet . getX ( ) - searchDist ; x < = playerFeet . getX ( ) + searchDist ; x + + ) {
for ( int y = playerFeet . getY ( ) - searchDist ; y < = playerFeet . getY ( ) + searchDist ; y + + ) {
for ( int z = playerFeet . getZ ( ) - searchDist ; z < = playerFeet . getZ ( ) + searchDist ; z + + ) {
BlockPos pos = new BlockPos ( x , y , z ) ;
2018-10-27 21:41:25 +00:00
if ( mining . contains ( BlockStateInterface . getBlock ( pos ) ) & & RotationUtils . reachable ( player ( ) , pos ) . isPresent ( ) ) { //crucial to only add blocks we can see because otherwise this is an x-ray and it'll get caught
knownOreLocations . add ( pos ) ;
2018-10-26 04:21:42 +00:00
}
}
}
}
2018-11-04 05:11:52 +00:00
knownOreLocations = prune ( knownOreLocations , mining , ORE_LOCATIONS_COUNT ) ;
2018-10-26 04:21:42 +00:00
}
2018-11-04 05:11:52 +00:00
public static List < BlockPos > prune ( List < BlockPos > locs2 , List < Block > mining , int max ) {
2018-10-26 04:21:42 +00:00
List < BlockPos > locs = locs2
. stream ( )
// remove any that are within loaded chunks that aren't actually what we want
2018-11-04 05:11:52 +00:00
. filter ( pos - > Helper . HELPER . world ( ) . getChunk ( pos ) instanceof EmptyChunk | | mining . contains ( BlockStateInterface . get ( pos ) . getBlock ( ) ) )
2018-10-26 04:21:42 +00:00
// remove any that are implausible to mine (encased in bedrock, or touching lava)
2018-11-04 05:11:52 +00:00
. filter ( MineProcess : : plausibleToBreak )
2018-10-26 04:21:42 +00:00
. sorted ( Comparator . comparingDouble ( Helper . HELPER . playerFeet ( ) : : distanceSq ) )
. collect ( Collectors . toList ( ) ) ;
2018-08-28 18:43:28 +00:00
2018-09-04 22:03:59 +00:00
if ( locs . size ( ) > max ) {
2018-09-17 00:49:19 +00:00
return locs . subList ( 0 , max ) ;
2018-09-01 19:16:55 +00:00
}
2018-09-04 22:03:59 +00:00
return locs ;
2018-08-28 18:43:28 +00:00
}
2018-10-26 04:21:42 +00:00
public static boolean plausibleToBreak ( BlockPos pos ) {
if ( MovementHelper . avoidBreaking ( pos . getX ( ) , pos . getY ( ) , pos . getZ ( ) , BlockStateInterface . get ( pos ) ) ) {
return false ;
}
// bedrock above and below makes it implausible, otherwise we're good
return ! ( BlockStateInterface . getBlock ( pos . up ( ) ) = = Blocks . BEDROCK & & BlockStateInterface . getBlock ( pos . down ( ) ) = = Blocks . BEDROCK ) ;
}
2018-09-23 21:44:35 +00:00
@Override
2018-11-04 05:11:52 +00:00
public void mineByName ( int quantity , String . . . blocks ) {
mine ( quantity , blocks = = null | | blocks . length = = 0 ? null : Arrays . stream ( blocks ) . map ( ChunkPacker : : stringToBlock ) . toArray ( Block [ ] : : new ) ) ;
2018-09-12 22:12:06 +00:00
}
2018-09-23 21:44:35 +00:00
@Override
public void mine ( int quantity , Block . . . blocks ) {
2018-09-12 22:12:06 +00:00
this . mining = blocks = = null | | blocks . length = = 0 ? null : Arrays . asList ( blocks ) ;
2018-10-26 03:08:52 +00:00
this . desiredQuantity = quantity ;
this . knownOreLocations = new ArrayList < > ( ) ;
2018-10-26 04:21:42 +00:00
this . branchPoint = null ;
2018-10-10 23:40:33 +00:00
rescan ( ) ;
2018-08-28 18:43:28 +00:00
}
2018-08-28 18:28:36 +00:00
}