summaryrefslogtreecommitdiff
path: root/src/SMAPI/Framework
diff options
context:
space:
mode:
authorJesse Plamondon-Willard <Pathoschild@users.noreply.github.com>2022-03-05 15:38:05 -0500
committerJesse Plamondon-Willard <Pathoschild@users.noreply.github.com>2022-03-05 15:38:05 -0500
commitb68b301b712a0047a7d6f24aa2fb776e19f8086d (patch)
treea127aa3cf95d682cd83dbc7ca8fb109181a0744e /src/SMAPI/Framework
parentb0d8b23c2c53ea3aafd60b0597a7562ac1708a42 (diff)
downloadSMAPI-b68b301b712a0047a7d6f24aa2fb776e19f8086d.tar.gz
SMAPI-b68b301b712a0047a7d6f24aa2fb776e19f8086d.tar.bz2
SMAPI-b68b301b712a0047a7d6f24aa2fb776e19f8086d.zip
add DoesAssetExist to support the upcoming Stardew Valley 1.6 (#766)
Diffstat (limited to 'src/SMAPI/Framework')
-rw-r--r--src/SMAPI/Framework/ContentCoordinator.cs16
-rw-r--r--src/SMAPI/Framework/ContentManagers/BaseContentManager.cs6
-rw-r--r--src/SMAPI/Framework/ContentManagers/GameContentManager.cs58
-rw-r--r--src/SMAPI/Framework/ContentManagers/IContentManager.cs4
-rw-r--r--src/SMAPI/Framework/ContentManagers/ModContentManager.cs10
5 files changed, 80 insertions, 14 deletions
diff --git a/src/SMAPI/Framework/ContentCoordinator.cs b/src/SMAPI/Framework/ContentCoordinator.cs
index b255dae1..fbbbe2d2 100644
--- a/src/SMAPI/Framework/ContentCoordinator.cs
+++ b/src/SMAPI/Framework/ContentCoordinator.cs
@@ -296,6 +296,22 @@ namespace StardewModdingAPI.Framework
return Path.Combine(this.ManagedPrefix, modID.ToLower());
}
+ /// <summary>Get whether an asset from a mod folder exists.</summary>
+ /// <param name="contentManagerID">The unique name for the content manager which should load this asset.</param>
+ /// <param name="assetName">The asset name within the mod folder.</param>
+ public bool DoesManagedAssetExist(string contentManagerID, IAssetName assetName)
+ {
+ // get content manager
+ IContentManager contentManager = this.ContentManagerLock.InReadLock(() =>
+ this.ContentManagers.FirstOrDefault(p => p.IsNamespaced && p.Name == contentManagerID)
+ );
+ if (contentManager == null)
+ throw new InvalidOperationException($"The '{contentManagerID}' prefix isn't handled by any mod.");
+
+ // get whether the asset exists
+ return contentManager.DoesAssetExist(assetName);
+ }
+
/// <summary>Get a copy of an asset from a mod folder.</summary>
/// <typeparam name="T">The asset type.</typeparam>
/// <param name="contentManagerID">The unique name for the content manager which should load this asset.</param>
diff --git a/src/SMAPI/Framework/ContentManagers/BaseContentManager.cs b/src/SMAPI/Framework/ContentManagers/BaseContentManager.cs
index 3efc33bb..030c60a7 100644
--- a/src/SMAPI/Framework/ContentManagers/BaseContentManager.cs
+++ b/src/SMAPI/Framework/ContentManagers/BaseContentManager.cs
@@ -93,6 +93,12 @@ namespace StardewModdingAPI.Framework.ContentManagers
}
/// <inheritdoc />
+ public virtual bool DoesAssetExist(IAssetName assetName)
+ {
+ return this.Cache.ContainsKey(assetName.Name);
+ }
+
+ /// <inheritdoc />
[Obsolete("This method is implemented for the base game and should not be used directly. To load an asset from the underlying content manager directly, use " + nameof(BaseContentManager.RawLoad) + " instead.")]
public override T LoadBase<T>(string assetName)
{
diff --git a/src/SMAPI/Framework/ContentManagers/GameContentManager.cs b/src/SMAPI/Framework/ContentManagers/GameContentManager.cs
index 9f686f97..e7fb0c5f 100644
--- a/src/SMAPI/Framework/ContentManagers/GameContentManager.cs
+++ b/src/SMAPI/Framework/ContentManagers/GameContentManager.cs
@@ -63,6 +63,29 @@ namespace StardewModdingAPI.Framework.ContentManagers
}
/// <inheritdoc />
+ public override bool DoesAssetExist(IAssetName assetName)
+ {
+ if (base.DoesAssetExist(assetName))
+ return true;
+
+ // managed asset
+ if (this.Coordinator.TryParseManagedAssetKey(assetName.Name, out string contentManagerID, out IAssetName relativePath))
+ return this.Coordinator.DoesManagedAssetExist(contentManagerID, relativePath);
+
+ // else check for loaders
+ string locale = this.GetLocale();
+ IAssetInfo info = new AssetInfo(locale, assetName, typeof(object), this.AssertAndNormalizeAssetName);
+ ModLinked<IAssetLoader>[] loaders = this.GetLoaders<object>(info).ToArray();
+ if (loaders.Length > 1)
+ {
+ string[] loaderNames = loaders.Select(p => p.Mod.DisplayName).ToArray();
+ this.Monitor.Log($"Multiple mods want to provide the '{info.Name}' asset ({string.Join(", ", loaderNames)}), but an asset can't be loaded multiple times. SMAPI will use the default asset instead; uninstall one of the mods to fix this. (Message for modders: you should usually use {typeof(IAssetEditor)} instead to avoid conflicts.)", LogLevel.Warn);
+ }
+
+ return loaders.Length == 1;
+ }
+
+ /// <inheritdoc />
public override T Load<T>(IAssetName assetName, LanguageCode language, bool useCache)
{
// raise first-load callback
@@ -246,20 +269,7 @@ namespace StardewModdingAPI.Framework.ContentManagers
private IAssetData ApplyLoader<T>(IAssetInfo info)
{
// find matching loaders
- var loaders = this.Loaders
- .Where(entry =>
- {
- try
- {
- return entry.Data.CanLoad<T>(info);
- }
- catch (Exception ex)
- {
- entry.Mod.LogAsMod($"Mod failed when checking whether it could load asset '{info.Name}', and will be ignored. Error details:\n{ex.GetLogSummary()}", LogLevel.Error);
- return false;
- }
- })
- .ToArray();
+ var loaders = this.GetLoaders<T>(info).ToArray();
// validate loaders
if (!loaders.Any())
@@ -360,6 +370,26 @@ namespace StardewModdingAPI.Framework.ContentManagers
return asset;
}
+ /// <summary>Get the asset loaders which handle the asset.</summary>
+ /// <typeparam name="T">The asset type.</typeparam>
+ /// <param name="info">The basic asset metadata.</param>
+ private IEnumerable<ModLinked<IAssetLoader>> GetLoaders<T>(IAssetInfo info)
+ {
+ return this.Loaders
+ .Where(entry =>
+ {
+ try
+ {
+ return entry.Data.CanLoad<T>(info);
+ }
+ catch (Exception ex)
+ {
+ entry.Mod.LogAsMod($"Mod failed when checking whether it could load asset '{info.Name}', and will be ignored. Error details:\n{ex.GetLogSummary()}", LogLevel.Error);
+ return false;
+ }
+ });
+ }
+
/// <summary>Validate that an asset loaded by a mod is valid and won't cause issues, and fix issues if possible.</summary>
/// <typeparam name="T">The asset type.</typeparam>
/// <param name="info">The basic asset metadata.</param>
diff --git a/src/SMAPI/Framework/ContentManagers/IContentManager.cs b/src/SMAPI/Framework/ContentManagers/IContentManager.cs
index fe0519b6..6d71472f 100644
--- a/src/SMAPI/Framework/ContentManagers/IContentManager.cs
+++ b/src/SMAPI/Framework/ContentManagers/IContentManager.cs
@@ -28,6 +28,10 @@ namespace StardewModdingAPI.Framework.ContentManagers
/*********
** Methods
*********/
+ /// <summary>Get whether an asset exists and can be loaded.</summary>
+ /// <param name="assetName">The normalized asset name.</param>
+ bool DoesAssetExist(IAssetName assetName);
+
/// <summary>Load an asset that has been processed by the content pipeline.</summary>
/// <typeparam name="T">The type of asset to load.</typeparam>
/// <param name="assetName">The asset name relative to the loader root directory.</param>
diff --git a/src/SMAPI/Framework/ContentManagers/ModContentManager.cs b/src/SMAPI/Framework/ContentManagers/ModContentManager.cs
index 267146ad..90836fcf 100644
--- a/src/SMAPI/Framework/ContentManagers/ModContentManager.cs
+++ b/src/SMAPI/Framework/ContentManagers/ModContentManager.cs
@@ -64,6 +64,16 @@ namespace StardewModdingAPI.Framework.ContentManagers
}
/// <inheritdoc />
+ public override bool DoesAssetExist(IAssetName assetName)
+ {
+ if (base.DoesAssetExist(assetName))
+ return true;
+
+ FileInfo file = this.GetModFile(assetName.Name);
+ return file.Exists;
+ }
+
+ /// <inheritdoc />
public override T Load<T>(string assetName)
{
return this.Load<T>(assetName, this.DefaultLanguage);