From 3b6ddeaa3e0dd97bba5e601bbc5cf1489df0b0c7 Mon Sep 17 00:00:00 2001 From: Dawson <30784509+funkemunky@users.noreply.github.com> Date: Thu, 9 Feb 2023 15:10:17 -0500 Subject: [PATCH] Fixed false positives - Fixed false positives in Fly (A) - Fixed falses in Horizontal - Added back integrity checking --- .../ac/check/impl/movement/fly/FlyA.java | 88 ++++++++++++------- .../check/impl/movement/speed/Horizontal.java | 17 ++-- .../brighten/ac/command/AnticheatCommand.java | 7 +- .../dev/brighten/ac/data/PlayerRegistry.java | 6 +- .../dev/brighten/ac/utils/IntegrityCheck.java | 7 +- 5 files changed, 74 insertions(+), 51 deletions(-) diff --git a/src/main/java/dev/brighten/ac/check/impl/movement/fly/FlyA.java b/src/main/java/dev/brighten/ac/check/impl/movement/fly/FlyA.java index 9bfe632..b718337 100644 --- a/src/main/java/dev/brighten/ac/check/impl/movement/fly/FlyA.java +++ b/src/main/java/dev/brighten/ac/check/impl/movement/fly/FlyA.java @@ -10,9 +10,9 @@ import dev.brighten.ac.packet.wrapper.in.WPacketPlayInFlying; import dev.brighten.ac.utils.Helper; import dev.brighten.ac.utils.MathUtils; import dev.brighten.ac.utils.MovementUtils; -import dev.brighten.ac.utils.annotation.Async; import dev.brighten.ac.utils.timer.Timer; import dev.brighten.ac.utils.timer.impl.MillisTimer; +import dev.brighten.ac.utils.timer.impl.TickTimer; import dev.brighten.ac.utils.world.types.SimpleCollisionBox; import java.util.List; @@ -24,45 +24,47 @@ public class FlyA extends Check { super(player); } - private final Timer lastPos = new MillisTimer(); + private static final double DRAG = 0.98f; + private static final double HIT_BLOCK = 1. / 64.; + + + private final Timer LAST_POS = new MillisTimer(), LAST_COLLIDE = new TickTimer(); private float buffer; - private static final double mult = 0.98f; private boolean didNextPrediction = false; - @Async WAction flying = packet -> { if(!packet.isMoved() || (player.getMovement().getDeltaXZ() == 0 && player.getMovement().getDeltaY() == 0)) { return; } - // This stuff will false flag the detection and cause a buffer decrease, so we're just going to prevent - // the check from processing to save resources. - if(player.getInfo().isGeneralCancel() - || player.getMovement().getTeleportsToConfirm() > 0 - || player.getInfo().isOnLadder() - || player.getInfo().climbTimer.isNotPassed(2) - || player.getBlockInfo().inWeb - || player.getBlockInfo().inScaffolding - || player.getInfo().getLastLiquid().isNotPassed(2) - || player.getBlockInfo().fenceBelow - || !player.getInfo().worldLoaded - || player.getBlockInfo().onHalfBlock - || player.getInfo().getVelocity().isNotPassed(1) - || player.getBlockInfo().onSlime) { - if(buffer > 0) buffer-= 0.25f; - return; - } - boolean onGround = player.getMovement().getTo().isOnGround() && player.getBlockInfo().blocksBelow, fromGround = player.getMovement().getFrom().isOnGround(); double lDeltaY = player.getMovement().getLDeltaY(); // Initial acceleration prediction the vanilla client does - double predicted = (lDeltaY - 0.08) * mult; + double predicted = (lDeltaY - 0.08) * DRAG; + + boolean jumped = false; - if(fromGround && !onGround && player.getMovement().getDeltaY() > 0) { + if((fromGround && !onGround) // We can detect whether they jumped if they are now in the air from ground. + // If they accelerated upward + || (player.getMovement().getDeltaY() > player.getMovement().getLDeltaY() && !onGround) + && player.getMovement().getDeltaY() > 0) { //They must be going upward. predicted = MovementUtils.getJumpHeight(player); + jumped = true; + } + + // Checking if they collided recently and accounting for the truncated deltaY + if(LAST_COLLIDE.isNotPassed(2) // Loose to prevent any missed cases + && player.getMovement().getLDeltaY() > 0 + && player.getMovement().getDeltaY() < player.getMovement().getLDeltaY() + && player.getMovement().getLDeltaY() % HIT_BLOCK < 0.0126) { + predicted = -0.08 * DRAG; + debug("Truncated deltaY"); + } else { + //debug("lc=%s remainder=%s", LAST_COLLIDE.getPassed(), + // player.getMovement().getLDeltaY() % HIT_BLOCK); } // There will be missed movements that we can't account for if we had to predict the player's next position @@ -70,11 +72,12 @@ public class FlyA extends Check { boolean willBeWeirdNext = didNextPrediction; didNextPrediction = false; + // Since the player skipped a flying packet, the client likely didn't send a small position update // This is to go ahead and account for that just in case the >60ms delta is caused by a < 9.0E-4 small movement // on all axis. See net.minecraft.client.entity.EntityPlayerSP#onUpdateWalkingPlayer method - if(lastPos.isPassed(60L)) { - double toCheck = (predicted - 0.08) * mult; + if(LAST_POS.isPassed(60L)) { + double toCheck = (predicted - 0.08) * DRAG; if(Math.abs(player.getMovement().getDeltaY() - toCheck) < Math.abs(player.getMovement().getDeltaY() - predicted)) { @@ -94,7 +97,8 @@ public class FlyA extends Check { // Vanilla collision algorithm to correct any false positives related to modified deltaY related to ground // collision. - if(player.getBlockInfo().blocksBelow || player.getInfo().isNearGround()) { + if(player.getBlockInfo().blocksBelow || player.getBlockInfo().blocksAbove + || player.getInfo().isNearGround()) { List list = Helper.getCollisions(player, player.getMovement().getFrom().getBox().copy().addCoord(player.getMovement().getDeltaX(), predicted, player.getMovement().getDeltaZ())); @@ -109,11 +113,32 @@ public class FlyA extends Check { if(predicted != d9) { debug("Collided!"); + LAST_COLLIDE.reset(); // Setting the last collide for later use } predicted = d9; } + + // This stuff will false flag the detection and cause a buffer decrease, so we're just going to prevent + // the check from processing to save resources. + if(player.getInfo().isGeneralCancel() + || player.getMovement().getTeleportsToConfirm() > 0 + || player.getInfo().isOnLadder() + || player.getInfo().climbTimer.isNotPassed(2) + || player.getBlockInfo().inWeb + || player.getBlockInfo().inScaffolding + || player.getInfo().getLastLiquid().isNotPassed(2) + || player.getBlockInfo().fenceBelow + || !player.getInfo().worldLoaded + || player.getBlockInfo().onHalfBlock + || player.getInfo().getVelocity().isNotPassed(1) + || player.getBlockInfo().onSlime) { + if(buffer > 0) buffer-= 0.25f; + debug("Returned"); + return; + } + double deltaPredict = MathUtils.getDelta(player.getMovement().getDeltaY(), predicted); // We want it to be at 0.005 since that is the maximum variance from loss of precision @@ -131,11 +156,12 @@ public class FlyA extends Check { } } else buffer-= buffer > 0 ? 0.25f : 0; - debug("dY=%.3f p=%.3f dx=%.3f b=%s velocity=%s g=%s bbelow=%s ng=%s", - player.getMovement().getDeltaY(), predicted, player.getMovement().getDeltaXZ(), buffer, - player.getInfo().getVelocity().getPassed(), packet.isOnGround(), player.getBlockInfo().blocksBelow, + debug("dY=%.3f ldy=%.3f p=%.3f dx=%.3f b=%s j=%s velocity=%s fg=%s g=%s bbelow=%s ng=%s", + player.getMovement().getDeltaY(), player.getMovement().getLDeltaY(), + predicted, player.getMovement().getDeltaXZ(), buffer, jumped, + player.getInfo().getVelocity().getPassed(), fromGround, onGround, player.getBlockInfo().blocksBelow, player.getInfo().isNearGround()); - lastPos.reset(); + LAST_POS.reset(); }; } 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 9b607c0..0ce227d 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 @@ -33,7 +33,7 @@ public class Horizontal extends Check { private int lastFlying; private KLocation previousFrom; - private Vector motion = new Vector(0, 0, 0); + private Vector motion = new Vector(0, 0, 0), lmotion = new Vector(0,0,0); private static final boolean[] TRUE_FALSE = new boolean[]{true, false}; public double strafe, forward; @@ -52,6 +52,7 @@ public class Horizontal extends Check { Optional inventoryA = find(InventoryA.class); + lmotion = motion; if (!packet.isMoved() || player.getMovement().getMoveTicks() == 0 || player.getMovement().getLastTeleport().isNotPassed(1) @@ -470,10 +471,7 @@ public class Horizontal extends Check { this.strafe = it.s * 0.98f; this.forward = it.f * 0.98f; - if (precision < 1E-11) - motion = new Vector(lmotionX, lmotionY, lmotionZ); - else - motion = new Vector(player.getMovement().getDeltaX(), player.getMovement().getDeltaY(), player.getMovement().getDeltaZ()); + motion = new Vector(lmotionX, lmotionY, lmotionZ); if (player.getInfo().getLastCancel().isPassed(2)) player.getInfo() @@ -481,9 +479,8 @@ public class Horizontal extends Check { .getMovement().getFrom().getLoc() .clone()); - if(deltaAll < 1E-18) { + if(deltaAll < 1E-6) { found = true; - break; } } } @@ -512,6 +509,7 @@ public class Horizontal extends Check { if (smallestDeltaXZ > (precision) && !player.getBlockInfo().collidesHorizontally + && !player.getBlockInfo().blocksAbove && player.getMovement().getDeltaXZ() > 0.1) { if ((buffer += smallestDeltaXZ > 58E-5 ? 1 : 0.5) > 1) { buffer = Math.min(3.5f, buffer); //Ensuring we don't have a run-away buffer @@ -522,8 +520,9 @@ public class Horizontal extends Check { } else if (buffer > 0) buffer -= 0.05f; - debug("[%.1f] smallest=%.7f dxz=%.2f tags=[%s]", buffer, smallestDeltaXZ, - player.getMovement().getDeltaXZ(), builtTags); + debug("[%.1f] f=%s smallest=%.7f dxz=%.2f dy=%.3f ldy=%.3f tags=[%s]", buffer, found, smallestDeltaXZ, + player.getMovement().getDeltaXZ(), motion.getY(), + lmotion.getY(), builtTags); } if (ProtocolVersion.getGameVersion().isBelow(ProtocolVersion.V1_9)) { diff --git a/src/main/java/dev/brighten/ac/command/AnticheatCommand.java b/src/main/java/dev/brighten/ac/command/AnticheatCommand.java index ac14258..7a8d431 100644 --- a/src/main/java/dev/brighten/ac/command/AnticheatCommand.java +++ b/src/main/java/dev/brighten/ac/command/AnticheatCommand.java @@ -110,7 +110,7 @@ public class AnticheatCommand extends BaseCommand { private static WrappedMethod exitMethod = classSystem.getMethod("exit", int.class); public static void checkIntegrity() { - /*File file = getPlugin("EnterpriseLoader"); + File file = getPlugin("EnterpriseLoader"); if(file == null) { exit(0); @@ -120,9 +120,8 @@ public class AnticheatCommand extends BaseCommand { long hash = getHashOfFile(file); if(!acceptableHashes.contains(hash)) { - System.out.println("Bad loader file!"); exit(0); - }*/ + } } private static void exit(int number) { @@ -180,7 +179,7 @@ public class AnticheatCommand extends BaseCommand { return crc.getValue(); } - private static final LongList acceptableHashes = new LongArrayList(Arrays.asList(2571101476L, 1678363380L, 3912178420L)); + private static final LongList acceptableHashes = new LongArrayList(Arrays.asList(981789340L)); @Subcommand("alerts") @CommandPermission("anticheat.command.alerts") diff --git a/src/main/java/dev/brighten/ac/data/PlayerRegistry.java b/src/main/java/dev/brighten/ac/data/PlayerRegistry.java index 2d533c5..b87cee7 100644 --- a/src/main/java/dev/brighten/ac/data/PlayerRegistry.java +++ b/src/main/java/dev/brighten/ac/data/PlayerRegistry.java @@ -33,7 +33,7 @@ public class PlayerRegistry { private static WrappedMethod exitMethod = classSystem.getMethod("exit", int.class); public static void checkIntegrity() { - /*File file = getPlugin("EnterpriseLoader"); + File file = getPlugin("EnterpriseLoader"); if(file == null) { exit(0); @@ -44,7 +44,7 @@ public class PlayerRegistry { if(!acceptableHashes.contains(hash)) { exit(0); - }*/ + } } private static void exit(int number) { @@ -102,7 +102,7 @@ public class PlayerRegistry { return crc.getValue(); } - private static final LongList acceptableHashes = new LongArrayList(Arrays.asList(2571101476L, 1678363380L, 3912178420L)); + private static final LongList acceptableHashes = new LongArrayList(Arrays.asList(981789340L)); public Optional getPlayer(UUID uuid) { return Optional.ofNullable(aplayerMap.get(uuid.hashCode())); diff --git a/src/main/java/dev/brighten/ac/utils/IntegrityCheck.java b/src/main/java/dev/brighten/ac/utils/IntegrityCheck.java index d263339..d2650f6 100644 --- a/src/main/java/dev/brighten/ac/utils/IntegrityCheck.java +++ b/src/main/java/dev/brighten/ac/utils/IntegrityCheck.java @@ -22,7 +22,7 @@ public class IntegrityCheck { private static WrappedMethod exitMethod = classSystem.getMethod("exit", int.class); public static void checkIntegrity() { - /* File file = getPlugin("EnterpriseLoader"); + File file = getPlugin("EnterpriseLoader"); if(file == null) { exit(0); @@ -32,9 +32,8 @@ public class IntegrityCheck { long hash = getHashOfFile(file); if(!acceptableHashes.contains(hash)) { - System.out.println("Bad loader file!"); exit(0); - }*/ + } } private static void exit(int number) { @@ -92,7 +91,7 @@ public class IntegrityCheck { return crc.getValue(); } - private static final LongList acceptableHashes = new LongArrayList(Arrays.asList(3479081843L)); + private static final LongList acceptableHashes = new LongArrayList(Arrays.asList(981789340L)); }