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.
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.
- π₯οΈ GUI-first β run
/boxerand 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 ladder β
dummyβeasyβmediumβhardβexpertβaimbot, 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 styles β
rush,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.
| Server | Paper (or a Paper fork) 1.17.1 through 26.x |
| Java | 17+ 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.
- Download the latest
SimpleBoxer-x.y.z.jarfrom the Releases page. - Drop it into your server's
plugins/folder. - Restart the server (a reload won't load a new plugin cleanly).
- Verify β you should see
SimpleBoxer x.y.z enabledin the console, and aplugins/SimpleBoxer/config.ymlwill be created. - Spawn one in-game:
/boxer spawn Rival hard target:YourName
That's it. By default only operators can use the commands (see Permissions).
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.
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.
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
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.
| Command | Description |
|---|---|
/boxer Β· /boxer menu |
Open 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 list |
List 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 reload |
Re-read config.yml. |
| Key | Value | Example |
|---|---|---|
ping |
whole number of ms (0β2000) | /boxer set Bot ping 150 |
cps |
clicks per second (0β50; 0 = never attacks) | /boxer set Bot cps 12 |
reach |
blocks (0.5β6) | /boxer set Bot reach 3.2 |
aim |
locked / sharp / smooth / sloppy |
/boxer set Bot aim smooth |
wtap |
true / false |
/boxer set Bot wtap true |
movement |
rush / strafe-circle / strafe-weave / stand |
/boxer set Bot movement strafe-circle |
preset |
any preset name | /boxer set Bot preset expert |
invincible |
true / 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.
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.
| Preset | Feel | Ping | CPS | Aim |
|---|---|---|---|---|
dummy |
Stands still, never attacks β a punching bag | 0 | 0 | smooth |
easy |
High ping, slow sloppy clicks, walks | 120 | 4 | sloppy |
medium |
An ordinary player | 60 | 7 | smooth |
hard |
A practiced PvPer, disciplined w-taps | 35 | 10 | sharp |
expert |
Tournament-grade, circles its target | 15 | 13 | tight |
aimbot |
The calibrator: zero ping, locked aim | 0 | 16 | locked |
You can also define your own presets in config.yml as sparse overlays β an
entry there with a built-in's name overrides it.
Everything defaults to operators only. Grant these nodes to delegate.
| Node | Grants | Default |
|---|---|---|
simpleboxer.gui |
Open and use the in-game menu (the full toolset on one screen) | op |
simpleboxer.command.use |
Run /boxer, plus help, list, info |
op |
simpleboxer.command.spawn |
spawn and remove |
op |
simpleboxer.command.control |
target, pause, resume |
op |
simpleboxer.command.tune |
set |
op |
simpleboxer.command.reload |
reload |
op |
simpleboxer.* |
All of the above | op |
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: true
defaults:
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.9
aim:
preset: sharp # locked / sharp / smooth / sloppy
# stiffness: 0.55 # optional granular overrides on top of the preset
# damping: 0.30
# max-velocity: 60.0
reach: 3.0 # attack range in blocks, 0.5β6
aim-tolerance-degrees: 10.0 # a click only attacks within this cone
w-tap:
enabled: false
delay-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 / stand
stop-distance: 0.0 # 0 = hold W through the target (true rusher)
sprint: true
invincible: true # take the full hit, then restore health
feed-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: smoothAfter editing, run /boxer reload.
Other plugins can spawn and control boxers. The api module exposes
BoxerService, obtainable from Bukkit's ServicesManager:
BoxerService boxers = Bukkit.getServicesManager().load(BoxerService.class);
boxers.spawn(new BoxerSpawnRequest(
"Rival",
player.getLocation(),
DifficultyPresets.HARD,
"Notch", // skin owner, or null
player.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(new Loadout(
helmet, chestplate, leggings, boots, // any ItemStacks, or null
mainHandWeapon, offHandShield));
Loadout worn = boxer.loadout(); // immutable, defensively copiedA starting kit can also ride the spawn request β new BoxerSpawnRequest(name, loc, settings, skin, target, loadout) β so a boxer spawns already dressed.
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.
./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.propertiesIntegration 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).
- 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.
Built by owengregson to pair with Mental and OldCombatMechanics. Issues and pull requests welcome on GitHub.