
BS-BanHammer
The most feature-rich ban hammer for Paper & Folia 1.21.x - Strike players with lightning effects while maintaining a complete punishment database, Discord integration, and preset system.
- Загрузки
- 765
- Подписчики
- 2
- Обновлён
- 3 июня 2026 г.
- Лицензия
- MIT
Опубликован 13 октября 2025 г.
⚡ BanHammer 4.0.0 - Enhanced Edition
The most feature-rich ban hammer plugin for Paper & Folia 26.1.x servers
Transform your moderation workflow with a dramatic ban hammer that strikes players with lightning, particles, and sound effects - all while maintaining a complete punishment database and Discord integration.
🎨 Resource Pack
The BanHammer texture pack is available as a separate download:
Staff members will see a clickable download hint on join (configurable in config.yml).
🎯 What Makes BS-BanHammer Special?
🔨 Dual-Action Preset System
Ban Presets (Shift + Right-Click):
- Cycle through unlimited predefined ban types on-the-fly
- Each preset has custom duration, reason, IP-ban option, and sound
- Actionbar feedback shows active preset
- No commands needed - just shift-click and ban!
Kick/Jail Presets (Shift + Left-Click):
- Mix instant kicks and timed jails in one preset list
- Left-click players to execute with active preset
- Perfect for quick moderation without typing commands
- Separate preset tracking from ban presets
Example Workflow:
1. Shift + Right-Click → Switch to "7 Day Ban" preset
2. Right-Click on griefer → Instantly banned for 7 days with lightning!
3. Shift + Left-Click → Switch to "30 Min Jail" preset
4. Left-Click on spammer → Jailed for 30 minutes
⚡ Dramatic Visual Effects
Every punishment comes with spectacular effects:
- Lightning strikes at player location
- Thunder & explosion sounds for maximum impact
- Particle effects (critical hits & smoke)
- Optional knockback for extra drama
- Fully configurable per preset
📊 Complete Database System
SQLite or MySQL - Your Choice:
- SQLite for single-server setups (zero configuration)
- MySQL for multi-server networks (shared ban database)
- Complete punishment history tracking
- Staff statistics and leaderboards
- Automatic cleanup of expired punishments
- GDPR-compliant IP anonymization
🔄 Auto-Unban Scheduler
Set it and forget it:
- Automatic unbanning when temporary punishments expire
- Works for temp-bans, temp-mutes, and jail sentences
- Configurable check intervals (default: 60 seconds)
- Discord notifications on auto-unbans
- Event system for external plugins
🎭 Extended Punishment Types
Beyond Bans:
- Mute System - Blocks chat and commands (permanent or temporary)
- Jail System - Locks players in place with Essentials integration
- Warning System - Auto-ban after X warnings (configurable)
- IP Bans - Network-wide bans with anonymization options
- Appeals - Let players submit unban requests
🌐 Essentials Jail Integration
Smart Integration:
- Soft dependency - no hard requirement
- Automatically uses Essentials jails if available
- Falls back to built-in jail system
- Works with existing Essentials jail configurations
- Reflection-based - no version conflicts
💬 Discord Webhook Integration
Real-Time Moderation Logs:
- Color-coded embeds for different actions
- Rich information: player, staff, reason, duration
- Works independently of database
- Configurable per event type (bans, kicks, mutes, unbans, appeals)
- Automatic notifications on punishment expiry
🌍 Multi-Language Support
Fully translated:
- 🇩🇪 German - Vollständig übersetzt
- 🇬🇧 English - Fully translated
- All messages configurable in YAML files
- Easy to add custom languages
🔌 Developer-Friendly API
Custom Events:
PlayerPunishEvent // Cancellable, fired before punishment
PlayerPunishedEvent // Fired after successful punishment
PlayerUnpunishedEvent // Fired when punishment removed
PunishmentManager API:
pm.banPlayer(staff, victim, reason, duration, ipBan)
pm.mutePlayer(staff, victim, reason, duration)
pm.jailPlayer(staff, victim, reason, duration)
pm.getHistory(playerUuid, limit)
📈 Statistics & Appeals
Track Everything:
- Staff leaderboards (most bans, kicks, etc.)
- Player punishment history
- Active punishment counts
Appeal System:
- Players can submit appeals via
/appeal <text> - Cooldown system prevents spam
- Staff review with
/bh approve/deny - Discord notifications for new appeals
🚀 Quick Start
- Install the plugin in your
plugins/folder - Start your server (auto-generates config)
- Give yourself the hammer:
/bh give <player> - Download the Resource Pack for the custom texture
- Configure presets in
config.yml(optional) - Use the hammer:
- Shift + Right-Click to switch ban presets
- Right-Click player to ban with active preset
- Shift + Left-Click to switch kick/jail presets
- Left-Click player to kick/jail with active preset
📝 Commands Overview
| Command | Description |
|---|---|
/bh give <player> |
Give the Ban Hammer item |
/bh reload |
Reload config (reinitializes Discord & DB) |
/bh history <player> |
View punishment history |
/bh unban <player> |
Manually unban a player |
/bh stats [player] |
View moderation statistics |
/bh appeals |
View pending appeals |
/mute <player> <duration> |
Mute a player |
/jail <player> <duration> |
Jail a player |
/warn <player> [reason] |
Warn a player |
Full command list in README.md
⚙️ Configuration Highlights
Ban Presets Example:
presets:
warning:
displayName: "Warning Ban"
reason: "First offense"
duration: "1h"
ipBan: false
sound: "BLOCK_NOTE_BLOCK_PLING"
serious:
displayName: "7 Day Ban"
reason: "Serious rule violation"
duration: "7d"
ipBan: false
sound: "BLOCK_NOTE_BLOCK_BASS"
permanent:
displayName: "Permanent Ban"
reason: "Permanently banned"
duration: "permanent"
ipBan: true
sound: "BLOCK_ANVIL_LAND"
Kick/Jail Presets Example:
kickJailPresets:
quick_kick:
displayName: "Quick Kick"
reason: "Kicked from server"
# No duration = instant kick
jail_30m:
displayName: "30 Min Jail"
reason: "Jailed for 30 minutes"
duration: "30m" # Has duration = jail
🔒 Security & Privacy
- GDPR Compliant - IP anonymization with 4 levels
- Permission-based - Granular permission system
- SQL Injection Protected - Prepared statements everywhere
- Bypass Protection - Immune players can't be banned
- Self-Protection - Can't ban yourself
- Cooldown System - Prevents spam abuse
🌟 What's New in 4.0.0?
Paper 26.1.x Support (BREAKING):
- ✨ Targets Paper 26.1.2+ with the new Minecraft versioning
- ✨ Requires Java 25
- ✨ All deprecated APIs modernized (Adventure Components, no more legacy color codes)
- ✨ Smart update checker filters by game version (1.21.x users won't see 4.x updates)
- ✨ Resource pack moved to separate download
Previous Major Features:
- ✨ Folia Support (dual Paper/Folia compatibility)
- ✨ Ban Presets System with preset cycling
- ✨ Kick/Jail Presets System (separate from ban presets)
- ✨ Essentials Jail Integration
- ✨ Modrinth Update Checker with game version filtering
- ✨ Complete translation system (DE/EN)
- ✨ Discord works without database requirement
📦 Requirements
- Server: Paper or Folia 26.1.x or higher
- Java: 25 or higher
- Optional: MySQL Server (for MySQL mode)
- Optional: Essentials Plugin (for enhanced jail system)
Looking for 1.21.x support? Use BanHammer v3.1.1 instead.
📜 License
MIT License - Free for all server types (commercial & non-commercial)
🙏 Credits
- Plugin Development: BoondockSulfur
- Resource Pack: BS-BanHammer Resource Pack
- Libraries: HikariCP, discord-webhooks, Adventure
⭐ If you enjoy BanHammer, please leave a rating! ⭐
Made with ❤️ for the Minecraft community
Ченджлог
4.0.1Релиз26.1.1, 26.1.2, 26.2 · 3 июня 2026 г.
[4.0.1] - 2026-06-03
🐛 Bug Fixes
Jail System
- Fixed jail escape via relogging — jailed players are now re-enforced on join (
JailListener#onJoin→JailManager#restoreJailOnJoin): the enforcement cache is rebuilt on every join (even within the offline-cleanup window) and restoration also works without a database (the periodic cleanup keeps active jails in memory when no DB is configured). Previously the cache was cleared on quit and never restored, so a player could leave jail simply by reconnecting. - Fixed jails not surviving server restarts —
loadJailedPlayers()now runs ininitializeDatabaseDependentComponents()after the (asynchronous) database is ready, instead of duringonEnablewhen it was stillnull. /unjailnow works for offline players — the database record is released even when the target is not online (previously rejected outright).- Fixed jail enforcement being blocked by the plugin's own teleports —
JailListener#onTeleportnow exemptsPLUGIN-cause teleports. Previously the plugin's own "teleport back into jail" (and, on Folia, the initial jailing teleport) was cancelled by the very teleport-prevention handler, so a jailed player could leave the jail radius and never be pulled back. - Temporary jails now auto-release without a database —
JailManagertracks an in-memory expiry as a fallback when no database is configured. With a database theUnbanSchedulerremains the sole authority, so there is no duplicate handling or leaked entry. - Fixed return-location being clobbered on re-jail — the pre-jail location is now saved with
putIfAbsent, so restoring a jail (relog/restart) no longer overwrites the player's real return location with the jail spot.
Essentials Integration
- Essentials is now always preferred when hooked — when Essentials is present, jails are created and managed in Essentials; the built-in jail system is no longer used as a fallback in that case.
- Auto-creates an Essentials jail when none exists — if Essentials is hooked but no jail has been configured, BanHammer registers its configured jail location as an Essentials jail (via
setJail) instead of falling back to the built-in system. An existing, admin-configured Essentials jail is preferred when present. - Cell selection for
/jail— new syntax/jail <player> <duration> [cell] [reason]. The optionalcelltargets a specific Essentials jail; when omitted, the configurable default cell is used. Tab-completion suggests existing cells, and a non-existent cell is rejected with the list of available ones. The hammer and reason-only commands use the default cell. Case-insensitive cell matching. /jailno longer requires a built-in jail location when Essentials is hooked — the location now comes from Essentials.
Configuration
- New
punishmentTypes.jail.useEssentialstoggle — enable/disable the Essentials jail hook from the config (defaulttrue). Whenfalse, BanHammer always uses its built-in jail even if Essentials is installed. Applies on (re)start. - New
punishmentTypes.jail.essentialsDefaultJail(default"1") — the Essentials cell used by the hammer and by/jailwhen no cell is specified.
Punishments / IP Bans
- Fixed IP-ban removal with anonymization enabled —
/unbanno longer attempts to pardon an anonymized IP. The real IP is only pardoned whenprivacy.ipAnonymization: NONE; otherwise a hint to use the vanilla/pardon-ipis logged. Applied to both manual unban and the auto-unban scheduler. - Muted players can no longer bypass chat blocking via namespaced commands (e.g.
/minecraft:msg).
Presets
- Fixed memory leak — per-player preset selections are now cleared on quit.
- Thread-safety — preset lists are immutable snapshots swapped atomically on reload, preventing a possible
ArithmeticException(modulo by zero) if a player cycled presets during/bh reload. - Modernized sound resolution — new registry-based
Soundsutility resolves both namespaced keys (block.note_block.pling) and legacy constants (BLOCK_NOTE_BLOCK_PLING), removing the deprecatedSound.valueOfwarnings.
Stability / Logging
- Removed noisy
INFO-level debug logging from the jail, hammer-use, ban and Discord code paths (nowdebug). ModrinthUpdateCheckershared fields (latestVersion,downloadUrl,changelogUrl,lastCheck) are nowvolatilefor correct visibility between the async check and the main thread.GUIListenerno longer risks aNullPointerExceptionon inventory items without a display name.
3.1.2Релиз1.21.9, 1.21.10, 1.21.11 · 3 июня 2026 г.
[3.1.2] - 2026-06-03
🐛 Bug Fixes
Jail System
- Fixed jail escape via relogging — jailed players are now re-enforced on join (
JailListener#onJoin→JailManager#restoreJailOnJoin): the enforcement cache is rebuilt on every join (even within the offline-cleanup window) and restoration also works without a database (the periodic cleanup keeps active jails in memory when no DB is configured). Previously the cache was cleared on quit and never restored, so a relog escaped the jail. - Fixed jails not surviving server restarts —
loadJailedPlayers()now runs ininitializeDatabaseDependentComponents()after the (asynchronous) database is ready, instead of duringonEnablewhen it was stillnull. /unjailnow works for offline players — the database record is released even when the target is not online.- Fixed jail enforcement being blocked by the plugin's own teleports —
JailListener#onTeleportnow exemptsPLUGIN-cause teleports. Previously the plugin's own "teleport back into jail" (and, on Folia, the initial jailing teleport) was cancelled by the very teleport-prevention handler, so a jailed player could leave the jail radius and never be pulled back. - Temporary jails now auto-release without a database —
JailManagertracks an in-memory expiry as a fallback when no database is configured. With a database theUnbanSchedulerremains the sole authority, so there is no duplicate handling or leaked entry. - Fixed return-location being clobbered on re-jail — the pre-jail location is now saved with
putIfAbsent, so restoring a jail (relog/restart) no longer overwrites the player's real return location with the jail spot.
Essentials Integration
- Essentials is now always preferred when hooked — when Essentials is present, jails are created and managed in Essentials; the built-in jail system is no longer used as a fallback in that case.
- Auto-creates an Essentials jail when none exists — if Essentials is hooked but no jail has been configured, BanHammer registers its configured jail location as an Essentials jail (via
setJail) instead of falling back to the built-in system. An existing, admin-configured Essentials jail is preferred when present. - Cell selection for
/jail— new syntax/jail <player> <duration> [cell] [reason]. The optionalcelltargets a specific Essentials jail; when omitted, the configurable default cell is used. Tab-completion suggests existing cells, and a non-existent cell is rejected with the list of available ones. The hammer and reason-only commands use the default cell. Case-insensitive cell matching. /jailno longer requires a built-in jail location when Essentials is hooked — the location now comes from Essentials.
Messages
- Hammer feedback now renders MiniMessage —
HammerListenerdeserializes MiniMessage tags (e.g.<green>…</green>) instead of sending them literally.
Configuration
- Resource pack is now disabled by default —
resourcePack.enabledships asfalsewith emptyurl/hash(andSettingsdefaults tofalse). The texture pack is no longer bundled/sent by the plugin; host it yourself and opt in explicitly. Previously a freshly generated config re-enabled it with a hardcoded URL. - New
punishmentTypes.jail.useEssentialstoggle — enable/disable the Essentials jail hook from the config (defaulttrue). Whenfalse, BanHammer always uses its built-in jail even if Essentials is installed. Applies on (re)start. - New
punishmentTypes.jail.essentialsDefaultJail(default"1") — the Essentials cell used by the hammer and by/jailwhen no cell is specified.
Punishments / IP Bans
- Fixed IP-ban removal with anonymization enabled —
/unbanno longer attempts to pardon an anonymized IP. The real IP is only pardoned whenprivacy.ipAnonymization: NONE; otherwise a hint to use the vanilla/pardon-ipis logged. Applied to both manual unban and the auto-unban scheduler. - Muted players can no longer bypass chat blocking via namespaced commands (e.g.
/minecraft:msg).
Presets
- Fixed memory leak — per-player preset selections are now cleared on quit.
- Thread-safety — preset lists are immutable snapshots swapped atomically on reload, preventing a possible
ArithmeticException(modulo by zero) if a player cycled presets during/bh reload. - Modernized sound resolution — new registry-based
Soundsutility resolves both namespaced keys (block.note_block.pling) and legacy constants (BLOCK_NOTE_BLOCK_PLING).
Stability / Logging
- Removed noisy
INFO-level debug logging from the jail, hammer-use, ban and Discord code paths (nowdebug). ModrinthUpdateCheckershared fields are nowvolatilefor correct visibility between the async check and the main thread.GUIListenerno longer risks aNullPointerExceptionon inventory items without a display name.
4.0.0Релиз26.1, 26.1.1, 26.1.2 · 3 мая 2026 г.
[4.0.0] - 2026-05-02
🚀 Major Release - Paper 26.1.x Support
Breaking Changes
- Minimum Java version: 25 (up from 21)
- Minimum Minecraft version: 26.1.x (Paper 26.1.2+)
- api-version:
26.1in plugin.yml - Not compatible with 1.21.x servers (use v3.1.1 for 1.21.x)
Modernized API Usage
- Removed all deprecated
kickPlayer(String)calls — now usesPlayer.kick(Component)everywhere - Removed
Bukkit.broadcastMessage(String)— now usesBukkit.broadcast(Component) - Removed legacy
§color codes — Update Checker now uses Adventure Component API with clickable links - Removed deprecated
setResourcePack()fallbacks — now uses AdventureResourcePackRequestAPI exclusively - Removed deprecated
Server.getResourcePack()fallback — usesServer.getServerResourcePack()only - Removed reflection-based ResourcePack sending — direct API calls now that Paper 26.x provides them natively
- Improved
getOfflinePlayer(String)usage — usesgetOfflinePlayerIfCached()first, deprecated call only as last resort - Replaced
Material.CHAIN(removed in 26.1) withMaterial.IRON_BARSin Statistics GUI
Build System Updates
- Updated
maven-compiler-pluginto 3.14.0 (Java 25 support) - Updated
maven-shade-pluginto 3.6.1 (class file version 69 / Java 25 support) - Paper API dependency uses new version format:
[26.1.2.build,)
Resource Pack
- Removed built-in resource pack sending — pack is now a separate download on Modrinth
- Removed
ResourcePackSender,ResourcePackListener, and allresourcePack.*config options - Added clickable join hint for staff (
resourcePackHint.enabled: truein config, disable if not needed)
Metrics
- Added bStats integration (Plugin ID: 31076)
Update Checker
- Game version filter (from v3.1.1) ensures 1.21.x users don't see 4.0.0 updates
3.1.1Релиз1.21.9, 1.21.10, 1.21.11 · 3 мая 2026 г.
[3.1.1] - 2026-05-02
🔧 Improvement
Update Checker - Game Version Filter
- Update notifications are now filtered by Minecraft version — servers only see updates compatible with their game version
- Uses
Bukkit.getMinecraftVersion()to detect the running server version - Passes
game_versionsparameter to Modrinth API to filter releases - Why: Prepares for Paper 26.x support — 1.21.x users won't receive update notifications for incompatible 26.x releases (and vice versa)
3.1.0Релиз1.21.9, 1.21.10, 1.21.11 · 24 апреля 2026 г.
[3.1.0] - 2026-04-24
🎉 New Feature
Folia Support (Dual-Compatibility)
- Paper + Folia from a single JAR — automatically detects the platform at startup
- New
FoliaSchedulerutility class abstracts all scheduler, teleport and kick operations plugin.ymldeclaresfolia-supported: true
Migrated APIs:
- All
Bukkit.getScheduler().runTask()calls →FoliaScheduler.runGlobal()/runOnEntity() - All
runTaskTimerAsynchronously()calls →FoliaScheduler.runAsyncRepeating() - All
player.teleport()calls →FoliaScheduler.teleportAsync()(usesteleportAsync()on Folia) - All
BukkitTaskfields →ObjectwithFoliaScheduler.cancelTask() - GUI
openInventory()calls run on entity scheduler for correct thread ownership - Resource pack sending uses entity-delayed scheduler
Files changed:
BanHammerPlugin.java— Folia detection on startupPunishmentManager.java— 13 scheduler replacementsUnbanScheduler.java— async scheduler, entity scheduler for jail releaseJailManager.java— 4 teleport migrations, scheduler migrationModrinthUpdateChecker.java— async scheduler, global scheduler for notificationsStatisticsGUI.java— entity scheduler for inventory operationsResourcePackListener.java— entity-delayed schedulerEssentialsJailIntegration.java— async teleport
No changes needed: HammerListener.java, AppealCommand.java, BanHammerCommand.java — events already fire on correct regional threads.
3.0.1Релиз1.21.9, 1.21.10, 1.21.11 · 18 апреля 2026 г.
[3.0.1] - 2026-04-18
🐛 Bug Fixes
Critical
Unjail Teleport nicht funktioniert: Spieler wurden beim Release aus dem Jail nicht an ihren ursprünglichen Ort zurückteleportiert
- Ursache: JailListener hat den Release-Teleport gecancelt, weil der Spieler noch im Jail-Cache war
- Fix: Cache-Entfernung erfolgt jetzt VOR dem Teleport in
JailManager.releasePlayer() - Gilt sowohl für
/unjailBefehl als auch automatischen Ablauf
SimpleDateFormat nicht thread-safe:
BanHammerCommandnutzte statischesSimpleDateFormataus async CompletableFuture-Callbacks- Fix: Ersetzt durch thread-sicheren
DateTimeFormatter
- Fix: Ersetzt durch thread-sicheren
loadActiveMutes() doppelte DB-Queries:
CompletableFuture.allOf()wurde aufgerufen und ignoriert, dann die gleichen 2 Queries nochmal einzeln- Fix: Sinnlosen allOf-Block entfernt (4 Queries → 2)
Discord Shutdown Hook Leak: Bei jedem
/bh reloadwurde ein neuerRuntime.addShutdownHook()registriert ohne den alten zu entfernen- Fix: Hook-Referenz wird gespeichert und bei
shutdown()entfernt
- Fix: Hook-Referenz wird gespeichert und bei
High Priority
getDatabase() NullPointerException:
handleAppeals()undreviewAppeal()riefenplugin.getDatabase()ohne Null-Check auf- Fix: Null-Checks vor allen direkten
getDatabase()-Aufrufen in BanHammerCommand
- Fix: Null-Checks vor allen direkten
unbanPlayer() findet nur BAN-Typ: Temp-Bans und IP-Bans konnten per
/bh unbannicht entfernt werden- Fix: Sucht jetzt nach allen Ban-Typen (BAN, TEMP_BAN, IP_BAN) und entfernt auch IP-Bans aus der IP-Banliste
unmutePlayer() findet nur MUTE-Typ: Temp-Mutes konnten per
/unmutenicht entfernt werden- Fix: Sucht jetzt nach allen Mute-Typen (MUTE, TEMP_MUTE)
IPv6-Validation immer true:
isValidIP()in UnbanScheduler gab für jede IPv6-Adresse true zurück, auch gehashte IPs- Fix: Gehashte IPs werden erkannt (kein
./:→ sofort false)
- Fix: Gehashte IPs werden erkannt (kein
HttpURLConnection Leak: ModrinthUpdateChecker hat
connection.disconnect()nie aufgerufen- Fix:
disconnect()im finally-Block; zusätzlich Null-Checks für JSON-Response-Felder
- Fix:
Medium Priority
PunishmentManager Race Condition: Manager wurde mit null-Database erstellt und bei DB-Init komplett neu erstellt — Listener behielten alte Referenz
- Fix: DB/Discord-Referenzen sind jetzt
volatileund updatebar viaupdateDatabase()/updateDiscord()
- Fix: DB/Discord-Referenzen sind jetzt
Cooldown Maps Memory Leak:
cooldowns,switchCooldowns,switchKickJailCooldownsin HammerListener wuchsen unbegrenzt- Fix: Cleanup bei
PlayerQuitEvent
- Fix: Cleanup bei
Auto-Unjail ohne Teleport: UnbanScheduler nutzte
releasePlayerByUUID()für abgelaufene Jails, was keinen Teleport zurück auslöst- Fix: Online-Spieler werden jetzt per
releasePlayer()(mit Teleport) auf dem Main-Thread freigelassen
- Fix: Online-Spieler werden jetzt per
Essentials Jail Release ohne Rück-Teleport: Bei Essentials-Release wurde der Spieler nicht zum Original-Ort zurückteleportiert
- Fix: Return-Location wird auch bei Essentials-Release verwendet
🔧 Improvements
- Modrinth API Response: Robustere JSON-Parsing mit Null-Checks für
version_number,urlundfiles - Doppelter
releasePlayer()-Aufruf inunjailPlayer()entfernt (Caller ist verantwortlich)
3.0.0Релиз1.21.9, 1.21.10, 1.21.11 · 8 января 2026 г.
[3.0.0] - 2026-01-08
🎉 Main Features
Ban Presets System (NEW!)
- Shift + Right-Click to switch between predefined ban presets
- Actionbar feedback shows current preset when switching
- Sound feedback individually configurable per preset
- Unlimited presets definable in config.yml
- Each preset with own duration, reason, IP-ban flag and sound
- Per-player tracking of active preset
- Configurable switch cooldown (250ms default)
- Works everywhere: on players, blocks or in the air
Kick/Jail Presets System (NEW!)
- Shift + Left-Click to switch between predefined kick/jail presets
- Mix kicks and jails in one preset list (no duration = kick, with duration = jail)
- Actionbar feedback shows current preset when switching
- Sound feedback individually configurable per preset
- Unlimited presets definable in config.yml
- Per-player tracking of active kick/jail preset
- Same configurable cooldown as ban presets
- Left-Click on Player executes kick or jail with active preset
Modrinth Update Checker (NEW!)
- Automatic update checking on server startup
- Periodic checks with configurable interval (default: 6 hours)
- Admin notifications on login (permission:
banhammer.updatenotify) - Semantic version comparison
- Download URLs and changelog links
- Rate limiting (max 1 check per hour)
- Fully configurable in config.yml
Database System
- SQLite support for single-server (no setup required)
- MySQL support for multi-server networks
- Complete ban history with detailed tracking
- Automatic schema creation and migrations
- Connection pooling with HikariCP for optimal performance
- WAL mode for SQLite (better concurrency)
- Optimized indexes for fast queries
Auto-Unban System
- Automatic unbanning when temporary bans expire
- Configurable check intervals (default: 60 seconds)
- Asynchronous processing (doesn't block main thread)
- Event triggers for external plugins
- Discord notifications on auto-unbans
- Supports temp-bans, temp-mutes and jail times
Discord Integration
- Webhook-based notifications
- Color-coded embeds for different actions:
- 🔴 Bans (Red)
- 🟠 Kicks (Orange)
- 🟢 Unbans (Green)
- 🟡 Mutes (Yellow)
- Staff names, player names, duration and reason in embeds
- Server names for multi-server setups
- Configurable which events are sent
- NEW: Discord now works independently of database (no database required)
- NEW: Discord webhook reinitializes on
/bh reloadwithout server restart
Essentials Jail Integration (NEW!)
- Soft Dependency: Optional Essentials plugin integration via
softdependin plugin.yml - Reflection-Based: No hard dependency - uses reflection to access Essentials API
- Smart Preference System: Automatically uses Essentials jail if available, falls back to built-in
- Automatic Detection: Checks for Essentials on startup and enables integration
- Built-in Fallback: Own jail system continues to work if Essentials not installed
- Seamless Integration: Works with existing Essentials jail configurations
- Debug Logging: Comprehensive DEBUG TELEPORT logs for troubleshooting
✨ New Features
Extended Punishment Types
- Mute System: Blocks chat and commands
- Permanent and temporary
- Cache-based for performance
- Shows remaining time
- Jail System: Locks players in place
- Configurable jail location via
/setjail - Prevents teleportation and movement
- Optional: Prevents damage and commands
- Configurable jail location via
- Warning System: Warnings with auto-ban
- Counts warnings per player
- Auto-ban after X warnings (configurable)
- Non-active punishment (only tracking)
Ban Appeals System
- Players can submit appeals via
/appeal <text> - Cooldown system (default: 24 hours)
- Maximum appeals per punishment (default: 3)
- Staff can approve/deny appeals
- Discord notifications for new appeals
- Appeal status tracking (PENDING, APPROVED, DENIED)
Statistics & Leaderboards
- Tracking of all punishments per staff member
- Total counts: Bans, kicks, mutes, warnings
- Leaderboard system
- GUI view via
/bh stats - Exportable via REST API
GDPR & Privacy Features
- IP anonymization with 4 levels:
NONE: Full IP storagePARTIAL: Last octet removed (192.168.1.0)HASH: One-way hash with server saltFULL: Complete masking
- Automatic salt generation
- Salt validation (min. 16 characters, 3 character types)
- Configurable data retention
🔧 Improvements
Performance Optimizations
- Asynchronous database initialization (no longer blocks server start)
loadActiveMutes()loads mutes into cache on startup- Optimized warning count via
SELECT COUNT(*)instead of N+1 query - SQLite connection pool set to 1 (single-writer)
- Race condition in
getActiveMute()fixed viacomputeIfPresent() - Composite indexes for common query patterns
Error Handling & Robustness
- Separate try-catch blocks in ban flow (prevents partial state)
- Improved Discord webhook validation
- URL format check
- Clear error messages
- Graceful degradation
- Robust duration parsing
- Supports: "7d", "1h30m", "PT24H", "permanent"
- Case-insensitive
- Warnings for invalid format
- Improved IPv6 validation via
InetAddress
Thread-Safety
- Mute cache removes expired entries atomically
- Switch cooldown via ConcurrentHashMap
- Database operations fully async
- Events fired on main thread
📝 Commands
New commands:
/bh appeals- Shows pending appeals/bh approve <id> [response]- Approves appeal/bh deny <id> [response]- Denies appeal/bh stats [player]- Shows statistics/bh reload- IMPROVED: Now reinitializes Discord webhook and Database connection/appeal <text>- Submits appeal/mute <player> <duration> [reason]- Mutes player/unmute <player> [reason]- Unmutes player/jail <player> <duration> [reason]- Jails player (uses Essentials if available)/unjail <player> [reason]- Releases from jail (works without database)/setjail- Sets jail location (only needed for built-in jail)/warn <player> [reason]- Warns player
🔑 Permissions
New permissions:
banhammer.appeals- Can view appealsbanhammer.appeals.review- Can review appealsbanhammer.appeal- Can submit appeals (default: true)banhammer.mute- Can mute playersbanhammer.jail- Can jail playersbanhammer.warn- Can warn playersbanhammer.stats- Can view statisticsbanhammer.updatenotify- Receive update notifications
🎨 API
Custom Events
PlayerPunishEvent- Fired BEFORE punishment (cancellable)PlayerPunishedEvent- Fired AFTER successful punishmentPlayerUnpunishedEvent- Fired when punishment removed
PunishmentManager API
// Fully async with CompletableFuture
pm.banPlayer(staff, victim, reason, duration, ipBan)
pm.mutePlayer(staff, victim, reason, duration)
pm.jailPlayer(staff, victim, reason, duration)
pm.warnPlayer(staff, victim, reason)
pm.getHistory(playerUuid, limit)
pm.getWarningCount(playerUuid)
Database Interface
- Abstract interface for SQLite/MySQL
- All operations via CompletableFuture
- Prepared statements against SQL injection
🐛 Bug Fixes
Critical Bug Fixes
✅ Expired Punishment Spam (CRITICAL): Fixed infinite "Found 1 expired punishment(s), processing..." spam
- Root Cause: NULL UUID handling in
deactivatePunishment()caused NullPointerException - Fix: Added null check for staffUuid in SQLiteDatabase.java:396 and MySQLDatabase.java:406
- Impact: Prevented database corruption and console spam
- Root Cause: NULL UUID handling in
✅ Jail Auto-Release Not Working (CRITICAL): Players weren't automatically released after jail time expired
- Root Cause: Missing JAIL case in UnbanScheduler switch statement
- Fix: Added JAIL case to UnbanScheduler.java:110-114
- Impact: Jail time now properly expires and releases players automatically
✅ Unjail Required Database:
/unjailcommand didn't work without database even with Essentials- Root Cause: Database check blocked everything in handleUnjail()
- Fix: Removed database requirement, calls JailManager.releasePlayer() directly
- Impact: Unjail now works with both Essentials and built-in jail without database
✅ Resourcepack Not Loading: Resourcepack wasn't being sent to players
- Root Cause: Empty URL and hash in config.yml
- Fix: Added proper URL and SHA-1 hash to config.yml
- Impact: Resourcepack now loads correctly for all players
Translation & Localization Fixes
- ✅ Incomplete Translations: Many messages were hardcoded in German
- Fix: Added 30+ new message keys to messages_de.yml and messages_en.yml
- Fix: Replaced 28 hardcoded strings across PunishmentCommands.java (15), BanHammerCommand.java (11), and AppealCommand.java (2)
- Fix: Extended Messages.java with 30+ new methods
- Impact: Plugin is now fully translatable, no hardcoded strings remaining
Reload Functionality Fixes
✅ Discord Not Reinitializing on Reload: Discord webhook required server restart after config changes
- Fix: Added
reinitializeDiscord()method in BanHammerPlugin.java - Impact: Discord webhook now reloads with
/bh reloadcommand
- Fix: Added
✅ Database Not Reinitializing on Reload: Database connection required server restart after config changes
- Fix: Added
reinitializeDatabase()method in BanHammerPlugin.java - Impact: Database connection now reloads with
/bh reloadcommand
- Fix: Added
Essentials Integration Fixes
✅ Essentials Jail Teleport Errors: "wrong number of arguments" and "Location.getLocation()" errors
- Fix: Fixed reflection to get Location directly from getJail() method
- Fix: Get jail list from Essentials and use first available jail
- Impact: Essentials jail integration now works correctly
✅ Jail Messages Not Colored: Jail/unjail messages showed raw MiniMessage tags instead of colors
- Fix: Added proper jail/unjail message calls to both Essentials and built-in jail paths
- Impact: Messages now display with proper colors
Logging Improvements
✅ Console Spam: Too many DEBUG messages during normal operation
- Fix: Reduced routine logs to DEBUG level, only show important info (Jail, Essentials, Discord, critical problems)
- Impact: Console is now clean and readable
✅ Missing Debug Logs for Troubleshooting: Hard to diagnose teleport and resourcepack issues
- Fix: Added comprehensive DEBUG TELEPORT logs (EssentialsJailIntegration.java:107-133)
- Fix: Added comprehensive DEBUG RESOURCEPACK logs (ResourcePackSender.java)
- Impact: Easier troubleshooting with debug mode enabled
Previous Bug Fixes
- ✅ Temporal bans were permanent → Duration parsing fixed
- ✅ Discord webhook no error messages → Validation added
- ✅ Server start blocks on DB init → Async initialization
- ✅ Mute cache memory leak → UnbanScheduler cleans cache
- ✅ Race condition in getActiveMute() → Atomic operation
- ✅ IPv6 validation incomplete → InetAddress validation
- ✅ SQL indexes wrongly defined → Separate CREATE INDEX statements
- ✅ N+1 query for warning count → Optimized COUNT query
- ✅ Resource leaks in ban flow → Separate error handling
🔄 Breaking Changes
No breaking changes - Version 3.0.0 is fully backwards compatible with 2.x configurations.
New features are optional and must be explicitly enabled:
database:
enabled: false # Default: off
discord:
enabled: false # Default: off
presets:
# Created automatically if not present
kickJailPresets:
# Created automatically if not present
updateChecker:
enabled: true # Default: on
📦 Dependencies
Required:
- Paper API: 1.21.1-R0.1-SNAPSHOT
- Java: 21
- HikariCP: 5.1.0
- SQLite JDBC: 3.47.1.0
- MySQL Connector/J: 9.1.0
- Gson: 2.11.0
- Discord Webhooks: 0.8.4
Optional (Soft Dependencies):
- Essentials (any recent version) - For enhanced jail system integration
📋 Technical Details
Code Quality
- Modern Java 21 features (Records, Text Blocks, Switch Expressions)
- Thread-safe implementations
- Async-first approach with CompletableFuture
- Event-based architecture
- Clean code principles
Architecture
- Manager pattern for business logic
- Database abstraction layer
- Event system for extensibility
- Preset system for flexible ban types
- Cache layer for performance
2.2.0Релиз1.21.8, 1.21.9, 1.21.10 · 28 ноября 2025 г.
[2.2.0] - 2025-11-29
Added
- Automatic resource pack delivery when players join, with configurable delay.
- Prioritization of existing server resource packs over the BanHammer pack.
- Shared ResourcePackSender, which is also used by the /banhammer pack command.
- Feedback for /banhammer pack, which shows which pack was sent.
Комментарии
Загружаем…