Revision Difference
Clothing#560473
<cat>Code.Player</cat>
<title>Clothing</title>
<deprecated>This page is outdated and needs a rewrite for the scene system due to mentions of client / server and entities</deprecated⤶
# What is Clothing?
s&box ships with pre-made clothing that developers and players alike can use to dress their character (pawn). You can view some of the available clothing from the main menu. In some gamemodes, developers may wish to manually set the clothing of players, for example to create a visual distinction between teams. You can do so by loading the clothing via the `ResourceLibrary` system using the clothing's `Resource ID`.
# Resource IDs?
Resource IDs are how s&box internally holds a reference to clothing, among other assets. You can view a list of available clothing names and resource IDs by adding the below console command to your game.
```csharp
/// <summary>
/// Debug console command to list all available player clothing.
/// </summary>
[ConCmd.Admin]
public static void ListAllClothing()
{
foreach ( var item in ResourceLibrary.GetAll<Clothing>() )
{
Log.Info( $"{item.Title} - {item.ResourceId}" );
}
}
```
# Dressing Players
Gamemodes must implement a clothing system in order to prevent naked pawns from spawning. You can do so either automatically (using the players selected clothing) or manually (for team based gamemodes, etc). s&box comes with a `ClothingContainer` class that abstracts away the loading of clothes and prevents potential collisions when adding clothes (e.g. two shirts, two shoes, etc.)
## Automatically
The following code will dress the player in whatever clothing they have selected from the main menu. Note that `Clothing.DressEntity` can dress any Pawn instance, such as NPCs.
## MyPlayer.Clothing.cs
```csharp
public partial class MyPlayer
{
public ClothingContainer Clothing { get; protected set; }
/// <summary>
/// Set the clothes to whatever the player is wearing
/// </summary>
public void UpdateClothes( IClient cl )
{
Clothing ??= new();
Clothing.LoadFromClient( cl );
}
}
```
## MyPlayer.cs
```csharp
public partial class MyPlayer : Player
{
public override void Respawn()
{
UpdateClothes( Client );
Clothing.DressEntity( this );
}
}
```
## Manually
You can also manually set player clothing, ignoring what they may have previously configured in the main menu. This is often important for team-based gamemodes.
## MyPlayer.Clothes.cs
```csharp
public partial class MyPlayer
{
public ClothingContainer Clothing { get; protected set; }
private static readonly int[] TeamAClothing =
{
1846461341, // Police Cap.
-923065548, // Suit Jacket.
1761917151, // Tactical Vest.
1194605997, // Smart Trousers.
-1377292782 // Black Boots.
};
private static readonly int[] TeamBClothing =
{
-394380878, // Prison Jumpsuit.
591027714 // Sneakers.
};
/// <summary>
/// Set the clothes depending on the players team
/// </summary>
public void UpdateClothes( IClient cl )
{
Clothing ??= new ClothingContainer();
var player = cl.Pawn as MyPlayer;
// Clear out any previously equipped clothing.
Clothing.Clothing.Clear();
// NOTE: You could refactor this code into a `GetTeamClothing` method.
if ( player.Team == Team.A )
{
foreach ( var itemId in TeamAClothing )
{
Clothing.Toggle( ResourceLibrary.Get<Clothing>( itemId ) );
}
}
else
{
foreach ( var itemId in TeamBClothing )
{
Clothing.Toggle( ResourceLibrary.Get<Clothing>( itemId ) );
}
}
}
}
```
# Whitelisting Clothing Categories
To enable some degree of customisation, you may want to allow players to configure their hair, skin, etc, while forcing them to wear a specific shirt and pair of shoes. To do this, you can whitelist certain clothing categories and manually deserialise what the player has equipped.
## MyPlayer.Clothes.cs
```csharp
public partial class MyPlayer
{
public ClothingContainer Clothing { get; protected set; }
private static readonly Clothing.ClothingCategory[] WhitelistedAccessories =
{
Sandbox.Clothing.ClothingCategory.Skin, Sandbox.Clothing.ClothingCategory.Facial,
Sandbox.Clothing.ClothingCategory.Hair
};
public void UpdateClothes( IClient cl )
{
Clothing ??= new ClothingContainer();
// Clear out any previously equipped clothing.
Clothing.Clothing.Clear();
// Only loads certain client configured clothing items.
// E.g. Hair, Skin, etc.
DeserializeAccessories( cl.GetClientData( "avatar" ) );
// ... Set the rest of the player's clothing manually ...
// (See above)
}
/// <summary>
/// Deserializes client accessories and equips them.
/// "Accessories" may include Hair, Skin, Etc.
/// </summary>
/// <param name="json"></param>
private void DeserializeAccessories( string json )
{
if ( string.IsNullOrWhiteSpace( json ) )
{
return;
}
try
{
var entries = JsonSerializer.Deserialize<ClothingContainer.Entry[]>( json );
foreach ( var entry in entries! )
{
var item = ResourceLibrary.Get<Clothing>( entry.Id );
if ( item == null ) continue;
if ( !WhitelistedAccessories.Contains( item.Category ) ) continue;
Clothing.Toggle( item );
}
}
catch ( System.Exception e )
{
Log.Warning( e, "Error deserializing accessories" );
}
}
}
```