From 4aa5a2121bf19674e8d4223ec0211fc3b9166180 Mon Sep 17 00:00:00 2001 From: DerGamer009 <169071753+DerGamer009@users.noreply.github.com> Date: Sun, 8 Feb 2026 03:41:09 +0100 Subject: [PATCH] #0001 --- .gitattributes | 2 + .gitignore | 123 ++ CHANGELOG.md | 922 +++++++++ LICENSE | 30 +- PREMIUM_INTEGRATION.md | 239 +++ PREMIUM_README.md | 265 +++ PlayerDataSync-Premium/premium/.gitignore | 16 + .../premium/PLUGIN_DESCRIPTION.md | 199 ++ PlayerDataSync-Premium/premium/README.md | 109 ++ PlayerDataSync-Premium/premium/SETUP.md | 121 ++ PlayerDataSync-Premium/premium/pom.xml | 381 ++++ .../premium/api/LicenseValidator.java | 269 +++ .../premium/api/PremiumUpdateChecker.java | 160 ++ .../commands/PremiumCommandHandler.java | 106 ++ .../premium/commands/SyncCommand.java | 595 ++++++ .../premium/core/PlayerDataSyncPremium.java | 910 +++++++++ .../premium/database/ConnectionPool.java | 180 ++ .../premium/database/DatabaseManager.java | 1686 +++++++++++++++++ .../InventoryViewerIntegrationManager.java | 405 ++++ .../premium/listeners/PlayerDataListener.java | 246 +++ .../listeners/ServerSwitchListener.java | 100 + .../managers/AdvancementSyncManager.java | 331 ++++ .../premium/managers/BackupManager.java | 345 ++++ .../premium/managers/ConfigManager.java | 545 ++++++ .../premium/managers/LicenseManager.java | 207 ++ .../premium/managers/MessageManager.java | 110 ++ .../premium/utils/InventoryUtils.java | 532 ++++++ .../premium/utils/OfflinePlayerData.java | 77 + .../premium/utils/PlayerDataCache.java | 255 +++ .../premium/utils/SchedulerUtils.java | 303 +++ .../premium/utils/VersionCompatibility.java | 151 ++ .../premium/src/main/resources/config.yml | 175 ++ .../src/main/resources/messages_de.yml | 182 ++ .../src/main/resources/messages_en.yml | 181 ++ .../premium/src/main/resources/plugin.yml | 201 ++ README.md | 337 ++++ pom.xml | 381 ++++ .../playerdatasync/api/UpdateChecker.java | 137 ++ .../playerdatasync/commands/SyncCommand.java | 586 ++++++ .../playerdatasync/core/PlayerDataSync.java | 1041 ++++++++++ .../database/ConnectionPool.java | 180 ++ .../database/DatabaseManager.java | 1686 +++++++++++++++++ .../InventoryViewerIntegrationManager.java | 407 ++++ .../listeners/PlayerDataListener.java | 247 +++ .../listeners/ServerSwitchListener.java | 101 + .../managers/AdvancementSyncManager.java | 332 ++++ .../managers/BackupManager.java | 346 ++++ .../managers/ConfigManager.java | 545 ++++++ .../managers/MessageManager.java | 110 ++ .../playerdatasync/utils/InventoryUtils.java | 532 ++++++ .../utils/OfflinePlayerData.java | 77 + .../playerdatasync/utils/PlayerDataCache.java | 255 +++ .../playerdatasync/utils/SchedulerUtils.java | 288 +++ .../utils/VersionCompatibility.java | 151 ++ src/main/resources/config.yml | 166 ++ src/main/resources/messages_de.yml | 182 ++ src/main/resources/messages_en.yml | 181 ++ src/main/resources/plugin.yml | 197 ++ 58 files changed, 19111 insertions(+), 13 deletions(-) create mode 100644 .gitattributes create mode 100644 .gitignore create mode 100644 CHANGELOG.md create mode 100644 PREMIUM_INTEGRATION.md create mode 100644 PREMIUM_README.md create mode 100644 PlayerDataSync-Premium/premium/.gitignore create mode 100644 PlayerDataSync-Premium/premium/PLUGIN_DESCRIPTION.md create mode 100644 PlayerDataSync-Premium/premium/README.md create mode 100644 PlayerDataSync-Premium/premium/SETUP.md create mode 100644 PlayerDataSync-Premium/premium/pom.xml create mode 100644 PlayerDataSync-Premium/premium/src/main/java/com/example/playerdatasync/premium/api/LicenseValidator.java create mode 100644 PlayerDataSync-Premium/premium/src/main/java/com/example/playerdatasync/premium/api/PremiumUpdateChecker.java create mode 100644 PlayerDataSync-Premium/premium/src/main/java/com/example/playerdatasync/premium/commands/PremiumCommandHandler.java create mode 100644 PlayerDataSync-Premium/premium/src/main/java/com/example/playerdatasync/premium/commands/SyncCommand.java create mode 100644 PlayerDataSync-Premium/premium/src/main/java/com/example/playerdatasync/premium/core/PlayerDataSyncPremium.java create mode 100644 PlayerDataSync-Premium/premium/src/main/java/com/example/playerdatasync/premium/database/ConnectionPool.java create mode 100644 PlayerDataSync-Premium/premium/src/main/java/com/example/playerdatasync/premium/database/DatabaseManager.java create mode 100644 PlayerDataSync-Premium/premium/src/main/java/com/example/playerdatasync/premium/integration/InventoryViewerIntegrationManager.java create mode 100644 PlayerDataSync-Premium/premium/src/main/java/com/example/playerdatasync/premium/listeners/PlayerDataListener.java create mode 100644 PlayerDataSync-Premium/premium/src/main/java/com/example/playerdatasync/premium/listeners/ServerSwitchListener.java create mode 100644 PlayerDataSync-Premium/premium/src/main/java/com/example/playerdatasync/premium/managers/AdvancementSyncManager.java create mode 100644 PlayerDataSync-Premium/premium/src/main/java/com/example/playerdatasync/premium/managers/BackupManager.java create mode 100644 PlayerDataSync-Premium/premium/src/main/java/com/example/playerdatasync/premium/managers/ConfigManager.java create mode 100644 PlayerDataSync-Premium/premium/src/main/java/com/example/playerdatasync/premium/managers/LicenseManager.java create mode 100644 PlayerDataSync-Premium/premium/src/main/java/com/example/playerdatasync/premium/managers/MessageManager.java create mode 100644 PlayerDataSync-Premium/premium/src/main/java/com/example/playerdatasync/premium/utils/InventoryUtils.java create mode 100644 PlayerDataSync-Premium/premium/src/main/java/com/example/playerdatasync/premium/utils/OfflinePlayerData.java create mode 100644 PlayerDataSync-Premium/premium/src/main/java/com/example/playerdatasync/premium/utils/PlayerDataCache.java create mode 100644 PlayerDataSync-Premium/premium/src/main/java/com/example/playerdatasync/premium/utils/SchedulerUtils.java create mode 100644 PlayerDataSync-Premium/premium/src/main/java/com/example/playerdatasync/premium/utils/VersionCompatibility.java create mode 100644 PlayerDataSync-Premium/premium/src/main/resources/config.yml create mode 100644 PlayerDataSync-Premium/premium/src/main/resources/messages_de.yml create mode 100644 PlayerDataSync-Premium/premium/src/main/resources/messages_en.yml create mode 100644 PlayerDataSync-Premium/premium/src/main/resources/plugin.yml create mode 100644 pom.xml create mode 100644 src/main/java/com/example/playerdatasync/api/UpdateChecker.java create mode 100644 src/main/java/com/example/playerdatasync/commands/SyncCommand.java create mode 100644 src/main/java/com/example/playerdatasync/core/PlayerDataSync.java create mode 100644 src/main/java/com/example/playerdatasync/database/ConnectionPool.java create mode 100644 src/main/java/com/example/playerdatasync/database/DatabaseManager.java create mode 100644 src/main/java/com/example/playerdatasync/integration/InventoryViewerIntegrationManager.java create mode 100644 src/main/java/com/example/playerdatasync/listeners/PlayerDataListener.java create mode 100644 src/main/java/com/example/playerdatasync/listeners/ServerSwitchListener.java create mode 100644 src/main/java/com/example/playerdatasync/managers/AdvancementSyncManager.java create mode 100644 src/main/java/com/example/playerdatasync/managers/BackupManager.java create mode 100644 src/main/java/com/example/playerdatasync/managers/ConfigManager.java create mode 100644 src/main/java/com/example/playerdatasync/managers/MessageManager.java create mode 100644 src/main/java/com/example/playerdatasync/utils/InventoryUtils.java create mode 100644 src/main/java/com/example/playerdatasync/utils/OfflinePlayerData.java create mode 100644 src/main/java/com/example/playerdatasync/utils/PlayerDataCache.java create mode 100644 src/main/java/com/example/playerdatasync/utils/SchedulerUtils.java create mode 100644 src/main/java/com/example/playerdatasync/utils/VersionCompatibility.java create mode 100644 src/main/resources/config.yml create mode 100644 src/main/resources/messages_de.yml create mode 100644 src/main/resources/messages_en.yml create mode 100644 src/main/resources/plugin.yml diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..dfe0770 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,2 @@ +# Auto detect text files and perform LF normalization +* text=auto diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..88e1548 --- /dev/null +++ b/.gitignore @@ -0,0 +1,123 @@ +# Maven +target/ +pom.xml.tag +pom.xml.releaseBackup +pom.xml.versionsBackup +pom.xml.next +release.properties +dependency-reduced-pom.xml +buildNumber.properties +.mvn/timing.properties +.mvn/wrapper/maven-wrapper.jar + +# Compiled class files +*.class + +# Log files +*.log + +# Package Files +*.jar +*.war +*.nar +*.ear +*.zip +*.tar.gz +*.rar + +# IDE - IntelliJ IDEA +.idea/ +*.iws +*.iml +*.ipr +out/ +.idea_modules/ + +# IDE - Eclipse +.classpath +.project +.settings/ +bin/ +.metadata + +# IDE - NetBeans +nbproject/private/ +build/ +nbbuild/ +dist/ +nbdist/ +.nb-gradle/ + +# IDE - VS Code +.vscode/ +*.code-workspace + +# OS files +.DS_Store +.DS_Store? +._* +.Spotlight-V100 +.Trashes +ehthumbs.db +Thumbs.db +*.swp +*.swo +*~ +.desktop.ini + +# Plugin specific +# Database files (SQLite) +*.db +*.db-journal +*.sqlite +*.sqlite3 + +# Configuration files with sensitive data +# Uncomment if you want to ignore config files with passwords +# config.yml +# database.yml + +# Logs directory +logs/ +server.log +latest.log + +# Temporary files +*.tmp +*.temp +*.bak +*.backup + +# Test output +test-output/ +coverage/ + +# Java +*.class +hs_err_pid* +replay_pid* + +# Minecraft server files (if testing locally) +server/ +world/ +world_nether/ +world_the_end/ +plugins/ +crash-reports/ +world-datapack/ +usercache.json +banned-players.json +banned-ips.json +ops.json +whitelist.json +eula.txt +server.properties +bukkit.yml +spigot.yml +paper.yml + +# Plugin development +# Keep config.yml and plugin.yml as examples, but ignore local config changes +# Uncomment if you want to ignore all config changes: +# src/main/resources/config.yml + diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..56f1dc3 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,922 @@ +# Changelog + +All notable changes to PlayerDataSync will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [1.2.9-RELEASE] - 2026-01-25 + +### 🎯 Custom-Enchantment-Support & Database Upgrade / Custom-Enchantment-Support & Datenbank-Upgrade + +### 🔧 Fixed + +- **Database Truncation Error (Critical Fix) / Datenbank-Truncation-Fehler (Critical Fix)**: + - **EN:** Fixes "Data too long for column" errors with large inventories + - **DE:** Behebt "Data too long for column" Fehler bei großen Inventaren + - ✅ **EN:** Automatic upgrade from `TEXT` to `LONGTEXT` for `inventory`, `enderchest`, `armor`, and `offhand` columns + - ✅ **DE:** Automatisches Upgrade von `TEXT` zu `LONGTEXT` für `inventory`, `enderchest`, `armor` und `offhand` Spalten + - ✅ **EN:** Now supports inventories with many custom enchantments (e.g., ExcellentEnchants) + - ✅ **DE:** Unterstützt jetzt Inventare mit vielen Custom-Enchantments (z.B. ExcellentEnchants) + - ✅ **EN:** Upgrade is performed automatically on server start + - ✅ **DE:** Upgrade wird automatisch beim Server-Start durchgeführt + - ✅ **EN:** Runtime upgrade attempt on truncation errors + - ✅ **DE:** Runtime-Upgrade-Versuch bei Truncation-Fehlern + - ✅ **EN:** Improved error messages with solution suggestions + - ✅ **DE:** Verbesserte Fehlermeldungen mit Lösungsvorschlägen + - 🔧 **EN:** Fixes issues with large inventories and custom enchantments + - 🔧 **DE:** Behebt Probleme mit großen Inventaren und Custom-Enchantments + +- **Custom-Enchantment Deserialization / Custom-Enchantment-Deserialisierung**: + - **EN:** Robust error handling for custom enchantments + - **DE:** Robuste Fehlerbehandlung für Custom-Enchantments + - ✅ **EN:** Improved detection of custom enchantment errors (e.g., `minecraft:venom`) + - ✅ **DE:** Verbesserte Erkennung von Custom-Enchantment-Fehlern (z.B. `minecraft:venom`) + - ✅ **EN:** Items are skipped instead of causing plugin crashes + - ✅ **DE:** Items werden übersprungen statt Plugin-Absturz zu verursachen + - ✅ **EN:** Data remains preserved in the database + - ✅ **DE:** Daten bleiben in der Datenbank erhalten + - ✅ **EN:** Detailed logging with enchantment names + - ✅ **DE:** Detailliertes Logging mit Enchantment-Namen + - ✅ **EN:** Support for ExcellentEnchants and similar plugins + - ✅ **DE:** Unterstützung für ExcellentEnchants und ähnliche Plugins + - 🔧 **EN:** Prevents crashes with unrecognized custom enchantments + - 🔧 **DE:** Verhindert Abstürze bei nicht erkannten Custom-Enchantments + +- **Stale Player Data / Veraltete Spielerdaten**: + - **EN:** Fixes issue with outdated player data + - **DE:** Behebt Problem mit nicht aktualisierten Spielerdaten + - ✅ **EN:** Database upgrade enables successful saves + - ✅ **DE:** Datenbank-Upgrade ermöglicht erfolgreiche Speicherungen + - ✅ **EN:** Improved error handling prevents data loss + - ✅ **DE:** Verbesserte Fehlerbehandlung verhindert Datenverlust + - ✅ **EN:** Automatic recovery after database upgrade + - ✅ **DE:** Automatische Wiederherstellung nach Datenbank-Upgrade + +### ✨ Added + +- **Custom-Enchantment Synchronization / Custom-Enchantment-Synchronisation**: + - **EN:** Full support for custom enchantments + - **DE:** Vollständige Unterstützung für Custom-Enchantments + - ✅ **EN:** Preservation of all NBT data including custom enchantments during serialization + - ✅ **DE:** Erhaltung aller NBT-Daten inklusive Custom-Enchantments beim Serialisieren + - ✅ **EN:** Refresh mechanism after loading inventories (2-tick delay) + - ✅ **DE:** Refresh-Mechanismus nach dem Laden von Inventaren (2-Tick-Delay) + - ✅ **EN:** Explicit re-setting of items so plugins can process enchantments + - ✅ **DE:** Explizites Neusetzen von Items, damit Plugins Enchantments verarbeiten können + - ✅ **EN:** Works for main inventory, armor, offhand, and enderchest + - ✅ **DE:** Funktioniert für Hauptinventar, Rüstung, Offhand und Enderchest + - 📝 **EN:** Supports plugins like ExcellentEnchants that use custom enchantments + - 📝 **DE:** Unterstützt Plugins wie ExcellentEnchants, die Custom-Enchantments verwenden + +- **Deserialization Statistics & Monitoring / Deserialisierungs-Statistiken & Monitoring**: + - **EN:** Comprehensive monitoring system + - **DE:** Umfassendes Monitoring-System + - ✅ **EN:** Counters for custom enchantment errors, version compatibility errors, and other errors + - ✅ **DE:** Zähler für Custom-Enchantment-Fehler, Versionskompatibilitäts-Fehler und andere Fehler + - ✅ **EN:** `getDeserializationStats()` method for statistics + - ✅ **DE:** `getDeserializationStats()` Methode für Statistiken + - ✅ **EN:** `resetDeserializationStats()` method to reset statistics + - ✅ **DE:** `resetDeserializationStats()` Methode zum Zurücksetzen + - ✅ **EN:** Integration into `/sync cache` command + - ✅ **DE:** Integration in `/sync cache` Befehl + - ✅ **EN:** Detailed error logging with enchantment names + - ✅ **DE:** Detaillierte Fehlerprotokollierung mit Enchantment-Namen + - 📝 **EN:** Admins can now easily monitor custom enchantment issues + - 📝 **DE:** Admins können jetzt Probleme mit Custom-Enchantments einfach überwachen + +- **Improved Error Handling / Verbesserte Fehlerbehandlung**: + - **EN:** Extended error detection and handling + - **DE:** Erweiterte Fehlererkennung und -behandlung + - ✅ **EN:** Automatic extraction of enchantment names from error messages + - ✅ **DE:** Automatische Extraktion von Enchantment-Namen aus Fehlermeldungen + - ✅ **EN:** Detailed error chain analysis (up to 3 levels) + - ✅ **DE:** Detaillierte Fehlerketten-Analyse (bis zu 3 Ebenen) + - ✅ **EN:** Contextual error messages with solution suggestions + - ✅ **DE:** Kontextuelle Fehlermeldungen mit Lösungsvorschlägen + - ✅ **EN:** Better detection of various error types (IllegalStateException, NullPointerException, etc.) + - ✅ **DE:** Bessere Erkennung verschiedener Fehlertypen (IllegalStateException, NullPointerException, etc.) + - ✅ **EN:** Pattern-based detection of custom enchantment errors + - ✅ **DE:** Pattern-basierte Erkennung von Custom-Enchantment-Fehlern + +### 🔄 Changed + +- **Database Schema / Datenbank-Schema**: + - **EN:** Automatic upgrade for existing installations + - **DE:** Automatisches Upgrade für bestehende Installationen + - ✅ **EN:** `inventory`: TEXT → LONGTEXT (max. ~4GB instead of ~65KB) + - ✅ **DE:** `inventory`: TEXT → LONGTEXT (max. ~4GB statt ~65KB) + - ✅ **EN:** `enderchest`: TEXT → LONGTEXT + - ✅ **DE:** `enderchest`: TEXT → LONGTEXT + - ✅ **EN:** `armor`: TEXT → LONGTEXT + - ✅ **DE:** `armor`: TEXT → LONGTEXT + - ✅ **EN:** `offhand`: TEXT → LONGTEXT + - ✅ **DE:** `offhand`: TEXT → LONGTEXT + - ✅ **EN:** Upgrade is performed automatically on server start + - ✅ **DE:** Upgrade wird beim Server-Start automatisch durchgeführt + - 📝 **EN:** Existing data is preserved, no data migration needed + - 📝 **DE:** Bestehende Daten bleiben erhalten, keine Datenmigration nötig + +- **EditorIntegration Removed / EditorIntegration entfernt**: + - **EN:** Preparation for website update + - **DE:** Vorbereitung für Website-Update + - ✅ **EN:** EditorIntegrationManager completely removed + - ✅ **DE:** EditorIntegrationManager komplett entfernt + - ✅ **EN:** All editor-related commands removed + - ✅ **DE:** Alle Editor-bezogenen Befehle entfernt + - ✅ **EN:** Code cleanup for future editor integration + - ✅ **DE:** Code-Bereinigung für zukünftige Editor-Integration + - 📝 **EN:** New editor integration will be added in a future version + - 📝 **DE:** Neue Editor-Integration wird in zukünftiger Version hinzugefügt + +### 📊 Technical Details + +#### Database Upgrade Process / Datenbank-Upgrade-Prozess + +**EN:** The plugin automatically performs an upgrade of database columns on startup: + +**DE:** Das Plugin führt beim Start automatisch ein Upgrade der Datenbank-Spalten durch: + +1. **EN:** **Check**: Verifies the current data type of each column + **DE:** **Prüfung**: Überprüft den aktuellen Datentyp jeder Spalte +2. **EN:** **Upgrade**: Converts `TEXT` to `LONGTEXT` if necessary + **DE:** **Upgrade**: Konvertiert `TEXT` zu `LONGTEXT` wenn nötig +3. **EN:** **Logging**: Logs all upgrades for transparency + **DE:** **Logging**: Protokolliert alle Upgrades für Transparenz +4. **EN:** **Runtime Upgrade**: Also attempts to upgrade during runtime if an error occurs + **DE:** **Runtime-Upgrade**: Versucht auch während des Betriebs zu upgraden, wenn ein Fehler auftritt + +**EN:** **Why LONGTEXT?** +**DE:** **Warum LONGTEXT?** +- `TEXT`: Max. ~65KB (65,535 bytes) +- `LONGTEXT`: Max. ~4GB (4,294,967,295 bytes) +- **EN:** Custom enchantments with extensive NBT data can become very large +- **DE:** Custom-Enchantments mit vielen NBT-Daten können sehr groß werden +- **EN:** Large inventories with many items and enchantments require more space +- **DE:** Große Inventare mit vielen Items und Enchantments benötigen mehr Platz + +#### Custom-Enchantment Error Handling / Custom-Enchantment-Fehlerbehandlung + +**EN:** The improved error handling recognizes various error types: + +**DE:** Die verbesserte Fehlerbehandlung erkennt verschiedene Fehlertypen: + +- **IllegalStateException** with DataResult/Codec/Decoder +- **NullPointerException** in enchantment-related classes +- **EN:** Error messages with "enchantment not found/unknown/invalid" +- **DE:** Fehlermeldungen mit "enchantment not found/unknown/invalid" +- **EN:** Pattern-based detection of custom enchantment names +- **DE:** Pattern-basierte Erkennung von Custom-Enchantment-Namen + +**EN:** **Error Handling Flow:** +**DE:** **Fehlerbehandlung-Flow:** +1. **EN:** Attempt normal deserialization + **DE:** Versuch der normalen Deserialisierung +2. **EN:** On error: Check if it's a custom enchantment problem + **DE:** Bei Fehler: Prüfung ob es ein Custom-Enchantment-Problem ist +3. **EN:** Extract enchantment name from error message + **DE:** Extraktion des Enchantment-Namens aus der Fehlermeldung +4. **EN:** Detailed logging with context + **DE:** Detailliertes Logging mit Kontext +5. **EN:** Item is skipped (null), but data remains in database + **DE:** Item wird übersprungen (null), aber Daten bleiben in DB +6. **EN:** Statistics are updated + **DE:** Statistiken werden aktualisiert + +#### Refresh Mechanism / Refresh-Mechanismus + +**EN:** After loading inventories, a refresh mechanism is executed: + +**DE:** Nach dem Laden von Inventaren wird ein Refresh-Mechanismus ausgeführt: + +1. **EN:** **Initial Load**: ItemStacks are loaded from database + **DE:** **Initiales Laden**: ItemStacks werden aus der Datenbank geladen +2. **EN:** **2-Tick Delay**: Waits 2 ticks to give plugins time to initialize + **DE:** **2-Tick-Delay**: Wartet 2 Ticks, damit Plugins Zeit haben zu initialisieren +3. **EN:** **Refresh**: Explicitly re-sets items to trigger plugin processing + **DE:** **Refresh**: Setzt Items explizit neu, um Plugin-Verarbeitung zu triggern +4. **EN:** **Update**: Calls `updateInventory()` for client synchronization + **DE:** **Update**: Ruft `updateInventory()` auf für Client-Synchronisation + +**EN:** **Why 2 Ticks?** +**DE:** **Warum 2 Ticks?** +- **EN:** Gives custom enchantment plugins time to register their enchantments +- **DE:** Gibt Custom-Enchantment-Plugins Zeit, ihre Enchantments zu registrieren +- **EN:** Enables plugin event handlers to react to item changes +- **DE:** Ermöglicht Plugin-Event-Handler, auf Item-Änderungen zu reagieren +- **EN:** Prevents race conditions between plugin loading and item loading +- **DE:** Verhindert Race-Conditions zwischen Plugin-Loading und Item-Loading + +#### Statistics System / Statistiken-System + +**EN:** The new statistics system collects information about deserialization errors: + +**DE:** Das neue Statistiken-System sammelt Informationen über Deserialisierungs-Fehler: + +- **EN:** **Custom Enchantment Errors**: Counts items skipped due to unrecognized custom enchantments +- **DE:** **Custom-Enchantment-Fehler**: Zählt Items, die wegen nicht erkannter Custom-Enchantments übersprungen wurden +- **EN:** **Version Compatibility Errors**: Counts items with version compatibility issues +- **DE:** **Versionskompatibilitäts-Fehler**: Zählt Items mit Versionskompatibilitätsproblemen +- **EN:** **Other Errors**: Counts all other deserialization errors +- **DE:** **Andere Fehler**: Zählt alle anderen Deserialisierungs-Fehler + +**EN:** **Usage:** +**DE:** **Verwendung:** +```bash +/sync cache # EN: Shows all statistics / DE: Zeigt alle Statistiken +/sync cache clear # EN: Resets statistics / DE: Setzt Statistiken zurück +``` + +### 🔍 Monitoring & Debugging + +**EN:** Admins can now easily monitor custom enchantment issues: + +**DE:** Admins können jetzt einfach Probleme mit Custom-Enchantments überwachen: + +1. **EN:** **View Statistics**: `/sync cache` shows deserialization statistics + **DE:** **Statistiken anzeigen**: `/sync cache` zeigt Deserialisierungs-Statistiken +2. **EN:** **Analyze Errors**: Detailed logs show exactly which enchantments cause problems + **DE:** **Fehler analysieren**: Detaillierte Logs zeigen genau, welche Enchantments Probleme verursachen +3. **EN:** **Fix Issues**: Clear error messages with solution suggestions + **DE:** **Probleme beheben**: Klare Fehlermeldungen mit Lösungsvorschlägen + +**EN:** **Example Output:** +**DE:** **Beispiel-Output:** +``` +Deserialization Stats: Deserialization failures: 5 total +(Custom Enchantments: 3, Version Issues: 1, Other: 1) +⚠ If you see custom enchantment failures, ensure enchantment plugins +(e.g., ExcellentEnchants) are loaded and all enchantments are registered. +``` + +### ⚠️ Important Notes / Wichtige Hinweise + +- **EN:** **Database Upgrade**: On first start after update, columns are automatically upgraded + **DE:** **Datenbank-Upgrade**: Beim ersten Start nach dem Update werden die Spalten automatisch geupgradet +- **EN:** **Custom Enchantments**: Ensure enchantment plugins (e.g., ExcellentEnchants) are installed and active on both servers + **DE:** **Custom-Enchantments**: Stellen Sie sicher, dass Enchantment-Plugins (z.B. ExcellentEnchants) auf beiden Servern installiert und aktiv sind +- **EN:** **Plugin Load Order**: Enchantment plugins should load before PlayerDataSync (check `plugin.yml`) + **DE:** **Plugin-Load-Reihenfolge**: Enchantment-Plugins sollten vor PlayerDataSync geladen werden (in `plugin.yml` prüfen) +- **EN:** **EditorIntegration**: EditorIntegration has been removed and will be re-implemented in a future version + **DE:** **EditorIntegration**: Die EditorIntegration wurde entfernt und wird in einer zukünftigen Version neu implementiert + +### 📝 Migration Guide + +**EN:** **For Existing Installations:** + +**DE:** **Für bestehende Installationen:** + +1. **EN:** **Automatic Upgrade**: No manual action needed - plugin performs upgrade automatically + **DE:** **Automatisches Upgrade**: Keine manuelle Aktion nötig - das Plugin führt das Upgrade automatisch durch +2. **EN:** **Restart Server**: Restart server after update to perform database upgrade + **DE:** **Server neu starten**: Nach dem Update den Server neu starten, damit das Datenbank-Upgrade durchgeführt wird +3. **EN:** **Check Logs**: Verify logs for upgrade messages: + **DE:** **Logs prüfen**: Überprüfen Sie die Logs auf Upgrade-Meldungen: + ``` + [INFO] Upgraded inventory column from TEXT to LONGTEXT to support large inventories + [INFO] Upgraded enderchest column from TEXT to LONGTEXT to support large inventories + [INFO] Upgraded armor column from TEXT to LONGTEXT to support large inventories + [INFO] Upgraded offhand column from TEXT to LONGTEXT to support large inventories + ``` +4. **EN:** **Check Custom Enchantments**: Ensure all enchantment plugins are loaded correctly + **DE:** **Custom-Enchantments prüfen**: Stellen Sie sicher, dass alle Enchantment-Plugins korrekt geladen sind + +**EN:** **Troubleshooting:** + +**DE:** **Bei Problemen:** + +- **EN:** Check `/sync cache` for deserialization statistics + **DE:** Prüfen Sie `/sync cache` für Deserialisierungs-Statistiken +- **EN:** Review logs for custom enchantment errors + **DE:** Überprüfen Sie die Logs auf Custom-Enchantment-Fehler +- **EN:** Ensure enchantment plugins are installed on both servers + **DE:** Stellen Sie sicher, dass Enchantment-Plugins auf beiden Servern installiert sind +- **EN:** Check plugin load order in `plugin.yml` + **DE:** Prüfen Sie die Plugin-Load-Reihenfolge in `plugin.yml` + +--- + +## [1.2.7-RELEASE] - 2025-12-29 + +### 🔧 Critical Fixes & New Features + +This release includes critical bug fixes for XP synchronization and Vault economy, plus a new Respawn to Lobby feature. + +### Fixed +- **Issue #45 - XP & Level Synchronization (Critical Fix)**: Complete rewrite of experience synchronization + - ✅ Replaced unreliable `setTotalExperience()` with `giveExp()` as primary method + - ✅ `giveExp()` is more reliable across all Minecraft versions (1.8-1.21.11) + - ✅ Better error handling and verification with detailed logging + - ✅ Automatic correction if experience doesn't match expected value + - ✅ Prevents XP sync failures on all supported versions + - ✅ Improved level calculation and synchronization + - 🔧 Fixes Issue #43, #45 and XP sync problems across version range + - 📝 Detailed logging for debugging XP sync issues +- **Issue #46 - Vault Balance de-sync on server shutdown**: Fixed economy balance not being saved during shutdown + - ✅ Enhanced shutdown save process to ensure Vault economy is available + - ✅ Reconfigure economy integration before shutdown save + - ✅ Added delay to ensure Vault is fully initialized before saving + - ✅ Force balance refresh before save to get latest balance + - ✅ Better error handling and logging during shutdown + - ✅ Prevents economy balance loss on server restart + - 🔧 Fixes Issue #46: Vault Balance de-sync on server shutdown + +### Added +- **Respawn to Lobby Feature**: New feature to send players to lobby server after death/respawn + - ✅ Automatically transfers players to lobby server after respawn + - ✅ Uses existing BungeeCord integration and shared database + - ✅ Configurable lobby server name + - ✅ Saves player data before transfer to ensure data consistency + - ✅ Smart detection to prevent transfers if already on lobby server + - ✅ Requires BungeeCord integration to be enabled + - 📝 Configuration: `respawn_to_lobby.enabled` and `respawn_to_lobby.server` in config.yml + +### Technical Details +- **XP Sync Method Change**: Switched from `setTotalExperience()` to `giveExp()` for better compatibility +- **Why**: `setTotalExperience()` has version-specific bugs, `giveExp()` works reliably everywhere +- **Verification**: Added automatic verification and correction mechanism +- **Logging**: Enhanced logging with before/after values for debugging +- **Shutdown Process**: Improved economy save process with Vault reconfiguration and balance refresh +- **Respawn Handler**: New `PlayerRespawnEvent` handler for lobby transfer functionality + +--- + +## [1.2.8-BETA] - 2025-12-29 + +### 🎉 Big Update - Major Improvements & API Migration + +This release includes significant improvements, API migrations, and enhanced compatibility features. + +### Fixed +- **XP Synchronization (Critical Fix)**: Complete rewrite of experience synchronization + - ✅ Replaced unreliable `setTotalExperience()` with `giveExp()` as primary method + - ✅ `giveExp()` is more reliable across all Minecraft versions (1.8-1.21.11) + - ✅ Better error handling and verification with detailed logging + - ✅ Automatic correction if experience doesn't match expected value + - ✅ Prevents XP sync failures on all supported versions + - 🔧 Fixes Issue #43, #45 and XP sync problems across version range + +### Changed +- **Update Checker**: Complete migration to CraftingStudio Pro API + - ✅ Migrated from SpigotMC Legacy API to CraftingStudio Pro API + - ✅ New API endpoint: `https://craftingstudiopro.de/api/plugins/playerdatasync/latest` + - ✅ Uses plugin slug (`playerdatasync`) instead of resource ID + - ✅ Improved JSON response parsing using Gson library + - ✅ Better error handling for HTTP status codes (429 Rate Limit, etc.) + - ✅ Enhanced update information with download URLs from API response + - 📖 API Documentation: https://www.craftingstudiopro.de/docs/api +- **Plugin API Version**: Updated to 1.13 for better modern API support + - Minimum required Minecraft version: 1.13 + - Still supports versions 1.8-1.21.11 with automatic compatibility handling + - Improved NamespacedKey support and modern Material API usage + +### Fixed +- **Version Compatibility**: Fixed critical GRAY_STAINED_GLASS_PANE compatibility issue + - ✅ Prevents fatal error on Minecraft 1.8-1.12 servers + - ✅ Automatic version detection and Material selection + - ✅ Uses `STAINED_GLASS_PANE` with durability value 7 for older versions (1.8-1.12) + - ✅ Uses `GRAY_STAINED_GLASS_PANE` for modern versions (1.13+) + - ✅ Filler item in inventory viewer now works correctly across all supported versions +- **Inventory Synchronization**: Enhanced inventory sync reliability + - ✅ Added `updateInventory()` calls after loading inventory, armor, and offhand + - ✅ Improved client synchronization for all inventory types + - ✅ Better inventory size validation (normalized to 36 slots for main inventory) + - ✅ Improved enderchest size validation (normalized to 27 slots) + - ✅ Better armor array normalization (ensures exactly 4 slots) +- **ItemStack Validation**: Enhanced ItemStack sanitization and validation + - ✅ Improved validation of item amounts (checks against max stack size) + - ✅ Better handling of invalid stack sizes (clamps to max instead of removing) + - ✅ Improved AIR item filtering + - ✅ More robust error handling for corrupted items +- **Logging System**: Complete logging overhaul + - ✅ Replaced all `System.err.println()` calls with proper Bukkit logger + - ✅ Replaced all `printStackTrace()` calls with proper `logger.log()` calls + - ✅ Better log levels (WARNING/SEVERE instead of stderr for compatibility issues) + - ✅ More consistent error messages across the codebase + - ✅ Stack traces now properly logged through plugin logger + - ✅ Improved logging for version compatibility issues + +### Improved +- **Code Quality**: Significant improvements to error handling and resource management + - ✅ Comprehensive exception handling with proper stack trace logging + - ✅ Better debug logging throughout inventory operations + - ✅ Improved client synchronization after inventory changes + - ✅ Better resource management and cleanup + - ✅ Enhanced error diagnostics throughout the codebase +- **Performance**: Optimizations for inventory operations + - ✅ Better item validation prevents unnecessary operations + - ✅ Improved error recovery mechanisms + - ✅ Enhanced memory management + +### Technical Details +- **API Migration**: Complete rewrite of UpdateChecker class + - Old: SpigotMC Legacy API (plain text response) + - New: CraftingStudio Pro API (JSON response with Gson parsing) + - Improved error handling for network issues and rate limits +- **Compatibility**: Maintained support for Minecraft 1.8-1.21.11 + - Version-based feature detection and automatic disabling + - Graceful degradation for unsupported features on older versions + - Comprehensive version compatibility checking at startup + +### Breaking Changes +⚠️ **Plugin API Version**: Changed from `1.8` to `1.13` +- Plugins compiled with this version require at least Minecraft 1.13 +- Server administrators using 1.8-1.12 should continue using previous versions +- Automatic legacy conversion may still work, but not guaranteed + +### Migration Guide +If upgrading from 1.2.6-RELEASE or earlier: +1. No configuration changes required +2. Update checker will now use CraftingStudio Pro API +3. All existing data is compatible +4. Recommended to test on a staging server first + +--- + +## [1.2.6-RELEASE] - 2025-12-29 + +### Changed +- **Update Checker**: Migrated to CraftingStudio Pro API + - Updated from SpigotMC API to CraftingStudio Pro API (https://craftingstudiopro.de/api) + - Now uses plugin slug instead of resource ID + - Improved JSON response parsing for better update information + - Better error handling for rate limits (429 responses) + - API endpoint: `/api/plugins/playerdatasync/latest` + +### Fixed +- **Version Compatibility**: Fixed GRAY_STAINED_GLASS_PANE compatibility issue for Minecraft 1.8-1.12 + - Added version check to use STAINED_GLASS_PANE with durability value 7 for older versions + - Prevents fatal error when loading plugin on 1.8-1.12 servers + - Filler item in inventory viewer now works correctly across all supported versions + +--- + +## [1.2.7-ALPHA] - 2025-12-29 + +### Changed +- **Update Checker**: Migrated to CraftingStudio Pro API + - Updated from SpigotMC API to CraftingStudio Pro API (https://craftingstudiopro.de/api) + - Now uses plugin slug instead of resource ID + - Improved JSON response parsing for better update information + - Better error handling for rate limits (429 responses) + - API endpoint: `/api/plugins/playerdatasync/latest` + +### Fixed +- **Version Compatibility**: Fixed GRAY_STAINED_GLASS_PANE compatibility issue for Minecraft 1.8-1.12 + - Added version check to use STAINED_GLASS_PANE with durability value 7 for older versions + - Prevents fatal error when loading plugin on 1.8-1.12 servers + - Filler item in inventory viewer now works correctly across all supported versions + +--- + +## [1.2.6-ALPHA] - 2025-12-29 + +### Improved +- **Inventory Synchronization**: Significantly improved inventory sync reliability + - Added `updateInventory()` call after loading inventory, armor, and offhand to ensure client synchronization + - Improved inventory size validation (normalized to 36 slots for main inventory) + - Improved enderchest size validation (normalized to 27 slots) + - Better armor array normalization (ensures exactly 4 slots) + - Enhanced error handling with detailed logging and stack traces + - Added debug logging for successful inventory loads +- **ItemStack Validation**: Enhanced ItemStack sanitization + - Improved validation of item amounts (checks against max stack size) + - Better handling of invalid stack sizes (clamps to max stack size instead of removing) + - Improved AIR item filtering + - More robust error handling for corrupted items +- **Logging System**: Improved logging consistency + - Replaced all `System.err.println()` calls with proper Bukkit logger + - Replaced all `printStackTrace()` calls with proper logger.log() calls + - Better log levels (WARNING instead of stderr for compatibility issues) + - More consistent error messages across the codebase + - Improved logging for version compatibility issues + - Stack traces now properly logged through plugin logger instead of printStackTrace() +- **Code Quality**: Further improvements to error handling + - Added comprehensive exception handling with stack traces + - Better debug logging throughout inventory operations + - Improved client synchronization after inventory changes + - Better resource management and cleanup + +### Fixed +- **Inventory Sync Issues**: Fixed cases where inventory changes weren't synchronized with client +- **ItemStack Validation**: Fixed potential issues with invalid item amounts and stack sizes +- **Logging**: Fixed inconsistent logging using System.err instead of proper logger + +--- + +## [1.2.5-SNAPSHOT] - 2025-12-29 + +### Fixed +- **Issue #45 - XP Sync Not Working**: Fixed experience synchronization not working + - Improved `applyExperience()` method with proper reset before setting experience + - Added verification to ensure experience is set correctly + - Added fallback mechanism using `giveExp()` if `setTotalExperience()` doesn't work + - Better error handling with detailed logging and stack traces + - Now works reliably across all Minecraft versions (1.8-1.21.11) + +### Improved +- **Code Quality**: Fixed deprecated method usage and improved compatibility + - Replaced deprecated `URL(String)` constructor with `URI.toURL()` for better Java 20+ compatibility + - Replaced deprecated `PotionEffectType.getName()` with `getKey().getKey()` for better compatibility + - Improved `PotionEffectType.getByName()` usage with NamespacedKey fallback + - Replaced deprecated `getMaxHealth()` with Attribute system where available + - Improved `getOfflinePlayer(String)` usage with better error handling + - Added `@SuppressWarnings` annotations for necessary deprecated method usage + - Cleaned up unused imports and improved code organization + +--- + +## [1.2.4-SNAPSHOT] - 2025-12-29 + +### Added +- **Extended Version Support**: Full compatibility with Minecraft 1.8 to 1.21.11 + - Comprehensive version detection and compatibility checking + - Maven build profiles for all major Minecraft versions (1.8, 1.9-1.16, 1.17, 1.18-1.20, 1.21+) + - Automatic feature detection and disabling based on server version + - VersionCompatibility utility class for runtime version checks +- **Project Structure Reorganization**: Complete package restructuring + - Organized code into logical packages: `core`, `database`, `integration`, `listeners`, `managers`, `utils`, `commands`, `api` + - Improved code maintainability and organization + - All imports and package declarations updated accordingly +- **Version-Based Feature Management**: Automatic feature disabling + - Offhand sync automatically disabled on 1.8 (requires 1.9+) + - Attribute sync automatically disabled on 1.8 (requires 1.9+) + - Advancement sync automatically disabled on 1.8-1.11 (requires 1.12+) + - Features are checked and disabled during plugin initialization + +### Fixed +- **Issue #43 - Experience Synchronization Error**: Fixed experience synchronization issues + - Initial fix for experience synchronization problems + - Added validation for negative experience values +- **Issue #42 - Vault Reset on Server Restart**: Fixed economy balance not being restored on server restart + - Economy integration is now reconfigured during shutdown to ensure availability + - Balance restoration with 5-tick delay and retry mechanism + - Improved Vault provider availability checking +- **Issue #41 - Potion Effect on Death**: Fixed potion effects being restored after death + - Effects are only restored if player is not dead or respawning + - Added death/respawn state checking before effect restoration + - Effects are properly cleared on death as expected +- **Issue #40 - Heartbeat HTTP 500**: Improved error handling for HTTP 500 errors + - Enhanced error handling with detailed logging + - Specific error messages for different HTTP status codes (400, 401, 404, 500+) + - Connection timeout and socket timeout handling + - Better debugging information for API issues + +### Changed +- **Minecraft Version Support**: Extended from 1.20.4-1.21.9 to 1.8-1.21.11 + - Default Java version set to 8 for maximum compatibility + - Maven profiles for different Java versions (8, 16, 17, 21) + - Plugin API version set to 1.8 (lowest supported version) +- **Build System**: Enhanced Maven configuration + - Compiler plugin now uses variables for source/target versions + - Multiple build profiles for different Minecraft versions + - Proper Java version handling per Minecraft version +- **Code Organization**: Complete package restructure + - `core/`: Main plugin class (PlayerDataSync) + - `database/`: Database management (DatabaseManager, ConnectionPool) + - `integration/`: Plugin integrations (EditorIntegrationManager, InventoryViewerIntegrationManager) + - `listeners/`: Event listeners (PlayerDataListener, ServerSwitchListener) + - `managers/`: Manager classes (AdvancementSyncManager, BackupManager, ConfigManager, MessageManager) + - `utils/`: Utility classes (InventoryUtils, OfflinePlayerData, PlayerDataCache, VersionCompatibility) + - `commands/`: Command handlers (SyncCommand) + - `api/`: API and update checker (UpdateChecker) +- **Version Compatibility Checking**: Enhanced startup version validation + - Detects Minecraft version range (1.8 to 1.21.11) + - Logs feature availability based on version + - Provides warnings for unsupported versions + - Tests critical API methods with version checks + +### Technical Details +- **Build Profiles**: + - `mvn package -Pmc-1.8` for Minecraft 1.8 (Java 8) + - `mvn package -Pmc-1.9` through `-Pmc-1.16` for 1.9-1.16 (Java 8) + - `mvn package -Pmc-1.17` for Minecraft 1.17 (Java 16) + - `mvn package -Pmc-1.18` through `-Pmc-1.20` for 1.18-1.20 (Java 17) + - `mvn package -Pmc-1.21` for Minecraft 1.21+ (Java 21) - Default +- **Code Quality**: Improved error handling and version compatibility +- **Resource Management**: Better cleanup and memory management +- **Exception Handling**: More specific error messages and recovery mechanisms + +### Compatibility +- **Minecraft 1.8**: Full support (some features disabled) +- **Minecraft 1.9-1.11**: Full support (advancements disabled) +- **Minecraft 1.12-1.16**: Full support +- **Minecraft 1.17**: Full support +- **Minecraft 1.18-1.20**: Full support +- **Minecraft 1.21-1.21.11**: Full support + +--- + +## [Unreleased] - 2025-01-14 + +### Fixed +- **API Server ID**: Fixed "Missing server_id" error in heartbeat and API requests + - Changed JSON field name from `"serverId"` (camelCase) to `"server_id"` (snake_case) in all API payloads + - Improved server_id resolution from config file with better fallback handling + - Added detailed logging to track which server_id source is being used + - Fixed server_id not being read correctly from `server.id` config option + - All API endpoints (heartbeat, token, snapshot) now correctly send server_id + +### Added +- **Message Configuration**: New option to disable sync messages + - Added `messages.show_sync_messages` config option (default: `true`) + - When set to `false`, all sync-related messages (loading, saving, server switch) are disabled + - Prevents empty messages from being sent when message strings are empty + - Works in conjunction with existing permission system + +### Changed +- **API Integration**: All JSON payloads now use snake_case for `server_id` field + - `buildHeartbeatPayload()`: Uses `"server_id"` instead of `"serverId"` + - `buildTokenPayload()`: Uses `"server_id"` instead of `"serverId"` + - `buildSnapshotPayload()`: Uses `"server_id"` instead of `"serverId"` +- **Server ID Resolution**: Enhanced resolution logic with better error handling + - Checks environment variables first, then system properties, then ConfigManager, then direct config + - Always ensures a valid server_id is returned (never null or empty) + - Added comprehensive logging for debugging server_id resolution + +### Configuration +- **New Settings**: + - `messages.show_sync_messages`: Control whether sync messages are shown to players (default: `true`) + +--- + +## [1.1.7-SNAPSHOT] - 2025-01-05 + +### Added +- **Extended Version Support**: Full compatibility with Minecraft 1.20.4 to 1.21.9 + - Comprehensive version detection and compatibility checking + - Maven build profiles for different Minecraft versions + - Enhanced startup version validation +- **Enhanced Message System**: Improved localization support + - Added parameter support to MessageManager (`get(String key, String... params)`) + - Support for both indexed (`{0}`, `{1}`) and named (`{version}`, `{error}`, `{url}`) placeholders + - Dynamic message content with variable substitution +- **Version Compatibility Fixes**: Robust ItemStack deserialization + - Safe deserialization methods (`safeItemStackArrayFromBase64`, `safeItemStackFromBase64`) + - Graceful handling of version-incompatible ItemStack data + - Individual item error handling to prevent complete deserialization failures + - Fallback mechanisms for corrupted or incompatible data +- **Enhanced Update Checker**: Improved console messaging + - Localized update checker messages in German and English + - Better error handling with specific error messages + - Configurable update checking with proper console feedback + - Dynamic content in update notifications (version numbers, URLs) + +### Changed +- **Java Version**: Upgraded from Java 17 to Java 21 for optimal performance +- **Minecraft Version**: Updated default target to Minecraft 1.21 +- **Plugin Metadata**: Enhanced plugin.yml with proper `authors` array and `load: STARTUP` +- **Version Compatibility**: Comprehensive support for 1.20.4 through 1.21.9 +- **Message Handling**: All hardcoded messages replaced with localized MessageManager calls +- **Error Recovery**: Better handling of version compatibility issues + +### Fixed +- **Critical Version Compatibility**: Fixed "Newer version! Server downgrades are not supported!" errors + - ItemStack deserialization now handles version mismatches gracefully + - Individual items that can't be deserialized are skipped instead of crashing + - Empty arrays returned as fallback for completely failed deserialization +- **MessageManager Compilation**: Fixed "Method get cannot be applied to given types" errors + - Added overloaded `get` method with parameter support + - Proper parameter replacement for dynamic content + - Backward compatibility with existing `get(String key)` method +- **Update Checker Messages**: Fixed missing console messages + - All update checker events now display proper localized messages + - Dynamic content (version numbers, URLs) properly integrated + - Better error reporting for different failure scenarios +- **Database Loading**: Enhanced error handling for corrupted inventory data + - Safe deserialization prevents server crashes from version issues + - Partial data recovery when some items are incompatible + - Better logging for version compatibility issues + +### Security +- **Data Validation**: Enhanced ItemStack validation and sanitization +- **Error Handling**: Graceful degradation for corrupted or incompatible data +- **Version Safety**: Protection against version-related crashes + +### Performance +- **Memory Efficiency**: Better handling of large ItemStack arrays +- **Error Recovery**: Faster recovery from deserialization failures +- **Resource Management**: Improved cleanup of failed operations + +### Compatibility +- **Minecraft 1.20.4**: Full support confirmed +- **Minecraft 1.20.5**: Full support confirmed +- **Minecraft 1.20.6**: Full support confirmed +- **Minecraft 1.21.0**: Full support confirmed +- **Minecraft 1.21.1**: Full support confirmed +- **Minecraft 1.21.2**: Full support confirmed +- **Minecraft 1.21.3**: Full support confirmed +- **Minecraft 1.21.4**: Full support confirmed +- **Minecraft 1.21.5**: Full support confirmed +- **Minecraft 1.21.6**: Full support confirmed +- **Minecraft 1.21.7**: Full support confirmed +- **Minecraft 1.21.8**: Full support confirmed +- **Minecraft 1.21.9**: Full support confirmed + +### Configuration +- **New Messages**: + - `loaded`: "Player data loaded successfully" / "Spielerdaten erfolgreich geladen" + - `load_failed`: "Failed to load player data" / "Fehler beim Laden der Spielerdaten" + - `update_check_disabled`: "Update checking is disabled" / "Update-Prüfung ist deaktiviert" + - `update_check_timeout`: "Update check timed out" / "Update-Prüfung ist abgelaufen" + - `update_check_no_internet`: "No internet connection for update check" / "Keine Internetverbindung für Update-Prüfung" + - `update_download_url`: "Download at: {url}" / "Download unter: {url}" + +### Commands +- **Enhanced Commands**: + - All commands now use localized messages with parameter support + - Better error reporting with dynamic content + - Improved user feedback for all operations + +### Technical Details +- **Build System**: Maven profiles for different Minecraft versions + - `mvn package -Pmc-1.20.4` for Minecraft 1.20.4 (Java 17) + - `mvn package -Pmc-1.21` for Minecraft 1.21 (Java 21) - Default + - `mvn package -Pmc-1.21.1` for Minecraft 1.21.1 (Java 21) +- **Code Quality**: Enhanced error handling and parameter validation +- **Resource Management**: Better cleanup and memory management +- **Exception Handling**: More specific error messages and recovery mechanisms +- **Debugging**: Enhanced diagnostic information and version compatibility logging + +--- + +### Added +- **Backup System**: Complete backup and restore functionality + - Automatic daily backups with configurable retention + - Manual backup creation via `/sync backup create` + - Backup restoration via `/sync restore [backup_id]` + - SQL dump generation for database backups + - ZIP compression for file backups + - Backup listing and management commands +- **Performance Caching**: In-memory player data cache + - Configurable cache size and TTL (Time-To-Live) + - LRU (Least Recently Used) eviction policy + - Optional compression for memory optimization + - Cache statistics and management via `/sync cache` +- **Enhanced Performance Monitoring** + - Detailed save/load time tracking + - Connection pool statistics + - Performance metrics logging + - Slow operation detection and warnings +- **Improved Update Checker** + - Configurable timeout settings + - Better error handling for network issues + - Download link in update notifications + - User-Agent header for API requests +- **Emergency Configuration System** + - Automatic config file creation if missing + - Fallback configuration generation + - Debug information for configuration issues + - Multi-layer configuration loading approach + +### Changed +- **Achievement Sync Limits**: Increased limits for Minecraft's 1000+ achievements + - `MAX_COUNT_ATTEMPTS`: 1000 → 2000 + - `MAX_ACHIEVEMENTS`: 1000 → 2000 + - `MAX_PROCESSED`: 2000 → 3000 + - Large amount warning threshold: 500 → 1500 +- **Database Performance**: Enhanced connection pooling + - Exponential backoff for connection acquisition + - Increased total timeout to 10 seconds + - Better connection pool exhaustion handling +- **Inventory Utilities**: Improved ItemStack handling + - Integrated sanitization and validation + - Better corruption data handling + - Enhanced Base64 serialization/deserialization +- **Configuration Management**: Robust config loading + - Multiple fallback mechanisms + - Emergency configuration creation + - Better error diagnostics + +### Fixed +- **Critical Achievement Bug**: Fixed infinite loop in achievement counting + - Added hard limits to prevent server freezes + - Implemented timeout-based processing + - Better error handling and logging +- **Database Parameter Error**: Fixed "No value specified for parameter 20" error + - Corrected SQL REPLACE INTO statement + - Added missing `advancements` and `server_id` parameters + - Fixed PreparedStatement parameter setting +- **Slow Save Detection**: Optimized achievement serialization + - Reduced processing time for large achievement counts + - Added performance monitoring + - Implemented batch processing with timeouts +- **Configuration Loading**: Fixed empty config.yml issue + - Added multiple fallback mechanisms + - Emergency configuration generation + - Better resource loading handling +- **Compilation Errors**: Fixed missing imports + - Added `java.io.File` and `java.io.FileWriter` imports + - Resolved Date ambiguity in BackupManager + - Fixed try-catch block nesting issues + +### Security +- **Enhanced Data Validation**: Improved ItemStack sanitization +- **Audit Logging**: Better security event tracking +- **Error Recovery**: Graceful handling of corrupted data + +### Performance +- **Memory Optimization**: Cache compression and TTL management +- **Database Efficiency**: Connection pooling and batch processing +- **Async Operations**: Non-blocking backup and save operations +- **Resource Management**: Better memory and connection cleanup + +### Compatibility +- **Minecraft 1.21.5**: Full support for Paper 1.21.5 +- **Legacy Support**: Maintained compatibility with 1.20.x +- **API Compatibility**: Proper handling of version differences +- **Database Compatibility**: Support for MySQL, SQLite, and PostgreSQL + +### Configuration +- **New Settings**: + - `performance.cache_ttl`: Cache time-to-live in milliseconds + - `performance.cache_compression`: Enable cache compression + - `update_checker.timeout`: Connection timeout for update checks + - `performance.max_achievements_per_player`: Increased to 2000 + - `server.id`: Unique server identifier for multi-server setups + +### Commands +- **New Commands**: + - `/sync backup create`: Create manual backup + - `/sync restore [backup_id]`: Restore from backup + - `/sync cache clear`: Clear performance statistics +- **Enhanced Commands**: + - `/sync cache`: Now shows performance and connection pool stats + - `/sync status`: Improved status reporting + - `/sync reload`: Better configuration reload handling + +### Technical Details +- **Code Quality**: Improved error handling and logging +- **Resource Management**: Better cleanup and memory management +- **Exception Handling**: More specific error messages and recovery +- **Debugging**: Enhanced diagnostic information and logging + +--- + +## [1.1.4] - 2024-12-XX + +### Added +- Initial release with basic player data synchronization +- MySQL and SQLite database support +- Basic configuration system +- Player event handling (join, quit, world change, death) +- Sync command with basic functionality + +### Features +- Coordinate synchronization +- Experience (XP) synchronization +- Gamemode synchronization +- Inventory synchronization +- Enderchest synchronization +- Armor synchronization +- Offhand synchronization +- Health and hunger synchronization +- Potion effects synchronization +- Achievements synchronization +- Statistics synchronization +- Attributes synchronization + +--- + +## [1.1.3] - 2024-12-XX + +### Fixed +- Various bug fixes and stability improvements +- Database connection handling improvements +- Better error messages and logging + +--- + +## [1.1.2] - 2024-12-XX + +### Fixed +- Configuration loading issues +- Database parameter errors +- Achievement sync problems + +--- + +## [1.1.1] - 2024-12-XX + +### Fixed +- Initial bug fixes and improvements +- Better error handling + +--- + +## [1.1.0] - 2024-12-XX + +### Added +- Initial stable release +- Core synchronization features +- Basic configuration system +- Database support + +--- + +## [1.0.0] - 2024-12-XX + +### Added +- Initial development release +- Basic plugin structure +- Core functionality implementation diff --git a/LICENSE b/LICENSE index ce59712..373aa79 100644 --- a/LICENSE +++ b/LICENSE @@ -1,18 +1,22 @@ MIT License -Copyright (c) 2026 DerGamer09 +Copyright (c) 2025 DerGamer009 -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and -associated documentation files (the "Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the -following conditions: +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in all copies or substantial -portions of the Software. +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT -LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO -EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE -USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/PREMIUM_INTEGRATION.md b/PREMIUM_INTEGRATION.md new file mode 100644 index 0000000..6e85bd1 --- /dev/null +++ b/PREMIUM_INTEGRATION.md @@ -0,0 +1,239 @@ +# PlayerDataSync Premium - Integration Guide + +## Übersicht / Overview + +Dieses Dokument beschreibt, wie die Premium-Komponenten (Lizenz-Validierung und Update-Check) in PlayerDataSync Premium integriert werden. + +This document describes how to integrate the premium components (license validation and update check) into PlayerDataSync Premium. + +## Komponenten / Components + +### 1. LicenseValidator +**Pfad / Path:** `com.example.playerdatasync.premium.api.LicenseValidator` + +**Funktion / Function:** +- Validiert Lizenzschlüssel gegen die CraftingStudio Pro API +- Validates license keys against the CraftingStudio Pro API +- Caching von Validierungsergebnissen (30 Minuten) +- Caches validation results (30 minutes) + +**API Endpoint:** +``` +POST https://craftingstudiopro.de/api/license/validate +Body: { "licenseKey": "YOUR-KEY", "pluginId": "playerdatasync-premium" } +Response: { "valid": boolean, "message": string, "purchase": {...} } +``` + +### 2. PremiumUpdateChecker +**Pfad / Path:** `com.example.playerdatasync.premium.api.PremiumUpdateChecker` + +**Funktion / Function:** +- Prüft auf Updates über die CraftingStudio Pro API +- Checks for updates via CraftingStudio Pro API +- Benachrichtigt OPs über verfügbare Updates +- Notifies OPs about available updates + +**API Endpoint:** +``` +GET https://craftingstudiopro.de/api/plugins/playerdatasync-premium/latest +Response: { "version": string, "downloadUrl": string, ... } +``` + +### 3. LicenseManager +**Pfad / Path:** `com.example.playerdatasync.premium.managers.LicenseManager` + +**Funktion / Function:** +- Verwaltet Lizenz-Validierung und Caching +- Manages license validation and caching +- Periodische Re-Validierung (alle 24 Stunden) +- Periodic re-validation (every 24 hours) +- Automatische Plugin-Deaktivierung bei ungültiger Lizenz +- Automatic plugin disabling on invalid license + +### 4. PremiumIntegration +**Pfad / Path:** `com.example.playerdatasync.premium.PremiumIntegration` + +**Funktion / Function:** +- Wrapper-Klasse für einfache Integration +- Wrapper class for easy integration +- Kombiniert LicenseManager und PremiumUpdateChecker +- Combines LicenseManager and PremiumUpdateChecker + +## Integration in Hauptklasse / Integration in Main Class + +### Beispiel / Example: + +```java +package com.example.playerdatasync.premium.core; + +import org.bukkit.plugin.java.JavaPlugin; +import com.example.playerdatasync.premium.PremiumIntegration; + +public class PlayerDataSyncPremium extends JavaPlugin { + private PremiumIntegration premiumIntegration; + + @Override + public void onEnable() { + getLogger().info("Enabling PlayerDataSync Premium..."); + + // Save default config + saveDefaultConfig(); + + // Initialize premium features (license validation) + premiumIntegration = new PremiumIntegration(this); + if (!premiumIntegration.initialize()) { + // License validation failed, plugin will be disabled + getLogger().severe("License validation failed. Plugin disabled."); + return; + } + + // Only continue if license is valid + if (!premiumIntegration.isLicenseValid()) { + getLogger().severe("Invalid license. Plugin disabled."); + getServer().getPluginManager().disablePlugin(this); + return; + } + + // ... rest of your plugin initialization ... + + getLogger().info("PlayerDataSync Premium enabled successfully!"); + } + + @Override + public void onDisable() { + getLogger().info("Disabling PlayerDataSync Premium..."); + + if (premiumIntegration != null) { + premiumIntegration.shutdown(); + } + + // ... rest of shutdown code ... + + getLogger().info("PlayerDataSync Premium disabled successfully"); + } + + public PremiumIntegration getPremiumIntegration() { + return premiumIntegration; + } +} +``` + +## Konfiguration / Configuration + +### config.yml Beispiel / Example: + +```yaml +# License Configuration +license: + key: YOUR-LICENSE-KEY-HERE # Your license key from CraftingStudio Pro + +# Update Checker +update_checker: + enabled: true + notify_ops: true + timeout: 10000 + +# Premium Features +premium: + revalidation_interval_hours: 24 + cache_validation: true + enable_premium_features: true +``` + +## API Verwendung / API Usage + +### Lizenz validieren / Validate License: + +```java +LicenseValidator validator = new LicenseValidator(plugin); + +// Asynchron +CompletableFuture future = + validator.validateLicenseAsync("YOUR-LICENSE-KEY"); + +future.thenAccept(result -> { + if (result.isValid()) { + // License is valid + PurchaseInfo purchase = result.getPurchase(); + // Use purchase information + } else { + // License is invalid + String message = result.getMessage(); + } +}); + +// Synchron (blockiert Thread) +LicenseValidationResult result = validator.validateLicense("YOUR-LICENSE-KEY"); +``` + +### Update prüfen / Check for Updates: + +```java +PremiumUpdateChecker updateChecker = new PremiumUpdateChecker(plugin); +updateChecker.check(); // Asynchron +``` + +### LicenseManager verwenden / Use LicenseManager: + +```java +LicenseManager licenseManager = new LicenseManager(plugin); +licenseManager.initialize(); // Validiert Lizenz beim Start + +// Prüfen ob Lizenz gültig ist +if (licenseManager.isLicenseValid()) { + // Plugin kann verwendet werden +} + +// Lizenz neu validieren +licenseManager.revalidateLicense(); + +// Neue Lizenz setzen +licenseManager.setLicenseKey("NEW-LICENSE-KEY"); +``` + +## Fehlerbehandlung / Error Handling + +### Rate Limiting: +Die API hat ein Rate Limit von 100 Requests pro Stunde pro IP. +The API has a rate limit of 100 requests per hour per IP. + +Bei Überschreitung wird ein `429 Too Many Requests` Status Code zurückgegeben. +On exceeding the limit, a `429 Too Many Requests` status code is returned. + +### Netzwerk-Fehler / Network Errors: +- `UnknownHostException`: Keine Internetverbindung / No internet connection +- `SocketTimeoutException`: Timeout beim Verbindungsaufbau / Connection timeout +- Alle Fehler werden geloggt / All errors are logged + +## Sicherheit / Security + +- **Lizenzschlüssel maskieren**: In Logs werden nur die ersten und letzten 4 Zeichen angezeigt +- **License key masking**: Only first and last 4 characters shown in logs +- **Caching**: Validierungsergebnisse werden 30 Minuten gecacht +- **Caching**: Validation results are cached for 30 minutes +- **Re-Validierung**: Automatische Re-Validierung alle 24 Stunden +- **Re-validation**: Automatic re-validation every 24 hours + +## Troubleshooting + +### Lizenz wird nicht akzeptiert / License not accepted: +1. Prüfen Sie den Lizenzschlüssel in `config.yml` +2. Check license key in `config.yml` +3. Stellen Sie sicher, dass die Lizenz für "playerdatasync-premium" gültig ist +4. Ensure license is valid for "playerdatasync-premium" +5. Prüfen Sie die Logs auf Fehlermeldungen +6. Check logs for error messages + +### Update-Check funktioniert nicht / Update check not working: +1. Prüfen Sie die Internetverbindung +2. Check internet connection +3. Prüfen Sie, ob `update_checker.enabled: true` in der Config ist +4. Check if `update_checker.enabled: true` in config +5. Prüfen Sie die Logs auf Rate-Limit-Fehler +6. Check logs for rate limit errors + +## API Dokumentation / API Documentation + +Vollständige API-Dokumentation: https://www.craftingstudiopro.de/docs/api + +Complete API documentation: https://www.craftingstudiopro.de/docs/api diff --git a/PREMIUM_README.md b/PREMIUM_README.md new file mode 100644 index 0000000..6bf5c70 --- /dev/null +++ b/PREMIUM_README.md @@ -0,0 +1,265 @@ +# PlayerDataSync Premium + +## Übersicht / Overview + +**EN:** PlayerDataSync Premium is the premium version of PlayerDataSync with license validation and additional features. +**DE:** PlayerDataSync Premium ist die Premium-Version von PlayerDataSync mit Lizenz-Validierung und zusätzlichen Features. + +## Features + +### ✅ License Validation / Lizenz-Validierung +- **EN:** Validates license keys against CraftingStudio Pro API +- **DE:** Validiert Lizenzschlüssel gegen CraftingStudio Pro API +- **EN:** Automatic license re-validation every 24 hours +- **DE:** Automatische Lizenz-Re-Validierung alle 24 Stunden +- **EN:** Caching to reduce API calls (30 minutes) +- **DE:** Caching zur Reduzierung von API-Aufrufen (30 Minuten) +- **EN:** Automatic plugin disabling on invalid license +- **DE:** Automatische Plugin-Deaktivierung bei ungültiger Lizenz + +### ✅ Update Checker / Update-Prüfung +- **EN:** Checks for updates using CraftingStudio Pro API +- **DE:** Prüft auf Updates über CraftingStudio Pro API +- **EN:** Notifies operators about available updates +- **DE:** Benachrichtigt Operatoren über verfügbare Updates +- **EN:** Rate limit handling (100 requests/hour) +- **DE:** Rate-Limit-Behandlung (100 Anfragen/Stunde) + +### ✅ Premium Features +- **EN:** All features from PlayerDataSync +- **DE:** Alle Features von PlayerDataSync +- **EN:** Enhanced support for custom enchantments (ExcellentEnchants, etc.) +- **DE:** Erweiterte Unterstützung für Custom-Enchantments (ExcellentEnchants, etc.) +- **EN:** Priority support +- **DE:** Prioritäts-Support + +## Installation / Installation + +### Requirements / Anforderungen + +- **EN:** Minecraft Server 1.8 - 1.21.11 +- **DE:** Minecraft Server 1.8 - 1.21.11 +- **EN:** Valid license key from CraftingStudio Pro +- **DE:** Gültiger Lizenzschlüssel von CraftingStudio Pro +- **EN:** Internet connection for license validation +- **DE:** Internetverbindung für Lizenz-Validierung + +### Setup / Einrichtung + +1. **EN:** Download PlayerDataSync Premium from CraftingStudio Pro + **DE:** Lade PlayerDataSync Premium von CraftingStudio Pro herunter + +2. **EN:** Place the JAR file in your `plugins` folder + **DE:** Platziere die JAR-Datei in deinem `plugins` Ordner + +3. **EN:** Start your server to generate the config file + **DE:** Starte deinen Server, um die Config-Datei zu generieren + +4. **EN:** Edit `plugins/PlayerDataSync-Premium/config.yml` and enter your license key: + **DE:** Bearbeite `plugins/PlayerDataSync-Premium/config.yml` und trage deinen Lizenzschlüssel ein: + +```yaml +license: + key: YOUR-LICENSE-KEY-HERE +``` + +5. **EN:** Restart your server + **DE:** Starte deinen Server neu + +## Configuration / Konfiguration + +### License Configuration / Lizenz-Konfiguration + +```yaml +license: + key: YOUR-LICENSE-KEY-HERE # Your license key from CraftingStudio Pro +``` + +### Update Checker Configuration / Update-Checker-Konfiguration + +```yaml +update_checker: + enabled: true # Enable automatic update checking + notify_ops: true # Notify operators when updates are available + timeout: 10000 # Timeout in milliseconds +``` + +### Premium Features Configuration / Premium-Features-Konfiguration + +```yaml +premium: + revalidation_interval_hours: 24 # Revalidate license every 24 hours + cache_validation: true # Cache validation results + enable_premium_features: true # Enable premium-specific features +``` + +## API Integration / API-Integration + +### License Validation / Lizenz-Validierung + +**Endpoint:** +``` +POST https://craftingstudiopro.de/api/license/validate +``` + +**Request Body:** +```json +{ + "licenseKey": "YOUR-LICENSE-KEY", + "pluginId": "playerdatasync-premium" +} +``` + +**Response:** +```json +{ + "valid": true, + "message": "License is valid", + "purchase": { + "id": "purchase-id", + "userId": "user-id", + "pluginId": "playerdatasync-premium", + "createdAt": "2025-01-01T00:00:00Z" + } +} +``` + +### Update Check / Update-Prüfung + +**Endpoint:** +``` +GET https://craftingstudiopro.de/api/plugins/playerdatasync-premium/latest +``` + +**Response:** +```json +{ + "version": "1.2.9-RELEASE", + "downloadUrl": "https://...", + "createdAt": "2025-01-01T00:00:00Z", + "title": "Release 1.2.9", + "releaseType": "release", + "pluginTitle": "PlayerDataSync Premium", + "pluginSlug": "playerdatasync-premium" +} +``` + +## Rate Limits / Rate-Limits + +**EN:** The API has a rate limit of 100 requests per hour per IP address. +**DE:** Die API hat ein Rate Limit von 100 Anfragen pro Stunde pro IP-Adresse. + +**EN:** If you exceed the limit, you will receive a `429 Too Many Requests` status code. +**DE:** Bei Überschreitung erhalten Sie einen `429 Too Many Requests` Status Code. + +**EN:** The plugin uses caching to minimize API calls: +- License validation: Cached for 30 minutes +- Update checks: Performed on server start and can be triggered manually + +**DE:** Das Plugin verwendet Caching zur Minimierung von API-Aufrufen: +- Lizenz-Validierung: 30 Minuten gecacht +- Update-Prüfungen: Beim Server-Start und manuell auslösbar + +## Troubleshooting / Fehlerbehebung + +### License Validation Failed / Lizenz-Validierung fehlgeschlagen + +**EN:** **Problem:** License validation fails on startup +**DE:** **Problem:** Lizenz-Validierung schlägt beim Start fehl + +**EN:** **Solutions:** +1. Check your license key in `config.yml` +2. Ensure the license is valid for "playerdatasync-premium" +3. Check your internet connection +4. Verify the license hasn't expired +5. Check server logs for detailed error messages + +**DE:** **Lösungen:** +1. Prüfe deinen Lizenzschlüssel in `config.yml` +2. Stelle sicher, dass die Lizenz für "playerdatasync-premium" gültig ist +3. Prüfe deine Internetverbindung +4. Verifiziere, dass die Lizenz nicht abgelaufen ist +5. Prüfe die Server-Logs für detaillierte Fehlermeldungen + +### Update Check Not Working / Update-Prüfung funktioniert nicht + +**EN:** **Problem:** Update checker doesn't find updates +**DE:** **Problem:** Update-Checker findet keine Updates + +**EN:** **Solutions:** +1. Check `update_checker.enabled: true` in config +2. Verify internet connection +3. Check logs for rate limit errors +4. Manually trigger update check: `/sync update` + +**DE:** **Lösungen:** +1. Prüfe `update_checker.enabled: true` in der Config +2. Verifiziere Internetverbindung +3. Prüfe Logs auf Rate-Limit-Fehler +4. Manuell Update-Prüfung auslösen: `/sync update` + +### Plugin Disables Itself / Plugin deaktiviert sich selbst + +**EN:** **Problem:** Plugin disables itself after 30 seconds +**DE:** **Problem:** Plugin deaktiviert sich nach 30 Sekunden + +**EN:** **Cause:** License validation failed or license is invalid +**DE:** **Ursache:** Lizenz-Validierung fehlgeschlagen oder Lizenz ist ungültig + +**EN:** **Solutions:** +1. Check license key in config +2. Verify license is valid on CraftingStudio Pro +3. Check server logs for validation errors +4. Contact support if license should be valid + +**DE:** **Lösungen:** +1. Prüfe Lizenzschlüssel in der Config +2. Verifiziere, dass die Lizenz auf CraftingStudio Pro gültig ist +3. Prüfe Server-Logs auf Validierungsfehler +4. Kontaktiere Support, wenn die Lizenz gültig sein sollte + +## Commands / Befehle + +### `/sync license validate` +**EN:** Manually validate license key +**DE:** Lizenzschlüssel manuell validieren + +**Permission:** `playerdatasync.premium.admin` + +### `/sync license info` +**EN:** Show license information (masked) +**DE:** Zeige Lizenzinformationen (maskiert) + +**Permission:** `playerdatasync.premium.admin` + +### `/sync update check` +**EN:** Manually check for updates +**DE:** Manuell auf Updates prüfen + +**Permission:** `playerdatasync.premium.admin` + +## Support / Support + +**EN:** For support, please visit: +- Website: https://craftingstudiopro.de +- Discord: [Join our Discord](https://discord.gg/...) +- Documentation: https://www.craftingstudiopro.de/docs/api + +**DE:** Für Support besuche bitte: +- Website: https://craftingstudiopro.de +- Discord: [Tritt unserem Discord bei](https://discord.gg/...) +- Dokumentation: https://www.craftingstudiopro.de/docs/api + +## License / Lizenz + +**EN:** PlayerDataSync Premium requires a valid license key from CraftingStudio Pro. +**DE:** PlayerDataSync Premium benötigt einen gültigen Lizenzschlüssel von CraftingStudio Pro. + +**EN:** Without a valid license, the plugin will disable itself after 30 seconds. +**DE:** Ohne gültige Lizenz deaktiviert sich das Plugin nach 30 Sekunden. + +## Changelog / Änderungsprotokoll + +See [CHANGELOG.md](CHANGELOG.md) for version history. + +Siehe [CHANGELOG.md](CHANGELOG.md) für Versionshistorie. diff --git a/PlayerDataSync-Premium/premium/.gitignore b/PlayerDataSync-Premium/premium/.gitignore new file mode 100644 index 0000000..596670e --- /dev/null +++ b/PlayerDataSync-Premium/premium/.gitignore @@ -0,0 +1,16 @@ +target/ +*.class +*.jar +*.war +*.ear +*.log +.idea/ +*.iml +.vscode/ +.settings/ +.classpath +.project +.DS_Store +*.swp +*.swo +*~ diff --git a/PlayerDataSync-Premium/premium/PLUGIN_DESCRIPTION.md b/PlayerDataSync-Premium/premium/PLUGIN_DESCRIPTION.md new file mode 100644 index 0000000..fc45f45 --- /dev/null +++ b/PlayerDataSync-Premium/premium/PLUGIN_DESCRIPTION.md @@ -0,0 +1,199 @@ +# PlayerDataSync Premium - Plugin Beschreibung + +## Kurzbeschreibung / Short Description + +**DE:** Premium-Version von PlayerDataSync mit Lizenz-Validierung, automatischen Updates und erweitertem Support für Custom-Enchantments. Synchronisiert Spielerdaten zwischen Servern über MySQL/SQLite. + +**EN:** Premium version of PlayerDataSync with license validation, automatic updates, and enhanced support for custom enchantments. Synchronizes player data between servers via MySQL/SQLite. + +--- + +## Beschreibung / Description + +### Deutsch + +**PlayerDataSync Premium** ist die Premium-Version des beliebten PlayerDataSync-Plugins für Minecraft-Server. Es bietet alle Features der Standard-Version plus erweiterte Funktionen für professionelle Server-Netzwerke. + +#### Hauptfunktionen: + +**✅ Vollständige Spielerdaten-Synchronisation** +- Inventar, Rüstung, Offhand und Enderkiste +- Gesundheit, Hunger und Sättigung +- Erfahrungspunkte und Level +- Spielmodus und Position +- Tränkeffekte und Attribute +- Statistiken und Erfolge/Advancements +- Economy-Balance (Vault-Integration) + +**✅ Premium-Features** +- **Lizenz-Validierung:** Automatische Validierung über CraftingStudio Pro API +- **Automatische Updates:** Update-Benachrichtigungen und -Prüfung +- **Erweiterte Custom-Enchantment-Unterstützung:** Optimiert für ExcellentEnchants und andere Custom-Enchantment-Plugins +- **Prioritäts-Support:** Schnellerer Support für Premium-Nutzer + +**✅ Datenbank-Unterstützung** +- MySQL/MariaDB für Multi-Server-Netzwerke +- SQLite für Single-Server-Installationen +- Automatische Datenbank-Upgrades (TEXT → LONGTEXT) +- Connection Pooling für bessere Performance + +**✅ Erweiterte Features** +- BungeeCord/Velocity-Integration +- InvSee/OpenInv-Integration für Offline-Spieler +- Automatische Backups +- Performance-Monitoring +- Umfassende Fehlerbehandlung + +**✅ Kompatibilität** +- Minecraft 1.8 - 1.21.11 +- Cross-Version-Kompatibilität +- Automatische Feature-Erkennung basierend auf Server-Version + +#### Technische Details: + +- **Lizenz-Validierung:** Über CraftingStudio Pro API mit 30-Minuten-Caching +- **Update-Checks:** Automatisch beim Server-Start und manuell via `/sync update check` +- **Rate Limits:** 100 API-Requests pro Stunde (automatisch verwaltet) +- **Datenbank-Upgrades:** Automatische Migration von TEXT zu LONGTEXT für große Inventare + +#### Installation: + +1. JAR-Datei in den `plugins` Ordner kopieren +2. Server starten (Config wird generiert) +3. Lizenzschlüssel in `config.yml` eintragen +4. Server neu starten + +#### Support: + +- Website: https://craftingstudiopro.de +- API-Dokumentation: https://www.craftingstudiopro.de/docs/api +- Discord: [Join our Discord](https://discord.gg/...) + +--- + +### English + +**PlayerDataSync Premium** is the premium version of the popular PlayerDataSync plugin for Minecraft servers. It offers all features from the standard version plus advanced functionality for professional server networks. + +#### Main Features: + +**✅ Complete Player Data Synchronization** +- Inventory, armor, offhand, and ender chest +- Health, hunger, and saturation +- Experience points and levels +- Gamemode and position +- Potion effects and attributes +- Statistics and advancements +- Economy balance (Vault integration) + +**✅ Premium Features** +- **License Validation:** Automatic validation via CraftingStudio Pro API +- **Automatic Updates:** Update notifications and checking +- **Enhanced Custom Enchantment Support:** Optimized for ExcellentEnchants and other custom enchantment plugins +- **Priority Support:** Faster support for premium users + +**✅ Database Support** +- MySQL/MariaDB for multi-server networks +- SQLite for single-server installations +- Automatic database upgrades (TEXT → LONGTEXT) +- Connection pooling for better performance + +**✅ Advanced Features** +- BungeeCord/Velocity integration +- InvSee/OpenInv integration for offline players +- Automatic backups +- Performance monitoring +- Comprehensive error handling + +**✅ Compatibility** +- Minecraft 1.8 - 1.21.11 +- Cross-version compatibility +- Automatic feature detection based on server version + +#### Technical Details: + +- **License Validation:** Via CraftingStudio Pro API with 30-minute caching +- **Update Checks:** Automatically on server start and manually via `/sync update check` +- **Rate Limits:** 100 API requests per hour (automatically managed) +- **Database Upgrades:** Automatic migration from TEXT to LONGTEXT for large inventories + +#### Installation: + +1. Copy JAR file to `plugins` folder +2. Start server (config will be generated) +3. Enter license key in `config.yml` +4. Restart server + +#### Support: + +- Website: https://craftingstudiopro.de +- API Documentation: https://www.craftingstudiopro.de/docs/api +- Discord: [Join our Discord](https://discord.gg/...) + +--- + +## Tags / Schlagwörter + +### Deutsch +- `player-data-sync` +- `premium` +- `multi-server` +- `bungeecord` +- `velocity` +- `inventory-sync` +- `data-synchronization` +- `mysql` +- `sqlite` +- `custom-enchantments` +- `excellentenchants` +- `vault` +- `economy-sync` +- `backup` +- `cross-server` +- `network` +- `spigot` +- `paper` +- `bukkit` +- `minecraft-plugin` + +### English +- `player-data-sync` +- `premium` +- `multi-server` +- `bungeecord` +- `velocity` +- `inventory-sync` +- `data-synchronization` +- `mysql` +- `sqlite` +- `custom-enchantments` +- `excellentenchants` +- `vault` +- `economy-sync` +- `backup` +- `cross-server` +- `network` +- `spigot` +- `paper` +- `bukkit` +- `minecraft-plugin` + +--- + +## Für CraftingStudio Pro / For CraftingStudio Pro + +### Kurzbeschreibung (Max. 200 Zeichen) + +**DE:** Premium-Version von PlayerDataSync mit Lizenz-Validierung, automatischen Updates und erweitertem Support für Custom-Enchantments. Synchronisiert Spielerdaten zwischen Servern. + +**EN:** Premium version of PlayerDataSync with license validation, automatic updates, and enhanced support for custom enchantments. Synchronizes player data between servers. + +### Beschreibung (Vollständig) + +Siehe oben / See above + +### Tags (Komma-getrennt) + +``` +player-data-sync, premium, multi-server, bungeecord, velocity, inventory-sync, data-synchronization, mysql, sqlite, custom-enchantments, excellentenchants, vault, economy-sync, backup, cross-server, network, spigot, paper, bukkit, minecraft-plugin +``` diff --git a/PlayerDataSync-Premium/premium/README.md b/PlayerDataSync-Premium/premium/README.md new file mode 100644 index 0000000..5ceb0ff --- /dev/null +++ b/PlayerDataSync-Premium/premium/README.md @@ -0,0 +1,109 @@ +# PlayerDataSync Premium + +## Übersicht / Overview + +**EN:** PlayerDataSync Premium is the premium version of PlayerDataSync with license validation, automatic update checking, and enhanced features for custom enchantments. +**DE:** PlayerDataSync Premium ist die Premium-Version von PlayerDataSync mit Lizenz-Validierung, automatischer Update-Prüfung und erweiterten Features für Custom-Enchantments. + +## Features + +### ✅ License Validation / Lizenz-Validierung +- **EN:** Validates license keys against CraftingStudio Pro API +- **DE:** Validiert Lizenzschlüssel gegen CraftingStudio Pro API +- **EN:** Automatic license re-validation every 24 hours +- **DE:** Automatische Lizenz-Re-Validierung alle 24 Stunden +- **EN:** Caching to reduce API calls (30 minutes) +- **DE:** Caching zur Reduzierung von API-Aufrufen (30 Minuten) +- **EN:** Automatic plugin disabling on invalid license +- **DE:** Automatische Plugin-Deaktivierung bei ungültiger Lizenz + +### ✅ Update Checker / Update-Prüfung +- **EN:** Checks for updates using CraftingStudio Pro API +- **DE:** Prüft auf Updates über CraftingStudio Pro API +- **EN:** Notifies operators about available updates +- **DE:** Benachrichtigt Operatoren über verfügbare Updates +- **EN:** Rate limit handling (100 requests/hour) +- **DE:** Rate-Limit-Behandlung (100 Anfragen/Stunde) + +### ✅ Premium Features +- **EN:** All features from PlayerDataSync +- **DE:** Alle Features von PlayerDataSync +- **EN:** Enhanced support for custom enchantments (ExcellentEnchants, etc.) +- **DE:** Erweiterte Unterstützung für Custom-Enchantments (ExcellentEnchants, etc.) +- **EN:** Priority support +- **DE:** Prioritäts-Support + +## Installation + +1. **EN:** Download PlayerDataSync Premium from CraftingStudio Pro + **DE:** Lade PlayerDataSync Premium von CraftingStudio Pro herunter + +2. **EN:** Place the JAR file in your `plugins` folder + **DE:** Platziere die JAR-Datei in deinem `plugins` Ordner + +3. **EN:** Start your server to generate the config file + **DE:** Starte deinen Server, um die Config-Datei zu generieren + +4. **EN:** Edit `plugins/PlayerDataSync-Premium/config.yml` and enter your license key: + **DE:** Bearbeite `plugins/PlayerDataSync-Premium/config.yml` und trage deinen Lizenzschlüssel ein: + +```yaml +license: + key: YOUR-LICENSE-KEY-HERE +``` + +5. **EN:** Restart your server + **DE:** Starte deinen Server neu + +## API Integration + +### License Validation + +**Endpoint:** `POST https://craftingstudiopro.de/api/license/validate` + +**Request:** +```json +{ + "licenseKey": "YOUR-LICENSE-KEY", + "pluginId": "playerdatasync-premium" +} +``` + +**Response:** +```json +{ + "valid": true, + "message": "License is valid", + "purchase": { + "id": "purchase-id", + "userId": "user-id", + "pluginId": "playerdatasync-premium", + "createdAt": "2025-01-01T00:00:00Z" + } +} +``` + +### Update Check + +**Endpoint:** `GET https://craftingstudiopro.de/api/plugins/playerdatasync-premium/latest` + +**Response:** +```json +{ + "version": "1.2.9-PREMIUM", + "downloadUrl": "https://...", + "pluginTitle": "PlayerDataSync Premium", + "pluginSlug": "playerdatasync-premium" +} +``` + +## Commands + +- `/sync license validate` - Manually validate license key +- `/sync license info` - Show license information (masked) +- `/sync update check` - Manually check for updates + +## Support + +- Website: https://craftingstudiopro.de +- API Documentation: https://www.craftingstudiopro.de/docs/api diff --git a/PlayerDataSync-Premium/premium/SETUP.md b/PlayerDataSync-Premium/premium/SETUP.md new file mode 100644 index 0000000..79191de --- /dev/null +++ b/PlayerDataSync-Premium/premium/SETUP.md @@ -0,0 +1,121 @@ +# PlayerDataSync Premium - Setup Anleitung + +## Projektstruktur + +Die Premium-Version benötigt alle Klassen aus PlayerDataSync, aber mit angepassten Package-Namen: + +### Package-Mapping + +**Von:** `com.example.playerdatasync.*` +**Zu:** `com.example.playerdatasync.premium.*` + +### Zu kopierende Klassen + +Alle folgenden Klassen müssen aus `PlayerDataSync/src/main/java/com/example/playerdatasync/` nach `PlayerDataSync-Premium/premium/src/main/java/com/example/playerdatasync/premium/` kopiert und Package-Namen angepasst werden: + +#### Core +- `core/PlayerDataSync.java` → `premium/core/PlayerDataSyncPremium.java` ✅ (bereits erstellt) + +#### Database +- `database/ConnectionPool.java` → `premium/database/ConnectionPool.java` +- `database/DatabaseManager.java` → `premium/database/DatabaseManager.java` + +#### Commands +- `commands/SyncCommand.java` → `premium/commands/SyncCommand.java` + - Premium-Befehle hinzufügen: `/sync license validate`, `/sync license info`, `/sync update check` + +#### Listeners +- `listeners/PlayerDataListener.java` → `premium/listeners/PlayerDataListener.java` +- `listeners/ServerSwitchListener.java` → `premium/listeners/ServerSwitchListener.java` + +#### Managers +- `managers/AdvancementSyncManager.java` → `premium/managers/AdvancementSyncManager.java` +- `managers/BackupManager.java` → `premium/managers/BackupManager.java` +- `managers/ConfigManager.java` → `premium/managers/ConfigManager.java` +- `managers/MessageManager.java` → `premium/managers/MessageManager.java` +- `managers/LicenseManager.java` → `premium/managers/LicenseManager.java` ✅ (bereits erstellt) + +#### Integration +- `integration/InventoryViewerIntegrationManager.java` → `premium/integration/InventoryViewerIntegrationManager.java` + +#### Utils +- `utils/InventoryUtils.java` → `premium/utils/InventoryUtils.java` +- `utils/OfflinePlayerData.java` → `premium/utils/OfflinePlayerData.java` +- `utils/PlayerDataCache.java` → `premium/utils/PlayerDataCache.java` +- `utils/VersionCompatibility.java` → `premium/utils/VersionCompatibility.java` + +#### API +- `api/PremiumUpdateChecker.java` → `premium/api/PremiumUpdateChecker.java` ✅ (bereits erstellt) +- `api/LicenseValidator.java` → `premium/api/LicenseValidator.java` ✅ (bereits erstellt) + +### Resources + +- `resources/config.yml` → `premium/src/main/resources/config.yml` ✅ (bereits erstellt) +- `resources/plugin.yml` → `premium/src/main/resources/plugin.yml` ✅ (bereits erstellt) +- `resources/messages_en.yml` → `premium/src/main/resources/messages_en.yml` +- `resources/messages_de.yml` → `premium/src/main/resources/messages_de.yml` + +## Anpassungen + +### 1. Package-Namen ändern + +Alle Klassen müssen von: +```java +package com.example.playerdatasync.xxx; +``` + +zu: +```java +package com.example.playerdatasync.premium.xxx; +``` + +### 2. Imports anpassen + +Alle Imports müssen angepasst werden: +```java +// Alt +import com.example.playerdatasync.database.DatabaseManager; + +// Neu +import com.example.playerdatasync.premium.database.DatabaseManager; +``` + +### 3. SyncCommand erweitern + +In `SyncCommand.java` müssen Premium-Befehle hinzugefügt werden: + +```java +case "license": + return handleLicense(sender, args); + +case "update": + return handleUpdate(sender, args); +``` + +### 4. PlayerDataSyncPremium.java vervollständigen + +Die Hauptklasse `PlayerDataSyncPremium.java` ist bereits erstellt, aber alle Methoden aus der originalen `PlayerDataSync.java` müssen kopiert werden. + +## Build + +```bash +cd PlayerDataSync-Premium/premium +mvn clean package +``` + +Die JAR-Datei wird in `target/PlayerDataSync-Premium-1.2.9-PREMIUM.jar` erstellt. + +## Wichtige Hinweise + +1. **License Key erforderlich**: Die Premium-Version funktioniert nur mit einem gültigen Lizenzschlüssel +2. **API-Zugriff**: Benötigt Internetverbindung für Lizenz-Validierung und Update-Checks +3. **Rate Limits**: API hat ein Limit von 100 Requests/Stunde pro IP +4. **Caching**: Lizenz-Validierung wird 30 Minuten gecacht + +## Nächste Schritte + +1. Alle Klassen aus PlayerDataSync kopieren +2. Package-Namen anpassen +3. Imports anpassen +4. Premium-Befehle in SyncCommand hinzufügen +5. Build und Test diff --git a/PlayerDataSync-Premium/premium/pom.xml b/PlayerDataSync-Premium/premium/pom.xml new file mode 100644 index 0000000..97f7a89 --- /dev/null +++ b/PlayerDataSync-Premium/premium/pom.xml @@ -0,0 +1,381 @@ + + 4.0.0 + com.example + PlayerDataSync-Premium + 1.0.0-PREMIUM + jar + + + UTF-8 + 1.21 + 8 + 8 + 8 + + + + + spigot-repo + https://hub.spigotmc.org/nexus/content/repositories/snapshots/ + + + jitpack.io + https://jitpack.io + + + placeholderapi + https://repo.extendedclip.com/content/repositories/placeholderapi/ + + + luck-repo + https://repo.lucko.me/ + + + + + + + org.spigotmc + spigot-api + ${minecraft.version}-R0.1-SNAPSHOT + provided + + + + + com.mysql + mysql-connector-j + 8.2.0 + compile + + + org.xerial + sqlite-jdbc + 3.44.1.0 + compile + + + org.postgresql + postgresql + 42.7.1 + compile + + + + + com.zaxxer + HikariCP + 5.1.0 + compile + + + + + org.bstats + bstats-bukkit + 3.0.2 + compile + + + + + net.milkbowl.vault + VaultAPI + 1.7 + provided + + + me.clip + placeholderapi + 2.11.5 + provided + + + net.luckperms + api + 5.4 + provided + + + + + com.google.code.gson + gson + 2.10.1 + compile + + + + + org.apache.commons + commons-compress + 1.25.0 + compile + + + + + org.apache.commons + commons-lang3 + 3.14.0 + compile + + + + + junit + junit + 4.13.2 + test + + + org.mockito + mockito-core + 5.8.0 + test + + + + + + + mc-1.8 + + 1.8.8 + 8 + 8 + 8 + + + + + + mc-1.9 + + 1.9.4 + 8 + 8 + 8 + + + + + mc-1.10 + + 1.10.2 + 8 + 8 + 8 + + + + + mc-1.11 + + 1.11.2 + 8 + 8 + 8 + + + + + mc-1.12 + + 1.12.2 + 8 + 8 + 8 + + + + + + mc-1.13 + + 1.13.2 + 8 + 8 + 8 + + + + + mc-1.14 + + 1.14.4 + 8 + 8 + 8 + + + + + mc-1.15 + + 1.15.2 + 8 + 8 + 8 + + + + + mc-1.16 + + 1.16.5 + 8 + 8 + 8 + + + + + + mc-1.17 + + 1.17.1 + 16 + 16 + 16 + + + + + + mc-1.18 + + 1.18.2 + 17 + 17 + 17 + + + + + mc-1.19 + + 1.19.4 + 17 + 17 + 17 + + + + + mc-1.20 + + 1.20.4 + 17 + 17 + 17 + + + + + + mc-1.21 + + true + + + 1.21 + 21 + 21 + 21 + + + + + mc-1.21.1 + + 1.21.1 + 21 + 21 + 21 + + + + + + + + src/main/resources + true + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.11.0 + + ${maven.compiler.source} + ${maven.compiler.target} + + -parameters + + + + + org.apache.maven.plugins + maven-jar-plugin + 3.2.2 + + + + true + + + + + + org.apache.maven.plugins + maven-shade-plugin + 3.5.1 + + + package + + shade + + + false + + + *:* + + META-INF/*.SF + META-INF/*.DSA + META-INF/*.RSA + META-INF/MANIFEST.MF + + + + + + org.bstats + com.example.playerdatasync.premium.libs.bstats + + + com.zaxxer.hikari + com.example.playerdatasync.premium.libs.hikari + + + com.google.gson + com.example.playerdatasync.premium.libs.gson + + + org.apache.commons + com.example.playerdatasync.premium.libs.commons + + + + + + + + + diff --git a/PlayerDataSync-Premium/premium/src/main/java/com/example/playerdatasync/premium/api/LicenseValidator.java b/PlayerDataSync-Premium/premium/src/main/java/com/example/playerdatasync/premium/api/LicenseValidator.java new file mode 100644 index 0000000..3e9c322 --- /dev/null +++ b/PlayerDataSync-Premium/premium/src/main/java/com/example/playerdatasync/premium/api/LicenseValidator.java @@ -0,0 +1,269 @@ +package com.example.playerdatasync.premium.api; + +import org.bukkit.Bukkit; +import org.bukkit.plugin.java.JavaPlugin; + +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; + +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.net.HttpURLConnection; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URL; +import java.nio.charset.StandardCharsets; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.TimeUnit; + +/** + * License validator for PlayerDataSync Premium using CraftingStudio Pro API + * API Documentation: https://www.craftingstudiopro.de/docs/api + * + * Validates license keys against the CraftingStudio Pro API + */ +public class LicenseValidator { + private static final String API_BASE_URL = "https://craftingstudiopro.de/api"; + private static final String LICENSE_VALIDATE_ENDPOINT = "/license/validate"; + private static final String PLUGIN_ID = "playerdatasync-premium"; // Plugin slug or ID + + private final JavaPlugin plugin; + private String cachedLicenseKey; + private LicenseValidationResult cachedResult; + private long lastValidationTime = 0; + private static final long CACHE_DURATION_MS = TimeUnit.MINUTES.toMillis(30); // Cache for 30 minutes + + public LicenseValidator(JavaPlugin plugin) { + this.plugin = plugin; + } + + /** + * Validate a license key asynchronously + * + * @param licenseKey The license key to validate + * @return CompletableFuture with validation result + */ + public CompletableFuture validateLicenseAsync(String licenseKey) { + // Check cache first + if (licenseKey != null && licenseKey.equals(cachedLicenseKey) && + cachedResult != null && + (System.currentTimeMillis() - lastValidationTime) < CACHE_DURATION_MS) { + return CompletableFuture.completedFuture(cachedResult); + } + + return CompletableFuture.supplyAsync(() -> { + try { + String apiUrl = API_BASE_URL + LICENSE_VALIDATE_ENDPOINT; + HttpURLConnection connection; + try { + URI uri = new URI(apiUrl); + connection = (HttpURLConnection) uri.toURL().openConnection(); + } catch (URISyntaxException e) { + @SuppressWarnings("deprecation") + URL fallbackUrl = new URL(apiUrl); + connection = (HttpURLConnection) fallbackUrl.openConnection(); + } + + connection.setConnectTimeout(10000); + connection.setReadTimeout(10000); + connection.setRequestMethod("POST"); + connection.setRequestProperty("Content-Type", "application/json"); + connection.setRequestProperty("User-Agent", "PlayerDataSync-Premium/" + plugin.getDescription().getVersion()); + connection.setRequestProperty("Accept", "application/json"); + connection.setDoOutput(true); + + // Create request body + JsonObject requestBody = new JsonObject(); + requestBody.addProperty("licenseKey", licenseKey); + requestBody.addProperty("pluginId", PLUGIN_ID); + + // Send request + try (OutputStream os = connection.getOutputStream()) { + byte[] input = requestBody.toString().getBytes(StandardCharsets.UTF_8); + os.write(input, 0, input.length); + } + + int responseCode = connection.getResponseCode(); + + // Handle rate limiting + if (responseCode == 429) { + plugin.getLogger().warning("[LicenseValidator] Rate limit exceeded. Please try again later."); + return new LicenseValidationResult(false, "Rate limit exceeded. Please try again later.", null); + } + + if (responseCode != 200) { + String errorMessage = "HTTP " + responseCode; + try (BufferedReader reader = new BufferedReader( + new InputStreamReader(connection.getErrorStream(), StandardCharsets.UTF_8))) { + StringBuilder errorResponse = new StringBuilder(); + String line; + while ((line = reader.readLine()) != null) { + errorResponse.append(line); + } + if (errorResponse.length() > 0) { + errorMessage = errorResponse.toString(); + } + } catch (Exception e) { + // Ignore error stream reading errors + } + plugin.getLogger().warning("[LicenseValidator] License validation failed: " + errorMessage); + return new LicenseValidationResult(false, errorMessage, null); + } + + // Read response + try (BufferedReader reader = new BufferedReader( + new InputStreamReader(connection.getInputStream(), StandardCharsets.UTF_8))) { + + StringBuilder response = new StringBuilder(); + String line; + while ((line = reader.readLine()) != null) { + response.append(line); + } + + String jsonResponse = response.toString(); + if (jsonResponse == null || jsonResponse.trim().isEmpty()) { + return new LicenseValidationResult(false, "Empty response from API", null); + } + + // Parse JSON response + // Response format: { valid: boolean, message?: string, purchase?: { id: string, userId: string, pluginId: string, createdAt: string } } + JsonObject jsonObject = JsonParser.parseString(jsonResponse).getAsJsonObject(); + + boolean valid = jsonObject.has("valid") && jsonObject.get("valid").getAsBoolean(); + String message = null; + if (jsonObject.has("message") && !jsonObject.get("message").isJsonNull()) { + message = jsonObject.get("message").getAsString(); + } + + PurchaseInfo purchaseInfo = null; + if (valid && jsonObject.has("purchase") && !jsonObject.get("purchase").isJsonNull()) { + JsonObject purchaseObj = jsonObject.getAsJsonObject("purchase"); + purchaseInfo = new PurchaseInfo( + purchaseObj.has("id") ? purchaseObj.get("id").getAsString() : null, + purchaseObj.has("userId") ? purchaseObj.get("userId").getAsString() : null, + purchaseObj.has("pluginId") ? purchaseObj.get("pluginId").getAsString() : null, + purchaseObj.has("createdAt") ? purchaseObj.get("createdAt").getAsString() : null + ); + } + + LicenseValidationResult result = new LicenseValidationResult(valid, message, purchaseInfo); + + // Cache result + cachedLicenseKey = licenseKey; + cachedResult = result; + lastValidationTime = System.currentTimeMillis(); + + return result; + } + } catch (java.net.UnknownHostException e) { + plugin.getLogger().warning("[LicenseValidator] No internet connection available for license validation."); + return new LicenseValidationResult(false, "No internet connection", null); + } catch (java.net.SocketTimeoutException e) { + plugin.getLogger().warning("[LicenseValidator] License validation timeout."); + return new LicenseValidationResult(false, "Connection timeout", null); + } catch (Exception e) { + plugin.getLogger().severe("[LicenseValidator] License validation error: " + e.getMessage()); + plugin.getLogger().log(java.util.logging.Level.FINE, "License validation error", e); + return new LicenseValidationResult(false, "Validation error: " + e.getMessage(), null); + } + }); + } + + /** + * Validate license key synchronously (blocks thread) + * Use validateLicenseAsync() for non-blocking validation + */ + public LicenseValidationResult validateLicense(String licenseKey) { + try { + return validateLicenseAsync(licenseKey).get(10, TimeUnit.SECONDS); + } catch (Exception e) { + plugin.getLogger().severe("[LicenseValidator] Failed to validate license: " + e.getMessage()); + return new LicenseValidationResult(false, "Validation failed: " + e.getMessage(), null); + } + } + + /** + * Clear the validation cache + */ + public void clearCache() { + cachedLicenseKey = null; + cachedResult = null; + lastValidationTime = 0; + } + + /** + * Check if cached validation is still valid + */ + public boolean isCacheValid() { + return cachedResult != null && + (System.currentTimeMillis() - lastValidationTime) < CACHE_DURATION_MS; + } + + /** + * Get cached validation result + */ + public LicenseValidationResult getCachedResult() { + return cachedResult; + } + + /** + * License validation result + */ + public static class LicenseValidationResult { + private final boolean valid; + private final String message; + private final PurchaseInfo purchase; + + public LicenseValidationResult(boolean valid, String message, PurchaseInfo purchase) { + this.valid = valid; + this.message = message; + this.purchase = purchase; + } + + public boolean isValid() { + return valid; + } + + public String getMessage() { + return message; + } + + public PurchaseInfo getPurchase() { + return purchase; + } + } + + /** + * Purchase information from API + */ + public static class PurchaseInfo { + private final String id; + private final String userId; + private final String pluginId; + private final String createdAt; + + public PurchaseInfo(String id, String userId, String pluginId, String createdAt) { + this.id = id; + this.userId = userId; + this.pluginId = pluginId; + this.createdAt = createdAt; + } + + public String getId() { + return id; + } + + public String getUserId() { + return userId; + } + + public String getPluginId() { + return pluginId; + } + + public String getCreatedAt() { + return createdAt; + } + } +} diff --git a/PlayerDataSync-Premium/premium/src/main/java/com/example/playerdatasync/premium/api/PremiumUpdateChecker.java b/PlayerDataSync-Premium/premium/src/main/java/com/example/playerdatasync/premium/api/PremiumUpdateChecker.java new file mode 100644 index 0000000..0484766 --- /dev/null +++ b/PlayerDataSync-Premium/premium/src/main/java/com/example/playerdatasync/premium/api/PremiumUpdateChecker.java @@ -0,0 +1,160 @@ +package com.example.playerdatasync.premium.api; + +import org.bukkit.Bukkit; +import org.bukkit.plugin.java.JavaPlugin; + +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; + +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.net.HttpURLConnection; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URL; +import java.nio.charset.StandardCharsets; + +/** + * Update checker for PlayerDataSync Premium using CraftingStudio Pro API + * API Documentation: https://www.craftingstudiopro.de/docs/api + * + * Checks for updates using the Premium plugin slug + */ +public class PremiumUpdateChecker { + private static final String API_BASE_URL = "https://craftingstudiopro.de/api"; + private static final String PLUGIN_SLUG = "playerdatasync-premium"; + + private final JavaPlugin plugin; + + public PremiumUpdateChecker(JavaPlugin plugin) { + this.plugin = plugin; + } + + /** + * Check for updates asynchronously + */ + public void check() { + // Only check for updates if enabled in config + if (!plugin.getConfig().getBoolean("update_checker.enabled", true)) { + plugin.getLogger().info("[PremiumUpdateChecker] Update checking is disabled in config"); + return; + } + + SchedulerUtils.runTaskAsync(plugin, () -> { + try { + // Use CraftingStudio Pro API endpoint + String apiUrl = API_BASE_URL + "/plugins/" + PLUGIN_SLUG + "/latest"; + HttpURLConnection connection; + try { + URI uri = new URI(apiUrl); + connection = (HttpURLConnection) uri.toURL().openConnection(); + } catch (URISyntaxException e) { + @SuppressWarnings("deprecation") + URL fallbackUrl = new URL(apiUrl); + connection = (HttpURLConnection) fallbackUrl.openConnection(); + } + connection.setConnectTimeout(10000); + connection.setReadTimeout(10000); + connection.setRequestMethod("GET"); + connection.setRequestProperty("User-Agent", "PlayerDataSync-Premium/" + plugin.getDescription().getVersion()); + connection.setRequestProperty("Accept", "application/json"); + + int responseCode = connection.getResponseCode(); + if (responseCode == 429) { + plugin.getLogger().warning("[PremiumUpdateChecker] Rate limit exceeded. Please try again later."); + return; + } + + if (responseCode != 200) { + plugin.getLogger().warning("[PremiumUpdateChecker] Update check failed: HTTP " + responseCode); + return; + } + + try (BufferedReader reader = new BufferedReader( + new InputStreamReader(connection.getInputStream(), StandardCharsets.UTF_8))) { + + StringBuilder response = new StringBuilder(); + String line; + while ((line = reader.readLine()) != null) { + response.append(line); + } + + String jsonResponse = response.toString(); + if (jsonResponse == null || jsonResponse.trim().isEmpty()) { + plugin.getLogger().warning("[PremiumUpdateChecker] Empty response from API"); + return; + } + + // Parse JSON response using Gson + // Response format: { version: string, downloadUrl: string, createdAt: string | null, + // title: string, releaseType: "release", slug: string | null, + // pluginTitle: string, pluginSlug: string } + JsonObject jsonObject; + try { + jsonObject = JsonParser.parseString(jsonResponse).getAsJsonObject(); + } catch (Exception e) { + plugin.getLogger().warning("[PremiumUpdateChecker] Invalid JSON response: " + e.getMessage()); + return; + } + + if (!jsonObject.has("version")) { + plugin.getLogger().warning("[PremiumUpdateChecker] Invalid response format: missing version field"); + return; + } + + final String latestVersion = jsonObject.get("version").getAsString(); + final String downloadUrl; + if (jsonObject.has("downloadUrl") && !jsonObject.get("downloadUrl").isJsonNull()) { + downloadUrl = jsonObject.get("downloadUrl").getAsString(); + } else { + downloadUrl = null; + } + + String pluginTitle = "PlayerDataSync Premium"; + if (jsonObject.has("pluginTitle") && !jsonObject.get("pluginTitle").isJsonNull()) { + pluginTitle = jsonObject.get("pluginTitle").getAsString(); + } + + String currentVersion = plugin.getDescription().getVersion(); + if (currentVersion.equalsIgnoreCase(latestVersion)) { + if (plugin.getConfig().getBoolean("update_checker.notify_ops", true)) { + plugin.getLogger().info("[PremiumUpdateChecker] " + pluginTitle + " is up to date (v" + currentVersion + ")"); + } + } else { + plugin.getLogger().info("================================================"); + plugin.getLogger().info("[PremiumUpdateChecker] Update available for " + pluginTitle + "!"); + plugin.getLogger().info("[PremiumUpdateChecker] Current version: " + currentVersion); + plugin.getLogger().info("[PremiumUpdateChecker] Latest version: " + latestVersion); + if (downloadUrl != null && !downloadUrl.isEmpty()) { + plugin.getLogger().info("[PremiumUpdateChecker] Download: " + downloadUrl); + } else { + plugin.getLogger().info("[PremiumUpdateChecker] Download: https://craftingstudiopro.de/plugins/" + PLUGIN_SLUG); + } + plugin.getLogger().info("================================================"); + + // Notify OPs if enabled + if (plugin.getConfig().getBoolean("update_checker.notify_ops", true)) { + SchedulerUtils.runTask(plugin, () -> { + Bukkit.getOnlinePlayers().stream() + .filter(p -> p.isOp() || p.hasPermission("playerdatasync.premium.admin")) + .forEach(p -> { + p.sendMessage("§8[§6PlayerDataSync Premium§8] §eUpdate available: v" + latestVersion); + if (downloadUrl != null && !downloadUrl.isEmpty()) { + p.sendMessage("§8[§6PlayerDataSync Premium§8] §7Download: §f" + downloadUrl); + } + }); + }); + } + } + } + } catch (java.net.UnknownHostException e) { + plugin.getLogger().fine("[PremiumUpdateChecker] No internet connection available for update check."); + } catch (java.net.SocketTimeoutException e) { + plugin.getLogger().warning("[PremiumUpdateChecker] Update check timeout."); + } catch (Exception e) { + plugin.getLogger().warning("[PremiumUpdateChecker] Update check failed: " + e.getMessage()); + plugin.getLogger().log(java.util.logging.Level.FINE, "Update check error", e); + } + }); + } +} diff --git a/PlayerDataSync-Premium/premium/src/main/java/com/example/playerdatasync/premium/commands/PremiumCommandHandler.java b/PlayerDataSync-Premium/premium/src/main/java/com/example/playerdatasync/premium/commands/PremiumCommandHandler.java new file mode 100644 index 0000000..397ff1f --- /dev/null +++ b/PlayerDataSync-Premium/premium/src/main/java/com/example/playerdatasync/premium/commands/PremiumCommandHandler.java @@ -0,0 +1,106 @@ +package com.example.playerdatasync.premium.commands; + +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +import com.example.playerdatasync.premium.core.PlayerDataSyncPremium; +import com.example.playerdatasync.premium.managers.LicenseManager; +import com.example.playerdatasync.premium.api.PremiumUpdateChecker; +import com.example.playerdatasync.premium.api.LicenseValidator.LicenseValidationResult; + +/** + * Premium command handler for license and update commands + * + * This class should be integrated into SyncCommand.java + */ +public class PremiumCommandHandler { + private final PlayerDataSyncPremium plugin; + + public PremiumCommandHandler(PlayerDataSyncPremium plugin) { + this.plugin = plugin; + } + + /** + * Handle license commands + * Usage: /sync license [validate|info] + */ + public boolean handleLicense(CommandSender sender, String[] args) { + if (!sender.hasPermission("playerdatasync.premium.admin.license")) { + sender.sendMessage("§cYou don't have permission to use this command."); + return true; + } + + LicenseManager licenseManager = plugin.getLicenseManager(); + if (licenseManager == null) { + sender.sendMessage("§cLicense manager is not initialized."); + return true; + } + + String action = args.length > 2 ? args[2].toLowerCase() : "info"; + + switch (action) { + case "validate": + case "revalidate": + sender.sendMessage("§8[§6PlayerDataSync Premium§8] §7Validating license..."); + licenseManager.revalidateLicense().thenAccept(result -> { + plugin.getServer().getScheduler().runTask(plugin, () -> { + if (result.isValid()) { + sender.sendMessage("§8[§6PlayerDataSync Premium§8] §aLicense is valid!"); + if (result.getPurchase() != null) { + sender.sendMessage("§8[§6PlayerDataSync Premium§8] §7Purchase ID: §f" + result.getPurchase().getId()); + sender.sendMessage("§8[§6PlayerDataSync Premium§8] §7User ID: §f" + result.getPurchase().getUserId()); + } + } else { + sender.sendMessage("§8[§6PlayerDataSync Premium§8] §cLicense validation failed!"); + sender.sendMessage("§8[§6PlayerDataSync Premium§8] §7Reason: §f" + + (result.getMessage() != null ? result.getMessage() : "Unknown error")); + } + }); + }); + return true; + + case "info": + sender.sendMessage("§8[§m----------§r §6License Information §8§m----------"); + sender.sendMessage("§7License Key: §f" + licenseManager.getLicenseKey()); + sender.sendMessage("§7Status: " + (licenseManager.isLicenseValid() ? "§aValid" : "§cInvalid")); + sender.sendMessage("§7Checked: " + (licenseManager.isLicenseChecked() ? "§aYes" : "§cNo")); + sender.sendMessage("§8§m----------------------------------------"); + return true; + + default: + sender.sendMessage("§8[§6PlayerDataSync Premium§8] §7Usage: /sync license [validate|info]"); + return true; + } + } + + /** + * Handle update commands + * Usage: /sync update [check] + */ + public boolean handleUpdate(CommandSender sender, String[] args) { + if (!sender.hasPermission("playerdatasync.premium.admin.update")) { + sender.sendMessage("§cYou don't have permission to use this command."); + return true; + } + + PremiumUpdateChecker updateChecker = plugin.getUpdateChecker(); + if (updateChecker == null) { + sender.sendMessage("§cUpdate checker is not initialized."); + return true; + } + + String action = args.length > 2 ? args[2].toLowerCase() : "check"; + + switch (action) { + case "check": + sender.sendMessage("§8[§6PlayerDataSync Premium§8] §7Checking for updates..."); + updateChecker.check(); + sender.sendMessage("§8[§6PlayerDataSync Premium§8] §7Update check initiated. Check console for results."); + return true; + + default: + sender.sendMessage("§8[§6PlayerDataSync Premium§8] §7Usage: /sync update check"); + return true; + } + } +} diff --git a/PlayerDataSync-Premium/premium/src/main/java/com/example/playerdatasync/premium/commands/SyncCommand.java b/PlayerDataSync-Premium/premium/src/main/java/com/example/playerdatasync/premium/commands/SyncCommand.java new file mode 100644 index 0000000..c992736 --- /dev/null +++ b/PlayerDataSync-Premium/premium/src/main/java/com/example/playerdatasync/premium/commands/SyncCommand.java @@ -0,0 +1,595 @@ +package com.example.playerdatasync.premium.commands; + +import org.bukkit.Bukkit; +import org.bukkit.command.Command; +import org.bukkit.command.CommandExecutor; +import org.bukkit.command.CommandSender; +import org.bukkit.command.TabCompleter; +import org.bukkit.entity.Player; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +import com.example.playerdatasync.premium.core.PlayerDataSyncPremium; +import com.example.playerdatasync.premium.commands.PremiumCommandHandler; +import com.example.playerdatasync.premium.managers.AdvancementSyncManager; +import com.example.playerdatasync.premium.managers.BackupManager; +import com.example.playerdatasync.premium.managers.MessageManager; +import com.example.playerdatasync.premium.utils.InventoryUtils; + +/** + * Enhanced sync command with expanded functionality + */ +public class SyncCommand implements CommandExecutor, TabCompleter { + private final PlayerDataSyncPremium plugin; + private final MessageManager messageManager; + private final PremiumCommandHandler premiumHandler; + + // Available sync options + private static final List SYNC_OPTIONS = Arrays.asList( + "coordinates", "position", "xp", "gamemode", "inventory", "enderchest", + "armor", "offhand", "health", "hunger", "effects", "achievements", + "statistics", "attributes", "permissions", "economy" + ); + + // Available sub-commands + private static final List SUB_COMMANDS = Arrays.asList( + "reload", "status", "save", "help", "cache", "validate", "backup", "restore", "achievements", "license", "update" + ); + + public SyncCommand(PlayerDataSyncPremium plugin) { + this.plugin = plugin; + this.messageManager = plugin.getMessageManager(); + this.premiumHandler = new PremiumCommandHandler(plugin); + } + + @Override + public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { + if (args.length == 0) { + return showStatus(sender); + } + + String subCommand = args[0].toLowerCase(); + + switch (subCommand) { + case "reload": + return handleReload(sender); + + case "status": + return handleStatus(sender, args); + + case "save": + return handleSave(sender, args); + + case "help": + return showHelp(sender); + + case "cache": + return handleCache(sender, args); + + case "validate": + return handleValidate(sender, args); + + case "backup": + return handleBackup(sender, args); + + case "restore": + return handleRestore(sender, args); + + case "achievements": + return handleAchievements(sender, args); + + case "license": + return premiumHandler.handleLicense(sender, args); + + case "update": + return premiumHandler.handleUpdate(sender, args); + + default: + // Try to parse as sync option + if (args.length == 2) { + return handleSyncOption(sender, args[0], args[1]); + } else { + return showHelp(sender); + } + } + } + + /** + * Show current sync status + */ + private boolean showStatus(CommandSender sender) { + if (!hasPermission(sender, "playerdatasync.premium.premium.admin")) return true; + + sender.sendMessage(messageManager.get("status_header")); + sender.sendMessage(messageManager.get("status_version").replace("{version}", plugin.getDescription().getVersion())); + + // Show sync options status + for (String option : SYNC_OPTIONS) { + boolean enabled = getSyncOptionValue(option); + String status = enabled ? messageManager.get("sync_status_enabled") : messageManager.get("sync_status_disabled"); + sender.sendMessage(messageManager.get("sync_status") + .replace("{option}", option) + .replace("{status}", status)); + } + + sender.sendMessage(messageManager.get("status_footer")); + return true; + } + + /** + * Handle reload command + */ + private boolean handleReload(CommandSender sender) { + if (!hasPermission(sender, "playerdatasync.premium.admin.reload")) return true; + + try { + plugin.reloadPlugin(); + sender.sendMessage(messageManager.get("prefix") + " " + messageManager.get("reloaded")); + } catch (Exception e) { + sender.sendMessage(messageManager.get("prefix") + " " + + messageManager.get("reload_failed").replace("{error}", e.getMessage())); + } + return true; + } + + /** + * Handle status command for specific player + */ + private boolean handleStatus(CommandSender sender, String[] args) { + if (!hasPermission(sender, "playerdatasync.premium.status")) return true; + + Player target; + if (args.length > 1) { + if (!hasPermission(sender, "playerdatasync.premium.status.others")) return true; + target = Bukkit.getPlayer(args[1]); + if (target == null) { + sender.sendMessage(messageManager.get("prefix") + " " + + messageManager.get("player_not_found").replace("{player}", args[1])); + return true; + } + } else { + if (!(sender instanceof Player)) { + sender.sendMessage(messageManager.get("prefix") + " " + messageManager.get("error_player_offline")); + return true; + } + target = (Player) sender; + } + + showPlayerStatus(sender, target); + return true; + } + + /** + * Handle save command + */ + private boolean handleSave(CommandSender sender, String[] args) { + if (!hasPermission(sender, "playerdatasync.premium.admin.save")) return true; + + if (args.length > 1) { + // Save specific player + Player target = Bukkit.getPlayer(args[1]); + if (target == null) { + sender.sendMessage(messageManager.get("prefix") + " " + + messageManager.get("player_not_found").replace("{player}", args[1])); + return true; + } + + try { + if (plugin.getDatabaseManager().savePlayer(target)) { + sender.sendMessage(messageManager.get("prefix") + " " + + messageManager.get("manual_save_success")); + } else { + sender.sendMessage(messageManager.get("prefix") + " " + + messageManager.get("manual_save_failed").replace("{error}", + "Unable to persist player data. See console for details.")); + } + } catch (Exception e) { + sender.sendMessage(messageManager.get("prefix") + " " + + messageManager.get("manual_save_failed").replace("{error}", e.getMessage())); + } + } else { + // Save all online players + try { + int savedCount = 0; + for (Player player : Bukkit.getOnlinePlayers()) { + if (plugin.getDatabaseManager().savePlayer(player)) { + savedCount++; + } + } + sender.sendMessage(messageManager.get("prefix") + " " + + "Saved data for " + savedCount + " players."); + } catch (Exception e) { + sender.sendMessage(messageManager.get("prefix") + " " + + messageManager.get("manual_save_failed").replace("{error}", e.getMessage())); + } + } + return true; + } + + /** + * Handle cache command + */ + private boolean handleCache(CommandSender sender, String[] args) { + if (!hasPermission(sender, "playerdatasync.premium.premium.admin")) return true; + + if (args.length > 1 && args[1].equalsIgnoreCase("clear")) { + // Clear performance stats + plugin.getDatabaseManager().resetPerformanceStats(); + InventoryUtils.resetDeserializationStats(); + sender.sendMessage(messageManager.get("prefix") + " " + "Performance and deserialization statistics cleared."); + } else { + // Show performance stats + String stats = plugin.getDatabaseManager().getPerformanceStats(); + sender.sendMessage(messageManager.get("prefix") + " " + "Performance Stats: " + stats); + + // Show connection pool stats if available + if (plugin.getConnectionPool() != null) { + sender.sendMessage(messageManager.get("prefix") + " " + "Connection Pool: " + plugin.getConnectionPool().getStats()); + } + + // Show deserialization statistics + String deserializationStats = InventoryUtils.getDeserializationStats(); + sender.sendMessage(messageManager.get("prefix") + " " + "Deserialization Stats: " + deserializationStats); + + // Show helpful message if there are custom enchantment failures + if (deserializationStats.contains("Custom Enchantments:") && + !deserializationStats.contains("Custom Enchantments: 0")) { + sender.sendMessage("§e⚠ If you see custom enchantment failures, ensure enchantment plugins " + + "(e.g., ExcellentEnchants) are loaded and all enchantments are registered."); + } + } + return true; + } + + /** + * Handle validate command + */ + private boolean handleValidate(CommandSender sender, String[] args) { + if (!hasPermission(sender, "playerdatasync.premium.premium.admin")) return true; + + // Perform data validation (placeholder) + sender.sendMessage(messageManager.get("prefix") + " Data validation completed."); + return true; + } + + /** + * Handle backup command + */ + private boolean handleBackup(CommandSender sender, String[] args) { + if (!hasPermission(sender, "playerdatasync.premium.admin.backup")) return true; + + String backupType = args.length > 1 ? args[1] : "manual"; + + sender.sendMessage(messageManager.get("prefix") + " Creating backup..."); + + plugin.getBackupManager().createBackup(backupType).thenAccept(result -> { + if (result.isSuccess()) { + sender.sendMessage(messageManager.get("prefix") + " Backup created: " + result.getFileName() + + " (" + formatFileSize(result.getFileSize()) + ")"); + } else { + sender.sendMessage(messageManager.get("prefix") + " Backup failed!"); + } + }); + + return true; + } + + /** + * Handle restore command + */ + private boolean handleRestore(CommandSender sender, String[] args) { + if (!hasPermission(sender, "playerdatasync.premium.admin.restore")) return true; + + if (args.length < 2) { + // List available backups + List backups = plugin.getBackupManager().listBackups(); + if (backups.isEmpty()) { + sender.sendMessage(messageManager.get("prefix") + " No backups available."); + } else { + sender.sendMessage(messageManager.get("prefix") + " Available backups:"); + for (BackupManager.BackupInfo backup : backups) { + sender.sendMessage("§7- §f" + backup.getFileName() + " §8(" + backup.getFormattedSize() + + ", " + backup.getCreatedDate() + ")"); + } + } + return true; + } + + String backupName = args[1]; + sender.sendMessage(messageManager.get("prefix") + " Restoring from backup: " + backupName); + + plugin.getBackupManager().restoreFromBackup(backupName).thenAccept(success -> { + if (success) { + sender.sendMessage(messageManager.get("prefix") + " Restore completed successfully!"); + } else { + sender.sendMessage(messageManager.get("prefix") + " Restore failed!"); + } + }); + + return true; + } + + private boolean handleAchievements(CommandSender sender, String[] args) { + if (!hasPermission(sender, "playerdatasync.premium.admin.achievements")) return true; + + AdvancementSyncManager advancementSyncManager = plugin.getAdvancementSyncManager(); + if (advancementSyncManager == null) { + sender.sendMessage(messageManager.get("prefix") + " Advancement manager is not available."); + return true; + } + + String prefix = messageManager.get("prefix") + " "; + + if (args.length == 1 || args[1].equalsIgnoreCase("status")) { + sender.sendMessage(prefix + "Advancement cache: " + advancementSyncManager.getGlobalImportStatus()); + + if (args.length > 2) { + Player target = Bukkit.getPlayer(args[2]); + if (target == null) { + sender.sendMessage(prefix + "Player '" + args[2] + "' is not online."); + } else { + sender.sendMessage(prefix + target.getName() + ": " + + advancementSyncManager.getPlayerStatus(target.getUniqueId())); + } + } else if (sender instanceof Player) { + Player player = (Player) sender; + sender.sendMessage(prefix + "You: " + + advancementSyncManager.getPlayerStatus(player.getUniqueId())); + } + + sender.sendMessage(prefix + "Use /sync achievements import [player] to queue an import."); + return true; + } + + String action = args[1].toLowerCase(); + if (action.equals("import") || action.equals("preload")) { + if (args.length == 2) { + boolean started = advancementSyncManager.startGlobalImport(true); + if (started) { + sender.sendMessage(prefix + "Started global advancement cache rebuild."); + } else if (advancementSyncManager.getGlobalImportStatus().startsWith("running")) { + sender.sendMessage(prefix + "Global advancement cache rebuild is already running."); + } else { + sender.sendMessage(prefix + "Advancement cache already up to date. Use /sync achievements import again later to rebuild."); + } + return true; + } + + Player target = Bukkit.getPlayer(args[2]); + if (target == null) { + sender.sendMessage(prefix + "Player '" + args[2] + "' is not online."); + return true; + } + + advancementSyncManager.forceRescan(target); + sender.sendMessage(prefix + "Queued advancement import for " + target.getName() + "."); + return true; + } + + sender.sendMessage(prefix + "Unknown achievements subcommand. Try /sync achievements status or /sync achievements import"); + return true; + } + + /** + * Format file size for display + */ + private String formatFileSize(long bytes) { + if (bytes < 1024) return bytes + " B"; + if (bytes < 1024 * 1024) return String.format("%.1f KB", bytes / 1024.0); + return String.format("%.1f MB", bytes / (1024.0 * 1024.0)); + } + + /** + * Handle sync option changes + */ + private boolean handleSyncOption(CommandSender sender, String option, String value) { + if (!hasPermission(sender, "playerdatasync.premium.admin." + option)) return true; + + if (!value.equalsIgnoreCase("true") && !value.equalsIgnoreCase("false")) { + sender.sendMessage(messageManager.get("prefix") + " " + + messageManager.get("invalid_syntax").replace("{usage}", "/sync