diff --git a/README.md b/README.md index 0ba9625..d6f7ac4 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,10 @@ # XeroAntiCheat +Lightweight, accurate anti-cheat for Paper 1.21.x + +## Latest Updates (v1.1.0) + +- **ReachCheck**: Now measures distance to entity bounding box center instead of feet. Eliminates false negatives when attacking tall entities (horses, iron golems, withers). Also switched from `distance()` to `distanceSquared()` comparison, removing a `Math.sqrt()` from the hot path. +- **AutoClickerCheck**: `checkPattern()` rewritten with zero-allocation two-pass iterator approach. Previously allocated two `ArrayList` objects on every combat click. +- **TimerCheck**: Removed redundant blink detection from `check()` method. Blink detection is fully handled by the 5-tick scheduled task. `setLastMovePacketTime()` retained to feed the task. +- **KillAuraCheck**: Removed unused `EntityEffect` import. diff --git a/pom.xml b/pom.xml index feae0eb..7d44431 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ com.xeroth xeroanticheat - 1.0.9 + 1.1.0 jar XeroAntiCheat diff --git a/src/main/java/com/xeroth/xeroanticheat/checks/combat/AutoClickerCheck.java b/src/main/java/com/xeroth/xeroanticheat/checks/combat/AutoClickerCheck.java index 15e9a6f..66689a6 100644 --- a/src/main/java/com/xeroth/xeroanticheat/checks/combat/AutoClickerCheck.java +++ b/src/main/java/com/xeroth/xeroanticheat/checks/combat/AutoClickerCheck.java @@ -5,9 +5,6 @@ import com.xeroth.xeroanticheat.check.Check; import com.xeroth.xeroanticheat.data.PlayerData; import org.bukkit.entity.Player; -import java.util.ArrayList; -import java.util.List; - /** * AutoClickerCheck - Tracks CPS (clicks per second) over a 1-second sliding window. * @@ -54,35 +51,33 @@ public class AutoClickerCheck extends Check { * Check click pattern for suspiciously low variance */ private void checkPattern(PlayerData data, Player player, double minVariance) { - List clicks = new ArrayList<>(data.getClickTimestamps()); - - if (clicks.size() < 5) return; - - // Calculate intervals between clicks - List intervals = new ArrayList<>(); - for (int i = 0; i < clicks.size() - 1; i++) { - intervals.add(clicks.get(i) - clicks.get(i + 1)); - } - - if (intervals.isEmpty()) return; - - // Calculate mean + if (data.getClickTimestamps().size() < 5) return; + double sum = 0; - for (Long interval : intervals) { - sum += interval; + int intervalCount = 0; + Long prev = null; + for (Long ts : data.getClickTimestamps()) { + if (prev != null) { + sum += (prev - ts); + intervalCount++; + } + prev = ts; } - double mean = sum / intervals.size(); - - // Calculate variance + if (intervalCount == 0) return; + double mean = sum / intervalCount; + double varianceSum = 0; - for (Long interval : intervals) { - double diff = interval - mean; - varianceSum += diff * diff; + prev = null; + for (Long ts : data.getClickTimestamps()) { + if (prev != null) { + double diff = (prev - ts) - mean; + varianceSum += diff * diff; + } + prev = ts; } - double variance = varianceSum / intervals.size(); - double stdDev = Math.sqrt(variance); - - // If variance is too low, flag (too perfect) + + double stdDev = Math.sqrt(varianceSum / intervalCount); + if (stdDev < minVariance && data.getCPS() > 10) { flag(data, player, 1.0); } diff --git a/src/main/java/com/xeroth/xeroanticheat/checks/combat/KillAuraCheck.java b/src/main/java/com/xeroth/xeroanticheat/checks/combat/KillAuraCheck.java index 6be9975..402ce2e 100644 --- a/src/main/java/com/xeroth/xeroanticheat/checks/combat/KillAuraCheck.java +++ b/src/main/java/com/xeroth/xeroanticheat/checks/combat/KillAuraCheck.java @@ -3,7 +3,6 @@ package com.xeroth.xeroanticheat.checks.combat; import com.xeroth.xeroanticheat.XeroAntiCheat; import com.xeroth.xeroanticheat.check.Check; import com.xeroth.xeroanticheat.data.PlayerData; -import org.bukkit.EntityEffect; import org.bukkit.Location; import org.bukkit.entity.Entity; import org.bukkit.entity.Player; diff --git a/src/main/java/com/xeroth/xeroanticheat/checks/combat/ReachCheck.java b/src/main/java/com/xeroth/xeroanticheat/checks/combat/ReachCheck.java index 869cbab..f4f25c9 100644 --- a/src/main/java/com/xeroth/xeroanticheat/checks/combat/ReachCheck.java +++ b/src/main/java/com/xeroth/xeroanticheat/checks/combat/ReachCheck.java @@ -60,12 +60,20 @@ public class ReachCheck extends Check { // Get player eye location Location eyeLoc = player.getEyeLocation(); - // Get target location (center of entity hitbox) - Location targetLoc = target.getLocation(); + // Use center of entity bounding box, not feet position. + // getLocation() returns feet; bounding box center is more accurate for tall entities. + org.bukkit.util.BoundingBox bb = target.getBoundingBox(); + double targetX = (bb.getMinX() + bb.getMaxX()) / 2.0; + double targetY = (bb.getMinY() + bb.getMaxY()) / 2.0; + double targetZ = (bb.getMinZ() + bb.getMaxZ()) / 2.0; - // Calculate 3D distance - double distance = eyeLoc.distance(targetLoc); + // Calculate 3D distance from player eye to entity center (no Location object needed) + double dx = eyeLoc.getX() - targetX; + double dy = eyeLoc.getY() - targetY; + double dz = eyeLoc.getZ() - targetZ; + double distanceSquared = dx * dx + dy * dy + dz * dz; - return distance > maxReach; + double maxReachSquared = maxReach * maxReach; + return distanceSquared > maxReachSquared; } } diff --git a/src/main/java/com/xeroth/xeroanticheat/checks/movement/TimerCheck.java b/src/main/java/com/xeroth/xeroanticheat/checks/movement/TimerCheck.java index 80c9853..11b876b 100644 --- a/src/main/java/com/xeroth/xeroanticheat/checks/movement/TimerCheck.java +++ b/src/main/java/com/xeroth/xeroanticheat/checks/movement/TimerCheck.java @@ -32,7 +32,6 @@ public class TimerCheck extends Check { // Get thresholds int maxPacketsPerSecond = getConfigInt("max_packets_per_second", 22); - long blinkThresholdMs = getConfigInt("blink_threshold_ms", 500); // If ProtocolLib is active, packet counting is handled by PacketListener if (plugin.isProtocolLibLoaded()) { @@ -57,28 +56,6 @@ public class TimerCheck extends Check { flag(data, player, (data.getPacketsThisSecond() - maxPacketsPerSecond) * 0.5); } - // Check for blink (packet suppression) - long lastMoveTime = data.getLastMovePacketTime(); - if (lastMoveTime > 0) { - long gap = now - lastMoveTime; - if (gap > blinkThresholdMs) { - // Check if player teleported during the gap - PlayerData.PositionSnapshot current = data.getLastPosition(); - PlayerData.PositionSnapshot last = data.getSecondLastPosition(); - if (current != null && last != null) { - double dx = current.x() - last.x(); - double dy = current.y() - last.y(); - double dz = current.z() - last.z(); - double distance = Math.sqrt(dx*dx + dy*dy + dz*dz); - - // If teleported more than 10 blocks, likely blink - if (distance > 10) { - flag(data, player, 2.0); - } - } - } - } - data.setLastMovePacketTime(now); } } diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index c7507c2..f3797b7 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -1,5 +1,5 @@ name: XeroAntiCheat -version: 1.0.9 +version: 1.1.0 main: com.xeroth.xeroanticheat.XeroAntiCheat author: Xeroth description: Lightweight, accurate anti-cheat for Paper 1.21.x