1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
|
using System;
using System.Linq;
using StardewModdingAPI.Framework.Content;
using StardewModdingAPI.Framework.ContentManagers;
using StardewModdingAPI.Framework.Exceptions;
using StardewValley;
namespace StardewModdingAPI.Framework.ModHelpers
{
/// <inheritdoc cref="IGameContentHelper"/>
internal class GameContentHelper : BaseHelper, IGameContentHelper
{
/*********
** Fields
*********/
/// <summary>SMAPI's core content logic.</summary>
private readonly ContentCoordinator ContentCore;
/// <summary>The underlying game content manager.</summary>
private readonly IContentManager GameContentManager;
/// <summary>The friendly mod name for use in errors.</summary>
private readonly string ModName;
/// <summary>Encapsulates monitoring and logging.</summary>
private readonly IMonitor Monitor;
/*********
** Accessors
*********/
/// <inheritdoc />
public string CurrentLocale => this.GameContentManager.GetLocale();
/// <inheritdoc />
public LocalizedContentManager.LanguageCode CurrentLocaleConstant => this.GameContentManager.Language;
/*********
** Public methods
*********/
/// <summary>Construct an instance.</summary>
/// <param name="contentCore">SMAPI's core content logic.</param>
/// <param name="modID">The unique ID of the relevant mod.</param>
/// <param name="modName">The friendly mod name for use in errors.</param>
/// <param name="monitor">Encapsulates monitoring and logging.</param>
public GameContentHelper(ContentCoordinator contentCore, string modID, string modName, IMonitor monitor)
: base(modID)
{
string managedAssetPrefix = contentCore.GetManagedAssetPrefix(modID);
this.ContentCore = contentCore;
this.GameContentManager = contentCore.CreateGameContentManager(managedAssetPrefix + ".content");
this.ModName = modName;
this.Monitor = monitor;
}
/// <inheritdoc />
public IAssetName ParseAssetName(string rawName)
{
return this.ContentCore.ParseAssetName(rawName, allowLocales: true);
}
/// <inheritdoc />
public T Load<T>(string key)
{
IAssetName assetName = this.ContentCore.ParseAssetName(key, allowLocales: true);
return this.Load<T>(assetName);
}
/// <inheritdoc />
public T Load<T>(IAssetName assetName)
{
try
{
return this.GameContentManager.LoadLocalized<T>(assetName, this.CurrentLocaleConstant, useCache: false);
}
catch (Exception ex) when (ex is not SContentLoadException)
{
throw new SContentLoadException($"{this.ModName} failed loading content asset '{assetName}' from the game content.", ex);
}
}
/// <inheritdoc />
public bool InvalidateCache(string key)
{
IAssetName assetName = this.ParseAssetName(key);
return this.InvalidateCache(assetName);
}
/// <inheritdoc />
public bool InvalidateCache(IAssetName assetName)
{
this.Monitor.Log($"Requested cache invalidation for '{assetName}'.");
return this.ContentCore.InvalidateCache(asset => asset.Name.IsEquivalentTo(assetName)).Any();
}
/// <inheritdoc />
public bool InvalidateCache<T>()
{
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();
}
/// <inheritdoc />
public bool InvalidateCache(Func<IAssetInfo, bool> predicate)
{
this.Monitor.Log("Requested cache invalidation for all assets matching a predicate.");
return this.ContentCore.InvalidateCache(predicate).Any();
}
/// <inheritdoc />
public IAssetData GetPatchHelper<T>(T data, string assetName = null)
{
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(this.CurrentLocale, this.ContentCore.ParseAssetName(assetName, allowLocales: true), data, key => this.ParseAssetName(key).Name);
}
/// <summary>Get the underlying game content manager.</summary>
internal IContentManager GetUnderlyingContentManager()
{
return this.GameContentManager;
}
}
}
|