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 <player>, /xac verbose <player>
  • Verbose mode - Per-flag debug output (disabled by default, enable with /xac verbose <player>)
  • 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:

checks.<check>:
  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:

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 <player> xac.command.status Show player's VL levels and ping
/xac punish <player> <check> xac.command.punish Manually trigger punishment
/xac clearviolations <player> xac.command.clearviolations Clear all VL for a player
/xac verbose <player> 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

# 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
Description
No description provided
Readme 217 KiB
Languages
Java 100%