Skip to content

Repository files navigation

SimpleBoxer

Virtual sparring players for testing combat plugins. Spawn a bot that is a real player to your server — real player-list entry, real inventory, real movement packets, real knockback — then tune its ping, aim, click speed, reach, and movement to spar against. Built for Paper 1.17.1 → 26.x.

MinecraftPlatformRelease


Why SimpleBoxer?

Testing a combat plugin (knockback tuning, anti-cheat, OldCombatMechanics modesets, Mental profiles) usually means rounding up real people. SimpleBoxer gives you opponents on demand.

A boxer is indistinguishable from a real player to the server. Whatever shapes combat on your server shapes the boxer identically, because the boxer rides the same wire:

  • Knockback arrives as the same velocity packet a real client receives, and is integrated through the vanilla client's motion math — so a boxer flies back exactly like a player with the same ping would.
  • Movement, sprinting, attacks, and swings leave as genuine player packets — same server validation, same Bukkit events (PlayerMoveEvent, PlayerToggleSprintEvent, …).
  • Vanilla commands (/tp, /effect, /give) and other plugins target boxers like any player. They're hidden from the tab list but stay tab-completable.

Use case: arena-style flat/simple terrain. Boxers sprint, strafe, and jump single-block steps — they don't path through mazes.


Features

  • 🖥️ GUI-first — run /boxer and everything (spawn, tune, target, kit, presets, config) is point-and-click. No command syntax to memorise; the command tree stays for console and scripts.
  • 🎒 Virtual inventories — kit a boxer out in armor and weapons, including custom-enchanted gear (StarEnchants and friends). It's a real player, so vanilla and custom enchant effects apply exactly as they would to a person wearing the same items — armor protects, weapons proc on hit, passive armor enchants tick.
  • 🥊 Real-player bots — no NPC shortcuts; the server sees a ServerPlayer.
  • 🎚️ Difficulty ladderdummyeasymediumhardexpertaimbot, each a full behaviour bundle.
  • 🛰️ Simulated ping — symmetric RTT that delays both perception and action, like a real laggy client.
  • 🎯 Spring-damper aim — presets locked/sharp/smooth/sloppy, or tune stiffness, damping, and max turn speed by hand.
  • 🖱️ Configurable clicking — CPS with jitter, reach and aim-cone gating.
  • 🏃 Movement stylesrush, strafe-circle, strafe-weave, stand, with w-tap rhythm and stop-distance rings.
  • ⚙️ Live tuning — change any knob at runtime with /boxer set.
  • 🧩 Skins & targets — wear any account's skin; pre-bind a follow target.
  • 🛡️ Tireless fixtures — invincible (full hit + restore) and well-fed by default, so a test never ends because the bot starved or died.

Requirements

ServerPaper (or a Paper fork) 1.17.1 through 26.x
Java17+ for MC 1.17–1.20.4 · 21+ for MC 1.20.5 and newer

SimpleBoxer reaches into server internals (NMS) to make boxers real players. It targets Paper; Spigot/CraftBukkit are untested. If your exact version is unsupported the plugin disables itself cleanly and logs why — it never half-loads.


Installation

  1. Download the latest SimpleBoxer-x.y.z.jar from the Releases page.
  2. Drop it into your server's plugins/ folder.
  3. Restart the server (a reload won't load a new plugin cleanly).
  4. Verify — you should see SimpleBoxer x.y.z enabled in the console, and a plugins/SimpleBoxer/config.yml will be created.
  5. Spawn one in-game:
    /boxer spawn Rival hard target:YourName
    

That's it. By default only operators can use the commands (see Permissions).


Quick start

Just run:

/boxer

That opens the menu — the front door for everything. From there you can:

  • Spawn a Boxer — name it, pick a difficulty, choose a skin and target, and build its starting kit, then drop it at your feet.
  • Manage Boxers — one head per live boxer; click to retune, re-kit, set a target, pause/resume, teleport, or remove. Bulk pause/resume/remove too.
  • Presets & Defaults — edit the spawn defaults and the difficulty presets, or create your own — all saved to config.yml.
  • Plugin Settings — tab-list visibility and a config reload.

Alias: /sb works anywhere /boxer does.

Kitting a boxer (virtual inventory)

Open a boxer's Kit screen and drop items into the six equipment slots — four armor pieces and both hands. It never touches your real items: cursor-click a slot to equip a copy (paint as many boxers as you like from one item in creative), shift-click your own gear to add it, or hit Copy my gear to mirror what you're wearing. Because the boxer is a real player, custom-enchanted gear behaves exactly as it would on a person — armor protects and procs, weapons activate on hit, and passive armor enchants tick. The kit survives death and respawn.

Prefer commands? They still work

The full command tree remains for console and scripting:

/boxer spawn Bot expert skin:Notch target:Steve
/boxer target Bot Steve # sic an existing boxer onto a player
/boxer set Bot ping 150 # tune anything, live
/boxer pause Bot # freeze its brain (it still takes hits)
/boxer remove all # clean up

Commands

All commands are under /boxer (alias /sb). Bare /boxer opens the menu — the commands below exist for console and scripting, but you never need them.

CommandDescription
/boxer · /boxer menuOpen the management GUI (players only).
/boxer spawn <name> [preset] [skin:<player>] [target:<player>] [at <x> <y> <z>]Spawn a boxer. With no preset it uses your defaults. at is required from console.
/boxer remove <name|all>Remove one boxer, or every boxer.
/boxer listList live boxers with their target, ping, and CPS.
/boxer info <name>Full settings dump for one boxer.
/boxer target <name> <player|none>Set or clear a boxer's follow/attack target.
/boxer pause <name|all>Freeze a boxer's brain (it still receives knockback).
/boxer resume <name|all>Un-freeze.
/boxer set <name> <key> <value>Tune one setting at runtime (see below).
/boxer reloadRe-read config.yml.

Tunable keys (/boxer set)

KeyValueExample
pingwhole number of ms (0–2000)/boxer set Bot ping 150
cpsclicks per second (0–50; 0 = never attacks)/boxer set Bot cps 12
reachblocks (0.5–6)/boxer set Bot reach 3.2
aimlocked / sharp / smooth / sloppy/boxer set Bot aim smooth
wtaptrue / false/boxer set Bot wtap true
movementrush / strafe-circle / strafe-weave / stand/boxer set Bot movement strafe-circle
presetany preset name/boxer set Bot preset expert
invincibletrue / false/boxer set Bot invincible false

Invalid input is answered in plain language — e.g. set Bot ping abc replies ping expects a whole number, not 'abc'. rather than throwing.


Difficulty presets

Each preset bundles ping, CPS, aim, reach discipline, w-tap, and movement into a named tier. Every component stays individually overridable at spawn or with /boxer set.

PresetFeelPingCPSAim
dummyStands still, never attacks — a punching bag00smooth
easyHigh ping, slow sloppy clicks, walks1204sloppy
mediumAn ordinary player607smooth
hardA practiced PvPer, disciplined w-taps3510sharp
expertTournament-grade, circles its target1513tight
aimbotThe calibrator: zero ping, locked aim016locked

You can also define your own presets in config.yml as sparse overlays — an entry there with a built-in's name overrides it.


Permissions

Everything defaults to operators only. Grant these nodes to delegate.

NodeGrantsDefault
simpleboxer.guiOpen and use the in-game menu (the full toolset on one screen)op
simpleboxer.command.useRun /boxer, plus help, list, infoop
simpleboxer.command.spawnspawn and removeop
simpleboxer.command.controltarget, pause, resumeop
simpleboxer.command.tunesetop
simpleboxer.command.reloadreloadop
simpleboxer.*All of the aboveop

Configuration

A documented config.yml is written to plugins/SimpleBoxer/ on first start. The two top-level blocks are defaults (applied to any spawn that names no preset, and the base every preset overlays) and presets (your own named overlays). Every key inherits a sensible default when omitted, and a malformed value warns in the console and keeps the inherited value — a typo can never break a spawn.

# Keep boxers out of the tab list (still tab-completable in commands).hide-from-tab: truedefaults:
ping-ms: 0# simulated RTT, 0–2000 (split: half perception, half action)cps: 8.0# clicks per second, 0–50 (0 = never attacks)click-jitter: 0.3# per-click interval wobble, 0–0.9aim:
preset: sharp # locked / sharp / smooth / sloppy# stiffness: 0.55 # optional granular overrides on top of the preset# damping: 0.30# max-velocity: 60.0reach: 3.0# attack range in blocks, 0.5–6aim-tolerance-degrees: 10.0# a click only attacks within this conew-tap:
enabled: falsedelay-ticks: 1# ticks after a hit before forward releases (0–20)release-ticks: 2# ticks forward stays released (1–20)movement:
style: rush # rush / strafe-circle / strafe-weave / standstop-distance: 0.0# 0 = hold W through the target (true rusher)sprint: trueinvincible: true # take the full hit, then restore healthfeed-hunger: true # pin hunger full so sprint stays legal# Your own presets (sparse overlays over `defaults`):presets:
# laggy-spammer:# ping-ms: 180# cps: 14# aim:# preset: smooth

After editing, run /boxer reload.


Developer API

Other plugins can spawn and control boxers. The api module exposes BoxerService, obtainable from Bukkit's ServicesManager:

BoxerServiceboxers = Bukkit.getServicesManager().load(BoxerService.class);
boxers.spawn(newBoxerSpawnRequest(
"Rival",
player.getLocation(),
DifficultyPresets.HARD,
"Notch", // skin owner, or nullplayer.getName() // target, or null
)).thenAccept(boxer -> boxer.setTarget(player));

BoxerSpawnEvent and BoxerRemoveEvent fire on the Bukkit event bus.

Boxers carry a virtual inventory you can read and set — kit one out (custom enchants included) and it behaves like a player wearing the same gear:

boxer.equip(newLoadout(
helmet, chestplate, leggings, boots, // any ItemStacks, or nullmainHandWeapon, offHandShield));
Loadoutworn = boxer.loadout(); // immutable, defensively copied

A starting kit can also ride the spawn request — new BoxerSpawnRequest(name, loc, settings, skin, target, loadout) — so a boxer spawns already dressed.


Building from source

Requires a JDK 21+ (the build provisions a Java 25 toolchain automatically).

git clone https://github.com/owengregson/SimpleBoxer.git
cd SimpleBoxer
./gradlew build # compiles + runs unit tests; jar in core/build/libs/

The shaded plugin jar is core/build/libs/SimpleBoxer-<version>.jar.

Tests

./gradlew build # unit tests (physics, aim, latency, settings)
./gradlew integrationTest # boots real Paper servers (floor + ceiling) and runs the in-server suite
./gradlew integrationTestMatrix # every version listed in gradle.properties

Integration results land in run/<version>/plugins/SimpleBoxerTester/test-results.txt.

See ARCHITECTURE.md for the module map, the captured-connection design, threading rules, and the honest boundaries (in-process packets are invisible to packet-sniffing plugins; Folia and pathfinding are deferred).


Honest boundaries

  • In-process boxers have no socket, so their outbound packets don't traverse the netty pipeline — ProtocolLib/PacketEvents listeners won't see boxer traffic. The interesting direction (a real player attacking a boxer) works fully, because the attacker's own connection carries the packets.
  • Folia isn't supported yet (the scheduling seam is ready; placement and cross-region brains aren't).
  • Boxers are ephemeral — they're never written to player data and are despawned cleanly on shutdown.

Credits

Built by owengregson to pair with Mental and OldCombatMechanics. Issues and pull requests welcome on GitHub.

Releases

Packages

Contributors

Languages