Infraestructura Digital Profesional · Citymoon Dynamics

Citymoon DynamicsCitymoon Dynamics
ServiciosDesarrolladoresPreciosDocsForosContacto
Iniciar SesiónRegistrarse

Documentación

Citymoon Dynamics
Minecraft
Discord
Servicios Web
Ulises Licenses
Glosario
Glosario

Documentación de Ulises Licenses

Integración de Plugin de Minecraft

1. Cargar Archivo de Configuración

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. Validación de Licencia con Lógica de Reintento

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. Verificaciones de Seguridad Periódicas

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);
}

Ejemplo Completo 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étodos de API Mejorados

String getDiscordId(String productId, String licenseKey)

Recupera el ID de Discord asociado con la licencia. Retorna null si la validación falla.

String discordId = ulib.getDiscordId(productId, licenseKey);
// Returns: "1216532655592439862"

String getProductName(String productId, String licenseKey)

Recupera el nombre del producto de la licencia. Retorna null si la validación falla.

String productName = ulib.getProductName(productId, licenseKey);
// Returns: "KrakenAnticheat"

String getExpirationDate(String productId, String licenseKey)

Recupera la fecha de expiración en formato ISO. Retorna null si la validación falla.

String expiresAt = ulib.getExpirationDate(productId, licenseKey);
// Returns: "2025-12-05T00:00:00.000Z"

String getLicenseStatus(String productId, String licenseKey)

Recupera el estado de la licencia (activa/revocada/expirada). Retorna null si la validación falla.

String status = ulib.getLicenseStatus(productId, licenseKey);
// Returns: "active"

String getSubType(String productId, String licenseKey)

Recupera el subtipo de licencia (Enterprise, Advanced, etc). Retorna null si la validación falla.

String subType = ulib.getSubType(productId, licenseKey);
// Returns: "Enterprise"

String getLastError()

Retorna el último mensaje de error. Útil para depurar problemas de conexión.

Gestión de Conexión

Reconexión Automática

La biblioteca ahora maneja problemas de conexión automáticamente

  • Reintento Infinito: Cuando el backend no es accesible, la biblioteca reintenta cada 30 segundos hasta tener éxito
  • Mensajes Claros: La consola muestra "No se puede conectar al servidor backend" con cuenta regresiva de reintento
  • Manejo Elegante: Solo deshabilita el plugin para problemas reales de licencia, no problemas de conexión

Nota Importante para Desarrolladores de Plugins

Tu plugin debería continuar funcionando normalmente durante problemas de conexión. Solo deshabilita el plugin cuando hay fallas reales de validación de licencia (expirada, revocada, inválida). Los problemas de conexión deberían disparar intentos de reintento, no apagado inmediato.

Integración de Auto-Actualización

UlisesLib incluye métodos integrados para verificar actualizaciones, descargar el jar más reciente y verificar su integridad. Todas las validaciones de seguridad (estado de licencia, vinculación HWID, límites IP) se manejan automáticamente por la biblioteca.

boolean checkForUpdate(String productId, String licenseKey, String currentVersion)

Verifica si existe una versión más reciente del jar del producto. Retorna true si existe una actualización.

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)

Descarga el archivo jar más reciente. Maneja automáticamente la vinculación HWID en la primera descarga. Retorna el archivo descargado, o null si la descarga falla.

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 el checksum SHA-256 del archivo jar descargado para asegurar la integridad del archivo.

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)

Retorna la cadena de versión más reciente del jar del producto disponible en el servidor.

String latestVersion = ulib.getCurrentVersion(productId, licenseKey);
getLogger().info("Latest version available: " + latestVersion);

Validaciones de Seguridad

Todas las operaciones de actualización validan automáticamente:

  • Estado de Licencia: Solo licencias activas y no expiradas pueden descargar actualizaciones
  • Vinculación HWID: El ID de hardware se valida y vincula a la licencia en la primera descarga
  • Límite IP: Respeta el límite IP configurado por licencia

Ejemplo Completo de Auto-Actualización

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.");
    }
}

Mejores Prácticas

✓ Haz Esto

  • Usa bucles de reintento infinito para problemas de conexión
  • Muestra información detallada de licencia en validación exitosa
  • Implementa verificaciones periódicas (cada 10 minutos)
  • Crea archivo de configuración con valores predeterminados

✗ Evita Esto

  • Deshabilitar plugin en timeout de conexión
  • Codificar credenciales en código fuente
  • Exponer detalles de error a usuarios finales
  • Ejecutar validación en hilo principal
Citymoon DynamicsCitymoon Dynamics

Soluciones avanzadas para infraestructura digital. Especialistas en Minecraft, Discord y Desarrollo Web.

Servicios relacionados

  • Ulises Licenses
  • Freewings Discord Bot
  • ResistanceCore Plugin

More

  • Rymbo
  • Vulcan + Grim Prime AC Configuration

Navegación

  • Servicios
  • Impacto
  • Contacto

Legal

  • Privacidad
  • Términos
  • Cookies
  • Reembolsos

© (2026) 2025-2030 Citymoon Dynamics (citymoon.org). Todos los derechos reservados.

An international service, made in Uruguay