XeroAntiCheat v1.1.0 bug fixes
This commit is contained in:
@@ -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.
|
||||
|
||||
2
pom.xml
2
pom.xml
@@ -6,7 +6,7 @@
|
||||
|
||||
<groupId>com.xeroth</groupId>
|
||||
<artifactId>xeroanticheat</artifactId>
|
||||
<version>1.0.9</version>
|
||||
<version>1.1.0</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>XeroAntiCheat</name>
|
||||
|
||||
@@ -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<Long> clicks = new ArrayList<>(data.getClickTimestamps());
|
||||
if (data.getClickTimestamps().size() < 5) return;
|
||||
|
||||
if (clicks.size() < 5) return;
|
||||
|
||||
// Calculate intervals between clicks
|
||||
List<Long> 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
|
||||
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++;
|
||||
}
|
||||
double mean = sum / intervals.size();
|
||||
prev = ts;
|
||||
}
|
||||
if (intervalCount == 0) return;
|
||||
double mean = sum / intervalCount;
|
||||
|
||||
// Calculate variance
|
||||
double varianceSum = 0;
|
||||
for (Long interval : intervals) {
|
||||
double diff = interval - mean;
|
||||
prev = null;
|
||||
for (Long ts : data.getClickTimestamps()) {
|
||||
if (prev != null) {
|
||||
double diff = (prev - ts) - mean;
|
||||
varianceSum += diff * diff;
|
||||
}
|
||||
double variance = varianceSum / intervals.size();
|
||||
double stdDev = Math.sqrt(variance);
|
||||
prev = ts;
|
||||
}
|
||||
|
||||
double stdDev = Math.sqrt(varianceSum / intervalCount);
|
||||
|
||||
// If variance is too low, flag (too perfect)
|
||||
if (stdDev < minVariance && data.getCPS() > 10) {
|
||||
flag(data, player, 1.0);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user