diff options
Diffstat (limited to 'src')
43 files changed, 1373 insertions, 447 deletions
diff --git a/src/.editorconfig b/src/.editorconfig index 4271803d..a5cdcf97 100644 --- a/src/.editorconfig +++ b/src/.editorconfig @@ -12,13 +12,16 @@ insert_final_newline = true trim_trailing_whitespace = true charset = utf-8 +[*.csproj] +indent_size = 2 +insert_final_newline = false + [*.json] indent_size = 2 ########## ## C# formatting ## documentation: https://docs.microsoft.com/en-us/visualstudio/ide/editorconfig-code-style-settings-reference -## some undocumented settings from: https://github.com/dotnet/roslyn/blob/master/.editorconfig ########## [*.cs] @@ -47,6 +50,7 @@ dotnet_style_explicit_tuple_names = true:suggestion csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion csharp_style_pattern_matching_over_as_with_null_check = true:suggestion csharp_style_conditional_delegate_call = true:suggestion +csharp_prefer_simple_default_expression = true:suggestion # prefer method block bodies csharp_style_expression_bodied_methods = false:suggestion @@ -59,3 +63,6 @@ csharp_style_expression_bodied_accessors = true:suggestion # prefer inline out variables csharp_style_inlined_variable_declaration = true:warning + +# avoid superfluous braces +csharp_prefer_braces = false:suggestion diff --git a/src/GlobalAssemblyInfo.cs b/src/GlobalAssemblyInfo.cs index d9a01635..d496fbd1 100644 --- a/src/GlobalAssemblyInfo.cs +++ b/src/GlobalAssemblyInfo.cs @@ -1,6 +1,6 @@ -using System.Reflection; +using System.Reflection; using System.Runtime.InteropServices; [assembly: ComVisible(false)] -[assembly: AssemblyVersion("1.15.1.0")] -[assembly: AssemblyFileVersion("1.15.1.0")] +[assembly: AssemblyVersion("1.15.2.0")] +[assembly: AssemblyFileVersion("1.15.2.0")] diff --git a/src/StardewModdingAPI.AssemblyRewriters/StardewModdingAPI.AssemblyRewriters.csproj b/src/StardewModdingAPI.AssemblyRewriters/StardewModdingAPI.AssemblyRewriters.csproj index 7a12a8e9..8416bd51 100644 --- a/src/StardewModdingAPI.AssemblyRewriters/StardewModdingAPI.AssemblyRewriters.csproj +++ b/src/StardewModdingAPI.AssemblyRewriters/StardewModdingAPI.AssemblyRewriters.csproj @@ -68,6 +68,6 @@ <ItemGroup> <None Include="packages.config" /> </ItemGroup> - <Import Project="$(SolutionDir)\crossplatform.targets" /> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> + <Import Project="$(SolutionDir)\common.targets" /> </Project>
\ No newline at end of file diff --git a/src/StardewModdingAPI.Installer/InteractiveInstaller.cs b/src/StardewModdingAPI.Installer/InteractiveInstaller.cs index 78d3d10e..01288f33 100644 --- a/src/StardewModdingAPI.Installer/InteractiveInstaller.cs +++ b/src/StardewModdingAPI.Installer/InteractiveInstaller.cs @@ -135,6 +135,33 @@ namespace StardewModdingApi.Installer /// </remarks> public void Run(string[] args) { +#if SMAPI_1_x + bool installArg = false; + bool uninstallArg = false; + string gamePathArg = null; +#else + /**** + ** read command-line arguments + ****/ + // get action from CLI + bool installArg = args.Contains("--install"); + bool uninstallArg = args.Contains("--uninstall"); + if (installArg && uninstallArg) + { + this.PrintError("You can't specify both --install and --uninstall command-line flags."); + Console.ReadLine(); + return; + } + + // get game path from CLI + string gamePathArg = null; + { + int pathIndex = Array.LastIndexOf(args, "--game-path") + 1; + if (pathIndex >= 1 && args.Length >= pathIndex) + gamePathArg = args[pathIndex]; + } +#endif + /**** ** collect details ****/ @@ -142,9 +169,17 @@ namespace StardewModdingApi.Installer Platform platform = this.DetectPlatform(); this.PrintDebug($"Platform: {(platform == Platform.Windows ? "Windows" : "Linux or Mac")}."); + // get game path + DirectoryInfo installDir = this.InteractivelyGetInstallPath(platform, gamePathArg); + if (installDir == null) + { + this.PrintError("Failed finding your game path."); + Console.ReadLine(); + return; + } + // get folders DirectoryInfo packageDir = new DirectoryInfo(Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "internal", platform.ToString())); - DirectoryInfo installDir = this.InteractivelyGetInstallPath(platform); DirectoryInfo modsDir = new DirectoryInfo(Path.Combine(installDir.FullName, "Mods")); var paths = new { @@ -203,13 +238,19 @@ namespace StardewModdingApi.Installer /**** ** ask user what to do ****/ - Console.WriteLine("You can...."); - Console.WriteLine("[1] Install SMAPI."); - Console.WriteLine("[2] Uninstall SMAPI."); - Console.WriteLine(); - ScriptAction action; + + if (installArg) + action = ScriptAction.Install; + else if (uninstallArg) + action = ScriptAction.Uninstall; + else { + Console.WriteLine("You can...."); + Console.WriteLine("[1] Install SMAPI."); + Console.WriteLine("[2] Uninstall SMAPI."); + Console.WriteLine(); + string choice = this.InteractivelyChoose("What do you want to do? Type 1 or 2, then press enter.", "1", "2"); switch (choice) { @@ -222,8 +263,8 @@ namespace StardewModdingApi.Installer default: throw new InvalidOperationException($"Unexpected action key '{choice}'."); } + Console.WriteLine(); } - Console.WriteLine(); /**** ** Always uninstall old files @@ -513,13 +554,31 @@ namespace StardewModdingApi.Installer /// <summary>Interactively locate the game install path to update.</summary> /// <param name="platform">The current platform.</param> - private DirectoryInfo InteractivelyGetInstallPath(Platform platform) + /// <param name="specifiedPath">The path specified as a command-line argument (if any), which should override automatic path detection.</param> + private DirectoryInfo InteractivelyGetInstallPath(Platform platform, string specifiedPath) { // get executable name string executableFilename = platform == Platform.Windows ? "Stardew Valley.exe" : "StardewValley.exe"; + // validate specified path + if (specifiedPath != null) + { + var dir = new DirectoryInfo(specifiedPath); + if (!dir.Exists) + { + this.PrintError($"You specified --game-path \"{specifiedPath}\", but that folder doesn't exist."); + return null; + } + if (!dir.EnumerateFiles(executableFilename).Any()) + { + this.PrintError($"You specified --game-path \"{specifiedPath}\", but that folder doesn't contain the Stardew Valley executable."); + return null; + } + return dir; + } + // get installed paths DirectoryInfo[] defaultPaths = ( diff --git a/src/StardewModdingAPI.Installer/StardewModdingAPI.Installer.csproj b/src/StardewModdingAPI.Installer/StardewModdingAPI.Installer.csproj index 765364dc..58ce519c 100644 --- a/src/StardewModdingAPI.Installer/StardewModdingAPI.Installer.csproj +++ b/src/StardewModdingAPI.Installer/StardewModdingAPI.Installer.csproj @@ -51,6 +51,6 @@ </Content> </ItemGroup> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> - <Import Project="$(SolutionDir)\crossplatform.targets" /> + <Import Project="$(SolutionDir)\common.targets" /> <Import Project="$(SolutionDir)\prepare-install-package.targets" /> </Project>
\ No newline at end of file diff --git a/src/StardewModdingAPI.Tests/Core/ModResolverTests.cs b/src/StardewModdingAPI.Tests/Core/ModResolverTests.cs index eda3a425..fc84ca29 100644 --- a/src/StardewModdingAPI.Tests/Core/ModResolverTests.cs +++ b/src/StardewModdingAPI.Tests/Core/ModResolverTests.cs @@ -141,7 +141,7 @@ namespace StardewModdingAPI.Tests.Core { // arrange Mock<IModMetadata> mock = this.GetMetadata("Mod A", new string[0], allowStatusChange: true); - this.SetupMetadataForValidation(mock, new ModCompatibility { Compatibility = ModCompatibilityType.AssumeBroken }); + this.SetupMetadataForValidation(mock, new ModCompatibility { Compatibility = ModCompatibilityType.AssumeBroken, UpperVersion = new SemanticVersion("1.0"), UpdateUrls = new[] { "http://example.org" }}); // act new ModResolver().ValidateManifests(new[] { mock.Object }, apiVersion: new SemanticVersion("1.0")); diff --git a/src/StardewModdingAPI.Tests/StardewModdingAPI.Tests.csproj b/src/StardewModdingAPI.Tests/StardewModdingAPI.Tests.csproj index 9bfd7567..f3dbcdd4 100644 --- a/src/StardewModdingAPI.Tests/StardewModdingAPI.Tests.csproj +++ b/src/StardewModdingAPI.Tests/StardewModdingAPI.Tests.csproj @@ -30,17 +30,17 @@ <WarningLevel>4</WarningLevel> </PropertyGroup> <ItemGroup> - <Reference Include="Castle.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=407dd0808d44fbdc, processorArchitecture=MSIL"> - <HintPath>..\packages\Castle.Core.4.0.0\lib\net45\Castle.Core.dll</HintPath> + <Reference Include="Castle.Core, Version=4.1.1.0, Culture=neutral, PublicKeyToken=407dd0808d44fbdc, processorArchitecture=MSIL"> + <HintPath>..\packages\Castle.Core.4.1.1\lib\net45\Castle.Core.dll</HintPath> </Reference> - <Reference Include="Moq, Version=4.7.10.0, Culture=neutral, PublicKeyToken=69f491c39445e920, processorArchitecture=MSIL"> - <HintPath>..\packages\Moq.4.7.10\lib\net45\Moq.dll</HintPath> + <Reference Include="Moq, Version=4.7.99.0, Culture=neutral, PublicKeyToken=69f491c39445e920, processorArchitecture=MSIL"> + <HintPath>..\packages\Moq.4.7.99\lib\net45\Moq.dll</HintPath> </Reference> <Reference Include="Newtonsoft.Json, Version=8.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL"> <HintPath>..\packages\Newtonsoft.Json.8.0.3\lib\net45\Newtonsoft.Json.dll</HintPath> </Reference> - <Reference Include="nunit.framework, Version=3.6.1.0, Culture=neutral, PublicKeyToken=2638cd05610744eb, processorArchitecture=MSIL"> - <HintPath>..\packages\NUnit.3.6.1\lib\net45\nunit.framework.dll</HintPath> + <Reference Include="nunit.framework, Version=3.7.1.0, Culture=neutral, PublicKeyToken=2638cd05610744eb, processorArchitecture=MSIL"> + <HintPath>..\packages\NUnit.3.7.1\lib\net45\nunit.framework.dll</HintPath> </Reference> <Reference Include="System" /> </ItemGroup> @@ -64,6 +64,6 @@ <Name>StardewModdingAPI</Name> </ProjectReference> </ItemGroup> - <Import Project="$(SolutionDir)\crossplatform.targets" /> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> + <Import Project="$(SolutionDir)\common.targets" /> </Project>
\ No newline at end of file diff --git a/src/StardewModdingAPI.Tests/Utilities/SemanticVersionTests.cs b/src/StardewModdingAPI.Tests/Utilities/SemanticVersionTests.cs index 95d0d74f..03cd26c9 100644 --- a/src/StardewModdingAPI.Tests/Utilities/SemanticVersionTests.cs +++ b/src/StardewModdingAPI.Tests/Utilities/SemanticVersionTests.cs @@ -1,6 +1,8 @@ using System; using System.Diagnostics.CodeAnalysis; +using Newtonsoft.Json; using NUnit.Framework; +using StardewModdingAPI.Framework; namespace StardewModdingAPI.Tests.Utilities { @@ -206,6 +208,51 @@ namespace StardewModdingAPI.Tests.Utilities return version.IsBetween(lower, upper); } + /**** + ** Serialisable + ****/ + [Test(Description = "Assert that SemanticVersion can be round-tripped through JSON with no special configuration.")] + [TestCase("1.0")] + public void Serialisable(string versionStr) + { + // act + string json = JsonConvert.SerializeObject(new SemanticVersion(versionStr)); + SemanticVersion after = JsonConvert.DeserializeObject<SemanticVersion>(json); + + // assert + Assert.IsNotNull(after, "The semantic version after deserialisation is unexpectedly null."); + Assert.AreEqual(versionStr, after.ToString(), "The semantic version after deserialisation doesn't match the input version."); + } + + /**** + ** GameVersion + ****/ + [Test(Description = "Assert that the GameVersion subclass correctly parses legacy game versions.")] + [TestCase("1.0")] + [TestCase("1.01")] + [TestCase("1.02")] + [TestCase("1.03")] + [TestCase("1.04")] + [TestCase("1.05")] + [TestCase("1.051")] + [TestCase("1.051b")] + [TestCase("1.06")] + [TestCase("1.07")] + [TestCase("1.07a")] + [TestCase("1.1")] + [TestCase("1.11")] + [TestCase("1.2")] + [TestCase("1.2.15")] + public void GameVersion(string versionStr) + { + // act + GameVersion version = new GameVersion(versionStr); + + // assert + Assert.AreEqual(versionStr, version.ToString(), "The game version did not round-trip to the same value."); + Assert.IsTrue(version.IsOlderThan(new SemanticVersion("1.2.30")), "The game version should be considered older than the later semantic versions."); + } + /********* ** Private methods diff --git a/src/StardewModdingAPI.Tests/packages.config b/src/StardewModdingAPI.Tests/packages.config index ba954308..6f04e625 100644 --- a/src/StardewModdingAPI.Tests/packages.config +++ b/src/StardewModdingAPI.Tests/packages.config @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="utf-8"?> <packages> - <package id="Castle.Core" version="4.0.0" targetFramework="net45" /> - <package id="Moq" version="4.7.10" targetFramework="net45" /> + <package id="Castle.Core" version="4.1.1" targetFramework="net45" /> + <package id="Moq" version="4.7.99" targetFramework="net45" /> <package id="Newtonsoft.Json" version="8.0.3" targetFramework="net45" /> - <package id="NUnit" version="3.6.1" targetFramework="net452" /> + <package id="NUnit" version="3.7.1" targetFramework="net45" /> </packages>
\ No newline at end of file diff --git a/src/StardewModdingAPI.sln b/src/StardewModdingAPI.sln index 4d27e51b..9c3f18f8 100644 --- a/src/StardewModdingAPI.sln +++ b/src/StardewModdingAPI.sln @@ -1,7 +1,7 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 15 -VisualStudioVersion = 15.0.26430.14 +VisualStudioVersion = 15.0.26430.16 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TrainerMod", "TrainerMod\TrainerMod.csproj", "{28480467-1A48-46A7-99F8-236D95225359}" EndProject @@ -12,8 +12,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "metadata", "metadata", "{86 .editorconfig = .editorconfig ..\.gitattributes = ..\.gitattributes ..\.gitignore = ..\.gitignore + common.targets = common.targets ..\CONTRIBUTING.md = ..\CONTRIBUTING.md - crossplatform.targets = crossplatform.targets GlobalAssemblyInfo.cs = GlobalAssemblyInfo.cs ..\LICENSE = ..\LICENSE prepare-install-package.targets = prepare-install-package.targets diff --git a/src/StardewModdingAPI/Constants.cs b/src/StardewModdingAPI/Constants.cs index 3bd31c2d..7a790f1a 100644 --- a/src/StardewModdingAPI/Constants.cs +++ b/src/StardewModdingAPI/Constants.cs @@ -9,6 +9,7 @@ using StardewModdingAPI.AssemblyRewriters.Finders; using StardewModdingAPI.AssemblyRewriters.Rewriters; using StardewModdingAPI.AssemblyRewriters.Rewriters.Wrappers; using StardewModdingAPI.Events; +using StardewModdingAPI.Framework; using StardewValley; namespace StardewModdingAPI @@ -35,7 +36,7 @@ namespace StardewModdingAPI /// <summary>SMAPI's current semantic version.</summary> public static ISemanticVersion ApiVersion { get; } = #if SMAPI_1_x - new SemanticVersion(1, 15, 1); // alpha-{DateTime.UtcNow:yyyyMMddHHmm} + new SemanticVersion(1, 15, 2); #else new SemanticVersion(2, 0, 0, $"alpha-{DateTime.UtcNow:yyyyMMddHHmm}"); #endif @@ -86,7 +87,7 @@ namespace StardewModdingAPI internal static string ModPath { get; } = Path.Combine(Constants.ExecutionPath, "Mods"); /// <summary>The game's current semantic version.</summary> - internal static ISemanticVersion GameVersion { get; } = Constants.GetGameVersion(); + internal static ISemanticVersion GameVersion { get; } = new GameVersion(Constants.GetGameVersion()); /// <summary>The target game platform.</summary> internal static Platform TargetPlatform { get; } = @@ -98,7 +99,7 @@ namespace StardewModdingAPI /********* - ** Protected methods + ** Internal methods *********/ /// <summary>Get metadata for mapping assemblies to the current platform.</summary> /// <param name="targetPlatform">The target game platform.</param> @@ -179,15 +180,6 @@ namespace StardewModdingAPI new TypeFinder("StardewModdingAPI.Command"), new TypeFinder("StardewModdingAPI.Config"), new TypeFinder("StardewModdingAPI.Log"), - new TypeFinder("StardewModdingAPI.Events.EventArgsCommand"), - new TypeFinder("StardewModdingAPI.Events.EventArgsFarmerChanged"), - new TypeFinder("StardewModdingAPI.Events.EventArgsLoadedGameChanged"), - new TypeFinder("StardewModdingAPI.Events.EventArgsNewDay"), - new TypeFinder("StardewModdingAPI.Events.EventArgsStringChanged"), - new PropertyFinder("StardewModdingAPI.Mod", "PathOnDisk"), - new PropertyFinder("StardewModdingAPI.Mod", "BaseConfigPath"), - new PropertyFinder("StardewModdingAPI.Mod", "PerSaveConfigFolder"), - new PropertyFinder("StardewModdingAPI.Mod", "PerSaveConfigPath"), new EventFinder("StardewModdingAPI.Events.GameEvents", "Initialize"), new EventFinder("StardewModdingAPI.Events.GameEvents", "LoadContent"), new EventFinder("StardewModdingAPI.Events.GameEvents", "GameLoaded"), @@ -198,6 +190,15 @@ namespace StardewModdingAPI new EventFinder("StardewModdingAPI.Events.TimeEvents", "YearOfGameChanged"), new EventFinder("StardewModdingAPI.Events.TimeEvents", "SeasonOfYearChanged"), new EventFinder("StardewModdingAPI.Events.TimeEvents", "OnNewDay"), + new TypeFinder("StardewModdingAPI.Events.EventArgsCommand"), + new TypeFinder("StardewModdingAPI.Events.EventArgsFarmerChanged"), + new TypeFinder("StardewModdingAPI.Events.EventArgsLoadedGameChanged"), + new TypeFinder("StardewModdingAPI.Events.EventArgsNewDay"), + new TypeFinder("StardewModdingAPI.Events.EventArgsStringChanged"), + new PropertyFinder("StardewModdingAPI.Mod", "PathOnDisk"), + new PropertyFinder("StardewModdingAPI.Mod", "BaseConfigPath"), + new PropertyFinder("StardewModdingAPI.Mod", "PerSaveConfigFolder"), + new PropertyFinder("StardewModdingAPI.Mod", "PerSaveConfigPath"), #endif /**** @@ -219,19 +220,10 @@ namespace StardewModdingAPI }; } - /// <summary>Get game current version as it should be displayed to players.</summary> - /// <param name="version">The semantic game version.</param> - internal static ISemanticVersion GetGameDisplayVersion(ISemanticVersion version) - { - switch (version.ToString()) - { - case "1.1.1": - return new SemanticVersion(1, 11, 0); // The 1.1 patch was released as 1.11 - default: - return version; - } - } + /********* + ** Private methods + *********/ /// <summary>Get the name of a save directory for the current player.</summary> private static string GetSaveFolderName() { @@ -239,20 +231,14 @@ namespace StardewModdingAPI return $"{prefix}_{Game1.uniqueIDForThisGame}"; } - /// <summary>Get the game's current semantic version.</summary> - private static ISemanticVersion GetGameVersion() + /// <summary>Get the game's current version string.</summary> + private static string GetGameVersion() { - // get raw version // we need reflection because it's a constant, so SMAPI's references to it are inlined at compile-time FieldInfo field = typeof(Game1).GetField(nameof(Game1.version), BindingFlags.Public | BindingFlags.Static); if (field == null) throw new InvalidOperationException($"The {nameof(Game1)}.{nameof(Game1.version)} field could not be found."); - string version = (string)field.GetValue(null); - - // get semantic version - if (version == "1.11") - version = "1.1.1"; // The 1.1 patch was released as 1.11, which means it's out of order for semantic version checks - return new SemanticVersion(version); + return (string)field.GetValue(null); } } } diff --git a/src/StardewModdingAPI/Context.cs b/src/StardewModdingAPI/Context.cs index 6c5ae40e..119e14c8 100644 --- a/src/StardewModdingAPI/Context.cs +++ b/src/StardewModdingAPI/Context.cs @@ -16,8 +16,11 @@ namespace StardewModdingAPI /// <summary>Whether the player has loaded a save and the world has finished initialising.</summary> public static bool IsWorldReady { get; internal set; } - /// <summary>Whether the player is free to move around (e.g. save is loaded, no menu is displayed, no cutscene is in progress, etc).</summary> - public static bool IsPlayerFree => Context.IsWorldReady && Game1.activeClickableMenu == null && Game1.player.CanMove && !Game1.dialogueUp && !Game1.eventUp; + /// <summary>Whether <see cref="IsWorldReady"/> is true and the player is free to act in the world (no menu is displayed, no cutscene is in progress, etc).</summary> + public static bool IsPlayerFree => Context.IsWorldReady && Game1.activeClickableMenu == null && !Game1.dialogueUp && !Game1.eventUp; + + /// <summary>Whether <see cref="IsPlayerFree"/> is true and the player is free to move (e.g. not using a tool).</summary> + public static bool CanPlayerMove => Context.IsPlayerFree && Game1.player.CanMove; /// <summary>Whether the game is currently running the draw loop. This isn't relevant to most mods, since you should use <see cref="GraphicsEvents.OnPostRenderEvent"/> to draw to the screen.</summary> public static bool IsInDrawLoop { get; internal set; } diff --git a/src/StardewModdingAPI/Events/GraphicsEvents.cs b/src/StardewModdingAPI/Events/GraphicsEvents.cs index 25b976f1..fff51bed 100644 --- a/src/StardewModdingAPI/Events/GraphicsEvents.cs +++ b/src/StardewModdingAPI/Events/GraphicsEvents.cs @@ -51,11 +51,9 @@ namespace StardewModdingAPI.Events ****/ /// <summary>Raise a <see cref="Resize"/> event.</summary> /// <param name="monitor">Encapsulates monitoring and logging.</param> - /// <param name="sender">The object which raised the event.</param> - /// <param name="e">The event arguments.</param> - internal static void InvokeResize(IMonitor monitor, object sender, EventArgs e) + internal static void InvokeResize(IMonitor monitor) { - monitor.SafelyRaisePlainEvent($"{nameof(GraphicsEvents)}.{nameof(GraphicsEvents.Resize)}", GraphicsEvents.Resize?.GetInvocationList(), sender, e); + monitor.SafelyRaisePlainEvent($"{nameof(GraphicsEvents)}.{nameof(GraphicsEvents.Resize)}", GraphicsEvents.Resize?.GetInvocationList()); } /**** diff --git a/src/StardewModdingAPI/Framework/Exceptions/SAssemblyLoadFailedException.cs b/src/StardewModdingAPI/Framework/Exceptions/SAssemblyLoadFailedException.cs new file mode 100644 index 00000000..ec9279f1 --- /dev/null +++ b/src/StardewModdingAPI/Framework/Exceptions/SAssemblyLoadFailedException.cs @@ -0,0 +1,16 @@ +using System; + +namespace StardewModdingAPI.Framework.Exceptions +{ + /// <summary>An exception thrown when an assembly can't be loaded by SMAPI, with all the relevant details in the message.</summary> + internal class SAssemblyLoadFailedException : Exception + { + /********* + ** Public methods + *********/ + /// <summary>Construct an instance.</summary> + /// <param name="message">The error message.</param> + public SAssemblyLoadFailedException(string message) + : base(message) { } + } +} diff --git a/src/StardewModdingAPI/Framework/GameVersion.cs b/src/StardewModdingAPI/Framework/GameVersion.cs new file mode 100644 index 00000000 |
