Documentation Ulises Licenses
Intégration de Plugin Minecraft
1. Charger le Fichier de Configuration
private void loadAntileakConfig() {
File krakenDir = getDataFolder();
if (!krakenDir.exists()) {
krakenDir.mkdirs();
}
File antileakFile = new File(krakenDir, "antileak.yml");
if (!antileakFile.exists()) {
try {
antileakFile.createNewFile();
this.antileakConfig = YamlConfiguration.loadConfiguration(antileakFile);
this.antileakConfig.set("license.key", "your-license-key-here");
this.antileakConfig.save(antileakFile);
} catch (IOException e) {
e.printStackTrace();
}
} else {
this.antileakConfig = YamlConfiguration.loadConfiguration(antileakFile);
}
}2. Validation de Licence avec Logique de Réessai
private void validateLicense() {
UlisesLib ulib = new UlisesLib();
String productId = "myproductid";
String licenseKey = this.antileakConfig.getString("license.key", "");
boolean licenseValid = false;
while (!licenseValid) {
if (ulib.isLicenseValid(productId, licenseKey)) {
licenseValid = true;
String discordId = ulib.getDiscordId(productId, licenseKey);
String productName = ulib.getProductName(productId, licenseKey);
String expiresAt = ulib.getExpirationDate(productId, licenseKey);
String licenseStatus = ulib.getLicenseStatus(productId, licenseKey);
Bukkit.getConsoleSender().sendMessage(
ChatColor.GRAY + "[" + ChatColor.DARK_AQUA + "Kraken" + ChatColor.GRAY + "] " +
ChatColor.DARK_AQUA + "✓ Authentication successful. Powering up Kraken..."
);
Bukkit.getConsoleSender().sendMessage(
ChatColor.GRAY + "[" + ChatColor.DARK_AQUA + "Kraken" + ChatColor.GRAY + "] " +
ChatColor.GRAY + " » Discord ID: " + ChatColor.AQUA + discordId
);
loadPlugin();
} else {
String lastError = ulib.getLastError();
Bukkit.getConsoleSender().sendMessage(
ChatColor.GRAY + "[" + ChatColor.DARK_AQUA + "Kraken" + ChatColor.GRAY + "] " +
ChatColor.RED + "✗ License authentication failed: " + lastError
);
if (lastError != null && lastError.contains("Unable to connect to the backend server")) {
Bukkit.getConsoleSender().sendMessage(
ChatColor.GRAY + "[" + ChatColor.DARK_AQUA + "Kraken" + ChatColor.GRAY + "] " +
ChatColor.YELLOW + "⚠ Retrying connection in 30 seconds..."
);
try {
Thread.sleep(30000);
} catch (InterruptedException e) {
Bukkit.getPluginManager().disablePlugin(this);
return;
}
} else {
Bukkit.getPluginManager().disablePlugin(this);
return;
}
}
}
}3. Vérifications de Sécurité Périodiques
private void startSecurityChecks() {
ScheduledExecutorService licenseService = Executors.newSingleThreadScheduledExecutor();
licenseService.scheduleAtFixedRate(() -> {
UlisesLib ulib = new UlisesLib();
String productId = antileakConfig.getString("license.product-id", "");
String licenseKey = antileakConfig.getString("license.key", "");
if (!ulib.isLicenseValid(productId, licenseKey)) {
String lastError = ulib.getLastError();
Bukkit.getConsoleSender().sendMessage(
ChatColor.GRAY + "[" + ChatColor.DARK_AQUA + "Kraken" + ChatColor.GRAY + "] " +
ChatColor.RED + "✗ License validation failed during periodic check."
);
if (lastError != null && lastError.contains("Unable to connect to the backend server")) {
Bukkit.getConsoleSender().sendMessage(
ChatColor.GRAY + "[" + ChatColor.DARK_AQUA + "Kraken" + ChatColor.GRAY + "] " +
ChatColor.YELLOW + "⚠ Will retry in next check cycle..."
);
} else {
Bukkit.getScheduler().runTask(this, () -> Bukkit.getPluginManager().disablePlugin(this));
licenseService.shutdown();
}
} else {
Bukkit.getConsoleSender().sendMessage(
ChatColor.GRAY + "[" + ChatColor.DARK_AQUA + "Kraken" + ChatColor.GRAY + "] " +
ChatColor.GREEN + "✓ License check passed. Status: " +
ulib.getLicenseStatus(productId, licenseKey)
);
}
}, 10L, 10L, TimeUnit.MINUTES);
}Exemple Complet de Plugin
public class KrakenAntiCheat extends JavaPlugin {
private FileConfiguration antileakConfig;
@Override
public void onEnable() {
loadAntileakConfig();
String productId = antileakConfig.getString("license.product-id");
String licenseKey = antileakConfig.getString("license.key");
if (productId.equals("your-product-id-here") || licenseKey.equals("your-license-key-here")) {
getLogger().severe("License details not configured. Please edit antileak.yml");
Bukkit.getPluginManager().disablePlugin(this);
return;
}
validateLicense(productId, licenseKey);
}
private void validateLicense(String productId, String licenseKey) {
UlisesLib ulib = new UlisesLib();
while (true) {
if (ulib.isLicenseValid(productId, licenseKey)) {
String discordId = ulib.getDiscordId(productId, licenseKey);
String expiresAt = ulib.getExpirationDate(productId, licenseKey);
getLogger().info("License validated for Discord ID: " + discordId);
getLogger().info("License expires: " + expiresAt);
loadFeatures();
startPeriodicChecks();
break;
} else {
String error = ulib.getLastError();
getLogger().severe("License validation failed: " + error);
if (error != null && error.contains("Unable to connect to the backend server")) {
getLogger().warning("Retrying connection in 30 seconds...");
try {
Thread.sleep(30000);
} catch (InterruptedException e) {
Bukkit.getPluginManager().disablePlugin(this);
break;
}
} else {
Bukkit.getPluginManager().disablePlugin(this);
break;
}
}
}
}
private void startPeriodicChecks() {
Bukkit.getScheduler().runTaskTimerAsynchronously(this, () -> {
UlisesLib ulib = new UlisesLib();
String productId = antileakConfig.getString("license.product-id");
String licenseKey = antileakConfig.getString("license.key");
if (!ulib.isLicenseValid(productId, licenseKey)) {
String error = ulib.getLastError();
getLogger().severe("Periodic license check failed: " + error);
if (!error.contains("Unable to connect to the backend server")) {
Bukkit.getScheduler().runTask(this, () ->
Bukkit.getPluginManager().disablePlugin(this)
);
}
} else {
getLogger().info("Periodic license check passed.");
}
}, 20L * 60 * 10, 20L * 60 * 10);
}
}Méthodes API Améliorées
String getDiscordId(String productId, String licenseKey)
Récupère l'ID Discord associé à la licence. Renvoie null si la validation échoue.
String discordId = ulib.getDiscordId(productId, licenseKey);
// Returns: "1216532655592439862"String getProductName(String productId, String licenseKey)
Récupère le nom du produit de la licence. Renvoie null si la validation échoue.
String productName = ulib.getProductName(productId, licenseKey);
// Returns: "KrakenAnticheat"String getExpirationDate(String productId, String licenseKey)
Récupère la date d'expiration au format ISO. Renvoie null si la validation échoue.
String expiresAt = ulib.getExpirationDate(productId, licenseKey);
// Returns: "2025-12-05T00:00:00.000Z"String getLicenseStatus(String productId, String licenseKey)
Récupère le statut de la licence (active/révoquée/expirée). Renvoie null si la validation échoue.
String status = ulib.getLicenseStatus(productId, licenseKey);
// Returns: "active"String getSubType(String productId, String licenseKey)
Récupère le sous-type de licence (Enterprise, Advanced, etc). Renvoie null si la validation échoue.
String subType = ulib.getSubType(productId, licenseKey);
// Returns: "Enterprise"String getLastError()
Renvoie le dernier message d'erreur. Utile pour déboguer les problèmes de connexion.
Gestion de Connexion
Reconnexion Automatique
La bibliothèque gère maintenant automatiquement les problèmes de connexion
- Réessai Infini: Lorsque le backend est inaccessible, la bibliothèque réessaie toutes les 30 secondes jusqu'au succès
- Messages Clairs: La console affiche "Impossible de se connecter au serveur backend" avec compte à rebours de réessai
- Gestion Gracieuse: Désactive uniquement le plugin pour les problèmes réels de licence, pas les problèmes de connexion
Note Importante pour les Développeurs de Plugins
Votre plugin devrait continuer à fonctionner normalement pendant les problèmes de connexion. Désactivez uniquement le plugin lorsqu'il y a des échecs réels de validation de licence (expirée, révoquée, invalide). Les problèmes de connexion devraient déclencher des tentatives de réessai, pas un arrêt immédiat.
Intégration de Mise à Jour Automatique
UlisesLib inclut des méthodes intégrées pour vérifier les mises à jour, télécharger le jar le plus récent et vérifier son intégrité. Toutes les validations de sécurité (statut de licence, liaison HWID, limites IP) sont gérées automatiquement par la bibliothèque.
boolean checkForUpdate(String productId, String licenseKey, String currentVersion)
Vérifie si une version plus récente du jar du produit est disponible. Renvoie true si une mise à jour existe.
String currentVersion = "1.0.0";
if (ulib.checkForUpdate(productId, licenseKey, currentVersion)) {
getLogger().info("Update available! Downloading...");
ulib.downloadUpdate(productId, licenseKey, hwid);
}File downloadUpdate(String productId, String licenseKey, String hwid)
Télécharge le fichier jar le plus récent. Gère automatiquement la liaison HWID lors du premier téléchargement. Renvoie le fichier téléchargé, ou null si le téléchargement échoue.
String hwid = ulib._getHwid();
File updatedJar = ulib.downloadUpdate(productId, licenseKey, hwid);
if (updatedJar != null) {
getLogger().info("Update downloaded: " + updatedJar.getName());
if (ulib.verifyChecksum(productId, licenseKey, hwid, updatedJar)) {
getLogger().info("Checksum verified!");
}
}boolean verifyChecksum(String productId, String licenseKey, String hwid, File jarFile)
Vérifie le checksum SHA-256 du fichier jar téléchargé pour assurer l'intégrité du fichier.
File jarFile = new File("plugins/MyPlugin.jar");
boolean valid = ulib.verifyChecksum(productId, licenseKey, hwid, jarFile);
if (!valid) {
getLogger().warning("Checksum mismatch! File may be corrupted.");
}String getCurrentVersion(String productId, String licenseKey)
Renvoie la chaîne de version la plus récente du jar du produit disponible sur le serveur.
String latestVersion = ulib.getCurrentVersion(productId, licenseKey);
getLogger().info("Latest version available: " + latestVersion);Validations de Sécurité
Toutes les opérations de mise à jour valident automatiquement:
- Statut de Licence: Seules les licences actives et non expirées peuvent télécharger des mises à jour
- Liaison HWID: L'ID matériel est validé et lié à la licence lors du premier téléchargement
- Limite IP: Respecte la limite IP configurée par licence
Exemple Complet de Mise à Jour Automatique
private void checkAndApplyUpdate(String productId, String licenseKey) {
String currentVersion = this.getDescription().getVersion();
String hwid = ulib.getHardwareId();
if (ulib.checkForUpdate(productId, licenseKey, currentVersion)) {
String latestVersion = ulib.getCurrentVersion(productId, licenseKey);
getLogger().info("New version available: " + latestVersion + " (current: " + currentVersion + ")");
File updatedJar = ulib.downloadUpdate(productId, licenseKey, hwid);
if (updatedJar != null) {
if (ulib.verifyChecksum(productId, licenseKey, hwid, updatedJar)) {
getLogger().info("Update downloaded and verified successfully!");
getLogger().info("Restart the server to apply the update.");
} else {
getLogger().warning("Checksum verification failed. Update may be corrupted.");
}
}
} else {
getLogger().info("Plugin is up to date.");
}
}Meilleures Pratiques
✓ Faire Cela
- Utiliser des boucles de réessai infinies pour les problèmes de connexion
- Afficher des informations détaillées de licence lors d'une validation réussie
- Implémenter des vérifications périodiques (toutes les 10 minutes)
- Créer un fichier de configuration avec des valeurs par défaut
✗ Éviter Cela
- Désactiver le plugin lors d'un timeout de connexion
- Coder les identifiants en dur dans le code source
- Exposer les détails d'erreur aux utilisateurs finaux
- Exécuter la validation sur le thread principal