S&box Wiki

Revision Difference

Clothing#548612

<cat>Code.Player</cat> <title>Clothing</title> # 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 ID's? Resource ID's are how s&box internally holds a reference to clothing, among other assets. You can view a list of available clothing names and resource id's by adding the below console command to your game. ```csharp /// <summary> /// Debug console command to list all available s&box clothing. /// Debug console command to list all available player clothing. /// </summary> [ConCmd.Admin] public static void ListAllClothing() { foreach (var item in ResourceLibrary.GetAll<Clothing>()) foreach ( var item in ResourceLibrary.GetAll<Clothing>() ) { Log.Info($"{item.Title} - {item.ResourceId}"); Log.Info( $"{item.Title} - {item.ResourceId}" ); } } ``` # Dressing Player's Gamemodes must implement a clothing system in order to prevent naked Pawn's 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 NPC's. ```csharp `MyPlayer.Clothing.cs` public partial class MyPlayer { public ClothingContainer Clothing { get; protected set; } /// <summary>⤶ ⤶ /// <summary>⤶ /// Set the clothes to whatever the player is wearing /// </summary> public void UpdateClothes(Client cl) public void UpdateClothes( Client cl ) { Clothing ??= new(); Clothing.LoadFromClient(cl); Clothing.LoadFromClient( cl ); } } ``` ```csharp `MyPlayer.cs` public partial class MyPlayer : Player { public override void Respawn() { UpdateClothes(Client); Clothing.DressEntity(this); 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. ```csharp `MyPlayer.Clothes.cs` public partial class MyPlayer { public ClothingContainer Clothing { get; protected set; } private static readonly int[] TeamAClothing = 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( Client 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 )⤶ { 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(Client 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 ) { foreach (var itemId in TeamAClothing) {⤶ Clothing.Toggle(ResourceLibrary.Get<Clothing>(itemId));⤶ }⤶ Clothing.Toggle( ResourceLibrary.Get<Clothing>( itemId ) ); } else⤶ }⤶ else⤶ {⤶ foreach ( var itemId in TeamBClothing )⤶ { foreach (var itemId in TeamBClothing) {⤶ Clothing.Toggle(ResourceLibrary.Get<Clothing>(itemId));⤶ }⤶ 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. ```csharp `MyPlayer.Clothes.cs` 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(Client cl) public void UpdateClothes( Client cl ) { Clothing ??= new ClothingContainer(); // Clear out any previously equipped clothing.⤶ ⤶ // 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")); DeserializeAccessories( cl.GetClientData( "avatar" ) ); // ... Set the rest of the player's clothing manually ... // (See above) } /// <summary> /// Deserialises client accessories and equips them. /// Deserializes client accessories and equips them. /// "Accessories" may include Hair, Skin, Etc. /// </summary> /// <param name="json"></param> private void DeserializeAccessories(string json) private void DeserializeAccessories( string json ) { if (string.IsNullOrWhiteSpace(json)) if ( string.IsNullOrWhiteSpace( json ) ) { return; } try { var entries = JsonSerializer.Deserialize<ClothingContainer.Entry[]>(json); foreach (var entry in entries!) 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); var item = ResourceLibrary.Get<Clothing>( entry.Id ); if ( item == null ) continue; if ( !WhitelistedAccessories.Contains( item.Category ) ) continue; Clothing.Toggle( item ); } } catch (System.Exception e) catch ( System.Exception e ) { Log.Warning(e, "Error deserializing accessories"); Log.Warning( e, "Error deserializing accessories" ); } } } ```