Docs

Extender PulsePrison

Además de leer y cambiar datos, un plugin puede agregar contenido que el dueño del servidor después usa desde YAML: tipos de acción, proveedores de monedas, encantamientos y fuentes de estadísticas.

QuéCómoEstado
Acciones propiasactions().registerAPI pública
Monedas de tu plugincurrencies().registerProviderTypeAPI pública
Encantamientos en Javapickaxe().registerEnchantAPI pública, la clase base es interna
Fuentes de estadísticasBonusService.registerAvanzado, interno

Acciones propias

Registrá un tipo y funciona en todas las listas de acciones: recompensas de niveles, logros, maestrías, boosters, habilidades, lucky blocks, bloques AFK, encantamientos propios y menús.

java
prison.actions().register("crate", (player, argument) -> {
    String[] parts = argument.split(" ");
    crates.giveKey(player, parts[0], parts.length > 1 ? Integer.parseInt(parts[1]) : 1);
});

El dueño del servidor lo usa así:

yaml
rewards:
  levels:
    "25":
      - "[crate] legendary 2"
      - "[chance=10] [crate] mythic"
  • El argument llega con {player}, los placeholders del sistema y los de PlaceholderAPI ya reemplazados.
  • Los prefijos [chance], [delay] y [permission] los resuelve PulsePrison antes de llamarte.
  • El handler corre en el hilo principal.
  • Registrá en onEnable. Un tipo con el mismo nombre que otro lo reemplaza.

Monedas de tu plugin

Agregá un valor nuevo para provider: en currencies.yml. Así cualquier servidor usa tu moneda en costos, recompensas, /balance, /pay y placeholders sin configurar comandos.

java
prison.currencies().registerProviderType("myaddon", (currencyId, section) -> {
    String account = section.getString("account", currencyId);
    return new CurrencyApi.ExternalCurrency() {
        @Override
        public double balance(UUID player) {
            return bank.get(player, account);
        }

        @Override
        public boolean add(UUID player, double amount) {
            return bank.deposit(player, account, amount);
        }

        @Override
        public boolean take(UUID player, double amount) {
            return bank.withdraw(player, account, amount);
        }

        @Override
        public boolean set(UUID player, double amount) {
            return bank.set(player, account, amount);
        }

        @Override
        public boolean available() {
            return bank.isConnected();
        }
    };
});
yaml
# currencies.yml del servidor
currencies:
  souls:
    provider: myaddon
    account: souls          # cualquier opción extra llega en "section"
    name: "Souls"
    format: "&5{amount} {name}"
  • Al registrar el tipo, PulsePrison recarga currencies.yml, así las monedas que ya lo usaban se activan aunque tu plugin cargue después.
  • Devolvé null desde la fábrica si la sección está mal configurada: esa moneda no se carga y la consola lo avisa.
  • Si tu fuente puede desconectarse, hacé que take devuelva false mientras tanto: los costos no se cobran.

Encantamientos en Java

Para efectos que YAML no alcanza, extendé BaseEnchant. El encantamiento aparece en el menú del pico, se compra con su moneda, respeta conflictos y requisitos, gana maestría y se ejecuta al minar.

BaseEnchant, EnchantContext y EnchantLoader.EnchantParams están fuera del paquete api: pueden cambiar entre versiones mayores.

Parámetros:

java
import dev.aeros.pulseprison.enchants.base.EnchantRarity;
import dev.aeros.pulseprison.enchants.base.EnchantTrigger;
import dev.aeros.pulseprison.enchants.base.EnchantType;
import dev.aeros.pulseprison.enchants.registry.EnchantLoader.EnchantParams;

public final class SoulParams {

    public static EnchantParams create() {
        EnchantParams p = new EnchantParams();
        p.id = "soul_harvest";
        p.displayName = "&5☠ Soul Harvest";
        p.type = EnchantType.PICKAXE;
        p.trigger = EnchantTrigger.POST_BREAK;
        p.rarity = EnchantRarity.EPIC;
        p.maxLevel = 50;
        p.baseCost = 100000;
        p.costMultiplier = 1.08;
        p.currency = "tokens";
        p.requiredPickaxeLevel = 20;
        p.guiSlot = 43;
        p.guiItem = "WITHER_SKELETON_SKULL";
        p.levelValues = Map.of(1, 1.0, 50, 25.0);
        p.levelChances = Map.of(1, 0.5, 50, 5.0);
        p.descriptionEN = List.of("&7Harvest souls while mining.", "&7Level {level}: &f{value} souls ({chance}%)");
        p.descriptionES = List.of("&7Cosecha almas al minar.", "&7Nivel {level}: &f{value} almas ({chance}%)");
        return p;
    }
}

Encantamiento: BaseEnchant tiene un constructor protegido con los campos de EnchantParams en orden, el mismo patrón que usan los encantamientos incluidos.

java
import dev.aeros.pulseprison.api.PulsePrisonProvider;
import dev.aeros.pulseprison.enchants.base.BaseEnchant;
import dev.aeros.pulseprison.enchants.base.EnchantContext;
import dev.aeros.pulseprison.enchants.registry.EnchantLoader.EnchantParams;
import dev.aeros.pulseprison.enchants.utils.ChanceCalculator;

public final class SoulHarvestEnchant extends BaseEnchant {

    public SoulHarvestEnchant(EnchantParams p) {
        super(p.id, p.displayName, p.type, p.trigger, p.rarity,
              p.maxLevel, p.baseCost, p.costMultiplier, p.currency,
              p.requiredPickaxeLevel, p.conflictsWith, p.requires,
              p.guiSlot, p.guiItem, p.levelValues, p.levelChances,
              p.descriptionES, p.descriptionEN);
    }

    @Override
    public boolean activate(EnchantContext context) {
        int level = context.getEnchantLevel();
        if (!ChanceCalculator.roll(getLevelChance(level))) {
            return false;
        }
        double souls = getLevelValue(level);
        PulsePrisonProvider.get().currencies().give(context.getPlayer().getUniqueId(), "souls", souls);
        return true;
    }
}

Registro:

java
@Override
public void onEnable() {
    prison = PulsePrisonProvider.get();
    prison.pickaxe().registerEnchant(new SoulHarvestEnchant(SoulParams.create()));
}

@Override
public void onDisable() {
    if (PulsePrisonProvider.isAvailable()) {
        PulsePrisonProvider.get().pickaxe().unregisterEnchant("soul_harvest");
    }
}

Qué hacer en activate

  • Devolvé true solo si el encantamiento hizo algo: cuenta para maestrías y mensajes de activación.
  • Usá ChanceCalculator.roll(getLevelChance(level)): aplica la estadística enchant-chance y el árbol de habilidades.
  • getLevelValue y getLevelChance ya interpolan entre los niveles de levelValues y levelChances.
  • Pagar: el encantamiento paga lo suyo. Para tokens y gemas, pagá el valor base con economy().addTokens o addGems y reportalo con context.addTokenBonus o addGemBonus: PulsePrison paga encima el extra de bonus (árbol, mascota, estadísticas) y lo muestra en la action bar. Para dinero, pagá y reportá con context.addMoneyBonus.
  • Otras monedas: currencies().give.
  • Experiencia del pico: context.multiplyExp(1.5).
  • PRE_BREAK corre antes de pagar el bloque y PASSIVE en cada bloque sin probabilidad propia.

Un encantamiento registrado desde Java no lee enchants.yml: sus valores son los de EnchantParams. Si querés que el dueño del servidor los cambie, leelos de un archivo de configuración de tu plugin.

Fuentes de estadísticas

Avanzado. Un addon puede sumar a las estadísticas con la misma interfaz que usan atributos, cristales y armaduras. Los bonus aparecen en /stats y afectan todo lo que usa esa estadística.

java
BonusService.BonusProvider provider = (player, sink) -> {
    int prestige = myRanks.getLevel(player);
    sink.add("sell", prestige * 0.01);
    sink.add("enchant-chance:soul_harvest", prestige * 0.02);
};

PulsePrison.getInstance().getBonusService().register(provider);
  • contribute se llama a menudo: PulsePrison cachea el total por jugador durante un segundo. Mantenelo rápido y sin consultas a base de datos.
  • Si tus valores cambian de golpe, llamá a getBonusService().invalidate(uuid).
  • Quitalo en onDisable con unregister(provider).

dev.aeros.pulseprison.bonus.BonusService es interno: puede cambiar entre versiones.


Límites actuales

  • Tipos de efecto para custom-enchants/: los encantamientos por YAML se cargan cuando arranca PulsePrison, antes que los addons, así que un addon todavía no puede agregar tipos de efecto nuevos. Usá acciones propias dentro del efecto actions, o un encantamiento en Java.
  • Menús: un addon no puede agregar acciones ni placeholders a los menús de PulsePrison. Puede agregar botones que ejecuten sus comandos o sus acciones propias.
  • Eventos: los sistemas de progresión nuevos no tienen eventos. Ver Lo que no tiene evento.
  • Artefacto: no hay repositorio Maven; se compila contra el jar.
Extending PulsePrison | PulsePrison Core Docs