diff options
| author | Jesse Plamondon-Willard <Pathoschild@users.noreply.github.com> | 2022-05-22 14:38:57 -0400 |
|---|---|---|
| committer | Jesse Plamondon-Willard <Pathoschild@users.noreply.github.com> | 2022-05-22 14:38:57 -0400 |
| commit | 2ab2182645179129997eac3fccb63f6f0683dbe1 (patch) | |
| tree | ddea4c6e4531a10c698d9757a57ae24c6732bff7 | |
| parent | 5731b015a0c548ac72e0d7ce9c4153aa52da3562 (diff) | |
| parent | 336cc1cc0f250c96ee23d45e1e08569b67a2e562 (diff) | |
| download | SMAPI-2ab2182645179129997eac3fccb63f6f0683dbe1.tar.gz SMAPI-2ab2182645179129997eac3fccb63f6f0683dbe1.tar.bz2 SMAPI-2ab2182645179129997eac3fccb63f6f0683dbe1.zip | |
Merge branch 'develop' into stable
19 files changed, 468 insertions, 355 deletions
diff --git a/build/common.targets b/build/common.targets index 76343b8d..7b59e4ae 100644 --- a/build/common.targets +++ b/build/common.targets @@ -1,7 +1,7 @@ <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <PropertyGroup> <!--set general build properties --> - <Version>3.14.4</Version> + <Version>3.14.5</Version> <Product>SMAPI</Product> <LangVersion>latest</LangVersion> <AssemblySearchPaths>$(AssemblySearchPaths);{GAC}</AssemblySearchPaths> diff --git a/docs/release-notes.md b/docs/release-notes.md index c29bc39c..cd177f61 100644 --- a/docs/release-notes.md +++ b/docs/release-notes.md @@ -1,6 +1,14 @@ ← [README](README.md) # Release notes +## 3.14.5 +Released 22 May 2022 for Stardew Valley 1.5.6 or later. + +* For players: + * Improved performance when mods change some asset types (including NPC portraits/sprites). + * Fixed _could not find file_ error if a mod provides a localized version of a normally unlocalized asset and then stops providing it. + * Fixed CurseForge update checks for the new CurseForge API. + ## 3.14.4 Released 15 May 2022 for Stardew Valley 1.5.6 or later. 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 |
