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ómo | Estado |
|---|---|---|
| Acciones propias | actions().register | API pública |
| Monedas de tu plugin | currencies().registerProviderType | API pública |
| Encantamientos en Java | pickaxe().registerEnchant | API pública, la clase base es interna |
| Fuentes de estadísticas | BonusService.register | Avanzado, 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.
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í:
rewards:
levels:
"25":
- "[crate] legendary 2"
- "[chance=10] [crate] mythic"- El
argumentllega 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.
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();
}
};
});# 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é
nulldesde 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
takedevuelvafalsemientras 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,EnchantContextyEnchantLoader.EnchantParamsestán fuera del paqueteapi: pueden cambiar entre versiones mayores.
Parámetros:
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.
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:
@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é
truesolo si el encantamiento hizo algo: cuenta para maestrías y mensajes de activación. - Usá
ChanceCalculator.roll(getLevelChance(level)): aplica la estadísticaenchant-chancey el árbol de habilidades. getLevelValueygetLevelChanceya interpolan entre los niveles delevelValuesylevelChances.- Pagar: el encantamiento paga lo suyo. Para tokens y gemas, pagá el valor base con
economy().addTokensoaddGemsy reportalo concontext.addTokenBonusoaddGemBonus: PulsePrison paga encima el extra de bonus (árbol, mascota, estadísticas) y lo muestra en la action bar. Para dinero, pagá y reportá concontext.addMoneyBonus. - Otras monedas:
currencies().give. - Experiencia del pico:
context.multiplyExp(1.5). PRE_BREAKcorre antes de pagar el bloque yPASSIVEen 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.
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);contributese 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
onDisableconunregister(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 efectoactions, 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.