2018-12-26 05:07:17 +00:00
/ *
* This file is part of Baritone .
*
* Baritone is free software : you can redistribute it and / or modify
* it under the terms of the GNU Lesser General Public License as published by
* 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
* GNU Lesser General Public License for more details .
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone . If not , see < https : //www.gnu.org/licenses/>.
* /
package baritone.process ;
import baritone.Baritone ;
import baritone.api.pathing.goals.Goal ;
import baritone.api.pathing.goals.GoalBlock ;
import baritone.api.pathing.goals.GoalComposite ;
import baritone.api.pathing.goals.GoalGetToBlock ;
2019-01-16 04:07:06 +00:00
import baritone.api.process.IBuilderProcess ;
2018-12-26 05:07:17 +00:00
import baritone.api.process.PathingCommand ;
import baritone.api.process.PathingCommandType ;
2019-12-19 18:03:02 +00:00
import baritone.api.schematic.FillSchematic ;
2019-10-11 23:15:14 +00:00
import baritone.api.schematic.ISchematic ;
2019-12-24 23:20:00 +00:00
import baritone.api.schematic.IStaticSchematic ;
import baritone.api.schematic.format.ISchematicFormat ;
2019-11-24 19:11:21 +00:00
import baritone.api.utils.BetterBlockPos ;
import baritone.api.utils.RayTraceUtils ;
import baritone.api.utils.Rotation ;
import baritone.api.utils.RotationUtils ;
2019-01-09 04:45:02 +00:00
import baritone.api.utils.input.Input ;
2018-12-26 05:07:17 +00:00
import baritone.pathing.movement.CalculationContext ;
2019-02-07 00:22:40 +00:00
import baritone.pathing.movement.Movement ;
2019-01-09 04:45:02 +00:00
import baritone.pathing.movement.MovementHelper ;
2018-12-26 05:07:17 +00:00
import baritone.utils.BaritoneProcessHelper ;
2019-02-07 00:22:40 +00:00
import baritone.utils.BlockStateInterface ;
2020-02-29 16:28:18 +00:00
import baritone.utils.NotificationHelper ;
2018-12-26 05:07:17 +00:00
import baritone.utils.PathingCommandContext ;
2019-08-20 18:23:23 +00:00
import baritone.utils.schematic.MapArtSchematic ;
2019-12-24 23:20:00 +00:00
import baritone.utils.schematic.SchematicSystem ;
2019-07-22 00:54:02 +00:00
import baritone.utils.schematic.schematica.SchematicaHelper ;
2019-04-29 21:55:14 +00:00
import it.unimi.dsi.fastutil.longs.LongOpenHashSet ;
2019-06-11 01:25:20 +00:00
import net.minecraft.block.AirBlock ;
import net.minecraft.block.BlockState ;
import net.minecraft.block.Blocks ;
import net.minecraft.block.FlowingFluidBlock ;
import net.minecraft.item.BlockItem ;
2019-03-14 03:09:08 +00:00
import net.minecraft.item.BlockItemUseContext ;
2018-12-26 05:07:17 +00:00
import net.minecraft.item.ItemStack ;
2019-03-14 03:09:08 +00:00
import net.minecraft.item.ItemUseContext ;
2019-06-10 19:43:02 +00:00
import net.minecraft.util.Direction ;
2019-06-11 01:25:20 +00:00
import net.minecraft.util.Hand ;
2019-01-09 04:45:02 +00:00
import net.minecraft.util.Tuple ;
2019-02-07 00:22:40 +00:00
import net.minecraft.util.math.* ;
2019-03-14 03:09:08 +00:00
import net.minecraft.util.math.shapes.VoxelShape ;
2018-12-26 05:07:17 +00:00
import java.io.File ;
2018-12-27 18:06:10 +00:00
import java.io.FileInputStream ;
2019-01-09 04:45:02 +00:00
import java.util.* ;
2021-01-15 11:52:25 +00:00
import java.util.stream.Collectors ;
2018-12-26 05:07:17 +00:00
import static baritone.api.pathing.movement.ActionCosts.COST_INF ;
2019-05-20 05:53:09 +00:00
public final class BuilderProcess extends BaritoneProcessHelper implements IBuilderProcess {
2019-01-16 04:07:06 +00:00
2018-12-26 05:07:17 +00:00
private HashSet < BetterBlockPos > incorrectPositions ;
2019-04-29 21:55:14 +00:00
private LongOpenHashSet observedCompleted ; // positions that are completed even if they're out of render distance and we can't make sure right now
2018-12-26 05:07:17 +00:00
private String name ;
2019-04-11 22:17:26 +00:00
private ISchematic realSchematic ;
2018-12-26 05:07:17 +00:00
private ISchematic schematic ;
private Vec3i origin ;
2019-02-07 00:22:40 +00:00
private int ticks ;
2019-03-28 00:32:02 +00:00
private boolean paused ;
2019-04-11 22:17:26 +00:00
private int layer ;
2019-11-24 19:11:21 +00:00
private int numRepeats ;
2019-10-07 00:02:41 +00:00
private List < BlockState > approxPlaceable ;
2018-12-26 05:07:17 +00:00
2019-04-03 05:40:33 +00:00
public BuilderProcess ( Baritone baritone ) {
super ( baritone ) ;
}
2018-12-26 05:07:17 +00:00
2019-01-16 04:07:06 +00:00
@Override
public void build ( String name , ISchematic schematic , Vec3i origin ) {
this . name = name ;
this . schematic = schematic ;
2019-04-11 22:17:26 +00:00
this . realSchematic = null ;
2019-09-15 18:37:09 +00:00
int x = origin . getX ( ) ;
int y = origin . getY ( ) ;
int z = origin . getZ ( ) ;
if ( Baritone . settings ( ) . schematicOrientationX . value ) {
x + = schematic . widthX ( ) ;
}
if ( Baritone . settings ( ) . schematicOrientationY . value ) {
y + = schematic . heightY ( ) ;
}
if ( Baritone . settings ( ) . schematicOrientationZ . value ) {
z + = schematic . lengthZ ( ) ;
}
this . origin = new Vec3i ( x , y , z ) ;
2019-03-28 00:32:02 +00:00
this . paused = false ;
2020-08-06 06:23:13 +00:00
this . layer = Baritone . settings ( ) . startAtLayer . value ;
2019-11-24 19:11:21 +00:00
this . numRepeats = 0 ;
2019-04-29 21:55:14 +00:00
this . observedCompleted = new LongOpenHashSet ( ) ;
2019-03-28 00:32:02 +00:00
}
public void resume ( ) {
paused = false ;
2019-01-16 04:07:06 +00:00
}
2018-12-27 18:06:10 +00:00
2019-04-13 15:36:14 +00:00
public void pause ( ) {
paused = true ;
}
2019-08-30 18:55:25 +00:00
@Override
public boolean isPaused ( ) {
return paused ;
}
2019-01-16 04:07:06 +00:00
@Override
public boolean build ( String name , File schematic , Vec3i origin ) {
2019-12-24 23:20:00 +00:00
Optional < ISchematicFormat > format = SchematicSystem . INSTANCE . getByFile ( schematic ) ;
2019-12-18 16:24:43 +00:00
if ( ! format . isPresent ( ) ) {
2018-12-26 05:07:17 +00:00
return false ;
}
2019-12-18 16:24:43 +00:00
ISchematic parsed ;
try {
2019-12-27 07:14:31 +00:00
parsed = format . get ( ) . parse ( new FileInputStream ( schematic ) ) ;
2019-12-18 16:24:43 +00:00
} catch ( Exception e ) {
e . printStackTrace ( ) ;
2018-12-26 05:07:17 +00:00
return false ;
}
2019-12-18 16:24:43 +00:00
if ( Baritone . settings ( ) . mapArtMode . value ) {
2019-12-24 23:20:00 +00:00
parsed = new MapArtSchematic ( ( IStaticSchematic ) parsed ) ;
2019-12-18 16:24:43 +00:00
}
build ( name , parsed , origin ) ;
2018-12-26 05:07:17 +00:00
return true ;
}
2019-07-22 00:54:02 +00:00
@Override
public void buildOpenSchematic ( ) {
if ( SchematicaHelper . isSchematicaPresent ( ) ) {
2019-12-25 07:35:10 +00:00
Optional < Tuple < IStaticSchematic , BlockPos > > schematic = SchematicaHelper . getOpenSchematic ( ) ;
2019-07-22 00:54:02 +00:00
if ( schematic . isPresent ( ) ) {
2020-01-01 01:40:14 +00:00
IStaticSchematic s = schematic . get ( ) . getA ( ) ;
2019-12-25 07:35:10 +00:00
this . build (
2020-01-01 01:40:14 +00:00
schematic . get ( ) . getA ( ) . toString ( ) ,
2019-12-25 07:35:10 +00:00
Baritone . settings ( ) . mapArtMode . value ? new MapArtSchematic ( s ) : s ,
2020-01-01 01:40:14 +00:00
schematic . get ( ) . getB ( )
2019-12-25 07:35:10 +00:00
) ;
2019-07-22 00:54:02 +00:00
} else {
logDirect ( " No schematic currently open " ) ;
}
} else {
logDirect ( " Schematica is not present " ) ;
}
}
2019-02-28 23:26:09 +00:00
public void clearArea ( BlockPos corner1 , BlockPos corner2 ) {
BlockPos origin = new BlockPos ( Math . min ( corner1 . getX ( ) , corner2 . getX ( ) ) , Math . min ( corner1 . getY ( ) , corner2 . getY ( ) ) , Math . min ( corner1 . getZ ( ) , corner2 . getZ ( ) ) ) ;
int widthX = Math . abs ( corner1 . getX ( ) - corner2 . getX ( ) ) + 1 ;
int heightY = Math . abs ( corner1 . getY ( ) - corner2 . getY ( ) ) + 1 ;
int lengthZ = Math . abs ( corner1 . getZ ( ) - corner2 . getZ ( ) ) + 1 ;
2019-09-01 22:53:13 +00:00
build ( " clear area " , new FillSchematic ( widthX , heightY , lengthZ , Blocks . AIR . getDefaultState ( ) ) , origin ) ;
2019-02-28 23:26:09 +00:00
}
2019-09-06 10:59:10 +00:00
@Override
2019-10-07 00:02:41 +00:00
public List < BlockState > getApproxPlaceable ( ) {
2019-09-06 10:59:10 +00:00
return new ArrayList < > ( approxPlaceable ) ;
2019-02-28 23:26:09 +00:00
}
2018-12-26 05:07:17 +00:00
@Override
public boolean isActive ( ) {
return schematic ! = null ;
}
2019-10-07 00:02:41 +00:00
public BlockState placeAt ( int x , int y , int z , BlockState current ) {
2019-01-13 03:51:21 +00:00
if ( ! isActive ( ) ) {
return null ;
}
2019-09-02 10:00:21 +00:00
if ( ! schematic . inSchematic ( x - origin . getX ( ) , y - origin . getY ( ) , z - origin . getZ ( ) , current ) ) {
2019-01-13 03:51:21 +00:00
return null ;
}
2019-10-07 00:02:41 +00:00
BlockState state = schematic . desiredState ( x - origin . getX ( ) , y - origin . getY ( ) , z - origin . getZ ( ) , current , this . approxPlaceable ) ;
2019-06-11 01:25:20 +00:00
if ( state . getBlock ( ) instanceof AirBlock ) {
2019-01-13 03:51:21 +00:00
return null ;
}
2019-01-15 03:49:26 +00:00
return state ;
2019-01-13 03:51:21 +00:00
}
2019-04-29 21:59:25 +00:00
private Optional < Tuple < BetterBlockPos , Rotation > > toBreakNearPlayer ( BuilderCalculationContext bcc ) {
2019-01-09 04:45:02 +00:00
BetterBlockPos center = ctx . playerFeet ( ) ;
2019-04-29 23:02:44 +00:00
BetterBlockPos pathStart = baritone . getPathingBehavior ( ) . pathStart ( ) ;
2019-01-09 04:45:02 +00:00
for ( int dx = - 5 ; dx < = 5 ; dx + + ) {
2019-04-29 23:02:44 +00:00
for ( int dy = Baritone . settings ( ) . breakFromAbove . value ? - 1 : 0 ; dy < = 5 ; dy + + ) {
2019-01-09 04:45:02 +00:00
for ( int dz = - 5 ; dz < = 5 ; dz + + ) {
int x = center . x + dx ;
int y = center . y + dy ;
int z = center . z + dz ;
2019-04-29 23:02:44 +00:00
if ( dy = = - 1 & & x = = pathStart . x & & z = = pathStart . z ) {
continue ; // dont mine what we're supported by, but not directly standing on
}
2019-10-07 00:02:41 +00:00
BlockState desired = bcc . getSchematic ( x , y , z , bcc . bsi . get0 ( x , y , z ) ) ;
2019-01-09 04:45:02 +00:00
if ( desired = = null ) {
continue ; // irrelevant
}
2019-06-10 19:43:02 +00:00
BlockState curr = bcc . bsi . get0 ( x , y , z ) ;
2020-03-08 02:37:47 +00:00
if ( ! ( curr . getBlock ( ) instanceof AirBlock ) & & ! ( curr . getBlock ( ) = = Blocks . WATER | | curr . getBlock ( ) = = Blocks . LAVA ) & & ! valid ( curr , desired , false ) ) {
2019-01-09 04:45:02 +00:00
BetterBlockPos pos = new BetterBlockPos ( x , y , z ) ;
Optional < Rotation > rot = RotationUtils . reachable ( ctx . player ( ) , pos , ctx . playerController ( ) . getBlockReachDistance ( ) ) ;
if ( rot . isPresent ( ) ) {
return Optional . of ( new Tuple < > ( pos , rot . get ( ) ) ) ;
}
}
}
}
}
return Optional . empty ( ) ;
}
2019-09-02 10:00:21 +00:00
public static class Placement {
2019-09-19 20:40:46 +00:00
2019-04-05 04:51:02 +00:00
private final int hotbarSelection ;
private final BlockPos placeAgainst ;
2019-06-10 19:43:02 +00:00
private final Direction side ;
2019-04-05 04:51:02 +00:00
private final Rotation rot ;
2019-02-07 00:22:40 +00:00
2019-06-10 19:43:02 +00:00
public Placement ( int hotbarSelection , BlockPos placeAgainst , Direction side , Rotation rot ) {
2019-02-07 00:22:40 +00:00
this . hotbarSelection = hotbarSelection ;
this . placeAgainst = placeAgainst ;
this . side = side ;
this . rot = rot ;
}
}
2019-06-10 19:43:02 +00:00
private Optional < Placement > searchForPlacables ( BuilderCalculationContext bcc , List < BlockState > desirableOnHotbar ) {
2019-02-07 00:22:40 +00:00
BetterBlockPos center = ctx . playerFeet ( ) ;
for ( int dx = - 5 ; dx < = 5 ; dx + + ) {
for ( int dy = - 5 ; dy < = 1 ; dy + + ) {
for ( int dz = - 5 ; dz < = 5 ; dz + + ) {
int x = center . x + dx ;
int y = center . y + dy ;
int z = center . z + dz ;
2019-10-07 00:02:41 +00:00
BlockState desired = bcc . getSchematic ( x , y , z , bcc . bsi . get0 ( x , y , z ) ) ;
2019-02-07 00:22:40 +00:00
if ( desired = = null ) {
continue ; // irrelevant
}
2019-06-10 19:43:02 +00:00
BlockState curr = bcc . bsi . get0 ( x , y , z ) ;
2020-03-07 23:34:27 +00:00
if ( MovementHelper . isReplaceable ( x , y , z , curr , bcc . bsi ) & & ! valid ( curr , desired , false ) ) {
2019-06-11 01:25:20 +00:00
if ( dy = = 1 & & bcc . bsi . get0 ( x , y + 1 , z ) . getBlock ( ) instanceof AirBlock ) {
2019-02-07 00:22:40 +00:00
continue ;
}
2019-02-07 21:59:37 +00:00
desirableOnHotbar . add ( desired ) ;
2019-02-07 00:22:40 +00:00
Optional < Placement > opt = possibleToPlace ( desired , x , y , z , bcc . bsi ) ;
if ( opt . isPresent ( ) ) {
return opt ;
}
}
}
}
}
return Optional . empty ( ) ;
}
2019-06-10 19:43:02 +00:00
public boolean placementPlausible ( BlockPos pos , BlockState state ) {
2019-03-14 03:09:08 +00:00
VoxelShape voxelshape = state . getCollisionShape ( ctx . world ( ) , pos ) ;
return voxelshape . isEmpty ( ) | | ctx . world ( ) . checkNoEntityCollision ( null , voxelshape . withOffset ( pos . getX ( ) , pos . getY ( ) , pos . getZ ( ) ) ) ;
}
2019-06-10 19:43:02 +00:00
private Optional < Placement > possibleToPlace ( BlockState toPlace , int x , int y , int z , BlockStateInterface bsi ) {
for ( Direction against : Direction . values ( ) ) {
2019-02-07 00:22:40 +00:00
BetterBlockPos placeAgainstPos = new BetterBlockPos ( x , y , z ) . offset ( against ) ;
2019-06-10 19:43:02 +00:00
BlockState placeAgainstState = bsi . get0 ( placeAgainstPos ) ;
2019-09-06 10:59:10 +00:00
if ( MovementHelper . isReplaceable ( placeAgainstPos . x , placeAgainstPos . y , placeAgainstPos . z , placeAgainstState , bsi ) ) {
2019-02-07 00:22:40 +00:00
continue ;
}
2019-03-14 03:09:08 +00:00
if ( ! toPlace . isValidPosition ( ctx . world ( ) , new BetterBlockPos ( x , y , z ) ) ) {
continue ;
}
if ( ! placementPlausible ( new BetterBlockPos ( x , y , z ) , toPlace ) ) {
2019-02-07 00:22:40 +00:00
continue ;
}
2019-03-14 03:09:08 +00:00
AxisAlignedBB aabb = placeAgainstState . getShape ( ctx . world ( ) , placeAgainstPos ) . getBoundingBox ( ) ;
2019-02-07 00:22:40 +00:00
for ( Vec3d placementMultiplier : aabbSideMultipliers ( against ) ) {
double placeX = placeAgainstPos . x + aabb . minX * placementMultiplier . x + aabb . maxX * ( 1 - placementMultiplier . x ) ;
double placeY = placeAgainstPos . y + aabb . minY * placementMultiplier . y + aabb . maxY * ( 1 - placementMultiplier . y ) ;
double placeZ = placeAgainstPos . z + aabb . minZ * placementMultiplier . z + aabb . maxZ * ( 1 - placementMultiplier . z ) ;
2020-02-25 03:27:11 +00:00
Rotation rot = RotationUtils . calcRotationFromVec3d ( RayTraceUtils . inferSneakingEyePosition ( ctx . player ( ) ) , new Vec3d ( placeX , placeY , placeZ ) , ctx . playerRotations ( ) ) ;
RayTraceResult result = RayTraceUtils . rayTraceTowards ( ctx . player ( ) , rot , ctx . playerController ( ) . getBlockReachDistance ( ) , true ) ;
2019-06-11 01:25:20 +00:00
if ( result ! = null & & result . getType ( ) = = RayTraceResult . Type . BLOCK & & ( ( BlockRayTraceResult ) result ) . getPos ( ) . equals ( placeAgainstPos ) & & ( ( BlockRayTraceResult ) result ) . getFace ( ) = = against . getOpposite ( ) ) {
2019-02-07 00:22:40 +00:00
OptionalInt hotbar = hasAnyItemThatWouldPlace ( toPlace , result , rot ) ;
if ( hotbar . isPresent ( ) ) {
return Optional . of ( new Placement ( hotbar . getAsInt ( ) , placeAgainstPos , against . getOpposite ( ) , rot ) ) ;
}
}
}
}
return Optional . empty ( ) ;
}
2019-06-10 19:43:02 +00:00
private OptionalInt hasAnyItemThatWouldPlace ( BlockState desired , RayTraceResult result , Rotation rot ) {
2019-02-07 00:22:40 +00:00
for ( int i = 0 ; i < 9 ; i + + ) {
ItemStack stack = ctx . player ( ) . inventory . mainInventory . get ( i ) ;
2019-06-11 01:25:20 +00:00
if ( stack . isEmpty ( ) | | ! ( stack . getItem ( ) instanceof BlockItem ) ) {
2019-02-07 00:22:40 +00:00
continue ;
}
float originalYaw = ctx . player ( ) . rotationYaw ;
float originalPitch = ctx . player ( ) . rotationPitch ;
// the state depends on the facing of the player sometimes
ctx . player ( ) . rotationYaw = rot . getYaw ( ) ;
ctx . player ( ) . rotationPitch = rot . getPitch ( ) ;
2019-03-14 03:09:08 +00:00
BlockItemUseContext meme = new BlockItemUseContext ( new ItemUseContext (
2019-06-11 01:25:20 +00:00
ctx . world ( ) ,
2019-03-14 03:09:08 +00:00
ctx . player ( ) ,
2019-06-11 01:25:20 +00:00
Hand . MAIN_HAND ,
2019-03-14 03:09:08 +00:00
stack ,
2019-06-11 01:25:20 +00:00
( BlockRayTraceResult ) result
) { } ) ; // that {} gives us access to a protected constructor lmfao
BlockState wouldBePlaced = ( ( BlockItem ) stack . getItem ( ) ) . getBlock ( ) . getStateForPlacement ( meme ) ;
2019-02-07 00:22:40 +00:00
ctx . player ( ) . rotationYaw = originalYaw ;
ctx . player ( ) . rotationPitch = originalPitch ;
2019-03-14 03:09:08 +00:00
if ( wouldBePlaced = = null ) {
continue ;
}
if ( ! meme . canPlace ( ) ) {
continue ;
}
2020-03-07 23:34:27 +00:00
if ( valid ( wouldBePlaced , desired , true ) ) {
2019-02-07 00:22:40 +00:00
return OptionalInt . of ( i ) ;
}
}
return OptionalInt . empty ( ) ;
}
2019-06-10 19:43:02 +00:00
private static Vec3d [ ] aabbSideMultipliers ( Direction side ) {
2019-02-07 00:22:40 +00:00
switch ( side ) {
case UP :
2019-02-21 22:24:23 +00:00
return new Vec3d [ ] { new Vec3d ( 0 . 5 , 1 , 0 . 5 ) , new Vec3d ( 0 . 1 , 1 , 0 . 5 ) , new Vec3d ( 0 . 9 , 1 , 0 . 5 ) , new Vec3d ( 0 . 5 , 1 , 0 . 1 ) , new Vec3d ( 0 . 5 , 1 , 0 . 9 ) } ;
2019-02-07 00:22:40 +00:00
case DOWN :
2019-02-21 22:24:23 +00:00
return new Vec3d [ ] { new Vec3d ( 0 . 5 , 0 , 0 . 5 ) , new Vec3d ( 0 . 1 , 0 , 0 . 5 ) , new Vec3d ( 0 . 9 , 0 , 0 . 5 ) , new Vec3d ( 0 . 5 , 0 , 0 . 1 ) , new Vec3d ( 0 . 5 , 0 , 0 . 9 ) } ;
2019-02-07 00:22:40 +00:00
case NORTH :
case SOUTH :
case EAST :
case WEST :
double x = side . getXOffset ( ) = = 0 ? 0 . 5 : ( 1 + side . getXOffset ( ) ) / 2D ;
double z = side . getZOffset ( ) = = 0 ? 0 . 5 : ( 1 + side . getZOffset ( ) ) / 2D ;
return new Vec3d [ ] { new Vec3d ( x , 0 . 25 , z ) , new Vec3d ( x , 0 . 75 , z ) } ;
default : // null
2019-04-04 06:19:32 +00:00
throw new IllegalStateException ( ) ;
2019-02-07 00:22:40 +00:00
}
}
2018-12-26 05:07:17 +00:00
@Override
public PathingCommand onTick ( boolean calcFailed , boolean isSafeToCancel ) {
2019-09-06 10:59:10 +00:00
approxPlaceable = approxPlaceable ( 36 ) ;
2019-04-11 23:36:20 +00:00
if ( baritone . getInputOverrideHandler ( ) . isInputForcedDown ( Input . CLICK_LEFT ) ) {
ticks = 5 ;
} else {
ticks - - ;
}
2019-02-28 23:26:09 +00:00
baritone . getInputOverrideHandler ( ) . clearAllKeys ( ) ;
2019-03-28 00:32:02 +00:00
if ( paused ) {
2019-04-17 05:43:33 +00:00
return new PathingCommand ( null , PathingCommandType . CANCEL_AND_SET_GOAL ) ;
2019-03-28 00:32:02 +00:00
}
2019-04-11 22:17:26 +00:00
if ( Baritone . settings ( ) . buildInLayers . value ) {
if ( realSchematic = = null ) {
realSchematic = schematic ;
}
2019-05-06 21:07:46 +00:00
ISchematic realSchematic = this . realSchematic ; // wrap this properly, dont just have the inner class refer to the builderprocess.this
2019-05-14 23:03:11 +00:00
int minYInclusive ;
int maxYInclusive ;
// layer = 0 should be nothing
// layer = realSchematic.heightY() should be everything
if ( Baritone . settings ( ) . layerOrder . value ) { // top to bottom
maxYInclusive = realSchematic . heightY ( ) - 1 ;
minYInclusive = realSchematic . heightY ( ) - layer ;
} else {
maxYInclusive = layer - 1 ;
minYInclusive = 0 ;
}
2019-04-11 22:17:26 +00:00
schematic = new ISchematic ( ) {
@Override
2019-10-07 00:02:41 +00:00
public BlockState desiredState ( int x , int y , int z , BlockState current , List < BlockState > approxPlaceable ) {
2019-09-06 10:59:10 +00:00
return realSchematic . desiredState ( x , y , z , current , BuilderProcess . this . approxPlaceable ) ;
2019-04-11 22:17:26 +00:00
}
2019-05-14 23:03:11 +00:00
@Override
2019-10-07 00:02:41 +00:00
public boolean inSchematic ( int x , int y , int z , BlockState currentState ) {
2019-10-01 21:29:19 +00:00
return ISchematic . super . inSchematic ( x , y , z , currentState ) & & y > = minYInclusive & & y < = maxYInclusive & & realSchematic . inSchematic ( x , y , z , currentState ) ;
2019-05-14 23:03:11 +00:00
}
2019-04-11 22:17:26 +00:00
@Override
public int widthX ( ) {
return realSchematic . widthX ( ) ;
}
@Override
public int heightY ( ) {
2019-05-14 23:03:11 +00:00
return realSchematic . heightY ( ) ;
2019-04-11 22:17:26 +00:00
}
@Override
public int lengthZ ( ) {
return realSchematic . lengthZ ( ) ;
}
} ;
}
2019-01-13 03:51:21 +00:00
BuilderCalculationContext bcc = new BuilderCalculationContext ( ) ;
2019-01-09 04:45:02 +00:00
if ( ! recalc ( bcc ) ) {
2019-04-11 22:17:26 +00:00
if ( Baritone . settings ( ) . buildInLayers . value & & layer < realSchematic . heightY ( ) ) {
logDirect ( " Starting layer " + layer ) ;
layer + + ;
return onTick ( calcFailed , isSafeToCancel ) ;
}
2019-05-06 21:01:01 +00:00
Vec3i repeat = Baritone . settings ( ) . buildRepeat . value ;
2019-11-24 19:11:21 +00:00
int max = Baritone . settings ( ) . buildRepeatCount . value ;
numRepeats + + ;
if ( repeat . equals ( new Vec3i ( 0 , 0 , 0 ) ) | | ( max ! = - 1 & & numRepeats > = max ) ) {
2019-04-11 23:36:20 +00:00
logDirect ( " Done building " ) ;
2020-02-29 16:28:18 +00:00
if ( Baritone . settings ( ) . desktopNotifications . value & & Baritone . settings ( ) . notificationOnBuildFinished . value ) {
NotificationHelper . notify ( " Done building " , false ) ;
}
2019-04-11 23:36:20 +00:00
onLostControl ( ) ;
return null ;
}
// build repeat time
layer = 0 ;
2019-05-06 21:01:01 +00:00
origin = new BlockPos ( origin ) . add ( repeat ) ;
logDirect ( " Repeating build in vector " + repeat + " , new origin is " + origin ) ;
2019-04-24 00:42:13 +00:00
return onTick ( calcFailed , isSafeToCancel ) ;
2019-01-09 04:45:02 +00:00
}
2019-08-23 07:21:29 +00:00
if ( Baritone . settings ( ) . distanceTrim . value ) {
trim ( ) ;
}
2019-04-11 23:36:20 +00:00
2019-01-09 04:45:02 +00:00
Optional < Tuple < BetterBlockPos , Rotation > > toBreak = toBreakNearPlayer ( bcc ) ;
if ( toBreak . isPresent ( ) & & isSafeToCancel & & ctx . player ( ) . onGround ) {
// we'd like to pause to break this block
// only change look direction if it's safe (don't want to fuck up an in progress parkour for example
2019-03-14 03:09:08 +00:00
Rotation rot = toBreak . get ( ) . getB ( ) ;
BetterBlockPos pos = toBreak . get ( ) . getA ( ) ;
2019-01-09 04:45:02 +00:00
baritone . getLookBehavior ( ) . updateTarget ( rot , true ) ;
MovementHelper . switchToBestToolFor ( ctx , bcc . get ( pos ) ) ;
2019-02-21 22:24:23 +00:00
if ( ctx . player ( ) . isSneaking ( ) ) {
// really horrible bug where a block is visible for breaking while sneaking but not otherwise
// so you can't see it, it goes to place something else, sneaks, then the next tick it tries to break
// and is unable since it's unsneaked in the intermediary tick
baritone . getInputOverrideHandler ( ) . setInputForceState ( Input . SNEAK , true ) ;
}
2019-04-16 00:12:20 +00:00
if ( ctx . isLookingAt ( pos ) | | ctx . playerRotations ( ) . isReallyCloseTo ( rot ) ) {
2019-01-09 04:45:02 +00:00
baritone . getInputOverrideHandler ( ) . setInputForceState ( Input . CLICK_LEFT , true ) ;
}
2019-04-17 06:19:55 +00:00
return new PathingCommand ( null , PathingCommandType . CANCEL_AND_SET_GOAL ) ;
2019-01-09 04:45:02 +00:00
}
2019-06-10 19:43:02 +00:00
List < BlockState > desirableOnHotbar = new ArrayList < > ( ) ;
2019-02-07 21:59:37 +00:00
Optional < Placement > toPlace = searchForPlacables ( bcc , desirableOnHotbar ) ;
2019-02-07 00:22:40 +00:00
if ( toPlace . isPresent ( ) & & isSafeToCancel & & ctx . player ( ) . onGround & & ticks < = 0 ) {
Rotation rot = toPlace . get ( ) . rot ;
baritone . getLookBehavior ( ) . updateTarget ( rot , true ) ;
ctx . player ( ) . inventory . currentItem = toPlace . get ( ) . hotbarSelection ;
baritone . getInputOverrideHandler ( ) . setInputForceState ( Input . SNEAK , true ) ;
2019-06-11 01:25:20 +00:00
if ( ( ctx . isLookingAt ( toPlace . get ( ) . placeAgainst ) & & ( ( BlockRayTraceResult ) ctx . objectMouseOver ( ) ) . getFace ( ) . equals ( toPlace . get ( ) . side ) ) | | ctx . playerRotations ( ) . isReallyCloseTo ( rot ) ) {
2019-02-07 00:22:40 +00:00
baritone . getInputOverrideHandler ( ) . setInputForceState ( Input . CLICK_RIGHT , true ) ;
}
2019-04-17 06:19:55 +00:00
return new PathingCommand ( null , PathingCommandType . CANCEL_AND_SET_GOAL ) ;
2019-02-07 00:22:40 +00:00
}
2019-01-09 04:45:02 +00:00
2019-03-12 06:29:39 +00:00
if ( Baritone . settings ( ) . allowInventory . value ) {
2019-02-07 21:59:37 +00:00
ArrayList < Integer > usefulSlots = new ArrayList < > ( ) ;
2019-06-10 19:43:02 +00:00
List < BlockState > noValidHotbarOption = new ArrayList < > ( ) ;
2019-02-07 21:59:37 +00:00
outer :
2019-06-10 19:43:02 +00:00
for ( BlockState desired : desirableOnHotbar ) {
2019-02-07 21:59:37 +00:00
for ( int i = 0 ; i < 9 ; i + + ) {
2020-03-07 23:34:27 +00:00
if ( valid ( approxPlaceable . get ( i ) , desired , true ) ) {
2019-02-07 21:59:37 +00:00
usefulSlots . add ( i ) ;
continue outer ;
}
}
noValidHotbarOption . add ( desired ) ;
}
outer :
for ( int i = 9 ; i < 36 ; i + + ) {
2019-06-10 19:43:02 +00:00
for ( BlockState desired : noValidHotbarOption ) {
2020-03-07 23:34:27 +00:00
if ( valid ( approxPlaceable . get ( i ) , desired , true ) ) {
2019-02-07 21:59:37 +00:00
baritone . getInventoryBehavior ( ) . attemptToPutOnHotbar ( i , usefulSlots : : contains ) ;
break outer ;
}
}
}
}
2019-09-06 10:59:10 +00:00
Goal goal = assemble ( bcc , approxPlaceable . subList ( 0 , 9 ) ) ;
2019-01-09 23:07:06 +00:00
if ( goal = = null ) {
2021-01-15 11:52:25 +00:00
goal = assemble ( bcc , approxPlaceable , true ) ; // we're far away, so assume that we have our whole inventory to recalculate placeable properly
2019-02-07 21:59:37 +00:00
if ( goal = = null ) {
2020-11-12 01:53:11 +00:00
if ( Baritone . settings ( ) . skipFailedLayers . value & & Baritone . settings ( ) . buildInLayers . value & & layer < realSchematic . heightY ( ) ) {
logDirect ( " Skipping layer that I cannot construct! Layer # " + layer ) ;
layer + + ;
return onTick ( calcFailed , isSafeToCancel ) ;
}
2019-03-28 00:32:02 +00:00
logDirect ( " Unable to do it. Pausing. resume to resume, cancel to cancel " ) ;
paused = true ;
return new PathingCommand ( null , PathingCommandType . REQUEST_PAUSE ) ;
2019-02-07 21:59:37 +00:00
}
2019-01-09 04:45:02 +00:00
}
2019-01-09 23:07:06 +00:00
return new PathingCommandContext ( goal , PathingCommandType . FORCE_REVALIDATE_GOAL_AND_PATH , bcc ) ;
2019-01-09 04:45:02 +00:00
}
2019-04-29 21:59:25 +00:00
private boolean recalc ( BuilderCalculationContext bcc ) {
2019-01-09 04:45:02 +00:00
if ( incorrectPositions = = null ) {
incorrectPositions = new HashSet < > ( ) ;
fullRecalc ( bcc ) ;
if ( incorrectPositions . isEmpty ( ) ) {
return false ;
}
}
recalcNearby ( bcc ) ;
if ( incorrectPositions . isEmpty ( ) ) {
fullRecalc ( bcc ) ;
}
return ! incorrectPositions . isEmpty ( ) ;
}
2019-05-26 19:14:08 +00:00
private void trim ( ) {
2019-02-20 06:50:03 +00:00
HashSet < BetterBlockPos > copy = new HashSet < > ( incorrectPositions ) ;
2019-06-11 01:25:20 +00:00
copy . removeIf ( pos - > pos . distanceSq ( new BlockPos ( ctx . player ( ) ) ) > 200 ) ;
2019-02-20 06:50:03 +00:00
if ( ! copy . isEmpty ( ) ) {
incorrectPositions = copy ;
}
}
2019-04-29 21:59:25 +00:00
private void recalcNearby ( BuilderCalculationContext bcc ) {
2019-01-09 04:45:02 +00:00
BetterBlockPos center = ctx . playerFeet ( ) ;
2019-09-17 06:17:20 +00:00
int radius = Baritone . settings ( ) . builderTickScanRadius . value ;
for ( int dx = - radius ; dx < = radius ; dx + + ) {
for ( int dy = - radius ; dy < = radius ; dy + + ) {
for ( int dz = - radius ; dz < = radius ; dz + + ) {
2019-01-09 04:45:02 +00:00
int x = center . x + dx ;
int y = center . y + dy ;
int z = center . z + dz ;
2019-10-07 00:02:41 +00:00
BlockState desired = bcc . getSchematic ( x , y , z , bcc . bsi . get0 ( x , y , z ) ) ;
2019-01-09 04:45:02 +00:00
if ( desired ! = null ) {
// we care about this position
2019-04-29 21:55:14 +00:00
BetterBlockPos pos = new BetterBlockPos ( x , y , z ) ;
2020-03-07 23:34:27 +00:00
if ( valid ( bcc . bsi . get0 ( x , y , z ) , desired , false ) ) {
2019-04-29 21:55:14 +00:00
incorrectPositions . remove ( pos ) ;
observedCompleted . add ( BetterBlockPos . longHash ( pos ) ) ;
2019-01-09 04:45:02 +00:00
} else {
2019-04-29 21:55:14 +00:00
incorrectPositions . add ( pos ) ;
2019-05-01 19:15:31 +00:00
observedCompleted . remove ( BetterBlockPos . longHash ( pos ) ) ;
2019-01-09 04:45:02 +00:00
}
}
}
}
}
}
2019-04-29 21:59:25 +00:00
private void fullRecalc ( BuilderCalculationContext bcc ) {
2019-01-09 04:45:02 +00:00
incorrectPositions = new HashSet < > ( ) ;
for ( int y = 0 ; y < schematic . heightY ( ) ; y + + ) {
for ( int z = 0 ; z < schematic . lengthZ ( ) ; z + + ) {
for ( int x = 0 ; x < schematic . widthX ( ) ; x + + ) {
2019-04-29 21:55:14 +00:00
int blockX = x + origin . getX ( ) ;
int blockY = y + origin . getY ( ) ;
int blockZ = z + origin . getZ ( ) ;
2019-10-07 00:02:41 +00:00
BlockState current = bcc . bsi . get0 ( blockX , blockY , blockZ ) ;
2019-09-02 10:00:21 +00:00
if ( ! schematic . inSchematic ( x , y , z , current ) ) {
continue ;
}
2019-04-29 21:55:14 +00:00
if ( bcc . bsi . worldContainsLoadedChunk ( blockX , blockZ ) ) { // check if its in render distance, not if its in cache
// we can directly observe this block, it is in render distance
2020-03-07 23:34:27 +00:00
if ( valid ( bcc . bsi . get0 ( blockX , blockY , blockZ ) , schematic . desiredState ( x , y , z , current , this . approxPlaceable ) , false ) ) {
2019-04-29 21:55:14 +00:00
observedCompleted . add ( BetterBlockPos . longHash ( blockX , blockY , blockZ ) ) ;
} else {
incorrectPositions . add ( new BetterBlockPos ( blockX , blockY , blockZ ) ) ;
2019-05-01 19:15:31 +00:00
observedCompleted . remove ( BetterBlockPos . longHash ( blockX , blockY , blockZ ) ) ;
2019-08-20 18:23:23 +00:00
if ( incorrectPositions . size ( ) > Baritone . settings ( ) . incorrectSize . value ) {
return ;
}
2019-04-29 21:55:14 +00:00
}
continue ;
}
// this is not in render distance
if ( ! observedCompleted . contains ( BetterBlockPos . longHash ( blockX , blockY , blockZ ) ) ) {
// and we've never seen this position be correct
// therefore mark as incorrect
incorrectPositions . add ( new BetterBlockPos ( blockX , blockY , blockZ ) ) ;
2019-08-20 18:23:23 +00:00
if ( incorrectPositions . size ( ) > Baritone . settings ( ) . incorrectSize . value ) {
return ;
}
2019-01-09 04:45:02 +00:00
}
}
}
}
2018-12-26 05:07:17 +00:00
}
2019-10-07 00:02:41 +00:00
private Goal assemble ( BuilderCalculationContext bcc , List < BlockState > approxPlaceable ) {
2021-01-15 11:52:25 +00:00
return assemble ( bcc , approxPlaceable , false ) ;
}
2021-01-30 03:49:11 +00:00
private Goal assemble ( BuilderCalculationContext bcc , List < BlockState > approxPlaceable , boolean logMissing ) {
2019-09-02 10:00:21 +00:00
List < BetterBlockPos > placeable = new ArrayList < > ( ) ;
2019-05-01 21:03:36 +00:00
List < BetterBlockPos > breakable = new ArrayList < > ( ) ;
List < BetterBlockPos > sourceLiquids = new ArrayList < > ( ) ;
2021-01-15 11:52:25 +00:00
List < BetterBlockPos > flowingLiquids = new ArrayList < > ( ) ;
2021-01-30 03:49:11 +00:00
Map < BlockState , Integer > missing = new HashMap < > ( ) ;
2019-05-01 21:03:36 +00:00
incorrectPositions . forEach ( pos - > {
2019-06-10 19:43:02 +00:00
BlockState state = bcc . bsi . get0 ( pos ) ;
2019-06-11 01:25:20 +00:00
if ( state . getBlock ( ) instanceof AirBlock ) {
2019-09-06 10:59:10 +00:00
if ( approxPlaceable . contains ( bcc . getSchematic ( pos . x , pos . y , pos . z , state ) ) ) {
2019-09-02 10:00:21 +00:00
placeable . add ( pos ) ;
2021-01-15 11:52:25 +00:00
} else {
2021-01-30 03:49:11 +00:00
BlockState desired = bcc . getSchematic ( pos . x , pos . y , pos . z , state ) ;
2021-01-15 11:52:25 +00:00
missing . put ( desired , 1 + missing . getOrDefault ( desired , 0 ) ) ;
2019-05-01 21:03:36 +00:00
}
} else {
2019-06-11 01:25:20 +00:00
if ( state . getBlock ( ) instanceof FlowingFluidBlock ) {
2019-05-01 21:03:36 +00:00
// if the block itself is JUST a liquid (i.e. not just a waterlogged block), we CANNOT break it
// TODO for 1.13 make sure that this only matches pure water, not waterlogged blocks
if ( ! MovementHelper . possiblyFlowing ( state ) ) {
// if it's a source block then we want to replace it with a throwaway
sourceLiquids . add ( pos ) ;
2021-01-15 11:52:25 +00:00
} else {
flowingLiquids . add ( pos ) ;
2019-05-01 21:03:36 +00:00
}
} else {
breakable . add ( pos ) ;
}
}
} ) ;
List < Goal > toBreak = new ArrayList < > ( ) ;
breakable . forEach ( pos - > toBreak . add ( breakGoal ( pos , bcc ) ) ) ;
List < Goal > toPlace = new ArrayList < > ( ) ;
2019-09-02 10:00:21 +00:00
placeable . forEach ( pos - > {
if ( ! placeable . contains ( pos . down ( ) ) & & ! placeable . contains ( pos . down ( 2 ) ) ) {
2019-05-01 21:03:36 +00:00
toPlace . add ( placementGoal ( pos , bcc ) ) ;
}
} ) ;
sourceLiquids . forEach ( pos - > toPlace . add ( new GoalBlock ( pos . up ( ) ) ) ) ;
2019-01-09 23:07:06 +00:00
2019-05-01 21:03:36 +00:00
if ( ! toPlace . isEmpty ( ) ) {
return new JankyGoalComposite ( new GoalComposite ( toPlace . toArray ( new Goal [ 0 ] ) ) , new GoalComposite ( toBreak . toArray ( new Goal [ 0 ] ) ) ) ;
2019-01-09 23:07:06 +00:00
}
2019-05-01 21:03:36 +00:00
if ( toBreak . isEmpty ( ) ) {
2021-01-15 11:52:25 +00:00
if ( logMissing & & ! missing . isEmpty ( ) ) {
logDirect ( " Missing materials for at least: " ) ;
logDirect ( missing . entrySet ( ) . stream ( )
2021-01-30 03:49:11 +00:00
. map ( e - > String . format ( " %sx %s " , e . getValue ( ) , e . getKey ( ) ) )
. collect ( Collectors . joining ( " \ n " ) ) ) ;
2021-01-15 11:52:25 +00:00
}
if ( logMissing & & ! flowingLiquids . isEmpty ( ) ) {
logDirect ( " Unreplaceable liquids at at least: " ) ;
logDirect ( flowingLiquids . stream ( )
2021-01-30 03:49:11 +00:00
. map ( p - > String . format ( " %s %s %s " , p . x , p . y , p . z ) )
. collect ( Collectors . joining ( " \ n " ) ) ) ;
2021-01-15 11:52:25 +00:00
}
2019-01-09 23:07:06 +00:00
return null ;
}
2019-05-01 21:03:36 +00:00
return new GoalComposite ( toBreak . toArray ( new Goal [ 0 ] ) ) ;
2019-01-09 23:07:06 +00:00
}
public static class JankyGoalComposite implements Goal {
2019-09-19 20:40:46 +00:00
2019-01-09 23:07:06 +00:00
private final Goal primary ;
private final Goal fallback ;
public JankyGoalComposite ( Goal primary , Goal fallback ) {
this . primary = primary ;
this . fallback = fallback ;
}
@Override
public boolean isInGoal ( int x , int y , int z ) {
return primary . isInGoal ( x , y , z ) | | fallback . isInGoal ( x , y , z ) ;
}
@Override
public double heuristic ( int x , int y , int z ) {
return primary . heuristic ( x , y , z ) ;
2019-01-09 04:45:02 +00:00
}
2019-02-21 22:24:23 +00:00
@Override
public String toString ( ) {
return " JankyComposite Primary: " + primary + " Fallback: " + fallback ;
}
2019-01-09 04:45:02 +00:00
}
public static class GoalBreak extends GoalGetToBlock {
public GoalBreak ( BlockPos pos ) {
super ( pos ) ;
}
@Override
public boolean isInGoal ( int x , int y , int z ) {
// can't stand right on top of a block, that might not work (what if it's unsupported, can't break then)
2019-01-09 22:36:44 +00:00
if ( y > this . y ) {
2019-01-09 04:45:02 +00:00
return false ;
}
// but any other adjacent works for breaking, including inside or below
return super . isInGoal ( x , y , z ) ;
}
2018-12-26 05:07:17 +00:00
}
2019-04-29 23:02:44 +00:00
private Goal placementGoal ( BlockPos pos , BuilderCalculationContext bcc ) {
2019-06-11 01:25:20 +00:00
if ( ! ( ctx . world ( ) . getBlockState ( pos ) . getBlock ( ) instanceof AirBlock ) ) { // TODO can this even happen?
2019-02-20 16:08:52 +00:00
return new GoalPlace ( pos ) ;
}
2019-06-11 01:25:20 +00:00
boolean allowSameLevel = ! ( ctx . world ( ) . getBlockState ( pos . up ( ) ) . getBlock ( ) instanceof AirBlock ) ;
2019-10-07 00:02:41 +00:00
BlockState current = ctx . world ( ) . getBlockState ( pos ) ;
2019-06-10 19:43:02 +00:00
for ( Direction facing : Movement . HORIZONTALS_BUT_ALSO_DOWN_____SO_EVERY_DIRECTION_EXCEPT_UP ) {
2019-09-02 10:00:21 +00:00
//noinspection ConstantConditions
2019-10-01 00:52:47 +00:00
if ( MovementHelper . canPlaceAgainst ( ctx , pos . offset ( facing ) ) & & placementPlausible ( pos , bcc . getSchematic ( pos . getX ( ) , pos . getY ( ) , pos . getZ ( ) , current ) ) ) {
2019-08-20 18:23:23 +00:00
return new GoalAdjacent ( pos , pos . offset ( facing ) , allowSameLevel ) ;
2019-02-07 00:22:40 +00:00
}
}
return new GoalPlace ( pos ) ;
}
2019-04-29 23:02:44 +00:00
private Goal breakGoal ( BlockPos pos , BuilderCalculationContext bcc ) {
2019-06-11 01:25:20 +00:00
if ( Baritone . settings ( ) . goalBreakFromAbove . value & & bcc . bsi . get0 ( pos . up ( ) ) . getBlock ( ) instanceof AirBlock & & bcc . bsi . get0 ( pos . up ( 2 ) ) . getBlock ( ) instanceof AirBlock ) { // TODO maybe possible without the up(2) check?
2019-04-29 23:02:44 +00:00
return new JankyGoalComposite ( new GoalBreak ( pos ) , new GoalGetToBlock ( pos . up ( ) ) {
@Override
public boolean isInGoal ( int x , int y , int z ) {
if ( y > this . y | | ( x = = this . x & & y = = this . y & & z = = this . z ) ) {
return false ;
}
return super . isInGoal ( x , y , z ) ;
}
} ) ;
}
return new GoalBreak ( pos ) ;
}
2019-02-07 00:22:40 +00:00
public static class GoalAdjacent extends GoalGetToBlock {
2019-09-19 20:40:46 +00:00
2019-04-08 00:44:23 +00:00
private boolean allowSameLevel ;
2019-08-20 18:23:23 +00:00
private BlockPos no ;
2019-02-07 00:22:40 +00:00
2019-08-20 18:23:23 +00:00
public GoalAdjacent ( BlockPos pos , BlockPos no , boolean allowSameLevel ) {
2019-02-07 00:22:40 +00:00
super ( pos ) ;
2019-08-20 18:23:23 +00:00
this . no = no ;
2019-02-07 00:22:40 +00:00
this . allowSameLevel = allowSameLevel ;
}
public boolean isInGoal ( int x , int y , int z ) {
if ( x = = this . x & & y = = this . y & & z = = this . z ) {
return false ;
}
2019-08-20 18:23:23 +00:00
if ( x = = no . getX ( ) & & y = = no . getY ( ) & & z = = no . getZ ( ) ) {
return false ;
}
2019-02-07 00:22:40 +00:00
if ( ! allowSameLevel & & y = = this . y - 1 ) {
return false ;
}
if ( y < this . y - 1 ) {
return false ;
}
return super . isInGoal ( x , y , z ) ;
}
public double heuristic ( int x , int y , int z ) {
// prioritize lower y coordinates
return this . y * 100 + super . heuristic ( x , y , z ) ;
}
}
2019-01-09 22:36:44 +00:00
public static class GoalPlace extends GoalBlock {
2019-09-19 20:40:46 +00:00
2019-01-09 22:36:44 +00:00
public GoalPlace ( BlockPos placeAt ) {
super ( placeAt . up ( ) ) ;
}
public double heuristic ( int x , int y , int z ) {
// prioritize lower y coordinates
return this . y * 100 + super . heuristic ( x , y , z ) ;
}
}
2018-12-26 05:07:17 +00:00
@Override
public void onLostControl ( ) {
incorrectPositions = null ;
name = null ;
schematic = null ;
2019-04-11 22:17:26 +00:00
realSchematic = null ;
2020-08-06 06:23:13 +00:00
layer = Baritone . settings ( ) . startAtLayer . value ;
2019-11-24 19:11:21 +00:00
numRepeats = 0 ;
2019-03-28 00:32:02 +00:00
paused = false ;
2019-04-29 21:55:14 +00:00
observedCompleted = null ;
2018-12-26 05:07:17 +00:00
}
@Override
2019-03-13 16:17:25 +00:00
public String displayName0 ( ) {
2019-03-28 00:32:02 +00:00
return paused ? " Builder Paused " : " Building " + name ;
2018-12-26 05:07:17 +00:00
}
2019-10-07 00:02:41 +00:00
private List < BlockState > approxPlaceable ( int size ) {
2019-06-10 19:43:02 +00:00
List < BlockState > result = new ArrayList < > ( ) ;
2019-02-07 21:59:37 +00:00
for ( int i = 0 ; i < size ; i + + ) {
2018-12-26 05:07:17 +00:00
ItemStack stack = ctx . player ( ) . inventory . mainInventory . get ( i ) ;
2019-06-11 01:25:20 +00:00
if ( stack . isEmpty ( ) | | ! ( stack . getItem ( ) instanceof BlockItem ) ) {
2018-12-26 05:07:17 +00:00
result . add ( Blocks . AIR . getDefaultState ( ) ) ;
continue ;
}
// <toxic cloud>
2019-06-11 01:25:20 +00:00
result . add ( ( ( BlockItem ) stack . getItem ( ) ) . getBlock ( ) . getStateForPlacement ( new BlockItemUseContext ( new ItemUseContext ( ctx . world ( ) , ctx . player ( ) , Hand . MAIN_HAND , stack , new BlockRayTraceResult ( new Vec3d ( ctx . player ( ) . posX , ctx . player ( ) . posY , ctx . player ( ) . posZ ) , Direction . UP , ctx . playerFeet ( ) , false ) ) { } ) ) ) ;
2018-12-26 05:07:17 +00:00
// </toxic cloud>
}
return result ;
}
2020-03-08 02:37:47 +00:00
private boolean valid ( BlockState current , BlockState desired , boolean itemVerify ) {
2019-03-14 23:06:32 +00:00
if ( desired = = null ) {
return true ;
}
2019-06-11 01:25:20 +00:00
if ( current . getBlock ( ) instanceof AirBlock & & desired . getBlock ( ) instanceof AirBlock ) {
2019-03-14 23:06:32 +00:00
return true ;
}
2019-08-20 21:28:59 +00:00
if ( ( current . getBlock ( ) = = Blocks . WATER | | current . getBlock ( ) = = Blocks . LAVA ) & & Baritone . settings ( ) . okIfWater . value ) {
return true ;
}
2021-01-30 03:49:11 +00:00
if ( current . getBlock ( ) instanceof AirBlock & & Baritone . settings ( ) . okIfAir . value . contains ( desired . getBlock ( ) ) ) {
2020-06-28 05:25:47 +00:00
return true ;
}
2020-01-01 03:57:55 +00:00
if ( desired . getBlock ( ) instanceof AirBlock & & Baritone . settings ( ) . buildIgnoreBlocks . value . contains ( current . getBlock ( ) ) ) {
2019-12-14 04:09:04 +00:00
return true ;
}
2020-03-08 02:37:47 +00:00
if ( ! ( current . getBlock ( ) instanceof AirBlock ) & & Baritone . settings ( ) . buildIgnoreExisting . value & & ! itemVerify ) {
2019-12-14 04:09:04 +00:00
return true ;
}
2019-03-14 23:06:32 +00:00
return current . equals ( desired ) ;
2019-01-09 04:45:02 +00:00
}
2018-12-26 05:07:17 +00:00
public class BuilderCalculationContext extends CalculationContext {
2019-09-19 20:40:46 +00:00
2019-10-07 00:02:41 +00:00
private final List < BlockState > placeable ;
2018-12-26 05:07:17 +00:00
private final ISchematic schematic ;
private final int originX ;
private final int originY ;
private final int originZ ;
2019-01-13 03:51:21 +00:00
public BuilderCalculationContext ( ) {
2018-12-26 05:07:17 +00:00
super ( BuilderProcess . this . baritone , true ) ; // wew lad
2019-09-06 10:59:10 +00:00
this . placeable = approxPlaceable ( 9 ) ;
2019-01-13 03:51:21 +00:00
this . schematic = BuilderProcess . this . schematic ;
this . originX = origin . getX ( ) ;
this . originY = origin . getY ( ) ;
this . originZ = origin . getZ ( ) ;
2019-01-09 22:36:44 +00:00
this . jumpPenalty + = 10 ;
2019-01-09 23:42:49 +00:00
this . backtrackCostFavoringCoefficient = 1 ;
2018-12-26 05:07:17 +00:00
}
2019-10-07 00:02:41 +00:00
private BlockState getSchematic ( int x , int y , int z , BlockState current ) {
2019-09-02 10:00:21 +00:00
if ( schematic . inSchematic ( x - originX , y - originY , z - originZ , current ) ) {
2019-09-06 10:59:10 +00:00
return schematic . desiredState ( x - originX , y - originY , z - originZ , current , BuilderProcess . this . approxPlaceable ) ;
2018-12-26 05:07:17 +00:00
} else {
return null ;
}
}
@Override
2019-10-07 00:36:25 +00:00
public double costOfPlacingAt ( int x , int y , int z , BlockState current ) {
2018-12-26 05:07:17 +00:00
if ( isPossiblyProtected ( x , y , z ) | | ! worldBorder . canPlaceAt ( x , z ) ) { // make calculation fail properly if we can't build
return COST_INF ;
}
2019-10-07 00:36:25 +00:00
BlockState sch = getSchematic ( x , y , z , current ) ;
2018-12-26 05:07:17 +00:00
if ( sch ! = null ) {
// TODO this can return true even when allowPlace is off.... is that an issue?
2019-06-11 01:25:20 +00:00
if ( sch . getBlock ( ) instanceof AirBlock ) {
2019-01-09 04:45:02 +00:00
// we want this to be air, but they're asking if they can place here
// this won't be a schematic block, this will be a throwaway
return placeBlockCost * 2 ; // we're going to have to break it eventually
}
2019-09-06 10:59:10 +00:00
if ( placeable . contains ( sch ) ) {
2018-12-26 05:07:17 +00:00
return 0 ; // thats right we gonna make it FREE to place a block where it should go in a structure
// no place block penalty at all 😎
// i'm such an idiot that i just tried to copy and paste the epic gamer moment emoji too
// get added to unicode when?
}
if ( ! hasThrowaway ) {
return COST_INF ;
}
2019-01-09 04:45:02 +00:00
// we want it to be something that we don't have
// even more of a pain to place something wrong
return placeBlockCost * 3 ;
2018-12-26 05:07:17 +00:00
} else {
if ( hasThrowaway ) {
return placeBlockCost ;
} else {
return COST_INF ;
}
}
}
@Override
2019-10-07 00:36:25 +00:00
public double breakCostMultiplierAt ( int x , int y , int z , BlockState current ) {
2018-12-26 05:07:17 +00:00
if ( ! allowBreak | | isPossiblyProtected ( x , y , z ) ) {
2019-01-09 04:45:02 +00:00
return COST_INF ;
2018-12-26 05:07:17 +00:00
}
2019-10-07 00:36:25 +00:00
BlockState sch = getSchematic ( x , y , z , current ) ;
2018-12-26 05:07:17 +00:00
if ( sch ! = null ) {
2019-06-11 01:25:20 +00:00
if ( sch . getBlock ( ) instanceof AirBlock ) {
2018-12-26 05:07:17 +00:00
// it should be air
// regardless of current contents, we can break it
2019-01-09 04:45:02 +00:00
return 1 ;
2018-12-26 05:07:17 +00:00
}
// it should be a real block
// is it already that block?
2020-03-07 23:34:27 +00:00
if ( valid ( bsi . get0 ( x , y , z ) , sch , false ) ) {
2019-08-20 18:23:23 +00:00
return Baritone . settings ( ) . breakCorrectBlockPenaltyMultiplier . value ;
2019-01-09 04:45:02 +00:00
} else {
// can break if it's wrong
// would be great to return less than 1 here, but that would actually make the cost calculation messed up
// since we're breaking a block, if we underestimate the cost, then it'll fail when it really takes the correct amount of time
return 1 ;
}
2018-12-26 05:07:17 +00:00
// TODO do blocks in render distace only?
// TODO allow breaking blocks that we have a tool to harvest and immediately place back?
} else {
2019-01-09 04:45:02 +00:00
return 1 ; // why not lol
2018-12-26 05:07:17 +00:00
}
}
}
}