Paradox AntiCheat
About
Paradox AntiCheat is a lightweight Spigot/Paper anti-cheat plugin built for Paper 1.21.x with a strong focus on low performance impact and minimizing false positives.
The plugin is modular (separate detection modules) and provides:
- A 3-step violation system (warn, warn, kick)
- Staff chat alerts (permission-based)
- Discord webhook logging via clean embeds (including world + coordinates)
- An in-game GUI for browsing detection history
- Optional YAML persistence for detection history
Features
Detection System
- Violation pipeline
- 1st detection: warning (VL 1)
- 2nd detection: warning (VL 2)
- 3rd detection: kick (VL 3 by default)
- Kick
- Configurable kick message
- Staff kick announcement in chat (configurable format)
- Bypass
anticheat.bypasscompletely excludes a player from all checks
Implemented Checks
- Fly / Air movement
- Conservative hover/air-time detection
- Exemptions for common legitimate scenarios (creative/spectator, elytra, flight permissions, water, etc.)
- Suppresses during lag spikes (MSPT gating)
- Grace windows for teleport, knockback/velocity, and riptide
- Speed / Teleport
- Conservative horizontal speed validation with buffers
- Teleport-like movement detection (large delta in one tick)
- MSPT gating + grace windows (teleport, velocity, riptide)
- Elytra/gliding is fully exempted
- Firework rocket usage during elytra/gliding gets a configurable grace window
- KillAura
- Multi-heuristic evaluation (rotation snap + aim angle + timing consistency)
- Sample-based buffering to reduce false positives
- AutoClicker
- Interval variance / stability analysis gated by recent combat activity
- Sample-based buffering to avoid punishing jitter clicking
- Potential Duplication (Drop-based)
- Watches high-value item drops over a time window
- Logs as Potential Dupe (no kick)
- Routes to a dedicated dupe webhook
- Includes item type and total quantity in the reason
Discord Webhooks (Embeds)
- Supports two webhook URLs:
- Normal detections
- Dupe alerts
- Embed format:
- Title (configurable)
- Description:
<username> detected for <reason> - Fields: World + Coords
- Timestamp + color (configurable)
Staff Alerts (Chat)
- Alerts are only visible to players with:
anticheat.seedetections
- Messages are configurable via
alerts.formatandalerts.kickFormat.
GUI (/anticheat)
/anticheatopens a GUI (online player list)- Displays player heads
- Clicking a player opens a paged history view
- Each detection entry shows:
- Detection type
- Timestamp
- World + coordinates
- Reason and violation level
Storage
- Stores detection history in memory with a per-player cap
- Optional persistence to
plugins/ParadoxAntiCheat/detections.yml - Configurable save interval
Installation
- Download
ParadoxAnticheat.jar. - Put it in your server
plugins/folder. - Start the server once to generate the config.
- Edit
plugins/ParadoxAntiCheat/config.yml(webhooks, messages, thresholds). - Restart the server.
Commands
/anticheat- Opens the AntiCheat GUI
Permissions
anticheat.use- Allows opening the GUI (/anticheat)anticheat.seedetections- Allows seeing staff alerts in chatanticheat.bypass- Bypasses all checks for the player
Configuration (config.yml)
File location:
plugins/ParadoxAntiCheat/config.yml
Placeholders
These placeholders can be used in alert formats:
{prefix}:alerts.prefix{player}: player name{type}: detection type (e.g. speed, fly){vl}: current violation level{maxVl}: max violation level before kick
Webhooks
webhook:
enabled: true
url: "https://discord.com/api/webhooks/..."
dupeUrl: "https://discord.com/api/webhooks/..."
connectTimeoutMillis: 2500
requestTimeoutMillis: 3500
embed:
title: "AntiCheat Detection"
color: 15158332
webhook.enabled: Enables/disables all Discord webhook logging.webhook.url: Webhook for normal detections (Fly/Speed/KillAura/AutoClicker).webhook.dupeUrl: Separate webhook for dupe alerts.connectTimeoutMillis: Connection timeout for webhook requests.requestTimeoutMillis: Total request timeout for webhook requests.webhook.embed.title: Embed title.webhook.embed.color: Embed color (decimal).
Embeds include:
- Description:
<username> detected for <reason> - Fields: World + Coords
- Timestamp
Staff Alerts
alerts:
enabled: true
prefix: "&8[&cAntiCheat&8]&r"
format: "{prefix} &f{player} &7detected for &c{type} &7(VL &f{vl}&7/&f{maxVl}&7)"
kickFormat: "{prefix} &cKicked &f{player} &7for &c{type} &7(VL &f{vl}&7/&f{maxVl}&7)"
alerts.enabled: Enables/disables staff alerts in chat.alerts.prefix: Prefix used in alert messages.alerts.format: Message for a detection (warning).alerts.kickFormat: Message sent to staff right before the kick happens.
Alerts are only shown to players with permission anticheat.seedetections.
Violations / Kick Settings
violations:
maxVl: 3
resetAfterSeconds: 600
kick:
enabled: true
message: "&cYou have been kicked for cheating. (&7{type}&c)"
violations.maxVl: Max violation level (VL). When a check reaches this, the player is kicked (if enabled).violations.resetAfterSeconds: If a player goes this long without a flag for the same check, their VL for that check resets.violations.kick.enabled: Enables/disables kicks entirely.violations.kick.message: Kick message shown to the kicked player ({type}is supported).
Storage
storage:
persist: true
saveIntervalSeconds: 60
maxEntriesPerPlayer: 150
storage.persist: Iftrue, detection history is saved toplugins/ParadoxAntiCheat/detections.yml.storage.saveIntervalSeconds: Auto-save interval for persistence.storage.maxEntriesPerPlayer: Max stored detection entries per player (in memory and in persistence).
Checks
All tuning for detections lives under checks.*.
checks:
fly:
enabled: true
lagMsptSuspend: 75
velocityGraceTicks: 30
riptideGraceTicks: 55
teleportGraceTicks: 20
maxAirTicks: 30
hoverDeltaY: 0.0035
hoverMinHorizontal: 0.12
bufferThreshold: 12.0
bufferDecayPerTick: 0.35
bufferAddPerTick: 1.2
speed:
enabled: true
lagMsptSuspend: 75
velocityGraceTicks: 25
riptideGraceTicks: 55
fireworkGraceTicks: 70
teleportGraceTicks: 20
maxHorizontalPerTick:
walk: 0.34
sprint: 0.46
addPerSpeedAmplifier: 0.055
addOnIce: 0.20
addOnSoulSpeed: 0.12
teleportLikeDistance: 7.5
bufferThreshold: 10.0
bufferDecayPerMove: 0.6
bufferAddPerMove: 1.6
General meanings:
enabled: Turns a check on/off.lagMsptSuspend: If MSPT is above this value, the check suppresses flags to avoid false positives during lag.velocityGraceTicks: Grace window after knockback/velocity where movement checks suppress flags.teleportGraceTicks: Grace window after teleport where movement checks suppress flags.bufferThreshold: How many suspicious samples are required before the check flags.bufferDecay*/bufferAdd*: How the suspicion buffer decays or increases.
Fly-specific:
maxAirTicks: Minimum air time before hover logic is evaluated.hoverDeltaY: Maximum vertical change considered “hovering”.hoverMinHorizontal: Minimum horizontal movement while hovering before it becomes suspicious.riptideGraceTicks: Grace window after riptide where Fly flags are suppressed.
Speed-specific:
maxHorizontalPerTick.*: Base allowed horizontal movement per tick for walking/sprinting (with additions for speed potions, ice, soul speed).teleportLikeDistance: One-tick horizontal distance that is treated as teleport-like movement.riptideGraceTicks: Grace window after riptide where Speed flags are suppressed.fireworkGraceTicks: Grace window after using a firework rocket while gliding/elytra, to prevent false Speed flags.
Combat checks (KillAura / AutoClicker) and Dupe:
checks.killaura.*: Controls sample size, aim thresholds, snap thresholds, and buffer tuning.checks.autoclicker.*: Controls combat window, sample requirements, CPS thresholds, and variance thresholds.checks.dupe.*: Controls watched items and the drop-count window and threshold. Dupe alerts never kick.
Troubleshooting
- It still flags elytra/rockets
- Ensure you replaced the jar and restarted the server (not just reload).
- Elytra/gliding is exempted at both the movement check level and at the violation pipeline level for Speed/Fly.
- You can increase
checks.speed.fireworkGraceTicksif needed.
- No Discord messages
- Check
webhook.enabledistrueand URLs are valid. - Ensure the server can reach Discord (network/firewall).
- Check
- Detection history resets
- Enable
storage.persist: trueto persist todetections.yml.
- Enable
Created by Paradox