# XeroAntiCheat - Minecraft Anti-Cheat Plugin A lightweight, production-ready anti-cheat plugin for Paper 1.21.x (compatible with 1.20-1.22). ## Overview XeroAntiCheat is designed to detect common Minecraft cheats while minimizing false positives. It features: - **17 comprehensive checks** across movement, combat, and miscellaneous categories - **Thread-safe architecture** with async/sync operation separation - **Configurable thresholds** via config.yml - **Violation level (VL) system** with temporal decay - **Punishment pipeline** (warn → kick → tempban → permban) - **MiniMessage support** for modern chat formatting - **ProtocolLib integration** (optional) for packet-level detection - **Automatic potion effect tracking** for accurate speed/fall detection - **Staff alert toggle** - staff can opt out of receiving alerts ## Latest Updates (v1.0.5) ### Bug Fixes - **DatabaseManager race condition** - Fixed `close()` method to be synchronized and null the connection after closing. Prevents `SQLException: database is closed` errors when async inserts race with plugin disable. - **PhaseCheck teleport false positives** - Added `max_distance` config (default 5.0 blocks). Movement deltas exceeding this value are now ignored (treated as teleports). Also replaced hardcoded Y-offset `0.1` with `player.getEyeHeight()` for state-aware ray-casting. - **Position history reset on teleport** - Added `PlayerTeleportEvent` handler in MovementListener that clears position/velocity history, resets air ticks, and clears server velocity. Prevents false positives across all inter-position checks after teleportation. - **VelocityCheck grace period** - Added `PlayerRespawnEvent` handler in MiscListener that clears server velocity and position history. Prevents false positives after respawn. - **ScaffoldCheck Signal 4 false positive** - Changed `lastPlacementYaw` initial value from `0` to `Float.NaN` as a sentinel. Signal 4 now skips on first block placement of the session to prevent false positives when yaw happens to be near 0. ### Quality Improvements - **Listener bypass comments** - Added explanatory comments at `hasPermission("xac.bypass")` early-return sites in all listeners to clarify that category/per-check bypass is enforced deeper in the call stack. --- ## Latest Updates (v1.0.7) ### Bug Fixes - **KillAura multi-target time window** - `checkMultiTarget()` was ignoring the configured time window entirely. Was counting all-time target transitions (up to 5 attacks) instead of distinct entities attacked within the window. Fixed by using parallel iterators over `attackTimestamps` and `attackedEntities` to correctly count unique targets within the last `window` milliseconds. - **PlayerData deque capacity mismatch** - `attackedEntities` deque was capped at 5 while `attackTimestamps` was capped at 10. After 5 attacks, deques would desync and parallel iteration would produce incorrect results. Fixed by aligning both to capacity 10. - **NoFall Feather Falling negative damage** - Custom enchant levels above 8 would produce negative expected damage (e.g., level 9 → multiplier -0.08), permanently disabling the check. Fixed by clamping multiplier to minimum 0.0. - **ScaffoldCheck allocation in hot path** - `computePlacementIntervalStdDev()` was calling `toArray()` on every block placement, allocating arrays in a performance-critical path. Fixed with zero-allocation two-pass iterator approach. --- ## Latest Updates (v1.0.6) ### Bug Fixes - **SpiderCheck and GlideCheck cross-player pollution** - Tick counters (`spiderAirTicks`, `glideAirTicks`) were stored as instance fields on the check class, shared across ALL players. Fixed by moving counters to PlayerData for per-player state. - **KillAuraCheck angle NaN false negative** - `Math.acos()` was receiving unconstrained dot product values, which can produce NaN when floating-point rounding pushes values outside [-1, 1]. This silently disabled angle detection. Fixed by clamping dot product to [-1, 1] before acos. - **SpeedCheck rolling average implementation** - `bufferTicks` config was read but never used. Implemented actual consecutive-tick counter that flags only after speed exceeds max for N consecutive ticks. - **SpeedCheck latency compensation ignored actual ping** - Was using fixed config value regardless of player ping. Now scales with actual ping using formula `min(ping / 100.0 * 0.01 * pingFactor, 0.15)`, consistent with ReachCheck. - **PlayerData.getSecondLastPosition() allocation** - Method was calling `toArray()` on every call, allocating a temporary array in a hot path. Replaced with iterator-based access. ### Config Changes - Renamed `checks.speed.latency_compensation` to `checks.speed.ping_factor` for clarity --- ## Latest Updates (v1.0.4) ### Bug Fixes - **FastEat bypass permissions** - Fixed missing `isBypassed()` guard in MiscListener for FastEat check. Permissions `xac.bypass.fasteat` and `xac.bypass.misc` now work correctly. - **Bypass consistency** - Replaced `hasPermission("xac.bypass")` with `isBypassed(player)` in all 15 check classes for consistent three-tier permission checking. ### ProtocolLib Integration - **Real packet listeners** - PacketListener.java completely rewritten to use actual ProtocolLib API (no more reflection-based stubs) - **Three packet adapters**: - Movement packets (POSITION, POSITION_LOOK, LOOK) → feeds TimerCheck counters and KillAura rotation history - ARM_ANIMATION → feeds AutoClickerCheck click tracking - ENTITY_VELOCITY → feeds VelocityCheck knockback verification - **Event guard** - TimerCheck now skips event-based counter increment when ProtocolLib is active (prevents double-counting) - **Click guard** - CombatListener no longer adds clicks via event when ProtocolLib handles ARM_ANIMATION ### New Checks - **PhaseCheck** - Detects players clipping through solid blocks using server-side ray-casting between positions. Requires 0.5+ block movement to trigger. - **VelocityCheck** - Detects players ignoring server-sent knockback (no-knockback hacks). Requires ProtocolLib. Compares actual horizontal displacement against expected velocity over 4 ticks. ### Scaffold Improvements - **Two new detection signals**: - Signal 4: Rotation lock - detects fixed yaw while side-bridging (yaw change <2° with horizontal speed >0.15) - Signal 5: Placement interval variance - detects suspiciously perfect timing (stdDev <30ms at 5+ BPS) - Now has 5 signals total, still requires 2 to flag ### SQLite Database - **DatabaseManager** - New manager for SQLite-based punishment logging - Punishments now logged to both flat-file (`logs/punishments.log`) and SQLite (`data.db`) - Configurable via `database.enabled` in config.yml (default: true) --- ## Latest Updates (v1.0.3) ### Bug Fixes - **Granular bypass permissions now working** - Added `isBypassed(Player)` method to Check.java and guarded all direct `addViolation()` calls in CombatListener and MiscListener. The permissions `xac.bypass.reach`, `xac.bypass.killaura`, `xac.bypass.critical`, `xac.bypass.scaffold`, `xac.bypass.nofall`, and category bypasses now function correctly for all checks. - **TimerCheck blink detection** - Fixed bypass check to use three-tier permission hierarchy instead of only checking global `xac.bypass`. - **SpeedCheck Slowness calculation** - Fixed incorrect field reference: was using `getSpeedLevel()` instead of `getSlownessLevel()` for Slowness potion penalty, causing false positives for players under Slowness effect. - **Async file I/O** - `logPunishment()` now writes to disk on a background thread to prevent tick lag. ### Quality Improvements - **Main thread Bukkit API** - Changed `startPotionRefreshTask()` from async to sync (Bukkit API should only be called from main thread). - **Thread-safe collections** - Changed `alertToggles` from `HashMap` to `ConcurrentHashMap` for future-proofing. ### Permission System Overhaul (v1.0.2) - **Granular permission tree** - One permission per action with wildcard inheritance - **Per-category alerts** - Staff can receive only movement, combat, or misc alerts - **Per-check bypass** - Bypass specific checks (e.g., `xac.bypass.speed`) - **Category bypass** - Bypass entire categories (e.g., `xac.bypass.movement`) - **New commands**: `/xac clearviolations `, `/xac verbose ` - **Verbose mode** - Per-flag debug output (disabled by default, enable with `/xac verbose `) - Category-filtered alerts respect permissions: `xac.alerts.movement`, `xac.alerts.combat`, `xac.alerts.misc` ### Bug Fixes (v1.0.2) - **NoFallCheck**: Rewrote damage detection logic - now properly calculates expected fall damage and compares against actual damage via EntityDamageEvent - **CriticalCheck**: Fixed physics-based crit detection - now uses velocity/fall distance instead of damage modulo (was causing 100% false positives) - **airTicks**: Fixed multiple checks incrementing airTicks in same tick - now only MovementListener manages airTicks, checks have their own counters - **Potion Effects**: Added automatic potion effect refresh task (runs every 10 ticks async) - Speed, Slowness, Levitation, Dolphins Grace, Jump Boost, Slow Falling now properly tracked - **Knockback**: Added knockback tracking - SpeedCheck now accounts for knockback (500ms grace after taking damage) - **FastEatCheck**: Fixed to track eat start time (PlayerInteractEvent) instead of consume-to-consume interval - **JesusCheck**: Added isSwimming() check to avoid false positives for underwater movement - **ReachCheck**: Ping compensation now scales dynamically with actual player ping (0.03 blocks per 100ms, capped at 0.3) - **TimerCheck**: Added scheduled task for blink detection (checks every 5 ticks for gaps >500ms) - **Alert Toggle**: Staff can now toggle alerts on/off with `/xac alerts on/off` - **ConfigManager**: Fixed validation to use getDouble() for max_speed - **Food Detection**: MiscListener now uses Paper API isEdible() instead of hardcoded switch ### Architecture Improvements - Async potion effect refresh task keeps all check data up-to-date - Independent tick counters per check prevent false positives from shared state - EntityDamageEvent listener for accurate damage comparison in NoFallCheck - Dynamic ping compensation in ReachCheck scales with actual network conditions ## Project Structure ``` /home/axel/Músicas/Java ├── pom.xml # Maven build configuration ├── src/main/ │ ├── java/com/xeroth/xeroanticheat/ │ │ ├── XeroAntiCheat.java # Main plugin class │ │ ├── check/ │ │ │ └── Check.java # Abstract base class for all checks │ │ ├── checks/ │ │ │ ├── movement/ # Movement-related checks │ │ │ │ ├── SpeedCheck.java │ │ │ │ ├── FlyCheck.java │ │ │ │ ├── JesusCheck.java │ │ │ │ ├── NoFallCheck.java │ │ │ │ ├── TimerCheck.java │ │ │ │ ├── SpiderCheck.java │ │ │ │ └── GlideCheck.java │ │ │ ├── combat/ # Combat-related checks │ │ │ │ ├── KillAuraCheck.java │ │ │ │ ├── ReachCheck.java │ │ │ │ ├── CriticalCheck.java │ │ │ │ └── AutoClickerCheck.java │ │ │ └── misc/ # Miscellaneous checks │ │ │ ├── FastPlaceCheck.java │ │ │ ├── ScaffoldCheck.java │ │ │ ├── FastEatCheck.java │ │ │ └── InventoryMoveCheck.java │ │ ├── manager/ # Core managers │ │ │ ├── CheckManager.java │ │ │ ├── ConfigManager.java │ │ │ ├── PunishmentManager.java │ │ │ └── ViolationManager.java │ │ ├── data/ │ │ │ └── PlayerData.java # Per-player state storage │ │ ├── command/ │ │ │ └── XACCommand.java # Command handler │ │ ├── listener/ # Event listeners │ │ │ ├── MovementListener.java │ │ │ ├── CombatListener.java │ │ │ └── MiscListener.java │ │ └── protocol/ │ │ └── PacketListener.java # ProtocolLib integration │ └── resources/ │ ├── plugin.yml # Plugin metadata │ └── config.yml # Configuration file └── target/ └── XeroAntiCheat.jar # Built plugin ``` ## Architecture ### Module Interaction ``` ┌─────────────────────────────────────────────────────────────┐ │ XeroAntiCheat (Main) │ │ - onEnable(): Initialize all managers, register listeners │ │ - onDisable(): Cleanup, save data, cancel tasks │ └─────────────────────────────────────────────────────────────┘ │ │ │ ▼ ▼ ▼ ┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐ │ ConfigManager │ │ CheckManager │ │ PlayerData Cache│ │ - loadConfig() │ │ - registerCheck│ │ - ConcurrentHM │ │ - getTyped() │ │ - runCheck() │ │ - onJoin/Quit │ │ - validate() │ │ - getCheck() │ │ - thread-safe │ └──────────────────┘ └──────────────────┘ └──────────────────┘ │ │ │ ▼ ▼ ▼ ┌─────────────────────────────────────────────────────────────┐ │ Event Listeners (Sync) │ │ - MovementListener → PlayerMoveEvent │ │ - CombatListener → EntityDamageByEntityEvent │ │ - MiscListener → BlockPlaceEvent, PlayerItemConsumeEvent│ └─────────────────────────────────────────────────────────────┘ │ │ │ ▼ ▼ ▼ ┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐ │ ViolationManager │ │ PunishmentManager │ │ ProtocolLib │ │ - addViolation │ │ - evaluate() │ │ PacketListener │ │ - decayVL() │ │ - punish() │ │ - MONITOR │ │ - getVL() │ │ - warn/kick/ban │ │ - hasProtocolLib│ └──────────────────┘ └──────────────────┘ └──────────────────┘ ``` ### Key Design Decisions 1. **Thread Safety**: PlayerData uses `ConcurrentHashMap` and `ArrayDeque` for thread-safe operations 2. **Performance**: Movement checks only run when `hasChangedPosition()` is true 3. **Async Operations**: VL decay, potion refresh, config validation run async 4. **Fallback System**: Features work without ProtocolLib (reduced accuracy) ## Check Descriptions ### Movement Checks | Check | Detection Method | |-------|-----------------| | **SpeedCheck** | Horizontal movement exceeding max speed for player state (sprinting, sneaking, swimming, potions, ice, etc.). Uses rolling average over 5 ticks with TPS/ping compensation. | | **FlyCheck** | Sustained flight without elytra/creative/spectator. Tracks air ticks and ground desync between client/server. | | **JesusCheck** | Walking on water without Frost Walker enchantment or boat. Checks block type at feet. | | **NoFallCheck** | No fall damage after falling >3 blocks. Compares expected damage vs actual, accounting for Feather Falling, Slow Falling, water, honey blocks. | | **TimerCheck** | Packet timing anomalies: >22 packets/sec or blink (no packets >500ms then teleport). | | **SpiderCheck** | Climbing non-climbable blocks (non-ladder/vine/scaffolding) with upward velocity. | | **GlideCheck** | Elytra-like fall curve (slow Y decrease) without elytra equipped. | | **PhaseCheck** | Server-side ray-cast between positions. Flags if solid block intersects movement path. Requires 0.5+ block travel. | ### Combat Checks | Check | Detection Method | |-------|-----------------| | **KillAuraCheck** | Three sub-checks: (1) Attack angle >100° from look direction, (2) Snap rotation >45° between attacks, (3) Multi-targeting >2 entities within 100ms. | | **ReachCheck** | 3D distance from player eye to entity hitbox. Default threshold 3.2 blocks (survival), 5.0 (creative), with ping compensation. | | **CriticalCheck** | Critical hits without airborne state. Detects crits while on ground or while sprinting (cancels sprint). Allows legitimate jump-crits. | | **AutoClickerCheck** | CPS tracking over 1-second window. Flags >20 CPS. Also analyzes inter-click variance - flags suspiciously perfect patterns (stdDev < 2.0). | | **VelocityCheck** | Compares actual horizontal displacement against server-sent ENTITY_VELOCITY. Flags if player moves <20% of expected knockback. Requires ProtocolLib. | ### Miscellaneous Checks | Check | Detection Method | |-------|-----------------| | **FastPlaceCheck** | Block placement >20 blocks/sec. Uses timestamp deque for tracking. | | **ScaffoldCheck** | Multi-signal detection (5 signals): (1) Pitch >75° while running, (2) Placing below player, (3) No valid support face, (4) Rotation lock (yaw change <2° while moving), (5) Placement interval variance (too-perfect timing). Requires 2+ signals. | | **FastEatCheck** | Food consumption faster than 32 ticks (1.6 seconds). | | **InventoryMoveCheck** | Position change >0.1 while inventory is open. | ## Violation System ### VL Accumulation - Each check maintains its own violation level per player - `addViolation(player, checkName, weight)` increments VL - Default weight is 1.0, scaled by detection severity ### Decay - Runs every 30 seconds (configurable) - Reduces each check's VL by decay_rate (default: 0.5) - Minimum VL is 0.0 ### Thresholds Configurable per check in `config.yml`: ```yaml checks.: warn_vl: 10 # Send warning kick_vl: 25 # Kick player tempban_vl: 50 # Temporary ban (30 days) permban_vl: 100 # Permanent ban ``` ## Punishment Pipeline 1. **Warning** (VL ≥ warn_vl): MiniMessage alert to player 2. **Kick** (VL ≥ kick_vl): `player.kick()` 3. **TempBan** (VL ≥ tempban_vl): Execute config command 4. **PermBan** (VL ≥ permban_vl): Execute config command Commands are configurable in config.yml: ```yaml punishments: kick_command: "kick %player% &c[XAC] Illegal activity detected" tempban_command: "tempban %player% 30d %reason%" permban_command: "ban %player% %reason%" ``` All punishments logged to `plugins/XeroAntiCheat/logs/punishments.log`. ## Configuration All settings in `config.yml`: ### General - `enabled`: Enable/disable plugin - `debug`: Additional logging - `async_task_threads`: Background thread count ### Violation - `decay_interval`: Seconds between decay (default: 30) - `decay_rate`: Amount to reduce VL per decay (default: 0.5) ### Checks Each check has `enabled` and threshold settings. See `config.yml` for defaults. ### Commands - `reload_permission`: xac.admin - `bypass_permission`: xac.bypass - `alerts_permission`: xac.alerts ## Commands | Command | Permission | Description | |---------|------------|-------------| | `/xac reload` | xac.command.reload | Reload configuration | | `/xac status ` | xac.command.status | Show player's VL levels and ping | | `/xac punish ` | xac.command.punish | Manually trigger punishment | | `/xac clearviolations ` | xac.command.clearviolations | Clear all VL for a player | | `/xac verbose ` | xac.command.verbose | Toggle per-flag debug output | | `/xac alerts [on\|off]` | xac.command.alerts | Toggle alert receiving | | `/xac version` | xac.command.version | Show plugin version | ## Permissions ### Wildcards - `xac.*` - All permissions (admin + bypass) - `xac.admin` - All commands and alerts (does NOT grant bypass) - `xac.bypass` - Bypass all checks - `xac.alerts` - Receive all alerts ### Command Permissions - `xac.command.reload` - /xac reload - `xac.command.status` - /xac status - `xac.command.punish` - /xac punish - `xac.command.clearviolations` - /xac clearviolations - `xac.command.verbose` - /xac verbose - `xac.command.alerts` - /xac alerts - `xac.command.version` - /xac version ### Category Alerts - `xac.alerts.movement` - Movement check alerts only - `xac.alerts.combat` - Combat check alerts only - `xac.alerts.misc` - Misc check alerts only ### Bypass Permissions **Movement:** - `xac.bypass.movement` - All movement checks - `xac.bypass.speed`, `xac.bypass.fly`, `xac.bypass.jesus`, `xac.bypass.nofall`, `xac.bypass.timer`, `xac.bypass.spider`, `xac.bypass.glide` **Combat:** - `xac.bypass.combat` - All combat checks - `xac.bypass.killaura`, `xac.bypass.reach`, `xac.bypass.critical`, `xac.bypass.autoclicker` **Misc:** - `xac.bypass.misc` - All misc checks - `xac.bypass.fastplace`, `xac.bypass.scaffold`, `xac.bypass.fasteat`, `xac.bypass.inventorymove` ### LuckPerms Example Roles ``` # Helper - read-only, sees all alerts /lp group helper permission set xac.command.status true /lp group helper permission set xac.command.alerts true /lp group helper permission set xac.alerts true # Junior Mod - combat alerts only /lp group junior-mod permission set xac.alerts.combat true # Moderator - full alerts + punish /lp group moderator permission set xac.alerts true /lp group moderator permission set xac.command.punish true # Streamer - bypass movement + combat /lp group streamer permission set xac.bypass.movement true /lp group streamer permission set xac.bypass.combat true # Build team - bypass speed/fly only /lp group build permission set xac.bypass.speed true /lp group build permission set xac.bypass.fly true ``` ## Build Instructions ```bash # Build the plugin mvn package # The JAR will be in target/XeroAntiCheat.jar ``` ## Dependencies - **Paper API** 1.21.1-R0.1-SNAPSHOT (provided) - **ProtocolLib** (optional, for packet-level detection) ## Performance Optimizations 1. **Event Filtering**: Movement checks only run when position actually changes 2. **Fixed-Size Data Structures**: ArrayDeque for position/click history (max 20 entries) 3. **Primitive Math**: Avoid creating new Location/Vector objects in hot paths 4. **TPS Compensation**: Velocity thresholds scale with server TPS 5. **Async Operations**: VL decay, config validation, logging run on background threads ## Edge Case Handling | Scenario | Handling | |----------|----------| | Creative mode | Most checks ignored | | Bypass permission | Silently ignored | | Lag spikes | TPS compensation applied | | Pearl teleportation | Reset air timers, position buffers | | Jump-crits | Allow if wasAirborne previous 3 ticks | | Frost Walker | Allow water walking | | Slow Falling potion | Ignore fall damage | | Water/honey landing | No damage expected | ## Future Enhancements Potential areas for expansion: - Entity prediction check - More scaffold signals - Velocity verification - Phase detection - Packet order validation - SQL-based violation logging - Web dashboard integration