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 ;
2019-09-07 00:46:26 +00:00
import baritone.api.utils.* ;
2019-04-18 05:17:09 +00:00
import baritone.api.utils.input.Input ;
2018-09-11 17:28:03 +00:00
import baritone.cache.CachedChunk ;
import baritone.cache.WorldScanner ;
2018-11-23 17:00:52 +00:00
import baritone.pathing.movement.CalculationContext ;
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 ;
2021-06-23 17:24:32 +00:00
import net.minecraft.client.multiplayer.ClientLevel ;
import net.minecraft.core.BlockPos ;
import net.minecraft.world.entity.Entity ;
import net.minecraft.world.entity.item.ItemEntity ;
import net.minecraft.world.item.ItemStack ;
import net.minecraft.world.level.block.AirBlock ;
import net.minecraft.world.level.block.Block ;
import net.minecraft.world.level.block.Blocks ;
import net.minecraft.world.level.block.FallingBlock ;
import net.minecraft.world.level.block.state.BlockState ;
2018-08-28 18:43:28 +00:00
2018-09-17 21:22:45 +00:00
import java.util.* ;
2018-08-28 18:43:28 +00:00
import java.util.stream.Collectors ;
2019-04-25 06:10:41 +00:00
import static baritone.api.pathing.movement.ActionCosts.COST_INF ;
2018-08-28 18:43:28 +00:00
/ * *
* 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
2019-08-30 22:38:15 +00:00
private BlockOptionalMetaLookup filter ;
2018-10-26 03:08:52 +00:00
private List < BlockPos > knownOreLocations ;
2019-03-12 03:06:19 +00:00
private List < BlockPos > blacklist ; // inaccessible
2019-10-06 20:26:29 +00:00
private Map < BlockPos , Long > anticipatedDrops ;
2018-10-26 04:21:42 +00:00
private BlockPos branchPoint ;
2018-11-08 01:27:57 +00:00
private GoalRunAway branchPointRunaway ;
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 ) {
2019-03-12 01:24:31 +00:00
super ( baritone ) ;
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 ( ) {
2019-08-30 18:55:25 +00:00
return filter ! = null ;
2018-11-04 05:11:52 +00:00
}
@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 ) {
2021-06-23 19:29:34 +00:00
int curr = ctx . player ( ) . getInventory ( ) . items . stream ( )
2019-09-07 00:46:26 +00:00
. filter ( stack - > filter . has ( stack ) )
. mapToInt ( ItemStack : : getCount ) . sum ( ) ;
2019-08-30 18:55:25 +00:00
System . out . println ( " Currently have " + curr + " valid items " ) ;
2018-10-26 03:08:52 +00:00
if ( curr > = desiredQuantity ) {
2019-08-30 18:55:25 +00:00
logDirect ( " Have " + curr + " valid items " ) ;
2018-09-17 21:22:45 +00:00
cancel ( ) ;
2018-11-04 05:11:52 +00:00
return null ;
2018-09-17 21:22:45 +00:00
}
}
2019-05-08 05:40:03 +00:00
if ( calcFailed ) {
if ( ! knownOreLocations . isEmpty ( ) & & Baritone . settings ( ) . blacklistClosestOnFailure . value ) {
2019-08-30 18:55:25 +00:00
logDirect ( " Unable to find any path to " + filter + " , blacklisting presumably unreachable closest instance... " ) ;
2021-05-09 21:15:34 +00:00
if ( Baritone . settings ( ) . notificationOnMineFail . value ) {
logNotification ( " Unable to find any path to " + filter + " , blacklisting presumably unreachable closest instance... " , true ) ;
2020-02-29 17:24:06 +00:00
}
2021-06-23 19:29:34 +00:00
knownOreLocations . stream ( ) . min ( Comparator . comparingDouble ( ctx . playerFeet ( ) : : distSqr ) ) . ifPresent ( blacklist : : add ) ;
2019-05-08 05:40:03 +00:00
knownOreLocations . removeIf ( blacklist : : contains ) ;
2019-05-08 18:51:48 +00:00
} else {
2019-08-30 18:55:25 +00:00
logDirect ( " Unable to find any path to " + filter + " , canceling mine " ) ;
2021-05-09 21:15:34 +00:00
if ( Baritone . settings ( ) . notificationOnMineFail . value ) {
logNotification ( " Unable to find any path to " + filter + " , canceling mine " , true ) ;
2020-02-29 17:24:06 +00:00
}
2019-05-08 18:51:48 +00:00
cancel ( ) ;
return null ;
2019-05-08 05:40:03 +00:00
}
2018-11-05 22:19:50 +00:00
}
2022-12-10 23:35:51 +00:00
2019-10-06 20:26:29 +00:00
updateLoucaSystem ( ) ;
2019-03-05 05:30:04 +00:00
int mineGoalUpdateInterval = Baritone . settings ( ) . mineGoalUpdateInterval . value ;
2019-04-18 05:17:09 +00:00
List < BlockPos > curr = new ArrayList < > ( knownOreLocations ) ;
2018-11-04 05:11:52 +00:00
if ( mineGoalUpdateInterval ! = 0 & & tickCount + + % mineGoalUpdateInterval = = 0 ) { // big brain
2018-11-26 06:30:37 +00:00
CalculationContext context = new CalculationContext ( baritone , true ) ;
2018-11-23 17:00:52 +00:00
Baritone . getExecutor ( ) . execute ( ( ) - > rescan ( curr , context ) ) ;
2018-09-15 17:34:02 +00:00
}
2019-03-05 05:30:04 +00:00
if ( Baritone . settings ( ) . legitMine . value ) {
2022-12-11 03:12:51 +00:00
if ( ! addNearby ( ) ) {
cancel ( ) ;
return null ;
}
2018-10-26 04:21:42 +00:00
}
2019-04-18 05:17:09 +00:00
Optional < BlockPos > shaft = curr . stream ( )
. filter ( pos - > pos . getX ( ) = = ctx . playerFeet ( ) . getX ( ) & & pos . getZ ( ) = = ctx . playerFeet ( ) . getZ ( ) )
2019-05-01 06:24:08 +00:00
. filter ( pos - > pos . getY ( ) > = ctx . playerFeet ( ) . getY ( ) )
2019-06-11 01:25:20 +00:00
. filter ( pos - > ! ( BlockStateInterface . get ( ctx , pos ) . getBlock ( ) instanceof AirBlock ) ) // after breaking a block, it takes mineGoalUpdateInterval ticks for it to actually update this list =(
2021-06-23 19:29:34 +00:00
. min ( Comparator . comparingDouble ( ctx . playerFeet ( ) : : distSqr ) ) ;
2019-04-18 05:17:09 +00:00
baritone . getInputOverrideHandler ( ) . clearAllKeys ( ) ;
2020-07-26 03:53:22 +00:00
if ( shaft . isPresent ( ) & & ctx . player ( ) . isOnGround ( ) ) {
2019-04-18 05:17:09 +00:00
BlockPos pos = shaft . get ( ) ;
2019-06-10 19:43:02 +00:00
BlockState state = baritone . bsi . get0 ( pos ) ;
2019-04-18 05:17:09 +00:00
if ( ! MovementHelper . avoidBreaking ( baritone . bsi , pos . getX ( ) , pos . getY ( ) , pos . getZ ( ) , state ) ) {
Optional < Rotation > rot = RotationUtils . reachable ( ctx , pos ) ;
if ( rot . isPresent ( ) & & isSafeToCancel ) {
baritone . getLookBehavior ( ) . updateTarget ( rot . get ( ) , true ) ;
MovementHelper . switchToBestToolFor ( ctx , ctx . world ( ) . getBlockState ( pos ) ) ;
if ( ctx . isLookingAt ( pos ) | | ctx . playerRotations ( ) . isReallyCloseTo ( rot . get ( ) ) ) {
baritone . getInputOverrideHandler ( ) . setInputForceState ( Input . CLICK_LEFT , true ) ;
}
return new PathingCommand ( null , PathingCommandType . REQUEST_PAUSE ) ;
}
}
}
2019-01-29 23:22:48 +00:00
PathingCommand command = updateGoal ( ) ;
if ( command = = null ) {
2018-11-04 05:11:52 +00:00
// none in range
// maybe say something in chat? (ahem impact)
cancel ( ) ;
return null ;
}
2019-01-29 23:22:48 +00:00
return command ;
2018-09-04 22:33:38 +00:00
}
2019-07-23 22:39:19 +00:00
2019-10-06 20:26:29 +00:00
private void updateLoucaSystem ( ) {
Map < BlockPos , Long > copy = new HashMap < > ( anticipatedDrops ) ;
ctx . getSelectedBlock ( ) . ifPresent ( pos - > {
if ( knownOreLocations . contains ( pos ) ) {
copy . put ( pos , System . currentTimeMillis ( ) + Baritone . settings ( ) . mineDropLoiterDurationMSThanksLouca . value ) ;
2019-07-23 22:39:19 +00:00
}
} ) ;
2019-10-06 20:26:29 +00:00
// elaborate dance to avoid concurrentmodificationexcepption since rescan thread reads this
// don't want to slow everything down with a gross lock do we now
for ( BlockPos pos : anticipatedDrops . keySet ( ) ) {
if ( copy . get ( pos ) < System . currentTimeMillis ( ) ) {
copy . remove ( pos ) ;
}
}
anticipatedDrops = copy ;
2019-07-23 22:39:19 +00:00
}
2018-11-04 05:11:52 +00:00
@Override
public void onLostControl ( ) {
2019-08-30 22:38:15 +00:00
mine ( 0 , ( BlockOptionalMetaLookup ) null ) ;
2018-11-04 05:11:52 +00:00
}
2018-11-04 18:29:22 +00:00
@Override
2019-03-13 16:17:25 +00:00
public String displayName0 ( ) {
2019-08-30 18:55:25 +00:00
return " Mine " + filter ;
2018-11-04 18:29:22 +00:00
}
2019-01-29 23:22:48 +00:00
private PathingCommand updateGoal ( ) {
2022-12-11 02:25:57 +00:00
BlockOptionalMetaLookup filter = filterFilter ( ) ;
if ( filter = = null ) {
return null ;
}
2019-03-05 05:30:04 +00:00
boolean legit = Baritone . settings ( ) . legitMine . value ;
2018-10-26 03:08:52 +00:00
List < BlockPos > locs = knownOreLocations ;
2018-10-10 23:40:33 +00:00
if ( ! locs . isEmpty ( ) ) {
2019-10-06 20:26:29 +00:00
CalculationContext context = new CalculationContext ( baritone ) ;
List < BlockPos > locs2 = prune ( context , new ArrayList < > ( locs ) , filter , ORE_LOCATIONS_COUNT , blacklist , droppedItemsScan ( ) ) ;
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
2019-10-06 20:26:29 +00:00
Goal goal = new GoalComposite ( locs2 . stream ( ) . map ( loc - > coalesce ( loc , locs2 , context ) ) . toArray ( Goal [ ] : : new ) ) ;
2018-11-04 03:25:09 +00:00
knownOreLocations = locs2 ;
2019-01-29 23:22:48 +00:00
return new PathingCommand ( goal , legit ? PathingCommandType . FORCE_REVALIDATE_GOAL_AND_PATH : PathingCommandType . REVALIDATE_GOAL_AND_PATH ) ;
2018-10-26 04:21:42 +00:00
}
// we don't know any ore locations at the moment
2021-05-28 20:18:33 +00:00
if ( ! legit & & ! Baritone . settings ( ) . exploreForBlocks . value ) {
2018-11-04 05:11:52 +00:00
return null ;
2018-10-26 04:21:42 +00:00
}
2021-05-28 20:18:33 +00:00
// only when we should explore for blocks or are in legit mode we do this
2019-03-05 05:30:04 +00:00
int y = Baritone . settings ( ) . legitMineYLevel . value ;
2018-10-26 04:21:42 +00:00
if ( branchPoint = = null ) {
2018-11-12 01:59:13 +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 ( ) ;
2018-11-08 01:27:57 +00:00
branchPointRunaway = null ;
2018-10-26 04:21:42 +00:00
} else {
2018-11-04 05:11:52 +00:00
return new GoalYLevel ( y ) ;
2018-11-12 01:59:13 +00:00
} * /
2018-11-13 17:50:29 +00:00
branchPoint = ctx . playerFeet ( ) ;
2018-10-26 04:21:42 +00:00
}
2018-11-08 22:58:18 +00:00
// TODO shaft mode, mine 1x1 shafts to either side
// TODO also, see if the GoalRunAway with maintain Y at 11 works even from the surface
2018-11-08 01:27:57 +00:00
if ( branchPointRunaway = = null ) {
2018-11-17 17:18:55 +00:00
branchPointRunaway = new GoalRunAway ( 1 , y , branchPoint ) {
2018-11-08 01:27:57 +00:00
@Override
public boolean isInGoal ( int x , int y , int z ) {
return false ;
}
2023-01-15 09:02:52 +00:00
2020-09-20 20:39:48 +00:00
@Override
public double heuristic ( ) {
return Double . NEGATIVE_INFINITY ;
}
2018-11-08 01:27:57 +00:00
} ;
}
2019-01-29 23:22:48 +00:00
return new PathingCommand ( branchPointRunaway , PathingCommandType . REVALIDATE_GOAL_AND_PATH ) ;
2018-10-10 23:40:33 +00:00
}
2018-11-23 17:00:52 +00:00
private void rescan ( List < BlockPos > already , CalculationContext context ) {
2022-12-11 02:25:57 +00:00
BlockOptionalMetaLookup filter = filterFilter ( ) ;
2019-08-30 18:55:25 +00:00
if ( filter = = null ) {
2018-10-10 23:40:33 +00:00
return ;
2018-09-15 19:56:35 +00:00
}
2019-03-05 05:30:04 +00:00
if ( Baritone . settings ( ) . legitMine . value ) {
2018-10-26 04:21:42 +00:00
return ;
}
2019-10-06 20:26:29 +00:00
List < BlockPos > dropped = droppedItemsScan ( ) ;
List < BlockPos > locs = searchWorld ( context , filter , ORE_LOCATIONS_COUNT , already , blacklist , dropped ) ;
locs . addAll ( dropped ) ;
2021-05-10 20:37:35 +00:00
if ( locs . isEmpty ( ) & & ! Baritone . settings ( ) . exploreForBlocks . value ) {
2019-08-30 18:55:25 +00:00
logDirect ( " No locations for " + filter + " known, cancelling " ) ;
2021-05-09 21:15:34 +00:00
if ( Baritone . settings ( ) . notificationOnMineFail . value ) {
logNotification ( " No locations for " + filter + " known, cancelling " , true ) ;
2020-02-29 16:28:18 +00:00
}
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
}
2019-10-06 20:26:29 +00:00
private boolean internalMiningGoal ( BlockPos pos , CalculationContext context , List < BlockPos > locs ) {
2019-04-18 17:36:20 +00:00
// Here, BlockStateInterface is used because the position may be in a cached chunk (the targeted block is one that is kept track of)
2019-05-02 06:07:20 +00:00
if ( locs . contains ( pos ) ) {
return true ;
}
2019-10-07 00:02:41 +00:00
BlockState state = context . bsi . get0 ( pos ) ;
if ( Baritone . settings ( ) . internalMiningAirException . value & & state . getBlock ( ) instanceof AirBlock ) {
2019-05-02 06:07:20 +00:00
return true ;
}
2019-10-06 20:26:29 +00:00
return filter . has ( state ) & & plausibleToBreak ( context , pos ) ;
2019-04-18 05:17:09 +00:00
}
2019-10-06 20:26:29 +00:00
private Goal coalesce ( BlockPos loc , List < BlockPos > locs , CalculationContext context ) {
2021-06-23 17:24:32 +00:00
boolean assumeVerticalShaftMine = ! ( baritone . bsi . get0 ( loc . above ( ) ) . getBlock ( ) instanceof FallingBlock ) ;
2019-03-05 05:30:04 +00:00
if ( ! Baritone . settings ( ) . forceInternalMining . value ) {
2019-04-25 17:49:54 +00:00
if ( assumeVerticalShaftMine ) {
// we can get directly below the block
return new GoalThreeBlocks ( loc ) ;
} else {
// we need to get feet or head into the block
return new GoalTwoBlocks ( loc ) ;
}
2018-10-12 03:36:18 +00:00
}
2021-06-23 17:24:32 +00:00
boolean upwardGoal = internalMiningGoal ( loc . above ( ) , context , locs ) ;
boolean downwardGoal = internalMiningGoal ( loc . below ( ) , context , locs ) ;
boolean doubleDownwardGoal = internalMiningGoal ( loc . below ( 2 ) , context , locs ) ;
2019-04-18 17:36:20 +00:00
if ( upwardGoal = = downwardGoal ) { // symmetric
2019-04-25 17:49:54 +00:00
if ( doubleDownwardGoal & & assumeVerticalShaftMine ) {
2019-04-18 17:36:20 +00:00
// we have a checkerboard like pattern
// this one, and the one two below it
// therefore it's fine to path to immediately below this one, since your feet will be in the doubleDownwardGoal
2019-04-25 17:49:54 +00:00
// but only if assumeVerticalShaftMine
2019-04-18 17:36:20 +00:00
return new GoalThreeBlocks ( loc ) ;
} else {
// this block has nothing interesting two below, but is symmetric vertically so we can get either feet or head into it
return new GoalTwoBlocks ( loc ) ;
}
}
if ( upwardGoal ) {
// downwardGoal known to be false
// ignore the gap then potential doubleDownward, because we want to path feet into this one and head into upwardGoal
return new GoalBlock ( loc ) ;
}
// upwardGoal known to be false, downwardGoal known to be true
2019-04-25 17:49:54 +00:00
if ( doubleDownwardGoal & & assumeVerticalShaftMine ) {
2019-04-18 17:36:20 +00:00
// this block and two below it are goals
// path into the center of the one below, because that includes directly below this one
2021-06-23 17:24:32 +00:00
return new GoalTwoBlocks ( loc . below ( ) ) ;
2018-10-12 03:36:18 +00:00
}
2019-04-18 17:36:20 +00:00
// upwardGoal false, downwardGoal true, doubleDownwardGoal false
// just this block and the one immediately below, no others
2021-06-23 17:24:32 +00:00
return new GoalBlock ( loc . below ( ) ) ;
2019-04-18 05:17:09 +00:00
}
2018-10-12 03:36:18 +00:00
2019-04-18 05:17:09 +00:00
private static class GoalThreeBlocks extends GoalTwoBlocks {
public GoalThreeBlocks ( BlockPos pos ) {
super ( pos ) ;
}
@Override
public boolean isInGoal ( int x , int y , int z ) {
return x = = this . x & & ( y = = this . y | | y = = this . y - 1 | | y = = this . y - 2 ) & & z = = this . z ;
}
@Override
public double heuristic ( int x , int y , int z ) {
int xDiff = x - this . x ;
int yDiff = y - this . y ;
int zDiff = z - this . z ;
return GoalBlock . calculate ( xDiff , yDiff < - 1 ? yDiff + 2 : yDiff = = - 1 ? 0 : yDiff , zDiff ) ;
}
2018-10-12 03:36:18 +00:00
}
2019-10-06 20:26:29 +00:00
public List < BlockPos > droppedItemsScan ( ) {
2019-03-05 05:30:04 +00:00
if ( ! Baritone . settings ( ) . mineScanDroppedItems . value ) {
2019-06-01 17:56:24 +00:00
return Collections . emptyList ( ) ;
2018-11-06 02:31:59 +00:00
}
List < BlockPos > ret = new ArrayList < > ( ) ;
2021-06-23 17:24:32 +00:00
for ( Entity entity : ( ( ClientLevel ) ctx . world ( ) ) . entitiesForRendering ( ) ) {
2019-06-11 01:25:20 +00:00
if ( entity instanceof ItemEntity ) {
ItemEntity ei = ( ItemEntity ) entity ;
2019-09-01 03:43:03 +00:00
if ( filter . has ( ei . getItem ( ) ) ) {
2021-06-23 17:24:32 +00:00
ret . add ( entity . blockPosition ( ) ) ;
2018-11-06 02:31:59 +00:00
}
}
}
2019-10-06 20:26:29 +00:00
ret . addAll ( anticipatedDrops . keySet ( ) ) ;
2018-11-06 02:31:59 +00:00
return ret ;
}
2019-10-06 20:26:29 +00:00
public static List < BlockPos > searchWorld ( CalculationContext ctx , BlockOptionalMetaLookup filter , int max , List < BlockPos > alreadyKnown , List < BlockPos > blacklist , List < BlockPos > dropped ) {
2018-09-04 15:50:42 +00:00
List < BlockPos > locs = new ArrayList < > ( ) ;
2019-08-31 00:12:05 +00:00
List < Block > untracked = new ArrayList < > ( ) ;
for ( BlockOptionalMeta bom : filter . blocks ( ) ) {
Block block = bom . getBlock ( ) ;
2019-08-31 00:13:09 +00:00
if ( CachedChunk . BLOCKS_TO_KEEP_TRACK_OF . contains ( block ) ) {
2019-08-31 00:12:05 +00:00
BetterBlockPos pf = ctx . baritone . getPlayerContext ( ) . playerFeet ( ) ;
2019-03-05 05:20:13 +00:00
// maxRegionDistanceSq 2 means adjacent directly or adjacent diagonally; nothing further than that
2019-08-31 00:12:05 +00:00
locs . addAll ( ctx . worldData . getCachedWorld ( ) . getLocationsOf (
2019-09-07 00:46:26 +00:00
BlockUtils . blockToString ( block ) ,
Baritone . settings ( ) . maxCachedWorldScanCount . value ,
pf . x ,
pf . z ,
2
2019-08-31 00:12:05 +00:00
) ) ;
2018-09-04 22:03:59 +00:00
} else {
2019-08-31 00:12:05 +00:00
untracked . add ( block ) ;
2018-09-04 22:03:59 +00:00
}
2018-09-04 15:50:42 +00:00
}
2019-08-31 00:12:05 +00:00
2019-10-06 20:26:29 +00:00
locs = prune ( ctx , locs , filter , max , blacklist , dropped ) ;
2019-08-31 00:20:20 +00:00
2019-08-31 00:19:44 +00:00
if ( ! untracked . isEmpty ( ) | | ( Baritone . settings ( ) . extendCacheOnThreshold . value & & locs . size ( ) < max ) ) {
2019-08-31 00:12:05 +00:00
locs . addAll ( WorldScanner . INSTANCE . scanChunkRadius (
2019-09-07 00:46:26 +00:00
ctx . getBaritone ( ) . getPlayerContext ( ) ,
filter ,
max ,
10 ,
32
2019-08-31 00:12:05 +00:00
) ) ; // maxSearchRadius is NOT sq
2018-09-04 22:08:21 +00:00
}
2019-08-31 00:12:05 +00:00
2018-11-07 22:09:23 +00:00
locs . addAll ( alreadyKnown ) ;
2019-08-31 00:12:05 +00:00
2019-10-06 20:26:29 +00:00
return prune ( ctx , locs , filter , max , blacklist , dropped ) ;
2018-09-15 19:56:35 +00:00
}
2022-12-11 02:25:57 +00:00
private boolean addNearby ( ) {
2019-10-06 20:26:29 +00:00
List < BlockPos > dropped = droppedItemsScan ( ) ;
knownOreLocations . addAll ( dropped ) ;
2018-11-13 17:50:29 +00:00
BlockPos playerFeet = ctx . playerFeet ( ) ;
2018-11-21 00:32:44 +00:00
BlockStateInterface bsi = new BlockStateInterface ( ctx ) ;
2022-12-11 02:25:57 +00:00
BlockOptionalMetaLookup filter = filterFilter ( ) ;
if ( filter = = null ) {
return false ;
}
2018-11-21 00:32:44 +00:00
int searchDist = 10 ;
double fakedBlockReachDistance = 20 ; // at least 10 * sqrt(3) with some extra space to account for positioning within the block
2018-10-26 04:21:42 +00:00
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 + + ) {
2018-11-13 21:14:29 +00:00
// crucial to only add blocks we can see because otherwise this
// is an x-ray and it'll get caught
2019-08-30 22:38:15 +00:00
if ( filter . has ( bsi . get0 ( x , y , z ) ) ) {
2019-02-11 00:44:09 +00:00
BlockPos pos = new BlockPos ( x , y , z ) ;
2021-06-23 17:24:32 +00:00
if ( ( Baritone . settings ( ) . legitMineIncludeDiagonals . value & & knownOreLocations . stream ( ) . anyMatch ( ore - > ore . distSqr ( pos ) < = 2 /* sq means this is pytha dist <= sqrt(2) */ ) ) | | RotationUtils . reachable ( ctx . player ( ) , pos , fakedBlockReachDistance ) . isPresent ( ) ) {
2019-02-11 00:44:09 +00:00
knownOreLocations . add ( pos ) ;
}
2018-10-26 04:21:42 +00:00
}
}
}
}
2019-10-06 20:26:29 +00:00
knownOreLocations = prune ( new CalculationContext ( baritone ) , knownOreLocations , filter , ORE_LOCATIONS_COUNT , blacklist , dropped ) ;
2022-12-11 02:25:57 +00:00
return true ;
2018-10-26 04:21:42 +00:00
}
2019-10-06 20:26:29 +00:00
private static List < BlockPos > prune ( CalculationContext ctx , List < BlockPos > locs2 , BlockOptionalMetaLookup filter , int max , List < BlockPos > blacklist , List < BlockPos > dropped ) {
2019-02-08 20:08:34 +00:00
dropped . removeIf ( drop - > {
for ( BlockPos pos : locs2 ) {
2021-06-23 17:24:32 +00:00
if ( pos . distSqr ( drop ) < = 9 & & filter . has ( ctx . get ( pos . getX ( ) , pos . getY ( ) , pos . getZ ( ) ) ) & & MineProcess . plausibleToBreak ( ctx , pos ) ) { // TODO maybe drop also has to be supported? no lava below?
2019-02-08 20:08:34 +00:00
return true ;
}
}
return false ;
} ) ;
2018-10-26 04:21:42 +00:00
List < BlockPos > locs = locs2
. stream ( )
2018-11-09 22:49:25 +00:00
. distinct ( )
2018-10-26 04:21:42 +00:00
// remove any that are within loaded chunks that aren't actually what we want
2019-09-07 00:46:26 +00:00
. filter ( pos - > ! ctx . bsi . worldContainsLoadedChunk ( pos . getX ( ) , pos . getZ ( ) ) | | filter . has ( ctx . get ( pos . getX ( ) , pos . getY ( ) , pos . getZ ( ) ) ) | | dropped . contains ( pos ) )
2018-10-26 04:21:42 +00:00
// remove any that are implausible to mine (encased in bedrock, or touching lava)
2019-04-25 06:10:41 +00:00
. filter ( pos - > MineProcess . plausibleToBreak ( ctx , pos ) )
2018-10-26 04:21:42 +00:00
2020-09-05 16:07:06 +00:00
. filter ( pos - > {
2020-10-14 18:56:09 +00:00
if ( Baritone . settings ( ) . allowOnlyExposedOres . value ) {
2020-09-05 16:07:06 +00:00
return isNextToAir ( ctx , pos ) ;
2020-10-14 18:56:09 +00:00
} else {
2020-09-05 16:07:06 +00:00
return true ;
2020-10-14 18:56:09 +00:00
}
2020-09-05 16:07:06 +00:00
} )
2020-09-04 09:43:05 +00:00
2021-10-09 21:29:02 +00:00
. filter ( pos - > pos . getY ( ) > = Baritone . settings ( ) . minYLevelWhileMining . value + ctx . world . dimensionType ( ) . minY ( ) )
2020-10-16 16:02:02 +00:00
2019-03-12 03:06:19 +00:00
. filter ( pos - > ! blacklist . contains ( pos ) )
2021-06-23 19:29:34 +00:00
. sorted ( Comparator . comparingDouble ( ctx . getBaritone ( ) . getPlayerContext ( ) . player ( ) . blockPosition ( ) : : distSqr ) )
2018-10-26 04:21:42 +00:00
. 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
}
2020-09-04 09:43:05 +00:00
public static boolean isNextToAir ( CalculationContext ctx , BlockPos pos ) {
2020-09-08 16:39:03 +00:00
int radius = Baritone . settings ( ) . allowOnlyExposedOresDistance . value ;
for ( int dx = - radius ; dx < = radius ; dx + + ) {
for ( int dy = - radius ; dy < = radius ; dy + + ) {
for ( int dz = - radius ; dz < = radius ; dz + + ) {
if ( Math . abs ( dx ) + Math . abs ( dy ) + Math . abs ( dz ) < = radius
2020-10-14 18:56:09 +00:00
& & MovementHelper . isTransparent ( ctx . getBlock ( pos . getX ( ) + dx , pos . getY ( ) + dy , pos . getZ ( ) + dz ) ) ) {
2020-09-08 16:39:03 +00:00
return true ;
}
}
}
}
return false ;
2020-09-04 09:43:05 +00:00
}
2019-04-25 06:10:41 +00:00
public static boolean plausibleToBreak ( CalculationContext ctx , BlockPos pos ) {
if ( MovementHelper . getMiningDurationTicks ( ctx , pos . getX ( ) , pos . getY ( ) , pos . getZ ( ) , ctx . bsi . get0 ( pos ) , true ) > = COST_INF ) {
2018-10-26 04:21:42 +00:00
return false ;
}
2018-11-23 17:00:52 +00:00
2018-10-26 04:21:42 +00:00
// bedrock above and below makes it implausible, otherwise we're good
2021-06-23 17:24:32 +00:00
return ! ( ctx . bsi . get0 ( pos . above ( ) ) . getBlock ( ) = = Blocks . BEDROCK & & ctx . bsi . get0 ( pos . below ( ) ) . getBlock ( ) = = Blocks . BEDROCK ) ;
2018-10-26 04:21:42 +00:00
}
2018-09-23 21:44:35 +00:00
@Override
2018-11-04 05:11:52 +00:00
public void mineByName ( int quantity , String . . . blocks ) {
2019-09-06 10:59:10 +00:00
mine ( quantity , new BlockOptionalMetaLookup ( blocks ) ) ;
2018-09-12 22:12:06 +00:00
}
2018-09-23 21:44:35 +00:00
@Override
2019-08-30 22:38:15 +00:00
public void mine ( int quantity , BlockOptionalMetaLookup filter ) {
2019-08-30 18:55:25 +00:00
this . filter = filter ;
2022-12-11 02:25:57 +00:00
if ( this . filterFilter ( ) = = null ) {
this . filter = null ;
2019-07-11 17:41:24 +00:00
}
2018-10-26 03:08:52 +00:00
this . desiredQuantity = quantity ;
this . knownOreLocations = new ArrayList < > ( ) ;
2019-03-12 03:06:19 +00:00
this . blacklist = new ArrayList < > ( ) ;
2018-10-26 04:21:42 +00:00
this . branchPoint = null ;
2018-11-08 01:27:57 +00:00
this . branchPointRunaway = null ;
2019-10-06 20:26:29 +00:00
this . anticipatedDrops = new HashMap < > ( ) ;
2019-08-30 18:55:25 +00:00
if ( filter ! = null ) {
2018-11-23 17:00:52 +00:00
rescan ( new ArrayList < > ( ) , new CalculationContext ( baritone ) ) ;
}
2018-08-28 18:43:28 +00:00
}
2022-12-11 02:25:57 +00:00
private BlockOptionalMetaLookup filterFilter ( ) {
if ( this . filter = = null ) {
return null ;
}
if ( ! Baritone . settings ( ) . allowBreak . value ) {
BlockOptionalMetaLookup f = new BlockOptionalMetaLookup ( this . filter . blocks ( )
2023-01-15 09:02:52 +00:00
. stream ( )
. filter ( e - > Baritone . settings ( ) . allowBreakAnyway . value . contains ( e . getBlock ( ) ) )
. toArray ( BlockOptionalMeta [ ] : : new ) ) ;
2022-12-11 02:25:57 +00:00
if ( f . blocks ( ) . isEmpty ( ) ) {
logDirect ( " Unable to mine when allowBreak is false and target block is not in allowBreakAnyway! " ) ;
return null ;
}
return f ;
}
return filter ;
}
2018-08-28 18:28:36 +00:00
}