Content generated with AI — it may contain mistakes.

Referencedev

API

Reading the skin catalogue, a player's wardrobe, and the skins written onto armor.

ArmorSkinService is what another plugin reads and drives ExyliaArmorSkin through: the catalogue, the wardrobe a player chooses in, and the skins written onto armor itself.

ExyliaAPI.get(ArmorSkinService.class).ifPresent(skins -> {
    skins.select(player, ArmorPiece.HELMET, "sakura");
    skins.skinItem("sakura").ifPresent(item -> player.getInventory().addItem(item));
});
Adding it to your project

The artifact, the repository and the plugin.yml line are the same for every Exylia plugin and live on the public API page.

Everything is addressed by skin id, matched without regard to case. An id the catalogue does not declare is not an error — a reload can remove one while a crate still hands it out — so lookups answer empty and writes answer false.

The catalogue

MethodWhat it does
skins()Every skin the server declares, in the order a menu draws them. A snapshot: fine for building a shop, wasteful in a loop.
skin(String skinId)One skin as an Optional<ArmorSkin>. Empty when the catalogue declares no such id.
exists(String skinId)Whether the catalogue declares that id.

Permissions

MethodWhat it does
canUse(Player, String skinId)Whether they may wear the skin on at least one piece.
canUse(Player, String skinId, ArmorPiece)Whether they may wear it on that one piece.

Both answer by the server's own rule, which includes the setting that turns permissions off entirely — a shop asking gets the same answer the wardrobe would give, not a raw permission check. The per-piece form is separate because a rank can be sold one slot at a time: a player given the helmet node wears the skin on their head and nowhere else.

The wardrobe

MethodWhat it does
mode()Where the skins this server draws come from, as a SkinMode.
selected(UUID player, ArmorPiece)The skin id chosen for that slot, as an Optional<String>. Empty when they chose none, the wardrobe is off, or their wardrobe is still being read.
select(Player, ArmorPiece, String skinId)Sets the choice for that slot. true when it was stored.
clear(Player, ArmorPiece)Takes the chosen skin off one slot. true when something was there to remove.
clearAll(Player)Takes every chosen skin off. true when something was there to remove.

selected is a choice, not a result: it stays set while the slot is empty, and the skin appears again the moment the player equips armor that fits.

select sets, and here it also checks

select is a set rather than a toggle — running it twice leaves the skin on. In this plugin it is gated by permission: the wardrobe offers one write, that write enforces the server's rule, and a player who may not wear the skin is refused. That is the opposite of ExyliaArmorTrims and ExyliaArrows, where the owner's own setting says selection is never limited by a node. Ask canUse(Player, String, ArmorPiece) first if you want to know why before asking.

Skins on items

MethodWhat it does
skinOf(ItemStack armor)The skin id written onto that armor, as an Optional<String>. Empty when it carries none.
apply(ItemStack armor, String skinId)Writes a skin onto the armor in place, keeping everything else it had. true when written.
strip(ItemStack armor)Takes the skin off and gives nothing back. true when a skin was there.
skinItem(String skinId)A skin item ready to be given out, as an Optional<ItemStack>. Empty when the catalogue declares no such skin.
isSkinItem(ItemStack)Whether an item is one of this plugin's skin items.

Ask isSkinItem before a container, a shop or a trade treats a stack as ordinary loot: a skin item is drawn as whatever suits it and is not the material it looks like.

Redrawing

MethodWhat it does
refresh(Player)Recomputes what the player looks like and re-sends it to everyone who can see them.

Only needed after something the service does not know about changed — a permission granted at runtime, an item swapped by another plugin. Every write above already redraws.

Types

ArmorSkin — id, name (colour codes still in it), permission (the node granting the skin on every piece it fits) and pieces. supports(ArmorPiece) answers whether the skin fits a slot. What the skin looks like is deliberately absent: that is the plugin's own drawing code, and skinItem already covers what a third party needs.

ArmorPiece — HELMET, CHESTPLATE, LEGGINGS, BOOTS. slot() gives the Bukkit EquipmentSlot, so a caller reading an inventory does not keep a switch of its own in step.

SkinMode — where a drawn skin comes from: ITEM (only what a skin item wrote onto the armor), WARDROBE (only what the wearer chose; skin items do nothing) or BOTH. usesItems() and usesWardrobe() answer without a switch. Worth asking before writing anything: the half a server does not use answers false or empty rather than throwing, so an integration written for both runs on either.

Queries are cheap, actions are not

Everything returning a value reads the plugin's cache and is safe from a menu redraw or a placeholder. Everything that changes a wardrobe writes to the database and redraws the player for everyone watching — call those on the main thread, and no more often than a player could.

What it does not expose

No events: ExyliaArmorSkin publishes none. Menu openers, the wardrobe's own editor flow, animation definitions and raw configuration rows are left out on purpose — a public contract cannot be broken later, so it carries what an integration needs and nothing that only made sense inside one version.

If something you need is genuinely missing, ask on Discord.

Something missing on this page? Tell us on Discord