using System.Diagnostics.CodeAnalysis;
using Robust.Client.ResourceManagement;
using Robust.Shared.Utility;
namespace Content.Client.Stylesheets;
public abstract partial class BaseStylesheet
{
///
/// The file roots of the stylesheet, dictates where assets get read from for the given type of resource.
/// Roots will be checked in order for assets, avoid having a significant number of them.
///
///
/// Must be a constant, changes to this after construction will not be reflected.
///
public abstract Dictionary Roots { get; }
///
/// Attempts to locate a resource within the stylesheet's roots.
///
/// The relative path of the target resource.
/// The discovered/cached resource, if any.
/// Type of the resource to read.
/// Whether is null.
public bool TryGetResource(ResPath target, [NotNullWhen(true)] out T? resource)
where T : BaseResource, new()
{
DebugTools.Assert(target.IsRelative,
"Target path must be relative. Use ResCache directly if you need an absolute file location.");
foreach (var root in Roots[typeof(T)])
{
if (ResCache.TryGetResource(root / target, out resource))
return true;
}
resource = null;
return false;
}
///
/// Retrieves a resource, or throws.
///
/// The relative path of the target resource.
/// Type of the resource to read.
/// The retrieved resource
/// Thrown if the resource does not exist within the stylesheet's roots.
public T GetResource(ResPath target)
where T : BaseResource, new()
{
if (TryGetResource(target, out T? res))
return res;
throw new MissingStyleResourceException(this, target.ToString());
}
///
/// Retrieves a resource, or falls back to the specified root. The resource should be present at the fallback
/// root, or else it throws
///
///
/// This should be used to allow common sheetlets to be generic over multiple stylesheets without forcing other
/// styles to have the resource present, if your sheetlet is stylesheet-specific you should not use this.
///
/// The relative path of the target resource.
/// The root that this resource will always exist at
/// Type of the resource to read.
/// The retrieved resource
/// Thrown if the resource does not exist in the fallback root.
public T GetResourceOr(ResPath target, ResPath fallbackRoot)
where T : BaseResource, new()
{
DebugTools.Assert(fallbackRoot.IsRooted,
"Fallback root must be absolute. Roots can be retrieved from the stylesheets.");
if (!ResCache.TryGetResource(fallbackRoot / target, out T? fallback))
throw new ExpectedResourceException(this, target.ToString());
return TryGetResource(target, out T? res) ? res : fallback;
}
}
///
/// Exception thrown when the never-fail helpers in fail to locate a resource.
///
/// The stylesheet
///
public sealed class MissingStyleResourceException(BaseStylesheet sheet, string target) : Exception
{
public override string Message =>
$"Failed to find any resource at \"{target}\" for {sheet}. The roots are: {sheet.Roots}";
public override string? Source => sheet.ToString();
}
///
/// Exception thrown when the never-fail helpers in expect a resource at a location
/// but do not find it.
///
/// The stylesheet
///
public sealed class ExpectedResourceException(BaseStylesheet sheet, string target) : Exception
{
public override string Message =>
$"Failed to find any resource at \"{target}\" for {sheet}, when such a resource was expected.";
public override string? Source => sheet.ToString();
}