FishSentry — Documentation
Installation
- Download FishSentry-1.0.0.jar from the resource page.
- Drop it into your server's plugins/ folder.
- Start the server once to generate plugins/FishSentry/config.yml.
- Edit the config (see below), then either restart or run /reload confirm.
Requirements
- Server: Paper 1.21.x (Spigot may work but is untested)
- Java: 21+
Configuration
The full annotated config lives at
plugins/FishSentry/config.yml. Defaults are sensible for a typical survival server.
Code (YAML):
thresholds
:
# If a player's reaction-time STD over the last 20 catches drops
# below this (ms), their timing is suspiciously consistent.
# Humans typically sit in the 80-300 range.
max-std
: 150.0
# Minimum acceptable time (ms) between a successful catch and the
# next cast. Macros often instantly recast within <250 ms.
min-recast-delay
: 300
# Squared distance (blocks^2) between successive bobber casts.
# If consecutive casts land inside this radius of the previous,
# it counts as clustering. Squared to avoid sqrt() in the hot path.
min-bobber-distance-sq
: 0.25
points:
std-violation
: 3
clustering-violation
: 2
recast-violation
: 2
punishment
:
# Total points needed to trigger the punishment command.
max-points
: 15
# Console command run when the threshold is crossed.
# {player} is replaced with the offender's name.
command
:
"kick {player} Suspected auto-fishing."
webhook:
enabled
: true
url
:
"https://discord.com/api/webhooks/..."
Tuning Tips
- More forgiving on legit players: lower max-std toward 100, raise max-points toward 20.
- Stricter: raise max-std toward 200, lower max-points toward 10.
- Tempban instead of kick: command: "tempban {player} 1d Suspected auto-fishing." (requires LiteBans / EssentialsX).
- Staff alert only, no punishment: point command at a broadcast/tellraw to your staff and crank max-points very high.
How Detection Works
FishSentry hooks
PlayerFishEvent at
MONITOR priority and branches on state:
- FISHING (cast): recast-delay check, bobber-clustering check, record bobber position.
- BITE: stamp the bite time.
- CAUGHT_FISH / CAUGHT_ENTITY: compute reaction time (now - lastBite) and append to the rolling buffer. Run STD check if the buffer is full.
- FAILED_ATTEMPT: reset the consecutive-flawless counter.
When
warningPoints >= max-points, the plugin:
- Builds a snapshot (session length, catches, reaction stats, per-check violation counts, the resolved command).
- Resets the player's points and per-check counters.
- Dispatches the configured punishment command from the console on the main thread.
- Fires a Discord webhook (async) with a rich embed of the snapshot.
Why Standard Deviation?
A human's reaction has natural jitter — distractions, ping, where they were looking on the screen. A macro that fires at a fixed offset after
BITE produces an STD close to zero. We require 20 samples before scoring it, so single-catch drive-by sessions are immune.
Discord Webhook
Set
webhook.enabled: true and paste your webhook URL into
webhook.url. On every punishment, FishSentry sends an embed containing:
- Player name + UUID
- Points scored / threshold
- Session duration
- Total catches and catches-per-minute
- Reaction-time mean and standard deviation
- Per-check violation breakdown (STD / clustering / recast)
- Consecutive flawless catch streak
- The exact command that was executed
Webhook delivery is fully async — it never blocks the main thread.
Permissions & Commands
FishSentry is currently
fully passive — no commands, no permissions. Detection runs on every fishing event; punishment is delivered through the console command you configure.
Compatibility
- Built and tested against Paper 1.21.4.
- Should work on any Paper 1.21.x build.
- Uses only stable Bukkit/Paper API — no NMS, no reflection.
- Plays nicely with anti-cheats, EssentialsX, LiteBans, and other punishment plugins.
Performance
- All state is per-player and held in memory. No I/O on the event path.
- Bobber distance check uses squared distance — no Math.sqrt per cast.
- STD is recomputed only on CAUGHT, over a fixed-size 20-sample buffer.
- Webhook posts run on Bukkit's async scheduler.
- Per-player state is removed on PlayerQuitEvent.
Typical overhead is a few microseconds per fishing event.
Support & Custom Development
Found a bug, want a feature, or need a custom Minecraft plugin built from scratch?
Discord:
rustycmd
I take on custom MC plugin development jobs — DM me on Discord.