Saltar a contenido

API para Desarrolladores NexusPrism

Última actualización: 2026-03-22

⚠️ Traducción desactualizada (marcada 2026-08-06). La versión en inglés de esta página fue corregida para señalar que las secciones Backpacks, Energy networks, Item registry y ResearchManager describen una API que nunca existió realmente en el código. Esta traducción española aún no fue sincronizada — revisar developer/api.md (inglés) o developer/api.pt.md (portugués) para el contenido actualizado.

Esta guía explica cómo integrarse con NexusPrism desde un plugin externo de Bukkit/Paper o un addon nativo. Solo compilas contra nexusprism-api — nunca contra los JARs concretos de los módulos.


Paso 1 — Agregar la dependencia

NexusPrism se publica a través de JitPack. Agrega el repositorio y el artefato de la API a tu pom.xml:

<repositories>
    <repository>
        <id>jitpack.io</id>
        <url>https://jitpack.io</url>
    </repository>
</repositories>

<dependencies>
    <dependency>
        <groupId>com.github.TigerDevLabs.NexusPrismModularizado</groupId>
        <artifactId>nexusprism-api</artifactId>
        <version>master-SNAPSHOT</version>
        <scope>provided</scope>
    </dependency>
</dependencies>

El alcance provided es obligatorio. NexusPrism incluye la API en tiempo de ejecución — no la incluyas (shade) en tu JAR.

Para Gradle (Kotlin DSL):

repositories {
    maven("https://jitpack.io")
}

dependencies {
    compileOnly("com.github.TigerDevLabs.NexusPrismModularizado:nexusprism-api:master-SNAPSHOT")
}

Paso 2 — Declarar la dependencia en plugin.yml

Como NexusPrism es opcional para la mayoría de las integraciones, usa softdepend. Usa depend solo si tu plugin no puede funcionar sin él.

name: MiPlugin
version: 1.0.0
main: com.ejemplo.MiPlugin
api-version: "1.21"

softdepend:
  - NexusPrism

Paso 3 — Obtener la instancia de la API

Siempre obtén la API dentro de onEnable(), después de que el servidor esté completamente iniciado. Nunca la llames desde un inicializador estático o constructor.

import io.github.otiger.nexusprism.api.NexusPrismAPI;

public class MiPlugin extends JavaPlugin {

    private NexusPrismAPI nexus;

    @Override
    public void onEnable() {
        nexus = NexusPrismAPI.get();

        if (nexus == null) {
            getLogger().warning("NexusPrism no encontrado — integración desactivada.");
            return;
        }

        if (!nexus.isReady()) {
            getLogger().warning("NexusPrism todavía está iniciando.");
            return;
        }

        getLogger().info("Conectado a NexusPrism " + nexus.getVersion());
    }
}

Paso 4 — Proveedores de módulos

Cada módulo opcional de NexusPrism expone un proveedor tipado a través de un registro estático. Todos los proveedores devuelven Optional — si el módulo está desactivado o no instalado, el Optional estará vacío. Siempre usa ifPresent u orElse para manejarlo de forma segura.

Economía

UUID uuid = player.getUniqueId();

// Leer saldo
double saldo = NexusPrismAPI.economy()
        .map(eco -> eco.getBalance(uuid))
        .orElse(0.0);

// Añadir dinero
NexusPrismAPI.economy().ifPresent(eco -> eco.addMoney(uuid, 500.0));

// Cobrar al jugador (devuelve false si saldo insuficiente)
boolean exito = NexusPrismAPI.economy()
        .map(eco -> eco.withdrawMoney(uuid, 100.0))
        .orElse(false);

// Top saldos
NexusPrismAPI.economy().ifPresent(eco ->
    eco.getTopBalances(10).forEach(entry ->
        System.out.println(entry.uuid() + " → " + entry.balance())));

Autenticación / Seguridad

// Verificar si el jugador ha iniciado sesión (por defecto true si el módulo está ausente)
boolean logueado = NexusPrismAPI.auth()
        .map(auth -> auth.isAuthenticated(uuid))
        .orElse(true);

Clanes

// Obtener la etiqueta del clan del jugador
String etiqueta = NexusPrismAPI.clans()
        .flatMap(c -> c.getClanTag(uuid))
        .orElse("");

// Verificar si pertenece a un clan
boolean tieneClan = NexusPrismAPI.clans()
        .map(c -> c.isInClan(uuid))
        .orElse(false);

Essentials

// Teleportar al jugador a su home "base"
NexusPrismAPI.essentials().ifPresent(ess ->
        ess.teleportHome(player, "base"));

// Verificar estado AFK
boolean estaAfk = NexusPrismAPI.essentials()
        .map(ess -> ess.isAfk(uuid))
        .orElse(false);

Votos

// Total de votos del jugador
int votos = NexusPrismAPI.votes()
        .map(v -> v.getTotalVotes(uuid))
        .orElse(0);

// Racha actual de votos
int racha = NexusPrismAPI.votes()
        .map(v -> v.getStreak(uuid))
        .orElse(0);

Encantamientos Personalizados

// Verificar si un ítem tiene un encantamiento personalizado
boolean tieneEncant = NexusPrismAPI.enchants()
        .map(e -> e.hasEnchant(item, "SOUL_MENDER"))
        .orElse(false);

// Obtener el nivel de un encantamiento
int nivel = NexusPrismAPI.enchants()
        .map(e -> e.getLevel(item, "SOUL_MENDER"))
        .orElse(0);

Cofres (Crates)

// Dar una llave de cofre al jugador
NexusPrismAPI.crates().ifPresent(c ->
        c.giveKey(player, "VOTE_CRATE", 1));

MMO

MmoRegistry.get().ifPresent(mmo -> {
    int nivel  = mmo.getLevel(uuid);
    int mana   = mmo.getCurrentMana(uuid);
    if (mmo.hasMana(uuid, 20) && mmo.consumeMana(uuid, 20)) {
        // habilidad activada
    }
    mmo.addSkillXp(player, "warrior", 100L);
    mmo.addProfessionXp(player, "mining", 50L);
    int fuerza = mmo.getStat(uuid, "STRENGTH");
});

Chat

ChatRegistry.get().ifPresent(chat -> {
    boolean silenciado = chat.isMuted(uuid);
    chat.mute(uuid, 10 * 60 * 1000L, "Spam", "Consola");
    chat.broadcastToChannel("global", "[MiAddon] ¡Anuncio del servidor!");
    String canalActivo = chat.getActiveChannel(uuid);
});

Protecciones

ProtectionsRegistry.get().ifPresent(prot -> {
    boolean pvp = prot.isPvpAllowed(location);
    boolean enDuelo = prot.isInDuel(uuid);
    prot.getDuelOpponent(uuid).ifPresent(oponente -> { /* ... */ });
    List<String> regiones = prot.getRegionNamesAt(location);
});

Eventos (Luna de Sangre, Arco del Sacrificio, Jefe Isekai)

EventsRegistry.get().ifPresent(events -> {
    boolean lunaActiva   = events.isBloodMoonActive();
    int racha            = events.getSacrificeStreak(uuid);
    boolean enSacrificio = events.isInSacrifice(uuid);
    boolean tienJefe     = events.hasActiveBossFight(uuid);
});

Hologramas

HologramRegistry.get().ifPresent(holo -> {
    holo.create("mi_holo", location);
    holo.addLine("mi_holo", "§a¡Hola desde mi addon!");
    holo.setLine("mi_holo", 0, "§eLínea actualizada");
    holo.showToPlayer("mi_holo", player);
    holo.delete("mi_holo");
});

Mochilas

BackpackRegistry.get().ifPresent(bp -> {
    int cantidad = bp.getBackpackCount(uuid);
    bp.openFirstBackpack(player);
    bp.openBackpack(player, ids.get(0));
});

Traits (Cartas del Tarot)

TraitsRegistry.get().ifPresent(traits -> {
    List<String> cartas = traits.getCards(uuid);
    boolean tieneCarta  = traits.hasCard(uuid, "The Tower");
    int nivelInvestigacion = traits.getResearchLevel(uuid);
});

Discord

DiscordRegistry.get().ifPresent(discord -> {
    boolean vinculado = discord.isLinked(uuid);
    discord.sendMessage("server-log", "[MiAddon] ¡Algo ocurrió!");
    discord.sendWebhook("server-log", "Bot MiAddon", null, "El jugador hizo algo.");
});

Empleos

JobRegistry.get().ifPresent(empleos -> {
    Optional<String> empleoId = empleos.getActiveJob(uuid);
    boolean tieneEmpleo = empleos.hasJob(uuid);
    if (tieneEmpleo) {
        int nivel = empleos.getLevel(uuid, empleoId.get());
    }
    empleos.joinJob(uuid, "miner");
    empleos.leaveJob(uuid);
});

Redes de Energía

EnergyRegistry.get().ifPresent(energia -> {
    energia.getNetworkAt(location).ifPresent(red -> {
        long almacenado = red.getTotalStoredEnergy();
        long cap        = red.getTotalCapacity();
        int  flujo      = red.getNetFlow();
    });
    energia.registerComponent(miComponente);
    energia.unregisterComponent(miComponente);
});

Paso 10 — Carga de Contenido desde Addons

Los addons nativos pueden registrar ítems, máquinas, recetas de crafteo y recetas de infinity directamente desde archivos YAML empaquetados en el JAR.

ContentLoadResult result = content()
        .items("items.yml")
        .machines("machines.yml")
        .recipes("recipes.yml")
        .infinityRecipes("infinity_recipes")
        .register();

result.logTo(getLogger());

Recetas de Procesamiento de Máquinas (programático)

MachineProcessingRegistry.register(
    MachineProcessingRecipe.builder("mi_receta", "EXAMPLE_FURNACE")
            .input("DIAMOND", 1)
            .output("EXAMPLE_INGOT", 3)
            .time(120)
            .source(getId())
            .build()
);

// En onDisable — siempre limpia:
MachineProcessingRegistry.unregisterBySource(getId());

Paso 5 — Ítems personalizados

Usa NexusItemBuilder para inspeccionar cualquier ItemStack y verificar si es un ítem personalizado de NexusPrism.

import io.github.otiger.nexusprism.api.items.builder.NexusItemBuilder;

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

// Obtener el ID interno del ítem (ej: "COPPER_DUST", "CELESTIAL_SWORD")
String id = NexusItemBuilder.getItemId(item); // null si no es ítem NexusPrism

if ("CELESTIAL_SWORD".equals(id)) {
    player.sendMessage("¡Estás sosteniendo la Espada Celestial!");
}

Para crear un ítem del registro:

import io.github.otiger.nexusprism.api.registry.ItemRegistry;

ItemRegistry registro = nexus.getService(ItemRegistry.class);
if (registro != null) {
    registro.getItem("COPPER_DUST").ifPresent(nexusItem -> {
        ItemStack stack = nexusItem.buildStack(1);
        player.getInventory().addItem(stack);
    });
}

Paso 6 — API de Territorio

Si estás construyendo un sistema de reclamación de tierras, implementa TerritoryProvider y regístralo para que se integre con las verificaciones de protección de NexusPrism.

import io.github.otiger.nexusprism.api.territory.TerritoryProvider;
import io.github.otiger.nexusprism.api.territory.TerritoryRegistry;

public class MiProveedorRegion implements TerritoryProvider {

    @Override
    public boolean isClaimed(Location location) {
        return MiGestorRegion.isClaimed(location);
    }

    @Override
    public boolean canBuild(Player player, Location location) {
        return MiGestorRegion.canBuild(player, location);
    }

    @Override
    public boolean canInteract(Player player, Location location) {
        return MiGestorRegion.canInteract(player, location);
    }

    @Override
    public Optional<String> getClaimName(Location location) {
        return MiGestorRegion.getRegionName(location);
    }
}
private final MiProveedorRegion proveedor = new MiProveedorRegion();

@Override
public void onEnable() {
    TerritoryRegistry.register(proveedor);
}

@Override
public void onDisable() {
    TerritoryRegistry.unregister(proveedor);
}

NexusPrism usa agregación deny-wins: si cualquier proveedor deniega canBuild, la acción se bloquea.


Paso 7 — Flags de eventos

EventFlags expone flags de estado en tiempo real del módulo de eventos.

import io.github.otiger.nexusprism.api.events.EventFlags;

// ¿Está activa la Luna de Sangre?
if (EventFlags.bloodMoonActive) {
    // Aplica efectos especiales...
}

// Multiplicador de recompensa por kill (1.0 = normal, 1.5 = +50% en Luna de Sangre)
double multiplicador = EventFlags.killPayMultiplier;
double recompensa = baseRecompensa * multiplicador;

Paso 8 — Inyección de loot en estructuras

Registra un StructureProvider para inyectar loot personalizado en estructuras vanilla durante la generación.

import io.github.otiger.nexusprism.api.structures.StructureProvider;
import io.github.otiger.nexusprism.api.structures.StructureRegistry;

public class MiLootProvider implements StructureProvider {

    @Override
    public NamespacedKey structure() {
        return NamespacedKey.minecraft("village/plains/houses/plains_small_house_1");
    }

    @Override
    public List<ItemStack> loot() {
        return List.of(new ItemStack(Material.DIAMOND, 1));
    }
}

// Registrar en onEnable:
StructureRegistry.register(new MiLootProvider());

Paso 9 — Escribiendo un addon nativo

Los addons nativos son JARs colocados en plugins/NexusPrism/addons/. Son cargados directamente por NexusPrism y no necesitan plugin.yml propio.

1. Crear la clase del addon

import io.github.otiger.nexusprism.api.addon.AbstractNexusAddon;

public class MiAddon extends AbstractNexusAddon {

    @Override
    public void onEnable() {
        saveDefaultConfig();
        String msg = getConfig().getString("mensaje-bienvenida", "¡Hola!");
        getLogger().info(msg);
        getLogger().info("Conectado — NexusPrism " + getAPI().getVersion());
    }

    @Override
    public void onDisable() {
        getLogger().info(getName() + " desactivado.");
    }
}

2. Crear addon.yml dentro del JAR

id: mi-addon
name: Mi Addon
version: 1.0.0
description: Demuestra la API de addon de NexusPrism.
authors:
  - TuNombre
main: com.ejemplo.MiAddon
min-nexus-version: 1.0.0
dependencies: []
soft-dependencies: []

3. Compilar e instalar

mvn package
cp target/mi-addon-1.0.0.jar plugins/NexusPrism/addons/

Paso 11 — Proveedores de integración (permisos, placeholders, idioma)

Estas tres interfaces viven en nexusprism-api y son usadas por NexusPrism internamente. Los addons pueden leerlas vía getService() o implementarlas para reemplazar/extender el comportamiento predeterminado.

PermissionProvider

Abstrae el sistema de permisos subyacente (LuckPerms, Vault, etc.). Obtén el proveedor activo para consultar grupos, prefijo/sufijo y metadatos sin dependencia en tiempo de compilación de LuckPerms.

import io.github.otiger.nexusprism.api.integration.PermissionProvider;

PermissionProvider perms = NexusPrismAPI.get().getService(PermissionProvider.class);
if (perms == null || !perms.isAvailable()) return;

boolean isAdmin = perms.hasPermission(player, "nexusprism.admin");
String grupo    = perms.getPrimaryGroup(player).orElse("default");
String prefijo  = perms.getPrefix(player).orElse("");
int tier        = perms.getNexusTierLevel(player); // 1–5, 0 si ninguno

PlaceholderProvider

SPI que NexusPrism expone a su puente PAPI. Impleméntala y regístrala para añadir nuevos identificadores %nexusprism_*% desde tu addon.

import io.github.otiger.nexusprism.api.integration.PlaceholderProvider;

public class MisPlaceholders implements PlaceholderProvider {
    @Override public String getIdentifier() { return "miaddon"; }

    @Override
    public String onPlaceholderRequest(Player player, String params) {
        if ("puntos".equals(params)) return String.valueOf(MiAddon.getPuntos(player));
        return null;
    }
}

LangProvider

Implementado por el LanguageManager del core. Obtenlo para obtener mensajes traducidos y coloreados para un jugador específico (respetando el idioma elegido).

import io.github.otiger.nexusprism.api.lang.LangProvider;

LangProvider lang = NexusPrismAPI.get().getService(LangProvider.class);
if (lang == null) return;

String msg = lang.getMsg(player.getUniqueId(), "chat.channel-switched", "channel", "Global");
player.sendMessage(msg);

lang.setPlayerLanguage(player.getUniqueId(), "es_ES");
List<String> disponibles = lang.getAvailableLanguages(); // ["en_US", "pt_BR", ...]

Ejemplo completo de integración

Plugin que recompensa a los jugadores con dinero al matar, respetando el multiplicador de la Luna de Sangre:

package com.ejemplo;

import io.github.otiger.nexusprism.api.NexusPrismAPI;
import io.github.otiger.nexusprism.api.events.EventFlags;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.entity.PlayerDeathEvent;
import org.bukkit.plugin.java.JavaPlugin;

public class RecompensaKillPlugin extends JavaPlugin implements Listener {

    @Override
    public void onEnable() {
        if (NexusPrismAPI.get() == null) {
            getLogger().warning("NexusPrism no encontrado — recompensas desactivadas.");
            return;
        }
        getServer().getPluginManager().registerEvents(this, this);
    }

    @EventHandler
    public void onMuerteJugador(PlayerDeathEvent event) {
        if (!(event.getEntity().getKiller() instanceof Player killer)) return;

        double base = 25.0;
        double recompensa = base * EventFlags.killPayMultiplier;

        NexusPrismAPI.economy().ifPresent(eco -> {
            eco.addMoney(killer.getUniqueId(), recompensa);
            killer.sendMessage("§a+$" + String.format("%.0f", recompensa) + " §7por la kill!");
        });
    }
}

Referencia Rápida

Superficie de API Clase / método
Obtener instancia de API NexusPrismAPI.get()
Proveedores principales
Economía NexusPrismAPI.economy() → EconomyProvider
Auth NexusPrismAPI.auth() → AuthProvider
Clanes NexusPrismAPI.clans() → ClanProvider
Essentials NexusPrismAPI.essentials() → EssentialsProvider
Votos NexusPrismAPI.votes() → VoteProvider
Encantamientos NexusPrismAPI.enchants() → CustomEnchantProvider
Cofres NexusPrismAPI.crates() → CrateProvider
Proveedores de módulos
MMO (nivel, stats, maná, skills, profesiones) MmoRegistry.get() → MmoProvider
Chat (silencio, canales, broadcast) ChatRegistry.get() → ChatProvider
Protecciones (PvP, regiones, duelos) ProtectionsRegistry.get() → ProtectionsProvider
Eventos (Luna de Sangre, Sacrificio, Isekai) EventsRegistry.get() → EventsProvider
Hologramas (crear, actualizar, mostrar/ocultar) HologramRegistry.get() → HologramProvider
Mochilas (cantidad, abrir GUI) BackpackRegistry.get() → BackpackProvider
Traits / Cartas del Tarot TraitsRegistry.get() → TraitsProvider
Discord (vincular, enviar mensaje/webhook) DiscordRegistry.get() → DiscordProvider
Empleos (empleo activo, nivel, XP) JobRegistry.get() → JobProvider
Redes de energía EnergyRegistry.get() → EnergyProvider
Proveedores de integración
Backend de permisos (grupos, prefijo, meta) nexus.getService(PermissionProvider.class)
Expansión de placeholders (puente PAPI) nexus.getService(PlaceholderProvider.class)
Idioma / traducción nexus.getService(LangProvider.class)
Contenido y extensibilidad
Carga de contenido de addon content().items().machines().recipes().register()
Recetas de procesamiento de máquinas MachineProcessingRegistry.register(MachineProcessingRecipe)
ID de ítem NexusItemBuilder.getItemId(ItemStack)
Registro de ítems nexus.getService(ItemRegistry.class)
Territorio TerritoryRegistry.register(TerritoryProvider)
Estado de eventos EventFlags.bloodMoonActive, EventFlags.killPayMultiplier
Estructuras StructureRegistry.register(StructureProvider)
Base de addon nativo AbstractNexusAddon + addon.yml
Plantilla inicial O-Tiger/NexusPrism-Addon-Example

ResearchManager

Accede al árbol de investigación y al progreso del jugador de forma programática.

ResearchManager research = NexusPrismAPI.get().getService(ResearchManager.class);

ResearchManager es un sistema central, no un provider de módulo. No es accesible mediante el patrón provider/registry — usa getService().


Verificando el estado de investigación

// Via PlayerData (disponible en cualquier evento de entrada de jugador o en tu propio listener)
boolean hasUnlocked = playerData.hasCompletedResearch("copper_wire_research");
Set<String> done = playerData.getCompletedResearches();

Formato de entrada de researches.yml

copper_wire_research:
  name: "Copper Wire"
  description: "Desbloquea la receta de crafteo para Copper Wire."
  tier: BASIC                    # BASIC | ADVANCED | INFINITY
  parchment-cost: 1              # número de pergaminos consumidos
  dependencies: []               # lista de IDs de entradas que deben completarse antes
  unlocks:
    - COPPER_WIRE                # IDs de ítems añadidos a los ítems desbloqueados del jugador

Tiers y pergaminos

Tier Ítem de pergamino
BASIC RESEARCH_PARCHMENT_BASIC
ADVANCED RESEARCH_PARCHMENT_ADVANCED
INFINITY RESEARCH_PARCHMENT_INFINITY

Íconos de Categoría de la Guía (gui_items.yml)

Desde la v2.3.0, el ícono de material para cada categoría y tier de la guía se define en gui_items.yml en lugar de estar codificado directamente en Java.

# gui_items.yml
categories:
  MY_CATEGORY:
    material: ENCHANTING_TABLE
tiers:
  MY_TIER:
    material: DRAGON_EGG

La guía reconoce las entradas automáticamente al recargar. Las sustituciones en guide.yml tienen mayor prioridad que gui_items.yml. Las entradas en gui_items.yml que no estén presentes en guide.yml utilizan el valor definido aquí.


Buenas prácticas

  • Siempre verifica null en NexusPrismAPI.get() antes de usar cualquier proveedor.
  • Usa softdepend a menos que tu plugin sea literalmente un JAR de addon.
  • Nunca hagas shade de nexusprism-api — usa alcance provided/compileOnly.
  • Cancela el registro de proveedores en onDisable() para evitar listeners fantasma tras un reload.
  • Usa cadenas de Optional (ifPresent, orElse) — nunca llames .get() en un Optional vacío.
  • Verifica isReady() si llamas a la API inmediatamente en el enable.