diff --git a/src/api/java/baritone/api/IBaritone.java b/src/api/java/baritone/api/IBaritone.java index 3c9681532..ea09e0123 100644 --- a/src/api/java/baritone/api/IBaritone.java +++ b/src/api/java/baritone/api/IBaritone.java @@ -94,6 +94,12 @@ public interface IBaritone { */ IElytraProcess getElytraProcess(); + /** + * @return The {@link IAttackProcess} instance + * @see IAttackProcess + */ + IAttackProcess getAttackProcess(); + /** * @return The {@link IWorldProvider} instance * @see IWorldProvider diff --git a/src/api/java/baritone/api/Settings.java b/src/api/java/baritone/api/Settings.java index 43ace5e31..c37739129 100644 --- a/src/api/java/baritone/api/Settings.java +++ b/src/api/java/baritone/api/Settings.java @@ -411,6 +411,26 @@ public final class Settings { */ public final Setting blockBreakSpeed = new Setting<>(6); + /** + * Determines if Baritone waits for the attack cooldown to recharge completely before attacking + */ + public final Setting timedAttacks = new Setting<>(true); + + /** + * Determines how many ticks between left clicks are allowed. + */ + public final Setting leftClickSpeed = new Setting<>(6); + + /** + * Assume external aiming functionality + */ + public final Setting assumeExternalAutoAim = new Setting<>(false); + + /** + * Assume external attacking functionality + */ + public final Setting assumeExternalKillAura = new Setting<>(false); + /** * How many degrees to randomize the pitch and yaw every tick. Set to 0 to disable */ @@ -1232,6 +1252,22 @@ public final class Settings { */ public final Setting followOffsetDistance = new Setting<>(0D); + /** + * The actual GoalNear is set to circle around your selected entity instead of remaining in one place. + * This disregards {@link #followOffsetDirection} when enabled. + */ + public final Setting followCircle = new Setting<>(false); + + /** + * The yaw amount the target is shifted by + */ + public final Setting followCircleIncrement = new Setting<>(90F); + + /** + * The chance every tick that the follow circle direction is switched from 0 to 100 + */ + public final Setting followCircleSwitchDirectionChance = new Setting<>(2.5D); + /** * The actual GoalNear is set in this direction from the entity you're following. This value is in degrees. */ @@ -1247,6 +1283,13 @@ public final class Settings { */ public final Setting followTargetMaxDistance = new Setting<>(0); + /** + * The distance until you start locking on and attacking entities. + *

+ * This doesn't change the direction you go, just the direction you face. + */ + public final Setting entityAttackRadius = new Setting<>(0D); + /** * Turn this on if your exploration filter is enormous, you don't want it to check if it's done, * and you are just fine with it just hanging on completion diff --git a/src/api/java/baritone/api/process/IAttackProcess.java b/src/api/java/baritone/api/process/IAttackProcess.java new file mode 100644 index 000000000..576773c79 --- /dev/null +++ b/src/api/java/baritone/api/process/IAttackProcess.java @@ -0,0 +1,24 @@ +/* + * 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 . + */ + +package baritone.api.process; + +public interface IAttackProcess extends IBaritoneProcess { + boolean isRotating(); + + boolean isAttacking(); +} diff --git a/src/api/java/baritone/api/utils/RayTraceUtils.java b/src/api/java/baritone/api/utils/RayTraceUtils.java index ed544302d..1c982957a 100644 --- a/src/api/java/baritone/api/utils/RayTraceUtils.java +++ b/src/api/java/baritone/api/utils/RayTraceUtils.java @@ -50,7 +50,7 @@ public static HitResult rayTraceTowards(Entity entity, Rotation rotation, double if (wouldSneak) { start = inferSneakingEyePosition(entity); } else { - start = entity.getEyePosition(1.0F); // do whatever is correct + start = entity.getEyePosition(); } Vec3 direction = RotationUtils.calcLookDirectionFromRotation(rotation); diff --git a/src/main/java/baritone/Baritone.java b/src/main/java/baritone/Baritone.java index ad6871413..c23646dcd 100755 --- a/src/main/java/baritone/Baritone.java +++ b/src/main/java/baritone/Baritone.java @@ -22,6 +22,7 @@ import baritone.api.Settings; import baritone.api.behavior.IBehavior; import baritone.api.event.listener.IEventBus; +import baritone.api.process.IAttackProcess; import baritone.api.process.IBaritoneProcess; import baritone.api.process.IElytraProcess; import baritone.api.utils.IPlayerContext; @@ -80,6 +81,7 @@ public class Baritone implements IBaritone { private final FarmProcess farmProcess; private final InventoryPauserProcess inventoryPauserProcess; private final IElytraProcess elytraProcess; + private final AttackProcess attackProcess; private final PathingControlManager pathingControlManager; private final SelectionManager selectionManager; @@ -123,6 +125,7 @@ public class Baritone implements IBaritone { this.farmProcess = this.registerProcess(FarmProcess::new); this.inventoryPauserProcess = this.registerProcess(InventoryPauserProcess::new); this.elytraProcess = this.registerProcess(ElytraProcess::create); + this.attackProcess = this.registerProcess(AttackProcess::new); this.registerProcess(BackfillProcess::new); } @@ -240,6 +243,11 @@ public IElytraProcess getElytraProcess() { return this.elytraProcess; } + @Override + public IAttackProcess getAttackProcess() { + return this.attackProcess; + } + @Override public void openClick() { new Thread(() -> { diff --git a/src/main/java/baritone/behavior/PathingBehavior.java b/src/main/java/baritone/behavior/PathingBehavior.java index d8df46681..6c936975f 100644 --- a/src/main/java/baritone/behavior/PathingBehavior.java +++ b/src/main/java/baritone/behavior/PathingBehavior.java @@ -33,7 +33,6 @@ import baritone.pathing.movement.CalculationContext; import baritone.pathing.movement.MovementHelper; import baritone.pathing.path.PathExecutor; -import baritone.process.ElytraProcess; import baritone.utils.PathRenderer; import baritone.utils.PathingCommandContext; import baritone.utils.pathing.Favoring; @@ -120,7 +119,7 @@ private void tickPath() { pauseRequestedLastTick = false; if (unpausedLastTick) { baritone.getInputOverrideHandler().clearAllKeys(); - baritone.getInputOverrideHandler().getBlockBreakHelper().stopBreakingBlock(); + baritone.getInputOverrideHandler().getLeftClickHelper().stopBreakingBlock(); } unpausedLastTick = false; pausedThisTick = true; @@ -363,7 +362,7 @@ public void secretInternalSegmentCancel() { current = null; next = null; baritone.getInputOverrideHandler().clearAllKeys(); - baritone.getInputOverrideHandler().getBlockBreakHelper().stopBreakingBlock(); + baritone.getInputOverrideHandler().getLeftClickHelper().stopBreakingBlock(); } } } diff --git a/src/main/java/baritone/pathing/movement/MovementHelper.java b/src/main/java/baritone/pathing/movement/MovementHelper.java index c01fd40e6..4c23bab09 100644 --- a/src/main/java/baritone/pathing/movement/MovementHelper.java +++ b/src/main/java/baritone/pathing/movement/MovementHelper.java @@ -650,13 +650,21 @@ static void switchToBestToolFor(IPlayerContext ctx, BlockState b, ToolSet ts, bo } } + static void moveTowards(IPlayerContext ctx, MovementState state, BlockPos dest, boolean changeRotation) { + if (!changeRotation) { + state.setTarget(new MovementTarget( + RotationUtils.calcRotationFromVec3d(ctx.playerHead(), + VecUtils.getBlockPosCenter(dest), + ctx.playerRotations()).withPitch(ctx.playerRotations().getPitch()), + false + )).setInput(Input.MOVE_FORWARD, true); + } else { + moveTowardsWithoutRotation(ctx, state, dest); + } + } + static void moveTowards(IPlayerContext ctx, MovementState state, BlockPos pos) { - state.setTarget(new MovementTarget( - RotationUtils.calcRotationFromVec3d(ctx.playerHead(), - VecUtils.getBlockPosCenter(pos), - ctx.playerRotations()).withPitch(ctx.playerRotations().getPitch()), - false - )).setInput(Input.MOVE_FORWARD, true); + moveTowards(ctx, state, pos, false); } static void moveTowardsWithoutRotation(IPlayerContext ctx, MovementState state, float idealYaw) { diff --git a/src/main/java/baritone/pathing/movement/movements/MovementAscend.java b/src/main/java/baritone/pathing/movement/movements/MovementAscend.java index 2ecd9d723..975babe9f 100644 --- a/src/main/java/baritone/pathing/movement/movements/MovementAscend.java +++ b/src/main/java/baritone/pathing/movement/movements/MovementAscend.java @@ -189,7 +189,7 @@ public MovementState updateState(MovementState state) { return state; } - MovementHelper.moveTowards(ctx, state, dest); + MovementHelper.moveTowards(ctx, state, dest, baritone.getAttackProcess().isRotating()); state.setInput(Input.SNEAK, Baritone.settings().allowWalkOnMagmaBlocks.value && jumpingOnto.is(Blocks.MAGMA_BLOCK)); diff --git a/src/main/java/baritone/pathing/movement/movements/MovementDescend.java b/src/main/java/baritone/pathing/movement/movements/MovementDescend.java index 3e860e301..c33407265 100644 --- a/src/main/java/baritone/pathing/movement/movements/MovementDescend.java +++ b/src/main/java/baritone/pathing/movement/movements/MovementDescend.java @@ -261,9 +261,9 @@ public MovementState updateState(MovementState state) { if (!playerFeet.equals(dest) || ab > 0.25) { if (numTicks++ < 20 && fromStart < 1.25) { - MovementHelper.moveTowards(ctx, state, fakeDest); + MovementHelper.moveTowards(ctx, state, fakeDest, baritone.getAttackProcess().isRotating()); } else { - MovementHelper.moveTowards(ctx, state, dest); + MovementHelper.moveTowards(ctx, state, dest, baritone.getAttackProcess().isRotating()); } } return state; diff --git a/src/main/java/baritone/pathing/movement/movements/MovementDiagonal.java b/src/main/java/baritone/pathing/movement/movements/MovementDiagonal.java index e7d74f03e..4893a0d07 100644 --- a/src/main/java/baritone/pathing/movement/movements/MovementDiagonal.java +++ b/src/main/java/baritone/pathing/movement/movements/MovementDiagonal.java @@ -278,7 +278,7 @@ public MovementState updateState(MovementState state) { state.setInput(Input.SPRINT, true); } state.setInput(Input.SNEAK, Baritone.settings().allowWalkOnMagmaBlocks.value && MovementHelper.steppingOnBlocks(ctx).stream().anyMatch(block -> ctx.world().getBlockState(block).is(Blocks.MAGMA_BLOCK))); - MovementHelper.moveTowards(ctx, state, dest); + MovementHelper.moveTowards(ctx, state, dest, baritone.getAttackProcess().isRotating()); return state; } diff --git a/src/main/java/baritone/pathing/movement/movements/MovementDownward.java b/src/main/java/baritone/pathing/movement/movements/MovementDownward.java index a37df38b6..2ca925fee 100644 --- a/src/main/java/baritone/pathing/movement/movements/MovementDownward.java +++ b/src/main/java/baritone/pathing/movement/movements/MovementDownward.java @@ -90,7 +90,7 @@ public MovementState updateState(MovementState state) { if (numTicks++ < 10 && ab < 0.2) { return state; } - MovementHelper.moveTowards(ctx, state, positionsToBreak[0]); + MovementHelper.moveTowards(ctx, state, positionsToBreak[0], baritone.getAttackProcess().isRotating()); return state; } } diff --git a/src/main/java/baritone/pathing/movement/movements/MovementParkour.java b/src/main/java/baritone/pathing/movement/movements/MovementParkour.java index 5ea1e4dcc..df0b67bba 100644 --- a/src/main/java/baritone/pathing/movement/movements/MovementParkour.java +++ b/src/main/java/baritone/pathing/movement/movements/MovementParkour.java @@ -266,7 +266,7 @@ public MovementState updateState(MovementState state) { state.setInput(Input.SNEAK, true); } - MovementHelper.moveTowards(ctx, state, dest); + MovementHelper.moveTowards(ctx, state, dest, baritone.getAttackProcess().isRotating()); if (ctx.playerFeet().equals(dest)) { Block d = BlockStateInterface.getBlock(ctx, dest); if (d == Blocks.VINE || d == Blocks.LADDER) { @@ -302,9 +302,9 @@ public MovementState updateState(MovementState state) { } else if (!ctx.playerFeet().equals(dest.relative(direction, -1))) { state.setInput(Input.SPRINT, false); if (ctx.playerFeet().equals(src.relative(direction, -1))) { - MovementHelper.moveTowards(ctx, state, src); + MovementHelper.moveTowards(ctx, state, src, baritone.getAttackProcess().isRotating()); } else { - MovementHelper.moveTowards(ctx, state, src.relative(direction, -1)); + MovementHelper.moveTowards(ctx, state, src.relative(direction, -1), baritone.getAttackProcess().isRotating()); } } } diff --git a/src/main/java/baritone/pathing/movement/movements/MovementPillar.java b/src/main/java/baritone/pathing/movement/movements/MovementPillar.java index 8007eb767..38a347db8 100644 --- a/src/main/java/baritone/pathing/movement/movements/MovementPillar.java +++ b/src/main/java/baritone/pathing/movement/movements/MovementPillar.java @@ -221,7 +221,7 @@ public MovementState updateState(MovementState state) { } */ - MovementHelper.moveTowards(ctx, state, against); + MovementHelper.moveTowards(ctx, state, against, baritone.getAttackProcess().isRotating()); return state; } else { // Get ready to place a throwaway block diff --git a/src/main/java/baritone/pathing/movement/movements/MovementTraverse.java b/src/main/java/baritone/pathing/movement/movements/MovementTraverse.java index 156da1adb..4240f91d2 100644 --- a/src/main/java/baritone/pathing/movement/movements/MovementTraverse.java +++ b/src/main/java/baritone/pathing/movement/movements/MovementTraverse.java @@ -286,7 +286,7 @@ public MovementState updateState(MovementState state) { return state.setStatus(MovementStatus.UNREACHABLE); } } - MovementHelper.moveTowards(ctx, state, against); + MovementHelper.moveTowards(ctx, state, against, baritone.getAttackProcess().isRotating()); return state; } else { wasTheBridgeBlockAlwaysThere = false; @@ -294,7 +294,7 @@ public MovementState updateState(MovementState state) { if (standingOn.equals(Blocks.SOUL_SAND) || standingOn instanceof SlabBlock) { // see issue #118 double dist = Math.max(Math.abs(dest.getX() + 0.5 - ctx.player().position().x), Math.abs(dest.getZ() + 0.5 - ctx.player().position().z)); if (dist < 0.85) { // 0.5 + 0.3 + epsilon - MovementHelper.moveTowards(ctx, state, dest); + MovementHelper.moveTowards(ctx, state, dest, baritone.getAttackProcess().isRotating()); return state.setInput(Input.MOVE_FORWARD, false) .setInput(Input.MOVE_BACK, true); } diff --git a/src/main/java/baritone/pathing/path/PathExecutor.java b/src/main/java/baritone/pathing/path/PathExecutor.java index 96d105208..4d986088e 100644 --- a/src/main/java/baritone/pathing/path/PathExecutor.java +++ b/src/main/java/baritone/pathing/path/PathExecutor.java @@ -589,7 +589,7 @@ private void clearKeys() { private void cancel() { clearKeys(); - behavior.baritone.getInputOverrideHandler().getBlockBreakHelper().stopBreakingBlock(); + behavior.baritone.getInputOverrideHandler().getLeftClickHelper().stopBreakingBlock(); pathPosition = path.length() + 3; failed = true; } diff --git a/src/main/java/baritone/process/AttackProcess.java b/src/main/java/baritone/process/AttackProcess.java new file mode 100644 index 000000000..9812bdb27 --- /dev/null +++ b/src/main/java/baritone/process/AttackProcess.java @@ -0,0 +1,115 @@ +/* + * 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 . + */ + +package baritone.process; + +import baritone.Baritone; +import baritone.api.process.IAttackProcess; +import baritone.api.process.PathingCommand; +import baritone.api.process.PathingCommandType; +import baritone.api.utils.RotationUtils; +import baritone.api.utils.input.Input; +import baritone.utils.BaritoneProcessHelper; +import net.minecraft.util.Mth; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.phys.HitResult; +import net.minecraft.world.phys.Vec3; + +public class AttackProcess extends BaritoneProcessHelper implements IAttackProcess { + private boolean rotating = false; + private boolean attacking = false; + + public AttackProcess(Baritone baritone) { + super(baritone); + } + + @Override + public boolean isActive() { + this.rotating = false; + this.attacking = false; + return ctx.player() != null && + ctx.world() != null && + Baritone.settings().entityAttackRadius.value != 0D && + (this.baritone.getFollowProcess().isActive() || this.baritone.getPathingBehavior().isPathing()); + } + + @Override + public PathingCommand onTick(boolean calcFailed, boolean isSafeToCancel) { + this.baritone.getInputOverrideHandler().clearAllKeys(); + double closestDistance = Double.MAX_VALUE; + Vec3 closestPosition = null; + for (Entity entity : ctx.entities()) { + if (!entity.is(ctx.player()) && entity instanceof LivingEntity && entity.isAlive() && entity.isAttackable()) { + Vec3 attackPoint = new Vec3( + entity.getBoundingBox().getCenter().x(),//Mth.clamp(ctx.playerHead().x(), entity.getBoundingBox().minX, entity.getBoundingBox().maxX), + Mth.clamp(ctx.playerHead().y(), entity.getBoundingBox().minY, entity.getBoundingBox().maxY), + entity.getBoundingBox().getCenter().z()//Mth.clamp(ctx.playerHead().z(), entity.getBoundingBox().minZ, entity.getBoundingBox().maxZ) + ); + double distance = this.ctx.player().getEyePosition().distanceToSqr(attackPoint); + if (distance < closestDistance) { + closestDistance = distance; + closestPosition = attackPoint; + } + } + } + if (closestPosition != null && Math.sqrt(closestDistance) <= Baritone.settings().entityAttackRadius.value) { + if (!Baritone.settings().assumeExternalAutoAim.value) { + this.rotating = true; + this.baritone.getLookBehavior().updateTarget( + RotationUtils.calcRotationFromVec3d(this.ctx.playerHead(), closestPosition, this.ctx.playerRotations()), + true + ); + } + if (!Baritone.settings().assumeExternalKillAura.value) { + HitResult hitResult = ctx.minecraft().hitResult; + if (hitResult != null && hitResult.getType().equals(HitResult.Type.ENTITY)) { + this.attacking = true; + } + } + } + return new PathingCommand(null, PathingCommandType.DEFER); + } + + @Override + public void onLostControl() {} + + @Override + public String displayName0() { + return "Attack"; + } + + @Override + public boolean isTemporary() { + return true; + } + + @Override + public double priority() { + return 5; + } + + @Override + public boolean isRotating() { + return this.rotating; + } + + @Override + public boolean isAttacking() { + return this.attacking; + } +} diff --git a/src/main/java/baritone/process/FollowProcess.java b/src/main/java/baritone/process/FollowProcess.java index 0be7a4e80..b7486ca30 100644 --- a/src/main/java/baritone/process/FollowProcess.java +++ b/src/main/java/baritone/process/FollowProcess.java @@ -27,6 +27,7 @@ import baritone.api.process.PathingCommand; import baritone.api.process.PathingCommandType; import baritone.api.utils.BetterBlockPos; +import baritone.api.utils.RotationUtils; import baritone.utils.BaritoneProcessHelper; import net.minecraft.core.BlockPos; import net.minecraft.world.entity.Entity; @@ -34,6 +35,7 @@ import net.minecraft.world.item.ItemStack; import java.util.List; +import java.util.Random; import java.util.function.Predicate; import java.util.stream.Collectors; @@ -47,6 +49,8 @@ public final class FollowProcess extends BaritoneProcessHelper implements IFollo private Predicate filter; private List cache; private boolean into; // walk straight into the target, regardless of settings + private boolean switchDirection = false; + private static final Random random = new Random(); // TODO global random instance public FollowProcess(Baritone baritone) { super(baritone); @@ -56,6 +60,9 @@ public FollowProcess(Baritone baritone) { public PathingCommand onTick(boolean calcFailed, boolean isSafeToCancel) { scanWorld(); Goal goal = new GoalComposite(cache.stream().map(this::towards).toArray(Goal[]::new)); + if (Baritone.settings().followCircleSwitchDirectionChance.value >= random.nextDouble(0, 100)) { + switchDirection = !switchDirection; + } return new PathingCommand(goal, PathingCommandType.REVALIDATE_GOAL_AND_PATH); } @@ -64,7 +71,19 @@ private Goal towards(Entity following) { if (Baritone.settings().followOffsetDistance.value == 0 || into) { pos = following.blockPosition(); } else { - GoalXZ g = GoalXZ.fromDirection(following.position(), Baritone.settings().followOffsetDirection.value, Baritone.settings().followOffsetDistance.value); + GoalXZ g = GoalXZ.fromDirection( + following.position(), + // I love me some ternary operators + Baritone.settings().followCircle.value ? + RotationUtils.calcRotationFromVec3d( + following.getEyePosition(), + ctx.playerHead(), + ctx.playerRotations()).getYaw() + + (switchDirection ? -Baritone.settings().followCircleIncrement.value : + Baritone.settings().followCircleIncrement.value) : + Baritone.settings().followOffsetDirection.value, + Baritone.settings().followOffsetDistance.value + ); pos = new BetterBlockPos(g.getX(), following.position().y, g.getZ()); } if (into) { diff --git a/src/main/java/baritone/utils/BlockBreakHelper.java b/src/main/java/baritone/utils/BlockBreakHelper.java deleted file mode 100644 index 0c5cf6f00..000000000 --- a/src/main/java/baritone/utils/BlockBreakHelper.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * 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 . - */ - -package baritone.utils; - -import baritone.api.BaritoneAPI; -import baritone.api.utils.IPlayerContext; -import baritone.utils.accessor.IPlayerControllerMP; -import net.minecraft.world.InteractionHand; -import net.minecraft.world.phys.BlockHitResult; -import net.minecraft.world.phys.HitResult; - -/** - * @author Brady - * @since 8/25/2018 - */ -public final class BlockBreakHelper { - // base ticks between block breaks caused by tick logic - private static final int BASE_BREAK_DELAY = 1; - - private final IPlayerContext ctx; - private boolean wasHitting; - private int breakDelayTimer = 0; - - BlockBreakHelper(IPlayerContext ctx) { - this.ctx = ctx; - } - - public void stopBreakingBlock() { - // The player controller will never be null, but the player can be - if (ctx.player() != null && wasHitting) { - ctx.playerController().setHittingBlock(false); - ctx.playerController().resetBlockRemoving(); - wasHitting = false; - } - } - - public void tick(boolean isLeftClick) { - if (breakDelayTimer > 0) { - breakDelayTimer--; - return; - } - HitResult trace = ctx.objectMouseOver(); - boolean isBlockTrace = trace != null && trace.getType() == HitResult.Type.BLOCK; - - if (isLeftClick && isBlockTrace) { - ctx.playerController().setHittingBlock(wasHitting); - if (ctx.playerController().hasBrokenBlock()) { - ctx.playerController().syncHeldItem(); - ctx.playerController().clickBlock(((BlockHitResult) trace).getBlockPos(), ((BlockHitResult) trace).getDirection()); - ctx.player().swing(InteractionHand.MAIN_HAND); - } else { - if (ctx.playerController().onPlayerDamageBlock(((BlockHitResult) trace).getBlockPos(), ((BlockHitResult) trace).getDirection())) { - ctx.player().swing(InteractionHand.MAIN_HAND); - } - if (ctx.playerController().hasBrokenBlock()) { // block broken this tick - // break delay timer only applies for multi-tick block breaks like vanilla - breakDelayTimer = BaritoneAPI.getSettings().blockBreakSpeed.value - BASE_BREAK_DELAY; - // must reset controller's destroy delay to prevent the client from delaying itself unnecessarily - ((IPlayerControllerMP) ctx.minecraft().gameMode).setDestroyDelay(0); - } - } - // if true, we're breaking a block. if false, we broke the block this tick - wasHitting = !ctx.playerController().hasBrokenBlock(); - // this value will be reset by the MC client handling mouse keys - // since we're not spoofing the click keybind to the client, the client will stop the break if isDestroyingBlock is true - // we store and restore this value on the next tick to determine if we're breaking a block - ctx.playerController().setHittingBlock(false); - } else { - wasHitting = false; - } - } -} diff --git a/src/main/java/baritone/utils/InputOverrideHandler.java b/src/main/java/baritone/utils/InputOverrideHandler.java index 38a32f515..1bc5c35e8 100755 --- a/src/main/java/baritone/utils/InputOverrideHandler.java +++ b/src/main/java/baritone/utils/InputOverrideHandler.java @@ -43,12 +43,12 @@ public final class InputOverrideHandler extends Behavior implements IInputOverri */ private final Map inputForceStateMap = new HashMap<>(); - private final BlockBreakHelper blockBreakHelper; + private final LeftClickHelper leftClickHelper; private final BlockPlaceHelper blockPlaceHelper; public InputOverrideHandler(Baritone baritone) { super(baritone); - this.blockBreakHelper = new BlockBreakHelper(baritone.getPlayerContext()); + this.leftClickHelper = new LeftClickHelper(baritone.getPlayerContext()); this.blockPlaceHelper = new BlockPlaceHelper(baritone.getPlayerContext()); } @@ -59,8 +59,8 @@ public InputOverrideHandler(Baritone baritone) { * @return Whether or not it is being forced down */ @Override - public final boolean isInputForcedDown(Input input) { - return input == null ? false : this.inputForceStateMap.getOrDefault(input, false); + public boolean isInputForcedDown(Input input) { + return input != null && this.inputForceStateMap.getOrDefault(input, false); } /** @@ -70,7 +70,7 @@ public final boolean isInputForcedDown(Input input) { * @param forced Whether or not the state is being forced */ @Override - public final void setInputForceState(Input input, boolean forced) { + public void setInputForceState(Input input, boolean forced) { this.inputForceStateMap.put(input, forced); } @@ -78,19 +78,23 @@ public final void setInputForceState(Input input, boolean forced) { * Clears the override state for all keys */ @Override - public final void clearAllKeys() { + public void clearAllKeys() { this.inputForceStateMap.clear(); } @Override - public final void onTick(TickEvent event) { + public void onTick(TickEvent event) { if (event.getType() == TickEvent.Type.OUT) { return; } + + if (baritone.getAttackProcess().isAttacking()) { + setInputForceState(Input.CLICK_LEFT, true); + } if (isInputForcedDown(Input.CLICK_LEFT)) { setInputForceState(Input.CLICK_RIGHT, false); } - blockBreakHelper.tick(isInputForcedDown(Input.CLICK_LEFT)); + leftClickHelper.tick(isInputForcedDown(Input.CLICK_LEFT)); blockPlaceHelper.tick(isInputForcedDown(Input.CLICK_RIGHT)); if (inControl()) { @@ -116,7 +120,7 @@ private boolean inControl() { return baritone.getPathingBehavior().isPathing() || baritone != BaritoneAPI.getProvider().getPrimaryBaritone(); } - public BlockBreakHelper getBlockBreakHelper() { - return blockBreakHelper; + public LeftClickHelper getLeftClickHelper() { + return leftClickHelper; } } diff --git a/src/main/java/baritone/utils/LeftClickHelper.java b/src/main/java/baritone/utils/LeftClickHelper.java new file mode 100644 index 000000000..007a7d256 --- /dev/null +++ b/src/main/java/baritone/utils/LeftClickHelper.java @@ -0,0 +1,84 @@ +/* + * 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 . + */ + +package baritone.utils; + +import baritone.Baritone; +import baritone.api.utils.IPlayerContext; +import net.minecraft.client.KeyMapping; +import net.minecraft.world.phys.HitResult; + +/** + * @author Brady + * @since 8/25/2018 + */ +public final class LeftClickHelper { + // base ticks between block breaks caused by tick logic + private static final int BASE_BREAK_DELAY = 1; + + private final IPlayerContext ctx; + private boolean isBreaking = false; + private int breakDelayTimer = 0; + private int leftClickTimer = 0; + + LeftClickHelper(IPlayerContext ctx) { + this.ctx = ctx; + } + + public void stopBreakingBlock() { + isBreaking = false; + ctx.minecraft().options.keyAttack.setDown(false); + } + + public void tick(boolean isLeftClick) { + if (leftClickTimer > 0) { + leftClickTimer--; + } + if (breakDelayTimer > 0) { + breakDelayTimer--; + } + HitResult trace = ctx.minecraft().hitResult; + if (isLeftClick && trace != null) { + switch (trace.getType()) { + case ENTITY: + stopBreakingBlock(); + if (leftClickTimer <= 0 && (!Baritone.settings().timedAttacks.value || ctx.player().getAttackStrengthScale(0f) == 1f)) { + leftClickTimer = Baritone.settings().leftClickSpeed.value; + KeyMapping.click(ctx.minecraft().options.keyAttack.getDefaultKey()); + } + break; + case BLOCK: + if (breakDelayTimer <= 0) { + if (!isBreaking) { + isBreaking = true; + KeyMapping.click(ctx.minecraft().options.keyAttack.getDefaultKey()); + } + ctx.minecraft().options.keyAttack.setDown(true); + if (ctx.playerController().hasBrokenBlock()) { + breakDelayTimer = Baritone.settings().blockBreakSpeed.value - BASE_BREAK_DELAY; + } + } + break; + default: + stopBreakingBlock(); + break; + } + } else { + stopBreakingBlock(); + } + } +}