[1] There's a report system now. Players type /report <player> and a menu pops up. They pick a Type, pick a Reason, drop in some Proof, and hit Submit. The head up top shows who they're reporting so they know they grabbed the right person. It's all clickable, nobody has to remember any syntax.
[2] Type and Reason both open their own little menu with preset options you set up. Don't see the one you want? There's a Custom button that closes the menu and lets you type your own answer in chat. Proof works the same way, you click it and type a link or a quick description. Type cancel any time to back out.
[3] Staff get /reports view to see everything that's come in. Every report shows the reported player's head, who reported them, the type, the reason and when it happened. Click one to open the full report. To delete one, Shift-Right-Click it twice (once to arm it, once to confirm) so nobody nukes a report by fat-fingering a click.
[4] /reports view <player> pulls up every report tied to that player, both the ones they made and the ones made about them, active or not. Handy when someone's a repeat problem or a serial false-reporter.
[5] /reports view non-active shows the reports that have been deleted or have aged out, and /reports view all shows the whole pile, active and not. So nothing is ever really gone, you can always go back and look.
[6] Reports remember who closed them. Open a non-active one and it tells you which staff member dealt with it.
[7] There's a cooldown so one angry player can't spam ten reports in a row. Set it to whatever you want in seconds, or 0 to turn it off. Staff with the bypass permission skip the wait.
[8] Reports can be set to expire on their own. Leave a time like 14d and anything older quietly moves into the non-active list. Set it to permanent if you'd rather keep them forever.
[9] You can hook reports up to Discord. Drop a webhook url in reports.yml and every new report gets posted to that channel with all the details. Put a role ping in there too if you want your staff team buzzed the moment something comes in. Off by default until you fill in the url.
[10] Your staff also get pinged in-game the second a report lands, as long as they have the notify permission. You can turn that off or change the wording.
[11] When you open a report there's a Punish button right there that drops you into the normal /punish menu for the reported player, so you can read a report and deal with it without typing their name out again. Only shows if you can punish, and it still respects all your usual punish permissions.
[12] There's also a Teleport button in the report. Left-click and you're standing next to them. Right-click and you go into vanish first so they don't see you coming, which is great for catching someone in the act. It just runs your vanish command, so set vanish-command in reports.yml to whatever your vanish plugin uses and it'll work. The right-click needs the vanish permission.
[13] The reporter now hears back. When you close a report, whoever filed it gets a message saying what happened, either the player got punished and what they got, or nothing was done this time. If they're offline when you close it they get the message the next time they log in, so reports don't just vanish into the void for the person who took the time to make one.
[14] Punishing a player auto-closes the open reports on them. So if five people reported the same cheater and you ban them, all five reports close on their own and all five reporters get told the player was dealt with. You can turn that off in reports.yml if you'd rather close them by hand.
[15] New /alts <player> command (also /alt or /ipscan). It scans everyone who's logged in from that player's IP and lists each account with a tag, [ONLINE] or [OFFLINE], plus [BANNED] if that account is banned and [IP-BANNED] if the whole IP is. Quick way to spot somebody's alts. Works on offline players too. The whole readout, badges and all, lives in messages.yml.
[16] On top of that, staff get a heads-up when someone joins from an IP another account has used, even if nobody on it is banned. The old alert only fired for ban evasion (a banned account on the IP). This one's broader so you catch alts early. Needs the alts notify permission, and you can shut it off in config.yml if your players share IPs a lot.
[17] All the report and alt stuff is yours to change. The new configs/reports.yml holds every menu, the preset Type and Reason lists, the cooldown, the expiry, the webhook, the teleport and vanish settings and all the messages. The alt scan text sits in messages.yml and the IP alert toggle in config.yml. Everything writes itself out on first start and updates itself on later versions while keeping whatever you changed.
[18] There's a web dashboard. It's a clean, self-hosted panel where your staff manage punishments from a browser. They log in with a one-time token from /dashboard in game, no account or password to set up. Host it yourself, or serve it straight from the plugin: point api.dashboard-path at the built dashboard folder in api.yml, open the API address in a browser, and it just works, with no cross-origin setup and no URL to type in.
[19] Player heads show up all over the dashboard and they always look right, including on offline-mode servers. A coloured tile with the player's initial shows instantly, then the real head fades in over it.
[20] The dashboard has a full Reports page. See active reports, deleted and expired ones, or everything at once, search by player, and open any report to read the proof and see who handled it. With the right permission you can close a report right from there. Search a player on the Players page and you get their whole record, the same as /check in game.
[21] Dashboard access runs on groups you set in api.yml. Two come ready: Moderator (view, punish, revoke, see reports) which everyone gets by default, and Admin which gets everything. Anyone with justbans.command.admin in game is always an Admin. Each staff member only sees and can do what their group allows.
[22] Admins get a Settings panel to build their own groups, tick exactly which permissions each one has, and assign staff to them, all from the dashboard without touching a config file. Moderators never see any of it.
[23] You can edit punishments from the dashboard, not just revoke them. Open Punishments, hit the edit pencil on any ban, mute or warn, and change its reason or its length right there. Editing a mute's length takes effect immediately for anyone who's online.
[24] Players hear about it when their punishment changes. Edit someone's ban or mute and they get a message saying it was updated and by whom, right away if they're online or the next time they join if they're offline. Word it however you like, or turn it off entirely, in messages.yml.
[25] Player heads on the dashboard are extra reliable now. They try a few head-render services in turn, so if one is blocked or down the next one fills in, and you still get the coloured initial tile if none of them answer.
[26] Works on Paper 1.21.11, 26.1.x, Folia, Spigot and BungeeCord/Velocity, same as always. The teleport uses Paper's async teleport so it's safe on Folia across worlds.
[1] Your backends connect to MySQL now. The plugin was trying to create its tables with a line MySQL doesn't support, so the whole setup crashed and the punishments table never got made. That's why every join said "table doesn't exist." Fixed.
[2] There's a full punishment menu now. Type /punish <player> and you click what you want (ban, temp-ban, IP-ban, mute, IP-mute, shadow-mute, warn or kick), then pick a reason and a length and confirm. The head up top tells you if they're already banned or muted, their warning count and how many alts they have. There's a silent toggle, an IP toggle, and a button to flip a ban into a mute without starting over. It does the same thing the commands do, just clickable.
[3] Run /punish on its own and it shows everyone who's online. Click a head to punish them instead of typing the name.
[4] New /justbans data screen. It's the full log of every punishment on the server: who did it, the exact time, the reason, the length, whether it's still active, and if it was lifted, which staff member lifted it. Search by a player's name or a staff name, click any entry for the details, and a Back button puts you right back on the page you were on. Admins only.
[5] /editban <player> opens a list of that player's active bans and mutes. Click one to change its reason or its length. /editban <id> <reason|duration> <value> still works if you'd rather type it, and it's the only way from console.
[6] You can jump straight from someone's /check history to punishing them. There's a Punish button in the bottom-right. It only shows if you have permission.
[7] "Custom reason" and "custom duration" ask you to type it in chat now instead of opening an anvil. The anvil never worked on 1.21.11 so that button used to look dead. Now it just closes the menu, you type it, done. Type cancel to back out.
[8] /unwarn works now. Warnings were getting saved as already-expired the instant you gave them, so /unwarn could never find one and told you "this player is not muted," which made no sense for a warning. Warnings now last as long as warnings.expire_after says (30 days by default) and /unwarn has its own message. One thing: warnings from before this update are already dead, so give a fresh one to test.
[9] IP bans stick across the network now. They were tied to the banned player's current IP, so the second that player logged in from somewhere else, the IP you banned quietly stopped being blocked and their alts could walk right back in. Now it sticks to the IP you actually banned, on the proxy and the backends both, so that address stays blocked for everyone on it.
[10] You can punish offline players from any server on the network now. Banning, muting or warning someone who's in the database but never joined the exact server you're standing on used to fail with a "not found" message, even though they showed up in tab-complete. It now looks them up in the database (and Mojang as a last resort), so it works no matter which backend you run it from.
[11] You can edit the network ban screen now. The "You are banned from this network!" message the proxy shows was locked in the code before. It's in messages.yml as network_ban_screen now, and on Velocity it uses MiniMessage like everything else (colors, gradients, hex). Edit it in your proxy's plugins/justbans/messages.yml. On BungeeCord it falls back to plain colors since Bungee has no MiniMessage.
[12] No more invisible item stuck to your cursor after jumping between menus, like going from History to Punish.
[13] Warns and kicks don't tack "(N/A)" onto the end of the confirmation anymore. There's no duration on them, so it just leaves it off.
[14] Player heads don't show that odd "Dynamic" line under the name anymore. (If you still see "minecraftlayer_head" or "X component(s)" lines, those are your own client's advanced tooltips. Hit F3 + H to turn them off. Players never see them.)
[15] The menus look a lot nicer, with fresh icons and shorter, cleaner text. Everything in them (titles, slots, icons, wording) lives in the new configs/gui.yml, and you can switch off any punishment you don't want showing in the menu right there.
[16] /justbans help got a cleaner look and lists every command now.
[17] Your config updates itself on the first start and keeps anything you changed. To get the new look on a setup you already have, delete configs/gui.yml and configs/messages.yml and let them regenerate.
[18] Works on Paper 1.21.11, 26.1.x, Folia, Spigot and BungeeCord/Velocity.
[1] Added BungeeCord proxy module, enforces bans at the network login stage, preventing banned players from being redirected to the lobby
[2] Added Velocity proxy module with the same proxy-level enforcement
[3] Added plugin message relay on both proxy modules for cross-server punishment sync
[4] Added player head thumbnail in Discord webhook embeds (Crafatar integration, configurable per target)
[5] Added shadow mute staff notification (previously missing, caused "Missing message: shadow_mute_notification")
[6] Added full tab completion across all commands, offline players, network-wide players, and preset filtering by type and permission
[7] Added cross-server player name cache with real-time updates via plugin messaging
[8] Added configurable footer icon for webhook embeds
[9] Added webhook assignments for all punishment types including shadow mute, IP ban revocations, and IP mute revocations
[10] Fixed obfuscation breaking shaded libraries at runtime
[11] Fixed webhook embed color for revocations (was neon green, now matches documented value)
[12] Fixed webhook IP address detection using string matching instead of proper enum comparison
[13] Migrated license and version check endpoints to api.deltura.net
[1] Fixed critical race condition in ban evasion detection
[2] Added IP-based ban checking on player join
[3] Enhanced Bedrock player enforcement and IP tracking
[4] Fixed players bypassing bans while evasion checks were running
[5] Added sequential ban checking: UUID -> IP -> Evasion (all awaited)
[6] Improved async ban enforcement to prevent chat before kick
[7] Added getActiveIpBan(ip) method for IP-based ban detection
[8] Fixed Custom Values not appearing correctly
[1] Added offline player support
[2] Added Bedrock/Floodgate support
[3] Fixed shadow mutes not working on legacy AsyncPlayerChatEvent
[4] Fixed staff unable to punish players with equal rank (default vs default)
[5] Fixed config files resetting after reload due to YAML syntax errors
[6] Optimized MySQL with server-side prepared statements and smart caching
[7] Removed all blocking operations, fully non-blocking punishment system
[1] Implemented H2 to MySQL migration tool (/justbans migrate-to-mysql)
[2] Major Webhook Overhaul:
- Multi-target support (e.g., game-mode specific webhooks)
- Full template customization (title, color, footer)
- Source server identification ({server} placeholder)
[3] Fixed command blocking bypass for muted players (synchronous cache check)
[4 Full compatibility with Paper and Folia (Thread-safe execution)
[5] Performance improvements in database and cache handling
[1] Fixed cross-server unban issue
[2] Implemented/punish <player> <preset> [-s]command for unified punishment via presets
[3] Added network sync for unpunishments
[4] Fixed ban override logic (existing punishments are now deactivated instead of blocking)
