diff options
Diffstat (limited to 'src/SMAPI')
32 files changed, 873 insertions, 385 deletions
diff --git a/src/SMAPI/Constants.cs b/src/SMAPI/Constants.cs index 41b79272..786ae32b 100644 --- a/src/SMAPI/Constants.cs +++ b/src/SMAPI/Constants.cs @@ -29,7 +29,7 @@ namespace StardewModdingAPI ** Public ****/ /// <summary>SMAPI's current semantic version.</summary> - public static ISemanticVersion ApiVersion { get; } = new SemanticVersion("2.2"); + public static ISemanticVersion ApiVersion { get; } = new SemanticVersion("2.3"); /// <summary>The minimum supported version of Stardew Valley.</summary> public static ISemanticVersion MinimumGameVersion { get; } = new SemanticVersion("1.2.30"); diff --git a/src/SMAPI/Events/EventArgsInput.cs b/src/SMAPI/Events/EventArgsInput.cs index 54ce9b53..a5325b76 100644 --- a/src/SMAPI/Events/EventArgsInput.cs +++ b/src/SMAPI/Events/EventArgsInput.cs @@ -16,7 +16,7 @@ namespace StardewModdingAPI.Events public SButton Button { get; } /// <summary>The current cursor position.</summary> - public ICursorPosition Cursor { get; set; } + public ICursorPosition Cursor { get; } /// <summary>Whether the input is considered a 'click' by the game for enabling action.</summary> [Obsolete("Use " + nameof(EventArgsInput.IsActionButton) + " or " + nameof(EventArgsInput.IsUseToolButton) + " instead")] // deprecated in SMAPI 2.1 @@ -28,6 +28,9 @@ namespace StardewModdingAPI.Events /// <summary>Whether the input should use tools on the affected tile.</summary> public bool IsUseToolButton { get; } + /// <summary>Whether a mod has indicated the key was already handled.</summary> + public bool IsSuppressed { get; private set; } + /********* ** Public methods @@ -55,6 +58,9 @@ namespace StardewModdingAPI.Events /// <param name="button">The button to suppress.</param> public void SuppressButton(SButton button) { + if (button == this.Button) + this.IsSuppressed = true; + // keyboard if (button.TryGetKeyboard(out Keys key)) Game1.oldKBState = new KeyboardState(Game1.oldKBState.GetPressedKeys().Union(new[] { key }).ToArray()); diff --git a/src/SMAPI/Events/GameEvents.cs b/src/SMAPI/Events/GameEvents.cs index b477376e..3466470d 100644 --- a/src/SMAPI/Events/GameEvents.cs +++ b/src/SMAPI/Events/GameEvents.cs @@ -33,6 +33,9 @@ namespace StardewModdingAPI.Events /// <summary>Raised every 60th tick (≈once per second).</summary> public static event EventHandler OneSecondTick; + /// <summary>Raised once after the game initialises and all <see cref="IMod.Entry"/> methods have been called.</summary> + public static event EventHandler FirstUpdateTick; + /********* ** Internal methods @@ -92,5 +95,12 @@ namespace StardewModdingAPI.Events { monitor.SafelyRaisePlainEvent($"{nameof(GameEvents)}.{nameof(GameEvents.OneSecondTick)}", GameEvents.OneSecondTick?.GetInvocationList()); } + + /// <summary>Raise a <see cref="FirstUpdateTick"/> event.</summary> + /// <param name="monitor">Encapsulates monitoring and logging.</param> + internal static void InvokeFirstUpdateTick(IMonitor monitor) + { + monitor.SafelyRaisePlainEvent($"{nameof(GameEvents)}.{nameof(GameEvents.FirstUpdateTick)}", GameEvents.FirstUpdateTick?.GetInvocationList()); + } } } diff --git a/src/SMAPI/Framework/Content/ContentCache.cs b/src/SMAPI/Framework/Content/ContentCache.cs index 10c41d08..4508e641 100644 --- a/src/SMAPI/Framework/Content/ContentCache.cs +++ b/src/SMAPI/Framework/Content/ContentCache.cs @@ -57,14 +57,14 @@ namespace StardewModdingAPI.Framework.Content public ContentCache(LocalizedContentManager contentManager, Reflector reflection, char[] possiblePathSeparators, string preferredPathSeparator) { // init - this.Cache = reflection.GetPrivateField<Dictionary<string, object>>(contentManager, "loadedAssets").GetValue(); + this.Cache = reflection.GetField<Dictionary<string, object>>(contentManager, "loadedAssets").GetValue(); this.PossiblePathSeparators = possiblePathSeparators; this.PreferredPathSeparator = preferredPathSeparator; // get key normalisation logic if (Constants.TargetPlatform == Platform.Windows) { - IPrivateMethod method = reflection.GetPrivateMethod(typeof(TitleContainer), "GetCleanPath"); + IReflectedMethod method = reflection.GetMethod(typeof(TitleContainer), "GetCleanPath"); this.NormaliseAssetNameForPlatform = path => method.Invoke<string>(path); } else diff --git a/src/SMAPI/Framework/DeprecationManager.cs b/src/SMAPI/Framework/DeprecationManager.cs index b07c6c7d..7a824a05 100644 --- a/src/SMAPI/Framework/DeprecationManager.cs +++ b/src/SMAPI/Framework/DeprecationManager.cs @@ -37,7 +37,7 @@ namespace StardewModdingAPI.Framework /// <param name="severity">How deprecated the code is.</param> public void Warn(string nounPhrase, string version, DeprecationLevel severity) { - this.Warn(this.ModRegistry.GetModFromStack(), nounPhrase, version, severity); + this.Warn(this.ModRegistry.GetFromStack()?.DisplayName, nounPhrase, version, severity); } /// <summary>Log a deprecation warning.</summary> @@ -52,7 +52,7 @@ namespace StardewModdingAPI.Framework return; // build message - string message = $"{source ?? "An unknown mod"} uses deprecated code ({nounPhrase})."; + string message = $"{source ?? "An unknown mod"} uses deprecated code ({nounPhrase} is deprecated since SMAPI {version})."; if (source == null) message += $"{Environment.NewLine}{Environment.StackTrace}"; @@ -82,7 +82,7 @@ namespace StardewModdingAPI.Framework /// <returns>Returns whether the deprecation was successfully marked as warned. Returns <c>false</c> if it was already marked.</returns> public bool MarkWarned(string nounPhrase, string version) { - return this.MarkWarned(this.ModRegistry.GetModFromStack(), nounPhrase, version); + return this.MarkWarned(this.ModRegistry.GetFromStack()?.DisplayName, nounPhrase, version); } /// <summary>Mark a deprecation warning as already logged.</summary> diff --git a/src/SMAPI/Framework/IModMetadata.cs b/src/SMAPI/Framework/IModMetadata.cs index c21734a7..a36994fd 100644 --- a/src/SMAPI/Framework/IModMetadata.cs +++ b/src/SMAPI/Framework/IModMetadata.cs @@ -30,6 +30,9 @@ namespace StardewModdingAPI.Framework /// <summary>The mod instance (if it was loaded).</summary> IMod Mod { get; } + /// <summary>The mod-provided API (if any).</summary> + object Api { get; } + /********* ** Public methods @@ -43,5 +46,9 @@ namespace StardewModdingAPI.Framework /// <summary>Set the mod instance.</summary> /// <param name="mod">The mod instance to set.</param> IModMetadata SetMod(IMod mod); + + /// <summary>Set the mod-provided API instance.</summary> + /// <param name="api">The mod-provided API.</param> + IModMetadata SetApi(object api); } } diff --git a/src/SMAPI/Framework/InternalExtensions.cs b/src/SMAPI/Framework/InternalExtensions.cs index 3709e05d..bec6c183 100644 --- a/src/SMAPI/Framework/InternalExtensions.cs +++ b/src/SMAPI/Framework/InternalExtensions.cs @@ -108,6 +108,15 @@ namespace StardewModdingAPI.Framework } } + /// <summary>Get the lowest exception in an exception stack.</summary> + /// <param name="exception">The exception from which to search.</param> + public static Exception GetInnermostException(this Exception exception) + { + while (exception.InnerException != null) + exception = exception.InnerException; + return exception; + } + /**** ** Sprite batch ****/ @@ -125,7 +134,7 @@ namespace StardewModdingAPI.Framework #endif // get result - return reflection.GetPrivateField<bool>(Game1.spriteBatch, fieldName).GetValue(); + return reflection.GetField<bool>(Game1.spriteBatch, fieldName).GetValue(); } } } diff --git a/src/SMAPI/Framework/ModHelpers/ModRegistryHelper.cs b/src/SMAPI/Framework/ModHelpers/ModRegistryHelper.cs index 9e824694..ea0dbb38 100644 --- a/src/SMAPI/Framework/ModHelpers/ModRegistryHelper.cs +++ b/src/SMAPI/Framework/ModHelpers/ModRegistryHelper.cs @@ -1,4 +1,6 @@ -using System.Collections.Generic; +using System.Collections.Generic; +using System.Linq; +using StardewModdingAPI.Framework.Reflection; namespace StardewModdingAPI.Framework.ModHelpers { @@ -11,6 +13,15 @@ namespace StardewModdingAPI.Framework.ModHelpers /// <summary>The underlying mod registry.</summary> private readonly ModRegistry Registry; + /// <summary>Encapsulates monitoring and logging for the mod.</summary> + private readonly IMonitor Monitor; + + /// <summary>The mod IDs for APIs accessed by this instanced.</summary> + private readonly HashSet<string> AccessedModApis = new HashSet<string>(); + + /// <summary>Generates proxy classes to access mod APIs through an arbitrary interface.</summary> + private readonly InterfaceProxyBuilder ProxyBuilder; + /********* ** Public methods @@ -18,16 +29,20 @@ namespace StardewModdingAPI.Framework.ModHelpers /// <summary>Construct an instance.</summary> /// <param name="modID">The unique ID of the relevant mod.</param> /// <param name="registry">The underlying mod registry.</param> - public ModRegistryHelper(string modID, ModRegistry registry) + /// <param name="proxyBuilder">Generates proxy classes to access mod APIs through an arbitrary interface.</param> + /// <param name="monitor">Encapsulates monitoring and logging for the mod.</param> + public ModRegistryHelper(string modID, ModRegistry registry, InterfaceProxyBuilder proxyBuilder, IMonitor monitor) : base(modID) { this.Registry = registry; + this.ProxyBuilder = proxyBuilder; + this.Monitor = monitor; } /// <summary>Get metadata for all loaded mods.</summary> public IEnumerable<IManifest> GetAll() { - return this.Registry.GetAll(); + return this.Registry.GetAll().Select(p => p.Manifest); } /// <summary>Get metadata for a loaded mod.</summary> @@ -35,14 +50,56 @@ namespace StardewModdingAPI.Framework.ModHelpers /// <returns>Returns the matching mod's metadata, or <c>null</c> if not found.</returns> public IManifest Get(string uniqueID) { - return this.Registry.Get(uniqueID); + return this.Registry.Get(uniqueID)?.Manifest; } /// <summary>Get whether a mod has been loaded.</summary> /// <param name="uniqueID">The mod's unique ID.</param> public bool IsLoaded(string uniqueID) { - return this.Registry.IsLoaded(uniqueID); + return this.Registry.Get(uniqueID) != null; + } + + /// <summary>Get the API provided by a mod, or <c>null</c> if it has none. This signature requires using the <see cref="IModHelper.Reflection"/> API to access the API's properties and methods.</summary> + public object GetApi(string uniqueID) + { + IModMetadata mod = this.Registry.Get(uniqueID); + if (mod?.Api != null && this.AccessedModApis.Add(mod.Manifest.UniqueID)) + this.Monitor.Log($"Accessed mod-provided API for {mod.DisplayName}.", LogLevel.Trace); + return mod?.Api; + } + + /// <summary>Get the API provided by a mod, mapped to a given interface which specifies the expected properties and methods. If the mod has no API or it's not compatible with the given interface, get <c>null</c>.</summary> + /// <typeparam name="TInterface">The interface which matches the properties and methods you intend to access.</typeparam> + /// <param name="uniqueID">The mod's unique ID.</param> + public TInterface GetApi<TInterface>(string uniqueID) where TInterface : class + { + // validate + if (!this.Registry.AreAllModsInitialised) + { + this.Monitor.Log("Tried to access a mod-provided API before all mods were initialised.", LogLevel.Error); + return null; + } + if (!typeof(TInterface).IsInterface) + { + this.Monitor.Log("Tried to map a mod-provided API to a class; must be a public interface.", LogLevel.Error); + return null; + } + if (!typeof(TInterface).IsPublic) + { + this.Monitor.Log("Tried to map a mod-provided API to a non-public interface; must be a public interface.", LogLevel.Error); + return null; + } + + // get raw API + object api = this.GetApi(uniqueID); + if (api == null) + return null; + + // get API of type + if (api is TInterface castApi) + return castApi; + return this.ProxyBuilder.CreateProxy<TInterface>(api, this.ModID, uniqueID); } } } diff --git a/src/SMAPI/Framework/ModHelpers/ReflectionHelper.cs b/src/SMAPI/Framework/ModHelpers/ReflectionHelper.cs index 8788b142..81453003 100644 --- a/src/SMAPI/Framework/ModHelpers/ReflectionHelper.cs +++ b/src/SMAPI/Framework/ModHelpers/ReflectionHelper.cs @@ -17,6 +17,9 @@ namespace StardewModdingAPI.Framework.ModHelpers /// <summary>The mod name for error messages.</summary> private readonly string ModName; + /// <summary>Manages deprecation warnings.</summary> + private readonly DeprecationManager DeprecationManager; + /********* ** Public methods @@ -25,15 +28,88 @@ namespace StardewModdingAPI.Framework.ModHelpers /// <param name="modID">The unique ID of the relevant mod.</param> /// <param name="modName">The mod name for error messages.</param> /// <param name="reflector">The underlying reflection helper.</param> - public ReflectionHelper(string modID, string modName, Reflector reflector) + /// <param name="deprecationManager">Manages deprecation warnings.</param> + public ReflectionHelper(string modID, string modName, Reflector reflector, DeprecationManager deprecationManager) : base(modID) { this.ModName = modName; this.Reflector = reflector; + this.DeprecationManager = deprecationManager; + } + + /// <summary>Get an instance field.</summary> + /// <typeparam name="TValue">The field type.</typeparam> + /// <param name="obj">The object which has the field.</param> + /// <param name="name">The field name.</param> + /// <param name="required">Whether to throw an exception if the field is not found.</param> + public IReflectedField<TValue> GetField<TValue>(object obj, string name, bool required = true) + { + return this.AssertAccessAllowed( + this.Reflector.GetField<TValue>(obj, name, required) + ); + } + + /// <summary>Get a static field.</summary> + /// <typeparam name="TValue">The field type.</typeparam> + /// <param name="type">The type which has the field.</param> + /// <param name="name">The field name.</param> + /// <param name="required">Whether to throw an exception if the field is not found.</param> + public IReflectedField<TValue> GetField<TValue>(Type type, string name, bool required = true) + { + return this.AssertAccessAllowed( + this.Reflector.GetField<TValue>(type, name, required) + ); + } + + /// <summary>Get an instance property.</summary> + /// <typeparam name="TValue">The property type.</typeparam> + /// <param name="obj">The object which has the property.</param> + /// <param name="name">The property name.</param> + /// <param name="required">Whether to throw an exception if the property is not found.</param> + public IReflectedProperty<TValue> GetProperty<TValue>(object obj, string name, bool required = true) + { + return this.AssertAccessAllowed( + this.Reflector.GetProperty<TValue>(obj, name, required) + ); + } + + /// <summary>Get a static property.</summary> + /// <typeparam name="TValue">The property type.</typeparam> + /// <param name="type">The type which has the property.</param> + /// <param name="name">The property name.</param> + /// <param name="required">Whether to throw an exception if the property is not found.</param> + public IReflectedProperty<TValue> GetProperty<TValue>(Type type, string name, bool required = true) + { + return this.AssertAccessAllowed( + this.Reflector.GetProperty<TValue>(type, name, required) + ); + } + + /// <summary>Get an instance method.</summary> + /// <param name="obj">The object which has the method.</param> + /// <param name="name">The field name.</param> + /// <param name="required">Whether to throw an exception if the field is not found.</param> + public IReflectedMethod GetMethod(object obj, string name, bool required = true) + { + return this.AssertAccessAllowed( + this.Reflector.GetMethod(obj, name, required) + ); + } + + /// <summary>Get a static method.</summary> + /// <param name="type">The type which has the method.</param> + /// <param name="name">The field name.</param> + /// <param name="required">Whether to throw an exception if the field is not found.</param> + public IReflectedMethod GetMethod(Type type, string name, bool required = true) + { + return this.AssertAccessAllowed( + this.Reflector.GetMethod(type, name, required) + ); } + /**** - ** Fields + ** Obsolete ****/ /// <summary>Get a private instance field.</summary> /// <typeparam name="TValue">The field type.</typeparam> @@ -41,11 +117,11 @@ namespace StardewModdingAPI.Framework.ModHelpers /// <param name="name">The field name.</param> /// <param name="required">Whether to throw an exception if the private field is not found.</param> /// <returns>Returns the field wrapper, or <c>null</c> if the field doesn't exist and <paramref name="required"/> is <c>false</c>.</returns> + [Obsolete] public IPrivateField<TValue> GetPrivateField<TValue>(object obj, string name, bool required = true) { - return this.AssertAccessAllowed( - this.Reflector.GetPrivateField<TValue>(obj, name, required) - ); + this.DeprecationManager.Warn($"{nameof(IReflectionHelper)}.GetPrivate*", "2.3", DeprecationLevel.Notice); + return (IPrivateField<TValue>)this.GetField<TValue>(obj, name, required); } /// <summary>Get a private static field.</summary> @@ -53,26 +129,23 @@ namespace StardewModdingAPI.Framework.ModHelpers /// <param name="type">The type which has the field.</param> /// <param name="name">The field name.</param> /// <param name="required">Whether to throw an exception if the private field is not found.</param> + [Obsolete] public IPrivateField<TValue> GetPrivateField<TValue>(Type type, string name, bool required = true) { - return this.AssertAccessAllowed( - this.Reflector.GetPrivateField<TValue>(type, name, required) - ); + this.DeprecationManager.Warn($"{nameof(IReflectionHelper)}.GetPrivate*", "2.3", DeprecationLevel.Notice); + return (IPrivateField<TValue>)this.GetField<TValue>(type, name, required); } - /**** - ** Properties - ****/ /// <summary>Get a private instance property.</summary> /// <typeparam name="TValue">The property type.</typeparam> /// <param name="obj">The object which has the property.</param> /// <param name="name">The property name.</param> /// <param name="required">Whether to throw an exception if the private property is not found.</param> + [Obsolete] public IPrivateProperty<TValue> GetPrivateProperty<TValue>(object obj, string name, bool required = true) { - return this.AssertAccessAllowed( - this.Reflector.GetPrivateProperty<TValue>(obj, name, required) - ); + this.DeprecationManager.Warn($"{nameof(IReflectionHelper)}.GetPrivate*", "2.3", DeprecationLevel.Notice); + return (IPrivateProperty<TValue>)this.GetProperty<TValue>(obj, name, required); } /// <summary>Get a private static property.</summary> @@ -80,17 +153,13 @@ namespace StardewModdingAPI.Framework.ModHelpers /// <param name="type">The type which has the property.</param> /// <param name="name">The property name.</param> /// <param name="required">Whether to throw an exception if the private property is not found.</param> + [Obsolete] public IPrivateProperty<TValue> GetPrivateProperty<TValue>(Type type, string name, bool required = true) { - return this.AssertAccessAllowed( - this.Reflector.GetPrivateProperty<TValue>(type, name, required) - ); + this.DeprecationManager.Warn($"{nameof(IReflectionHelper)}.GetPrivate*", "2.3", DeprecationLevel.Notice); + return (IPrivateProperty<TValue>)this.GetProperty<TValue>(type, name, required); } - /**** - ** Field values - ** (shorthand since this is the most common case) - ****/ /// <summary>Get the value of a private instance field.</summary> /// <typeparam name="TValue">The field type.</typeparam> /// <param name="obj">The object which has the field.</param> @@ -101,9 +170,11 @@ namespace StardewModdingAPI.Framework.ModHelpers /// This is a shortcut for <see cref="GetPrivateField{TValue}(object,string,bool)"/> followed by <see cref="IPrivateField{TValue}.GetValue"/>. /// When <paramref name="required" /> is false, this will return the default value if reflection fails. If you need to check whether the field exists, use <see cref="GetPrivateField{TValue}(object,string,bool)" /> instead. /// </remarks> + [Obsolete] public TValue GetPrivateValue<TValue>(object obj, string name, bool required = true) { - IPrivateField<TValue> field = this.GetPrivateField<TValue>(obj, name, required); + this.DeprecationManager.Warn($"{nameof(IReflectionHelper)}.GetPrivate*", "2.3", DeprecationLevel.Notice); + IPrivateField<TValue> field = (IPrivateField<TValue>)this.GetField<TValue>(obj, name, required); return field != null ? field.GetValue() : default(TValue); @@ -119,64 +190,36 @@ namespace StardewModdingAPI.Framework.ModHelpers /// This is a shortcut for <see cref="GetPrivateField{TValue}(Type,string,bool)"/> followed by <see cref="IPrivateField{TValue}.GetValue"/>. /// When <paramref name="required" /> is false, this will return the default value if reflection fails. If you need to check whether the field exists, use <see cref="GetPrivateField{TValue}(Type,string,bool)" /> instead. /// </remarks> + [Obsolete] public TValue GetPrivateValue<TValue>(Type type, string name, bool required = true) { - IPrivateField<TValue> field = this.GetPrivateField<TValue>(type, name, required); + this.DeprecationManager.Warn($"{nameof(IReflectionHelper)}.GetPrivate*", "2.3", DeprecationLevel.Notice); + IPrivateField<TValue> field = (IPrivateField<TValue>)this.GetField<TValue>(type, name, required); return field != null ? field.GetValue() : default(TValue); } - /**** - ** Methods - ****/ /// <summary>Get a private instance method.</summary> /// <param name="obj">The object which has the method.</param> /// <param name="name">The field name.</param> /// <param name="required">Whether to throw an exception if the private field is not found.</param> + [Obsolete] public IPrivateMethod GetPrivateMethod(object obj, string name, bool required = true) { - return this.AssertAccessAllowed( - this.Reflector.GetPrivateMethod(obj, name, required) - ); + this.DeprecationManager.Warn($"{nameof(IReflectionHelper)}.GetPrivate*", "2.3", DeprecationLevel.Notice); + return (IPrivateMethod)this.GetMethod(obj, name, required); } /// <summary>Get a private static method.</summary> /// <param name="type">The type which has the method.</param> /// <param name="name">The field name.</param> /// <param name="required">Whether to throw an exception if the private field is not found.</param> + [Obsolete] public IPrivateMethod GetPrivateMethod(Type type, string name, bool required = true) { - return this.AssertAccessAllowed( - this.Reflector.GetPrivateMethod(type, name, required) - ); - } - - /**** - ** Methods by signature - ****/ - /// <summary>Get a private instance method.</summary> - /// <param name="obj">The object which has the method.</param> - /// <param name="name">The field name.</param> - /// <param name="argumentTypes">The argument types of the method signature to find.</param> - /// <param name="required">Whether to throw an exception if the private field is not found.</param> - public IPrivateMethod GetPrivateMethod(object obj, string name, Type[] argumentTypes, bool required = true) - { - return this.AssertAccessAllowed( - this.Reflector.GetPrivateMethod(obj, name, argumentTypes, required) - ); - } - - /// <summary>Get a private static method.</summary> - /// <param name="type">The type which has the method.</param> - /// <param name="name">The field name.</param> - /// <param name="argumentTypes">The argument types of the method signature to find.</param> - /// <param name="required">Whether to throw an exception if the private field is not found.</param> - public IPrivateMethod GetPrivateMethod(Type type, string name, Type[] argumentTypes, bool required = true) - { - return this.AssertAccessAllowed( - this.Reflector.GetPrivateMethod(type, name, argumentTypes, required) - ); + this.DeprecationManager.Warn($"{nameof(IReflectionHelper)}.GetPrivate*", "2.3", DeprecationLevel.Notice); + return (IPrivateMethod)this.GetMethod(type, name, required); } @@ -187,7 +230,7 @@ namespace StardewModdingAPI.Framework.ModHelpers /// <typeparam name="T">The field value type.</typeparam> /// <param name="field">The field being accessed.</param> /// <returns>Returns the same field instance for convenience.</returns> - private IPrivateField<T> AssertAccessAllowed<T>(IPrivateField<T> field) + private IReflectedField<T> AssertAccessAllowed<T>(IReflectedField<T> field) { this.AssertAccessAllowed(field?.FieldInfo); return field; @@ -197,7 +240,7 @@ namespace StardewModdingAPI.Framework.ModHelpers /// <typeparam name="T">The property value type.</typeparam> /// <param name="property">The property being accessed.</param> /// <returns>Returns the same property instance for convenience.</returns> - private IPrivateProperty<T> AssertAccessAllowed<T>(IPrivateProperty<T> property) + private IReflectedProperty<T> AssertAccessAllowed<T>(IReflectedProperty<T> property) { this.AssertAccessAllowed(property?.PropertyInfo); return property; @@ -206,7 +249,7 @@ namespace StardewModdingAPI.Framework.ModHelpers /// <summary>Assert that mods can use the reflection helper to access the given member.</summary> /// <param name="method">The method being accessed.</param> /// <returns>Returns the same method instance for convenience.</returns> - private IPrivateMethod AssertAccessAllowed(IPrivateMethod method) + private IReflectedMethod AssertAccessAllowed(IReflectedMethod method) { this.AssertAccessAllowed(method?.MethodInfo); return method; diff --git a/src/SMAPI/Framework/ModLoading/ModMetadata.cs b/src/SMAPI/Framework/ModLoading/ModMetadata.cs index 5055da75..30fe211b 100644 --- a/src/SMAPI/Framework/ModLoading/ModMetadata.cs +++ b/src/SMAPI/Framework/ModLoading/ModMetadata.cs @@ -29,6 +29,9 @@ namespace StardewModdingAPI.Framework.ModLoading /// <summary>The mod instance (if it was loaded).</summary> public IMod Mod { get; private set; } |
