ZenForge Logo
ZenForgeDocs
ZenEnchants

API para Desarrolladores

Documentación oficial y técnica de la API de ZenEnchants: catálogo de encantamientos, manipulación de ítems, libros custom, polvos mágicos, extensibilidad (efectos, condiciones, mutadores, filtros) y eventos de Bukkit.

Bienvenido a la documentación técnica y de integración de la API de ZenEnchants. Esta API está diseñada para permitir que cualquier plugin externo (sistemas de ítems custom, MMOItems, EcoItems, plugins de economía, tiendas GUI, recompensas de crates, minijuegos, etc.) interactúe de forma nativa, fluida y sin fricción con los encantamientos, libros, polvos mágicos y mecánicas del plugin.


1. Instalación y Dependencia

Para usar ZenEnchants en tu plugin, añade el .jar o artefacto como dependencia de compilación:

build.gradle.kts
repositories {
    mavenCentral()
}

dependencies {
    compileOnly(files("libs/ZenEnchants-1.0.0.jar"))
}
build.gradle
repositories {
    mavenCentral()
}

dependencies {
    compileOnly files('libs/ZenEnchants-1.0.0.jar')
}
pom.xml
<dependency>
    <groupId>com.cuac_xd.zenenchants</groupId>
    <artifactId>ZenEnchants</artifactId>
    <version>1.0.0</version>
    <scope>provided</scope>
</dependency>

Declaración en plugin.yml o paper-plugin.yml

Declara a ZenEnchants como dependencia suave (softdepend) o mandatoria (depend):

plugin.yml
name: MiPluginCustom
version: 1.0.0
main: com.miusuario.miplugin.MiPlugin
softdepend:
  - ZenEnchants

2. Punto de Entrada Principal: ZenEnchantsAPI

Todo el acceso a la API se canaliza de forma estática y segura a través de la clase: com.cuac_xd.zenenchants.api.ZenEnchantsAPI

Hilos y Ciclo de Vida

La API se inicializa automáticamente durante el onEnable de ZenEnchants. Toda operación de lectura o modificación sobre instancias de ItemStack debe ejecutarse en el hilo principal del servidor (Server Main Thread).

import com.cuac_xd.zenenchants.api.ZenEnchantsAPI;
import com.cuac_xd.zenenchants.model.ZenEnchantment;
import com.cuac_xd.zenenchants.model.Rarity;
import com.cuac_xd.zenenchants.model.EnchantmentType;
import org.bukkit.inventory.ItemStack;

3. Guía de Casos de Uso

Puedes buscar encantamientos por su ID, listar todos los registrados o consultar catálogos independientes (customs vs vanillas).

// Buscar un encantamiento por ID
Optional<ZenEnchantment> opt = ZenEnchantsAPI.getEnchantment("telepathy");
if (opt.isPresent()) {
    ZenEnchantment enchant = opt.get();
    String nombre = enchant.getDisplayNameRaw();
    int nivelMax = enchant.getMaxLevel();
    String rarezaId = enchant.getRarityId();
    String tipoId = enchant.getTypeId(); // normal, special, curse, etc.
}

// Saber si existe un ID
if (ZenEnchantsAPI.isEnchantmentRegistered("lifesteal")) {
    // Está cargado y listo
}

// Listar todos los encantamientos (customs + overrides vanilla)
List<ZenEnchantment> todos = ZenEnchantsAPI.getAllEnchantments();

// Obtener solo custom o solo vanilla
Collection<ZenEnchantment> customs = ZenEnchantsAPI.getCustomEnchantmentsCatalog();
Collection<ZenEnchantment> vanillas = ZenEnchantsAPI.getVanillaEnchantmentsCatalog();

3.2 Registro Dinámico de Encantamientos en Tiempo de Ejecución

Otros plugins pueden registrar o desregistrar encantamientos personalizados en tiempo de ejecución sin necesidad de archivos YAML:

ZenEnchantment miEnchant = new ZenEnchantment(
    "mi_encantamiento",       // id
    "<gold>Poder Oculto</gold>",// display name
    "legendary",              // rarity id
    "special",                // type id
    5,                        // max level
    true,                     // enabled
    false,                    // is vanilla
    null,                     // vanilla key
    Set.of(TargetGroup.SWORD),// targets
    Set.of("sword"),          // target ids
    Set.of("sharpness"),      // conflicts
    true,                     // table available
    true,                     // villager available
    true,                     // loot available
    List.of("<gray>Otorga un golpe devastador.</gray>"), // description
    Map.of(),                 // placeholders
    List.of()                 // configured effects
);

// Registrar
ZenEnchantsAPI.registerEnchantment(miEnchant);

// Desregistrar si fuese necesario
ZenEnchantsAPI.unregisterEnchantment("mi_encantamiento");

3.3 Consulta y Manipulación de Encantamientos en Ítems

Obtener y Comprobar Encantamientos en un Ítem

ItemStack item = player.getInventory().getItemInMainHand();

// Obtener mapa de [ID del encantamiento -> Nivel]
Map<String, Integer> enchants = ZenEnchantsAPI.getCustomEnchantments(item);

// Comprobar si tiene uno en específico
if (ZenEnchantsAPI.hasCustomEnchantment(item, "telepathy")) {
    int nivel = ZenEnchantsAPI.getEnchantmentLevel(item, "telepathy");
    player.sendMessage("¡Tu herramienta tiene Telepatía nivel " + nivel + "!");
}

Validar si un Encantamiento es Compatible

Antes de aplicar, puedes verificar si cumple los requisitos (targets, niveles, conflictos, límite global por ítem y límite por tipo):

ZenEnchantment enchant = ZenEnchantsAPI.getEnchantment("lifesteal").get();

// Validación booleana simple
if (ZenEnchantsAPI.canApply(item, enchant, 3)) {
    // Es aplicable
}

// O diagnóstico detallado del motivo por el cual no aplica:
Optional<String> error = ZenEnchantsAPI.getApplyError(item, enchant, 3);
if (error.isPresent()) {
    switch (error.get()) {
        case "incompatible-item" -> player.sendMessage("Este ítem no admite ese encantamiento.");
        case "invalid-level" -> player.sendMessage("El nivel está fuera del rango permitido.");
        case "conflict" -> player.sendMessage("Entra en conflicto con otro encantamiento presente.");
        case "enchantment-limit" -> player.sendMessage("El ítem alcanzó el límite máximo de encantamientos.");
        case "type-limit-reached" -> player.sendMessage("Has alcanzado el límite para esa categoría de encantamiento.");
    }
}

Aplicar y Remover Encantamientos

Aplica encantamientos actualizando automáticamente los tags PDC (PersistentDataContainer) y el Lore visual del ítem (soportando formateo MiniMessage):

// Aplicar por ID (retorna true si fue exitoso)
boolean exito = ZenEnchantsAPI.applyEnchantment(item, "critical_strike", 3);

// Aplicar en contexto de un jugador (dispara EnchantApplyEvent con su contexto)
ZenEnchantsAPI.applyEnchantment(player, item, "critical_strike", 3);

// Remover un encantamiento y actualizar el Lore limpiamente
ZenEnchantsAPI.removeEnchantment(player, item, "critical_strike");

// Forzar actualización visual del Lore si hiciste modificaciones manuales
ZenEnchantsAPI.updateItemLore(item);

3.4 Libros Encantados Custom y Polvos Mágicos

Libros Encantados con Probabilidad de Éxito y Destrucción

ZenEnchantment enchant = ZenEnchantsAPI.getEnchantment("bleed").get();

// Crear libro: (Encantamiento, Nivel, % Éxito, % Destrucción)
ItemStack libro = ZenEnchantsAPI.createEnchantedBook(enchant, 2, 80, 15);
player.getInventory().addItem(libro);

// Comprobar y leer metadatos de un libro
if (ZenEnchantsAPI.isCustomBook(libro)) {
    String enchantId = ZenEnchantsAPI.getBookEnchantmentId(libro).orElse("ninguno");
    int nivel = ZenEnchantsAPI.getBookEnchantmentLevel(libro);
    int exitoRate = ZenEnchantsAPI.getBookSuccessRate(libro);
    int destruccionRate = ZenEnchantsAPI.getBookDestroyRate(libro);
    
    // Modificar tasa de éxito y actualizar su Lore automáticamente
    ZenEnchantsAPI.setBookSuccessRate(libro, 100);
}

Libros Misteriosos (Mystery Books)

// Crear libro misterioso de rareza legendaria
ItemStack mysteryBook = ZenEnchantsAPI.createMysteryBook("legendary");
player.getInventory().addItem(mysteryBook);

// Validar y leer rareza
if (ZenEnchantsAPI.isMysteryBook(item)) {
    String rareza = ZenEnchantsAPI.getMysteryBookRarity(item);
}

Polvos Mágicos de Éxito (Magic Dust)

// Crear polvo mágico que añade +15% de éxito
ItemStack polvo = ZenEnchantsAPI.createMagicDust(15);
player.getInventory().addItem(polvo);

// Comprobar si un ítem es polvo mágico y obtener su valor
if (ZenEnchantsAPI.isMagicDust(item)) {
    int porcentaje = ZenEnchantsAPI.getDustRate(item);
    player.sendMessage("Este polvo añade +" + porcentaje + "% de éxito.");
}

3.5 Rarezas, Tipos y Targets

// Obtener información de una rareza
Optional<Rarity> rarezaOpt = ZenEnchantsAPI.getRarity("legendary");
rarezaOpt.ifPresent(rarity -> {
    String nombre = rarity.displayNameRaw();
    String color = rarity.colorTag();
    int pesoLoot = rarity.lootWeight();
});

// Obtener todos los tipos de encantamiento (EcoEnchants style)
for (EnchantmentType tipo : ZenEnchantsAPI.getAllTypes()) {
    String id = tipo.id();
    int limite = tipo.limit(); // -1 si es ilimitado
}

// Validar compatibilidad de target
boolean compatible = ZenEnchantsAPI.matchesTargets(List.of("pickaxe", "shovel"), Material.DIAMOND_PICKAXE);

3.6 Extensibilidad del Motor: Efectos, Condiciones, Mutadores y Filtros

ZenEnchants permite registrar efectos, condiciones, mutadores y filtros personalizados desde tu propio plugin. Una vez registrados en código Java, pueden invocarse en cualquier archivo YAML de enchants/*.yml:

Registrar Efecto Personalizado

ZenEnchantsAPI.registerCustomEffect("LIGHTNING_EXPLOSION", (context, args) -> {
    Player player = context.getPlayer();
    if (player != null && context.getTarget() != null) {
        Location loc = context.getTarget().getLocation();
        loc.getWorld().strikeLightning(loc);
        loc.getWorld().createExplosion(loc, 2.0f, false, false);
    }
});

Registrar Condición Personalizada

ZenEnchantsAPI.registerCustomCondition("IS_FULL_MOON", (context, config) -> {
    Player player = context.getPlayer();
    if (player == null) return false;
    long time = player.getWorld().getFullTime();
    long days = time / 24000;
    return (days % 8) == 0; // Luna llena
});

Registrar Mutador Personalizado

ZenEnchantsAPI.registerCustomMutator("DOUBLE_DAMAGE_MUTATOR", (context, config) -> {
    context.setDamage(context.getDamage() * 2.0);
});

Registrar Filtro Personalizado

ZenEnchantsAPI.registerCustomFilter((context, filterMap) -> {
    if (filterMap.containsKey("custom_permission")) {
        String perm = String.valueOf(filterMap.get("custom_permission"));
        return context.getPlayer() != null && context.getPlayer().hasPermission(perm);
    }
    return true;
});

Disparo Manual de Triggers y Daño de Efectos

// Procesar un trigger programáticamente sobre una espada en la mano
ExecutionContext ctx = new ExecutionContext(TriggerType.MELEE_ATTACK, player, victim, null, weapon, 1, 10.0);
ZenEnchantsAPI.processTrigger(TriggerType.MELEE_ATTACK, ctx);

// Infligir daño desde un efecto sin riesgo de causar bucles infinitos
ZenEnchantsAPI.damageFromEffect(victim, 8.5, player);

4. Eventos de la API (Bukkit Event System)

ZenEnchants despacha eventos públicos a través del gestor de eventos de Bukkit (org.bukkit.event.Listener). Todos estos eventos son cancelables (Cancellable) o modificables:

EventoPaqueteDescripciónCancelable
EnchantApplyEventcom.cuac_xd.zenenchants.api.eventSe dispara antes de aplicar un encantamiento a un ítem. Permite modificar el nivel o cancelar la aplicación.Sí
EnchantRemoveEventcom.cuac_xd.zenenchants.api.eventSe dispara antes de purgar o remover un encantamiento de un ítem.Sí
EnchantTriggerEventcom.cuac_xd.zenenchants.api.eventSe dispara en el motor antes de ejecutar los efectos de un encantamiento tras un disparador. Permite anular efectos específicos.Sí
CustomBookApplyEventcom.cuac_xd.zenenchants.api.eventSe dispara cuando un jugador aplica un libro en yunque o arrastrándolo (drag & drop). Permite editar las tasas de éxito/destrucción.Sí
MysteryBookOpenEventcom.cuac_xd.zenenchants.api.eventSe dispara al abrir un Libro Misterioso. Permite cambiar el encantamiento generado, su nivel o cancelar la apertura.Sí
MagicDustApplyEventcom.cuac_xd.zenenchants.api.eventSe dispara cuando un jugador aplica Polvo Mágico sobre un libro encantado. Permite modificar el incremento porcentual.Sí

Ejemplo: Escuchando Eventos

package com.miplugin.listeners;

import com.cuac_xd.zenenchants.api.event.EnchantApplyEvent;
import com.cuac_xd.zenenchants.api.event.CustomBookApplyEvent;
import com.cuac_xd.zenenchants.api.event.MysteryBookOpenEvent;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;

public class ZenEnchantsEventListener implements Listener {

    @EventHandler
    public void onEnchantApply(EnchantApplyEvent event) {
        if (event.getPlayer() != null && !event.getPlayer().hasPermission("miplugin.enchants.use")) {
            event.setCancelled(true);
            event.getPlayer().sendMessage("§c¡No tienes permiso para aplicar este encantamiento!");
        }
    }

    @EventHandler
    public void onCustomBookApply(CustomBookApplyEvent event) {
        // Otorgar 100% de éxito garantizado a usuarios VIP
        if (event.getPlayer().hasPermission("miplugin.vip.luck")) {
            event.setSuccessRate(100);
            event.setDestroyRate(0);
        }
    }

    @EventHandler
    public void onMysteryBookOpen(MysteryBookOpenEvent event) {
        // Notificar en el chat si un jugador reveló un encantamiento legendario o especial
        if ("legendary".equalsIgnoreCase(event.getSelectedEnchantment().getRarityId())) {
            event.getPlayer().sendMessage("§6§l¡HAS OBTENIDO UN ENCANTAMIENTO LEGENDARIO!");
        }
    }
}

5. Resumen de Métodos de ZenEnchantsAPI

// Instancia
ZenEnchantsPlugin getPlugin()

// Catálogo y Registro
Optional<ZenEnchantment> getEnchantment(String id)
boolean isEnchantmentRegistered(String id)
List<ZenEnchantment> getAllEnchantments()
Collection<ZenEnchantment> getCustomEnchantmentsCatalog()
Collection<ZenEnchantment> getVanillaEnchantmentsCatalog()
void registerEnchantment(ZenEnchantment enchantment)
boolean unregisterEnchantment(String id)

// Rarezas, Tipos y Targets
Optional<Rarity> getRarity(String id)
Collection<Rarity> getAllRarities()
Optional<EnchantmentType> getType(String id)
Collection<EnchantmentType> getAllTypes()
Optional<TargetDefinition> getTarget(String id)
boolean matchesTargets(Collection<String> targetIds, Material material)

// Manipulación de Ítems
Map<String, Integer> getCustomEnchantments(ItemStack item)
boolean hasCustomEnchantment(ItemStack item, String enchantId)
int getEnchantmentLevel(ItemStack item, String enchantId)
Optional<String> getApplyError(ItemStack item, ZenEnchantment enchantment, int level)
boolean canApply(ItemStack item, ZenEnchantment enchantment, int level)
void applyEnchantment(ItemStack item, ZenEnchantment enchantment, int level)
void applyEnchantment(Player player, ItemStack item, ZenEnchantment enchantment, int level)
boolean applyEnchantment(ItemStack item, String enchantId, int level)
boolean applyEnchantment(Player player, ItemStack item, String enchantId, int level)
void removeEnchantment(ItemStack item, String enchantId)
void removeEnchantment(Player player, ItemStack item, String enchantId)
void updateItemLore(ItemStack item)

// Libros y Polvos Mágicos
ItemStack createEnchantedBook(ZenEnchantment enchantment, int level, int successRate, int destroyRate)
boolean isCustomBook(ItemStack item)
Optional<String> getBookEnchantmentId(ItemStack item)
int getBookEnchantmentLevel(ItemStack item)
int getBookSuccessRate(ItemStack item)
void setBookSuccessRate(ItemStack item, int successRate)
int getBookDestroyRate(ItemStack item)
ItemStack createMysteryBook(String rarityId)
boolean isMysteryBook(ItemStack item)
String getMysteryBookRarity(ItemStack item)
ItemStack createMagicDust(int rate)
boolean isMagicDust(ItemStack item)
int getDustRate(ItemStack item)

// Extensibilidad del Motor
void registerCustomEffect(String effectId, EnchantEffect effect)
void registerCustomCondition(String conditionId, EnchantCondition condition)
void registerCustomMutator(String mutatorId, EnchantMutator mutator)
void registerCustomFilter(EnchantFilter filter)
void processTrigger(TriggerType trigger, ExecutionContext context)
void damageFromEffect(LivingEntity target, double amount, Entity source)

¿Te resultó útil esta página?

Tus respuestas nos ayudan a perfeccionar la wiki de ZenForge.

On this page

Soporte Oficial

¿Tienes dudas o necesitas ayuda?

Preguntas sobre configuración, guías o soporte técnico directo con nuestro equipo.

Preguntar en Discord