Compatibility
Minecraft: Java Edition
Platforms
Tags
Creators
Details
AntiESP
A Paper plugin that makes ESP / wallhack / xray cheats far less useful by never sending the client information it should not be able to see in the first place.
Three independent protections in one plugin:
| # | Protection | What it does |
|---|---|---|
| 1 | Player hiding | Players behind walls are removed client-side for the viewer (optionally keeping a floating nametag and their tab-list entry). |
| 2 | Block disguise | Chests, shulkers, spawners, barrels … look like plain stone from a distance. |
| 3 | Ore obfuscator | Self-written anti-xray: real ores are hidden, fake ore veins are scattered in, and caves can be filled with solid rock (freecam-proof). |
Everything is configurable in config.yml, and every feature can be turned off
individually.
Requirements
- Paper 1.21.8 (or a compatible build) — the plugin uses the Paper API
- Java 21
- Optional: PacketEvents — required for packet mode (cave filling / freecam protection) and for keeping hidden players in the tab list. Without it the plugin still runs, just with the block-mode feature set.
Installation
- Drop
AntiESP-1.0.0.jarinto your server'splugins/folder. - (Recommended) Drop
PacketEventsintoplugins/as well. - Start the server —
plugins/AntiESP/config.ymlis generated on first run. - Before going live with packet mode, run the
identity-testonce (see Ore obfuscator).
Building from source
mvn clean package
The jar ends up in target/AntiESP-1.0.0.jar. Both dependencies are provided,
so nothing is shaded in — the jar stays tiny.
1) Player hiding
For every viewer/target pair the plugin ray-traces the line of sight
(Amanatides & Woo voxel traversal, RayTracer) and picks one of three states:
- VISIBLE — close by or in clear sight: nothing changes.
- NAMETAG — occluded at medium range: the player model and hitbox are hidden,
but a floating name (a proxy
TextDisplay) stays visible. - GONE — occluded and far away: completely invisible.
Hiding starts at min-distance (default 12 blocks) and only when more than
walls-to-hide opaque blocks are in the way. Several target points on the body
are checked — a player is only hidden when all of them are occluded, so nobody
pops out of existence while half-visible around a corner.
Key options:
| Option | Default | Meaning |
|---|---|---|
check-interval-ticks |
10 |
How often visibility is recalculated |
min-distance |
12.0 |
Below this distance players are always visible |
max-distance |
96.0 |
Upper bound for the check (0 = no limit) |
walls-to-hide |
2 |
Hide when the wall count is greater than this |
require-occlusion |
true |
Only hide genuinely occluded players |
keep-nametags |
true |
Keep the floating name for hidden players |
nametag-max-distance |
48.0 |
Beyond this the nametag disappears too |
keep-tablist |
true |
Keep hidden players in the tab list (needs PacketEvents) |
Sneaking hides the nametag immediately instead of waiting for the next tick.
Note: a visible nametag still roughly gives away a position. Set
keep-nametags: falsefor the strongest protection.
2) Block disguise
Valuable block-entities are replaced with stone (disguise-as) via
sendBlockChange for viewers that are far away or looking through walls. Walk
closer than reveal-distance and the real block comes back, so containers open
normally. Uses only the Bukkit API — no ProtocolLib, no PacketEvents.
By default chests, trapped chests, ender chests, barrels, hoppers, droppers,
dispensers, all shulker boxes, spawners, trial spawners, vaults, brewing stands,
beacons, furnaces, blast furnaces, smokers and decorated pots are disguised. Edit
the block-disguise.blocks list, or set all-block-entities: true to cover every
block-entity (signs and banners included — this is noticeable).
3) Ore obfuscator (anti-xray)
A fully self-contained anti-xray implementation — no Paper anti-xray, no Orebfuscator. Real ores are sent as stone/deepslate and fake ore veins are grown in natural Y ranges and vein sizes.
Two modes:
| Block mode | Packet mode (recommended) | |
|---|---|---|
| Needs PacketEvents | no | yes |
| Hide enclosed real ores | ✅ | ✅ |
| Scatter fake ore veins | ✅ | ✅ |
| Fill small enclosed pockets | ✅ | ✅ |
| Fill large open caves (freecam-proof) | ❌ | ✅ |
| How | sendBlockChange after chunk load |
rewrites the CHUNK_DATA packet itself |
Ores that border air are left real — you would see them anyway — so the world "normalizes" itself exactly where a player could legitimately look. In packet mode a proximity reveal flood-fills through the connected cave air you are standing in and uncovers the whole cave system, direction-independently, spread across a few ticks. Revealed blocks stay revealed until relog. Nether and End are not obfuscated at all.
The fake pattern is seeded from a secretSalt generated with SecureRandom at
every server start (RAM only) XOR'd with the chunk coordinates: stable per chunk
(no flickering), but not reproducible without the salt.
Test packet mode first. Rewriting the chunk binary format is version sensitive. Set
ore-obfuscation.identity-test: true, restart, and check that the world looks normal — that decodes and re-encodes every chunk packet without changing anything. If it looks fine, set it back tofalse.
Full details, tuning advice and the honest limitations (notably: anyone who knows the world seed can regenerate ore positions server-side, no client-side obfuscation can prevent that) are in docs/ANTI-XRAY.md.
Commands & permissions
| Command | Description |
|---|---|
/antiesp reload |
Reload config.yml and clear the chunk cache |
/antiesp status |
Show the active settings, mode and cache sizes |
| Permission | Default | Description |
|---|---|---|
antiesp.admin |
op | Access to /antiesp |
antiesp.bypass |
false | This player is never hidden from others and sees the real, unobfuscated world |
packet-modeandidentity-testare only applied on a server restart, not via/antiesp reload.
Project layout
src/main/java/dev/antiesp/
AntiESPPlugin.java entry point, events, commands
PlayerVisibilityService.java player hiding + proxy nametags
TabListKeeper.java keeps hidden players in the tab list (PacketEvents)
BlockDisguiseService.java container/block-entity disguise
OreObfuscationService.java anti-xray, block mode
ChunkPacketObfuscator.java anti-xray, packet mode (CHUNK_DATA rewriting)
ProximityRevealer.java persistent flood-fill cave reveal
RayTracer.java voxel ray tracing for occlusion counting
src/main/resources/
config.yml, plugin.yml
docs/ANTI-XRAY.md in-depth anti-xray documentation (German)
Performance notes
- Packet mode computes per chunk on the Netty threads; results are cached
(
max-cache-chunks, default 6000) and invalidated when blocks are mined. - Only player block-breaking invalidates the cache — TNT, pistons and water do not, currently.
- The proximity reveal only re-floods when you move to a new block, mine, or join; standing still and turning around costs nothing.

