You can define your own custom asset types as GameResources. They give you a nice inspector window and they're hotloaded in-game, which means you can whip things up pretty quickly if you're using them.
You can find plenty of examples of assets throughout s&box, here's a snippet from a clothing asset:
// Custom Asset named "Clothing Definition" with the extension ".clothing"
[GameResource("Clothing Definition", "clothing", "A piece of clothing.", Category = "Citizen", Icon = "checkroom")]
public partial class Clothing : GameResource
{
public string Title { get; set; }
[ResourceType( "vmdl" )]
public string Model { get; set; }
[Hide]
public int Amount { get; set; }
[JsonIgnore]
public int MySecretNumber => 10;
// ...
}
It is important to note:
Now that you've created the GameResource class, it should automatically be added to the "New" menu in the Asset Browser. If you didn't specify a Category, then it will show under "Other".
All assets are loaded when you first start the game, and there are several ways you can access them:
// Load the resource from a path
// If the asset isn't found, this returns null
Clothing = ResourceLibrary.Get<Clothing>( "config/tshirt.clothing" );
// Serves a similar purpose to Get<T> but returns a bool indicating
// whether the resource could be found. If the resource was found,
// the method provides it through an `out` parameter.
if( ResourceLibrary.TryGet<Clothing>( "config/tshirt.clothing", out var loadedClothing ) )
{
Clothing = loadedClothing;
}
else
{
// Resource couldn't be found, handle that here...
}
When assets are loaded they call their PostLoad
method. You can use this to store a list of your assets.
public partial class Clothing : GameResource
{
// Access these statically with Clothing.All
public static IReadOnlyList<Clothing> All => _all;
internal static List<Clothing> _all = new();
protected override void PostLoad()
{
base.PostLoad();
// Since you are constructing the list yourself, you could add your own logic here
// to create lists for All, AllHats, AllShirts, AllShoes, ect.
if ( !_all.Contains( this ) )
_all.Add( this );
}
}
You can use any of the Attributes you'd normally use on Properties (just like Components)