Documentazione Ulises Licenses
Documentazione ufficiale
Riferimento completo per sviluppatori sul sito Ulises Licenses.
Apri documentazione ufficialeIntegrazione Plugin Minecraft
1. Carica File di Configurazione
private void loadAntileakConfig() {
File myBestPluginDir = getDataFolder();
if (!myBestPluginDir.exists()) {
myBestPluginDir.mkdirs();
}
File antileakFile = new File(myBestPluginDir, "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. Validazione Licenza con Retry Logic
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 + "MyBestPlugin" + ChatColor.GRAY + "] " +
ChatColor.DARK_AQUA + "✓ Authentication successful. Powering up MyBestPlugin..."
);
Bukkit.getConsoleSender().sendMessage(
ChatColor.GRAY + "[" + ChatColor.DARK_AQUA + "MyBestPlugin" + ChatColor.GRAY + "] " +
ChatColor.GRAY + " » Discord ID: " + ChatColor.AQUA + discordId
);
loadPlugin();
} else {
String lastError = ulib.getLastError();
Bukkit.getConsoleSender().sendMessage(
ChatColor.GRAY + "[" + ChatColor.DARK_AQUA + "MyBestPlugin" + 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 + "MyBestPlugin" + 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. Controlli di Sicurezza Periodici
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 + "MyBestPlugin" + 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 + "MyBestPlugin" + 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 + "MyBestPlugin" + ChatColor.GRAY + "] " +
ChatColor.GREEN + "✓ License check passed. Status: " +
ulib.getLicenseStatus(productId, licenseKey)
);
}
}, 10L, 10L, TimeUnit.MINUTES);
}Esempio Completo di Plugin
public class MyBestPlugin 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);
}
}Metodi API Avanzati
String getDiscordId(String productId, String licenseKey)
Recupera il Discord ID associato alla licenza. Ritorna null se la validazione fallisce.
String discordId = ulib.getDiscordId(productId, licenseKey);
// Returns: <span className="text-primary">"1216532655592439862"</span>String getProductName(String productId, String licenseKey)
Recupera il nome prodotto della licenza. Ritorna null se la validazione fallisce.
String productName = ulib.getProductName(productId, licenseKey);
// Returns: <span className="text-primary">"MyBestPlugin"</span>String getExpirationDate(String productId, String licenseKey)
Recupera la data di scadenza in formato ISO. Ritorna null se la validazione fallisce.
String expiresAt = ulib.getExpirationDate(productId, licenseKey);
// Returns: <span className="text-primary">"2025-12-05T00:00:00.000Z"</span>String getLicenseStatus(String productId, String licenseKey)
Recupera lo stato licenza (attiva/revocata/scaduta). Ritorna null se la validazione fallisce.
String status = ulib.getLicenseStatus(productId, licenseKey);
// Returns: <span className="text-primary">"active"</span>String getSubType(String productId, String licenseKey)
Recupera il sottotipo licenza (Enterprise, Advanced, ecc). Ritorna null se la validazione fallisce.
String subType = ulib.getSubType(productId, licenseKey);
// Returns: <span className="text-primary">"Enterprise"</span>String getLastError()
Ritorna l’ultimo messaggio di errore. Utile per debug di connessione.
Gestione Connessione
Riconnessione Automatica
La libreria gestisce i problemi di connessione in automatico
- Retry Infinito: se il backend non risponde, la libreria riprova ogni 30 secondi fino al successo
- Messaggi Chiari: la console mostra "Unable to connect to the backend server" con countdown
- Gestione Elegante: disattiva il plugin solo per problemi reali di licenza, non di connessione
Nota Importante per Plugin Developer
Il tuo plugin deve continuare a girare durante problemi di connessione. Disattivalo solo per fallimenti reali di licenza (scaduta, revocata, invalida). I problemi di connessione richiedono retry, non shutdown immediato.
Integrazione Auto-Update
UlisesLib include metodi per check update, download ultimo jar e verifica integrità. Tutte le validazioni (stato, HWID, limiti IP) sono automatiche.
boolean checkForUpdate(String productId, String licenseKey, String currentVersion)
Verifica se esiste una versione più recente del jar. Ritorna true se c’è un update.
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)
Scarica l’ultimo jar. Gestisce HWID binding al primo download. Ritorna il File o null se fallisce.
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)
Verifica lo SHA-256 del jar scaricato per garantirne l’integrità.
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)
Ritorna l’ultima versione del jar disponibile sul server.
String latestVersion = ulib.getCurrentVersion(productId, licenseKey);
getLogger().info("Latest version available: " + latestVersion);Validazioni di Sicurezza
Tutte le operazioni di update validano automaticamente:
- Stato Licenza: solo licenze attive non scadute possono scaricare update
- HWID Binding: Hardware ID validato e legato alla licenza al primo download
- Limite IP: rispetta il limite IP configurato per licenza
Esempio Completo Auto-Update
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.");
}
}Best Practice
✓ Da Fare
- Usa retry loop infiniti per problemi di connessione
- Mostra info licenza dettagliate a validazione riuscita
- Implementa controlli periodici (ogni 10 minuti)
- Crea file di configurazione con valori default
✗ Da Evitare
- Disattivare il plugin a timeout di connessione
- Hardcodare credenziali nel sorgente
- Esporre dettagli errore agli utenti finali
- Eseguire validazione sul main thread