Tags
Creators
Details
2.2.0
Compatibility
Changes
[2.2.0] - 2026-01-05
🏗️ Major Release - Stability & Performance Update
This release focuses on security hardening, graceful degradation, performance optimizations, and critical bug fixes to ensure stable operation on production servers.
🔐 Security Hardening
SQL Injection Prevention
- Type-Safe Database Queries
- New
TimeUnitenum for SQL time unit operations - Replaces dangerous string concatenation in
DatabaseManager - Prevents SQL injection attacks via time-based queries
- Enum values:
SECOND,MINUTE,HOUR,DAY - Each value provides safe SQL name via
getSqlNameUpper()
- New
SSRF Protection
- Discord Webhook URL Validation
- Protocol validation: HTTPS-only (HTTP rejected)
- Domain whitelist: Only
discord.comanddiscordapp.comallowed - Path validation: Must start with
/api/webhooks/ - Prevents Server-Side Request Forgery attacks
- Logs validation failures for security monitoring
Memory Leak Prevention
- Size Limits on All Maps
XRayDetector.playerPlacedBlocks- Max size: 10,000 entriesXRayDetector.playerOreMines- NEW: Max size: 5,000 playersXRayDetector.playerStoneMines- NEW: Max size: 5,000 playersMovementChecker.moveCounter- Periodic reset at threshold- Automatic cleanup routines prevent unbounded growth
- Warning logs when size limits are hit
- Debug logging shows cleanup statistics and map sizes
💾 Graceful Degradation
FallbackLogger System
- Automatic Database Failover
- Queue-based async file writing (
ConcurrentLinkedQueue) - CSV format:
timestamp | type | value | description - Detects 3 consecutive database failures
- Switches to file logging automatically
- Configurable flush threshold (default: 100 entries)
- File rotation and management
- Fallback file path:
plugins/PerformanceAnalyzer/fallback.log
- Queue-based async file writing (
Database Availability Monitoring
- Failure Detection
isDatabaseAvailable()method for health checks- Consecutive failure counter
- Automatic recovery detection (resets to DB logging)
- Logs critical warnings when switching modes
Configuration
fallback_logging:
enabled: true
file: "plugins/PerformanceAnalyzer/fallback.log"
⚡ Performance & Reliability
AsyncConfigSaver (CRITICAL FIX)
- Thread-Safe Config Operations
- FIXED: Now uses Bukkit Scheduler instead of ForkJoinPool
- CRITICAL:
saveConfig()runs on main thread (Bukkit requirement) - Previously used
CompletableFuture.runAsync()which caused ConcurrentModificationException - Uses
CompletableFuturefor async pattern - Atomic boolean flags prevent concurrent saves
saveAsync()schedules on main thread viarunTask()saveSyncOnShutdown()ensures data persistence on server stop- Error handling with exception logging and stack traces
- Prevents thread-safety violations and data corruption
Performance Optimizations
-
Event Sampling - Movement checks reduced by ~90%
- Only every 10th PlayerMoveEvent processed
- OR significant distance (>2 blocks) always checked
- Counter reset at 1000 to prevent overflow
- Minimal detection accuracy loss
-
Database Indexing
- Indexes on
timestampcolumn for time-range queries - Indexes on
typecolumn for metric filtering - Significantly faster query performance
- Auto-created during database initialization
- Indexes on
Constants Class
- Centralized Configuration
- 255 lines of well-organized constants
- Categories: Database, Discord, Movement, XRay, Performance, Vehicle Speeds
- No more magic numbers scattered throughout codebase
- Easy to tune and maintain
- All values documented with comments
🏗️ Architecture Improvements
CommandRegistry System
- Modular Command Registration
- Replaces 112-line monster method in
PerformanceAnalyzer - Separate methods for each category:
registerPerformanceCommands()- /perfstatus, /perfhistory, /perfreloadregisterAnalysisCommands()- /worldstats, /entitystats, /chunkstats, /perfdropsregisterGUICommands()- /perfguiregisterAntiCheatCommands()- /acwhitelist, /xrayalerts, /movealerts, /xrayores
- Easy to extend with new commands
- Clean separation of concerns
- AntiCheat commands dynamically registered when module enabled
- Replaces 112-line monster method in
ConfigMigrator Class
- Extracted Migration Logic
- Separate class for config version upgrades
- Version-by-version migration (v0 → v1 → v2 → ... → v5)
- Only runs when
config_version < Constants.CONFIG_VERSION - Returns boolean if changes were made
- Cleaner
PluginConfigclass (separation of concerns) - Easy to add new migrations
Public API
- PerformanceAPI Interface
double getCurrentTPS()- Get current server TPSdouble getCurrentMSPT()- Get current MSPTboolean isPlayerSuspicious(UUID playerUUID)- Check if player flagged- Enables third-party plugin integration
- Future: Additional methods for detailed performance data
🐛 Critical Bug Fixes
DatabaseManager Exception Handling
- FIXED: Added missing stack traces to SQL exceptions
- IMPROVED: Now logs failed SQL statements for debugging
- ADDED: JavaDoc documentation for
run()method - Better error messages for database initialization failures
- Prevents silent failures during schema creation
XRayDetector Map Size Enforcement
- FIXED: Unbounded memory growth in
playerOreMinesandplayerStoneMines - ADDED: Hard limit of 5,000 player entries per map
- IMPROVED: Cleanup task now removes empty
playerStoneMinesentries - Warning logs when size limit is exceeded
- Debug output shows current map sizes
Config.yml Language Consistency
- FIXED: All comments now in English (was mixed German/English)
- Consistent with multi-language support design
- User-facing messages still use language files (en.yml/de.yml)
- Better for international plugin distribution
🔧 Code Quality Improvements
- Consistent Error Handling - All exceptions logged with stack traces
- English Logging - All console logs in English (user-facing messages use i18n)
- Null Safety - Extensive null checks before operations
- Improved Documentation - JavaDoc added to critical methods
- Code Comments - All config comments translated to English
📦 New Files Created
util/Constants.java- Centralized constantscommands/CommandRegistry.java- Modular command registrationconfig/ConfigMigrator.java- Config migration logicconfig/AsyncConfigSaver.java- Async config savesdb/FallbackLogger.java- Fallback file loggingdb/TimeUnit.java- SQL-safe time unitsapi/PerformanceAPI.java- Public API interface
🔧 Modified Files
PerformanceAnalyzer.java- CommandRegistry integration, version update to 2.2.0DatabaseManager.java- CRITICAL FIX: Stack traces, SQL logging, FallbackLogger, TimeUnit enum, failure detectionAsyncConfigSaver.java- CRITICAL FIX: Thread-safety with Bukkit SchedulerPluginConfig.java- AsyncConfigSaver, ConfigMigrator, fallback config methodsDiscordWebhook.java- URL validation, SSRF protectionMovementChecker.java- Constants usage, event samplingXRayDetector.java- CRITICAL FIX: Size limits (5000 players), improved cleanup, memory leak preventionConstants.java- NEW:XRAY_MAX_PLAYER_ENTRIESconstantconfig.yml- FIXED: All comments translated to Englishpom.xml- Version 2.2.0
⚠️ Breaking Changes
None - This release is fully backward compatible with v2.1.0.
- All new features have sensible defaults
- Existing configs auto-migrate
- No database schema changes
- No API changes to existing methods
📊 Configuration Changes
New Config Sections:
# Graceful Degradation
fallback_logging:
enabled: true
file: "plugins/PerformanceAnalyzer/fallback.log"
Auto-Migration:
- Config auto-migrates from v5 to v5 (no version bump needed)
- New
fallback_loggingsection added automatically - Existing settings preserved
🔄 Migration Guide (from v2.1.0)
- Backup - Backup your
plugins/PerformanceAnalyzer/folder - Stop Server - Stop your server
- Replace JAR - Replace old JAR with
PerformanceAnalyzer-2.2.0.jar - Start Server - Start your server
- Auto-Migration - Config auto-updates (check console for "Config migrated")
- Verify - Run
/perfstatusto ensure plugin loaded correctly
Optional Post-Migration:
- Review fallback logging settings in
config.yml - Check
fallback.logfile (created only on database failure)
📈 Performance Impact
- CPU Usage: Reduced ~90% for movement checks (event sampling)
- Memory Usage: Lower (cleanup routines, size limits)
- Disk I/O: Reduced (async config saves, fallback only on failure)
- Database Load: Reduced (batching, indexing)
- Startup Time: Unchanged
🐛 Known Issues
None - All known issues from v2.1.0 have been resolved, including:
- ✅ AsyncConfigSaver thread-safety violation (ConcurrentModificationException)
- ✅ DatabaseManager silent failures (missing stack traces)
- ✅ XRayDetector unbounded memory growth (5000+ players)
- ✅ Config.yml mixed language comments (now all English)
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:xcpph8Xo:bRAWmi14"
}
// Legacy Loom dependency
dependencies {
modImplementation "maven.modrinth:xcpph8Xo:bRAWmi14"
}

