diff --git a/src/main/java/dev/brighten/ac/check/CheckData.java b/src/main/java/dev/brighten/ac/check/CheckData.java index 3ffff1c..3ebbe6b 100644 --- a/src/main/java/dev/brighten/ac/check/CheckData.java +++ b/src/main/java/dev/brighten/ac/check/CheckData.java @@ -14,5 +14,5 @@ public @interface CheckData { int punishVl() default 10; ProtocolVersion minVersion() default ProtocolVersion.V1_7; - ProtocolVersion maxVersion() default ProtocolVersion.V1_19; + ProtocolVersion maxVersion() default ProtocolVersion.v1_19_1; } diff --git a/src/main/java/dev/brighten/ac/check/impl/combat/Hitbox.java b/src/main/java/dev/brighten/ac/check/impl/combat/Hitbox.java index 2ed5424..f7dcaf6 100644 --- a/src/main/java/dev/brighten/ac/check/impl/combat/Hitbox.java +++ b/src/main/java/dev/brighten/ac/check/impl/combat/Hitbox.java @@ -81,7 +81,7 @@ public class Hitbox extends Check { EntityData.getEntityBox(oldLocation.toVector(), target.one); if(player.getPlayerVersion().isBelow(ProtocolVersion.V1_9)) { - box = box.expand(0.1325); + box = box.expand(0.12); } else box = box.expand(0.0325); boxes.add(box); } @@ -90,7 +90,7 @@ public class Hitbox extends Check { EntityData.getEntityBox(oldLocation.toVector(), target.one); if(player.getPlayerVersion().isBelow(ProtocolVersion.V1_9)) { - box = box.expand(0.1325); + box = box.expand(0.12); } else box = box.expand(0.0325); boxes.add(box); } @@ -100,7 +100,7 @@ public class Hitbox extends Check { EntityData.getEntityBox(oldLocation.toVector(), target.one); if(player.getPlayerVersion().isBelow(ProtocolVersion.V1_9)) { - box = box.expand(0.1325); + box = box.expand(0.12); } else box = box.expand(0.0325); boxes.add(box); } @@ -166,12 +166,12 @@ public class Hitbox extends Check { flag("d=%.3f>-3.0", distance); buffer = Math.min(1, buffer); } - } else if(buffer > 0) buffer-= 0.05f; + } else if(buffer > 0) buffer-= 0.02f; if(hbuffer > 0) hbuffer--; debug("buffer: %.3f distance=%.2f hits=%s", buffer, distance, hits); - } else { + } else if(player.getEntityLocationHandler().streak > 1) { if (++hbuffer > 5) { flag("%.1f;%.1f;%.1f", eloc.one.x, eloc.one.y, eloc.one.z); } diff --git a/src/main/java/dev/brighten/ac/check/impl/fly/FlyA.java b/src/main/java/dev/brighten/ac/check/impl/movement/fly/FlyA.java similarity index 84% rename from src/main/java/dev/brighten/ac/check/impl/fly/FlyA.java rename to src/main/java/dev/brighten/ac/check/impl/movement/fly/FlyA.java index fab5c2a..a19a7f9 100644 --- a/src/main/java/dev/brighten/ac/check/impl/fly/FlyA.java +++ b/src/main/java/dev/brighten/ac/check/impl/movement/fly/FlyA.java @@ -1,4 +1,4 @@ -package dev.brighten.ac.check.impl.fly; +package dev.brighten.ac.check.impl.movement.fly; import dev.brighten.ac.check.WAction; import dev.brighten.ac.check.Check; @@ -21,7 +21,8 @@ public class FlyA extends Check { private Timer lastPos = new MillisTimer(); private float buffer; - private static double mult = 0.98f; + private static double mult = 0.98f, previousPrediction; + private boolean didNextPrediction = false; WAction flying = packet -> { if(!packet.isMoved() || (player.getMovement().getDeltaXZ() == 0 @@ -42,12 +43,19 @@ public class FlyA extends Check { predicted = 0; } + // There will be missed movements that we can't account for if we had to predict the player's next position + // twice, so we shouldn't flag regardless. + boolean willBeWeirdNext = didNextPrediction; + didNextPrediction = false; + if(lastPos.isPassed(60L)) { double toCheck = (predicted - 0.08) * mult; if(Math.abs(player.getMovement().getDeltaY() - toCheck) < Math.abs(player.getMovement().getDeltaY() - predicted)) { + previousPrediction = predicted; predicted = toCheck; + didNextPrediction = true; } } @@ -59,9 +67,11 @@ public class FlyA extends Check { && !player.getInfo().isOnLadder() && player.getInfo().climbTimer.isPassed(2) && !player.getBlockInfo().inWeb + && !willBeWeirdNext && !player.getBlockInfo().inScaffolding && player.getInfo().getLastLiquid().isPassed(2) && !player.getBlockInfo().fenceBelow + && !packet.isOnGround() && !player.getInfo().isServerGround() && !player.getBlockInfo().onHalfBlock && player.getInfo().getVelocity().isPassed(1) diff --git a/src/main/java/dev/brighten/ac/check/impl/fly/FlyB.java b/src/main/java/dev/brighten/ac/check/impl/movement/fly/FlyB.java similarity index 96% rename from src/main/java/dev/brighten/ac/check/impl/fly/FlyB.java rename to src/main/java/dev/brighten/ac/check/impl/movement/fly/FlyB.java index d321297..d9185fa 100644 --- a/src/main/java/dev/brighten/ac/check/impl/fly/FlyB.java +++ b/src/main/java/dev/brighten/ac/check/impl/movement/fly/FlyB.java @@ -1,4 +1,4 @@ -package dev.brighten.ac.check.impl.fly; +package dev.brighten.ac.check.impl.movement.fly; import dev.brighten.ac.check.WAction; import dev.brighten.ac.check.Check; diff --git a/src/main/java/dev/brighten/ac/check/impl/nofall/NoFallA.java b/src/main/java/dev/brighten/ac/check/impl/movement/nofall/NoFallA.java similarity index 95% rename from src/main/java/dev/brighten/ac/check/impl/nofall/NoFallA.java rename to src/main/java/dev/brighten/ac/check/impl/movement/nofall/NoFallA.java index 9986bd6..4e5431d 100644 --- a/src/main/java/dev/brighten/ac/check/impl/nofall/NoFallA.java +++ b/src/main/java/dev/brighten/ac/check/impl/movement/nofall/NoFallA.java @@ -1,4 +1,4 @@ -package dev.brighten.ac.check.impl.nofall; +package dev.brighten.ac.check.impl.movement.nofall; import dev.brighten.ac.check.WAction; import dev.brighten.ac.check.Check; @@ -21,6 +21,7 @@ public class NoFallA extends Check { if(player.getInfo().isGeneralCancel() || (player.getMovement().getDeltaXZ() == 0 && player.getMovement().getDeltaY() == 0) || player.getBlockInfo().inLiquid + || player.getInfo().velocity.isNotPassed(1) || player.getMovement().getLastTeleport().isNotPassed(1) || !packet.isMoved()) { if(buffer > 0) buffer-= 0.5f; diff --git a/src/main/java/dev/brighten/ac/check/impl/nofall/NoFallB.java b/src/main/java/dev/brighten/ac/check/impl/movement/nofall/NoFallB.java similarity index 98% rename from src/main/java/dev/brighten/ac/check/impl/nofall/NoFallB.java rename to src/main/java/dev/brighten/ac/check/impl/movement/nofall/NoFallB.java index 0eed846..b22a172 100644 --- a/src/main/java/dev/brighten/ac/check/impl/nofall/NoFallB.java +++ b/src/main/java/dev/brighten/ac/check/impl/movement/nofall/NoFallB.java @@ -1,4 +1,4 @@ -package dev.brighten.ac.check.impl.nofall; +package dev.brighten.ac.check.impl.movement.nofall; import dev.brighten.ac.check.WAction; import dev.brighten.ac.check.Check; diff --git a/src/main/java/dev/brighten/ac/check/impl/speed/Horizontal.java b/src/main/java/dev/brighten/ac/check/impl/movement/speed/Horizontal.java similarity index 99% rename from src/main/java/dev/brighten/ac/check/impl/speed/Horizontal.java rename to src/main/java/dev/brighten/ac/check/impl/movement/speed/Horizontal.java index d4192c3..56f9ddc 100644 --- a/src/main/java/dev/brighten/ac/check/impl/speed/Horizontal.java +++ b/src/main/java/dev/brighten/ac/check/impl/movement/speed/Horizontal.java @@ -1,4 +1,4 @@ -package dev.brighten.ac.check.impl.speed; +package dev.brighten.ac.check.impl.movement.speed; import dev.brighten.ac.check.WAction; import dev.brighten.ac.check.Check; @@ -53,10 +53,10 @@ public class Horizontal extends Check { if (!packet.isMoved() || player.getMovement().getMoveTicks() == 0 - || player.getInfo().getVelocity().isNotPassed(1) + || player.getInfo().getVelocity().isNotPassed(2) || player.getInfo().isGeneralCancel() || player.getBlockInfo().onClimbable - || player.getBlockInfo().inLiquid + || player.getInfo().lastLiquid.isNotPassed(2) || player.getBlockInfo().collidesHorizontally) { break check; } diff --git a/src/main/java/dev/brighten/ac/check/impl/velocity/VelocityA.java b/src/main/java/dev/brighten/ac/check/impl/movement/velocity/VelocityA.java similarity index 97% rename from src/main/java/dev/brighten/ac/check/impl/velocity/VelocityA.java rename to src/main/java/dev/brighten/ac/check/impl/movement/velocity/VelocityA.java index 59da101..756bb92 100644 --- a/src/main/java/dev/brighten/ac/check/impl/velocity/VelocityA.java +++ b/src/main/java/dev/brighten/ac/check/impl/movement/velocity/VelocityA.java @@ -1,4 +1,4 @@ -package dev.brighten.ac.check.impl.velocity; +package dev.brighten.ac.check.impl.movement.velocity; import dev.brighten.ac.check.WAction; import dev.brighten.ac.check.Check; diff --git a/src/main/java/dev/brighten/ac/check/impl/velocity/VelocityB.java b/src/main/java/dev/brighten/ac/check/impl/movement/velocity/VelocityB.java similarity index 93% rename from src/main/java/dev/brighten/ac/check/impl/velocity/VelocityB.java rename to src/main/java/dev/brighten/ac/check/impl/movement/velocity/VelocityB.java index 27b7193..6d06382 100644 --- a/src/main/java/dev/brighten/ac/check/impl/velocity/VelocityB.java +++ b/src/main/java/dev/brighten/ac/check/impl/movement/velocity/VelocityB.java @@ -1,14 +1,16 @@ -package dev.brighten.ac.check.impl.velocity; +package dev.brighten.ac.check.impl.movement.velocity; -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.impl.speed.Horizontal; +import dev.brighten.ac.check.WAction; +import dev.brighten.ac.check.impl.movement.speed.Horizontal; import dev.brighten.ac.data.APlayer; import dev.brighten.ac.packet.wrapper.in.WPacketPlayInFlying; import dev.brighten.ac.packet.wrapper.in.WPacketPlayInUseEntity; import dev.brighten.ac.utils.Tuple; +import dev.brighten.ac.utils.timer.Timer; +import dev.brighten.ac.utils.timer.impl.TickTimer; import org.bukkit.craftbukkit.v1_8_R3.util.CraftMagicNumbers; import org.bukkit.enchantments.Enchantment; import org.bukkit.potion.PotionEffectType; @@ -20,14 +22,19 @@ import java.util.Optional; @CheckData(name = "Velocity (B)", type = CheckType.MOVEMENT) public class VelocityB extends Check { + private Timer lastVelocity = new TickTimer(); public VelocityB(APlayer player) { super(player); player.onVelocity(velocity -> { - pvX = velocity.getX(); - pvZ = velocity.getZ(); - ticks = 0; - debug("did velocity: %.3f, %.3f", pvX, pvZ); + if(lastVelocity.isPassed(10)) { //Temp fix for combo mode + pvX = velocity.getX(); + pvZ = velocity.getZ(); + ticks = 0; + debug("did velocity: %.3f, %.3f", pvX, pvZ); + } + + lastVelocity.reset(); }); } diff --git a/src/main/java/dev/brighten/ac/check/impl/order/Timer.java b/src/main/java/dev/brighten/ac/check/impl/order/Timer.java new file mode 100644 index 0000000..0422cd2 --- /dev/null +++ b/src/main/java/dev/brighten/ac/check/impl/order/Timer.java @@ -0,0 +1,76 @@ +package dev.brighten.ac.check.impl.order; + +import dev.brighten.ac.Anticheat; +import dev.brighten.ac.api.check.CheckType; +import dev.brighten.ac.check.Check; +import dev.brighten.ac.check.CheckData; +import dev.brighten.ac.check.TimedWAction; +import dev.brighten.ac.check.WAction; +import dev.brighten.ac.data.APlayer; +import dev.brighten.ac.packet.ProtocolVersion; +import dev.brighten.ac.packet.wrapper.in.WPacketPlayInBlockPlace; +import dev.brighten.ac.packet.wrapper.in.WPacketPlayInFlying; +import dev.brighten.ac.packet.wrapper.out.WPacketPlayOutPosition; +import dev.brighten.ac.utils.timer.impl.TickTimer; +import net.minecraft.server.v1_8_R3.PacketPlayInTransaction; + +@CheckData(name = "Timer", type = CheckType.ORDER) +public class Timer extends Check { + + public Timer(APlayer player) { + super(player); + } + + private int buffer; + private final dev.brighten.ac.utils.timer.Timer lastFlag = new TickTimer(), + lastReset = new TickTimer(); + private long totalTimer = -1; + + WAction position = packet -> { + totalTimer-= 50; + }; + + WAction blockPlace = packet -> { + if(player.getPlayerVersion().isOrAbove(ProtocolVersion.V1_17)) + totalTimer-= 50; + }; + + /** + * Fixing bug with 1.9 since flying packets are not always sent + */ + TimedWAction transaction = (packet, timestamp) -> { + if(player.getPlayerVersion().isBelow(ProtocolVersion.V1_9)) return; + + Anticheat.INSTANCE.getKeepaliveProcessor().getKeepById(packet.b()).ifPresent(ka -> { + long delta = timestamp - ka.startStamp; + + if(delta < 1095L && totalTimer - (timestamp + 100) > 3000L) { + totalTimer = timestamp - 300; + } + }); + }; + + TimedWAction flying = (packet, timestamp) -> { + if(totalTimer == -1) { + totalTimer = player.getCreation().getCurrent() - 50; + debug("set base time"); + } + else totalTimer+= 50; + + long threshold = timestamp + 100, delta = totalTimer - threshold; + + boolean isLagProblem = Anticheat.INSTANCE.getKeepaliveProcessor().laggyPlayers + / (double)Anticheat.INSTANCE.getKeepaliveProcessor().totalPlayers > 0.8; + + if(totalTimer > threshold && !isLagProblem) { + if(++buffer > 5) { + flag("p=%s;d=%s;r=%s", totalTimer, delta, isLagProblem); + } + totalTimer = timestamp - 80; + debug("Flagged;reset time"); + lastFlag.reset(); + } else if(lastFlag.isPassed(100)) buffer = 0; + + debug("buffer=%s delta=%s threshold=%s ilp=%s", buffer, delta, threshold, isLagProblem); + }; +} diff --git a/src/main/java/dev/brighten/ac/handler/EntityLocationHandler.java b/src/main/java/dev/brighten/ac/handler/EntityLocationHandler.java index e3926a8..f07161b 100644 --- a/src/main/java/dev/brighten/ac/handler/EntityLocationHandler.java +++ b/src/main/java/dev/brighten/ac/handler/EntityLocationHandler.java @@ -57,8 +57,18 @@ public class EntityLocationHandler { } entityLocationMap.values().forEach(eloc -> { - if(eloc.one != null) eloc.one.interpolateLocation(); - if(eloc.two != null) eloc.two.interpolateLocation(); + if(eloc.one != null) { + eloc.one.interpolateLocation(); + if(streak > 2 && eloc.one.interpolatedLocations.size() > 1) { + eloc.one.interpolatedLocations.removeFirst(); + } + } + if(eloc.two != null) { + eloc.two.interpolateLocation(); + if(streak > 2 && eloc.two.interpolatedLocations.size() > 1) { + eloc.two.interpolatedLocations.removeFirst(); + } + } }); lastFlying.reset(); diff --git a/src/main/java/dev/brighten/ac/utils/EntityLocation.java b/src/main/java/dev/brighten/ac/utils/EntityLocation.java index b47c14e..c9e19ca 100644 --- a/src/main/java/dev/brighten/ac/utils/EntityLocation.java +++ b/src/main/java/dev/brighten/ac/utils/EntityLocation.java @@ -40,6 +40,25 @@ public class EntityLocation { } } + public void interpolateRestOfLocations() { + while(increment > 0) { + double d0 = x + (newX - x) / increment; + double d1 = y + (newY - y) / increment; + double d2 = z + (newZ - z) / increment; + double d3 = MathHelper.wrapAngleTo180_float(newYaw - yaw); + + yaw = (float) ((double) yaw + d3 / (double) increment); + pitch = (float) ((double) pitch + (newPitch - (double) pitch) / (double) increment); + + increment--; + + this.x = d0; + this.y = d1; + this.z = d2; + interpolatedLocations.add(new KLocation(x, y, z, yaw, pitch, Anticheat.INSTANCE.getKeepaliveProcessor().tick)); + } + } + public List getInterpolatedLocations() { int increment = 3; double x = this.x, y = this.y, z = this.z, newX = this.newX, newY = this.newY, newZ = this.newZ;