Skip to content
BasaltSoftware
Bedrock 1.26.60

Site colour

Discord
Esc

    ↑↓ moveEnter openEsc close

    Keyboard shortcuts
    Ctrl K
    Search the whole site, from any page
    /
    Jump to the sidebar search, or search the whole site where there isn't one
    Enter
    Open the top search result
    Esc
    Clear the search, or close this panel
    ?
    Show these shortcuts
    Docs

    Anti-cheat

    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.

    A check never speaks in chat and never punishes on one event. It works in three steps:

    1. 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.
    2. 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.
    3. 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"
    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 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.

    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.

    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.

    No honest client attacks its own player. The hit is dropped with no damage and no knockback.

    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.

    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.

    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.

    Set a check to false in basalt.toml and restart:

    anticheat_fly = false
    anticheat_scaffold = false

    With 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.

    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_proxy off.

    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.