summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/SMAPI.Mods.ConsoleCommands/manifest.json4
-rw-r--r--src/SMAPI.Mods.ErrorHandler/manifest.json4
-rw-r--r--src/SMAPI.Mods.SaveBackup/manifest.json4
-rw-r--r--src/SMAPI.Web/Framework/Clients/CurseForge/CurseForgeClient.cs25
-rw-r--r--src/SMAPI.Web/Framework/Clients/CurseForge/ResponseModels/ModLinksModel.cs7
-rw-r--r--src/SMAPI.Web/Framework/Clients/CurseForge/ResponseModels/ModModel.cs41
-rw-r--r--src/SMAPI.Web/Framework/Clients/CurseForge/ResponseModels/ResponseModel.cs8
-rw-r--r--src/SMAPI.Web/Framework/ConfigModels/ApiClientsConfig.cs3
-rw-r--r--src/SMAPI.Web/Startup.cs3
-rw-r--r--src/SMAPI.Web/appsettings.json3
-rw-r--r--src/SMAPI/Constants.cs2
-rw-r--r--src/SMAPI/Framework/ContentCoordinator.cs36
-rw-r--r--src/SMAPI/Framework/ContentManagers/BaseContentManager.cs27
-rw-r--r--src/SMAPI/Framework/ContentManagers/GameContentManager.cs2
-rw-r--r--src/SMAPI/Framework/ContentManagers/IContentManager.cs11
-rw-r--r--src/SMAPI/Framework/Utilities/TickCacheDictionary.cs26
-rw-r--r--src/SMAPI/Metadata/CoreAssetPropagator.cs607
17 files changed, 459 insertions, 354 deletions
diff --git a/src/SMAPI.Mods.ConsoleCommands/manifest.json b/src/SMAPI.Mods.ConsoleCommands/manifest.json
index 78d26802..7b403a75 100644
--- a/src/SMAPI.Mods.ConsoleCommands/manifest.json
+++ b/src/SMAPI.Mods.ConsoleCommands/manifest.json
@@ -1,9 +1,9 @@
{
"Name": "Console Commands",
"Author": "SMAPI",
- "Version": "3.14.4",
+ "Version": "3.14.5",
"Description": "Adds SMAPI console commands that let you manipulate the game.",
"UniqueID": "SMAPI.ConsoleCommands",
"EntryDll": "ConsoleCommands.dll",
- "MinimumApiVersion": "3.14.4"
+ "MinimumApiVersion": "3.14.5"
}
diff --git a/src/SMAPI.Mods.ErrorHandler/manifest.json b/src/SMAPI.Mods.ErrorHandler/manifest.json
index be1030f4..2ac959bb 100644
--- a/src/SMAPI.Mods.ErrorHandler/manifest.json
+++ b/src/SMAPI.Mods.ErrorHandler/manifest.json
@@ -1,9 +1,9 @@
{
"Name": "Error Handler",
"Author": "SMAPI",
- "Version": "3.14.4",
+ "Version": "3.14.5",
"Description": "Handles some common vanilla errors to log more useful info or avoid breaking the game.",
"UniqueID": "SMAPI.ErrorHandler",
"EntryDll": "ErrorHandler.dll",
- "MinimumApiVersion": "3.14.4"
+ "MinimumApiVersion": "3.14.5"
}
diff --git a/src/SMAPI.Mods.SaveBackup/manifest.json b/src/SMAPI.Mods.SaveBackup/manifest.json
index 8a50162e..707b6d8a 100644
--- a/src/SMAPI.Mods.SaveBackup/manifest.json
+++ b/src/SMAPI.Mods.SaveBackup/manifest.json
@@ -1,9 +1,9 @@
{
"Name": "Save Backup",
"Author": "SMAPI",
- "Version": "3.14.4",
+ "Version": "3.14.5",
"Description": "Automatically backs up all your saves once per day into its folder.",
"UniqueID": "SMAPI.SaveBackup",
"EntryDll": "SaveBackup.dll",
- "MinimumApiVersion": "3.14.4"
+ "MinimumApiVersion": "3.14.5"
}
diff --git a/src/SMAPI.Web/Framework/Clients/CurseForge/CurseForgeClient.cs b/src/SMAPI.Web/Framework/Clients/CurseForge/CurseForgeClient.cs
index d351b42d..9b4f2580 100644
--- a/src/SMAPI.Web/Framework/Clients/CurseForge/CurseForgeClient.cs
+++ b/src/SMAPI.Web/Framework/Clients/CurseForge/CurseForgeClient.cs
@@ -1,4 +1,5 @@
using System.Collections.Generic;
+using System.Net;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using Pathoschild.Http.Client;
@@ -33,9 +34,12 @@ namespace StardewModdingAPI.Web.Framework.Clients.CurseForge
/// <summary>Construct an instance.</summary>
/// <param name="userAgent">The user agent for the API client.</param>
/// <param name="apiUrl">The base URL for the CurseForge API.</param>
- public CurseForgeClient(string userAgent, string apiUrl)
+ /// <param name="apiKey">The API authentication key.</param>
+ public CurseForgeClient(string userAgent, string apiUrl, string apiKey)
{
- this.Client = new FluentClient(apiUrl).SetUserAgent(userAgent);
+ this.Client = new FluentClient(apiUrl)
+ .SetUserAgent(userAgent)
+ .AddDefault(request => request.WithHeader("x-api-key", apiKey));
}
/// <summary>Get update check info about a mod.</summary>
@@ -49,11 +53,18 @@ namespace StardewModdingAPI.Web.Framework.Clients.CurseForge
return page.SetError(RemoteModStatus.DoesNotExist, $"The value '{id}' isn't a valid CurseForge mod ID, must be an integer ID.");
// get raw data
- ModModel? mod = await this.Client
- .GetAsync($"addon/{parsedId}")
- .As<ModModel?>();
- if (mod == null)
+ ModModel? mod;
+ try
+ {
+ ResponseModel<ModModel> response = await this.Client
+ .GetAsync($"mods/{parsedId}")
+ .As<ResponseModel<ModModel>>();
+ mod = response.Data;
+ }
+ catch (ApiException ex) when (ex.Status == HttpStatusCode.NotFound)
+ {
return page.SetError(RemoteModStatus.DoesNotExist, "Found no CurseForge mod with this ID.");
+ }
// get downloads
List<IModDownload> downloads = new List<IModDownload>();
@@ -65,7 +76,7 @@ namespace StardewModdingAPI.Web.Framework.Clients.CurseForge
}
// return info
- return page.SetInfo(name: mod.Name, version: null, url: mod.WebsiteUrl, downloads: downloads);
+ return page.SetInfo(name: mod.Name, version: null, url: mod.Links.WebsiteUrl, downloads: downloads);
}
/// <summary>Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.</summary>
diff --git a/src/SMAPI.Web/Framework/Clients/CurseForge/ResponseModels/ModLinksModel.cs b/src/SMAPI.Web/Framework/Clients/CurseForge/ResponseModels/ModLinksModel.cs
new file mode 100644
index 00000000..2f9abe4f
--- /dev/null
+++ b/src/SMAPI.Web/Framework/Clients/CurseForge/ResponseModels/ModLinksModel.cs
@@ -0,0 +1,7 @@
+namespace StardewModdingAPI.Web.Framework.Clients.CurseForge.ResponseModels
+{
+ /// <summary>A list of links for a mod.</summary>
+ /// <param name="WebsiteUrl">The URL for the CurseForge mod page.</param>
+ /// <param name="SourceUrl">The URL for the mod's source code, if any.</param>
+ public record ModLinksModel(string WebsiteUrl, string? SourceUrl);
+}
diff --git a/src/SMAPI.Web/Framework/Clients/CurseForge/ResponseModels/ModModel.cs b/src/SMAPI.Web/Framework/Clients/CurseForge/ResponseModels/ModModel.cs
index fd7796f2..7018be54 100644
--- a/src/SMAPI.Web/Framework/Clients/CurseForge/ResponseModels/ModModel.cs
+++ b/src/SMAPI.Web/Framework/Clients/CurseForge/ResponseModels/ModModel.cs
@@ -1,38 +1,9 @@
namespace StardewModdingAPI.Web.Framework.Clients.CurseForge.ResponseModels
{
- /// <summary>An mod from the CurseForge API.</summary>
- public class ModModel
- {
- /*********
- ** Accessors
- *********/
- /// <summary>The mod's unique ID on CurseForge.</summary>
- public int ID { get; }
-
- /// <summary>The mod name.</summary>
- public string Name { get; }
-
- /// <summary>The web URL for the mod page.</summary>
- public string WebsiteUrl { get; }
-
- /// <summary>The available file downloads.</summary>
- public ModFileModel[] LatestFiles { get; }
-
-
- /*********
- ** Public methods
- *********/
- /// <summary>Construct an instance.</summary>
- /// <param name="id">The mod's unique ID on CurseForge.</param>
- /// <param name="name">The mod name.</param>
- /// <param name="websiteUrl">The web URL for the mod page.</param>
- /// <param name="latestFiles">The available file downloads.</param>
- public ModModel(int id, string name, string websiteUrl, ModFileModel[] latestFiles)
- {
- this.ID = id;
- this.Name = name;
- this.WebsiteUrl = websiteUrl;
- this.LatestFiles = latestFiles;
- }
- }
+ /// <summary>A mod from the CurseForge API.</summary>
+ /// <param name="Id">The mod's unique ID on CurseForge.</param>
+ /// <param name="Name">The mod name.</param>
+ /// <param name="LatestFiles">The available file downloads.</param>
+ /// <param name="Links">The URLs for this mod.</param>
+ public record ModModel(int Id, string Name, ModFileModel[] LatestFiles, ModLinksModel Links);
}
diff --git a/src/SMAPI.Web/Framework/Clients/CurseForge/ResponseModels/ResponseModel.cs b/src/SMAPI.Web/Framework/Clients/CurseForge/ResponseModels/ResponseModel.cs
new file mode 100644
index 00000000..4d538a93
--- /dev/null
+++ b/src/SMAPI.Web/Framework/Clients/CurseForge/ResponseModels/ResponseModel.cs
@@ -0,0 +1,8 @@
+using Newtonsoft.Json;
+
+namespace StardewModdingAPI.Web.Framework.Clients.CurseForge.ResponseModels
+{
+ /// <summary>A response from the CurseForge API.</summary>
+ /// <param name="Data">The data returned by the API.</param>
+ public record ResponseModel<TData>(TData Data);
+}
diff --git a/src/SMAPI.Web/Framework/ConfigModels/ApiClientsConfig.cs b/src/SMAPI.Web/Framework/ConfigModels/ApiClientsConfig.cs
index b582b2b0..ebb3618a 100644
--- a/src/SMAPI.Web/Framework/ConfigModels/ApiClientsConfig.cs
+++ b/src/SMAPI.Web/Framework/ConfigModels/ApiClientsConfig.cs
@@ -42,6 +42,9 @@ namespace StardewModdingAPI.Web.Framework.ConfigModels
/// <summary>The base URL for the CurseForge API.</summary>
public string CurseForgeBaseUrl { get; set; } = null!;
+ /// <summary>The API authentication key for the CurseForge API.</summary>
+ public string CurseForgeApiKey { get; set; } = null!;
+
/****
** GitHub
diff --git a/src/SMAPI.Web/Startup.cs b/src/SMAPI.Web/Startup.cs
index 2693aa90..9980d00c 100644
--- a/src/SMAPI.Web/Startup.cs
+++ b/src/SMAPI.Web/Startup.cs
@@ -111,7 +111,8 @@ namespace StardewModdingAPI.Web
services.AddSingleton<ICurseForgeClient>(new CurseForgeClient(
userAgent: userAgent,
- apiUrl: api.CurseForgeBaseUrl
+ apiUrl: api.CurseForgeBaseUrl,
+ apiKey: api.CurseForgeApiKey
));
services.AddSingleton<IGitHubClient>(new GitHubClient(
diff --git a/src/SMAPI.Web/appsettings.json b/src/SMAPI.Web/appsettings.json
index 1231f824..10fcbe9c 100644
--- a/src/SMAPI.Web/appsettings.json
+++ b/src/SMAPI.Web/appsettings.json
@@ -31,7 +31,8 @@
"ChucklefishBaseUrl": "https://community.playstarbound.com",
"ChucklefishModPageUrlFormat": "resources/{0}",
- "CurseForgeBaseUrl": "https://addons-ecs.forgesvc.net/api/v2/",
+ "CurseForgeBaseUrl": "https://api.curseforge.com/v1/",
+ "CurseForgeApiKey": null,
"GitHubBaseUrl": "https://api.github.com",
"GitHubAcceptHeader": "application/vnd.github.v3+json",
diff --git a/src/SMAPI/Constants.cs b/src/SMAPI/Constants.cs
index 357b8db8..b2916a8d 100644
--- a/src/SMAPI/Constants.cs
+++ b/src/SMAPI/Constants.cs
@@ -50,7 +50,7 @@ namespace StardewModdingAPI
internal static int? LogScreenId { get; set; }
/// <summary>SMAPI's current raw semantic version.</summary>
- internal static string RawApiVersion = "3.14.4";
+ internal static string RawApiVersion = "3.14.5";
}
/// <summary>Contains SMAPI's constants and assumptions.</summary>
diff --git a/src/SMAPI/Framework/ContentCoordinator.cs b/src/SMAPI/Framework/ContentCoordinator.cs
index 2b13f57a..fc61b44b 100644
--- a/src/SMAPI/Framework/ContentCoordinator.cs
+++ b/src/SMAPI/Framework/ContentCoordinator.cs
@@ -151,8 +151,23 @@ namespace StardewModdingAPI.Framework
onAssetLoaded: onAssetLoaded
)
);
+
+ var contentManagerForAssetPropagation = new GameContentManagerForAssetPropagation(
+ name: nameof(GameContentManagerForAssetPropagation),
+ serviceProvider: serviceProvider,
+ rootDirectory: rootDirectory,
+ currentCulture: currentCulture,
+ coordinator: this,
+ monitor: monitor,
+ reflection: reflection,
+ onDisposing: this.OnDisposing,
+ onLoadingFirstAsset: onLoadingFirstAsset,
+ onAssetLoaded: onAssetLoaded
+ );
+ this.ContentManagers.Add(contentManagerForAssetPropagation);
+
this.VanillaContentManager = new LocalizedContentManager(serviceProvider, rootDirectory);
- this.CoreAssets = new CoreAssetPropagator(this.MainContentManager, this.Monitor, reflection, name => this.ParseAssetName(name, allowLocales: true));
+ this.CoreAssets = new CoreAssetPropagator(this.MainContentManager, contentManagerForAssetPropagation, this.Monitor, reflection, name => this.ParseAssetName(name, allowLocales: true));
this.LocaleCodes = new Lazy<Dictionary<string, LocalizedContentManager.LanguageCode>>(() => this.GetLocaleCodes(customLanguages: Enumerable.Empty<ModLanguage>()));
}
@@ -379,14 +394,31 @@ namespace StardewModdingAPI.Framework
// cached assets
foreach (IContentManager contentManager in this.ContentManagers)
{
- foreach ((string key, object asset) in contentManager.InvalidateCache((key, type) => predicate(contentManager, key, type), dispose))
+ foreach ((string key, object asset) in contentManager.GetCachedAssets())
{
+ if (!predicate(contentManager, key, asset.GetType()))
+ continue;
+
AssetName assetName = this.ParseAssetName(key, allowLocales: true);
+ contentManager.InvalidateCache(assetName, dispose);
+
if (!invalidatedAssets.ContainsKey(assetName))
invalidatedAssets[assetName] = asset.GetType();
}
}
+ // forget localized flags
+ // A mod might provide a localized variant of a normally non-localized asset (like
+ // `Maps/MovieTheater.fr-FR`). When the asset is invalidated, we need to recheck
+ // whether the asset is localized in case it stops providing it.
+ foreach (IAssetName assetName in invalidatedAssets.Keys)
+ {
+ LocalizedContentManager.localizedAssetNames.Remove(assetName.Name);
+
+ if (LocalizedContentManager.localizedAssetNames.TryGetValue(assetName.BaseName, out string? targetForBaseKey) && targetForBaseKey == assetName.Name)
+ LocalizedContentManager.localizedAssetNames.Remove(assetName.BaseName);
+ }
+
// special case: maps may be loaded through a temporary content manager that's removed while the map is still in use.
// This notably affects the town and farmhouse maps.
if (Game1.locations != null)
diff --git a/src/SMAPI/Framework/ContentManagers/BaseContentManager.cs b/src/SMAPI/Framework/ContentManagers/BaseContentManager.cs
index 575d252e..ddc02a8c 100644
--- a/src/SMAPI/Framework/ContentManagers/BaseContentManager.cs
+++ b/src/SMAPI/Framework/ContentManagers/BaseContentManager.cs
@@ -231,24 +231,21 @@ namespace StardewModdingAPI.Framework.ContentManagers
** Cache invalidation
****/
/// <inheritdoc />
- public IDictionary<string, object> InvalidateCache(Func<string, Type, bool> predicate, bool dispose = false)
+ public IEnumerable<KeyValuePair<string, object>> GetCachedAssets()
{
- IDictionary<string, object> removeAssets = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase);
- this.Cache.Remove((key, asset) =>
- {
- string baseAssetName = this.Coordinator.ParseAssetName(key, allowLocales: this.TryLocalizeKeys).BaseName;
+ foreach (string key in this.Cache.Keys)
+ yield return new(key, this.Cache[key]);
+ }
- // check if asset should be removed
- bool remove = removeAssets.ContainsKey(baseAssetName);
- if (!remove && predicate(baseAssetName, asset.GetType()))
- {
- removeAssets[baseAssetName] = asset;
- remove = true;
- }
- return remove;
- }, dispose);
+ /// <inheritdoc />
+ public bool InvalidateCache(IAssetName assetName, bool dispose = false)
+ {
+ if (!this.Cache.ContainsKey(assetName.Name))
+ return false;
- return removeAssets;
+ // remove from cache
+ this.Cache.Remove(assetName.Name, dispose);
+ return true;
}
/// <inheritdoc />
diff --git a/src/SMAPI/Framework/ContentManagers/GameContentManager.cs b/src/SMAPI/Framework/ContentManagers/GameContentManager.cs
index 1c603f85..4390d472 100644
--- a/src/SMAPI/Framework/ContentManagers/GameContentManager.cs
+++ b/src/SMAPI/Framework/ContentManagers/GameContentManager.cs
@@ -75,7 +75,7 @@ namespace StardewModdingAPI.Framework.ContentManagers
// custom asset from a loader
string locale = this.GetLocale();
IAssetInfo info = new AssetInfo(locale, assetName, typeof(T), this.AssertAndNormalizeAssetName);
- AssetOperationGroup? operations = this.Coordinator.GetAssetOperations<object>(info);
+ AssetOperationGroup? operations = this.Coordinator.GetAssetOperations<T>(info);
if (operations?.LoadOperations.Count > 0)
{
if (!this.AssertMaxOneRequiredLoader(info, operations.LoadOperations, out string? error))
diff --git a/src/SMAPI/Framework/ContentManagers/IContentManager.cs b/src/SMAPI/Framework/ContentManagers/IContentManager.cs
index ac67cad5..f2e3b9f0 100644
--- a/src/SMAPI/Framework/ContentManagers/IContentManager.cs
+++ b/src/SMAPI/Framework/ContentManagers/IContentManager.cs
@@ -32,7 +32,7 @@ namespace StardewModdingAPI.Framework.ContentManagers
/// <typeparam name="T">The expected asset type.</typeparam>
/// <param name="assetName">The normalized asset name.</param>
bool DoesAssetExist<T>(IAssetName assetName)
- where T: notnull;
+ where T : notnull;
/// <summary>Load an asset through the content pipeline, using a localized variant of the <paramref name="assetName"/> if available.</summary>
/// <typeparam name="T">The type of asset to load.</typeparam>
@@ -65,10 +65,13 @@ namespace StardewModdingAPI.Framework.ContentManagers
/// <param name="assetName">The asset path relative to the loader root directory, not including the <c>.xnb</c> extension.</param>
bool IsLoaded(IAssetName assetName);
+ /// <summary>Get all assets in the cache.</summary>
+ IEnumerable<KeyValuePair<string, object>> GetCachedAssets();
+
/// <summary>Purge matched assets from the cache.</summary>
- /// <param name="predicate">Matches the asset keys to invalidate.</param>
+ /// <param name="assetName">The asset name to dispose.</param>
/// <param name="dispose">Whether to dispose invalidated assets. This should only be <c>true</c> when they're being invalidated as part of a dispose, to avoid crashing the game.</param>
- /// <returns>Returns the invalidated asset names and instances.</returns>
- IDictionary<string, object> InvalidateCache(Func<string, Type, bool> predicate, bool dispose = false);
+ /// <returns>Returns whether the asset was in the cache.</returns>
+ bool InvalidateCache(IAssetName assetName, bool dispose = false);
}
}
diff --git a/src/SMAPI/Framework/Utilities/TickCacheDictionary.cs b/src/SMAPI/Framework/Utilities/TickCacheDictionary.cs
index 20d206e2..7732ace8 100644
--- a/src/SMAPI/Framework/Utilities/TickCacheDictionary.cs
+++ b/src/SMAPI/Framework/Utilities/TickCacheDictionary.cs
@@ -48,4 +48,30 @@ namespace StardewModdingAPI.Framework.Utilities
return this.Cache.Remove(cacheKey);
}
}
+
+ /// <summary>An in-memory dictionary cache that stores data for the duration of a game update tick.</summary>
+ /// <typeparam name="TKey">The dictionary key type.</typeparam>
+ internal class TickCacheDictionary<TKey> : TickCacheDictionary<TKey, object>
+ where TKey : notnull
+ {
+ /*********
+ ** Public methods
+ *********/
+ /// <summary>Get a value from the cache, fetching it first if it's not cached yet.</summary>
+ /// <param name="cacheKey">The unique key for the cached value.</param>
+ /// <param name="get">Get the latest data if it's not in the cache yet.</param>
+ public TValue GetOrSet<TValue>(TKey cacheKey, Func<TValue> get)
+ {
+ object? value = base.GetOrSet(cacheKey, () => get()!);
+
+ try
+ {
+ return (TValue)value;
+ }
+ catch (Exception ex)
+ {
+ throw new InvalidCastException($"Can't cast value of the '{cacheKey}' cache entry from {value?.GetType().FullName ?? "null"} to {typeof(TValue).FullName}.", ex);
+ }
+ }
+ }
}
diff --git a/src/SMAPI/Metadata/CoreAssetPropagator.cs b/src/SMAPI/Metadata/CoreAssetPropagator.cs
index e014f9a9..8ed6b591 100644
--- a/src/SMAPI/Metadata/CoreAssetPropagator.cs
+++ b/src/SMAPI/Metadata/CoreAssetPropagator.cs
@@ -5,7 +5,9 @@ using System.IO;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
+using StardewModdingAPI.Framework.ContentManagers;
using StardewModdingAPI.Framework.Reflection;
+using StardewModdingAPI.Framework.Utilities;
using StardewModdingAPI.Internal;
using StardewModdingAPI.Toolkit.Utilities;
using StardewValley;
@@ -32,6 +34,9 @@ namespace StardewModdingAPI.Metadata
/// <summary>The main content manager through which to reload assets.</summary>
private readonly LocalizedContentManager MainContentManager;
+ /// <summary>An internal content manager used only for asset propagation. See remarks on <see cref="GameContentManagerForAssetPropagation"/>.</summary>
+ private readonly GameContentManagerForAssetPropagation DisposableContentManager;
+
/// <summary>Writes messages to the console.</summary>
private readonly IMonitor Monitor;
@@ -54,18 +59,23 @@ namespace StardewModdingAPI.Metadata
Other
};
+ /// <summary>A cache of world data fetched for the current tick.</summary>
+ private readonly TickCacheDictionary<string> WorldCache = new();
+
/*********
** Public methods
*********/
/// <summary>Initialize the core asset data.</summary>
/// <param name="mainContent">The main content manager through which to reload assets.</param>
+ /// <param name="disposableContent">An internal content manager used only for asset propagation.</param>
/// <param name="monitor">Writes messages to the console.</param>
/// <param name="reflection">Simplifies access to private code.</param>
/// <param name="parseAssetName">Parse a raw asset name.</param>
- public CoreAssetPropagator(LocalizedContentManager mainContent, IMonitor monitor, Reflector reflection, Func<string, IAssetName> parseAssetName)
+ public CoreAssetPropagator(LocalizedContentManager mainContent, GameContentManagerForAssetPropagation disposableContent, IMonitor monitor, Reflector reflection, Func<string, IAssetName> parseAssetName)
{
this.MainContentManager = mainContent;
+ this.DisposableContentManager = disposableContent;
this.Monitor = monitor;
this.Reflection = reflection;
this.ParseAssetName = parseAssetName;
@@ -104,12 +114,12 @@ namespace StardewModdingAPI.Metadata
{
case AssetBucket.Sprite:
if (!ignoreWorld)
- this.ReloadNpcSprites(propagatedAssets);
+ this.UpdateNpcSprites(propagatedAssets);
break;
case AssetBucket.Portrait:
if (!ignoreWorld)
- this.ReloadNpcPortraits(propagatedAssets);
+ this.UpdateNpcPortraits(propagatedAssets);
break;
default:
@@ -192,7 +202,7 @@ namespace StardewModdingAPI.Metadata
}
var oldWarps = GetWarpSet(location);
- this.ReloadMap(info);
+ this.UpdateMap(info);
var newWarps = GetWarpSet(location);
changedWarps = changedWarps || oldWarps.Count != newWarps.Count || oldWarps.Any(p => !newWarps.Contains(p));
@@ -213,7 +223,7 @@ namespace StardewModdingAPI.Metadata
** Animals
****/
case "animals/horse":
- return !ignoreWorld && this.ReloadPetOrHorseSprites<Horse>(content, assetName);
+ return !ignoreWorld && this.UpdatePetOrHorseSprites<Horse>(assetName);
/****
** Buildings
@@ -243,7 +253,7 @@ namespace StardewModdingAPI.Metadata
case "characters/farmer/farmer_base_bald":
case "characters/farmer/farmer_girl_base":
case "characters/farmer/farmer_girl_base_bald":
- return !ignoreWorld && this.ReloadPlayerSprites(assetName);
+ return !ignoreWorld && this.UpdatePlayerSprites(assetName);
case "characters/farmer/hairstyles": // Game1.LoadContent
FarmerRenderer.hairStylesTexture = this.LoadTexture(key);
@@ -295,10 +305,10 @@ namespace StardewModdingAPI.Metadata
return true;
case "data/farmanimals": // FarmAnimal constructor
- return !ignoreWorld && this.ReloadFarmAnimalData();
+ return !ignoreWorld && this.UpdateFarmAnimalData();
case "data/hairdata": // Farmer.GetHairStyleMetadataFile
- return this.ReloadHairData();
+ return this.UpdateHairData();
case "data/movies": // MovieTheater.GetMovieData
case "data/moviesreactions": // MovieTheater.GetMovieReactions
@@ -306,7 +316,7 @@ namespace StardewModdingAPI.Metadata
return true;
case "data/npcdispositions": // NPC constructor
- return !ignoreWorld && this.ReloadNpcDispositions(content, assetName);
+ return !ignoreWorld && this.UpdateNpcDispositions(content, assetName);
case "data/npcgifttastes": // Game1.LoadContent
Game1.NPCGiftTastes = content.Load<Dictionary<string, string>>(key);
@@ -386,7 +396,7 @@ namespace StardewModdingAPI.Metadata
}
if (!ignoreWorld)
- this.ReloadDoorSprites(content, assetName);
+ this.UpdateDoorSprites(content, assetName);
return true;
case "loosesprites/cursors2": // Game1.LoadContent
@@ -418,7 +428,7 @@ namespace StardewModdingAPI.Metadata
return true;
case "loosesprites/suspensionbridge": // SuspensionBridge constructor
- return !ignoreWorld && this.ReloadSuspensionBridges(content, assetName);
+ return !ignoreWorld && this.UpdateSuspensionBridges(content, assetName);
/****
** Content\Maps
@@ -449,13 +459,13 @@ namespace StardewModdingAPI.Metadata
return false;
case "minigames/titlebuttons": // TitleMenu
- return this.ReloadTitleButtons(content, assetName);
+ return this.UpdateTitleButtons(content, assetName);
/****
** Content\Strings
****/
case "strings/stringsfromcsfiles":
- return this.ReloadStringsFromCsFiles(content);
+ return this.UpdateStringsFromCsFiles(content);
/****
** Content\TileSheets
@@ -473,14 +483,14 @@ namespace StardewModdingAPI.Metadata
return true;
case "tilesheets/chairtiles": // Game1.LoadContent
- return this.ReloadChairTiles(content, assetName, ignoreWorld);
+ return this.UpdateChairTiles(content, assetName, ignoreWorld);
case "tilesheets/craftables": // Game1.LoadContent
Game1.bigCraftableSpriteSheet = content.Load<Texture2D>(key);
return true;
case "tilesheets/critters": // Critter constructor
- return !ignoreWorld && this.ReloadCritterTextures(content, assetName) > 0;
+ return !ignoreWorld && this.UpdateCritterTextures(assetName);
case "tilesheets/crops": // Game1.LoadContent
Game1.cropSpriteSheet = content.Load<Texture2D>(key);
@@ -534,7 +544,7 @@ namespace StardewModdingAPI.Metadata
return true;
case "terrainfeatures/grass": // from Grass
- return !ignoreWorld && this.ReloadGrassTextures(content, assetName);
+ return !ignoreWorld && this.UpdateGrassTextures(content, assetName);
case "terrainfeatures/hoedirt": // from HoeDirt
HoeDirt.lightTexture = content.Load<Texture2D>(key);
@@ -549,27 +559,27 @@ namespace StardewModdingAPI.Metadata
return true;
case "terrainfeatures/mushroom_tree": // from Tree
- return !ignoreWorld && this.ReloadTreeTextures(content, assetName, Tree.mushroomTree);
+ return !ignoreWorld && this.UpdateTreeTextures(Tree.mushroomTree);
case "terrainfeatures/tree_palm": // from Tree
- return !ignoreWorld && this.ReloadTreeTextures(content, assetName, Tree.palmTree);
+ return !ignoreWorld && this.UpdateTreeTextures(Tree.palmTree);
case "terrainfeatures/tree1_fall": // from Tree
case "terrainfeatures/tree1_spring": // from Tree
case "terrainfeatures/tree1_summer": // from Tree
case "terrainfeatures/tree1_winter": // from Tree
- return !ignoreWorld && this.ReloadTreeTextures(content, assetName, Tree.bushyTree);
+ return !ignoreWorld && this.UpdateTreeTextures(Tree.bushyTree);
case "terrainfeatures/tree2_fall": // from Tree
case "terrainfeatures/tree2_spring": // from Tree
case "terrainfeatures/tree2_summer": // from Tree
case "terrainfeatures/tree2_winter": // from Tree
- return !ignoreWorld && this.ReloadTreeTextures(content, assetName, Tree.leafyTree);
+ return !ignoreWorld && this.UpdateTreeTextures(Tree.leafyTree);
case "terrainfeatures/tree3_fall": // from Tree
case "terrainfeatures/tree3_spring": // from Tree
case "terrainfeatures/tree3_winter": // from Tree
- return !ignoreWorld && this.ReloadTreeTextures(content, assetName, Tree.pineTree);
+ return !ignoreWorld && this.UpdateTreeTextures(Tree.pineTree);
}
/****
@@ -579,24 +589,24 @@ namespace StardewModdingAPI.Metadata
{
// dynamic textures
if (assetName.StartsWith("animals/cat"))
- return this.ReloadPetOrHorseSprites<Cat>(content, assetName);
+ return this.UpdatePetOrHorseSprites<Cat>(assetName);
if (assetName.StartsWith("animals/dog"))
- return this.ReloadPetOrHorseSprites<Dog>(content, assetName);
+ return this.UpdatePetOrHorseSprites<Dog>(assetName);
if (assetName.IsDirectlyUnderPath("Animals"))
- return this.ReloadFarmAnimalSprites(content, assetName);
+ return this.UpdateFarmAnimalSprites(assetName);
if (assetName.IsDirectlyUnderPath("Buildings"))
- return this.ReloadBuildings(assetName);
+ return this.UpdateBuildings(assetName);
if (assetName.StartsWith("LooseSprites/Fence"))
- return this.ReloadFenceTextures(assetName);
+ return this.UpdateFenceTextures(assetName);
// dynamic data
if (assetName.IsDirectlyUnderPath("Characters/Dialogue"))
- return this.ReloadNpcDialogue(assetName);
+ return this.UpdateNpcDialogue(assetName);
if (assetName.IsDirectlyUnderPath("Characters/schedules"))
- return this.ReloadNpcSchedules(assetName);
+ return this.UpdateNpcSchedules(assetName);
}
return false;
@@ -607,14 +617,14 @@ namespace StardewModdingAPI.Metadata
** Private methods
*********/
/****
- ** Reload texture methods
+ ** Update texture methods
****/
- /// <summary>Reload buttons on the title screen.</summary>
- /// <param name="content">The content manager through which to reload the asset.</param>
- /// <param name="assetName">The asset name to reload.</param>
- /// <returns>Returns whether any textures were reloaded.</returns>
+ /// <summary>Update buttons on the title screen.</summary>
+ /// <param name="content">The content manager through which to update the asset.</param>
+ /// <param name="assetName">The asset name to update.</param>
+ /// <returns>Returns whether any references were updated.</returns>
/// <remarks>Derived from the <see cref="TitleMenu"/> constructor and <see cref="TitleMenu.setUpIcons"/>.</remarks>
- private bool ReloadTitleButtons(LocalizedContentManager content, IAssetName assetName)
+ private bool UpdateTitleButtons(LocalizedContentManager content, IAssetName assetName)
{