Installation
Install OptimalCosmetics and OptimalLibrary on your Paper or Folia server.
Requirements
Section titled “Requirements”- OptimalLibrary - required. It is a separate free plugin that every Optimal plugin runs on (text and MiniMessage, menus, storage, economy hooks, the packet holograms). OptimalCosmetics will not load without it.
- Paper or Folia (or a Paper fork) on 1.21.11, 26.1.1, 26.1.2, 26.2 or 26.3. Spigot is not supported.
- Java 21 for 1.21.11, Java 25 for the 26.x versions. Check with
java -version.
Soft dependencies, hooked only when installed:
- PlaceholderAPI - strongly recommended. The cosmetic placeholders are how your chat, tab and
nametag plugins show tags, name paints, chat colors, rank colors, glow colors and tab icons. It also
resolves
%...%from other plugins in messages, menu items and case holograms. Without it only join/leave messages, the glow outline andPaint-Chat-Messagestill work. - Vault (with an economy plugin), PlayerPoints or RivalCredits - the currency for the
market (
Settings.Economy) and for each case (Settings.Currencyin the case file). Without the configured provider, market buying and selling and opening that case are refused with a “currency unavailable” message.
Holograms above case blocks are built in. No hologram plugin is needed.
- Confirm
java -versionreports the right version for your server (21 or 25). - Stop the server.
- Drop
OptimalLibrary.jarandOptimalCosmetics.jarintoplugins/. - (Recommended) Add
PlaceholderAPI.jarand your economy plugin. - Start the server. OptimalCosmetics generates its files and prints a startup banner with the number of loaded cosmetics.
- Run
/plugins- bothOptimalLibraryandOptimalCosmeticsshould be green.
OptimalLibrary downloads sqlite-jdbc, mysql-connector-j, HikariCP and XSeries through Paper’s
library loader on first startup, so the first launch needs internet access and may take a few extra
seconds.
Generated files
Section titled “Generated files”plugins/OptimalCosmetics/├─ config.yml # settings, economy, MySQL, market, voucher, types, sorts, rarities, lore, sounds├─ messages.yml # every message, plus the type labels├─ locations.yml # placed case blocks (written by the plugin)├─ cosmetics/ # one file per type, each holding many cosmetics│ ├─ chat-colors.yml│ ├─ tags.yml│ ├─ name-paints.yml│ ├─ rank-colors.yml│ ├─ glow.yml│ ├─ tab-icons.yml│ ├─ join-messages.yml│ └─ leave-messages.yml├─ cases/│ └─ secret.yml # example case, the file name is the case id├─ guis/│ ├─ cosmetics-menu.yml # the /cosmetics menu│ ├─ equip-menu.yml # equip / unequip / sell one cosmetic│ ├─ cosmetics-market.yml # the market│ ├─ market-confirm.yml # market purchase confirmation│ └─ case-confirm.yml # case opening confirmation└─ data/ └─ data.db # SQLite data (only with Database: "SQLite")A few example cosmetics ship in each type file and one example case (secret) ships in cases/.
Before going live, check the example case’s Currency and Price, and edit or replace the example
cosmetics.
How missing files come back:
cosmetics/andcases/are only extracted when the folder does not exist. A type file you delete stays deleted (that type then has no cosmetics). Delete the whole folder to get the defaults back.- Files missing from
guis/are re-extracted on every load and reload. - Keys missing from
messages.ymlare written back with their defaults. config.ymlis created once and never merged. A setting you delete falls back to its built-in default, but the list and lore sections must stay (see config.yml).
Storage
Section titled “Storage”Everything players own is stored in SQLite at data/data.db by default: equipped cosmetics,
owned cosmetics, market listings, listing-limit overrides, pending market payouts and refunds, the
purchase journal, case rotations and limited-edition winners.
Set Settings.Database: "MySQL" and fill in the MySQL
section to share that data across a network, so ownership and equips follow a player between
servers. The market is built for this: a listing can only be bought, removed or expired once, even
when several servers share the database. Switching database needs a full restart;
/cosmeticsadmin reload does not reconnect.
When data is written:
- Ownership grants and removals are written immediately.
- Equipping or unequipping saves the player straight away. Any unsaved profile is also flushed every
Settings.Save-Intervalseconds, on quit and on shutdown. - A player’s profile is loaded while they log in. If it cannot be loaded, the login is refused with
PROFILE-LOAD-FAILEDinstead of letting them in with empty cosmetics.
Placed cases are stored in locations.yml, not in the database. Each server keeps its own.
Continue to Creating Cosmetics, or read the Information overview first.
