horrifying placement

This commit is contained in:
Leijurv 2019-02-06 16:22:40 -08:00
parent 311cf81e8a
commit a822d3ef05
No known key found for this signature in database
GPG Key ID: 44A3EA646EADAC6A
5 changed files with 195 additions and 17 deletions

View File

@ -73,7 +73,7 @@ public final class LookBehavior extends Behavior implements ILookBehavior {
float desiredPitch = this.target.getPitch(); float desiredPitch = this.target.getPitch();
ctx.player().rotationPitch = desiredPitch; ctx.player().rotationPitch = desiredPitch;
if (desiredPitch == oldPitch) { if (desiredPitch == oldPitch) {
nudgeToLevel(); //nudgeToLevel();
} }
this.target = null; this.target = null;
} }

View File

@ -34,7 +34,7 @@ import java.util.Optional;
public abstract class Movement implements IMovement, MovementHelper { public abstract class Movement implements IMovement, MovementHelper {
protected static final EnumFacing[] HORIZONTALS_BUT_ALSO_DOWN____SO_EVERY_DIRECTION_EXCEPT_UP = {EnumFacing.NORTH, EnumFacing.SOUTH, EnumFacing.EAST, EnumFacing.WEST, EnumFacing.DOWN}; public static final EnumFacing[] HORIZONTALS_BUT_ALSO_DOWN____SO_EVERY_DIRECTION_EXCEPT_UP = {EnumFacing.NORTH, EnumFacing.SOUTH, EnumFacing.EAST, EnumFacing.WEST, EnumFacing.DOWN};
protected final IBaritone baritone; protected final IBaritone baritone;
protected final IPlayerContext ctx; protected final IPlayerContext ctx;

View File

@ -80,6 +80,9 @@ public interface MovementHelper extends ActionCosts, Helper {
// be opened by just interacting. // be opened by just interacting.
return block != Blocks.IRON_DOOR; return block != Blocks.IRON_DOOR;
} }
if (block == Blocks.CARPET) {
return canWalkOn(bsi, x, y - 1, z);
}
boolean snow = block instanceof BlockSnow; boolean snow = block instanceof BlockSnow;
boolean trapdoor = block instanceof BlockTrapDoor; boolean trapdoor = block instanceof BlockTrapDoor;
if (snow || trapdoor) { if (snow || trapdoor) {
@ -321,20 +324,22 @@ public interface MovementHelper extends ActionCosts, Helper {
} }
static boolean canPlaceAgainst(BlockStateInterface bsi, int x, int y, int z) { static boolean canPlaceAgainst(BlockStateInterface bsi, int x, int y, int z) {
return canPlaceAgainst(bsi.get0(x, y, z)); return canPlaceAgainst(bsi, x, y, z, bsi.get0(x, y, z));
} }
static boolean canPlaceAgainst(BlockStateInterface bsi, BlockPos pos) { static boolean canPlaceAgainst(BlockStateInterface bsi, BlockPos pos) {
return canPlaceAgainst(bsi.get0(pos.getX(), pos.getY(), pos.getZ())); return canPlaceAgainst(bsi, pos.getX(), pos.getY(), pos.getZ());
} }
static boolean canPlaceAgainst(IPlayerContext ctx, BlockPos pos) { static boolean canPlaceAgainst(IPlayerContext ctx, BlockPos pos) {
return canPlaceAgainst(new BlockStateInterface(ctx), pos); return canPlaceAgainst(new BlockStateInterface(ctx), pos);
} }
static boolean canPlaceAgainst(IBlockState state) { static boolean canPlaceAgainst(BlockStateInterface bsi, int x, int y, int z, IBlockState state) {
// TODO isBlockNormalCube isn't the best check for whether or not we can place a block against it. e.g. glass isn't normalCube but we can place against it // can we look at the center of a side face of this block and likely be able to place?
return state.isBlockNormalCube(); // (thats how this check is used)
// therefore dont include weird things that we technically could place against (like carpet) but practically can't
return state.isBlockNormalCube() || state.isFullBlock() || state.getBlock() == Blocks.GLASS || state.getBlock() == Blocks.STAINED_GLASS;
} }
static double getMiningDurationTicks(CalculationContext context, int x, int y, int z, boolean includeFalling) { static double getMiningDurationTicks(CalculationContext context, int x, int y, int z, boolean includeFalling) {

View File

@ -25,14 +25,13 @@ import baritone.api.pathing.goals.GoalGetToBlock;
import baritone.api.process.IBuilderProcess; import baritone.api.process.IBuilderProcess;
import baritone.api.process.PathingCommand; import baritone.api.process.PathingCommand;
import baritone.api.process.PathingCommandType; import baritone.api.process.PathingCommandType;
import baritone.api.utils.BetterBlockPos; import baritone.api.utils.*;
import baritone.api.utils.ISchematic;
import baritone.api.utils.Rotation;
import baritone.api.utils.RotationUtils;
import baritone.api.utils.input.Input; import baritone.api.utils.input.Input;
import baritone.pathing.movement.CalculationContext; import baritone.pathing.movement.CalculationContext;
import baritone.pathing.movement.Movement;
import baritone.pathing.movement.MovementHelper; import baritone.pathing.movement.MovementHelper;
import baritone.utils.BaritoneProcessHelper; import baritone.utils.BaritoneProcessHelper;
import baritone.utils.BlockStateInterface;
import baritone.utils.PathingCommandContext; import baritone.utils.PathingCommandContext;
import baritone.utils.schematic.Schematic; import baritone.utils.schematic.Schematic;
import net.minecraft.block.state.IBlockState; import net.minecraft.block.state.IBlockState;
@ -44,8 +43,7 @@ import net.minecraft.nbt.CompressedStreamTools;
import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumFacing;
import net.minecraft.util.Tuple; import net.minecraft.util.Tuple;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.*;
import net.minecraft.util.math.Vec3i;
import java.io.File; import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
@ -65,6 +63,7 @@ public class BuilderProcess extends BaritoneProcessHelper implements IBuilderPro
private String name; private String name;
private ISchematic schematic; private ISchematic schematic;
private Vec3i origin; private Vec3i origin;
private int ticks;
public boolean build(String schematicFile) { public boolean build(String schematicFile) {
File file = new File(new File(Minecraft.getMinecraft().gameDir, "schematics"), schematicFile); File file = new File(new File(Minecraft.getMinecraft().gameDir, "schematics"), schematicFile);
@ -145,6 +144,125 @@ public class BuilderProcess extends BaritoneProcessHelper implements IBuilderPro
return Optional.empty(); return Optional.empty();
} }
public class Placement {
final int hotbarSelection;
final BlockPos placeAgainst;
final EnumFacing side;
final Rotation rot;
public Placement(int hotbarSelection, BlockPos placeAgainst, EnumFacing side, Rotation rot) {
this.hotbarSelection = hotbarSelection;
this.placeAgainst = placeAgainst;
this.side = side;
this.rot = rot;
}
}
public Optional<Placement> searchForPlacables(BuilderCalculationContext bcc) {
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;
IBlockState desired = bcc.getSchematic(x, y, z);
if (desired == null) {
continue; // irrelevant
}
IBlockState curr = bcc.bsi.get0(x, y, z);
if (MovementHelper.isReplacable(x, y, z, curr, bcc.bsi) && !valid(curr, desired)) {
if (dy == 1 && bcc.bsi.get0(x, y + 1, z).getBlock() == Blocks.AIR) {
continue;
}
Optional<Placement> opt = possibleToPlace(desired, x, y, z, bcc.bsi);
if (opt.isPresent()) {
return opt;
}
}
}
}
}
return Optional.empty();
}
public Optional<Placement> possibleToPlace(IBlockState toPlace, int x, int y, int z, BlockStateInterface bsi) {
for (EnumFacing against : EnumFacing.values()) {
BetterBlockPos placeAgainstPos = new BetterBlockPos(x, y, z).offset(against);
IBlockState placeAgainstState = bsi.get0(placeAgainstPos);
if (MovementHelper.isReplacable(placeAgainstPos.x, placeAgainstPos.y, placeAgainstPos.z, placeAgainstState, bsi)) {
continue;
}
if (!ctx.world().mayPlace(toPlace.getBlock(), new BetterBlockPos(x, y, z), false, against, null)) {
continue;
}
AxisAlignedBB aabb = placeAgainstState.getBoundingBox(ctx.world(), placeAgainstPos);
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);
Rotation rot = RotationUtils.calcRotationFromVec3d(ctx.playerHead(), new Vec3d(placeX, placeY, placeZ));
RayTraceResult result = RayTraceUtils.rayTraceTowards(ctx.player(), rot, ctx.playerController().getBlockReachDistance());
if (result != null && result.typeOfHit == RayTraceResult.Type.BLOCK && result.getBlockPos().equals(placeAgainstPos) && result.sideHit == against.getOpposite()) {
OptionalInt hotbar = hasAnyItemThatWouldPlace(toPlace, result, rot);
if (hotbar.isPresent()) {
return Optional.of(new Placement(hotbar.getAsInt(), placeAgainstPos, against.getOpposite(), rot));
}
}
}
}
return Optional.empty();
}
public OptionalInt hasAnyItemThatWouldPlace(IBlockState desired, RayTraceResult result, Rotation rot) {
for (int i = 0; i < 9; i++) {
ItemStack stack = ctx.player().inventory.mainInventory.get(i);
if (stack.isEmpty() || !(stack.getItem() instanceof ItemBlock)) {
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();
IBlockState wouldBePlaced = ((ItemBlock) stack.getItem()).getBlock().getStateForPlacement(
ctx.world(),
result.getBlockPos().offset(result.sideHit),
result.sideHit,
(float) result.hitVec.x - result.getBlockPos().getX(), // as in PlayerControllerMP
(float) result.hitVec.y - result.getBlockPos().getY(),
(float) result.hitVec.z - result.getBlockPos().getZ(),
stack.getItem().getMetadata(stack.getMetadata()),
ctx.player()
);
ctx.player().rotationYaw = originalYaw;
ctx.player().rotationPitch = originalPitch;
if (valid(wouldBePlaced, desired)) {
return OptionalInt.of(i);
}
}
return OptionalInt.empty();
}
private static Vec3d[] aabbSideMultipliers(EnumFacing side) {
switch (side) {
case UP:
return new Vec3d[]{new Vec3d(0.5, 1, 0.5)};
case DOWN:
return new Vec3d[]{new Vec3d(0.5, 0, 0.5)};
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
throw new NullPointerException();
}
}
@Override @Override
public PathingCommand onTick(boolean calcFailed, boolean isSafeToCancel) { public PathingCommand onTick(boolean calcFailed, boolean isSafeToCancel) {
// TODO somehow tell inventorybehavior what we'd like to have on the hotbar // TODO somehow tell inventorybehavior what we'd like to have on the hotbar
@ -161,6 +279,11 @@ public class BuilderProcess extends BaritoneProcessHelper implements IBuilderPro
onLostControl(); onLostControl();
return null; return null;
} }
if (baritone.getInputOverrideHandler().isInputForcedDown(Input.CLICK_LEFT)) {
ticks = 5;
} else {
ticks--;
}
Optional<Tuple<BetterBlockPos, Rotation>> toBreak = toBreakNearPlayer(bcc); Optional<Tuple<BetterBlockPos, Rotation>> toBreak = toBreakNearPlayer(bcc);
baritone.getInputOverrideHandler().clearAllKeys(); baritone.getInputOverrideHandler().clearAllKeys();
if (toBreak.isPresent() && isSafeToCancel && ctx.player().onGround) { if (toBreak.isPresent() && isSafeToCancel && ctx.player().onGround) {
@ -170,11 +293,22 @@ public class BuilderProcess extends BaritoneProcessHelper implements IBuilderPro
BetterBlockPos pos = toBreak.get().getFirst(); BetterBlockPos pos = toBreak.get().getFirst();
baritone.getLookBehavior().updateTarget(rot, true); baritone.getLookBehavior().updateTarget(rot, true);
MovementHelper.switchToBestToolFor(ctx, bcc.get(pos)); MovementHelper.switchToBestToolFor(ctx, bcc.get(pos));
if (Objects.equals(ctx.objectMouseOver().getBlockPos(), rot) || ctx.playerRotations().isReallyCloseTo(rot)) { if (Objects.equals(ctx.objectMouseOver().getBlockPos(), pos) || ctx.playerRotations().isReallyCloseTo(rot)) {
baritone.getInputOverrideHandler().setInputForceState(Input.CLICK_LEFT, true); baritone.getInputOverrideHandler().setInputForceState(Input.CLICK_LEFT, true);
} }
return new PathingCommand(null, PathingCommandType.REQUEST_PAUSE); return new PathingCommand(null, PathingCommandType.REQUEST_PAUSE);
} }
Optional<Placement> toPlace = searchForPlacables(bcc);
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);
if ((Objects.equals(ctx.objectMouseOver().getBlockPos(), toPlace.get().placeAgainst) && ctx.objectMouseOver().sideHit.equals(toPlace.get().side)) || ctx.playerRotations().isReallyCloseTo(rot)) {
baritone.getInputOverrideHandler().setInputForceState(Input.CLICK_RIGHT, true);
}
return new PathingCommand(null, PathingCommandType.REQUEST_PAUSE);
}
Goal goal = assemble(bcc); Goal goal = assemble(bcc);
if (goal == null) { if (goal == null) {
@ -241,7 +375,7 @@ public class BuilderProcess extends BaritoneProcessHelper implements IBuilderPro
List<IBlockState> approxPlacable = placable(); List<IBlockState> approxPlacable = placable();
List<BetterBlockPos> placable = incorrectPositions.stream().filter(pos -> bcc.bsi.get0(pos).getBlock() == Blocks.AIR && approxPlacable.contains(bcc.getSchematic(pos.x, pos.y, pos.z))).collect(Collectors.toList()); List<BetterBlockPos> placable = incorrectPositions.stream().filter(pos -> bcc.bsi.get0(pos).getBlock() == Blocks.AIR && approxPlacable.contains(bcc.getSchematic(pos.x, pos.y, pos.z))).collect(Collectors.toList());
Goal[] toBreak = incorrectPositions.stream().filter(pos -> bcc.bsi.get0(pos).getBlock() != Blocks.AIR).map(GoalBreak::new).toArray(Goal[]::new); Goal[] toBreak = incorrectPositions.stream().filter(pos -> bcc.bsi.get0(pos).getBlock() != Blocks.AIR).map(GoalBreak::new).toArray(Goal[]::new);
Goal[] toPlace = placable.stream().filter(pos -> !placable.contains(pos.down()) && !placable.contains(pos.down(2))).map(GoalPlace::new).toArray(Goal[]::new); Goal[] toPlace = placable.stream().filter(pos -> !placable.contains(pos.down()) && !placable.contains(pos.down(2))).map(pos -> placementgoal(pos, bcc)).toArray(Goal[]::new);
if (toPlace.length != 0) { if (toPlace.length != 0) {
return new JankyGoalComposite(new GoalComposite(toPlace), new GoalComposite(toBreak)); return new JankyGoalComposite(new GoalComposite(toPlace), new GoalComposite(toBreak));
@ -290,6 +424,43 @@ public class BuilderProcess extends BaritoneProcessHelper implements IBuilderPro
} }
} }
public Goal placementgoal(BlockPos pos, BuilderCalculationContext bcc) {
boolean allowSameLevel = ctx.world().getBlockState(pos.up()).getBlock() != Blocks.AIR;
for (EnumFacing facing : Movement.HORIZONTALS_BUT_ALSO_DOWN____SO_EVERY_DIRECTION_EXCEPT_UP) {
if (MovementHelper.canPlaceAgainst(ctx, pos.offset(facing)) && ctx.world().mayPlace(bcc.getSchematic(pos.getX(), pos.getY(), pos.getZ()).getBlock(), pos, false, facing, null)) {
return new GoalAdjacent(pos, allowSameLevel);
}
}
return new GoalPlace(pos);
}
public static class GoalAdjacent extends GoalGetToBlock {
boolean allowSameLevel;
public GoalAdjacent(BlockPos pos, boolean allowSameLevel) {
super(pos);
this.allowSameLevel = allowSameLevel;
}
public boolean isInGoal(int x, int y, int z) {
if (x == this.x && y == this.y && z == this.z) {
return false;
}
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);
}
}
public static class GoalPlace extends GoalBlock { public static class GoalPlace extends GoalBlock {
public GoalPlace(BlockPos placeAt) { public GoalPlace(BlockPos placeAt) {
super(placeAt.up()); super(placeAt.up());

View File

@ -69,7 +69,9 @@ public final class InputOverrideHandler extends Behavior implements IInputOverri
return false; return false;
} }
if (input == Input.CLICK_RIGHT) { if (input == Input.CLICK_RIGHT) {
return isInputForcedDown(Input.CLICK_RIGHT); boolean ret = isInputForcedDown(Input.CLICK_RIGHT);
System.out.println("click right ret: " + ret);
return ret;
} }
return null; return null;
} }
@ -122,7 +124,7 @@ public final class InputOverrideHandler extends Behavior implements IInputOverri
} }
private boolean inControl() { private boolean inControl() {
return baritone.getPathingBehavior().isPathing() || baritone != BaritoneAPI.getProvider().getPrimaryBaritone(); return baritone.getPathingBehavior().isPathing() || baritone.getBuilderProcess().isActive() || baritone != BaritoneAPI.getProvider().getPrimaryBaritone();
} }
public BlockBreakHelper getBlockBreakHelper() { public BlockBreakHelper getBlockBreakHelper() {