Zenith-Mod
1.2.7Advanced moderation plugin with ban/mute systems, escalation templates, offline support, and Web-API integration for professional server management.
1.2.7latestZenith-Mod 1.2.7Mar 15, 2026 Changelog
Ban GUI - Completely remade the Ban GUI, fixing several bugs from the previous version - Added a Case-ID search feature — simply click the magnifying glass and type the ID in chat - Active bans now show in red, expired/unbanned players in green - Added a filter button to toggle between all bans, active only, or inactive only AutoMod - Added an AutoMod system that automatically detects and removes messages containing blacklisted words - Leetspeak detection included — things like 1d10t or i.d.i.o.t are caught automatically, you only need to add the base word to the list - Added an AntiSpam system that detects duplicate messages and message flooding - Staff alerts are sent in-game and to Discord when a message is blocked - Staff can toggle their own alerts with /automod alerts1.2.6Zenith-Mod 1.2.6Jan 30, 2026 Zenith-Mod v1.2.6 Update
Bug Fixes
BanList GUI Critical Fixes
This update fixes several critical issues in the BanList GUI module that could cause server crashes. #### Fixed Issues - Fixed: Critical crash when opening Ban Details GUI caused by invalid material name (HOURGLASS) - The materialHOURGLASSdoes not exist in Minecraft/Bukkit API - Changed toCLOCK(the correct material name) - Added fallback handling for invalid material names throughout the module - Fixed: Material validation errors - AllMaterial.valueOf()calls now include proper try-catch error handling - Invalid material names from configuration now fallback to safe defaults (PAPER, RED_CONCRETE) - PreventsIllegalArgumentExceptioncrashes when configuration contains invalid materials - Fixed: Pagination bounds checking - Improved index validation when clicking on ban items - PreventsIndexOutOfBoundsExceptionwhen navigating between pages - Better handling of edge cases in pagination logic #### Technical Improvements - Added: Safe material name validation with fallback handling for all GUI items - Filter buttons, navigation buttons, action buttons, and info items all have fallback materials - Configuration errors no longer cause server crashes - Server continues to function even with invalid material names in config - Added: Enhanced slot bounds checking throughout the BanList module - All slot assignments now validate bounds before setting items - PreventsArrayIndexOutOfBoundsExceptionerrors - Better error logging for configuration issues - Improved: Better error handling for invalid configuration values - Invalid slot numbers are safely ignored - Invalid material names use fallback materials - Configuration errors are logged but don't crash the server
Zenith-Mod Velocity v1.2.5 is now also available! The Velocity version includes all the same features and bug fixes as the Bukkit version.Velocity Plugin Available
- Fully backward compatible - No breaking changes - No configuration changes needed - Existing configs work as-is - No database migrations needed - Automatic database handling - Works with all database types - H2, SQLite, MySQL, MariaDBCompatibility
Technical Details
Material Name Validation
All GUI item creation now includes safe material validation:
This ensures that even if the configuration contains invalid material names (likeMaterial material; try { material = Material.valueOf(materialName); } catch (IllegalArgumentException e) { // Fallback to safe default material = Material.PAPER; // or appropriate fallback }HOURGLASS), the server will not crash and will use a safe fallback material instead.Slot Bounds Checking
All slot assignments now validate bounds:
This preventsif (slot >= 0 && slot < gui.getSize()) { gui.setItem(slot, item); }ArrayIndexOutOfBoundsExceptionerrors when configuration contains invalid slot numbers.
If you're using custom material names inConfiguration Notes
modules/banlist.yml, please ensure they are valid Minecraft material names. Common mistakes: -HOURGLASS→CLOCK-WOOL→WHITE_WOOL(or specific color) -STAINED_GLASS→WHITE_STAINED_GLASS(or specific color) For a complete list of valid material names, refer to the [Bukkit Material API documentation](https://hub.spigotmc.org/javadocs/bukkit/org/bukkit/Mater…
- This update is highly recommended - Fixes critical crashes in the BanList GUI - No data loss - All existing bans and history entries remain intact - Automatic fallback - Invalid configurations are automatically handled with safe defaults - Error logging - Configuration errors are logged to help identify issuesImportant Notes
- Bukkit Version: [Download on Modrinth](https://modrinth.com/plugin/z-mod/versions) - Documentation: [Plugin Documentation](https://docs.zenith-studios.org/zenith-mod/introduction/) - API Documentation: [Java API Docs](http://javadocs.zenith-studios.org/) --- ⚠️ Recommendation: If you're using the BanList GUI feature, we strongly recommend updating to this version to prevent potential server crashes. Developed by Zenith-StudiosLinks
1.2.5Zenith-Mod 1.2.5Jan 24, 2026 Zenith-Mod v1.2.5 Update
- GUI-based ban overview with player heads - Click a ban to open a detail view - Unban directly from the GUI (permission-based) - Pagination + filters (Active/Expired, Player/IP, All)New: Ban List GUI (
/banlist)
- Fixed: A crash (Fixed
ArrayIndexOutOfBoundsException) when opening the Ban Details GUI caused by invalid slot handling / config path mismatch.
- The Zenith-Mod Velocity plugin is now available for proxy/network setups. Download on our DiscordVelocity Plugin Available
-Permissions
zenith.banlist— Access/banlist-zenith.banlist.unban— Unban from the GUI --- Developed by Zenith-Studios1.2.4Zenith-Mod 1.2.4Jan 22, 2026 Zenith-Mod v1.2.4 Update
A powerful, interactive GUI system for managing bans! Zenith-Mod now includes a comprehensive ban list interface that makes it easier than ever to view, filter, and manage player bans directly from an in-game GUI.New Feature: Ban List GUI
#### Interactive Ban List GUI - Visual Ban Overview: Browse all bans in a beautiful, organized GUI - Player Heads: See player avatars for each banned player - Detailed Information: View ban reason, staff member, case ID, date, duration, and status at a glance - Click to View Details: Click on any ban to see full information #### Advanced Filtering System - Active Bans: Filter to show only currently active bans - Expired Bans: View bans that have expired or been lifted - Player Bans: Filter to show only player-specific bans - IP Bans: Filter to show only IP-based bans - All Bans: View complete ban history #### Pagination Support - Navigate through large ban lists with ease - Page indicators show your current position - Smooth navigation between pages #### Quick Actions - Unban Directly from GUI: Unban players with a single click (requires permission) - Detailed View: Click any ban to see complete information including: - Player UUID and IP address - Full ban reason - Staff member details - Case ID - Ban date and duration - Current status (Active/Expired/Unbanned)Key Features
The ban list GUI is fully configurable viaConfiguration
modules/banlist.yml: - Customizable GUI Titles: Use hex colors and small caps formatting - Configurable Item Lore: Customize what information is displayed - Filter Button Positions: Arrange filter buttons as you prefer - Material Customization: Choose different materials for active/expired/IP bans - Variable Support: Use placeholders like{player_name},{reason},{case_id}, etc. - Color Utils Support: Full support for%smcaps%and hex colors (&#RRGGBB)
-Permissions
zenith.banlist- Access to/banlistcommand -zenith.banlist.unban- Unban players from the GUI
Simply use theUsage
/banlistcommand to open the ban list GUI. From there, you can: 1. Browse all bans with pagination 2. Apply filters to narrow down results 3. Click on any ban to view detailed information 4. Unban players directly from the detail view (if you have permission)
The ban list GUI supports extensive customization through the configuration file:Customization Examples
All text supports: - Hex colors (gui: title: '�FFAA%smcaps%BAN LIST%smreset%' ban_item: name: '&#FF5555{player_name}' lore: - '&#AAAAAAReason: &#FFFFFF{reason}' - '&#AAAAAAStaff: &#FFFFFF{staff_name}' - '&#AAAAAACase ID: &#FFFFFF{case_id}'&#RRGGBB) - Small caps formatting (%smcaps%...%smreset%) - Variable placeholders ({player_name},{reason}, etc.) - Standard Minecraft color codes
- Asynchronous Loading: Ban data is loaded asynchronously to prevent server lag - Session Management: Player sessions track current filter and page state - Efficient Filtering: Smart filtering system handles large ban lists efficiently - Thread-Safe: All GUI operations are properly synchronizedTechnical Details
The ban list GUI integrates seamlessly with: - Existing ban system - History tracking - Case ID system - Unban functionality - Staff notification systemIntegration
None - This update is fully backward compatible. All existing commands and functionality work exactly as before.Breaking Changes
- No configuration changes required - The ban list module is enabled by default - New configuration fileMigration Notes
modules/banlist.ymlwill be created automatically - All existing bans are immediately visible in the GUI
#### New Classes -Files Changed
me.kzlyth.modules.banlist.BanListModule-me.kzlyth.modules.banlist.BanListConfig-me.kzlyth.modules.banlist.gui.BanListGUI-me.kzlyth.modules.banlist.gui.BanDetailGUI-me.kzlyth.modules.banlist.gui.BanListGUIHandler-me.kzlyth.commands.admin.BanListCommand#### New Configuration -modules/banlist.yml- Complete GUI configuration #### Enhanced -ZenithMod- Added ban list module initialization -plugin.yml- Added/banlistcommand and permissions --- 🎉 Enjoy the new ban list GUI! This feature makes ban management more intuitive and efficient than ever before. 📢 Note: The ban list GUI requires players to have thezenith.banlistpermission. Make sure to grant this permission to your staff members.1.2.3Zenith-Mod 1.2.3Oct 31, 2025 Zenith-Mod v1.2.3 Update
This update includes significant API additions that are currently in Beta. While we've thoroughly tested all features, please be aware that: - In very rare cases, API methods may behave unexpectedly - In very rare cases, events may not fire or fire incorrectly - API structure may undergo changes in future versions - We do not provide any warranty or guarantee regarding the API's functionality Use of the new API features is at your own risk. However, all core plugin functionality (commands, moderation, etc.) remains stable and fully supported.Beta Notice
⚠️ THIS UPDATE IS HIGHLY RECOMMENDED - CRITICAL DATABASE ISSUE FIXED This version fixes a critical database problem that could cause data inconsistency issues. We strongly recommend updating immediately, especially if you're using MySQL or MariaDB databases.CRITICAL: Database Fix
What Was Fixed?
- Fixed: Critical database transaction issue that could cause history entries to be incomplete - Fixed: Potential race condition in database operations that could lead to missing case IDs - Improved: Database connection handling and error recovery - Result: More reliable database operations and complete history tracking Note: If you experience any issues after updating, please check your database logs and ensure all migrations completed successfully.
Zenith-Mod now includes a comprehensive Java API for developers to integrate with other plugins and extend functionality!New API System (Beta)
#### FreezeAPI (New API Modules
me.kzlyth.api.freeze) -freeze(UUID, UUID, String)- Freeze a player with reason -unfreeze(UUID, UUID, String)- Unfreeze a player -isFrozen(UUID)- Check if player is frozen -getFrozenPlayers()- Get list of all frozen players - Automatic history logging with case IDs - Staff notifications for all freeze actions #### ChatFreezeAPI (me.kzlyth.api.chatfreeze) -freezeChat(UUID, String)- Freeze the server chat -unfreezeChat(UUID, String)- Unfreeze the server chat -isChatFrozen()- Check if chat is currently frozen - Server-wide chat control with history tracking - Automatic staff notifications #### EssentialsAPI (me.kzlyth.api.essentials) - God Mode:setGodMode(UUID, UUID, boolean),isGodMode(UUID)- Fly Mode:setFlyMode(UUID, UUID, boolean),isFlying(UUID)- Heal:heal(UUID, UUID)- Restore player health - Feed:feed(UUID, UUID)- Restore player hunger - Clear Inventory:clearInventory(UUID, UUID)- Clear player inventory - Teleport:teleport(UUID, UUID),teleportHere(UUID, UUID)- Teleport players - All methods include staff notifications #### VanishAPI (me.kzlyth.api.vanish) -vanish(UUID)- Make player invisible -unvanish(UUID)- Make player visible -toggleVanish(UUID)- Toggle vanish status -isVanished(UUID)- Check if player is vanished -getVanishedPlayers()- Get list of all vanished players - Automatic staff notifications
A powerful event bus system for listening to moderation actions in real-time! #### Available Events - Ban Events:Event System (Beta)
PlayerBanEvent,PlayerUnbanEvent- Mute Events:PlayerMuteEvent,PlayerUnmuteEvent- Warn Events:PlayerWarnEvent- Kick Events:PlayerKickEvent#### Event Packages -me.kzlyth.api.events.ban.*- Ban and unban events -me.kzlyth.api.events.mute.*- Mute and unmute events -me.kzlyth.api.events.warn.*- Warn events -me.kzlyth.api.events.kick.*- Kick events #### Features - Events fired after actions complete (for integrations and logging) - Complete event data (player info, staff info, reason, case ID, duration, etc.) - Automatic main-thread handling for safe Bukkit API access - Simple subscription/unsubscription system - Perfect for Discord webhooks, external databases, analytics, and plugin integrations
All new APIs are accessible through the mainAPI Integration
ZenithAPIclass:ZenithAPI api = ZenithAPI.getInstance(); if (api != null && api.isAvailable()) { FreezeAPI freezeAPI = api.getFreezeAPI(); ChatFreezeAPI chatFreezeAPI = api.getChatFreezeAPI(); EssentialsAPI essentialsAPI = api.getEssentialsAPI(); VanishAPI vanishAPI = api.getVanishAPI(); ZenithEventBus eventBus = ZenithEventBus.getInstance(); eventBus.subscribe(PlayerBanEvent.class, event -> { // Handle ban event }); }
For detailed API documentation, method signatures, parameters, and usage examples, visit: [http://javadocs.zenith-studios.org/](http://javadocs.zenith-studios.org/) The Javadoc includes: - Complete class and method documentation - Parameter descriptions and return types - Usage examples and best practices - Exception handling guides - Event system documentationComplete API Documentation
Enhanced Existing APIs
BanAPI Improvements
- Fixed: Players are now automatically kicked when banned via API - Added: Staff notifications for all ban API calls - Improved: Better error handling and validationMuteAPI Improvements
- Added: Staff notifications for all mute API calls - Improved: Better offline player handlingWarnAPI Improvements
- Added: Staff notifications for all warn API calls - Fixed: Auto-escalation now works correctly with API callsKickAPI Improvements
- Added: Staff notifications for all kick API calls - Improved: Better integration with history systemAnalytics Integration
bStats Integration
- Added: Integrated bStats metrics system for plugin analytics - Anonymous usage statistics to help us improve the plugin - Respects server privacy settings - Can be disabled via bStats configurationTechnical Details
API Architecture
- Asynchronous Operations: All API methods useCompletableFuturefor non-blocking operations - Thread Safety: Event bus automatically handles thread synchronization - Error Handling: Comprehensive exception handling withAPIUnavailableException- History Integration: All API actions automatically create history entries with case IDs - Notification System: Automatic staff notifications for all moderation actionsDatabase Improvements
- Fixed critical transaction issues - Improved connection handling - Better error recovery mechanisms - Enhanced history entry consistencyPerformance
- Asynchronous API calls prevent server lag - Event system optimized for high-throughput scenarios - Efficient database operationsSetup Instructions
For Plugin Developers
1. Add Zenith-Mod as a dependency in yourplugin.yml:
2. Get the API instance:depend: [Zenith-Mod]
3. Subscribe to events:ZenithAPI api = ZenithAPI.getInstance(); if (api != null && api.isAvailable()) { // Use API... }
For complete setup instructions and examples, see the [API Documentation](http://javadocs.zenith-studios.org/).ZenithEventBus bus = ZenithEventBus.getInstance(); bus.subscribe(PlayerBanEvent.class, event -> { // Handle event... });
None - This update is fully backward compatible. All existing commands and functionality work exactly as before.Breaking Changes
- No configuration changes required - No database migrations needed (automatic) - All existing bans, mutes, warns, and history entries remain intact - API is opt-in - existing plugins continue to work without changesMigration Notes
Files Changed
New API Classes
-me.kzlyth.api.freeze.FreezeAPI-me.kzlyth.api.chatfreeze.ChatFreezeAPI-me.kzlyth.api.essentials.EssentialsAPI-me.kzlyth.api.vanish.VanishAPI-me.kzlyth.api.events.ZenithEvent-me.kzlyth.api.events.ZenithEventBus- Event classes inme.kzlyth.api.events.*packagesEnhanced Existing Classes
-ZenithAPI- Added getters for new APIs -BanAPI- Added notifications and auto-kick -MuteAPI- Added1.2.2Zenith-Mod 1.2.2Oct 28, 2025 Zenith-Mod v1.2.2 Release Notes
Update Notification System & Critical Bug Fixes
- Added: Automatic update checking for new plugin versions - Added: Players withUpdate Notification System
zenith.update.notifypermission get notified when a new version is available - Added: Clickable green "Modrinth" link that opens the download page - Features: - Async version checking via Modrinth API - Non-blocking update checks - Clean notification message with clickable link - Permission-based notification system (default: OP only) - Result: Staff members are automatically notified of new versions when joining the server
- Fixed:Unmute System Fix
active_casenow correctly set tonullafter unmute (instead of unmute case ID) - Fixed:ip_mutedstatus now properly cleared when unmuting IP-muted players - Fixed: IPMUTE recognition (without underscore) in unmute operations - Added: Support for bothIP_MUTEandIPMUTEpunishment types in unmute logic - Changed:updatePlayerMuteStatusnow setsactive_casetonullinstead of unmute case ID - Result: Unmuted players have correct status flags, allowing them to be muted again if needed
- Fixed: "Unknown" or "Permanent" duration display for IP-muted players - Fixed: Correct remaining duration calculation forIP-Mute Duration Display Fix
IP_MUTEandIPMUTEtypes - Changed: JSON parsing now supports both"expiry_time"and"expiryTime"formats - Changed: Staff notifications now show accurate remaining mute time for IP-muted players - Result: Staff see correct remaining time (e.g., "45 minutes") instead of "Unknown" or "Permanent"
- Fixed: Offense counting now works per template/reason instead of globally - Fixed: Different templates (e.g., "Doxx Threats", "Cheating") are counted separately - Changed: SQL query now filters by reason base (e.g., "Doxx Threats%") instead of all offenses - Changed: Template-based offense tracking prevents cross-template contamination - Result: Correct escalation levels per template (1st/2nd/3rd offense per specific reason)Offense Counter Fix
- Fixed: "Player not found in database" error when muting freshly joined players - Fixed: Race condition between player join and mute commands - Changed: Intelligent player database handling on join (existing vs new players) - Changed: Synchronous database creation for new players to prevent race conditions - Changed: Asynchronous updates for existing players (last_seen, IP) for performance - Added: Fallback mechanism for database errors during player join - Result: Mute commands work immediately after player join, no more "not found" errorsPlayer Join Optimization & Mute Command Fix
What Changed?
Before:
-No automatic update notifications for staff -
Players had to manually check for new versions -
active_caseset to unmute case ID prevented re-muting players -ip_mutedstatus not cleared after unmuting IP-muted players -Staff notifications showed "Unknown" or "Permanent" for IP-muted players -
Duration calculation failed for
IP_MUTEandIPMUTEtypes -JSON parsing only checked for
"expiryTime"format -Offense counting was global across all templates -
Different templates contaminated each other's offense counts -
Players got wrong escalation levels (e.g., "2nd Offense" when it was their first) -
"Player not found in database" error when muting freshly joined players -
Race condition between player join and mute commands -
All player joins used asynchronous database operations
After:
-Automatic update notifications when joining server -
Clickable Modrinth link for easy download access -
Permission-based notification system -
active_casecorrectly set tonullafter unmute -ip_mutedstatus properly cleared after unmuting IP-muted players -Both
IP_MUTEandIPMUTEsupported in unmute operations (I dont even know why I did IP_MUTE and IPMUTE in the first place) -
Accurate remaining duration shown in staff notifications -
Supports both
"expiry_time"and"expiryTime"JSON formats -Correct duration calculation for all mute types -
Offense counting works per template/reason -
Each template tracks offenses independently -
Correct escalation levels per specific reason -
Mute commands work immediately after player join -
No more "Player not found in database" errors -
Intelligent player database handling (existing vs new players) -
Synchronous database creation for new players prevents race conditions
Technical Details
Update Notification System
- UpdateChecker.java: New utility class for checking Modrinth API for updates - UpdateCheckListener.java: Event listener that checks for updates on player join - API Integration: Fetches version list fromhttps://api.modrinth.com/v2/project/z-mod/version- Version Comparison: Semantic versioning comparison (MAJOR.MINOR.PATCH) - Notification: Adventure API message with clickable link usingClickEvent.OPEN_URL- Permission:zenith.update.notify(default: OP only) - Thread Safety: Async operations prevent blocking server threadUnmute System Fix
- MuteManager.unmutePlayerWithCaseId(): Now checks forMUTE,IP_MUTE, andIPMUTEtypes - MuteManager.unmuteOfflinePlayerWithCaseId(): Same fixes for offline unmute operations - PlayerRepository.updatePlayerMuteStatus(): Setsactive_casetonullinstead of unmute case ID - PlayerRepository.setIpMuted(): Clearsip_mutedstatus when unmuting IP-muted players - Case ID Tracking: Original mute case ID stored inadditional_datafor audit trail - Discord Logging: Original case ID displayed in unmute embedsIP-Mute Duration Display Fix
- MuteHandler.sendStaffNotificationForIpMutedChat(): Fixed JSON parsing for expiry time - JSON Parsing: Supports both"expiry_time"(underscore) and"expiryTime"(no underscore) - String Parsing: Proper extraction ofexpiry_timevalue from JSON strings - Duration Calculation:remainingSeconds = (expiryTime - currentTime) / 1000- Format Display: UsesDurationParser.formatDuration()for readable time display - Punishment Type Support: Recognizes bothIP_MUTEandIPMUTEtypesOffense Counter Fix
- HistoryRepository.getOffenseCountByType(): Now filters by reason base instead of all offenses - Template Integration: Loads BanTemplate to get correct default reason for filtering - SQL Query:reason LIKE baseReason + "%"instead ofreason LIKE "%(%"- Cross-Template Prevention: Different templates (e.g., "Doxx Threats", "Cheating") counted separately - Escalation Accuracy: Each template maintains independent offense counts - Backward Compatibility: Existing history entries remain unchangedPlayer Join Optimization & Mute Command Fix
- PlayerJoinHandler.continueNormalJoinProcess(): Intelligent player database handling - PlayerRepository.updatePlayerLastSeenAndIp(): New method for updating existing players - Synchronous Database Creation: New players created synchronously to prevent race conditions - Asynchronous Updates: Existing players updated asynchronously for performance - MuteCommand.handleOfflineManualMute(): Online player detection prevents database lookup errors - Race Condition Prevention: Eliminates timing issues between join and mute commands - Fallback Mechanism: Graceful error handling with async fallbackCompatibility
Update Notification System
-Fully backward compatible -
No configuration required -
Permission-based access control -
Works with all server types (Paper/Purpur) -
Graceful handling of API failures
Unmute System
-Fully backward compatible with existing unmutes -
No database migration required -
Works with all mute types (MUTE, IP_
1.2.1Zenith-Mod 1.2.1Oct 27, 2025 Zenith-Mod v1.2.1 Release Notes
CRITICAL Bug Fixes
- Fixed: Fly mode is now properly restored when exiting vanish - Changed: Previous fly state (from EssentialsXVanish Module - Fly State Preservation
/flyor Creative gamemode) is now saved and restored automatically - Result: Players can now fly again after exiting vanish if they had fly enabled before entering vanish - Technical: AddedpreviousAllowFlightandpreviousFlyingMaps to store and restore player fly states
- Fixed: Permanent ban/mute now usesBan/Mute Duration Fixes
0duration instead of-1for consistency - Fixed: Commands/ban player perm reasonand/ban player 0 reasonnow correctly create permanent bans - Fixed: Player is no longer instantly unbanned when using duration "0" - Changed: Internal logic now treats0as permanent ban/mute across all systems - Result: Permanent bans now work correctly without instant unbans
- Fixed: Better error messages when trying to mute already muted players - Changed: Now shows "Player is already muted!" instead of "Failed to mute offline player" - Result: Staff members get clear feedback when attempting to mute already muted playersMute Already Muted Player Error
- Fixed: Unban actions now properly log to Discord channel when executed ingame - Fixed: Original case ID from ban is now displayed in Discord embed for unbans - Changed: Discord embed now shows the original ban case ID in "Original Case" field - Result: Staff can now track which ban was undone by each unban actionUnban Discord Logging & Case ID Display
- Fixed: Unmute actions now properly log to Discord channel for both online and offline players - Fixed: Original case ID from mute is now displayed in Discord embed for unmutes - Changed: UnmuteCommand now properly waits for Discord logging to complete before showing success message - Result: Staff can now track which mute was undone by each unmute action, complete audit trail for mute/unmute workflowUnmute Discord Logging & Case ID Display
- Fixed: Banned players can no longer join server during async ban check - Changed: Ban checking is now synchronous inBan Check Race Condition Fix
AsyncPlayerPreLoginHandlerto prevent race conditions - Result: Banned players are instantly blocked before they can join, no matter how fast they connect
- Fixed: "zip file closed" errors during plugin reloads no longer spam console - Changed: Added global exception handler inDiscord Plugin Reload Fix
DiscordBotto catch and ignore expected "zip file closed" errors - Result: Clean console during Discord interactions after plugin updates, no error spam
- Fixed: Players with expired bans can now connect, ban status is automatically updated - Changed: Added automatic expiry check inAuto-Unban Expired Bans Fix
AsyncPlayerPreLoginHandlerfor both regular and IP bans - Result: Expired bans are automatically deactivated when players try to join, no manual unban required
- Fixed: Better JSON parsing forJSON Parsing Fix for Expired Bans
expiry_timeinadditional_datato correctly extract expiry timestamps - Changed: Now properly finds the end of the number value (either comma or closing brace) in JSON strings - Result: Expired bans are now correctly detected and auto-unbanned, no more parsing errors
- Fixed: Disconnect screen now shows real ban data instead of placeholders - Changed: AddedDisconnect Screen - Real Ban Data Display
handleIpBanWithData()andhandlePlayerBanWithData()methods that load real ban information before disconnecting - Result: Players now see correct staff name, reason, remaining time, and case ID on disconnect screen
- Fixed: Disconnect screen now shows remaining ban time instead of original duration - Changed: Calculates remaining time fromRemaining Ban Time Calculation
expiry_timeinadditional_datafor both IP bans and regular bans - Result: Players see "2h 30m" instead of original "6h" ban duration on disconnect screen
- Fixed: Players withOrphaned IP Ban Fix
ip_banned=truebut no active history entry are now allowed to connect - Changed: Added check forcaseId <= 0to detect orphaned ban status in players table - Result: Removes incorrectip_bannedflag when no active history entry exists, prevents false positivesWhat Changed?
Before:
-Players lost ability to fly after exiting vanish -
Creative mode flight disappeared after vanish -
[EssentialsX](https://essentialsx.net/)
/flyno longer worked after vanish -Permanent bans using "perm" or "0" didn't work correctly -
Player was instantly unbanned when using duration "0" -
Unclear error messages when trying to mute already muted players -
Unban actions didn't log to Discord when executed ingame -
Discord embeds didn't show which ban was undone -
No way to track which case was reversed by an unban -
Unmute actions didn't log to Discord for offline players -
Original case ID not displayed in unmute embeds -
Banned players could join server during async ban check (race condition) -
"zip file closed" errors flooded console after plugin updates -
Expired bans kept players blocked, required manual unban -
ip_bannedflag stayedtrueeven after ban expiration -JSON parsing errors when checking expired ban expiry times -
Disconnect screen showed "Admin", "N/A", "No expiration" instead of real ban data -
Disconnect screen showed original ban duration instead of remaining time -
Players with orphaned
ip_banned=trueflag couldn't connectAfter:
-Players keep their original fly state after exiting vanish -
Creative mode flight is preserved -
[EssentialsX](https://essentialsx.net/)
/flycontinues working after vanish -Fly speed returns to normal (0.1f) -
Permanent bans work correctly with both "perm" and "0" durations -
Players stay banned when using permanent ban durations -
Clear error messages when attempting to mute already muted players -
All unban actions log to Discord (both ingame and Discord bot) -
Discord embed shows original ban case ID -
Complete audit trail for ban/unban workflow -
Staff can see which specific ban was reversed -
All unmute actions log to Discord (both online and offline players) -
Discord embed shows original mute case ID for unmutes -
Complete audit trail for mute/unmute workflow -
Banned players are instantly blocked, no race condition possible -
Clean console during plugin reloads, no "zip file closed" spam -
Expired bans are automatically removed, players can reconnect -
Ban status flags are updated when bans expire -
JSON expiry time parsing works correctly, no more parsing errors -
Disconnect screen shows real staff name, reason, remaining time, and case ID -
Disconnect screen shows remaining ban time instead of original duration -
Orphaned ban statuses are automatically cleaned up
Technical Details
Vanish Module
- Vanish Entry: System now stores currentallowFlightandisFlyingstate before enabling vanish flying - Vanish Exit: System restores the exact previous fly state (including EssentialsX/flyor Creative mode) - Storage: UsesHashMap<UUID, Boolean>to track previous fly states per playerDuration System
- DurationParser: Changed permanent ban/mute from-1to0for consistency - BanManager/MuteManager: Updated all-1checks to use0for permanent bans - Validation: Both "perm" and "0" are now treated as permanent ban/mute durations - Expiry Time: Changed fromexpiryTime = -1toexpiryTime = 0for permanent punishmentsError Handling
- MuteCommand: Added check forcaseId == -1to detect already muted players - Error Messages: Improved messaging to distinguish between "1.2.0Zenith-Mod 1.2.0Oct 27, 2025 Zenith-Mod v1.2.0 Release Notes
Performance & UX Improvements
- Fixed: Players are now instantly kicked during login without waiting for database queries - Improved: Disconnect screen shows immediately for banned players - Changes: Ban checks now happen inInstant Ban Disconnect
AsyncPlayerPreLoginEventwith instant kick, while history details load asynchronously in background - Result: No more delays when banned players try to join - connection is rejected immediately
- Fixed:Instant Kick Command
/kickcommand now executes immediately without any delay - Removed: 20-tick (1 second) delay that was previously added - Improved: Kick disconnect screen appears instantly for kicked players - Changes: History entry is now created asynchronously after the kick, not blocking the kick execution - Result: Staff can instantly kick players without waiting for database operations
- Fixed: SQLite syntax errors in all repository files - Added: Proper SQL syntax for all database types (SQLite, MySQL, MariaDB, H2) - Changed: All repository files now use database-specific AUTO_INCREMENT syntax - Changed: UPSERT operations now use database-specific syntax (Full Database Compatibility
ON DUPLICATE KEY UPDATEfor MySQL/MariaDB,INSERT OR REPLACEfor SQLite/H2) - Result: Plugin now works seamlessly with SQLite, MySQL, MariaDB, and H2 databases
- Fixed:Configuration Improvements
config.ymlis now truly read-only and never overwritten by the system - Changed: Plugin now stops immediately if database connection fails (no automatic fallback) - Result: User database settings are preserved exactly as configuredWhat Changed?
Before:
-Banned players could briefly connect before being kicked -
Kick command had a 1-second delay -
Server had to wait for database queries before kicking -
SQLite databases caused syntax errors -
config.ymlwas sometimes overwritten by the system -Plugin tried to fallback to different databases when connection failed
After:
-Banned players are rejected immediately at login -
Kick command executes instantly -
Database operations happen in background without affecting user experience -
SQLite works perfectly with proper syntax -
config.ymlis truly read-only -Plugin stops gracefully on database connection failure (respects user configuration)
Technical Details
- Ban Handler: OptimizedAsyncPlayerPreLoginHandlerto kick players instantly with default message, then load actual ban details asynchronously - Kick Manager: Removed blocking.join()calls andrunTaskLaterdelay, now kicks immediately - Database Operations: All history entries and Discord logs now happen asynchronously without blocking user operations - SQLite Support: Fixed AUTO_INCREMENT syntax in all 6 repository files (History, Player, AltLimit, Notes, Warn, RequestLog) - UPSERT Operations: Database-specific syntax for insert-or-update operations - Config Protection:config.ymlis now read-only at save time to prevent system overwrites - Database Failures: Plugin stops gracefully when connection fails instead of automatic fallbackCompatibility
-Fully backward compatible -
No configuration changes required -
All existing bans/kicks continue to work normally -
Works with all database types (H2, SQLite, MySQL, MariaDB) --- Note: This version focuses on performance and user experience improvements, ensuring instant feedback for moderation actions.
1.1.9Zenith-Mod 1.1.9Oct 27, 2025 Zenith-Mod v1.1.9 - Bug Fixes & Improvements
Critical Fixes
Fixed YAML Configuration Auto-Formatting
Issue: Module configuration files (ban.yml,mutes.yml, etc.) were being auto-formatted by the plugin, causing line breaks in long strings and breaking the YAML syntax. Problem: The plugin was loading module configs into a global map and then saving them duringsaveAllConfigs(), which triggered Bukkit's YAML formatter to add unwanted line breaks for strings longer than ~80 characters. Fix: - Module configuration files are now read-only - Onlyconfig.ymlandmessages.ymlare saved by the plugin - Module configs are loaded fresh from disk each time they're accessed - Prevents automatic formatting and preserves your custom YAML structure Impact: Your module configuration files will no longer be modified by the plugin, preserving their original formatting and structure.Fixed Staff Notification Duration Display
Issue: Staff notifications for muted players showed "Unknown" as duration instead of the actual remaining mute time. Problem: The code was using blocking.get()calls and only checking for "MUTE" punishment type, missing "IP_MUTE" entries. Fix: - Converted blocking calls to asyncthenAcceptAsync()handlers - Added support for both "MUTE" and "IP_MUTE" punishment types in notification checks - Proper async handling prevents thread blocking and ensures duration is calculated correctly - Staff notifications now display accurate remaining mute times Impact: Staff will now see correct mute durations in chat attempt notifications for both regular and IP mutes.Fixed Discord Command Interaction Timeouts
Issue: Discord slash commands were timing out with "Unknown interaction" errors after 3 seconds. Problem: The/getinfocommand was using blocking.get()calls on database queries, preventing Discord from receiving an immediate acknowledgment. Fix: - Converted blocking database calls to asyncCompletableFuturechains - CreatedgetPlayerDataAsync()method that returnsCompletableFuture<PlayerData>- Removed all blocking.get()calls from Discord command handlers - Discord interactions now respond within the required 3-second window Impact: Discord commands will no longer timeout, providing a smoother experience for staff members using the Discord bot.Fixed Discord Dropdown Interaction Timeouts
Issue: History dropdown interactions in Discord were timing out with "zip file closed" errors. Problem: TheHistoryDropdownHandlerwas using.thenAccept()instead of.thenAcceptAsync(), which could cause thread blocking during database operations. Fix: - Converted.thenAccept()to.thenAcceptAsync()in both outer and inner chains - Ensures proper async handling for all database queries - Prevents "zip file closed" errors during plugin reloads - All Discord dropdown interactions now complete without timing out Impact: Discord dropdown menus for history entries will no longer timeout or cause errors, providing a seamless experience for staff.Fixed Mute Duration Display in Staff Notifications
Issue: Staff notifications for muted players showed "0 seconds" instead of the actual remaining mute time. Problem: The code was checking for"expiryTime"in JSON data, but the database stores it as"expiry_time"(with underscore). Fix: - Updated code to check for both"expiry_time"and"expiryTime"for backward compatibility - Added debug logging to track duration calculations - Proper JSON parsing now retrieves the correct expiry time - Duration is now calculated and displayed accurately Impact: Staff will see correct mute durations like "2 hours, 15 minutes" instead of "0 seconds".Added Knockback Prevention for Vanished Players
Issue: Vanished players still received knockback when hit, making their vanished status obvious to others. Solution: Implemented knockback prevention using Paper's nativeEntityKnockbackEventAPI. Features: - Vanished players no longer receive knockback when damaged - Uses Paper's native event system for optimal performance - Simple event cancellation - no workarounds needed - All sources of knockback are blocked (melee, ranged, explosions, etc.) Impact: Vanished players remain completely invisible, making staff investigations undetectable.Fixed Template Escalation NullPointerException
Issue: Using ban/mute templates without proper configuration caused crashes withNullPointerException. Problem: Templates could be missingescalationordurationsfields in configuration, causing crashes when the code tried to access them. Fix: - Added null checks forescalationconfiguration before accessing it - Added null checks fordurationslist before accessing it - Templates with missing fields now use sensible defaults instead of crashing - Added warning logs when default values are used Impact: The plugin will no longer crash when using templates with incomplete configuration, improving stability.Fixed IP Ban JSON Format
Issue: IP ban entries in database had incomplete JSON inadditional_datafield (missing closing brace). Problem: When creating IP ban history entries for offline players, the JSON string was incomplete, causing parsing errors. Fix: - Added missing"ip"field to IP ban JSON for offline players - Ensured all JSON objects are properly formatted with closing braces - Both online and offline IP bans now store complete JSON data Impact: IP ban data is now properly stored and can be correctly parsed for duration calculations and case management.Fixed Ban Join Notification Duration Display
Issue: Staff notifications for banned players trying to join showed "Permanent" even for temporary bans. Problem: The code was not calculating the remaining ban duration correctly from the expiry time stored inadditional_dataJSON. Fix: - Implemented proper remaining duration calculation fromexpiry_timein JSON - Added fallback to original duration if expiry time parsing fails - Properly handles permanent bans (duration <= 0) - Both IP bans and normal bans now show correct remaining time Impact: Staff will now see accurate ban durations in join attempt notifications, making it easier to track when players can return.Fixed Template Escalation and Disconnect Screen Duration Display
Issue: Template bans showed incorrect escalation levels and disconnect screen showed "Permanent" instead of actual duration. Problem: - Template escalation was looking for wrong reason pattern in database - Disconnect screen was parsing already-formatted duration strings (e.g., "3 hours") instead of using them directly - Template name was being passed instead of template key/identifier - OR clause in offense count query was preventing proper offense counting Fix: - Simplified offense count query to search for offense suffix pattern%(%in reason field - Removed unnecessary duration parsing in disconnect screen (duration is already formatted) - Changed template processing to use template key instead of display name - Added debug logging to track offense counts - Disconnect screen now displays correct ban duration (e.g., "Unbanned in: 3 hours") Impact: Template bans now properly escalate (1st offense → 2nd offense) and show correct duration on disconnect screen.Fixed Vanish Module AsyncCatcher Error
Issue: Vanish module caused "Thread ForkJoinPool.commonPool-worker-5 failed main thread check" errors when applying vanish effects during player join. Problem: ThehandlePlayerJoin()method inVanishModulewas applying vanish effects (hiding players) from an async thread, but Bukkit'shidePlayer()operation must run on the main thread. Fix: - Wrapped vanish effect application inBukkit.getScheduler().runTask()to ensure it runs on main thread - All vanish-r1.1.8Zenith-Mod 1.1.8Oct 26, 2025 Zenith-Mod v1.1.8 - Critical Bug Fixes
Critical Fix
Fixed Offense Counting Bug
Issue: Players were incorrectly getting "2nd offense" when they should have gotten "1st offense", even though another player from a different IP was banned. Fix: The offense counting now properly tracks by IP address or player UUID based on the template'strack_by_ipsetting: - IP-based tracking: All players from the same IP share the same offense count - UUID-based tracking: Each player has their own separate offense count - Result: Escalation levels now correctly apply per player/IP group Impact: Ban durations now correctly reflect the actual offense count for each player or IP address.Database Improvements
Auto-Increment ID Support
- All database tables now have AUTO_INCREMENT IDs - Works for MySQL, MariaDB, H2, and SQLite - Automatic migration for existing databasesTechnical Details
History Repository Fix
- Fixed offense counting to use proper WHERE clauses - Now filters bytarget_iportarget_uuidbased on tracking key - Properly tracks escalation levels per player/IP group --- Version: 1.1.81.1.7Zenith-Mod 1.1.7Oct 26, 2025 Zenith-Mod v1.1.7 - Template Identifier Validation
Templates now require the identifier (YAML key) instead of display names.What's Changed
Before & After
Before:
/ban Player "Bug Abuse"Now:
/ban Player bug-abuse
When using a display name, you'll get a helpful error message:What You Need to Know
This applies to both Ban and Mute templates.You entered the display name 'Bug Abuse' instead of the identifier! Please use the identifier: bug-abuse
Display names can now include spaces in theConfiguration
namefield:
Use the YAML key (bug-abuse: name: "Bug Abuse" # ← Spaces allowed! description: "Ban template for bug abuse" auto_ip_ban: true # ...bug-abuse) in commands, not the display name. --- Version: 1.1.7 | Date: January 15, 20251.1.6Zenith-Mod 1.1.6Oct 26, 2025 Zenith-Mod v1.1.6 - First Release
A comprehensive and professional moderation plugin for Paper servers with advanced player management tools, database persistence, and modern architecture.
Zenith-Mod is a complete moderation solution designed for modern Paper servers. Built with performance and scalability in mind, it provides everything you need to manage your community professionally.What is Zenith-Mod?
Features
- Advanced Ban System - Complete ban management with IP bans, temporary/permanent bans, and escalation templates - Mute System - Chat muting with command blocking, offline player support, and template-based escalation - Warning System - Comprehensive warning management with escalation levels and automatic punishments - Freeze System - Player freezing with configurable restrictions and notificationsCore Moderation Systems
- Pre-configured punishment templates with automatic escalation - Track offenses by player UUID or IP address - Customizable duration levels and reason suffixes - Template-specific permissions for staff membersTemplate System
- Mute, ban, and warn players even when they're offline - Automatic player creation in database for offline operations - Complete audit trail with case IDs for all actionsOffline Player Support
- Alt Detection & Limiting - Automatic detection of alt accounts and configurable limits per IP - History System - Complete moderation history with case IDs and audit trails - Note System - Staff notes for players, invisible to players - Player Info System - Real-time player information and status checksAdvanced Player Management
- Complete invisibility from other players - Hides from tab list, player list, and nametags - Prevents damage, block interactions, and item pickup - Auto god-mode and flight for vanished players - Permission-based visibility controlVanish System
- Zero thread blocking with async operations - Async database queries throughout - Hot-reload configuration without server restart - Custom logging system with colored console outputPerformance Optimized
- Real-time notifications for moderation events - Banned player join attempts - Muted player chat attempts - Permission-based notification systemStaff Notifications
- RESTful API for external integrations and web panels - Token-based authentication system - Real-time server statistics and player management - License validation for premium featuresWeb-API Integration (Premium)
- Discord slash commands for moderation - Ban, mute, and player management via Discord - Real-time moderation from Discord - Discord embed notifications -Discord Integration (Beta)
Currently in BETA - use with caution
The plugin uses a modular configuration system for easy customization:Modular Configuration
Core Configuration
-config.yml- Main plugin configuration, database settings, and general options -messages.yml- Customizable messages, notifications, and placeholder supportModule Configurations
-modules/ban.yml- Ban system with templates and escalation -modules/mutes.yml- Mute system with chat blocking -modules/warn.yml- Warning system -modules/freeze.yml- Player freeze system -modules/kick.yml- Kick system -modules/notes.yml- Staff notes system -modules/essentials.yml- Essential commands -modules/gamemodes.yml- Gamemode management -modules/vanish.yml- Vanish system -modules/limiter.yml- Alt detection and limiting -modules/client-detector.yml- Client detection -modules/chat-freeze.yml- Chat freeze system -modules/history.yml- History tracking -modules/check.yml- Player check system -modules/web-api.yml- Web-API configuration -modules/discord/discord-bot.yml- Discord bot configuration (BETA)Requirements & Compatibility
- Paper 1.21.4 (Primary development and testing version)Tested On
- Paper 1.21.4+:Compatibility Rating
Fully supported and tested - Paper 1.21.0-1.21.3:
Very likely compatible - Paper 1.20.x:
Very likely compatible - Paper 1.19.4:
Probably compatible - Paper 1.19.0-1.19.3:
May work with minor issues - Paper 1.18.x and older:
Unlikely to work - Spigot:
Partially supported (some features may not work)
- No Deprecated APIs: This plugin uses only current, non-deprecated Bukkit/Paper APIs - Modern Architecture: Built with latest Paper Plugin system and async operations - Stable Dependencies: Uses only stable, long-term supported features - Forward Compatible: Designed to work with future Paper versions - Clean Code: No legacy code or deprecated methods that could break in future updatesFuture-Proof Design
- Custom Paper Forks - Use at your own risk, no support provided - PlugMan - Do not use PlugMan to load this plugin (Paper plugins not supported) - Bukkit - Requires Paper/Spigot API featuresNot Supported
Database Support
Supported Databases
- H2 (Embedded - Default, perfect for single-server setups) - SQLite (File-based, great for small servers) - MySQL (Network database, ideal for multi-server setups) - MariaDB (Network database, MySQL alternative)Features
- HikariCP connection pooling for optimal performance - Automatic database initialization - Async database operations throughout - Migration support for future updatesChangelog (v1.1.6)
Fixed
- Alt Limit System: Fixed critical bug where players could bypass alt limits - Proxy Support: Added Velocity/BungeeCord IP forwarding support - Performance: Removed thread blocking in CommandBlocker and Discord commandsAdded
- Proxy Detection: Automatic IP detection from proxy servers - Debug Logging: Enhanced IP detection with detailed logging - Performance Optimizations: Async operations throughoutChanged
- CommandBlocker: Now uses async operations, no more thread blocking - MuteSlashCommand: Optimized async handling to prevent "zip file closed" errors - IPUtils: Added Velocity proxy support with reflection-based IP detection
1. Download the latest version from Modrinth 2. Place the JAR file in yourGetting Started
plugins/folder 3. Restart your server 4. Configure the plugin inplugins/Zenith-Mod/5. Set up your database inconfig.yml6. Customize messages inmessages.yml7. Configure modules inmodules/directory
- Discord: [Zenith Studios Discord](https://discord.gg/2qCMn6KHj4) - Documentation: [Zenith-Mod](https://docs.zenith-studios.org/docs/zenith-mod/)Support & Resources
Important Notes
Discord Integration (BETA)
- Discord slash commands are currently in BETA - Use with caution in production environments - Report any issues on Discord - Configuration available inmodules/discord/discord-bot.ymlPermissions
- All permissions are documented inplugin.yml- Use LuckPerms or your preferred permission manager - Template permissions follow pattern:zenith.[action].template.[name]Performance
- All database operations are async - No thread blocking in moderation commands - Built-in connection pooling for optimal performance - Hot-reload with/zenith reloadcommand
Zenith-Mod is the complete moderation solution you've been waiting for. Download now and revolutionize your server's moderation system! --- Version: 1.1.6 Release Date: January 14, 2025 Platform: Paper 1.21.4+ --- Made withReady to Get Started?
by Zenith Studios
Similar projects
Plugin →Simple Voice Chat
A working voice chat in Minecraft!
76.8MSueta
WorldEdit
A Minecraft Map Editor... that runs in-game! With selections, schematics, copy and paste, brushes, and scripting. Use it in creative, or use it temporarily in survival.
11.6MSueta
Emotecraft
Create your own emotes in Minecraft.
7.5MSueta
Plasmo Voice
A proximity voice chat mod with audio positioning and lots of features
4.1MSueta
Customizable Player Models
Customize your minecraft avatar!
3.2MSueta
PatPat [Mod & Plugin]
Allows you to pat ANY loved and unloved living mobs in Minecraft!
2.8MSueta