horrifying placement
This commit is contained in:
parent
311cf81e8a
commit
a822d3ef05
@ -73,7 +73,7 @@ public final class LookBehavior extends Behavior implements ILookBehavior {
|
||||
float desiredPitch = this.target.getPitch();
|
||||
ctx.player().rotationPitch = desiredPitch;
|
||||
if (desiredPitch == oldPitch) {
|
||||
nudgeToLevel();
|
||||
//nudgeToLevel();
|
||||
}
|
||||
this.target = null;
|
||||
}
|
||||
|
@ -34,7 +34,7 @@ import java.util.Optional;
|
||||
|
||||
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 IPlayerContext ctx;
|
||||
|
@ -80,6 +80,9 @@ public interface MovementHelper extends ActionCosts, Helper {
|
||||
// be opened by just interacting.
|
||||
return block != Blocks.IRON_DOOR;
|
||||
}
|
||||
if (block == Blocks.CARPET) {
|
||||
return canWalkOn(bsi, x, y - 1, z);
|
||||
}
|
||||
boolean snow = block instanceof BlockSnow;
|
||||
boolean trapdoor = block instanceof BlockTrapDoor;
|
||||
if (snow || trapdoor) {
|
||||
@ -321,20 +324,22 @@ public interface MovementHelper extends ActionCosts, Helper {
|
||||
}
|
||||
|
||||
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) {
|
||||
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) {
|
||||
return canPlaceAgainst(new BlockStateInterface(ctx), pos);
|
||||
}
|
||||
|
||||
static boolean canPlaceAgainst(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
|
||||
return state.isBlockNormalCube();
|
||||
static boolean canPlaceAgainst(BlockStateInterface bsi, int x, int y, int z, IBlockState state) {
|
||||
// can we look at the center of a side face of this block and likely be able to place?
|
||||
// (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) {
|
||||
|
@ -25,14 +25,13 @@ import baritone.api.pathing.goals.GoalGetToBlock;
|
||||
import baritone.api.process.IBuilderProcess;
|
||||
import baritone.api.process.PathingCommand;
|
||||
import baritone.api.process.PathingCommandType;
|
||||
import baritone.api.utils.BetterBlockPos;
|
||||
import baritone.api.utils.ISchematic;
|
||||
import baritone.api.utils.Rotation;
|
||||
import baritone.api.utils.RotationUtils;
|
||||
import baritone.api.utils.*;
|
||||
import baritone.api.utils.input.Input;
|
||||
import baritone.pathing.movement.CalculationContext;
|
||||
import baritone.pathing.movement.Movement;
|
||||
import baritone.pathing.movement.MovementHelper;
|
||||
import baritone.utils.BaritoneProcessHelper;
|
||||
import baritone.utils.BlockStateInterface;
|
||||
import baritone.utils.PathingCommandContext;
|
||||
import baritone.utils.schematic.Schematic;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
@ -44,8 +43,7 @@ import net.minecraft.nbt.CompressedStreamTools;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.util.EnumFacing;
|
||||
import net.minecraft.util.Tuple;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Vec3i;
|
||||
import net.minecraft.util.math.*;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
@ -65,6 +63,7 @@ public class BuilderProcess extends BaritoneProcessHelper implements IBuilderPro
|
||||
private String name;
|
||||
private ISchematic schematic;
|
||||
private Vec3i origin;
|
||||
private int ticks;
|
||||
|
||||
public boolean build(String 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();
|
||||
}
|
||||
|
||||
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
|
||||
public PathingCommand onTick(boolean calcFailed, boolean isSafeToCancel) {
|
||||
// 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();
|
||||
return null;
|
||||
}
|
||||
if (baritone.getInputOverrideHandler().isInputForcedDown(Input.CLICK_LEFT)) {
|
||||
ticks = 5;
|
||||
} else {
|
||||
ticks--;
|
||||
}
|
||||
Optional<Tuple<BetterBlockPos, Rotation>> toBreak = toBreakNearPlayer(bcc);
|
||||
baritone.getInputOverrideHandler().clearAllKeys();
|
||||
if (toBreak.isPresent() && isSafeToCancel && ctx.player().onGround) {
|
||||
@ -170,11 +293,22 @@ public class BuilderProcess extends BaritoneProcessHelper implements IBuilderPro
|
||||
BetterBlockPos pos = toBreak.get().getFirst();
|
||||
baritone.getLookBehavior().updateTarget(rot, true);
|
||||
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);
|
||||
}
|
||||
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);
|
||||
if (goal == null) {
|
||||
@ -241,7 +375,7 @@ public class BuilderProcess extends BaritoneProcessHelper implements IBuilderPro
|
||||
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());
|
||||
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) {
|
||||
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 GoalPlace(BlockPos placeAt) {
|
||||
super(placeAt.up());
|
||||
|
@ -69,7 +69,9 @@ public final class InputOverrideHandler extends Behavior implements IInputOverri
|
||||
return false;
|
||||
}
|
||||
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;
|
||||
}
|
||||
@ -122,7 +124,7 @@ public final class InputOverrideHandler extends Behavior implements IInputOverri
|
||||
}
|
||||
|
||||
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() {
|
||||
|
Loading…
Reference in New Issue
Block a user