XeroAntiCheat v1.0.9 bug fixes
- BUG-1: Added alerts.cooldown_ms (default 5s) to throttle warn() and sendAlert() in PunishmentManager, preventing chat spam during high-frequency flags. Verbose output in ViolationManager also respects the cooldown. Kick/ban punishments always fire immediately regardless of cooldown. - BUG-2: Fixed FlyCheck false positive with Jump Boost I - condition was incorrectly flagging players with Jump Boost level 1. Now exempts all jump boost levels from the sustained-flight flag. - BUG-3: Optimized SpiderCheck by caching player.getLocation() in a single variable instead of calling it 3 times.
This commit is contained in:
2
pom.xml
2
pom.xml
@@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
<groupId>com.xeroth</groupId>
|
<groupId>com.xeroth</groupId>
|
||||||
<artifactId>xeroanticheat</artifactId>
|
<artifactId>xeroanticheat</artifactId>
|
||||||
<version>1.0.8</version>
|
<version>1.0.9</version>
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
<name>XeroAntiCheat</name>
|
<name>XeroAntiCheat</name>
|
||||||
|
|||||||
@@ -67,8 +67,7 @@ public class FlyCheck extends Check {
|
|||||||
// If moving up or staying at same height while not supposed to
|
// If moving up or staying at same height while not supposed to
|
||||||
if (velocity.getY() > 0.1 || Math.abs(velocity.getY()) < 0.01) {
|
if (velocity.getY() > 0.1 || Math.abs(velocity.getY()) < 0.01) {
|
||||||
if (data.getAirTicks() > fallBuffer) {
|
if (data.getAirTicks() > fallBuffer) {
|
||||||
// Additional check: see if player has jump boost
|
if (!data.hasJumpBoost()) {
|
||||||
if (!data.hasJumpBoost() || data.getJumpBoostLevel() <= 1) {
|
|
||||||
flag(data, player);
|
flag(data, player);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,9 +48,10 @@ public class SpiderCheck extends Check {
|
|||||||
|
|
||||||
// Get blocks around player using block coordinates (no Location mutation)
|
// Get blocks around player using block coordinates (no Location mutation)
|
||||||
org.bukkit.World world = player.getWorld();
|
org.bukkit.World world = player.getWorld();
|
||||||
int blockX = player.getLocation().getBlockX();
|
org.bukkit.Location loc = player.getLocation();
|
||||||
int blockY = player.getLocation().getBlockY();
|
int blockX = loc.getBlockX();
|
||||||
int blockZ = player.getLocation().getBlockZ();
|
int blockY = loc.getBlockY();
|
||||||
|
int blockZ = loc.getBlockZ();
|
||||||
|
|
||||||
Material feetBlock = world.getBlockAt(blockX, blockY - 1, blockZ).getType();
|
Material feetBlock = world.getBlockAt(blockX, blockY - 1, blockZ).getType();
|
||||||
Material bodyBlock = world.getBlockAt(blockX, blockY, blockZ).getType();
|
Material bodyBlock = world.getBlockAt(blockX, blockY, blockZ).getType();
|
||||||
|
|||||||
@@ -111,6 +111,9 @@ public class PlayerData {
|
|||||||
// SpeedCheck tracking
|
// SpeedCheck tracking
|
||||||
private int speedViolationTicks = 0;
|
private int speedViolationTicks = 0;
|
||||||
|
|
||||||
|
// Alert cooldown tracking
|
||||||
|
private final Map<String, Long> lastWarnTime = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
public PlayerData(Player player) {
|
public PlayerData(Player player) {
|
||||||
this.uuid = player.getUniqueId();
|
this.uuid = player.getUniqueId();
|
||||||
this.name = player.getName();
|
this.name = player.getName();
|
||||||
@@ -618,6 +621,14 @@ public class PlayerData {
|
|||||||
this.speedViolationTicks = 0;
|
this.speedViolationTicks = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public long getLastWarnTime(String checkName) {
|
||||||
|
return lastWarnTime.getOrDefault(checkName, 0L);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLastWarnTime(String checkName, long time) {
|
||||||
|
lastWarnTime.put(checkName, time);
|
||||||
|
}
|
||||||
|
|
||||||
public void clearPositionHistory() {
|
public void clearPositionHistory() {
|
||||||
positionHistory.clear();
|
positionHistory.clear();
|
||||||
rotationHistory.clear();
|
rotationHistory.clear();
|
||||||
|
|||||||
@@ -171,6 +171,7 @@ public class ConfigManager {
|
|||||||
DEFAULTS.put("alerts.enabled", true);
|
DEFAULTS.put("alerts.enabled", true);
|
||||||
DEFAULTS.put("alerts.format", "<dark_red>[<red>XAC<dark_red>] <white>%player% <red>failed <white>%check% <red>(VL: <white>%vl%<red>)");
|
DEFAULTS.put("alerts.format", "<dark_red>[<red>XAC<dark_red>] <white>%player% <red>failed <white>%check% <red>(VL: <white>%vl%<red>)");
|
||||||
DEFAULTS.put("alerts.staff_format", "<gray>[%time%] %message%");
|
DEFAULTS.put("alerts.staff_format", "<gray>[%time%] %message%");
|
||||||
|
DEFAULTS.put("alerts.cooldown_ms", 5000);
|
||||||
|
|
||||||
// Commands
|
// Commands
|
||||||
DEFAULTS.put("commands.reload_permission", "xac.admin");
|
DEFAULTS.put("commands.reload_permission", "xac.admin");
|
||||||
|
|||||||
@@ -76,7 +76,17 @@ public class PunishmentManager {
|
|||||||
Check check = plugin.getCheckManager().getCheck(checkName);
|
Check check = plugin.getCheckManager().getCheck(checkName);
|
||||||
String category = check != null ? check.getCategory() : "misc";
|
String category = check != null ? check.getCategory() : "misc";
|
||||||
|
|
||||||
sendAlert(player, checkName, vl, category);
|
long cooldownMs = plugin.getConfigManager().getInt("alerts.cooldown_ms", 5000);
|
||||||
|
long now = System.currentTimeMillis();
|
||||||
|
long lastWarn = data.getLastWarnTime(checkName);
|
||||||
|
boolean cooledDown = (now - lastWarn) >= cooldownMs;
|
||||||
|
|
||||||
|
boolean isPunishment = vl >= kickVl;
|
||||||
|
|
||||||
|
if (cooledDown || isPunishment) {
|
||||||
|
sendAlert(player, checkName, vl, category);
|
||||||
|
data.setLastWarnTime(checkName, now);
|
||||||
|
}
|
||||||
|
|
||||||
if (vl >= permbanVl) {
|
if (vl >= permbanVl) {
|
||||||
punish(player, checkName, "PERMBAN", permbanVl);
|
punish(player, checkName, "PERMBAN", permbanVl);
|
||||||
@@ -84,7 +94,7 @@ public class PunishmentManager {
|
|||||||
punish(player, checkName, "TEMPBAN", tempbanVl);
|
punish(player, checkName, "TEMPBAN", tempbanVl);
|
||||||
} else if (vl >= kickVl) {
|
} else if (vl >= kickVl) {
|
||||||
punish(player, checkName, "KICK", kickVl);
|
punish(player, checkName, "KICK", kickVl);
|
||||||
} else if (vl >= warnVl) {
|
} else if (vl >= warnVl && cooledDown) {
|
||||||
warn(player, checkName);
|
warn(player, checkName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -62,16 +62,21 @@ public class ViolationManager {
|
|||||||
double newVl = data.getViolationLevel(checkName);
|
double newVl = data.getViolationLevel(checkName);
|
||||||
|
|
||||||
if (plugin.isVerboseTarget(player.getUniqueId())) {
|
if (plugin.isVerboseTarget(player.getUniqueId())) {
|
||||||
Component verbose = miniMessage.deserialize(
|
long cooldownMs = plugin.getConfigManager().getInt("alerts.cooldown_ms", 5000);
|
||||||
"<gray>[<white>VERBOSE<gray>] <yellow>" + player.getName()
|
long now = System.currentTimeMillis();
|
||||||
+ " <gray>» <white>" + checkName
|
if ((now - data.getLastWarnTime(checkName)) >= cooldownMs) {
|
||||||
+ " <gray>+<green>" + String.format("%.1f", weight)
|
Component verbose = miniMessage.deserialize(
|
||||||
+ " <gray>(VL: <white>" + String.format("%.1f", newVl) + "<gray>)"
|
"<gray>[<white>VERBOSE<gray>] <yellow>" + player.getName()
|
||||||
);
|
+ " <gray>» <white>" + checkName
|
||||||
for (Player staff : Bukkit.getOnlinePlayers()) {
|
+ " <gray>+<green>" + String.format("%.1f", weight)
|
||||||
if (staff.hasPermission("xac.command.verbose") || staff.hasPermission("xac.admin")) {
|
+ " <gray>(VL: <white>" + String.format("%.1f", newVl) + "<gray>)"
|
||||||
staff.sendMessage(verbose);
|
);
|
||||||
|
for (Player staff : Bukkit.getOnlinePlayers()) {
|
||||||
|
if (staff.hasPermission("xac.command.verbose") || staff.hasPermission("xac.admin")) {
|
||||||
|
staff.sendMessage(verbose);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
data.setLastWarnTime(checkName, now);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -316,6 +316,11 @@ alerts:
|
|||||||
# Staff-only alert format
|
# Staff-only alert format
|
||||||
staff_format: "<gray>[%time%] %message%"
|
staff_format: "<gray>[%time%] %message%"
|
||||||
|
|
||||||
|
# Minimum milliseconds between alert/warn messages for the same player+check.
|
||||||
|
# Prevents chat spam when a player is flagging at high frequency.
|
||||||
|
# Default: 5000ms (5 seconds). Set to 0 to disable throttling.
|
||||||
|
cooldown_ms: 5000
|
||||||
|
|
||||||
# ==========================================
|
# ==========================================
|
||||||
# COMMANDS
|
# COMMANDS
|
||||||
# ==========================================
|
# ==========================================
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
name: XeroAntiCheat
|
name: XeroAntiCheat
|
||||||
version: 1.0.8
|
version: 1.0.9
|
||||||
main: com.xeroth.xeroanticheat.XeroAntiCheat
|
main: com.xeroth.xeroanticheat.XeroAntiCheat
|
||||||
author: Xeroth
|
author: Xeroth
|
||||||
description: Lightweight, accurate anti-cheat for Paper 1.21.x
|
description: Lightweight, accurate anti-cheat for Paper 1.21.x
|
||||||
|
|||||||
Reference in New Issue
Block a user