summaryrefslogtreecommitdiff
path: root/src/SMAPI/Framework
diff options
context:
space:
mode:
Diffstat (limited to 'src/SMAPI/Framework')
-rw-r--r--src/SMAPI/Framework/ModHelpers/ContentHelper.cs31
-rw-r--r--src/SMAPI/Framework/ModLoading/ModResolver.cs12
-rw-r--r--src/SMAPI/Framework/Models/ManifestDependency.cs1
-rw-r--r--src/SMAPI/Framework/SContentManager.cs52
4 files changed, 50 insertions, 46 deletions
diff --git a/src/SMAPI/Framework/ModHelpers/ContentHelper.cs b/src/SMAPI/Framework/ModHelpers/ContentHelper.cs
index be9594ee..4a1d3853 100644
--- a/src/SMAPI/Framework/ModHelpers/ContentHelper.cs
+++ b/src/SMAPI/Framework/ModHelpers/ContentHelper.cs
@@ -2,6 +2,7 @@ using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics.CodeAnalysis;
+using System.Diagnostics.Contracts;
using System.IO;
using System.Linq;
using Microsoft.Xna.Framework.Content;
@@ -26,9 +27,6 @@ namespace StardewModdingAPI.Framework.ModHelpers
/// <summary>The absolute path to the mod folder.</summary>
private readonly string ModFolderPath;
- /// <summary>The path to the mod's folder, relative to the game's content folder (e.g. "../Mods/ModName").</summary>
- private readonly string ModFolderPathFromContent;
-
/// <summary>The friendly mod name for use in errors.</summary>
private readonly string ModName;
@@ -73,7 +71,6 @@ namespace StardewModdingAPI.Framework.ModHelpers
this.ContentManager = contentManager;
this.ModFolderPath = modFolderPath;
this.ModName = modName;
- this.ModFolderPathFromContent = this.ContentManager.GetRelativePath(modFolderPath);
this.Monitor = monitor;
}
@@ -102,7 +99,7 @@ namespace StardewModdingAPI.Framework.ModHelpers
throw GetContentError($"there's no matching file at path '{file.FullName}'.");
// get asset path
- string assetName = this.GetModAssetPath(key, file.FullName);
+ string assetName = this.ContentManager.GetAssetNameFromFilePath(file.FullName);
// try cache
if (this.ContentManager.IsLoaded(assetName))
@@ -138,6 +135,14 @@ namespace StardewModdingAPI.Framework.ModHelpers
}
}
+ /// <summary>Normalise an asset name so it's consistent with those generated by the game. This is mainly useful for string comparisons like <see cref="string.StartsWith(string)"/> on generated asset names, and isn't necessary when passing asset names into other content helper methods.</summary>
+ /// <param name="assetName">The asset key.</param>
+ [Pure]
+ public string NormaliseAssetName(string assetName)
+ {
+ return this.ContentManager.NormaliseAssetName(assetName);
+ }
+
/// <summary>Get the underlying key in the game's content cache for an asset. This can be used to load custom map tilesheets, but should be avoided when you can use the content API instead. This does not validate whether the asset exists.</summary>
/// <param name="key">The asset key to fetch (if the <paramref name="source"/> is <see cref="ContentSource.GameContent"/>), or the local path to a content file relative to the mod folder.</param>
/// <param name="source">Where to search for a matching content asset.</param>
@@ -151,7 +156,7 @@ namespace StardewModdingAPI.Framework.ModHelpers
case ContentSource.ModFolder:
FileInfo file = this.GetModFile(key);
- return this.ContentManager.NormaliseAssetName(this.GetModAssetPath(key, file.FullName));
+ return this.ContentManager.NormaliseAssetName(this.ContentManager.GetAssetNameFromFilePath(file.FullName));
default:
throw new NotSupportedException($"Unknown content source '{source}'.");
@@ -356,19 +361,5 @@ namespace StardewModdingAPI.Framework.ModHelpers
// get file
return new FileInfo(path);
}
-
- /// <summary>Get the asset path which loads a mod folder through a content manager.</summary>
- /// <param name="localPath">The file path relative to the mod's folder.</param>
- /// <param name="absolutePath">The absolute file path.</param>
- private string GetModAssetPath(string localPath, string absolutePath)
- {
-#if SMAPI_FOR_WINDOWS
- // XNA doesn't allow absolute asset paths, so get a path relative to the content folder
- return Path.Combine(this.ModFolderPathFromContent, localPath);
-#else
- // MonoGame is weird about relative paths on Mac, but allows absolute paths
- return absolutePath;
-#endif
- }
}
}
diff --git a/src/SMAPI/Framework/ModLoading/ModResolver.cs b/src/SMAPI/Framework/ModLoading/ModResolver.cs
index d0ef1b08..9802d9e9 100644
--- a/src/SMAPI/Framework/ModLoading/ModResolver.cs
+++ b/src/SMAPI/Framework/ModLoading/ModResolver.cs
@@ -142,6 +142,18 @@ namespace StardewModdingAPI.Framework.ModLoading
continue;
}
+ // validate DLL value
+ if (string.IsNullOrWhiteSpace(mod.Manifest.EntryDll))
+ {
+ mod.SetStatus(ModMetadataStatus.Failed, "its manifest has no EntryDLL field.");
+ continue;
+ }
+ if (mod.Manifest.EntryDll.Intersect(Path.GetInvalidFileNameChars()).Any())
+ {
+ mod.SetStatus(ModMetadataStatus.Failed, $"its manifest has invalid filename '{mod.Manifest.EntryDll}' for the EntryDLL field.");
+ continue;
+ }
+
// validate DLL path
string assemblyPath = Path.Combine(mod.DirectoryPath, mod.Manifest.EntryDll);
if (!File.Exists(assemblyPath))
diff --git a/src/SMAPI/Framework/Models/ManifestDependency.cs b/src/SMAPI/Framework/Models/ManifestDependency.cs
index 5646b335..97f0775a 100644
--- a/src/SMAPI/Framework/Models/ManifestDependency.cs
+++ b/src/SMAPI/Framework/Models/ManifestDependency.cs
@@ -15,6 +15,7 @@ namespace StardewModdingAPI.Framework.Models
/// <summary>Whether the dependency must be installed to use the mod.</summary>
public bool IsRequired { get; set; }
+
/*********
** Public methods
*********/
diff --git a/src/SMAPI/Framework/SContentManager.cs b/src/SMAPI/Framework/SContentManager.cs
index a755a6df..524b2d17 100644
--- a/src/SMAPI/Framework/SContentManager.cs
+++ b/src/SMAPI/Framework/SContentManager.cs
@@ -102,7 +102,7 @@ namespace StardewModdingAPI.Framework
this.Monitor = monitor ?? throw new ArgumentNullException(nameof(monitor));
this.Cache = new ContentCache(this, reflection, SContentManager.PossiblePathSeparators, SContentManager.PreferredPathSeparator);
this.GetKeyLocale = reflection.GetPrivateMethod(this, "languageCode");
- this.ModContentPrefix = this.GetRelativePath(Constants.ModPath);
+ this.ModContentPrefix = this.GetAssetNameFromFilePath(Constants.ModPath);
// get asset data
this.CoreAssets = new CoreAssets(this.NormaliseAssetName);
@@ -140,19 +140,17 @@ namespace StardewModdingAPI.Framework
throw new ArgumentException("The asset key or local path contains invalid characters.");
}
- /// <summary>Get a directory path relative to the content root.</summary>
- /// <param name="targetPath">The target file path.</param>
- public string GetRelativePath(string targetPath)
+ /// <summary>Convert an absolute file path into a appropriate asset name.</summary>
+ /// <param name="absolutePath">The absolute path to the file.</param>
+ public string GetAssetNameFromFilePath(string absolutePath)
{
- // convert to URIs
- Uri from = new Uri(this.FullRootDirectory + "/");
- Uri to = new Uri(targetPath + "/");
- if (from.Scheme != to.Scheme)
- throw new InvalidOperationException($"Can't get path for '{targetPath}' relative to '{this.FullRootDirectory}'.");
-
- // get relative path
- return Uri.UnescapeDataString(from.MakeRelativeUri(to).ToString())
- .Replace(Path.DirectorySeparatorChar == '/' ? '\\' : '/', Path.DirectorySeparatorChar); // use correct separator for platform
+#if SMAPI_FOR_WINDOWS
+ // XNA doesn't allow absolute asset paths, so get a path relative to the content folder
+ return this.GetRelativePath(absolutePath);
+#else
+ // MonoGame is weird about relative paths on Mac, but allows absolute paths
+ return absolutePath;
+#endif
}
/****
@@ -395,6 +393,21 @@ namespace StardewModdingAPI.Framework
/****
** Asset name/key handling
****/
+ /// <summary>Get a directory or file path relative to the content root.</summary>
+ /// <param name="targetPath">The target file path.</param>
+ private string GetRelativePath(string targetPath)
+ {
+ // convert to URIs
+ Uri from = new Uri(this.FullRootDirectory + "/");
+ Uri to = new Uri(targetPath + "/");
+ if (from.Scheme != to.Scheme)
+ throw new InvalidOperationException($"Can't get path for '{targetPath}' relative to '{this.FullRootDirectory}'.");
+
+ // get relative path
+ return Uri.UnescapeDataString(from.MakeRelativeUri(to).ToString())
+ .Replace(Path.DirectorySeparatorChar == '/' ? '\\' : '/', Path.DirectorySeparatorChar); // use correct separator for platform
+ }
+
/// <summary>Get the locale codes (like <c>ja-JP</c>) used in asset keys.</summary>
/// <param name="reflection">Simplifies access to private game code.</param>
private IDictionary<string, LanguageCode> GetKeyLocales(Reflector reflection)
@@ -551,19 +564,6 @@ namespace StardewModdingAPI.Framework
return file;
}
- /// <summary>Get a file from the game's content folder.</summary>
- /// <param name="key">The asset key.</param>
- private FileInfo GetContentFolderFile(string key)
- {
- // get file path
- string path = Path.Combine(this.FullRootDirectory, key);
- if (!path.EndsWith(".xnb"))
- path += ".xnb";
-
- // get file
- return new FileInfo(path);
- }
-
/// <summary>Load the initial asset from the registered <see cref="Loaders"/>.</summary>
/// <param name="info">The basic asset metadata.</param>
/// <returns>Returns the loaded asset metadata, or <c>null</c> if no loader matched.</returns>