Content generated with AI — it may contain mistakes.

Referencedev

API

Reading the trim catalogue, the halves a player combines by hand, their chosen trim, and the trims written onto armor.

ArmorTrimService is what another plugin reads and drives ExyliaArmorTrims through: the presets, the patterns and materials a player combines by hand, the trim they chose, and the trims written onto armor itself.

ExyliaAPI.get(ArmorTrimService.class).ifPresent(trims -> {
    trims.select(player, ArmorPiece.CHESTPLATE, "sentry/netherite");
    trims.trimItem("ruby").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 trim id, matched without regard to case. That is either a preset the server owner named, or the pattern/material form of a combination — the slash tells them apart, and no registry key contains one. An id that names neither is not an error, so lookups answer empty and writes answer false.

The catalogue

MethodWhat it does
trims()Every preset the server declares, in the order a menu draws them. Presets only: combinations are too many to list.
trim(String trimId)One trim as an Optional<ArmorTrim>, taking a preset id or a pattern/material combination. Empty when the id names neither.
exists(String trimId)Whether the catalogue declares that preset. Presets only — a combination is valid whenever both halves are, so ask trim for one of those.
patterns()The patterns a player can combine by hand, in menu order.
materials()The materials a player can combine by hand, in menu order.

Permissions

MethodWhat it does
canUse(Player, String trimId)Whether they may wear the trim on at least one piece.
canUse(Player, String trimId, 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 menu 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 trim on their head and nowhere else.

What the player chose

MethodWhat it does
mode()Where the trims this server draws come from, as a TrimMode.
selected(UUID player, ArmorPiece)The trim id chosen for that slot, as an Optional<String>. Empty when they chose none, the menu is off, or their selection is still being read.
select(Player, ArmorPiece, String trimId)Sets the choice for that slot. true when it was stored.
clear(Player, ArmorPiece)Takes the chosen trim off one slot. true when something was there to remove.
clearAll(Player)Takes every chosen trim 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 trim appears again the moment the player equips armor that fits.

select sets, and does not ask for a node

select is a set rather than a toggle — running it twice leaves the trim on. It is not gated by permission, because the server owner's own setting says it should not be: a trim handed out by a crate or a reward is owned whether or not a node was ever granted for it. That is the same rule ExyliaArrows follows and the opposite of ExyliaArmorSkin. Ask canUse(Player, String, ArmorPiece) first when you do want the permission to decide.

Trims on items

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

Ask isTrimItem before a container, a shop or a trade treats a stack as ordinary loot: a trim 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

ArmorTrim — id, name (colour codes still in it), permission, pieces, pattern, material and preset. supports(ArmorPiece) answers whether the trim fits a slot. A preset is an entry the owner named and has one node; a combination has an empty permission, because it is granted by the two halves behind it instead.

TrimOption — one half a player combines by hand: id, name, permission. Patterns and materials share the record, and which half one is comes from the method that handed it over. They exist because a combination is sold in halves: giving a player a preset never quietly gives them its pattern to recombine.

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.

TrimMode — where a drawn trim comes from: ITEM (only what a trim item wrote onto the armor), MENU (only what the wearer chose; trim items do nothing) or BOTH. usesItems() and usesMenu() 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 selection 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: ExyliaArmorTrims publishes none. Menu openers, the custom-tab editor flow, removers 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