From 00c502c1925314a444a57a25445e69655e7fa02a Mon Sep 17 00:00:00 2001 From: Dawson <30784509+funkemunky@users.noreply.github.com> Date: Mon, 13 Feb 2023 10:21:28 -0500 Subject: [PATCH] Adding neo --- pom.xml | 10 +- src/main/java/dev/brighten/ac/Anticheat.java | 39 ++ .../java/dev/brighten/ac/check/Check.java | 16 + .../ac/check/impl/movement/fly/FlyB.java | 37 +- .../check/impl/movement/speed/Horizontal.java | 647 +----------------- .../java/dev/brighten/ac/data/APlayer.java | 49 +- .../brighten/ac/handler/MovementHandler.java | 79 +++ .../ac/packet/wrapper/PacketConverter.java | 4 + .../ac/packet/wrapper/PacketType.java | 3 + .../ac/packet/wrapper/impl/Processor_18.java | 31 + .../out/WPacketPlayOutGameStateChange.java | 24 + .../dev/brighten/ac/utils/AxisAlignedBB.java | 4 + .../dev/brighten/ac/utils/TagsBuilder.java | 10 +- .../utils/world/types/SimpleCollisionBox.java | 5 + 14 files changed, 294 insertions(+), 664 deletions(-) create mode 100644 src/main/java/dev/brighten/ac/packet/wrapper/out/WPacketPlayOutGameStateChange.java diff --git a/pom.xml b/pom.xml index 59604ac..c6eed0b 100644 --- a/pom.xml +++ b/pom.xml @@ -40,8 +40,8 @@ maven-compiler-plugin 3.8.1 - 8 - 8 + 17 + 17 true -XDignore.symbol.file @@ -98,6 +98,12 @@ 1.18.24 provided + + me.hydro + emulator + 1.1-neo + compile + org.github.spigot 1.13 diff --git a/src/main/java/dev/brighten/ac/Anticheat.java b/src/main/java/dev/brighten/ac/Anticheat.java index 68db541..2297d99 100644 --- a/src/main/java/dev/brighten/ac/Anticheat.java +++ b/src/main/java/dev/brighten/ac/Anticheat.java @@ -73,6 +73,45 @@ public class Anticheat extends LoaderPlugin { private RollingAverageDouble tps = new RollingAverageDouble(4, 20); private final Map worldInfoMap = new HashMap<>(); + /** + * private final Emulator emulator = new Emulator(new DataSupplier() { + * + * @Override + * public List getCollidingBoxes(AxisAlignedBB bb) { + * return Collections.emptyList(); + * } + * + * @Override + * public Block getBlockAt(BlockPos blockPos) { + * return null; + * } + * }); + * + * public void runEmulation() { + * // 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()); + * } + */ + public static boolean allowDebug = true; @ConfigSetting(path = "logging", name = "verbose") diff --git a/src/main/java/dev/brighten/ac/check/Check.java b/src/main/java/dev/brighten/ac/check/Check.java index 6f5cd3f..1fabe23 100644 --- a/src/main/java/dev/brighten/ac/check/Check.java +++ b/src/main/java/dev/brighten/ac/check/Check.java @@ -99,6 +99,22 @@ public class Check implements ECheck { } } + public void correctMovement(KLocation toLoc) { + CancelResult result = CancelResult.builder().cancelled(false).build(); + + for (AnticheatEvent event : AnticheatAPI.INSTANCE.getAllEvents()) { + result = event.onCancel(player.getBukkitPlayer(), this, result.isCancelled()); + } + + if(result.isCancelled()) return; + + player.getInfo().getLastCancel().reset(); + + final Location CORRECTED = toLoc.toLocation(player.getBukkitPlayer().getWorld()); + + RunUtils.task(() -> player.getBukkitPlayer().teleport(CORRECTED)); + } + public void debug(String information, Object... variables) { if(!Anticheat.allowDebug) return; diff --git a/src/main/java/dev/brighten/ac/check/impl/movement/fly/FlyB.java b/src/main/java/dev/brighten/ac/check/impl/movement/fly/FlyB.java index e8cb0fd..eaefc51 100644 --- a/src/main/java/dev/brighten/ac/check/impl/movement/fly/FlyB.java +++ b/src/main/java/dev/brighten/ac/check/impl/movement/fly/FlyB.java @@ -1,14 +1,11 @@ package dev.brighten.ac.check.impl.movement.fly; -import dev.brighten.ac.check.WAction; +import dev.brighten.ac.api.check.CheckType; import dev.brighten.ac.check.Check; import dev.brighten.ac.check.CheckData; -import dev.brighten.ac.api.check.CheckType; +import dev.brighten.ac.check.WAction; import dev.brighten.ac.data.APlayer; import dev.brighten.ac.packet.wrapper.in.WPacketPlayInFlying; -import dev.brighten.ac.utils.annotation.Async; -import dev.brighten.ac.utils.timer.Timer; -import dev.brighten.ac.utils.timer.impl.TickTimer; @CheckData(name = "Fly (B)", checkId = "flyb", type = CheckType.MOVEMENT) public class FlyB extends Check { @@ -16,28 +13,18 @@ public class FlyB extends Check { super(player); } - private Timer lastNearGround = new TickTimer(); - private float buffer; - @Async + private double lastGroundY; + + WAction flying = packet -> { - if((player.getInfo().isNearGround() && !player.getBlockInfo().collidesHorizontally) - || player.getInfo().isServerGround()) lastNearGround.reset(); - if(!packet.isMoved() || player.getInfo().isGeneralCancel()) return; + if(!packet.isMoved()) + return; - if(player.getMovement().getDeltaY() - player.getMovement().getLDeltaY() > 0.01 - && player.getMovement().getMoveTicks() > 1 - && player.getInfo().getLastPlace().isPassed(3) - && lastNearGround.isPassed(2) - && !player.getInfo().onLadder - && player.getInfo().lastLiquid.isPassed(1) - && player.getInfo().climbTimer.isPassed(1) - && player.getInfo().getVelocity().isPassed(2) - && player.getMovement().getDeltaY() > 0) { - if(++buffer > 1) { - flag("%.4f>-%.4f", - player.getMovement().getDeltaY(), player.getMovement().getLDeltaY()); - } - } else if(buffer > 0) buffer-= 0.05f; + + + if(packet.isOnGround()) { + lastGroundY = packet.getY(); + } }; } 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 0ce227d..c61c354 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,661 +6,46 @@ 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.*; -import dev.brighten.ac.utils.math.IntVector; -import dev.brighten.ac.utils.timer.Timer; -import dev.brighten.ac.utils.timer.impl.TickTimer; -import dev.brighten.ac.utils.world.types.SimpleCollisionBox; -import dev.brighten.ac.utils.wrapper.Wrapper; -import lombok.AllArgsConstructor; -import lombok.val; -import org.bukkit.Material; -import org.bukkit.potion.PotionEffectType; -import org.bukkit.util.Vector; -import java.util.ArrayList; -import java.util.List; import java.util.Optional; @CheckData(name = "Horizontal", checkId = "horizontala", type = CheckType.MOVEMENT, experimental = true) public class Horizontal extends Check { - private boolean lastLastClientGround; private float buffer; - private boolean maybeSkippedPos; - private final Timer lastSkipPos = new TickTimer(); - private int lastFlying; - - private KLocation previousFrom; - 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; public Horizontal(APlayer player) { super(player); } WAction flying = packet -> { - check: - { + double offset = player.EMULATOR.getOffset(); - if(!packet.isMoved() || (player.getMovement().getDeltaXZ() == 0)) { - forward = strafe = 0; - } + debug("offset=%s", offset); - Optional inventoryA = find(InventoryA.class); + // Running inventory check + Optional inventoryA = find(InventoryA.class); - lmotion = motion; - if (!packet.isMoved() - || player.getMovement().getMoveTicks() == 0 - || player.getMovement().getLastTeleport().isNotPassed(1) - || player.getInfo().getVelocity().isNotPassed(2) - || player.getInfo().isGeneralCancel() - || player.getBlockInfo().onClimbable - || player.getBlockInfo().collidesHorizontally - || player.getMovement().getTo().getLoc() - .distanceSquared(player.getMovement().getFrom().getLoc()) > 2500 - || player.getInfo().lastLiquid.isNotPassed(2)) { - motion = new Vector(player.getMovement().getDeltaX(), player.getMovement().getDeltaY(), - player.getMovement().getDeltaZ()); - inventoryA.ifPresent(check -> { - if(check.buffer > 0) - check.buffer--; - }); - break check; - } + inventoryA.ifPresent(check -> { - double smallDelta = Double.MAX_VALUE, smallestDeltaXZ = Double.MAX_VALUE; + final int STRAFING = player.EMULATOR.getInput().getStrafing(); + final int FORWARD = player.EMULATOR.getInput().getForward(); - double predictedMotionX = 0, predictedMotionY = 0, predictedMotionZ = 0; - boolean onGround = player.getMovement().getFrom().isOnGround(); - - List iterations = getIteration(); - - boolean found = false; - double precision = getPrecision(); - TagsBuilder tags = null; - - val speed = player.getPotionHandler().getEffectByType(PotionEffectType.SPEED); - val slow = player.getPotionHandler().getEffectByType(PotionEffectType.SLOW); - - for (Iteration it : iterations) { - - TagsBuilder tagsBuilder = new TagsBuilder(); - float forward = it.f, strafe = it.s; - - tagsBuilder.addTag("forward:" + it.f); - tagsBuilder.addTag("strafe:" + it.s); - - if (it.sneaking) { - tagsBuilder.addTag("sneak"); - forward *= 0.3; - strafe *= 0.3; + if((STRAFING != 0 || FORWARD != 0) + && player.getInfo().isInventoryOpen()) { + if(check.buffer++ > 6) { + check.buffer = Math.min(8, check.buffer); + check.flag("s=%s f=%s", STRAFING, FORWARD); } + } else if(check.buffer > 0) check.buffer--; - float friction = Wrapper.getInstance().getFriction(it.underMaterial); - float lfriction = Wrapper.getInstance().getFriction(it.lastUnderMaterial); + check.debug("buffer=%d inv=%s s=%.2f f=%.2f", check.buffer, + player.getInfo().isInventoryOpen(), STRAFING, FORWARD); + }); - if (it.using) { - tagsBuilder.addTag("itemUse"); - forward *= 0.2; - strafe *= 0.2; - } - //Multiplying by 0.98 like in client - forward *= 0.9800000190734863F; - strafe *= 0.9800000190734863F; - - double aiMoveSpeed = player.getBukkitPlayer().getWalkSpeed() / 2; - - float drag = 0.91f; - double lmotionX = motion.getX(), - lmotionY = motion.getY(), - lmotionZ = motion.getZ(); - - double totalMotion = Math.abs(lmotionX) + Math.abs(lmotionY) + Math.abs(lmotionZ); - - if(totalMotion > 30) { - motion = new Vector(player.getMovement().getDeltaX(), player.getMovement().getDeltaY(), - player.getMovement().getDeltaZ()); - return; - } - - lmotionY -= 0.08; - lmotionY *= 0.98f; - - //The "1" will effectively remove lastFriction from the equation - lmotionX *= (lastLastClientGround ? lfriction : 1) * 0.9100000262260437D; - lmotionZ *= (lastLastClientGround ? lfriction : 1) * 0.9100000262260437D; - - //Running multiplication done after previous prediction - if (player.getPlayerVersion().isOrAbove(ProtocolVersion.V1_9)) { - if (Math.abs(lmotionX) < 0.003) { - lmotionX = 0; - tagsBuilder.addTag("motionXZero"); - } - if (Math.abs(lmotionZ) < 0.003) { - lmotionZ = 0; - tagsBuilder.addTag("motionZZero"); - } - if (Math.abs(lmotionY) < 0.003) { - lmotionY = 0; - tagsBuilder.addTag("motionYZero"); - } - } else { - if (Math.abs(lmotionX) < 0.005) { - lmotionX = 0; - tagsBuilder.addTag("motionXZero"); - } - if (Math.abs(lmotionZ) < 0.005) { - lmotionZ = 0; - tagsBuilder.addTag("motionZZero"); - } - if (Math.abs(lmotionY) < 0.005) { - lmotionY = 0; - tagsBuilder.addTag("motionYZero"); - } - } - - // Attack slowdown - if (it.attack) { - lmotionX *= 0.6; - lmotionZ *= 0.6; - tagsBuilder.addTag("attackSlow"); - } - - if (it.sprinting) { - aiMoveSpeed += aiMoveSpeed * 0.30000001192092896D; - tagsBuilder.addTag("sprinting"); - } - - if (speed.isPresent()) { - aiMoveSpeed += (speed.get().getAmplifier() + 1) * (double) 0.20000000298023224D * aiMoveSpeed; - tagsBuilder.addTag("speedPotion"); - } - if (slow.isPresent()) { - aiMoveSpeed += (slow.get().getAmplifier() + 1) * (double) -0.15000000596046448D * aiMoveSpeed; - tagsBuilder.addTag("slowPotion"); - } - - float f5; - if (onGround) { - tagsBuilder.addTag("ground"); - drag *= friction; - - f5 = (float) (aiMoveSpeed * (0.16277136F / (drag * drag * drag))); - - if (it.jumped) { - if (it.sprinting) { - float rot = player.getMovement().getTo().getLoc().yaw * 0.017453292F; - lmotionX -= sin(it.fastMath, rot) * 0.2F; - lmotionZ += cos(it.fastMath, rot) * 0.2F; - } - - lmotionY = MovementUtils.getJumpHeight(player); - - tagsBuilder.addTag("jumped"); - } - - } else { - tagsBuilder.addTag("air"); - f5 = it.sprinting ? 0.025999999F : 0.02f; - } - - tagsBuilder.addTag("mathit:" + it.fastMath); - - if (player.getPlayerVersion().isOrAbove(ProtocolVersion.V1_9)) { - double keyedMotion = forward * forward + strafe * strafe; - - if (keyedMotion >= 1.0E-4F) { - keyedMotion = f5 / Math.max(1.0, Math.sqrt(keyedMotion)); - forward *= keyedMotion; - strafe *= keyedMotion; - - final float yawSin = sin(it.fastMath, - player.getMovement().getTo().getLoc().yaw * (float) Math.PI / 180.F), - yawCos = cos(it.fastMath, - player.getMovement().getTo().getLoc().yaw * (float) Math.PI / 180.F); - - lmotionX += (strafe * yawCos - forward * yawSin); - lmotionZ += (forward * yawCos + strafe * yawSin); - } - } else { - float keyedMotion = forward * forward + strafe * strafe; - - if (keyedMotion >= 1.0E-4F) { - keyedMotion = f5 / Math.max(1.0f, MathHelper.sqrt_float(keyedMotion)); - forward *= keyedMotion; - strafe *= keyedMotion; - - final float yawSin = sin(it.fastMath, - player.getMovement().getTo().getLoc().yaw * (float) Math.PI / 180.F), - yawCos = cos(it.fastMath, - player.getMovement().getTo().getLoc().yaw * (float) Math.PI / 180.F); - - lmotionX += (strafe * yawCos - forward * yawSin); - lmotionZ += (forward * yawCos + strafe * yawSin); - } - } - - if (player.getBlockInfo().onSoulSand - && player.getBlockInfo().collisionMaterialCount. - containsKey(Material.SOUL_SAND)) { - - int i; - for (i = 0 - ; i < player.getBlockInfo() - .collisionMaterialCount - .get(Material.SOUL_SAND) - ; i++) { - lmotionX *= 0.4; - lmotionZ *= 0.4; - } - - if (i > 0) { - tagsBuilder.addTag("soulSand:" + i); - } - } - - if (player.getBlockInfo().inWeb) { - lmotionX *= 0.25; - lmotionZ *= 0.25; - tagsBuilder.addTag("web"); - } - - double originalX = lmotionX, originalY = lmotionY, originalZ = lmotionZ; - - SimpleCollisionBox box = player.getMovement().getFrom().getBox().copy(); - - if (it.edge && it.sneaking && onGround) { - double d6; - - // 1.9+ changes from 0.05 to 0.03 - double protocolOffset = player.getPlayerVersion().isBelow(ProtocolVersion.V1_9) ? 0.05D : 0.03D; - - for (d6 = protocolOffset; lmotionX != 0.0D && Helper.getCollisions(player, box.copy() - .offset(lmotionX, 0, 0)).isEmpty(); originalX = lmotionX) { - if (lmotionX < d6 && lmotionX >= -d6) { - lmotionX = 0.0D; - } else if (lmotionX > 0.0D) { - lmotionX -= d6; - } else { - lmotionX += d6; - } - } - - for (; lmotionZ != 0.0D && Helper.getCollisions(player, box.copy() - .offset(0, 0, lmotionZ)).isEmpty(); originalZ = lmotionZ) { - if (lmotionZ < d6 && lmotionZ >= -d6) { - lmotionZ = 0.0D; - } else if (lmotionZ > 0.0D) { - lmotionZ -= d6; - } else { - lmotionZ += d6; - } - } - - for (; lmotionX != 0.0D && lmotionZ != 0.0D && Helper.getCollisions(player, box.copy() - .offset(lmotionX, -1.0, lmotionZ)).isEmpty(); - originalZ = lmotionZ) { - if (lmotionX < d6 && lmotionX >= -d6) { - lmotionX = 0.0D; - } else if (lmotionX > 0.0D) { - lmotionX -= d6; - } else { - lmotionX += d6; - } - - originalX = lmotionX; - - if (lmotionZ < d6 && lmotionZ >= -d6) { - lmotionZ = 0.0D; - } else if (lmotionZ > 0.0D) { - lmotionZ -= d6; - } else { - lmotionZ += d6; - } - } - tagsBuilder.addTag("sneak-edge"); - } - - List collisionBoxes = Helper.getCollisions(player, box.copy() - .addCoord(lmotionX, lmotionY, lmotionZ)); - - for (SimpleCollisionBox blockBox : collisionBoxes) { - lmotionY = blockBox.calculateYOffset(box, lmotionY); - } - - box = box.offset(0, lmotionY, 0); - - boolean stepped = onGround || (originalY != lmotionY && originalY < 0); - - for (SimpleCollisionBox blockBox : collisionBoxes) { - lmotionX = blockBox.calculateXOffset(box, lmotionX); - } - - box = box.offset(lmotionX, 0, 0); - for (SimpleCollisionBox blockBox : collisionBoxes) { - lmotionZ = blockBox.calculateZOffset(box, lmotionZ); - } - - box = box.offset(0, 0, lmotionZ); - - if (stepped && (lmotionX != originalX || lmotionZ != originalZ)) { - double d11 = lmotionX; - double d7 = lmotionY; - double d8 = lmotionZ; - SimpleCollisionBox axisalignedbb3 = box; - - box = player.getMovement().getFrom().getBox().copy(); - - lmotionY = 0.6; //Step height - List list = Helper.getCollisions(player, - box.copy().addCoord(originalX, lmotionY, originalZ)); - SimpleCollisionBox axisalignedbb4 = box; - SimpleCollisionBox axisalignedbb5 = axisalignedbb4.copy().addCoord(originalX, 0.0D, originalZ); - double d9 = lmotionY; - - for (SimpleCollisionBox axisalignedbb6 : list) { - d9 = axisalignedbb6.calculateYOffset(axisalignedbb5, d9); - } - - axisalignedbb4 = axisalignedbb4.copy().offset(0.0D, d9, 0.0D); - double d15 = originalX; - - for (SimpleCollisionBox axisalignedbb7 : list) { - d15 = axisalignedbb7.calculateXOffset(axisalignedbb4, d15); - } - - axisalignedbb4 = axisalignedbb4.offset(d15, 0.0D, 0.0D); - - double d16 = originalZ; - - for (SimpleCollisionBox axisalignedbb8 : list) { - d16 = axisalignedbb8.calculateZOffset(axisalignedbb4, d16); - } - - axisalignedbb4 = axisalignedbb4.offset(0.0D, 0.0D, d16); - SimpleCollisionBox axisalignedbb14 = box; - double d17 = lmotionY; - - for (SimpleCollisionBox axisalignedbb9 : list) { - d17 = axisalignedbb9.calculateYOffset(axisalignedbb14, d17); - } - - axisalignedbb14 = axisalignedbb14.copy().offset(0.0D, d17, 0.0D); - double d18 = originalX; - - for (SimpleCollisionBox axisalignedbb10 : list) { - d18 = axisalignedbb10.calculateXOffset(axisalignedbb14, d18); - } - - axisalignedbb14 = axisalignedbb14.copy().offset(d18, 0.0D, 0.0D); - double d19 = originalZ; - - for (SimpleCollisionBox axisalignedbb11 : list) { - d19 = axisalignedbb11.calculateZOffset(axisalignedbb14, d19); - } - - axisalignedbb14 = axisalignedbb14.copy().offset(0.0D, 0.0D, d19); - double d20 = d15 * d15 + d16 * d16; - double d10 = d18 * d18 + d19 * d19; - - if (d20 > d10) { - lmotionX = d15; - lmotionZ = d16; - lmotionY = -d9; - box = axisalignedbb4; - } else { - lmotionX = d18; - lmotionZ = d19; - lmotionY = -d17; - box = axisalignedbb14; - } - - for (SimpleCollisionBox axisalignedbb12 : list) { - lmotionY = axisalignedbb12.calculateYOffset(box, lmotionY); - } - - box = box.copy().offset(0.0D, lmotionY, 0.0D); - - if (d11 * d11 + d8 * d8 >= lmotionX * lmotionX + lmotionZ * lmotionZ) { - lmotionX = d11; - lmotionY = d7; - lmotionZ = d8; - box = axisalignedbb3; - } - - tagsBuilder.addTag("stepped"); - } - - if (originalX != lmotionX) { - lmotionX = 0.0D; - tagsBuilder.addTag("x-collision"); - } - - if (originalY != lmotionY) { - lmotionY = 0.0D; - tagsBuilder.addTag("y-collision"); - } - - if (originalZ != lmotionZ) { - lmotionZ = 0.0D; - tagsBuilder.addTag("z-collision"); - } - - - double diffX = player.getMovement().getDeltaX() - lmotionX, - diffY = player.getMovement().getDeltaY() - lmotionY, - diffZ = player.getMovement().getDeltaZ() - lmotionZ; - double delta = (diffX * diffX) + (diffZ * diffZ); - double deltaAll = delta + (diffY * diffY); - - if (delta < smallestDeltaXZ) { - //smallDelta = deltaAll; - smallestDeltaXZ = delta; - predictedMotionX = lmotionX; - //predictedMotionY = lmotionY; - predictedMotionZ = lmotionZ; - - tags = tagsBuilder; - - if (deltaAll < precision) { - this.strafe = it.s * 0.98f; - this.forward = it.f * 0.98f; - - motion = new Vector(lmotionX, lmotionY, lmotionZ); - - if (player.getInfo().getLastCancel().isPassed(2)) - player.getInfo() - .setLastKnownGoodPosition(player - .getMovement().getFrom().getLoc() - .clone()); - - if(deltaAll < 1E-6) { - found = true; - } - } - } - } - - // Inventory (A) check - inventoryA.ifPresent(check -> { - - if((strafe != 0 || forward != 0) && player.getInfo().isInventoryOpen()) { - if(check.buffer++ > 6) { - check.buffer = Math.min(8, check.buffer); - check.flag("s=%.2f f=%.2f", strafe, forward); - } - } else if(check.buffer > 0) check.buffer--; - - check.debug("buffer=%d inv=%s s=%.2f f=%.2f", check.buffer, - player.getInfo().isInventoryOpen(), strafe, forward); - }); - iterations.clear(); - - if (!found) { - motion = new Vector(player.getMovement().getDeltaX(), player.getMovement().getDeltaY(), player.getMovement().getDeltaZ()); - } - - final String builtTags = tags == null ? "null" : tags.build(); - - 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 - flag("smallest=%.7f b=%.1f dxz=%.2f tags=[%s]", smallestDeltaXZ, buffer, - player.getMovement().getDeltaXZ(), builtTags); - cancel(); - } else debug("bad movement"); - - } else if (buffer > 0) buffer -= 0.05f; - - 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)) { - maybeSkippedPos = !packet.isMoved(); - } else { - if (player.getPlayerTick() - lastFlying > 1) { - maybeSkippedPos = true; - debug("maybe skipped pos"); - } - lastFlying = player.getPlayerTick(); - } - - if (maybeSkippedPos) { - lastSkipPos.reset(); - } - lastLastClientGround = player.getMovement().getFrom().isOnGround(); - previousFrom = player.getMovement().getFrom().getLoc().clone(); }; - private double getPrecision() { - if (player.getBlockInfo().onSoulSand) { - return 5E-4; - } else if (lastSkipPos.isNotPassed(2)) { - return 0.03; - } - return 5E-13; - } - - private List getIteration() { - List iterations = new ArrayList<>(); - val underBlockLoc = previousFrom != null ? player.getMovement().getFrom().getLoc() : player.getMovement().getTo().getLoc(); - val lastUnderBlockLoc = previousFrom != null ? previousFrom : player.getMovement().getFrom().getLoc(); - - Material underMaterial = player.getBlockUpdateHandler() - .getBlock(new IntVector(MathHelper.floor_double(underBlockLoc.x), - MathHelper.floor_double(underBlockLoc.y - 1), MathHelper.floor_double(underBlockLoc.z))).getType(), - lastUnderMaterial = player.getBlockUpdateHandler() - .getBlock(new IntVector(MathHelper.floor_double(lastUnderBlockLoc.x), - MathHelper.floor_double(lastUnderBlockLoc.y - 1), - MathHelper.floor_double(lastUnderBlockLoc.z))).getType(); - for (int f = -1; f < 2; f++) { - for (int s = -1; s < 2; s++) { - for (boolean sneaking : getSneakingIteration(f, s)) { - for (boolean sprinting : getSprintIteration(f, sneaking)) { - for(boolean edge : getEdgeIteration(sneaking)) { - for (int fastMath = 0; fastMath <= 2; fastMath++) { - for (boolean attack : TRUE_FALSE) { - for (boolean using : TRUE_FALSE) { - for (boolean jumped : - getJumpingIteration(player.getMovement().getFrom().isOnGround())) { - iterations.add(new Iteration(underMaterial, lastUnderMaterial, f, s, - fastMath, sprinting, sneaking, edge, attack, using, jumped)); - } - } - } - } - } - } - } - } - } - - return iterations; - } - - - @AllArgsConstructor - private static class Iteration { - public Material underMaterial, lastUnderMaterial; - public int f, s, fastMath; - public boolean sprinting, sneaking, edge, attack, using, jumped; - } - - private static boolean[] getSprintIteration(int f, boolean sneaking) { - return f > 0 ? new boolean[]{true, false} : new boolean[] {false}; - } - - private static boolean[] getSneakingIteration(int f, int s) { - return f != 0 || s != 0 ? new boolean[]{true, false} : new boolean[] {false}; - } - - private static boolean[] getEdgeIteration(boolean sneaking) { - return sneaking ? new boolean[] {true, false} : new boolean[] {false}; - } - - private static boolean[] getJumpingIteration(boolean onGround) { - return new boolean[]{true, false}; - } - - private static final float[] SIN_TABLE_FAST = new float[4096], SIN_TABLE_FAST_NEW = new float[4096]; - private static final float[] SIN_TABLE = new float[65536]; - private static final float radToIndex = roundToFloat(651.8986469044033D); - - public static float sin(int type, float value) { - switch (type) { - case 0: - default: { - return SIN_TABLE[(int) (value * 10430.378F) & 65535]; - } - case 1: { - return SIN_TABLE_FAST[(int) (value * 651.8986F) & 4095]; - } - case 2: { - return SIN_TABLE_FAST_NEW[(int) (value * radToIndex) & 4095]; - } - } - } - - public static float cos(int type, float value) { - switch (type) { - case 0: - default: - return SIN_TABLE[(int) (value * 10430.378F + 16384.0F) & 65535]; - case 1: - return SIN_TABLE_FAST[(int) ((value + ((float) Math.PI / 2F)) * 651.8986F) & 4095]; - case 2: - return SIN_TABLE_FAST_NEW[(int) (value * radToIndex + 1024.0F) & 4095]; - } - } - - static { - for (int i = 0; i < 65536; ++i) { - SIN_TABLE[i] = (float) Math.sin((double) i * Math.PI * 2.0D / 65536.0D); - } - - for (int j = 0; j < 4096; ++j) { - SIN_TABLE_FAST[j] = (float) Math.sin((double) (((float) j + 0.5F) / 4096.0F * ((float) Math.PI * 2F))); - } - - for (int l = 0; l < 360; l += 90) { - SIN_TABLE_FAST[(int) ((float) l * 11.377778F) & 4095] = (float) Math.sin((double) ((float) l * 0.017453292F)); - } - - for (int j = 0; j < SIN_TABLE_FAST_NEW.length; ++j) { - SIN_TABLE_FAST_NEW[j] = roundToFloat(Math.sin((double) j * Math.PI * 2.0D / 4096.0D)); - } - } - private static float roundToFloat(double d) { return (float) ((double) Math.round(d * 1.0E8D) / 1.0E8D); } diff --git a/src/main/java/dev/brighten/ac/data/APlayer.java b/src/main/java/dev/brighten/ac/data/APlayer.java index 4b752cc..b377638 100644 --- a/src/main/java/dev/brighten/ac/data/APlayer.java +++ b/src/main/java/dev/brighten/ac/data/APlayer.java @@ -21,17 +21,24 @@ import dev.brighten.ac.packet.ProtocolVersion; import dev.brighten.ac.packet.handler.HandlerAbstract; import dev.brighten.ac.packet.wrapper.WPacket; import dev.brighten.ac.packet.wrapper.objects.WrappedWatchableObject; -import dev.brighten.ac.utils.KLocation; -import dev.brighten.ac.utils.RunUtils; -import dev.brighten.ac.utils.Tuple; +import dev.brighten.ac.utils.*; import dev.brighten.ac.utils.objects.evicting.EvictingList; import dev.brighten.ac.utils.reflections.impl.MinecraftReflection; import dev.brighten.ac.utils.timer.Timer; import dev.brighten.ac.utils.timer.impl.MillisTimer; import dev.brighten.ac.utils.world.types.RayCollision; +import dev.brighten.ac.utils.world.types.SimpleCollisionBox; import lombok.Getter; import lombok.Setter; import lombok.val; +import me.hydro.emulator.Emulator; +import me.hydro.emulator.collision.Block; +import me.hydro.emulator.collision.impl.BlockSlime; +import me.hydro.emulator.collision.impl.BlockSoulSand; +import me.hydro.emulator.collision.impl.BlockWeb; +import me.hydro.emulator.object.input.DataSupplier; +import me.hydro.emulator.util.mcp.AxisAlignedBB; +import me.hydro.emulator.util.mcp.BlockPos; import net.minecraft.server.v1_8_R3.PacketPlayOutTransaction; import org.bukkit.Achievement; import org.bukkit.Location; @@ -43,6 +50,7 @@ import java.util.*; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.ThreadLocalRandom; import java.util.function.Consumer; +import java.util.stream.Collectors; public class APlayer { @@ -83,6 +91,41 @@ public class APlayer { @Getter private Object playerConnection; + public final Emulator EMULATOR = new Emulator(new DataSupplier() { + @Override + public List getCollidingBoxes(AxisAlignedBB bb) { + return Helper.getCollisions(APlayer.this, + new SimpleCollisionBox(bb.minX, bb.minY, bb.minZ, bb.maxX, bb.maxY, bb.maxZ), + Materials.COLLIDABLE).stream().map(bb2 -> + new AxisAlignedBB(bb2.minX, bb2.minY, bb2.minZ, bb2.maxX, bb2.maxY, bb2.maxZ)) + .collect(Collectors.toList()); + } + + @Override + public Block getBlockAt(BlockPos blockPos) { + //Optional + val block = BlockUtils.getBlockAsync( + new Location(getBukkitPlayer().getWorld(), blockPos.getX(), blockPos.getY(), blockPos.getZ())); + + if(block.isPresent()) { + XMaterial xmaterial = XMaterial.matchXMaterial(block.get().getType()); + + switch (xmaterial) { + case SLIME_BLOCK -> { + return new BlockSlime(); + } + case SOUL_SAND -> { + return new BlockSoulSand(); + } + case COBWEB -> { + return new BlockWeb(); + } + } + } + return new Block(); + } + }); + public int hitsToCancel; public final Map>> instantTransaction = new HashMap<>(); diff --git a/src/main/java/dev/brighten/ac/handler/MovementHandler.java b/src/main/java/dev/brighten/ac/handler/MovementHandler.java index 5a5532a..d57b258 100644 --- a/src/main/java/dev/brighten/ac/handler/MovementHandler.java +++ b/src/main/java/dev/brighten/ac/handler/MovementHandler.java @@ -17,6 +17,9 @@ import dev.brighten.ac.utils.world.types.SimpleCollisionBox; import lombok.Getter; import lombok.Setter; import lombok.val; +import me.hydro.emulator.object.input.IterationInput; +import me.hydro.emulator.object.result.IterationResult; +import me.hydro.emulator.util.Vector; import org.bukkit.GameMode; import org.bukkit.Location; import org.bukkit.entity.Player; @@ -93,6 +96,80 @@ 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 int[] FULL_RANGE = new int[] {-1, 0, -1}; + + private static final IterationInput.IterationInputBuilder[] INPUT_BUILDERS = new IterationInput.IterationInputBuilder[288]; + + static { + int i = 0; + for(boolean jumping : IS_OR_NOT) { // 2 + for(boolean sneaking : IS_OR_NOT) { // 4 + for(boolean usingItem : IS_OR_NOT) { // 8 + for(boolean sprinting : IS_OR_NOT) { // 16 + for(boolean hitSlow : IS_OR_NOT) { // 32 + for(int forward : FULL_RANGE) { //96 + for(int strafe : FULL_RANGE) { // 288 + INPUT_BUILDERS[i] = IterationInput.builder() + .jumping(jumping) + .forward(forward) + .strafing(strafe) + .sprinting(sprinting) + .usingItem(usingItem) + .hitSlowdown(hitSlow) + .sneaking(sneaking); + i++; + } + } + } + } + } + } + } + } + + public void runEmulation(WPacketPlayInFlying packet) { + IterationResult minimum = null; + for (IterationInput.IterationInputBuilder inputBuilder : INPUT_BUILDERS) { + IterationInput input = inputBuilder.ground(packet.isOnGround()) + .to(new Vector(to.getX(), to.getY(), to.getZ())) + .yaw(to.getYaw()) + .lastReportedBoundingBox(from.getBox().toNeo()) + .build(); + + IterationResult result = player.EMULATOR.runIteration(input); + + if(minimum == null || minimum.getOffset() > result.getOffset()) { + minimum = result; + } + } + player.EMULATOR.confirm(minimum.getIteration()); + } + public void process(WPacketPlayInFlying packet) { @@ -285,6 +362,8 @@ public class MovementHandler { } } else jumped = inAir = false; + runEmulation(packet); + player.getInfo().setGeneralCancel(player.getBukkitPlayer().getAllowFlight() || moveTicks == 0 || excuseNextFlying diff --git a/src/main/java/dev/brighten/ac/packet/wrapper/PacketConverter.java b/src/main/java/dev/brighten/ac/packet/wrapper/PacketConverter.java index 04bc8fc..ce42b7c 100644 --- a/src/main/java/dev/brighten/ac/packet/wrapper/PacketConverter.java +++ b/src/main/java/dev/brighten/ac/packet/wrapper/PacketConverter.java @@ -94,4 +94,8 @@ public interface PacketConverter { WPacketPlayInClientCommand processInClientCommand(Object packet); WPacketPlayInWindowClick processInWindowClick(Object packet); + + WPacketPlayOutGameStateChange processOutGameStateChange(Object packet); + + Object processOutGameStateChange(WPacketPlayOutGameStateChange packet); } diff --git a/src/main/java/dev/brighten/ac/packet/wrapper/PacketType.java b/src/main/java/dev/brighten/ac/packet/wrapper/PacketType.java index 62384f0..54608cb 100644 --- a/src/main/java/dev/brighten/ac/packet/wrapper/PacketType.java +++ b/src/main/java/dev/brighten/ac/packet/wrapper/PacketType.java @@ -70,6 +70,7 @@ public enum PacketType { STATUS_START("PacketStatusInStart"), LOGIN_START("PacketLoginInStart"), REMOVE_EFFECT("PacketPlayOutRemoveEntityEffect"), + GAME_STATE_CHANGE("PacketPlayOutGameStateChange"), UNKNOWN(); PacketType(String... packetIds) { @@ -157,6 +158,8 @@ public enum PacketType { return convert.processInClientCommand(object); case WINDOW_CLICK: return convert.processInWindowClick(object); + case GAME_STATE_CHANGE: + return convert.processOutGameStateChange(object); default: return object; } diff --git a/src/main/java/dev/brighten/ac/packet/wrapper/impl/Processor_18.java b/src/main/java/dev/brighten/ac/packet/wrapper/impl/Processor_18.java index bfb22e0..1d3dd41 100644 --- a/src/main/java/dev/brighten/ac/packet/wrapper/impl/Processor_18.java +++ b/src/main/java/dev/brighten/ac/packet/wrapper/impl/Processor_18.java @@ -813,6 +813,37 @@ public class Processor_18 implements PacketConverter { .build(); } + @SneakyThrows + @Override + public WPacketPlayOutGameStateChange processOutGameStateChange(Object packet) { + PacketPlayOutGameStateChange gameStateChange = (PacketPlayOutGameStateChange) packet; + PacketDataSerializer serialized = serialize(gameStateChange); + gameStateChange.b(serialized); + + final short reason = serialized.readUnsignedByte(); + final float value = serialized.readFloat(); + + + return WPacketPlayOutGameStateChange.builder() + .reason(reason) + .value(value) + .build(); + } + + @SneakyThrows + @Override + public Object processOutGameStateChange(WPacketPlayOutGameStateChange packet) { + PacketPlayOutGameStateChange gameStateChange = new PacketPlayOutGameStateChange(); + PacketDataSerializer serialized = new PacketDataSerializer(Unpooled.buffer()); + + serialized.writeByte(packet.getReason()); + serialized.writeFloat(packet.getValue()); + + gameStateChange.a(serialized); + + return gameStateChange; + } + private static void processChunk(byte[] locs, int size, int chunkX, int chunkZ, boolean groundUp, Map blocks) { ChunkSection[] sections = new ChunkSection[16]; diff --git a/src/main/java/dev/brighten/ac/packet/wrapper/out/WPacketPlayOutGameStateChange.java b/src/main/java/dev/brighten/ac/packet/wrapper/out/WPacketPlayOutGameStateChange.java new file mode 100644 index 0000000..f27cb60 --- /dev/null +++ b/src/main/java/dev/brighten/ac/packet/wrapper/out/WPacketPlayOutGameStateChange.java @@ -0,0 +1,24 @@ +package dev.brighten.ac.packet.wrapper.out; + +import dev.brighten.ac.Anticheat; +import dev.brighten.ac.packet.wrapper.PacketType; +import dev.brighten.ac.packet.wrapper.WPacket; +import lombok.Builder; +import lombok.Getter; + +@Getter +@Builder +public class WPacketPlayOutGameStateChange extends WPacket { + private short reason; + private float value; + + @Override + public PacketType getPacketType() { + return PacketType.GAME_STATE_CHANGE; + } + + @Override + public Object getPacket() { + return Anticheat.INSTANCE.getPacketProcessor().getPacketConverter().processOutGameStateChange(this); + } +} diff --git a/src/main/java/dev/brighten/ac/utils/AxisAlignedBB.java b/src/main/java/dev/brighten/ac/utils/AxisAlignedBB.java index b6e3163..e23e318 100644 --- a/src/main/java/dev/brighten/ac/utils/AxisAlignedBB.java +++ b/src/main/java/dev/brighten/ac/utils/AxisAlignedBB.java @@ -313,6 +313,10 @@ public class AxisAlignedBB { return vec3d != null && (vec3d.x >= this.minX && vec3d.x <= this.maxX && vec3d.y >= this.minY && vec3d.y <= this.maxY); } + public me.hydro.emulator.util.mcp.AxisAlignedBB toNeo() { + return new me.hydro.emulator.util.mcp.AxisAlignedBB(minX, minY, minZ, maxX, maxY, maxZ); + } + public String toString() { return "box[" + this.minX + ", " + this.minY + ", " + this.minZ + " -> " + this.maxX + ", " + this.maxY + ", " + this.maxZ + "]"; } diff --git a/src/main/java/dev/brighten/ac/utils/TagsBuilder.java b/src/main/java/dev/brighten/ac/utils/TagsBuilder.java index a9422a5..7178140 100644 --- a/src/main/java/dev/brighten/ac/utils/TagsBuilder.java +++ b/src/main/java/dev/brighten/ac/utils/TagsBuilder.java @@ -1,10 +1,10 @@ package dev.brighten.ac.utils; -import java.util.ArrayList; -import java.util.List; +import java.util.HashSet; +import java.util.Set; public class TagsBuilder { - private final List tags = new ArrayList<>(); + private final Set tags = new HashSet<>(); public TagsBuilder addTag(String string) { tags.add(string); @@ -19,4 +19,8 @@ public class TagsBuilder { public int getSize() { return tags.size(); } + + public boolean containsTag(String tag) { + return tags.contains(tag); + } } \ No newline at end of file diff --git a/src/main/java/dev/brighten/ac/utils/world/types/SimpleCollisionBox.java b/src/main/java/dev/brighten/ac/utils/world/types/SimpleCollisionBox.java index cb58c02..c1422da 100644 --- a/src/main/java/dev/brighten/ac/utils/world/types/SimpleCollisionBox.java +++ b/src/main/java/dev/brighten/ac/utils/world/types/SimpleCollisionBox.java @@ -6,6 +6,7 @@ import dev.brighten.ac.utils.Helper; import dev.brighten.ac.utils.KLocation; import dev.brighten.ac.utils.reflections.impl.MinecraftReflection; import dev.brighten.ac.utils.world.CollisionBox; +import me.hydro.emulator.util.mcp.AxisAlignedBB; import org.bukkit.Location; import org.bukkit.entity.Player; import org.bukkit.util.Vector; @@ -345,6 +346,10 @@ public class SimpleCollisionBox implements CollisionBox { return MinecraftReflection.toAABB(this); } + public AxisAlignedBB toNeo() { + return new AxisAlignedBB(minX, minY, minZ, maxX, maxY, maxZ); + } + public double distance(SimpleCollisionBox box) { double xwidth = (maxX - minX) / 2, zwidth = (maxZ - minZ) / 2; double bxwidth = (box.maxX - box.minX) / 2, bzwidth = (box.maxZ - box.minZ) / 2;