Skip to content

Information

OptimalCosmetics gives players a menu of equippable cosmetics - chat colors, tags, name paints, glow, tab icons, join and leave messages - with a player-to-player market and openable cases (crates) placed in the world. Players own cosmetics (there are no per-cosmetic permissions) and equip one per type.

The plugin does not render chat or nametags itself. It exposes every equipped cosmetic through PlaceholderAPI, and an external chat/nametag plugin (DeluxeChat, that kind of thing) renders them. The exceptions the plugin handles directly: join/leave messages (it sets the vanilla join/quit message), glow (it toggles the entity glow flag), and - optionally - chat colors (see Paint-Chat-Message). See Placeholders below.

  • Software: Paper / Folia (and Paper forks). api-version 1.20, Folia-supported.
  • Minecraft: 1.20+ (tested on 1.21.11)
  • Java: 21+ (required)
  • Soft dependencies: PlaceholderAPI, Vault, PlayerPoints, RivalCredits, DecentHolograms

One cosmetic can be equipped per type. Each type is one file in cosmetics/ holding many cosmetics.

Type File What it does
Chat Color chat-colors.yml Colors the player’s chat message (via placeholder, or directly with Paint-Chat-Message).
Tag tags.yml A prefix/label exposed for your chat or nametag plugin to render.
Name Paint name-paints.yml Colors/gradients the player’s name (via placeholder).
Glow glow.yml Makes the player glow. Outline color cycles via a placeholder.
Tab Icon tab-icons.yml A symbol exposed for the tab list (via placeholder).
Join Message join-messages.yml Replaces the player’s vanilla join message.
Leave Message leave-messages.yml Replaces the player’s vanilla quit message.

How players get cosmetics: an admin give, redeeming a voucher, buying on the market, or winning one from a case.

  • Seven cosmetic types, one equipped per type, stored per player (SQLite or MySQL)
  • Paginated cosmetics menu with a type filter and sort (Item / Rarity / Alphabetical)
  • Player-to-player market: list a cosmetic for sale, buy others’, with escrow, tax, fees and limits
  • Cases (crates): a placed block players pay to open, with a spin animation and limited-edition wins
  • Vouchers: redeemable items that grant a specific cosmetic
  • Fully dynamic rarities (add/remove your own; config order = rank)
  • Pluggable economy: Vault, PlayerPoints or RivalCredits
  • Every menu is a config file with action-driven items you can re-theme freely
  • Full PlaceholderAPI output in MiniMessage or legacy § form for any chat/nametag plugin
  • Folia-ready (region schedulers throughout)

Player - /cosmetics (alias /cosmetic):

  • /cosmetics - open the cosmetics menu · optimalcosmetics.use
  • /cosmetics market - open the cosmetics market · optimalcosmetics.use

Admin - /cosmeticsadmin (alias /cosmeticadmin) · all optimalcosmetics.admin:

  • /cosmeticsadmin give <player> <cosmetic|all> - grant a cosmetic, or all. Works on offline players. Blocked if the target has that cosmetic listed on the market.
  • /cosmeticsadmin remove <player> <cosmetic|all> - revoke a cosmetic, or all. Works offline.
  • /cosmeticsadmin givevoucher <player> <cosmetic> [amount] - give redeemable vouchers (online player; the cosmetic needs a Voucher block).
  • /cosmeticsadmin maxlistings <player> <amount|reset> - set or reset a player’s market listing limit.
  • /cosmeticsadmin place <case> - get a case block to place in the world.
  • /cosmeticsadmin reload - reload every config file.
  • optimalcosmetics.use - /cosmetics and the market (default: everyone)
  • optimalcosmetics.admin - every /cosmeticsadmin command, plus placing and removing case blocks in the world (default: op)

Cosmetics themselves are ownership-based, not permission-based - there are no per-cosmetic permission nodes. A player either owns a cosmetic or does not.

Requires PlaceholderAPI. Identifier optimalcosmetics. Text placeholders return MiniMessage by default, or legacy § codes when Settings.Placeholder-Format is Legacy - match this to what your chat/nametag plugin expects.

Equipped cosmetic output:

  • %optimalcosmetics_tag% - equipped tag
  • %optimalcosmetics_chatcolor% / %optimalcosmetics_chatcolor_suffix% - chat-color prefix / suffix (split around {context})
  • %optimalcosmetics_namepaint% - the player’s name, painted (%..._namepaint_suffix% is always empty)
  • %optimalcosmetics_glow% - the current glow outline color, cycling every 2 seconds
  • %optimalcosmetics_tabicon% - equipped tab icon (with a leading space), or empty

Per type (<type> = chatcolor, tag, namepaint, glow, tabicon, joinmessage, leavemessage):

  • %optimalcosmetics_<type>_id% - equipped cosmetic id (raw)
  • %optimalcosmetics_<type>_name% - equipped cosmetic display name
  • %optimalcosmetics_<type>_value% - equipped cosmetic value
  • %optimalcosmetics_<type>_count% - number of enabled cosmetics of that type
  • %optimalcosmetics_<type>_owned% - how many of that type the player owns

Totals:

  • %optimalcosmetics_count% - total enabled cosmetics
  • %optimalcosmetics_owned% - cosmetics the player owns

Players sell cosmetics they own to other players for your server currency. Listing a cosmetic puts it in escrow (it leaves the seller’s collection until it sells or is delisted). A sale charges the buyer the full price and pays the seller the price minus a configurable sale tax; an optional listing fee is charged when the item is listed. Prices are bounded by Min-Price/Max-Price, players are capped by Max-Listings, and listings expire after Expiry-Days. Full guide: Market; tuning: config.yml → Market.

A case is a block you place in the world that players pay to open. Opening plays a spin animation and awards a random cosmetic from the case’s pool; owning it already gives a voucher instead. Cases can hold limited cosmetics with a fixed number of winners. Setup: Cases; file reference: cases.yml.

A voucher is an item a player right-clicks to unlock a specific cosmetic. Admins hand them out with /cosmeticsadmin givevoucher, and cases give one when a player wins a cosmetic they already own. A cosmetic is only voucher-giveable if it has a Voucher block (or you set a global fallback in config.yml). See config.yml → Voucher and Creating Cosmetics.

Every text field supports legacy & codes, &#RRGGBB hex, MiniMessage (<gradient:a,b,c>, <rainbow>, <bold>, <#RRGGBB>, <solid:HEX>, …) and PlaceholderAPI %...%. <gradient> accepts comma-separated hex stops. Join and leave messages also support [center]...[/center] to center the line in chat. Rarity color tokens {primary} and {secondary} are filled from Rarity-Colors wherever they appear.