Tags
Creators
Details
1.1.9
Compatibility
Changes
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 during saveAllConfigs(), 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
- Only
config.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 async
thenAcceptAsync()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 /getinfo command was using blocking .get() calls on database queries, preventing Discord from receiving an immediate acknowledgment.
Fix:
- Converted blocking database calls to async
CompletableFuturechains - Created
getPlayerDataAsync()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: The HistoryDropdownHandler was 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 native EntityKnockbackEvent API.
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 with NullPointerException.
Problem: Templates could be missing escalation or durations fields in configuration, causing crashes when the code tried to access them.
Fix:
- Added null checks for
escalationconfiguration before accessing it - Added null checks for
durationslist 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 in additional_data field (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 in additional_data JSON.
Fix:
- Implemented proper remaining duration calculation from
expiry_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: The handlePlayerJoin() method in VanishModule was applying vanish effects (hiding players) from an async thread, but Bukkit's hidePlayer() operation must run on the main thread.
Fix:
- Wrapped vanish effect application in
Bukkit.getScheduler().runTask()to ensure it runs on main thread - All vanish-related operations (hidePlayer, setInvulnerable, setAllowFlight, etc.) now execute on the main thread
Impact: Vanish module no longer causes thread errors, providing a smoother experience for staff members using vanish.
Fixed Discord Unban Command Not Recognizing IP Bans
Issue: Discord /unban command incorrectly reported "Player is not banned" for IP-banned players, even when they were clearly banned in the database.
Problem: The command was only checking playerData.isBanned() (regular ban status) and not checking playerData.isIpBanned() (IP ban status), causing IP-banned players to be rejected.
Fix:
- Updated ban status check to include both
isBanned()andisIpBanned() - Players with either regular ban or IP ban can now be unbanned via Discord
- Consistent with in-game
/unbancommand which checks both ban types
Impact: Staff can now unban IP-banned players via Discord without receiving false "not banned" errors.
Fixed Disconnect Screen Showing Wrong Remaining Duration
Issue: Disconnect screen showed the original ban duration (e.g., "Unbanned in: 3 hours") instead of the actual remaining time (e.g., "Unbanned in: 20 minutes").
Problem: The code was using durationSeconds (original duration) instead of remainingDuration when creating the disconnect screen message.
Fix:
- Calculate remaining duration from
expiry_timeinadditional_dataJSON - Use remaining duration for both
durationDisplayanduntilMessage - Works for both IP bans and regular bans
- Works for both new bans and existing bans stored in the database
Impact: Banned players now see accurate remaining ban time on disconnect screen. For example, if they were banned for 3 hours 40 minutes ago, they'll see "Unbanned in: 20 minutes" instead of "Unbanned in: 3 hours". This fix applies to all bans, including existing ones in your database.
Fixed Vanish Module Not Hiding Players for New Joiners
Issue: When a normal player joins the server while a staff member is vanished, the normal player could see the vanished staff member in both the world and the tab list.
Problem: The handlePlayerJoin() method wasn't properly hiding already-vanished players from new joiners. It only handled the case when the joining player was vanished, not when other players were already vanished.
Fix:
- Added loop to hide all vanished players from new joiners without see permission
- Ensures vanished players are hidden in both world and tab list for new players
- Added proper tab name hiding with
playerListName(Component.empty()) - Runs on main thread with slight delay to ensure proper player loading
Impact: Vanished staff members are now completely invisible to normal players, both in the world and in the tab list. This applies to both newly vanished players and already-vanished players.
Fixed Discord Logging for All Ban Operations
Issue: Not all ban and unban operations were being logged to Discord channels.
Problem: The banOfflinePlayerWithCaseId() and ipBanOfflinePlayerWithCaseId() methods were missing Discord logging calls, causing offline bans to not appear in Discord.
Fix:
- Added Discord logging to
banOfflinePlayerWithCaseId()for offline player bans - Added Discord logging to
ipBanOfflinePlayerWithCaseId()for offline IP bans - All ban operations (online/offline, normal/IP) now log to Discord consistently
- All unban operations were already logging correctly
Impact: All ban and unban operations are now consistently logged to Discord channels, providing complete audit trails for staff.
Fixed IP_BAN / IPBAN Inconsistency
Issue: Sometimes "IPBAN" was stored instead of "IP_BAN", causing inconsistencies in database queries.
Problem:
- Inconsistent use of "IP_BAN" (with underscore) and "IPBAN" (without underscore)
- Some methods stored "IPBAN" while others searched for "IP_BAN"
- This caused queries to fail finding existing bans
Fix:
- Standardized to use "IP_BAN" (with underscore) throughout the codebase
- Added backward compatibility: queries now search for both "IP_BAN" and "IPBAN"
- Updated
getActiveBanOrMuteCaseId()to support both formats - Updated
deactivateIpBans()to support both formats - All new IP bans now consistently store "IP_BAN"
Impact: All IP ban queries now work correctly regardless of whether old entries use "IPBAN" or new entries use "IP_BAN".
📋 What You Need to Know
- Module configs are read-only: The plugin will never modify
modules/*.ymlfiles - Manual editing only: You can edit module configs directly in a file editor
- No auto-reformatting: Long strings won't be broken into multiple lines anymore
- Better async performance: Staff notifications no longer block the main thread
- No Discord timeouts: Discord slash commands respond instantly without blocking database queries
- No dropdown errors: History dropdown interactions complete successfully without "zip file closed" errors
- Accurate mute durations: Staff notifications now show correct remaining mute times
- Perfect vanish: Vanished players no longer reveal their presence through knockback
- Stable templates: Templates work even with incomplete configuration
- Correct ban durations: Staff join notifications show accurate remaining ban times
- Complete ban data: IP ban entries are properly stored with all information
- Working template escalation: Template bans now properly count offenses and escalate duration
- No vanish errors: Vanish module no longer causes thread errors on player join
- Discord unban works: Discord unban command now recognizes both regular and IP-banned players
- Accurate disconnect durations: Disconnect screen now shows actual remaining ban time, not original duration
- Complete vanish for new joiners: Vanished players are now properly hidden from players joining the server
- Complete Discord logging: All ban and unban operations are now logged to Discord channels
- IP ban consistency: All IP ban queries work correctly regardless of old or new format
Version: 1.1.9
Projects on Modrinth are automatically available through a Maven repository for use with JVM build tools such as Gradle. To learn more about the Modrinth Maven API, click here.
Note: When available, you should use the creator's maven repo instead as it will have transitive dependency information that the Modrinth Maven API does not. You may also end up with duplicate dependencies if you use a mix of Modrinth and non-Modrinth Maven repositories for your dependencies, because the group identifier will be different when served through the Modrinth Maven API.
Maven coordinates:
Version ID:
build.gradle:
repositories {
exclusiveContent {
forRepository {
maven {
name = "Modrinth"
url = "https://api.modrinth.com/maven"
}
}
// forRepositories(fg.repository) // Uncomment when using ForgeGradle
filter {
includeGroup "maven.modrinth"
}
}
}
// Standard Gradle dependency
dependencies {
implementation "maven.modrinth:TY8FR9Ml:ZDL3rhMP"
}
// Legacy Loom dependency
dependencies {
modImplementation "maven.modrinth:TY8FR9Ml:ZDL3rhMP"
}

