Skip to content

Lalyan Cosmetic Core



An API to register and customize cosmetics without using armor slots

Custom Wardrobe model and texture are made by EtherealShigure.

This plugin allows players to customize which cosmetic they have equipped, without having to use up their armor slots

It also allows plugin makers to create their custom cosmetics, without needing any java code!

The plugin features a custom GUI to customize cosmetics, which can be opened by command or, in a more immersive way, by crafting the Cosmetic Wardrobe

The Cosmetic Wardrobe can be crafted in the Builder’s Workbench using 4 of any Hardwood

The GUI provides an easy way to select cosmetics and cosmetic variants. Left-click on a cosmetic to equip it, if the cosmetic has the variant icon, right-click it to open the variant menu!

The plugin includes several commands, primarily for testing purposes:

  • /cosmetic apply <Cosmetic_ID> [Override] – Manually applies a specific cosmetic. The [Override] parameter is optional (default is yes; other value is no) and determines whether all other cosmetics of that type should be removed. Requires OP.
  • /cosmetic change – Opens the Cosmetic Customization UI. Does not require permissions.
  • /cosmetic list – Prints all loaded cosmetic IDs in the chat. Requires OP. Use --permissions to print all cosmetics alongside their relative permissions.
  • /cosmetic reload – Manually reloads all cosmetics. Requires OP.
  • /cosmetic clear – Removes all custom cosmetics and resets the default skin. Requires OP.
  • /cosmetic perms <Action> <Permission_Type> <Subject_Type> <Permission> <Subject> – Checks or modifies mod permissions. Requires OP.

These are the parameters used in the commands above.

The complete ID of the cosmetic. Use /cosmetic list to see all available IDs.

  • add: Adds a permission.
  • remove: Removes a permission.
  • check: Checks a permission status.
  • cosmetic: A permission for a specific cosmetic.
  • slot: A permission for a slot (applies to all cosmetics within it).
  • player: Sets the permission for a specific player.
  • group: Sets the permission for an entire group.

Enter the specific permission node here.
You can find more info on how permissions are formatted here.

  • If Subject_Type is player: Enter the player’s name or UUID.
  • If Subject_Type is group: Enter the group name.
!Warning! Remember that the name you give to the files is important!

Registering a cosmetic is quite simple. You’ll need to make an asset pack (obviously), and will need 3 files:

  • The cosmetic’s .blockymodel
  • The cosmetic’s .png texture
  • The cosmetic’s .png icon, which is the same icon you would use for the item!

These files must be named in the same way, that being CustomID.extension

Each cosmetic will be its own folder, with this structure

CustomID/
├── CustomID.blockymodel
├── CustomID.png
└── Icon/
└── CustomID.png

Then the cosmetic will go in a certain folder, depending on the type:

The base path for cosmetics is Common/Resources/ (For backwards compatibility the folders Common/Resources/Cosmetics and Common/Resources/Characters are also checked), then the folder based on the slot, which can be:

  • Capes
  • Ears_Accessories
  • Gloves
  • Head
  • Face_Accessories
  • Overpants
  • Overtops
  • Pants
  • Shoes
  • Undertops
  • Underwears
  • Beards
  • Ears
  • Eyebrows
  • Eyes
  • Faces
  • Mouth
  • Haircuts
  • Hair_Extension
  • Wings
  • Tails
  • Horns
  • Face_Details

Then the folder you made before.

So, for a cosmetic called Custom_Cape, which is in the cape slot it would be like this:

Common/Resources/Capes/Custom_Cape and inside the Custom_Cape folder:

Custom_Cape/
├── Custom_Cape.blockymodel
├── Custom_Cape.png
└── Icon/
└── Custom_Cape.png

The Hair_Extension slot automatically takes the same gradient as the Hairstyle.

!Warning! Variants and colors are mutually exclusive!
!Warning! Hair extensions cannot have variants nor colors, they changes according to the hairstyle!

This API also allows you to add variants.

To add variants, you will need to add the variant texture and icon inside your cosmetic’s folder.

The variant textures must be placed in the cosmetic folder (CustomID) and named as follows:

CustomID_Variant_VariantName.png

The variant icons must have the same name given to the variant texture, but unlike the texture, they must be placed inside the Icon/ folder.

Taking the Propeller_Hat as an example:

Propeller_Hat/
├── Propeller_Hat.blockymodel
├── Propeller_Hat.png
├── Propeller_Hat_Variant_Circus.png
├── Propeller_Hat_Variant_Rainbow.png
└── Icon/
├── Propeller_Hat.png
├── Propeller_Hat_Variant_Circus.png
└── Propeller_Hat_Variant_Rainbow.png

Doing so, the API will load: Propeller_Hat, Propeller_Hat_Variant_Circus, Propeller_Hat_Variant_Rainbow.

They will be seen by the API as variants of the same cosmetic, so they will implicitly use Propeller_Hat.blockymodel

!Warning! Variants and colors are mutually exclusive!
!Warning! Hair extensions cannot have variants nor colors, they change according to the hairstyle!

This API also allows you to add multiple colors to a cosmetic!

To add colors you need to change the folder of your cosmetic like this: Cosmetic_Id_Colors_GRADIENTSET

The texture has to be grayscale (completely desaturated).

here’s a list of all available gradient sets:

  • Colored_Cotton
  • Eyes_Gradient
  • Faded_Leather
  • Fantasy_Cotton
  • Fantasy_Cotton_Dark
  • Flashy_Synthetic
  • Hair
  • Jean_Generic
  • Ornamented_Metal
  • Pastel_Cotton
  • Rotten_Fabric
  • Shiny_Fabric
  • Skin

Here’s an example: Item name: Sample_Shirt Alternative: Colors Gradient Set: Colored_Cotton

The folder name is: Sample_Shirt_Colors_Colored_Cotton

The folder structure is:

Sample_Shirt_Colors_Colored_Cotton/
├── Sample_Shirt.blockymodel
├── Sample_Shirt.png
└── Icon/
└── Sample_Shirt.png

model, texture and icon’s names have to be just the name without _Colors_GRADIENTSET

Inside your cosmetic folder, you can add a Cosmetic_Id.json file. This file allows you to customize even more your cosmetics.

Within the JSON file, you are able to change the name and path of the model, texture and icon of your cosmetic. And that’s not all, you’ll also be able to define variants and color gradients of your cosmetic and if the cosmetic occupies MORE THAN ONE SLOT!

{
"Model": "Resources/Cosmetics/Head/Propeller_Hat/Propeller_Hat.blockymodel",
"Texture": "Resources/Cosmetics/Head/Propeller_Hat/Propeller_Hat.png",
"Icon": "Resources/Cosmetics/Head/Propeller_Hat/Propeller_Hat_Icon.png",
"SlotOverrides": [
//Insert slots here, for example "Head", "Capes" etc
],
"Alternatives": {
//THESE 2 ARE MUTUALLY EXCLUSIVE, YOU EITHER HAVE VARIANTS OR COLORS!!!
//Choice 1 (Colors)
"Gradient_Set": "Hair",
//Choice 2 (Variants)
"Variants": {
"Variant": {
"Texture": "Resources/Cosmetics/Head/Propeller_Hat/Variant/Variant.png",
"Icon": "Resources/Cosmetics/Head/Propeller_Hat/Variant/Variant_Icon.png"
}
}
},
"Default_Color": {
"Gradient_Set": "Hair",
"Gradient_Id": "Red"
}
}

“Model” Is the path of the base cosmetic model and any variants.

“Texture” Is the path of the base cosmetic texture and any variants.

“Icon” Is the path of the base cosmetic icon.

“Alternatives” Defines that the cosmetic has 1 of 2 alternative styles

“Default_Color” If your cosmetic is grayscale, this can define which color the main slot should equip

“Alternatives” > “Variants” Announces the presence of variants that will be listed.

“Alternatives” > “Variants” > “Variant1Name” Will be replaced with the name of the first variant.

“Alternatives” > “Variants” > “Variant2Name” Will be replaced with the name of the second variant.

Inside the variant names mentioned above are the definitions of the variant components.

“Alternatives” > “Variants” > “VariantName” > “Texture” Is the path of the texture of the variant in question.

“Alternatives” > “Variants” > “VariantName” > “Icon” Is the path of the icon of the variant in question.

“Alternatives” > “Gradient_Set” Tells the game which gradient set to use

Gradient List:

  • Colored_Cotton
  • Eyes_Gradient
  • Faded_Leather
  • Fantasy_Cotton
  • Fantasy_Cotton_Dark
  • Flashy_Synthetic
  • Hair
  • Jean_Generic
  • Ornamented_Metal
  • Pastel_Cotton
  • Rotten_Fabric
  • Shiny_Fabric
  • Skin

Since version 2.0, you can also add custom Categories (The left-most buttons) and Slots (The middle-left buttons).

Categories are purely cosmetic, while slots can also be used when making a cosmetic

Cosmetic json schema:

{
"Name": "Capes"
}

Name: The name to display when hovering over the button, also used when assigning it to a slot, CAN ONLY HAVE UPPERCASE OR LOWERCASE LETTERS, CANNOT HAVE NUMBERS, UNDERSCORES OR ANY OTHER SPECIAL CHARACTER

Slot json schema:

{
"Name": "Capes",
"Icon": "UI/Custom/Common/Categories/Categories/Capes.png",
"SelectedIcon": "UI/Custom/Common/Categories/Categories/Selected/Capes.png",
"TopLevelCategory": "Capes",
"Camera": {
"Distance": 2,
"Position_Offset": {
"X": 0.0,
"Y": -0.3,
"Z": 0.0
},
"LookAtBack": true
},
"CanVanish": true
}

Name: The name to display when hovering over the button, also used when assigning it to a cosmetic, CAN ONLY HAVE UPPERCASE OR LOWERCASE LETTERS, CANNOT HAVE NUMBERS, UNDERSCORES OR ANY OTHER SPECIAL CHARACTER
Icon: The icon of the button
SelectedIcon: The icon of the button used when the slot is the current one being displayed
TopLevelCategory: The category that will be assigned to the slot (see above)
Camera: The camera settings used when this slot is selected
CanVanish: Whether the slot has a vanish button (Faces is the only “vanilla” one that doesn’t)

Permissions can be enabled trough the configuration file.

The permissions are made like this: lalyancosmeticcore.[FIELD].[ID].[ACTION]

If you aren’t using luckperms the mod will automatically use the vanilla permission’s system.

If you are using luckperms the mod will automatically use the luckperms permission’s system.

The fields are permissions’ groups.

the cosmetic field is for get the permissions for a specific cosmetic.

It’s written like this: lalyancosmeticcore.cosmetic.[Cosmetic_ID].[ACTION].

A few examples:

lalyancosmeticcore.cosmetic.GoodWitchLalya:ExampleCosmetics#Propeller_Hat.use
lalyancosmeticcore.cosmetic.GoodWitchLalya:ExampleCosmetics#Rainbow_Shirt.use

If you want to know how’s written a permission for a specific cosmetic you can sue /cosmetic list --permissions to get a list of all of the permissions

the slot field is for get the permissions for a specific slot and all of its cosmetics.

It’s written like this: lalyancosmeticcore.slot.[Slot_ID].[ACTION].

A few examples:

lalyancosmeticcore.slot.Head.use
lalyancosmeticcore.slot.Overpants.use

the list with all of the slots: Here(character), Here(cosmetic)

at the moment ther’s only one action, use.

this permission decides if a player can view and set a cosmetic or a view slot.

At the moment the configuration file only has the Enable Permissions voice.

The configuration for the Enable Permissions value works this way:

If the value is true:
The permission system will be enabled letting a player use a cosmetic only if they have the right permission.

If the value is false:
The API will work as it always has: Everyone can use everything.

This value is set to false by default.


Project released under license GNU AGPLv3.