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;