using System;
using System.Linq;
using StardewModdingAPI.Framework.Content;
using StardewModdingAPI.Framework.ContentManagers;
using StardewModdingAPI.Framework.Exceptions;
using StardewModdingAPI.Framework.Reflection;
using StardewValley;
namespace StardewModdingAPI.Framework.ModHelpers
{
///
internal class GameContentHelper : BaseHelper, IGameContentHelper
{
/*********
** Fields
*********/
/// SMAPI's core content logic.
private readonly ContentCoordinator ContentCore;
/// The underlying game content manager.
private readonly IContentManager GameContentManager;
/// The friendly mod name for use in errors.
private readonly string ModName;
/// Encapsulates monitoring and logging.
private readonly IMonitor Monitor;
/// Simplifies access to private code.
private readonly Reflector Reflection;
/*********
** Accessors
*********/
///
public string CurrentLocale => this.GameContentManager.GetLocale();
///
public LocalizedContentManager.LanguageCode CurrentLocaleConstant => this.GameContentManager.Language;
/*********
** Public methods
*********/
/// Construct an instance.
/// SMAPI's core content logic.
/// The mod using this instance.
/// The friendly mod name for use in errors.
/// Encapsulates monitoring and logging.
/// Simplifies access to private code.
public GameContentHelper(ContentCoordinator contentCore, IModMetadata mod, string modName, IMonitor monitor, Reflector reflection)
: base(mod)
{
string managedAssetPrefix = contentCore.GetManagedAssetPrefix(mod.Manifest.UniqueID);
this.ContentCore = contentCore;
this.GameContentManager = contentCore.CreateGameContentManager(managedAssetPrefix + ".content");
this.ModName = modName;
this.Monitor = monitor;
this.Reflection = reflection;
}
///
public IAssetName ParseAssetName(string rawName)
{
return this.ContentCore.ParseAssetName(rawName, allowLocales: true);
}
///
public T Load(string key)
where T : notnull
{
IAssetName assetName = this.ContentCore.ParseAssetName(key, allowLocales: true);
return this.Load(assetName);
}
///
public T Load(IAssetName assetName)
where T : notnull
{
try
{
return this.GameContentManager.LoadLocalized(assetName, this.CurrentLocaleConstant, useCache: true);
}
catch (Exception ex) when (ex is not SContentLoadException)
{
throw new SContentLoadException(ContentLoadErrorType.Other, $"{this.ModName} failed loading content asset '{assetName}' from the game content.", ex);
}
}
///
public bool InvalidateCache(string key)
{
IAssetName assetName = this.ParseAssetName(key);
return this.InvalidateCache(assetName);
}
///
public bool InvalidateCache(IAssetName assetName)
{
this.Monitor.Log($"Requested cache invalidation for '{assetName}'.");
return this.ContentCore.InvalidateCache(asset => asset.Name.IsEquivalentTo(assetName)).Any();
}
///
public bool InvalidateCache()
where T : notnull
{
this.Monitor.Log($"Requested cache invalidation for all assets of type {typeof(T)}. This is an expensive operation and should be avoided if possible.");
return this.ContentCore.InvalidateCache((_, _, type) => typeof(T).IsAssignableFrom(type)).Any();
}
///
public bool InvalidateCache(Func predicate)
{
this.Monitor.Log("Requested cache invalidation for all assets matching a predicate.");
return this.ContentCore.InvalidateCache(predicate).Any();
}
///
public IAssetData GetPatchHelper(T data, string? assetName = null)
where T : notnull
{
if (data == null)
throw new ArgumentNullException(nameof(data), "Can't get a patch helper for a null value.");
assetName ??= $"temp/{Guid.NewGuid():N}";
return new AssetDataForObject(
locale: this.CurrentLocale,
assetName: this.ContentCore.ParseAssetName(assetName, allowLocales: true),
data: data,
getNormalizedPath: key => this.ParseAssetName(key).Name,
reflection: this.Reflection
);
}
/// Get the underlying game content manager.
internal IContentManager GetUnderlyingContentManager()
{
return this.GameContentManager;
}
}
}