Cosmetics
Overview
Cosmetics lets players dress up and customise their gear. It covers two kinds of cosmetic. Entity cosmetics are 3D models (a hat, a backpack, wings, a halo) that follow the player, with optional particles. Item cosmetics change the model of a real item the player carries, such as an armor piece or a sword, so the new look also shows when the item is held, worn or dropped. A separate skins feature applies a wrap to the item in the player's hand.
Players pick cosmetics in a wardrobe menu with one tab per category. A cosmetic is available when it has no permission, when the player holds its permission, or when an administrator or another entry has unlocked it. Equipped and unlocked cosmetics are saved per player in artifacts.
The extension runs on the BTC build of TypeWriter (BTC Core, Paper/Folia) and is documented here for reference. Version 0.0.2 is an early release.
Features
- Entity cosmetics — attach any entity definition (an item display, a BetterModel model…) to a player, relative to the body or the head, or fixed.
- Item cosmetics — replace the
item_modeland the worn appearance of matching items, and restore them when the cosmetic is removed. - Particles — attach particle effects to a cosmetic.
- Categories and tabs — group cosmetics in categories, one tab per category, with an ownership filter (all, owned, not owned).
- One per category — a player wears one cosmetic per category at a time.
- Unlocks — free, by permission, by command, or from other entries.
- Skins — wraps for the held item, chosen in a dedicated menu, removed when the item is dropped.
- Cosmetics on entities — attach a cosmetic to an NPC or other entity with entity data.
- Placeholders and facts — show counts in other plugins and test ownership in criteria.
Installation
- Install the GUI extension (
GuiAndDialogsin the BTC build), used by both menus. - Install the TypeWriter Entity extension, or another extension that provides entity definitions, for entity cosmetics. Item cosmetics and skins do not need it.
- Optional: install CraftEngine if your item cosmetics target CraftEngine items, and the Profiles extension if cosmetics must follow the active profile.
- Put the Cosmetics JAR in
plugins/Typewriter/extensions/and restart the server. - Provide the models in your resource pack:
item_modelkeys for item cosmetics and skins (Minecraft 1.21.4 or later), andassets/<namespace>/textures/entity/equipment/textures for worn armor appearances.
Getting started
Create a hat that players unlock with a permission:
- In the TypeWriter web panel, open a manifest page and add a Cosmetic Category entry. Name it
Hatsand choose anicon. - Add a Cosmetic Definition entry. Set
categoryto the ID of the category entry (or its name if it has no ID),priority, amenuIcon, andpermission(for examplecosmetics.hat.top_hat). - In
model, reference an entity definition, for example an item display holding your hat model. SetrotationModetoRELATIVE_TO_HEADand adjustoffsetandrotationOffset. - Add a Player Cosmetics artifact so equipped and unlocked cosmetics are saved. Leave
artifactIdfor the web panel to generate. - Add a BTC Cosmetics Menu action. Build its layout in
layoutPool, with the fivecosmetics_button:markers described under Menus, and setbaseMenuIdif you use a shared menu chassis. - Publish. Give the permission to a test player, or run
/tw cosmetics give <player> <cosmetic entry id>, then run/tw cosmeticsand equip the hat.
The unlock list, the equipped list, the give command and the Has Cosmetic fact all identify a cosmetic by its entry ID, not by the cosmeticId field. The cosmeticId field is only shown as the {cosmetic_id} token in menus.
How it works
A definition is an item cosmetic when it has an itemModel or an equipmentAssetId, and also lists applicableCraftEngineIds or applicableItems. Every other definition is an entity cosmetic and uses model. Item cosmetics are applied to the matching items in the player's inventory every tick of the refresh, and the original model is kept on the item so it can be restored.
Menus
The BTC Cosmetics Menu is a GUI entry with one view per category, generated from your Cosmetic Category entries. A category used by a cosmetic but never declared still appears as a tab. Put these markers in your layout with the tag cosmetics_button:<TYPE>:
| Marker | Where | What it does |
|---|---|---|
CATEGORY_TAB | Repeatable | One tab per category. Tokens: {category_id}, {category_name}, {owned}, {total}. |
COSMETIC_SLOT | Repeatable | One slot per cosmetic of the active tab, sorted by priority. Click equips, or unequips when it is already worn. Not owned cosmetics are shown but inert. Tokens: {cosmetic_id}, {cosmetic_name}, {category_name}, {state}. |
SORT_TOGGLE | Once | Cycles between all, owned and not owned. Token: {current_filter}. The filter resets when the player leaves. |
CLEAR_CATEGORY | Once | Unequips the cosmetic of the active tab. |
PAGE_NAV | Once | Left click for the next page, right click for the previous one. Tokens: {page}, {total_pages}, {page_indicator}. Hidden when one page is enough. |
categoryView is a template cloned for each category (its name accepts {category_name} and {category_id}), and categoryViewIdPrefix (default cosmetic_) prefixes the view ids. There is no close or page-indicator marker: closing is handled by the chassis and the counter is carried by PAGE_NAV. The default texts of these buttons are in French.
The skins menu is separate: it opens with the Open Skins Menu action or /tw skins, shows the skins that apply to the item in the player's main hand, and is laid out by the Skins Menu Config entry (skinSlots, templates for unlocked, active and locked skins, and the buttons). Left click on an unlocked skin applies it, and the buttons remove the skin or apply it to every compatible item in the inventory. A skinned item that is dropped loses its skin.
Configuration
Cosmetics and skins are stored through two artifacts, loaded about one second after startup and saved a few seconds after each change:
- Player Cosmetics stores, per player, the unlocked cosmetics and the equipped one of each category.
- Player Skins stores the unlocked skins and the selected skin of each item type.
When the Profiles extension is installed, equipped cosmetics are stored under the player's active profile instead of their UUID. Cosmetics saved earlier under the UUID are not deleted, but they are no longer found. On a server that already holds real player data, migrate the keys before you install or update with Profiles present. Unlocks are always stored per player UUID.
Commands
Cosmetics commands are subcommands of the TypeWriter command, so they start with /typewriter or /tw.
| Command | Description |
|---|---|
/tw cosmetics or /tw cosmetics open | Opens the cosmetics menu. Requires cosmetics.use. |
/tw cosmetics give <player> <cosmetic> | Unlocks a cosmetic, given by its entry ID. Requires cosmetics.admin. |
/tw cosmetics remove <player> <cosmetic> | Removes an unlock. Requires cosmetics.admin. |
/tw cosmetics reset <player> | Clears the player's cosmetics. Requires cosmetics.admin. |
/tw skins or /tw skins open | Opens the skins menu for the item in hand. Requires skins.use. |
/tw skins give <player> <skin> | Unlocks a skin by its skinId. Requires skins.admin. |
/tw skins remove <player> <skin> | Removes a skin unlock. Requires skins.admin. |
/tw skins reset <player> | Clears the player's skins. Requires skins.admin. |
Menu clicks use the internal commands cosmetics ... and skins ..., handled by the extension. They are not meant to be typed by hand.
Permissions
| Permission | Grants |
|---|---|
cosmetics.use | /tw cosmetics and /tw cosmetics open. |
cosmetics.admin | give, remove and reset for cosmetics. |
skins.use | /tw skins and /tw skins open. |
skins.admin | give, remove and reset for skins. |
Cosmetic permission | A permission of your choice that unlocks one cosmetic. |
Skin permission | A permission of your choice that unlocks one skin. |
Placeholders
These are MiniPlaceholders tags of the cosmetics expansion. Replace cat with a category ID or name and id with a cosmetic entry ID.
| Placeholder | Returns |
|---|---|
<cosmetics_total_unlocked> | Number of cosmetics the player has unlocked. |
<cosmetics_total_available> | Number of cosmetic definitions on the server. |
<cosmetics_category_unlocked:cat> | Unlocked cosmetics in the category. |
<cosmetics_category_total:cat> | Cosmetics in the category. |
<cosmetics_is_unlocked:id> | true or false. |
<cosmetics_is_active:id> | true when that cosmetic is equipped. |
<cosmetics_active:cat> | The ID of the cosmetic equipped in the category, empty when none. |
<cosmetics_category_unlocked:cat> counts only cosmetics unlocked by command or by other entries, not those that are available through a permission.
Entries
11 entries, generated from the extension source.
Actions2
- BTC Cosmetics MenuBTC Cosmetics Menu
- Open Skins Menu ActionOpens the skins menu
Facts2
- Has Cosmetic FactChecks if a player has a specific cosmetic unlocked.
- Has Skin FactVérifie si un joueur possède un skin spécifique.
Entity data1
- Cosmetic Entity DataAttach cosmetics to an entity definition
Artifacts2
- Player Cosmetics ArtifactStores player unlocked cosmetics
- Player Skins ArtifactStores player selected skins
Manifests4
- Cosmetic CategoryDéfinition d'une catégorie de cosmétiques (ex: Chapeaux, Capes)
- Cosmetic DefinitionDefine a 3D Cosmetic
- Skin DefinitionDéfinition d'une catégorie de skins (wraps) pour les items
- Skins Menu ConfigConfiguration du menu des skins
Troubleshooting
The menu says "Aucun menu de cosmétiques n'est configuré". No BTC Cosmetics Menu entry is published. /tw cosmetics opens the first one it finds.
A category tab is empty or a cosmetic is missing. category on the cosmetic must match the category entry's ID (or name when it has no ID), ignoring case. A name that matches no category entry still creates a tab of its own.
The model never appears. Entity cosmetics need model to reference an entity definition. A definition that has itemModel but no applicableItems or applicableCraftEngineIds is not an item cosmetic and falls back to the entity path. For item cosmetics, the itemModel key must be a valid namespaced key (namespace:path); an invalid key is logged once as "Invalid itemModel".
The item model changes in the inventory but not on the body. itemModel only changes how the item looks in hand and in inventory. For armor, also set equipmentAssetId to the equipment asset of the material (for example armors:enderite), without the piece name. It is only applied when the worn item already carries an equippable component.
A CraftEngine item does not get the cosmetic. Use applicableCraftEngineIds with the CraftEngine id (for example armors:enderite_helmet). A CraftEngine item is recognised by its id, not by its material, so applicableItems will not match it.
Equipped cosmetics or unlocks are lost. Add the artifacts to a published page. The log reports a missing artifact or "has no generated artifact id", and nothing is saved without them. If the Profiles extension was installed recently, see the warning above.
Other players do not see my cosmetic. Entity cosmetics are fake entities. If the log shows "Viewer method ... unavailable ... owner-only fallback active", the Entity extension in use does not allow extra viewers and only the owner sees the cosmetic.
/tw skins says there is no skin for this item. The held item must match an item in applicableItems of a Skin Definition that lists at least one skin, and a skins menu entry must be published. The message texts come from the Skins Menu Config entry.
Related extensions
- GUI — menu layouts and chassis.
- Profiles — cosmetics can follow the active profile.
- BetterModel — 3D models usable as entity cosmetics.