diff options
Diffstat (limited to 'src')
66 files changed, 1727 insertions, 530 deletions
diff --git a/src/SMAPI.Internal/ExceptionHelper.cs b/src/SMAPI.Internal/ExceptionHelper.cs index 05b96c2e..03d48911 100644 --- a/src/SMAPI.Internal/ExceptionHelper.cs +++ b/src/SMAPI.Internal/ExceptionHelper.cs @@ -25,7 +25,7 @@ namespace StardewModdingAPI.Internal case ReflectionTypeLoadException ex: string summary = ex.ToString(); - foreach (Exception childEx in ex.LoaderExceptions ?? new Exception[0]) + foreach (Exception childEx in ex.LoaderExceptions ?? Array.Empty<Exception>()) summary += $"\n\n{childEx?.GetLogSummary()}"; message = summary; break; diff --git a/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/Other/ShowGameFilesCommand.cs b/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/Other/ShowGameFilesCommand.cs index 71093184..b97cb3e6 100644 --- a/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/Other/ShowGameFilesCommand.cs +++ b/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/Other/ShowGameFilesCommand.cs @@ -1,4 +1,4 @@ -using System.Diagnostics; +using System.Diagnostics; namespace StardewModdingAPI.Mods.ConsoleCommands.Framework.Commands.Other { @@ -18,8 +18,8 @@ namespace StardewModdingAPI.Mods.ConsoleCommands.Framework.Commands.Other /// <param name="args">The command arguments.</param> public override void Handle(IMonitor monitor, string command, ArgumentParser args) { - Process.Start(Constants.ExecutionPath); - monitor.Log($"OK, opening {Constants.ExecutionPath}.", LogLevel.Info); + Process.Start(Constants.GamePath); + monitor.Log($"OK, opening {Constants.GamePath}.", LogLevel.Info); } } } diff --git a/src/SMAPI.Mods.ErrorHandler/ModEntry.cs b/src/SMAPI.Mods.ErrorHandler/ModEntry.cs index 7286e316..2d6242cf 100644 --- a/src/SMAPI.Mods.ErrorHandler/ModEntry.cs +++ b/src/SMAPI.Mods.ErrorHandler/ModEntry.cs @@ -80,7 +80,7 @@ namespace StardewModdingAPI.Mods.ErrorHandler MethodInfo getMonitorForGame = coreType.GetMethod("GetMonitorForGame") ?? throw new InvalidOperationException("Can't access the SMAPI's 'GetMonitorForGame' method. This mod may not work correctly."); - return (IMonitor)getMonitorForGame.Invoke(core, new object[0]) ?? this.Monitor; + return (IMonitor)getMonitorForGame.Invoke(core, Array.Empty<object>()) ?? this.Monitor; } } } diff --git a/src/SMAPI.Mods.SaveBackup/ModEntry.cs b/src/SMAPI.Mods.SaveBackup/ModEntry.cs index d6414e9c..b89bb9c3 100644 --- a/src/SMAPI.Mods.SaveBackup/ModEntry.cs +++ b/src/SMAPI.Mods.SaveBackup/ModEntry.cs @@ -19,7 +19,7 @@ namespace StardewModdingAPI.Mods.SaveBackup private readonly int BackupsToKeep = 10; /// <summary>The absolute path to the folder in which to store save backups.</summary> - private readonly string BackupFolder = Path.Combine(Constants.ExecutionPath, "save-backups"); + private readonly string BackupFolder = Path.Combine(Constants.GamePath, "save-backups"); /// <summary>A unique label for the save backup to create.</summary> private readonly string BackupLabel = $"{DateTime.UtcNow:yyyy-MM-dd} - SMAPI {Constants.ApiVersion} with Stardew Valley {Game1.version}"; diff --git a/src/SMAPI.Tests.ModApiConsumer/ApiConsumer.cs b/src/SMAPI.Tests.ModApiConsumer/ApiConsumer.cs new file mode 100644 index 00000000..2c7f9952 --- /dev/null +++ b/src/SMAPI.Tests.ModApiConsumer/ApiConsumer.cs @@ -0,0 +1,46 @@ +using System; +using SMAPI.Tests.ModApiConsumer.Interfaces; + +namespace SMAPI.Tests.ModApiConsumer +{ + /// <summary>A simulated API consumer.</summary> + public class ApiConsumer + { + /********* + ** Public methods + *********/ + /// <summary>Call the event field on the given API.</summary> + /// <param name="api">The API to call.</param> + /// <param name="getValues">Get the number of times the event was called and the last value received.</param> + public void UseEventField(ISimpleApi api, out Func<(int timesCalled, int actualValue)> getValues) + { + // act + int calls = 0; + int lastValue = -1; + api.OnEventRaised += (sender, value) => + { + calls++; + lastValue = value; + }; + + getValues = () => (timesCalled: calls, actualValue: lastValue); + } + + /// <summary>Call the event property on the given API.</summary> + /// <param name="api">The API to call.</param> + /// <param name="getValues">Get the number of times the event was called and the last value received.</param> + public void UseEventProperty(ISimpleApi api, out Func<(int timesCalled, int actualValue)> getValues) + { + // act + int calls = 0; + int lastValue = -1; + api.OnEventRaisedProperty += (sender, value) => + { + calls++; + lastValue = value; + }; + + getValues = () => (timesCalled: calls, actualValue: lastValue); + } + } +} diff --git a/src/SMAPI.Tests.ModApiConsumer/Interfaces/ISimpleApi.cs b/src/SMAPI.Tests.ModApiConsumer/Interfaces/ISimpleApi.cs new file mode 100644 index 00000000..7f94e137 --- /dev/null +++ b/src/SMAPI.Tests.ModApiConsumer/Interfaces/ISimpleApi.cs @@ -0,0 +1,79 @@ +using System; +using System.Collections.Generic; +using System.Reflection; + +namespace SMAPI.Tests.ModApiConsumer.Interfaces +{ + /// <summary>A mod-provided API which provides basic events, properties, and methods.</summary> + public interface ISimpleApi + { + /********* + ** Test interface + *********/ + /**** + ** Events + ****/ + /// <summary>A simple event field.</summary> + event EventHandler<int> OnEventRaised; + + /// <summary>A simple event property with custom add/remove logic.</summary> + event EventHandler<int> OnEventRaisedProperty; + + + /**** + ** Properties + ****/ + /// <summary>A simple numeric property.</summary> + int NumberProperty { get; set; } + + /// <summary>A simple object property.</summary> + object ObjectProperty { get; set; } + + /// <summary>A simple list property.</summary> + List<string> ListProperty { get; set; } + + /// <summary>A simple list property with an interface.</summary> + IList<string> ListPropertyWithInterface { get; set; } + + /// <summary>A property with nested generics.</summary> + IDictionary<string, IList<string>> GenericsProperty { get; set; } + + /// <summary>A property using an enum available to both mods.</summary> + BindingFlags EnumProperty { get; set; } + + /// <summary>A read-only property.</summary> + int GetterProperty { get; } + + + /**** + ** Methods + ****/ + /// <summary>A simple method with no return value.</summary> + void GetNothing(); + + /// <summary>A simple method which returns a number.</summary> + int GetInt(int value); + + /// <summary>A simple method which returns an object.</summary> + object GetObject(object value); + + /// <summary>A simple method which returns a list.</summary> + List<string> GetList(string value); + + /// <summary>A simple method which returns a list with an interface.</summary> + IList<string> GetListWithInterface(string value); + + /// <summary>A simple method which returns nested generics.</summary> + IDictionary<string, IList<string>> GetGenerics(string key, string value); + + /// <summary>A simple method which returns a lambda.</summary> + Func<string, string> GetLambda(Func<string, string> value); + + + /**** + ** Inherited members + ****/ + /// <summary>A property inherited from a base class.</summary> + public string InheritedProperty { get; set; } + } +} diff --git a/src/SMAPI.Tests.ModApiConsumer/README.md b/src/SMAPI.Tests.ModApiConsumer/README.md new file mode 100644 index 00000000..ed0c6e3f --- /dev/null +++ b/src/SMAPI.Tests.ModApiConsumer/README.md @@ -0,0 +1,3 @@ +This project contains a simulated [mod-provided API] consumer used in the API proxying unit tests. + +[mod-provided API]: https://stardewvalleywiki.com/Modding:Modder_Guide/APIs/Integrations diff --git a/src/SMAPI.Tests.ModApiConsumer/SMAPI.Tests.ModApiConsumer.csproj b/src/SMAPI.Tests.ModApiConsumer/SMAPI.Tests.ModApiConsumer.csproj new file mode 100644 index 00000000..7fef4ebd --- /dev/null +++ b/src/SMAPI.Tests.ModApiConsumer/SMAPI.Tests.ModApiConsumer.csproj @@ -0,0 +1,11 @@ +<Project Sdk="Microsoft.NET.Sdk"> + <PropertyGroup> + <TargetFramework>net5.0</TargetFramework> + </PropertyGroup> + + <Import Project="..\..\build\common.targets" /> + + <ItemGroup> + <ProjectReference Include="..\SMAPI\SMAPI.csproj" /> + </ItemGroup> +</Project> diff --git a/src/SMAPI.Tests.ModApiProvider/Framework/BaseApi.cs b/src/SMAPI.Tests.ModApiProvider/Framework/BaseApi.cs new file mode 100644 index 00000000..8092e3e7 --- /dev/null +++ b/src/SMAPI.Tests.ModApiProvider/Framework/BaseApi.cs @@ -0,0 +1,12 @@ +namespace SMAPI.Tests.ModApiProvider.Framework +{ + /// <summary>The base class for <see cref="SimpleApi"/>.</summary> + public class BaseApi + { + /********* + ** Test interface + *********/ + /// <summary>A property inherited from a base class.</summary> + public string InheritedProperty { get; set; } + } +} diff --git a/src/SMAPI.Tests.ModApiProvider/Framework/SimpleApi.cs b/src/SMAPI.Tests.ModApiProvider/Framework/SimpleApi.cs new file mode 100644 index 00000000..1100af36 --- /dev/null +++ b/src/SMAPI.Tests.ModApiProvider/Framework/SimpleApi.cs @@ -0,0 +1,108 @@ +using System; +using System.Collections.Generic; +using System.Reflection; + +namespace SMAPI.Tests.ModApiProvider.Framework +{ + /// <summary>A mod-provided API which provides basic events, properties, and methods.</summary> + public class SimpleApi : BaseApi + { + /********* + ** Test interface + *********/ + /**** + ** Events + ****/ + /// <summary>A simple event field.</summary> + public event EventHandler<int> OnEventRaised; + + /// <summary>A simple event property with custom add/remove logic.</summary> + public event EventHandler<int> OnEventRaisedProperty + { + add => this.OnEventRaised += value; + remove => this.OnEventRaised -= value; + } + + + /**** + ** Properties + ****/ + /// <summary>A simple numeric property.</summary> + public int NumberProperty { get; set; } + + /// <summary>A simple object property.</summary> + public object ObjectProperty { get; set; } + + /// <summary>A simple list property.</summary> + public List<string> ListProperty { get; set; } + + /// <summary>A simple list property with an interface.</summary> + public IList<string> ListPropertyWithInterface { get; set; } + + /// <summary>A property with nested generics.</summary> + public IDictionary<string, IList<string>> GenericsProperty { get; set; } + + /// <summary>A property using an enum available to both mods.</summary> + public BindingFlags EnumProperty { get; set; } + + /// <summary>A read-only property.</summary> + public int GetterProperty => 42; + + + /**** + ** Methods + ****/ + /// <summary>A simple method with no return value.</summary> + public void GetNothing() { } + + /// <summary>A simple method which returns a number.</summary> + public int GetInt(int value) + { + return value; + } + + /// <summary>A simple method which returns an object.</summary> + public object GetObject(object value) + { + return value; + } + + /// <summary>A simple method which returns a list.</summary> + public List<string> GetList(string value) + { + return new() { value }; + } + + /// <summary>A simple method which returns a list with an interface.</summary> + public IList<string> GetListWithInterface(string value) + { + return new List<string> { value }; + } + + /// <summary>A simple method which returns nested generics.</summary> + public IDictionary<string, IList<string>> GetGenerics(string key, string value) + { + return new Dictionary<string, IList<string>> + { + [key] = new List<string> { value } + }; + } + + /// <summary>A simple method which returns a lambda.</summary> + public Func<string, string> GetLambda(Func<string, string> value) + { + return value; + } + + + /********* + ** Helper methods + *********/ + /// <summary>Raise the <see cref="OnEventRaised"/> event.</summary> + /// <param name="value">The value to pass to the event.</param> + public void RaiseEventField(int value) + { + this.OnEventRaised?.Invoke(null, value); + } + } +} diff --git a/src/SMAPI.Tests.ModApiProvider/ProviderMod.cs b/src/SMAPI.Tests.ModApiProvider/ProviderMod.cs new file mode 100644 index 00000000..c36e1c6d --- /dev/null +++ b/src/SMAPI.Tests.ModApiProvider/ProviderMod.cs @@ -0,0 +1,38 @@ +using System.Collections.Generic; +using System.Reflection; +using SMAPI.Tests.ModApiProvider.Framework; + +namespace SMAPI.Tests.ModApiProvider +{ + /// <summary>A simulated mod instance.</summary> + public class ProviderMod + { + /// <summary>The underlying API instance.</summary> + private readonly SimpleApi Api = new(); + + /// <summary>Get the mod API instance.</summary> + public object GetModApi() + { + return this.Api; + } + + /// <summary>Raise the <see cref="SimpleApi.OnEventRaised"/> event.</summary> + /// <param name="value">The value to send as an event argument.</param> + public void RaiseEvent(int value) + { + this.Api.RaiseEventField(value); + } + + /// <summary>Set the values for the API property.</summary> + public void SetPropertyValues(int number, object obj, string listValue, string listWithInterfaceValue, string dictionaryKey, string dictionaryListValue, BindingFlags enumValue, string inheritedValue) + { + this.Api.NumberProperty = number; + this.Api.ObjectProperty = obj; + this.Api.ListProperty = new List<string> { listValue }; + this.Api.ListPropertyWithInterface = new List<string> { listWithInterfaceValue }; + this.Api.GenericsProperty = new Dictionary<string, IList<string>> { [dictionaryKey] = new List<string> { dictionaryListValue } }; + this.Api.EnumProperty = enumValue; + this.Api.InheritedProperty = inheritedValue; + } + } +} diff --git a/src/SMAPI.Tests.ModApiProvider/README.md b/src/SMAPI.Tests.ModApiProvider/README.md new file mode 100644 index 00000000..c79838e0 --- /dev/null +++ b/src/SMAPI.Tests.ModApiProvider/README.md @@ -0,0 +1,3 @@ +This project contains simulated [mod-provided APIs] used in the API proxying unit tests. + +[mod-pro |
