From ab00a71e84d4b642d6f63f2e748b0b7bec4a7c28 Mon Sep 17 00:00:00 2001 From: Dawson <30784509+funkemunky@users.noreply.github.com> Date: Sat, 18 Feb 2023 10:46:08 -0500 Subject: [PATCH] Fixing false positives --- .../check/impl/movement/speed/Horizontal.java | 66 +++++++++-- .../brighten/ac/handler/MovementHandler.java | 109 ++++++++---------- 2 files changed, 102 insertions(+), 73 deletions(-) diff --git a/src/main/java/dev/brighten/ac/check/impl/movement/speed/Horizontal.java b/src/main/java/dev/brighten/ac/check/impl/movement/speed/Horizontal.java index c6ca471..7a3fcfb 100644 --- a/src/main/java/dev/brighten/ac/check/impl/movement/speed/Horizontal.java +++ b/src/main/java/dev/brighten/ac/check/impl/movement/speed/Horizontal.java @@ -6,32 +6,66 @@ import dev.brighten.ac.check.CheckData; import dev.brighten.ac.check.WAction; import dev.brighten.ac.check.impl.misc.inventory.InventoryA; import dev.brighten.ac.data.APlayer; +import dev.brighten.ac.packet.ProtocolVersion; import dev.brighten.ac.packet.wrapper.in.WPacketPlayInFlying; +import dev.brighten.ac.utils.Color; +import dev.brighten.ac.utils.KLocation; +import dev.brighten.ac.utils.timer.Timer; +import dev.brighten.ac.utils.timer.impl.TickTimer; +import me.hydro.emulator.object.iteration.Motion; import java.util.Optional; @CheckData(name = "Horizontal", checkId = "horizontala", type = CheckType.MOVEMENT, experimental = true) public class Horizontal extends Check { private float buffer; + private boolean maybeSkippedPos; + private int lastFlying; + private final Timer lastSkipPos = new TickTimer(); public Horizontal(APlayer player) { super(player); } WAction flying = packet -> { - if(!packet.isMoved()) return; - double offset = player.EMULATOR.getOffset(); + check: { + if(!packet.isMoved() + || player.getMovement().getLastTeleport().isNotPassed(1) + || player.getInfo().getVelocity().isNotPassed(2) + || player.getBlockInfo().onClimbable + || player.getInfo().lastLiquid.isNotPassed(2) + || player.getInfo().isGeneralCancel()) break check; - if(offset > 1E-6) { - if(++buffer > 1) { - flag("o=%s", offset); - } - } else if(buffer > 0) buffer-= 0.1f; + double offset = player.EMULATOR.getOffset(); + int forward = player.EMULATOR.getInput().getForward(); + int strafe = player.EMULATOR.getInput().getStrafing(); + String tags = String.join(", ", player.EMULATOR.getTags()); + Motion predicted = player.getMovement().getPredicted(); - debug("dx=%s dz=%s offset=%s f=%s s=%s tags[%s]", player.getMovement().getDeltaX(), - player.getMovement().getDeltaZ(), player.EMULATOR.getOffset(), player.EMULATOR.getInput().getForward(), - player.EMULATOR.getInput().getStrafing(), String.join(", ", player.EMULATOR.getTags())); + boolean zeroThree = + predicted.getMotionX() * predicted.getMotionX() + + predicted.getMotionY() * predicted.getMotionY() + + predicted.getMotionZ() * predicted.getMotionZ() < 9E-4; + + boolean badOffset = offset > (lastSkipPos.isNotPassed(4) ? 0.03 : 5E-4); + + if(badOffset) { + debug("[%s] dx=%.6f px=%.6f dz=%.6f pz=%.6f dy=%.6f py=%.6f", zeroThree, player.getMovement().getDeltaX(), + predicted.getMotionX(), player.getMovement().getDeltaZ(), predicted.getMotionZ(), + player.getMovement().getDeltaY(), predicted.getMotionY()); + KLocation loc = player.getMovement().getFrom().getLoc().clone() + .add(predicted.getMotionX(), predicted.getMotionY(), predicted.getMotionZ()); + + if(++buffer > 5) { + flag("%s", offset); + correctMovement(loc); + buffer = 4; + } + } else if(buffer > 0) buffer-= 0.1f; + debug((badOffset ? Color.Red : "") + "offset=%s f=%s s=%s py=%.3f tags=[%s]", + offset, forward, strafe, predicted.getMotionY(), tags); + } // Running inventory check Optional inventoryA = find(InventoryA.class); @@ -53,7 +87,19 @@ public class Horizontal extends Check { player.getInfo().isInventoryOpen(), STRAFING, FORWARD); }); + if (ProtocolVersion.getGameVersion().isBelow(ProtocolVersion.V1_9)) { + maybeSkippedPos = !packet.isMoved(); + } else { + if (player.getPlayerTick() - lastFlying > 1) { + maybeSkippedPos = true; + debug("maybe skipped pos"); + } + lastFlying = player.getPlayerTick(); + } + if (maybeSkippedPos) { + lastSkipPos.reset(); + } }; private static float roundToFloat(double d) { diff --git a/src/main/java/dev/brighten/ac/handler/MovementHandler.java b/src/main/java/dev/brighten/ac/handler/MovementHandler.java index 61999e5..9ca0393 100644 --- a/src/main/java/dev/brighten/ac/handler/MovementHandler.java +++ b/src/main/java/dev/brighten/ac/handler/MovementHandler.java @@ -18,6 +18,7 @@ import lombok.Getter; import lombok.Setter; import lombok.val; import me.hydro.emulator.object.input.IterationInput; +import me.hydro.emulator.object.iteration.Motion; import me.hydro.emulator.object.result.IterationResult; import me.hydro.emulator.util.mcp.MathHelper.FastMathType; import me.hydro.emulator.util.PotionEffect; @@ -39,6 +40,9 @@ public class MovementHandler { @Getter private double deltaX, deltaY, deltaZ, deltaXZ, lDeltaX, lDeltaY, lDeltaZ, lDeltaXZ; + + @Getter + private Motion predicted; @Getter private float lookX, lookY, lastLookX, lastLookY; @Getter @@ -97,30 +101,6 @@ public class MovementHandler { from.setLoc(to); } - /** - * // Here we'll build the iteration input object we'll feed into the emulator - * final IterationInput input = IterationInput.builder() - * .to(new Vector(1, 2, 3)) // location from the flying packet - * .yaw(5F) // current yaw - * .ground(false) - * .jumping(false) // you'll want to bruteforce this - * .forward(0) // you'll want to bruteforce this - * .strafing(0) // you'll want to bruteforce this - * .sprinting(false) // you'll want to bruteforce this - * .usingItem(false) // you'll want to bruteforce this - * .hitSlowdown(false) // you'll want to bruteforce this - * .sneaking(false) - * .lastReportedBoundingBox(new AxisAlignedBB(0, 0, 0, 0, 0, 0)) // from location, as a bounding box - * .build(); - *

- * // Run the emulation and get the result - * final IterationResult result = emulator.runIteration(input); - *

- * // Once we've found our best candidate (in the case of a bruteforce), - * // confirm it to run post actions. - * emulator.confirm(result.getIteration()); - */ - private static final boolean[] IS_OR_NOT = new boolean[]{true, false}; private static final boolean[] ALWAYS_FALSE = new boolean[1]; private static final int[] FULL_RANGE = new int[]{-1, 0, 1}; @@ -154,37 +134,43 @@ public class MovementHandler { } IterationResult minimum = null; - for (int forward : FULL_RANGE) { - for (int strafe : FULL_RANGE) { - for (boolean jumping : getJumpingIterations()) { - for (boolean usingItem : getUsingItemIterations(forward, strafe)) { - for (boolean sprinting : getSprintingIterations(forward)) { - for (boolean hitSlow : (player.getInfo().lastAttack.isNotPassed(1) - ? IS_OR_NOT : ALWAYS_FALSE)) { - for (FastMathType fastMath : getFastMathIterations()) { - IterationInput input = IterationInput.builder() - .jumping(jumping) - .forward(forward) - .strafing(strafe) - .sprinting(sprinting) - .usingItem(usingItem) - .hitSlowdown(hitSlow) - .aiMoveSpeed(player.getBukkitPlayer().getWalkSpeed() / 2) - .fastMathType(fastMath) - .sneaking(player.getInfo().isSneaking()) - .ground(from.isOnGround()) - .to(new Vector(to.getX(), to.getY(), to.getZ())) - .yaw(to.getYaw()) - .lastReportedBoundingBox(from.getBox().toNeo()) - .effectSpeed(EFFECTS[0]) - .effectSlow(EFFECTS[1]) - .effectJump(EFFECTS[2]) - .build(); + iteration: { + for (int forward : FULL_RANGE) { + for (int strafe : FULL_RANGE) { + for (boolean jumping : getJumpingIterations()) { + for (boolean usingItem : getUsingItemIterations(forward, strafe)) { + for (boolean sprinting : getSprintingIterations(forward)) { + for (boolean hitSlow : (player.getInfo().lastAttack.isNotPassed(1) + ? IS_OR_NOT : ALWAYS_FALSE)) { + for (FastMathType fastMath : getFastMathIterations()) { + IterationInput input = IterationInput.builder() + .jumping(jumping) + .forward(forward) + .strafing(strafe) + .sprinting(sprinting) + .usingItem(usingItem) + .hitSlowdown(hitSlow) + .aiMoveSpeed(player.getBukkitPlayer().getWalkSpeed() / 2) + .fastMathType(fastMath) + .sneaking(player.getInfo().isSneaking()) + .ground(from.isOnGround()) + .to(new Vector(to.getX(), to.getY(), to.getZ())) + .yaw(to.getYaw()) + .lastReportedBoundingBox(from.getBox().toNeo()) + .effectSpeed(EFFECTS[0]) + .effectSlow(EFFECTS[1]) + .effectJump(EFFECTS[2]) + .build(); - IterationResult result = player.EMULATOR.runIteration(input); + IterationResult result = player.EMULATOR.runIteration(input); - if (minimum == null || minimum.getOffset() > result.getOffset()) { - minimum = result; + if (minimum == null || minimum.getOffset() > result.getOffset()) { + minimum = result; + + if(minimum.getOffset() < 1E-26) { + break iteration; + } + } } } } @@ -195,11 +181,12 @@ public class MovementHandler { } if(minimum != null) { - if (minimum.getOffset() > 1E-10) { + predicted = minimum.getMotion().clone(); + if (minimum.getOffset() > 1E-8) { minimum.getTags().add("bad_offset"); - minimum.getIteration().getMotion().setMotionX(deltaX); - minimum.getIteration().getMotion().setMotionY(deltaY); - minimum.getIteration().getMotion().setMotionZ(deltaZ); + minimum.getMotion().setMotionX(deltaX); + minimum.getMotion().setMotionY(deltaY); + minimum.getMotion().setMotionZ(deltaZ); } player.EMULATOR.confirm(minimum.getIteration()); } @@ -216,7 +203,7 @@ public class MovementHandler { } private boolean[] getSprintingIterations(int forward) { - if (player.getInfo().isSneaking() || forward <= 0) + if (player.getInfo().isSneaking()) return ALWAYS_FALSE; return IS_OR_NOT; @@ -226,12 +213,8 @@ public class MovementHandler { return forward == 0 && strafe == 0 ? ALWAYS_FALSE : IS_OR_NOT; } - private int[] getStrafeAndForwardIterations() { - return deltaXZ == 0 ? new int[]{0} : FULL_RANGE; - } - private boolean[] getJumpingIterations() { - return deltaY <= lDeltaY ? ALWAYS_FALSE : IS_OR_NOT; + return IS_OR_NOT; }