summaryrefslogtreecommitdiff
path: root/src/StardewModdingAPI/Framework
diff options
context:
space:
mode:
Diffstat (limited to 'src/StardewModdingAPI/Framework')
-rw-r--r--src/StardewModdingAPI/Framework/Content/AssetData.cs44
-rw-r--r--src/StardewModdingAPI/Framework/Content/AssetDataForDictionary.cs (renamed from src/StardewModdingAPI/Framework/Content/ContentEventHelperForDictionary.cs)4
-rw-r--r--src/StardewModdingAPI/Framework/Content/AssetDataForImage.cs (renamed from src/StardewModdingAPI/Framework/Content/ContentEventHelperForImage.cs)4
-rw-r--r--src/StardewModdingAPI/Framework/Content/AssetDataForObject.cs (renamed from src/StardewModdingAPI/Framework/Content/ContentEventHelper.cs)19
-rw-r--r--src/StardewModdingAPI/Framework/Content/AssetInfo.cs (renamed from src/StardewModdingAPI/Framework/Content/ContentEventData.cs)41
-rw-r--r--src/StardewModdingAPI/Framework/CursorPosition.cs37
-rw-r--r--src/StardewModdingAPI/Framework/DeprecationManager.cs13
-rw-r--r--src/StardewModdingAPI/Framework/Exceptions/SParseException.cs17
-rw-r--r--src/StardewModdingAPI/Framework/InternalExtensions.cs5
-rw-r--r--src/StardewModdingAPI/Framework/ModHelpers/BaseHelper.cs23
-rw-r--r--src/StardewModdingAPI/Framework/ModHelpers/CommandHelper.cs (renamed from src/StardewModdingAPI/Framework/CommandHelper.cs)9
-rw-r--r--src/StardewModdingAPI/Framework/ModHelpers/ContentHelper.cs (renamed from src/StardewModdingAPI/Framework/ContentHelper.cs)26
-rw-r--r--src/StardewModdingAPI/Framework/ModHelpers/ModHelper.cs (renamed from src/StardewModdingAPI/Framework/ModHelper.cs)42
-rw-r--r--src/StardewModdingAPI/Framework/ModHelpers/ModRegistryHelper.cs48
-rw-r--r--src/StardewModdingAPI/Framework/ModHelpers/ReflectionHelper.cs160
-rw-r--r--src/StardewModdingAPI/Framework/ModHelpers/TranslationHelper.cs (renamed from src/StardewModdingAPI/Framework/TranslationHelper.cs)8
-rw-r--r--src/StardewModdingAPI/Framework/ModLoading/AssemblyLoader.cs27
-rw-r--r--src/StardewModdingAPI/Framework/ModLoading/ModResolver.cs124
-rw-r--r--src/StardewModdingAPI/Framework/ModRegistry.cs6
-rw-r--r--src/StardewModdingAPI/Framework/Models/DisabledMod.cs22
-rw-r--r--src/StardewModdingAPI/Framework/Models/Manifest.cs5
-rw-r--r--src/StardewModdingAPI/Framework/Models/ManifestDependency.cs21
-rw-r--r--src/StardewModdingAPI/Framework/Models/SConfig.cs3
-rw-r--r--src/StardewModdingAPI/Framework/Monitor.cs32
-rw-r--r--src/StardewModdingAPI/Framework/Reflection/Reflector.cs (renamed from src/StardewModdingAPI/Framework/Reflection/ReflectionHelper.cs)44
-rw-r--r--src/StardewModdingAPI/Framework/SContentManager.cs248
-rw-r--r--src/StardewModdingAPI/Framework/SGame.cs357
-rw-r--r--src/StardewModdingAPI/Framework/Serialisation/JsonHelper.cs19
-rw-r--r--src/StardewModdingAPI/Framework/Serialisation/ManifestFieldConverter.cs41
29 files changed, 1064 insertions, 385 deletions
diff --git a/src/StardewModdingAPI/Framework/Content/AssetData.cs b/src/StardewModdingAPI/Framework/Content/AssetData.cs
new file mode 100644
index 00000000..1ab9eebd
--- /dev/null
+++ b/src/StardewModdingAPI/Framework/Content/AssetData.cs
@@ -0,0 +1,44 @@
+using System;
+
+namespace StardewModdingAPI.Framework.Content
+{
+ /// <summary>Base implementation for a content helper which encapsulates access and changes to content being read from a data file.</summary>
+ /// <typeparam name="TValue">The interface value type.</typeparam>
+ internal class AssetData<TValue> : AssetInfo, IAssetData<TValue>
+ {
+ /*********
+ ** Accessors
+ *********/
+ /// <summary>The content data being read.</summary>
+ public TValue Data { get; protected set; }
+
+
+ /*********
+ ** Public methods
+ *********/
+ /// <summary>Construct an instance.</summary>
+ /// <param name="locale">The content's locale code, if the content is localised.</param>
+ /// <param name="assetName">The normalised asset name being read.</param>
+ /// <param name="data">The content data being read.</param>
+ /// <param name="getNormalisedPath">Normalises an asset key to match the cache key.</param>
+ public AssetData(string locale, string assetName, TValue data, Func<string, string> getNormalisedPath)
+ : base(locale, assetName, data.GetType(), getNormalisedPath)
+ {
+ this.Data = data;
+ }
+
+ /// <summary>Replace the entire content value with the given value. This is generally not recommended, since it may break compatibility with other mods or different versions of the game.</summary>
+ /// <param name="value">The new content value.</param>
+ /// <exception cref="ArgumentNullException">The <paramref name="value"/> is null.</exception>
+ /// <exception cref="InvalidCastException">The <paramref name="value"/>'s type is not compatible with the loaded asset's type.</exception>
+ public void ReplaceWith(TValue value)
+ {
+ if (value == null)
+ throw new ArgumentNullException(nameof(value), "Can't set a loaded asset to a null value.");
+ if (!this.DataType.IsInstanceOfType(value))
+ throw new InvalidCastException($"Can't replace loaded asset of type {this.GetFriendlyTypeName(this.DataType)} with value of type {this.GetFriendlyTypeName(value.GetType())}. The new type must be compatible to prevent game errors.");
+
+ this.Data = value;
+ }
+ }
+}
diff --git a/src/StardewModdingAPI/Framework/Content/ContentEventHelperForDictionary.cs b/src/StardewModdingAPI/Framework/Content/AssetDataForDictionary.cs
index 26f059e4..e9b29b12 100644
--- a/src/StardewModdingAPI/Framework/Content/ContentEventHelperForDictionary.cs
+++ b/src/StardewModdingAPI/Framework/Content/AssetDataForDictionary.cs
@@ -5,7 +5,7 @@ using System.Linq;
namespace StardewModdingAPI.Framework.Content
{
/// <summary>Encapsulates access and changes to dictionary content being read from a data file.</summary>
- internal class ContentEventHelperForDictionary<TKey, TValue> : ContentEventData<IDictionary<TKey, TValue>>, IContentEventHelperForDictionary<TKey, TValue>
+ internal class AssetDataForDictionary<TKey, TValue> : AssetData<IDictionary<TKey, TValue>>, IAssetDataForDictionary<TKey, TValue>
{
/*********
** Public methods
@@ -15,7 +15,7 @@ namespace StardewModdingAPI.Framework.Content
/// <param name="assetName">The normalised asset name being read.</param>
/// <param name="data">The content data being read.</param>
/// <param name="getNormalisedPath">Normalises an asset key to match the cache key.</param>
- public ContentEventHelperForDictionary(string locale, string assetName, IDictionary<TKey, TValue> data, Func<string, string> getNormalisedPath)
+ public AssetDataForDictionary(string locale, string assetName, IDictionary<TKey, TValue> data, Func<string, string> getNormalisedPath)
: base(locale, assetName, data, getNormalisedPath) { }
/// <summary>Add or replace an entry in the dictionary.</summary>
diff --git a/src/StardewModdingAPI/Framework/Content/ContentEventHelperForImage.cs b/src/StardewModdingAPI/Framework/Content/AssetDataForImage.cs
index da30590b..45c5588b 100644
--- a/src/StardewModdingAPI/Framework/Content/ContentEventHelperForImage.cs
+++ b/src/StardewModdingAPI/Framework/Content/AssetDataForImage.cs
@@ -5,7 +5,7 @@ using Microsoft.Xna.Framework.Graphics;
namespace StardewModdingAPI.Framework.Content
{
/// <summary>Encapsulates access and changes to dictionary content being read from a data file.</summary>
- internal class ContentEventHelperForImage : ContentEventData<Texture2D>, IContentEventHelperForImage
+ internal class AssetDataForImage : AssetData<Texture2D>, IAssetDataForImage
{
/*********
** Public methods
@@ -15,7 +15,7 @@ namespace StardewModdingAPI.Framework.Content
/// <param name="assetName">The normalised asset name being read.</param>
/// <param name="data">The content data being read.</param>
/// <param name="getNormalisedPath">Normalises an asset key to match the cache key.</param>
- public ContentEventHelperForImage(string locale, string assetName, Texture2D data, Func<string, string> getNormalisedPath)
+ public AssetDataForImage(string locale, string assetName, Texture2D data, Func<string, string> getNormalisedPath)
: base(locale, assetName, data, getNormalisedPath) { }
/// <summary>Overwrite part of the image.</summary>
diff --git a/src/StardewModdingAPI/Framework/Content/ContentEventHelper.cs b/src/StardewModdingAPI/Framework/Content/AssetDataForObject.cs
index 9bf1ea17..f30003e4 100644
--- a/src/StardewModdingAPI/Framework/Content/ContentEventHelper.cs
+++ b/src/StardewModdingAPI/Framework/Content/AssetDataForObject.cs
@@ -5,7 +5,7 @@ using Microsoft.Xna.Framework.Graphics;
namespace StardewModdingAPI.Framework.Content
{
/// <summary>Encapsulates access and changes to content being read from a data file.</summary>
- internal class ContentEventHelper : ContentEventData<object>, IContentEventHelper
+ internal class AssetDataForObject : AssetData<object>, IAssetData
{
/*********
** Public methods
@@ -15,23 +15,30 @@ namespace StardewModdingAPI.Framework.Content
/// <param name="assetName">The normalised asset name being read.</param>
/// <param name="data">The content data being read.</param>
/// <param name="getNormalisedPath">Normalises an asset key to match the cache key.</param>
- public ContentEventHelper(string locale, string assetName, object data, Func<string, string> getNormalisedPath)
+ public AssetDataForObject(string locale, string assetName, object data, Func<string, string> getNormalisedPath)
: base(locale, assetName, data, getNormalisedPath) { }
+ /// <summary>Construct an instance.</summary>
+ /// <param name="info">The asset metadata.</param>
+ /// <param name="data">The content data being read.</param>
+ /// <param name="getNormalisedPath">Normalises an asset key to match the cache key.</param>
+ public AssetDataForObject(IAssetInfo info, object data, Func<string, string> getNormalisedPath)
+ : this(info.Locale, info.AssetName, data, getNormalisedPath) { }
+
/// <summary>Get a helper to manipulate the data as a dictionary.</summary>
/// <typeparam name="TKey">The expected dictionary key.</typeparam>
/// <typeparam name="TValue">The expected dictionary balue.</typeparam>
/// <exception cref="InvalidOperationException">The content being read isn't a dictionary.</exception>
- public IContentEventHelperForDictionary<TKey, TValue> AsDictionary<TKey, TValue>()
+ public IAssetDataForDictionary<TKey, TValue> AsDictionary<TKey, TValue>()
{
- return new ContentEventHelperForDictionary<TKey, TValue>(this.Locale, this.AssetName, this.GetData<IDictionary<TKey, TValue>>(), this.GetNormalisedPath);
+ return new AssetDataForDictionary<TKey, TValue>(this.Locale, this.AssetName, this.GetData<IDictionary<TKey, TValue>>(), this.GetNormalisedPath);
}
/// <summary>Get a helper to manipulate the data as an image.</summary>
/// <exception cref="InvalidOperationException">The content being read isn't an image.</exception>
- public IContentEventHelperForImage AsImage()
+ public IAssetDataForImage AsImage()
{
- return new ContentEventHelperForImage(this.Locale, this.AssetName, this.GetData<Texture2D>(), this.GetNormalisedPath);
+ return new AssetDataForImage(this.Locale, this.AssetName, this.GetData<Texture2D>(), this.GetNormalisedPath);
}
/// <summary>Get the data as a given type.</summary>
diff --git a/src/StardewModdingAPI/Framework/Content/ContentEventData.cs b/src/StardewModdingAPI/Framework/Content/AssetInfo.cs
index 1a1779d4..d580dc06 100644
--- a/src/StardewModdingAPI/Framework/Content/ContentEventData.cs
+++ b/src/StardewModdingAPI/Framework/Content/AssetInfo.cs
@@ -4,9 +4,7 @@ using Microsoft.Xna.Framework.Graphics;
namespace StardewModdingAPI.Framework.Content
{
- /// <summary>Base implementation for a content helper which encapsulates access and changes to content being read from a data file.</summary>
- /// <typeparam name="TValue">The interface value type.</typeparam>
- internal class ContentEventData<TValue> : EventArgs, IContentEventData<TValue>
+ internal class AssetInfo : IAssetInfo
{
/*********
** Properties
@@ -21,12 +19,9 @@ namespace StardewModdingAPI.Framework.Content
/// <summary>The content's locale code, if the content is localised.</summary>
public string Locale { get; }
- /// <summary>The normalised asset name being read. The format may change between platforms; see <see cref="IsAssetName"/> to compare with a known path.</summary>
+ /// <summary>The normalised asset name being read. The format may change between platforms; see <see cref="AssetNameEquals"/> to compare with a known path.</summary>
public string AssetName { get; }
- /// <summary>The content data being read.</summary>
- public TValue Data { get; protected set; }
-
/// <summary>The content data type.</summary>
public Type DataType { get; }
@@ -37,48 +32,24 @@ namespace StardewModdingAPI.Framework.Content
/// <summary>Construct an instance.</summary>
/// <param name="locale">The content's locale code, if the content is localised.</param>
/// <param name="assetName">The normalised asset name being read.</param>
- /// <param name="data">The content data being read.</param>
- /// <param name="getNormalisedPath">Normalises an asset key to match the cache key.</param>
- public ContentEventData(string locale, string assetName, TValue data, Func<string, string> getNormalisedPath)
- : this(locale, assetName, data, data.GetType(), getNormalisedPath) { }
-
- /// <summary>Construct an instance.</summary>
- /// <param name="locale">The content's locale code, if the content is localised.</param>
- /// <param name="assetName">The normalised asset name being read.</param>
- /// <param name="data">The content data being read.</param>
- /// <param name="dataType">The content data type being read.</param>
+ /// <param name="type">The content type being read.</param>
/// <param name="getNormalisedPath">Normalises an asset key to match the cache key.</param>
- public ContentEventData(string locale, string assetName, TValue data, Type dataType, Func<string, string> getNormalisedPath)
+ public AssetInfo(string locale, string assetName, Type type, Func<string, string> getNormalisedPath)
{
this.Locale = locale;
this.AssetName = assetName;
- this.Data = data;
- this.DataType = dataType;
+ this.DataType = type;
this.GetNormalisedPath = getNormalisedPath;
}
/// <summary>Get whether the asset name being loaded matches a given name after normalisation.</summary>
/// <param name="path">The expected asset path, relative to the game's content folder and without the .xnb extension or locale suffix (like 'Data\ObjectInformation').</param>
- public bool IsAssetName(string path)
+ public bool AssetNameEquals(string path)
{
path = this.GetNormalisedPath(path);
return this.AssetName.Equals(path, StringComparison.InvariantCultureIgnoreCase);
}
- /// <summary>Replace the entire content value with the given value. This is generally not recommended, since it may break compatibility with other mods or different versions of the game.</summary>
- /// <param name="value">The new content value.</param>
- /// <exception cref="ArgumentNullException">The <paramref name="value"/> is null.</exception>
- /// <exception cref="InvalidCastException">The <paramref name="value"/>'s type is not compatible with the loaded asset's type.</exception>
- public void ReplaceWith(TValue value)
- {
- if (value == null)
- throw new ArgumentNullException(nameof(value), "Can't set a loaded asset to a null value.");
- if (!this.DataType.IsInstanceOfType(value))
- throw new InvalidCastException($"Can't replace loaded asset of type {this.GetFriendlyTypeName(this.DataType)} with value of type {this.GetFriendlyTypeName(value.GetType())}. The new type must be compatible to prevent game errors.");
-
- this.Data = value;
- }
-
/*********
** Protected methods
diff --git a/src/StardewModdingAPI/Framework/CursorPosition.cs b/src/StardewModdingAPI/Framework/CursorPosition.cs
new file mode 100644
index 00000000..4f256da5
--- /dev/null
+++ b/src/StardewModdingAPI/Framework/CursorPosition.cs
@@ -0,0 +1,37 @@
+#if SMAPI_2_0
+using Microsoft.Xna.Framework;
+
+namespace StardewModdingAPI.Framework
+{
+ /// <summary>Defines a position on a given map at different reference points.</summary>
+ internal class CursorPosition : ICursorPosition
+ {
+ /*********
+ ** Accessors
+ *********/
+ /// <summary>The pixel position relative to the top-left corner of the visible screen.</summary>
+ public Vector2 ScreenPixels { get; }
+
+ /// <summary>The tile position under the cursor relative to the top-left corner of the map.</summary>
+ public Vector2 Tile { get; }
+
+ /// <summary>The tile position that the game considers under the cursor for purposes of clicking actions. This may be different than <see cref="Tile"/> if that's too far from the player.</summary>
+ public Vector2 GrabTile { get; }
+
+
+ /*********
+ ** Public methods
+ *********/
+ /// <summary>Construct an instance.</summary>
+ /// <param name="screenPixels">The pixel position relative to the top-left corner of the visible screen.</param>
+ /// <param name="tile">The tile position relative to the top-left corner of the map.</param>
+ /// <param name="grabTile">The tile position that the game considers under the cursor for purposes of clicking actions.</param>
+ public CursorPosition(Vector2 screenPixels, Vector2 tile, Vector2 grabTile)
+ {
+ this.ScreenPixels = screenPixels;
+ this.Tile = tile;
+ this.GrabTile = grabTile;
+ }
+ }
+}
+#endif
diff --git a/src/StardewModdingAPI/Framework/DeprecationManager.cs b/src/StardewModdingAPI/Framework/DeprecationManager.cs
index 6b95960b..153d8829 100644
--- a/src/StardewModdingAPI/Framework/DeprecationManager.cs
+++ b/src/StardewModdingAPI/Framework/DeprecationManager.cs
@@ -52,13 +52,12 @@ namespace StardewModdingAPI.Framework
if (!this.MarkWarned(source ?? "<unknown>", nounPhrase, version))
return;
+ // show SMAPI 2.0 meta-warning
+ if(this.MarkWarned("SMAPI", "SMAPI 2.0 meta-warning", "2.0"))
+ this.Monitor.Log("Some mods may stop working in SMAPI 2.0 (but they'll work fine for now). Try updating mods with 'deprecated code' warnings; if that doesn't remove the warnings, let the mod authors know about this message or see http://community.playstarbound.com/threads/135000 for details.", LogLevel.Warn);
+
// build message
- string message = source != null
- ? $"{source} used {nounPhrase}, which is deprecated since SMAPI {version}."
- : $"An unknown mod used {nounPhrase}, which is deprecated since SMAPI {version}.";
- message += severity != DeprecationLevel.PendingRemoval
- ? " This will break in a future version of SMAPI."
- : " It will be removed soon, so the mod will break if it's not updated.";
+ string message = $"{source ?? "An unknown mod"} uses deprecated code ({nounPhrase}).";
if (source == null)
message += $"{Environment.NewLine}{Environment.StackTrace}";
@@ -70,7 +69,7 @@ namespace StardewModdingAPI.Framework
break;
case DeprecationLevel.Info:
- this.Monitor.Log(message, LogLevel.Warn);
+ this.Monitor.Log(message, LogLevel.Debug);
break;
case DeprecationLevel.PendingRemoval:
diff --git a/src/StardewModdingAPI/Framework/Exceptions/SParseException.cs b/src/StardewModdingAPI/Framework/Exceptions/SParseException.cs
new file mode 100644
index 00000000..f7133ee7
--- /dev/null
+++ b/src/StardewModdingAPI/Framework/Exceptions/SParseException.cs
@@ -0,0 +1,17 @@
+using System;
+
+namespace StardewModdingAPI.Framework.Exceptions
+{
+ /// <summary>A format exception which provides a user-facing error message.</summary>
+ internal class SParseException : FormatException
+ {
+ /*********
+ ** Public methods
+ *********/
+ /// <summary>Construct an instance.</summary>
+ /// <param name="message">The error message.</param>
+ /// <param name="ex">The underlying exception, if any.</param>
+ public SParseException(string message, Exception ex = null)
+ : base(message, ex) { }
+ }
+}
diff --git a/src/StardewModdingAPI/Framework/InternalExtensions.cs b/src/StardewModdingAPI/Framework/InternalExtensions.cs
index b99d3798..2842bc83 100644
--- a/src/StardewModdingAPI/Framework/InternalExtensions.cs
+++ b/src/StardewModdingAPI/Framework/InternalExtensions.cs
@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Microsoft.Xna.Framework.Graphics;
+using StardewModdingAPI.Framework.Reflection;
using StardewValley;
namespace StardewModdingAPI.Framework
@@ -99,7 +100,7 @@ namespace StardewModdingAPI.Framework
/// <summary>Get whether the sprite batch is between a begin and end pair.</summary>
/// <param name="spriteBatch">The sprite batch to check.</param>
/// <param name="reflection">The reflection helper with which to access private fields.</param>
- public static bool IsOpen(this SpriteBatch spriteBatch, IReflectionHelper reflection)
+ public static bool IsOpen(this SpriteBatch spriteBatch, Reflector reflection)
{
// get field name
const string fieldName =
@@ -110,7 +111,7 @@ namespace StardewModdingAPI.Framework
#endif
// get result
- return reflection.GetPrivateValue<bool>(Game1.spriteBatch, fieldName);
+ return reflection.GetPrivateField<bool>(Game1.spriteBatch, fieldName).GetValue();
}
}
}
diff --git a/src/StardewModdingAPI/Framework/ModHelpers/BaseHelper.cs b/src/StardewModdingAPI/Framework/ModHelpers/BaseHelper.cs
new file mode 100644
index 00000000..16032da1
--- /dev/null
+++ b/src/StardewModdingAPI/Framework/ModHelpers/BaseHelper.cs
@@ -0,0 +1,23 @@
+namespace StardewModdingAPI.Framework.ModHelpers
+{
+ /// <summary>The common base class for mod helpers.</summary>
+ internal abstract class BaseHelper : IModLinked
+ {
+ /*********
+ ** Accessors
+ *********/
+ /// <summary>The unique ID of the mod for which the helper was created.</summary>
+ public string ModID { get; }
+
+
+ /*********
+ ** Protected methods
+ *********/
+ /// <summary>Construct an instance.</summary>
+ /// <param name="modID">The unique ID of the relevant mod.</param>
+ protected BaseHelper(string modID)
+ {
+ this.ModID = modID;
+ }
+ }
+}
diff --git a/src/StardewModdingAPI/Framework/CommandHelper.cs b/src/StardewModdingAPI/Framework/ModHelpers/CommandHelper.cs
index 86734fc5..bdedb07c 100644
--- a/src/StardewModdingAPI/Framework/CommandHelper.cs
+++ b/src/StardewModdingAPI/Framework/ModHelpers/CommandHelper.cs
@@ -1,9 +1,9 @@
using System;
-namespace StardewModdingAPI.Framework
+namespace StardewModdingAPI.Framework.ModHelpers
{
/// <summary>Provides an API for managing console commands.</summary>
- internal class CommandHelper : ICommandHelper
+ internal class CommandHelper : BaseHelper, ICommandHelper
{
/*********
** Accessors
@@ -15,14 +15,15 @@ namespace StardewModdingAPI.Framework
private readonly CommandManager CommandManager;
-
/*********
** Public methods
*********/
/// <summary>Construct an instance.</summary>
+ /// <param name="modID">The unique ID of the relevant mod.</param>
/// <param name="modName">The friendly mod name for this instance.</param>
/// <param name="commandManager">Manages console commands.</param>
- public CommandHelper(string modName, CommandManager commandManager)
+ public CommandHelper(string modID, string modName, CommandManager commandManager)
+ : base(modID)
{
this.ModName = modName;
this.CommandManager = commandManager;
diff --git a/src/StardewModdingAPI/Framework/ContentHelper.cs b/src/StardewModdingAPI/Framework/ModHelpers/ContentHelper.cs
index 7fd5e803..5f72176e 100644
--- a/src/StardewModdingAPI/Framework/ContentHelper.cs
+++ b/src/StardewModdingAPI/Framework/ModHelpers/ContentHelper.cs
@@ -1,4 +1,6 @@
using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Linq;
@@ -11,10 +13,10 @@ using xTile;
using xTile.Format;
using xTile.Tiles;
-namespace StardewModdingAPI.Framework
+namespace StardewModdingAPI.Framework.ModHelpers
{
/// <summary>Provides an API for loading content assets.</summary>
- internal class ContentHelper : IContentHelper
+ internal class ContentHelper : BaseHelper, IContentHelper
{
/*********
** Properties
@@ -33,13 +35,31 @@ namespace StardewModdingAPI.Framework
/*********
+ ** Accessors
+ *********/
+ /// <summary>The observable implementation of <see cref="AssetEditors"/>.</summary>
+ internal ObservableCollection<IAssetEditor> ObservableAssetEditors { get; } = new ObservableCollection<IAssetEditor>();
+
+ /// <summary>The observable implementation of <see cref="AssetLoaders"/>.</summary>
+ internal ObservableCollection<IAssetLoader> ObservableAssetLoaders { get; } = new ObservableCollection<IAssetLoader>();
+
+ /// <summary>Interceptors which provide the initial versions of matching content assets.</summary>
+ internal IList<IAssetLoader> AssetLoaders => this.ObservableAssetLoaders;
+
+ /// <summary>Interceptors which edit matching content assets after they're loaded.</summary>
+ internal IList<IAssetEditor> AssetEditors => this.ObservableAssetEditors;
+
+
+ /*********
** Public methods
*********/
/// <summary>Construct an instance.</summary>
/// <param name="contentManager">SMAPI's underlying content manager.</param>
/// <param name="modFolderPath">The absolute path to the mod folder.</param>
+ /// <param name="modID">The unique ID of the relevant mod.</param>
/// <param name="modName">The friendly mod name for use in errors.</param>
- public ContentHelper(SContentManager contentManager, string modFolderPath, string modName)
+ public ContentHelper(SContentManager contentManager, string modFolderPath, string modID, string modName)
+ : base(modID)
{
this.ContentManager = contentManager;
this.ModFolderPath = modFolderPath;
diff --git a/src/StardewModdingAPI/Framework/ModHelper.cs b/src/StardewModdingAPI/Framework/ModHelpers/ModHelper.cs
index 5a8ce459..665b9cf4 100644
--- a/src/StardewModdingAPI/Framework/ModHelper.cs
+++ b/src/StardewModdingAPI/Framework/ModHelpers/ModHelper.cs
@@ -2,10 +2,10 @@
using System.IO;
using StardewModdingAPI.Framework.Serialisation;
-namespace StardewModdingAPI.Framework
+namespace StardewModdingAPI.Framework.ModHelpers
{
/// <summary>Provides simplified APIs for writing mods.</summary>
- internal class ModHelper : IModHelper, IDisposable
+ internal class ModHelper : BaseHelper, IModHelper, IDisposable
{
/*********
** Properties
@@ -23,16 +23,16 @@ namespace StardewModdingAPI.Framework
/// <summary>An API for loading content assets.</summary>
public IContentHelper Content { get; }
- /// <summary>Simplifies access to private game code.</summary>
+ /// <summary>An API for accessing private game code.</summary>
public IReflectionHelper Reflection { get; }
- /// <summary>Metadata about loaded mods.</summary>
+ /// <summary>an API for fetching metadata about loaded mods.</summary>
public IModRegistry ModRegistry { get; }
/// <summary>An API for managing console commands.</summary>
public ICommandHelper ConsoleCommands { get; }
- /// <summary>Provides translations stored in the mod's <c>i18n</c> folder, with one file per locale (like <c>en.json</c>) containing a flat key => value structure. Translations are fetched with locale fallback, so missing translations are filled in from broader locales (like <c>pt-BR.json</c> &lt; <c>pt.json</c> &lt; <c>default.json</c>).</summary>
+ /// <summary>An API for reading translations stored in the mod's <c>i18n</c> folder, with one file per locale (like <c>en.json</c>) containing a flat key => value structure. Translations are fetched with locale fallback, so missing translations are filled in from broader locales (like <c>pt-BR.json</c> &lt; <c>pt.json</c> &lt; <c>default.json</c>).</summary>
public ITranslationHelper Translation { get; }
@@ -40,35 +40,33 @@ namespace StardewModdingAPI.Framework
** Public methods
*********/
/// <summary>Construct an instance.</summary>
- /// <param name="displayName">The mod's display name.</param>
+ /// <param name="modID">The mod's unique ID.</param>
/// <param name="modDirectory">The full path to the mod's folder.</param>
/// <param name="jsonHelper">Encapsulate SMAPI's JSON parsing.</param>
- /// <param name="modRegistry">Metadata about loaded mods.</param>
- /// <param name="commandManager">Manages console commands.</param>
- /// <param name="contentManager">The content manager which loads content assets.</param>
- /// <param name="reflection">Simplifies access to private game code.</param>
+ /// <param name="contentHelper">An API for loading content assets.</param>
+ /// <param name="commandHelper">An API for managing console commands.</param>
+ /// <param name="modRegistry">an API for fetching metadata about loaded mods.</param>
+ /// <param name="reflectionHelper">An API for accessing private game code.</param>
+ /// <param name="translationHelper">An API for reading translations stored in the mod's <c>i18n</c> folder.</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(string displayName, string modDirectory, JsonHelper jsonHelper, IModRegistry modRegistry, CommandManager commandManager, SContentManager contentManager, IReflectionHelper reflection)
+ public ModHelper(string modID, string modDirectory, JsonHelper jsonHelper, IContentHelper contentHelper, ICommandHelper commandHelper, IModRegistry modRegistry, IReflectionHelper reflectionHelper, ITranslationHelper translationHelper)
+ : base(modID)
{
- // validate
+ // validate directory
if (string.IsNullOrWhiteSpace(modDirectory))
throw new ArgumentNullException(nameof(modDirectory));
- if (jsonHelper == null)
- throw new ArgumentNullException(nameof(jsonHelper));
- if (modRegistry == null)
- throw new ArgumentNullException(nameof(modRegistry));
if (!Directory.Exists(modDirectory))
throw new InvalidOperationException("The specified mod directory does not exist.");
// initialise
this.