add metadata to internal mod registry & use mod display name everywhere

This commit is contained in:
Jesse Plamondon-Willard 2017-05-20 00:29:04 -04:00
parent 2781c27786
commit 9ef4876c5e
8 changed files with 48 additions and 23 deletions

View File

@ -14,7 +14,8 @@ For mod developers:
See [log](https://github.com/Pathoschild/SMAPI/compare/1.13...1.13.1).
For players:
* Fixed error when loading a mod with no version.
* Fixed errors when loading a mod with no name or version.
* Fixed mods with no manifest `Name` field having no name (SMAPI will now shows their filename).
## 1.13
See [log](https://github.com/Pathoschild/SMAPI/compare/1.12...1.13).

View File

@ -5,6 +5,7 @@ using System.Linq;
using Moq;
using Newtonsoft.Json;
using NUnit.Framework;
using StardewModdingAPI.Framework;
using StardewModdingAPI.Framework.Models;
using StardewModdingAPI.Framework.ModLoading;
using StardewModdingAPI.Framework.Serialisation;

View File

@ -1,6 +1,7 @@
using StardewModdingAPI.Framework.Models;
using StardewModdingAPI.Framework.ModLoading;
namespace StardewModdingAPI.Framework.ModLoading
namespace StardewModdingAPI.Framework
{
/// <summary>Metadata for a mod.</summary>
internal interface IModMetadata
@ -26,6 +27,9 @@ namespace StardewModdingAPI.Framework.ModLoading
/// <summary>The reason the metadata is invalid, if any.</summary>
string Error { get; }
/// <summary>The mod instance (if it was loaded).</summary>
IMod Mod { get; }
/*********
** Public methods
@ -35,5 +39,9 @@ namespace StardewModdingAPI.Framework.ModLoading
/// <param name="error">The reason the metadata is invalid, if any.</param>
/// <returns>Return the instance for chaining.</returns>
IModMetadata SetStatus(ModMetadataStatus status, string error = null);
/// <summary>Set the mod instance.</summary>
/// <param name="mod">The mod instance to set.</param>
IModMetadata SetMod(IMod mod);
}
}

View File

@ -37,6 +37,7 @@ namespace StardewModdingAPI.Framework
** Public methods
*********/
/// <summary>Construct an instance.</summary>
/// <param name="displayName">The mod's display name.</param>
/// <param name="manifest">The manifest for the associated mod.</param>
/// <param name="modDirectory">The full path to the mod's folder.</param>
/// <param name="jsonHelper">Encapsulate SMAPI's JSON parsing.</param>
@ -46,7 +47,7 @@ namespace StardewModdingAPI.Framework
/// <param name="reflection">Simplifies access to private game code.</param>
/// <exception cref="ArgumentNullException">An argument is null or empty.</exception>
/// <exception cref="InvalidOperationException">The <paramref name="modDirectory"/> path does not exist on disk.</exception>
public ModHelper(IManifest manifest, string modDirectory, JsonHelper jsonHelper, IModRegistry modRegistry, CommandManager commandManager, SContentManager contentManager, IReflectionHelper reflection)
public ModHelper(string displayName, IManifest manifest, string modDirectory, JsonHelper jsonHelper, IModRegistry modRegistry, CommandManager commandManager, SContentManager contentManager, IReflectionHelper reflection)
{
// validate
if (string.IsNullOrWhiteSpace(modDirectory))
@ -61,9 +62,9 @@ namespace StardewModdingAPI.Framework
// initialise
this.DirectoryPath = modDirectory;
this.JsonHelper = jsonHelper;
this.Content = new ContentHelper(contentManager, modDirectory, manifest.Name);
this.Content = new ContentHelper(contentManager, modDirectory, displayName);
this.ModRegistry = modRegistry;
this.ConsoleCommands = new CommandHelper(manifest.Name, commandManager);
this.ConsoleCommands = new CommandHelper(displayName, commandManager);
this.Reflection = reflection;
}

View File

@ -26,6 +26,9 @@ namespace StardewModdingAPI.Framework.ModLoading
/// <summary>The reason the metadata is invalid, if any.</summary>
public string Error { get; private set; }
/// <summary>The mod instance (if it was loaded).</summary>
public IMod Mod { get; private set; }
/*********
** Public methods
@ -53,5 +56,13 @@ namespace StardewModdingAPI.Framework.ModLoading
this.Error = error;
return this;
}
/// <summary>Set the mod instance.</summary>
/// <param name="mod">The mod instance to set.</param>
public IModMetadata SetMod(IMod mod)
{
this.Mod = mod;
return this;
}
}
}

View File

@ -13,7 +13,7 @@ namespace StardewModdingAPI.Framework
** Properties
*********/
/// <summary>The registered mod data.</summary>
private readonly List<IMod> Mods = new List<IMod>();
private readonly List<IModMetadata> Mods = new List<IModMetadata>();
/// <summary>The friendly mod names treated as deprecation warning sources (assembly full name => mod name).</summary>
private readonly IDictionary<string, string> ModNamesByAssembly = new Dictionary<string, string>();
@ -28,7 +28,7 @@ namespace StardewModdingAPI.Framework
/// <summary>Get metadata for all loaded mods.</summary>
public IEnumerable<IManifest> GetAll()
{
return this.Mods.Select(p => p.ModManifest);
return this.Mods.Select(p => p.Manifest);
}
/// <summary>Get metadata for a loaded mod.</summary>
@ -50,15 +50,15 @@ namespace StardewModdingAPI.Framework
** Internal methods
****/
/// <summary>Register a mod as a possible source of deprecation warnings.</summary>
/// <param name="mod">The mod instance.</param>
public void Add(IMod mod)
/// <param name="metadata">The mod metadata.</param>
public void Add(IModMetadata metadata)
{
this.Mods.Add(mod);
this.ModNamesByAssembly[mod.GetType().Assembly.FullName] = mod.ModManifest.Name;
this.Mods.Add(metadata);
this.ModNamesByAssembly[metadata.Mod.GetType().Assembly.FullName] = metadata.DisplayName;
}
/// <summary>Get all enabled mods.</summary>
public IEnumerable<IMod> GetMods()
public IEnumerable<IModMetadata> GetMods()
{
return (from mod in this.Mods select mod);
}

View File

@ -237,15 +237,15 @@ namespace StardewModdingAPI
this.IsDisposed = true;
// dispose mod data
foreach (IMod mod in this.ModRegistry.GetMods())
foreach (IModMetadata mod in this.ModRegistry.GetMods())
{
try
{
(mod as IDisposable)?.Dispose();
(mod.Mod as IDisposable)?.Dispose();
}
catch (Exception ex)
{
this.Monitor.Log($"The {mod.ModManifest.Name} mod failed during disposal: {ex.GetLogSummary()}.", LogLevel.Warn);
this.Monitor.Log($"The {mod.DisplayName} mod failed during disposal: {ex.GetLogSummary()}.", LogLevel.Warn);
}
}
@ -580,14 +580,15 @@ namespace StardewModdingAPI
// inject data
mod.ModManifest = manifest;
mod.Helper = new ModHelper(manifest, metadata.DirectoryPath, jsonHelper, this.ModRegistry, this.CommandManager, contentManager, this.Reflection);
mod.Monitor = this.GetSecondaryMonitor(manifest.Name);
mod.Helper = new ModHelper(metadata.DisplayName, manifest, metadata.DirectoryPath, jsonHelper, this.ModRegistry, this.CommandManager, contentManager, this.Reflection);
mod.Monitor = this.GetSecondaryMonitor(metadata.DisplayName);
mod.PathOnDisk = metadata.DirectoryPath;
// track mod
this.ModRegistry.Add(mod);
metadata.SetMod(mod);
this.ModRegistry.Add(metadata);
modsLoaded += 1;
this.Monitor.Log($"Loaded {manifest.Name} by {manifest.Author}, v{manifest.Version} | {manifest.Description}", LogLevel.Info);
this.Monitor.Log($"Loaded {metadata.DisplayName} by {manifest.Author}, v{manifest.Version} | {manifest.Description}", LogLevel.Info);
}
catch (Exception ex)
{
@ -596,21 +597,23 @@ namespace StardewModdingAPI
}
// initialise loaded mods
foreach (IMod mod in this.ModRegistry.GetMods())
foreach (IModMetadata metadata in this.ModRegistry.GetMods())
{
try
{
IMod mod = metadata.Mod;
// call entry methods
(mod as Mod)?.Entry(); // deprecated since 1.0
mod.Entry(mod.Helper);
// raise deprecation warning for old Entry() methods
if (this.DeprecationManager.IsVirtualMethodImplemented(mod.GetType(), typeof(Mod), nameof(Mod.Entry), new[] { typeof(object[]) }))
deprecationWarnings.Add(() => this.DeprecationManager.Warn(mod.ModManifest.Name, $"{nameof(Mod)}.{nameof(Mod.Entry)}(object[]) instead of {nameof(Mod)}.{nameof(Mod.Entry)}({nameof(IModHelper)})", "1.0", DeprecationLevel.Info));
deprecationWarnings.Add(() => this.DeprecationManager.Warn(metadata.DisplayName, $"{nameof(Mod)}.{nameof(Mod.Entry)}(object[]) instead of {nameof(Mod)}.{nameof(Mod.Entry)}({nameof(IModHelper)})", "1.0", DeprecationLevel.Info));
}
catch (Exception ex)
{
this.Monitor.Log($"The {mod.ModManifest.Name} mod failed on entry initialisation. It will still be loaded, but may not function correctly.\n{ex.GetLogSummary()}", LogLevel.Warn);
this.Monitor.Log($"The {metadata.DisplayName} mod failed on entry initialisation. It will still be loaded, but may not function correctly.\n{ex.GetLogSummary()}", LogLevel.Warn);
}
}

View File

@ -122,7 +122,7 @@
<Compile Include="Events\GameEvents.cs" />
<Compile Include="Events\GraphicsEvents.cs" />
<Compile Include="Framework\Countdown.cs" />
<Compile Include="Framework\ModLoading\IModMetadata.cs" />
<Compile Include="Framework\IModMetadata.cs" />
<Compile Include="Framework\ModLoading\InvalidModStateException.cs" />
<Compile Include="Framework\ModLoading\ModDependencyStatus.cs" />
<Compile Include="Framework\ModLoading\ModMetadataStatus.cs" />