XeroAntiCheat v1.0.8 bug fixes

- SpiderCheck: fixed Location mutation bug - bodyBlock was reading y-1 (same as feetBlock) and headBlock was reading y instead of y+1. Now uses block coordinates directly.
- ConfigManager: decay task no longer reads YamlConfiguration from background thread. decayRate is now volatile and refreshed on reload from main thread only.
- JesusCheck, SpeedCheck, NoFallCheck: loc.subtract() now uses .clone() to prevent silent Location mutation.
- VelocityCheck: decrementVelocityCheckTicks() moved past the minExpected threshold check to avoid consuming a tick on packets that are immediately discarded.
This commit is contained in:
2026-03-15 03:39:39 -03:00
parent 71daf9ffc1
commit daccfedae6
23 changed files with 866 additions and 22 deletions

View File

@@ -231,6 +231,8 @@ public final class XeroAntiCheat extends JavaPlugin {
public void reload() {
configManager.loadConfig();
violationManager.clearAll();
violationManager.setDecayRate(
configManager.getDouble("violation.decay_rate", 0.5));
getLogger().info("Configuration reloaded!");
}

View File

@@ -34,8 +34,6 @@ public class VelocityCheck extends Check {
Vector expected = data.getLastServerVelocity();
if (expected == null || data.getVelocityCheckTicks() <= 0) return;
data.decrementVelocityCheckTicks();
double expectedHorizontal = Math.sqrt(
expected.getX() * expected.getX() + expected.getZ() * expected.getZ());
@@ -45,6 +43,8 @@ public class VelocityCheck extends Check {
return;
}
data.decrementVelocityCheckTicks();
PlayerData.PositionSnapshot curr = data.getLastPosition();
PlayerData.PositionSnapshot prev = data.getSecondLastPosition();
if (curr == null || prev == null) return;

View File

@@ -37,7 +37,7 @@ public class JesusCheck extends Check {
// Get block below player
Location loc = player.getLocation();
Material blockBelow = loc.subtract(0, 1, 0).getBlock().getType();
Material blockBelow = loc.clone().subtract(0, 1, 0).getBlock().getType();
// Check if player is on water or lava
boolean onWater = blockBelow == Material.WATER;

View File

@@ -54,7 +54,7 @@ public class NoFallCheck extends Check {
// Check for damage-reducing blocks
Location loc = player.getLocation();
Material blockBelow = loc.subtract(0, 1, 0).getBlock().getType();
Material blockBelow = loc.clone().subtract(0, 1, 0).getBlock().getType();
// Blocks that reduce/cancel fall damage
if (blockBelow == Material.WATER ||

View File

@@ -130,7 +130,7 @@ public class SpeedCheck extends Check {
// Soul sand slows
Location loc = player.getLocation();
Material blockBelow = loc.subtract(0, 1, 0).getBlock().getType();
Material blockBelow = loc.clone().subtract(0, 1, 0).getBlock().getType();
if (blockBelow == Material.SOUL_SAND || blockBelow == Material.SOUL_SOIL) {
baseSpeed *= 0.75;
}

View File

@@ -3,7 +3,6 @@ package com.xeroth.xeroanticheat.checks.movement;
import com.xeroth.xeroanticheat.XeroAntiCheat;
import com.xeroth.xeroanticheat.check.Check;
import com.xeroth.xeroanticheat.data.PlayerData;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.entity.Player;
@@ -47,17 +46,15 @@ public class SpiderCheck extends Check {
return;
}
// Get blocks around player
Location loc = player.getLocation();
// Check block at feet
Material feetBlock = loc.subtract(0, 1, 0).getBlock().getType();
// Check block at body level
Material bodyBlock = loc.getBlock().getType();
// Check block above head
Material headBlock = loc.add(0, 1, 0).getBlock().getType();
// Get blocks around player using block coordinates (no Location mutation)
org.bukkit.World world = player.getWorld();
int blockX = player.getLocation().getBlockX();
int blockY = player.getLocation().getBlockY();
int blockZ = player.getLocation().getBlockZ();
Material feetBlock = world.getBlockAt(blockX, blockY - 1, blockZ).getType();
Material bodyBlock = world.getBlockAt(blockX, blockY, blockZ).getType();
Material headBlock = world.getBlockAt(blockX, blockY + 1, blockZ).getType();
// Check if any of these blocks are climbable
boolean feetClimbable = isClimbable(feetBlock);

View File

@@ -22,13 +22,17 @@ public class ViolationManager {
private final Map<UUID, PlayerData> playerDataCache = new ConcurrentHashMap<>();
private final MiniMessage miniMessage = MiniMessage.miniMessage();
private double decayRate;
private volatile double decayRate;
public ViolationManager(XeroAntiCheat plugin) {
this.plugin = plugin;
this.decayRate = plugin.getConfigManager().getDouble("violation.decay_rate", 0.5);
}
public void setDecayRate(double rate) {
this.decayRate = rate;
}
/**
* Get or create player data for a player
*/
@@ -89,8 +93,6 @@ public class ViolationManager {
* Decay all violation levels for all players
*/
public void decayAll() {
decayRate = plugin.getConfigManager().getDouble("violation.decay_rate", 0.5);
for (PlayerData data : playerDataCache.values()) {
for (String checkName : data.getViolationLevels().keySet()) {
data.decayViolation(checkName, decayRate);

View File

@@ -1,5 +1,5 @@
name: XeroAntiCheat
version: 1.0.7
version: 1.0.8
main: com.xeroth.xeroanticheat.XeroAntiCheat
author: Xeroth
description: Lightweight, accurate anti-cheat for Paper 1.21.x