What each anti-cheat check catches, how it responds and how to switch it off.
Basalt checks what clients send against what the game allows. There are nine checks, each aimed at one kind of hacked client or proxy, and each with its own switch in basalt.toml. All are on by default.
How a check responds
Section titled “How a check responds”A check never speaks in chat and never punishes on one event. It works in three steps:
- Correct. The offending action is dropped or undone every time: the hit does nothing, the block is put back, the player is pulled back to the ground.
- Count. Each catch adds to that player’s count for the check. The count wears off over time, so an occasional false alarm never adds up.
- Kick. When the count reaches the check’s limit, the player is disconnected with “Kicked by admin. Reason: Unfair advantage”. The proxy check says “Proxy Detected” instead.
Every check kicks at a count of five, except the proxy check, which kicks at once.
Each catch is logged as a warning with the player, the check, the count, the limit and what was seen:
WARN anti-cheat player="Steve" check="fly" level=1.0 limit=5.0 detail="jumped while already off the ground"The checks
Section titled “The checks”| Setting | Catches | Correction | Count wears off |
|---|---|---|---|
anticheat_fly |
Jumping again while already in the air with no way to fly | Pulled back to where they last stood on the ground | 0.2 a second |
anticheat_reach |
Using blocks or hitting players and mobs through walls or from too far away | The click or hit is refused and the blocks are sent back | 0.1 a second |
anticheat_scaffold |
Placing blocks faster than a hand can, or on a face the player is not looking at | The placement is refused and the block sent back | 0.2 a second |
anticheat_fast_break |
Many ticks of block breaking packed into one input | The input’s breaking is cleared | 0.5 a second |
anticheat_criticals |
Critical hits from a “fall” the player never jumped or stepped into | The hit is dropped | 0.2 a second |
anticheat_self_hit |
A player attacking themselves | The hit is dropped | 0.05 a second |
anticheat_inventory |
Moving items into armour slots with old-style inventory transactions | The move is dropped and the inventory sent back | 0.05 a second |
anticheat_crash_packets |
Packets built to crash other players’ games | The packet is dropped | 0.5 a second |
anticheat_proxy |
A login rewritten by a proxy | Disconnected immediately | Never |
Flight hacks make the client believe there is ground under the player’s feet, so it sends a fresh jump while the player is in mid-air. Basalt allows one jump off real ground; a second jump while there is still nothing under or beside the player is flight. The player is pulled back to where they last stood.
Holding the jump key through a normal jump, bouncing on slime or a bed, and Jump Boost do not trigger it. The check is skipped for players in creative or spectator mode, anyone allowed to fly, anyone climbing, swimming, gliding, riding, holding a trident, under Levitation or dead, and for a short while (40 inputs) after knockback, a shield push, a teleport, leaving a vehicle, respawning or being moved by a plugin.
Two things are checked.
- Blocks. A click on a block is refused unless there is a clear line from the player’s eyes to it. This stops reaching through a wall to open a chest behind it.
- Hits. A melee hit must be within 5 blocks, or 8 in creative, measured from the attacker’s eyes to the nearest point of the target, with a clear line of sight.
The distance is measured to the nearest point of the target’s hitbox, not its centre, so hitting the near side of a wide mob is judged fairly. Two allowances are added automatically; see Compensation.
Scaffold
Section titled “Scaffold”Scaffold and auto-bridge hacks place blocks far faster than a player can and often without looking at them. A placement is refused when either is true:
- the player has already placed 10 blocks within the last second (fast legitimate bridging is about 5 a second), or
- the clicked point is behind the player, more than 90 degrees from where they are facing.
Only blocks that were actually placed count towards the rate. Clicks that place nothing, such as opening a door or holding the button on a spot that is already taken, do not.
Fast break
Section titled “Fast break”Honest clients send at most one tick of breaking progress per input. Basalt only ever counts one, so a fast-break hack gains nothing even with the check off. The check itself counts inputs that carry more than four breaking actions.
Criticals
Section titled “Criticals”A critical hit needs a real fall. Basalt tracks how the player left the ground: by jumping, by walking off an edge, or by being pushed. A “falling” hit that began with none of those and rose less than 0.4 blocks is not a critical and is counted. Crits from real jumps, falls and knockback are untouched.
Self-hit
Section titled “Self-hit”No honest client attacks its own player. The hit is dropped with no damage and no knockback.
Inventory
Section titled “Inventory”Current clients move items with server-checked requests. A client that sends an old-style transaction touching the armour slots is refused and has its inventory sent back.
Crash packets
Section titled “Crash packets”Some hacks flood packets that crash the games of everyone nearby. Basalt drops and counts:
- eating events that do not match the item the player is holding, or that name another entity,
- sounds whose name is not a valid sound name,
- emotes whose id is not a valid id.
Separately, and always on, a packet that only Basalt should ever send (chunk data, resource pack data and the like) is rejected if a client sends it.
Proxies that sit between a player and Basalt rebuild the login and leave a tell-tale mismatch between it and the client’s cache setting. A signed login that shows the mismatch is treated as a proxy, as is a client that flips the cache setting mid-game. Logins from Nintendo Switch are never judged, because that console behaves differently.
Compensation
Section titled “Compensation”Players with high ping act on a world that is slightly out of date, and a player who has just been hit is moving fast. The reach check allows for both so that honest players are not flagged.
| Allowance | When | How much |
|---|---|---|
| Ping | Always, based on the attacker’s measured ping | +0.5 blocks per 100 ms, up to +1.5 blocks |
| Knockback | For 3 ticks after a hit lands, for that target’s attacker | The target’s launch speed times 3, up to +1.0 block |
So a survival player with 150 ms of ping may hit from up to 5.75 blocks. The allowances are capped, so an obvious over-reach, such as a 7-block hit, is still caught. A refused hit never earns a knockback allowance, so a reach hack cannot build up its own margin.
Basalt measures each player’s ping itself, about once a second, and smooths the result.
These allowances are automatic and have no settings.
Turning checks off
Section titled “Turning checks off”Set a check to false in basalt.toml and restart:
anticheat_fly = falseanticheat_scaffold = falseWith a check off, nothing is counted or corrected for that case. The kick limits and wear-off rates are fixed and cannot be changed in the file.
Related settings:
| Setting | Default | What it does |
|---|---|---|
max_movement_packets_per_second |
40 |
Vehicle moves a riding player may send in a second. More are dropped. |
skin_change_cooldown |
30 |
Seconds between skin changes in game. |
botnet_detection |
true |
Watches for several connections flooding packets at once. When three or more connections each send 300 or more packets a second, and they also started flooding together, mostly send the same packet, share a subnet or are newly connected, they are disconnected and their addresses are turned away for a minute. |
The packet rate limits in Configuration also protect against flooding.
Known false positives
Section titled “Known false positives”The checks are written so ordinary play never counts, but a few edge cases are worth knowing:
- Fly. Movement Basalt did not cause itself, such as a piston push, has no grace period.
- Criticals. Stepping up a block edge and hitting while dropping back can lose that one critical and count once.
- Reach. The eye position is taken from the last input, so a click right after a fast move is judged from one tick earlier.
- Proxy. If a genuine client is ever disconnected with “Proxy Detected”, turn
anticheat_proxyoff.
Letting a plugin decide
Section titled “Letting a plugin decide”Just before a check kicks, Basalt fires the playerViolation event. A plugin that cancels it keeps the player online and resets the count, which lets you log, warn, or apply your own punishment instead.
import { world } from "@minecraft/server";
world.beforeEvents.playerViolation.subscribe((event) => { console.warn(`${event.player.name} tripped ${event.check}: ${event.detail}`); if (event.check === "scaffold") event.cancel = true;});See Events for how before events work.