diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/SMAPI.Tests/Core/ModResolverTests.cs | 14 | ||||
-rw-r--r-- | src/SMAPI/Framework/IModMetadata.cs | 10 | ||||
-rw-r--r-- | src/SMAPI/Framework/ModLoading/ModMetadata.cs | 25 | ||||
-rw-r--r-- | src/SMAPI/Framework/ModLoading/ModResolver.cs | 12 | ||||
-rw-r--r-- | src/SMAPI/Framework/SCore.cs | 10 |
5 files changed, 51 insertions, 20 deletions
diff --git a/src/SMAPI.Tests/Core/ModResolverTests.cs b/src/SMAPI.Tests/Core/ModResolverTests.cs index 4a1f04c6..ee1c0b99 100644 --- a/src/SMAPI.Tests/Core/ModResolverTests.cs +++ b/src/SMAPI.Tests/Core/ModResolverTests.cs @@ -27,7 +27,7 @@ namespace StardewModdingAPI.Tests.Core public void ReadBasicManifest_NoMods_ReturnsEmptyList() { // arrange - string rootFolder = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString("N")); + string rootFolder = this.GetTempFolderPath(); Directory.CreateDirectory(rootFolder); // act @@ -41,7 +41,7 @@ namespace StardewModdingAPI.Tests.Core public void ReadBasicManifest_EmptyModFolder_ReturnsFailedManifest() { // arrange - string rootFolder = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString("N")); + string rootFolder = this.GetTempFolderPath(); string modFolder = Path.Combine(rootFolder, Guid.NewGuid().ToString("N")); Directory.CreateDirectory(modFolder); @@ -78,7 +78,7 @@ namespace StardewModdingAPI.Tests.Core }; // write to filesystem - string rootFolder = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString("N")); + string rootFolder = this.GetTempFolderPath(); string modFolder = Path.Combine(rootFolder, Guid.NewGuid().ToString("N")); string filename = Path.Combine(modFolder, "manifest.json"); Directory.CreateDirectory(modFolder); @@ -209,7 +209,7 @@ namespace StardewModdingAPI.Tests.Core IManifest manifest = this.GetManifest(); // create DLL - string modFolder = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString("N")); + string modFolder = Path.Combine(this.GetTempFolderPath(), Guid.NewGuid().ToString("N")); Directory.CreateDirectory(modFolder); File.WriteAllText(Path.Combine(modFolder, manifest.EntryDll), ""); @@ -462,6 +462,12 @@ namespace StardewModdingAPI.Tests.Core /********* ** Private methods *********/ + /// <summary>Get a generated folder path in the temp folder. This folder isn't created automatically.</summary> + private string GetTempFolderPath() + { + return Path.Combine(Path.GetTempPath(), "smapi-unit-tests", Guid.NewGuid().ToString("N")); + } + /// <summary>Get a randomised basic manifest.</summary> /// <param name="id">The <see cref="IManifest.UniqueID"/> value, or <c>null</c> for a generated value.</param> /// <param name="name">The <see cref="IManifest.Name"/> value, or <c>null</c> for a generated value.</param> diff --git a/src/SMAPI/Framework/IModMetadata.cs b/src/SMAPI/Framework/IModMetadata.cs index 32870c2a..6ee7df69 100644 --- a/src/SMAPI/Framework/IModMetadata.cs +++ b/src/SMAPI/Framework/IModMetadata.cs @@ -16,10 +16,13 @@ namespace StardewModdingAPI.Framework /// <summary>The mod's display name.</summary> string DisplayName { get; } - /// <summary>The mod's full directory path.</summary> + /// <summary>The root path containing mods.</summary> + string RootPath { get; } + + /// <summary>The mod's full directory path within the <see cref="RootPath"/>.</summary> string DirectoryPath { get; } - /// <summary>The <see cref="DirectoryPath"/> relative to the game's Mods folder.</summary> + /// <summary>The <see cref="DirectoryPath"/> relative to the <see cref="RootPath"/>.</summary> string RelativeDirectoryPath { get; } /// <summary>Metadata about the mod from SMAPI's internal data (if any).</summary> @@ -108,5 +111,8 @@ namespace StardewModdingAPI.Framework /// <summary>Get whether the mod has a given warning and it hasn't been suppressed in the <see cref="DataRecord"/>.</summary> /// <param name="warning">The warning to check.</param> bool HasUnsuppressWarning(ModWarning warning); + + /// <summary>Get a relative path which includes the root folder name.</summary> + string GetRelativePathWithRoot(); } } diff --git a/src/SMAPI/Framework/ModLoading/ModMetadata.cs b/src/SMAPI/Framework/ModLoading/ModMetadata.cs index 39f2f482..7f788d17 100644 --- a/src/SMAPI/Framework/ModLoading/ModMetadata.cs +++ b/src/SMAPI/Framework/ModLoading/ModMetadata.cs @@ -1,10 +1,12 @@ using System; using System.Collections.Generic; +using System.IO; using System.Linq; using StardewModdingAPI.Framework.ModHelpers; using StardewModdingAPI.Toolkit.Framework.Clients.WebApi; using StardewModdingAPI.Toolkit.Framework.ModData; using StardewModdingAPI.Toolkit.Framework.UpdateData; +using StardewModdingAPI.Toolkit.Utilities; namespace StardewModdingAPI.Framework.ModLoading { @@ -17,10 +19,13 @@ namespace StardewModdingAPI.Framework.ModLoading /// <summary>The mod's display name.</summary> public string DisplayName { get; } - /// <summary>The mod's full directory path.</summary> + /// <summary>The root path containing mods.</summary> + public string RootPath { get; } + + /// <summary>The mod's full directory path within the <see cref="RootPath"/>.</summary> public string DirectoryPath { get; } - /// <summary>The <see cref="IModMetadata.DirectoryPath"/> relative to the game's Mods folder.</summary> + /// <summary>The <see cref="DirectoryPath"/> relative to the <see cref="RootPath"/>.</summary> public string RelativeDirectoryPath { get; } /// <summary>The mod manifest.</summary> @@ -68,16 +73,17 @@ namespace StardewModdingAPI.Framework.ModLoading *********/ /// <summary>Construct an instance.</summary> /// <param name="displayName">The mod's display name.</param> - /// <param name="directoryPath">The mod's full directory path.</param> - /// <param name="relativeDirectoryPath">The <paramref name="directoryPath"/> relative to the game's Mods folder.</param> + /// <param name="directoryPath">The mod's full directory path within the <paramref name="rootPath"/>.</param> + /// <param name="rootPath">The root path containing mods.</param> /// <param name="manifest">The mod manifest.</param> /// <param name="dataRecord">Metadata about the mod from SMAPI's internal data (if any).</param> /// <param name="isIgnored">Whether the mod folder should be ignored. This should be <c>true</c> if it was found within a folder whose name starts with a dot.</param> - public ModMetadata(string displayName, string directoryPath, string relativeDirectoryPath, IManifest manifest, ModDataRecordVersionedFields dataRecord, bool isIgnored) + public ModMetadata(string displayName, string directoryPath, string rootPath, IManifest manifest, ModDataRecordVersionedFields dataRecord, bool isIgnored) { this.DisplayName = displayName; this.DirectoryPath = directoryPath; - this.RelativeDirectoryPath = relativeDirectoryPath; + this.RootPath = rootPath; + this.RelativeDirectoryPath = PathUtilities.GetRelativePath(this.RootPath, this.DirectoryPath); this.Manifest = manifest; this.DataRecord = dataRecord; this.IsIgnored = isIgnored; @@ -196,5 +202,12 @@ namespace StardewModdingAPI.Framework.ModLoading this.Warnings.HasFlag(warning) && (this.DataRecord?.DataRecord == null || !this.DataRecord.DataRecord.SuppressWarnings.HasFlag(warning)); } + + /// <summary>Get a relative path which includes the root folder name.</summary> + public string GetRelativePathWithRoot() + { + string rootFolderName = Path.GetFileName(this.RootPath) ?? ""; + return Path.Combine(rootFolderName, this.RelativeDirectoryPath); + } } } diff --git a/src/SMAPI/Framework/ModLoading/ModResolver.cs b/src/SMAPI/Framework/ModLoading/ModResolver.cs index b6bdb357..20941a5f 100644 --- a/src/SMAPI/Framework/ModLoading/ModResolver.cs +++ b/src/SMAPI/Framework/ModLoading/ModResolver.cs @@ -42,9 +42,8 @@ namespace StardewModdingAPI.Framework.ModLoading ModMetadataStatus status = folder.ManifestParseError == ModParseError.None || shouldIgnore ? ModMetadataStatus.Found : ModMetadataStatus.Failed; - string relativePath = PathUtilities.GetRelativePath(rootPath, folder.Directory.FullName); - yield return new ModMetadata(folder.DisplayName, folder.Directory.FullName, relativePath, manifest, dataRecord, isIgnored: shouldIgnore) + yield return new ModMetadata(folder.DisplayName, folder.Directory.FullName, rootPath, manifest, dataRecord, isIgnored: shouldIgnore) .SetStatus(status, shouldIgnore ? "disabled by dot convention" : folder.ManifestParseErrorText); } } @@ -199,7 +198,14 @@ namespace StardewModdingAPI.Framework.ModLoading { if (mod.Status == ModMetadataStatus.Failed) continue; // don't replace metadata error - mod.SetStatus(ModMetadataStatus.Failed, $"you have multiple copies of this mod installed ({string.Join(", ", group.Select(p => p.RelativeDirectoryPath).OrderBy(p => p))})."); + + string folderList = string.Join(", ", + from entry in @group + let relativePath = entry.GetRelativePathWithRoot() + orderby relativePath + select $"{relativePath} ({entry.Manifest.Version})" + ); + mod.SetStatus(ModMetadataStatus.Failed, $"you have multiple copies of this mod installed. Found in folders: {folderList}."); } } } diff --git a/src/SMAPI/Framework/SCore.cs b/src/SMAPI/Framework/SCore.cs index 60deed70..0aae3b84 100644 --- a/src/SMAPI/Framework/SCore.cs +++ b/src/SMAPI/Framework/SCore.cs @@ -400,7 +400,7 @@ namespace StardewModdingAPI.Framework // filter out ignored mods foreach (IModMetadata mod in mods.Where(p => p.IsIgnored)) - this.Monitor.Log($" Skipped {mod.RelativeDirectoryPath} (folder name starts with a dot).", LogLevel.Trace); + this.Monitor.Log($" Skipped {mod.GetRelativePathWithRoot()} (folder name starts with a dot).", LogLevel.Trace); mods = mods.Where(p => !p.IsIgnored).ToArray(); // load mods @@ -902,13 +902,13 @@ namespace StardewModdingAPI.Framework // log entry { - string relativePath = PathUtilities.GetRelativePath(this.ModsPath, mod.DirectoryPath); + string relativePath = mod.GetRelativePathWithRoot(); if (mod.IsContentPack) - this.Monitor.Log($" {mod.DisplayName} ({relativePath}) [content pack]...", LogLevel.Trace); + this.Monitor.Log($" {mod.DisplayName} (from {relativePath}) [content pack]...", LogLevel.Trace); else if (mod.Manifest?.EntryDll != null) - this.Monitor.Log($" {mod.DisplayName} ({relativePath}{Path.DirectorySeparatorChar}{mod.Manifest.EntryDll})...", LogLevel.Trace); // don't use Path.Combine here, since EntryDLL might not be valid + this.Monitor.Log($" {mod.DisplayName} (from {relativePath}{Path.DirectorySeparatorChar}{mod.Manifest.EntryDll})...", LogLevel.Trace); // don't use Path.Combine here, since EntryDLL might not be valid else - this.Monitor.Log($" {mod.DisplayName} ({relativePath})...", LogLevel.Trace); + this.Monitor.Log($" {mod.DisplayName} (from {relativePath})...", LogLevel.Trace); } // add warning for missing update key |