diff options
23 files changed, 416 insertions, 493 deletions
@@ -1,4 +1,4 @@ - + **SMAPI** is an [open-source](LICENSE) modding API for [Stardew Valley](http://stardewvalley.net/). It takes care of loading mods into the game context, and exposes events they can use to interact @@ -70,46 +70,47 @@ folder containing `src`). 2. In Linux or Mac: 1. Rebuild the solution in _Release_ mode. - 2. Copy `bin/Packaged/Mono` into the `SMAPI <version>` folder. + 2. Copy `bin/internal/Packaged/Mono` into the `SMAPI <version>` folder. 3. If you did everything right so far, you should have a folder like this: ``` SMAPI-1.x/ - Mono/ - Mods/* - Mono.Cecil.dll - Mono.Cecil.Rocks.dll - Newtonsoft.Json.dll - StardewModdingAPI - StardewModdingAPI.config.json - StardewModdingAPI.data.json - StardewModdingAPI.exe - StardewModdingAPI.exe.mdb - StardewModdingAPI.AssemblyRewriters.dll - System.Numerics.dll - System.Runtime.Caching.dll - steam_appid.txt - Windows/ - Mods/* - Mono.Cecil.dll - Mono.Cecil.Rocks.dll - Newtonsoft.Json.dll - StardewModdingAPI.config.json - StardewModdingAPI.data.json - StardewModdingAPI.exe - StardewModdingAPI.pdb - StardewModdingAPI.xml - StardewModdingAPI.AssemblyRewriters.dll - steam_appid.txt install.exe readme.txt + internal/ + Mono/ + Mods/* + Mono.Cecil.dll + Mono.Cecil.Rocks.dll + Newtonsoft.Json.dll + StardewModdingAPI + StardewModdingAPI.AssemblyRewriters.dll + StardewModdingAPI.config.json + StardewModdingAPI.data.json + StardewModdingAPI.exe + StardewModdingAPI.exe.mdb + steam_appid.txt + System.Numerics.dll + System.Runtime.Caching.dll + Windows/ + Mods/* + Mono.Cecil.dll + Mono.Cecil.Rocks.dll + Newtonsoft.Json.dll + StardewModdingAPI.AssemblyRewriters.dll + StardewModdingAPI.config.json + StardewModdingAPI.data.json + StardewModdingAPI.exe + StardewModdingAPI.pdb + StardewModdingAPI.xml + steam_appid.txt ``` - 4. Open a terminal in the `SMAPI <version>` folder and run `chmod 755 Mono/StardewModdingAPI`. + 4. Open a terminal in the `SMAPI <version>` folder and run `chmod 755 internal/Mono/StardewModdingAPI`. 5. Copy & paste the `SMAPI <version>` folder as `SMAPI <version> for developers`. 6. In the `SMAPI <version>` folder, delete the following files: - * `Mono/StardewModdingAPI.config.json` - * `Windows/StardewModdingAPI.config.json` - * `Windows/StardewModdingAPI.xml` + * `internal/Mono/StardewModdingAPI.config.json` + * `internal/Windows/StardewModdingAPI.config.json` + * `internal/Windows/StardewModdingAPI.xml` 7. Compress the two folders into `SMAPI <version>.zip` and `SMAPI <version> for developers.zip`. ## Advanced usage diff --git a/release-notes.md b/release-notes.md index 4e7b3a30..1ff868a4 100644 --- a/release-notes.md +++ b/release-notes.md @@ -1,5 +1,30 @@ # Release notes +## 1.8 +See [log](https://github.com/Pathoschild/SMAPI/compare/1.7...1.8). + +For players: +* Mods no longer generate `.cache` subfolders. +* Fixed multiple issues where mods failed during assembly loading. +* Tweaked install package to reduce confusion. + +For mod developers: +* The `SemanticVersion` constructor now accepts a string version. +* Increased deprecation level for `Extensions` to _pending removal_. +* **Warning:** `Assembly.GetExecutingAssembly().Location` will no longer reliably + return a valid path, because mod assemblies are loaded from memory when rewritten for + compatibility. This approach has been discouraged since SMAPI 1.3; use `helper.DirectoryPath` + instead. + +For SMAPI developers: +* Rewrote assembly loading from the ground up. The new implementation... + * is much simpler; + * eliminates the `.cache` folders by loading rewritten assemblies from memory; + * ensures DLLs are loaded in leaf-to-root order (i.e. dependencies first); + * improves dependent assembly resolution; + * no longer loads DLLs if they're not referenced; + * reduces log verbosity. + ## 1.7 See [log](https://github.com/Pathoschild/SMAPI/compare/1.6...1.7). diff --git a/src/GlobalAssemblyInfo.cs b/src/GlobalAssemblyInfo.cs index 29e5dae7..b591153a 100644 --- a/src/GlobalAssemblyInfo.cs +++ b/src/GlobalAssemblyInfo.cs @@ -2,5 +2,5 @@ using System.Runtime.InteropServices; [assembly: ComVisible(false)] -[assembly: AssemblyVersion("1.7.0.0")] -[assembly: AssemblyFileVersion("1.7.0.0")]
\ No newline at end of file +[assembly: AssemblyVersion("1.8.0.0")] +[assembly: AssemblyFileVersion("1.8.0.0")]
\ No newline at end of file diff --git a/src/StardewModdingAPI.AssemblyRewriters/PlatformAssemblyMap.cs b/src/StardewModdingAPI.AssemblyRewriters/PlatformAssemblyMap.cs index f2826080..fce2b187 100644 --- a/src/StardewModdingAPI.AssemblyRewriters/PlatformAssemblyMap.cs +++ b/src/StardewModdingAPI.AssemblyRewriters/PlatformAssemblyMap.cs @@ -20,8 +20,6 @@ namespace StardewModdingAPI.AssemblyRewriters /// <summary>The short assembly names to remove as assembly reference, and replace with the <see cref="Targets"/>. These should be short names (like "Stardew Valley").</summary> public readonly string[] RemoveNames; - /// <summary>The assembly filenames to target. Equivalent types should be rewritten to use these assemblies.</summary> - /**** ** Metadata ****/ diff --git a/src/StardewModdingAPI.Installer/InteractiveInstaller.cs b/src/StardewModdingAPI.Installer/InteractiveInstaller.cs index ef813eb3..5abcfc8f 100644 --- a/src/StardewModdingAPI.Installer/InteractiveInstaller.cs +++ b/src/StardewModdingAPI.Installer/InteractiveInstaller.cs @@ -27,6 +27,7 @@ namespace StardewModdingApi.Installer yield return $"{Environment.GetEnvironmentVariable("HOME")}/.local/share/Steam/steamapps/common/Stardew Valley"; // Mac + yield return "/Applications/Stardew Valley.app/Contents/MacOS"; yield return $"{Environment.GetEnvironmentVariable("HOME")}/Library/Application Support/Steam/steamapps/common/Stardew Valley/Contents/MacOS"; // Windows @@ -50,32 +51,38 @@ namespace StardewModdingApi.Installer } } - /// <summary>The directory or file paths to remove when uninstalling SMAPI, relative to the game directory.</summary> - private readonly string[] UninstallPaths = + /// <summary>Get the absolute file or folder paths to remove when uninstalling SMAPI.</summary> + /// <param name="installDir">The folder for Stardew Valley and SMAPI.</param> + /// <param name="modsDir">The folder for SMAPI mods.</param> + private IEnumerable<string> GetUninstallPaths(DirectoryInfo installDir, DirectoryInfo modsDir) { + Func<string, string> installPath = path => Path.Combine(installDir.FullName, path); + // common - "StardewModdingAPI.exe", - "StardewModdingAPI.config.json", - "StardewModdingAPI.data.json", - "StardewModdingAPI.AssemblyRewriters.dll", - "steam_appid.txt", + yield return installPath("StardewModdingAPI.exe"); + yield return installPath("StardewModdingAPI.config.json"); + yield return installPath("StardewModdingAPI.data.json"); + yield return installPath("StardewModdingAPI.AssemblyRewriters.dll"); + yield return installPath("steam_appid.txt"); // Linux/Mac only - "Mono.Cecil.dll", - "Mono.Cecil.Rocks.dll", - "Newtonsoft.Json.dll", - "StardewModdingAPI", - "StardewModdingAPI.exe.mdb", - "System.Numerics.dll", - "System.Runtime.Caching.dll", + yield return installPath("Mono.Cecil.dll"); + yield return installPath("Mono.Cecil.Rocks.dll"); + yield return installPath("Newtonsoft.Json.dll"); + yield return installPath("StardewModdingAPI"); + yield return installPath("StardewModdingAPI.exe.mdb"); + yield return installPath("System.Numerics.dll"); + yield return installPath("System.Runtime.Caching.dll"); // Windows only - "StardewModdingAPI.pdb", + yield return installPath("StardewModdingAPI.pdb"); // obsolete - "Mods/.cache", // 1.3-1.4 - "StardewModdingAPI-settings.json" // 1.0-1.4 - }; + yield return installPath("Mods/.cache"); // 1.3-1.4 + yield return installPath("StardewModdingAPI-settings.json"); // 1.0-1.4 + foreach (DirectoryInfo modDir in modsDir.EnumerateDirectories()) + yield return Path.Combine(modDir.FullName, ".cache"); // 1.4–1.7 + } /// <summary>Whether the current console supports color formatting.</summary> private static readonly bool ConsoleSupportsColor = InteractiveInstaller.GetConsoleSupportsColor(); @@ -109,8 +116,9 @@ namespace StardewModdingApi.Installer ** collect details ****/ Platform platform = this.DetectPlatform(); - DirectoryInfo packageDir = new DirectoryInfo(Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), platform.ToString())); + 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 { executable = Path.Combine(installDir.FullName, platform == Platform.Mono ? "StardewValley.exe" : "Stardew Valley.exe"), @@ -125,7 +133,7 @@ namespace StardewModdingApi.Installer ****/ if (!packageDir.Exists) { - this.ExitError($"The '{platform}' package directory is missing (should be at {packageDir})."); + this.ExitError($"The 'internal/{platform}' package folder is missing (should be at {packageDir})."); return; } if (!File.Exists(paths.executable)) @@ -139,11 +147,9 @@ namespace StardewModdingApi.Installer ** ask user what to do ****/ Console.WriteLine("You can...."); - Console.WriteLine(platform == Platform.Mono - ? "[1] Install SMAPI. This will safely update the files so you can launch the game the same way as before." - : "[1] Install SMAPI. You'll need to launch StardewModdingAPI.exe instead afterwards; see the readme.txt for details." - ); + Console.WriteLine("[1] Install SMAPI."); Console.WriteLine("[2] Uninstall SMAPI."); + Console.WriteLine(); ScriptAction action; { @@ -175,8 +181,7 @@ namespace StardewModdingApi.Installer } // remove old files - string[] removePaths = this.UninstallPaths - .Select(path => Path.Combine(installDir.FullName, path)) + string[] removePaths = this.GetUninstallPaths(installDir, modsDir) .Where(path => Directory.Exists(path) || File.Exists(path)) .ToArray(); if (removePaths.Any()) @@ -219,7 +224,6 @@ namespace StardewModdingApi.Installer } // create mods directory (if needed) - DirectoryInfo modsDir = new DirectoryInfo(Path.Combine(installDir.FullName, "Mods")); if (!modsDir.Exists) { this.PrintDebug("Creating mods directory..."); diff --git a/src/StardewModdingAPI.Installer/StardewModdingAPI.Installer.csproj b/src/StardewModdingAPI.Installer/StardewModdingAPI.Installer.csproj index 4e4872b6..e31a1452 100644 --- a/src/StardewModdingAPI.Installer/StardewModdingAPI.Installer.csproj +++ b/src/StardewModdingAPI.Installer/StardewModdingAPI.Installer.csproj @@ -50,47 +50,7 @@ <CopyToOutputDirectory>Always</CopyToOutputDirectory> </Content> </ItemGroup> - <Import Project="$(SolutionDir)\crossplatform.targets" /> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> - <!-- package files --> - <Target Name="AfterBuild"> - <PropertyGroup> - <CompiledInstallerPath>$(SolutionDir)\..\bin\Packaged</CompiledInstallerPath> - <CompiledSmapiPath>$(SolutionDir)\..\bin\$(Configuration)\SMAPI</CompiledSmapiPath> - </PropertyGroup> - <ItemGroup> - <CompiledMods Include="$(SolutionDir)\..\bin\$(Configuration)\Mods\**\*.*" /> - </ItemGroup> - <!-- reset package directory --> - <RemoveDir Directories="$(CompiledInstallerPath)" /> - <!-- copy installer files --> - <Copy SourceFiles="$(TargetDir)\$(TargetName).exe" DestinationFiles="$(CompiledInstallerPath)\install.exe" /> - <Copy SourceFiles="$(TargetDir)\readme.txt" DestinationFiles="$(CompiledInstallerPath)\readme.txt" /> - <!-- copy SMAPI files for Mono --> - <Copy Condition="$(OS) != 'Windows_NT'" SourceFiles="$(CompiledSmapiPath)\Mono.Cecil.dll" DestinationFolder="$(CompiledInstallerPath)\Mono" /> - <Copy Condition="$(OS) != 'Windows_NT'" SourceFiles="$(CompiledSmapiPath)\Mono.Cecil.Rocks.dll" DestinationFolder="$(CompiledInstallerPath)\Mono" /> - <Copy Condition="$(OS) != 'Windows_NT'" SourceFiles="$(CompiledSmapiPath)\Newtonsoft.Json.dll" DestinationFolder="$(CompiledInstallerPath)\Mono" /> - <Copy Condition="$(OS) != 'Windows_NT'" SourceFiles="$(CompiledSmapiPath)\StardewModdingAPI.exe" DestinationFolder="$(CompiledInstallerPath)\Mono" /> - <Copy Condition="$(OS) != 'Windows_NT'" SourceFiles="$(CompiledSmapiPath)\StardewModdingAPI.exe.mdb" DestinationFolder="$(CompiledInstallerPath)\Mono" /> - <Copy Condition="$(OS) != 'Windows_NT'" SourceFiles="$(CompiledSmapiPath)\StardewModdingAPI.AssemblyRewriters.dll" DestinationFolder="$(CompiledInstallerPath)\Mono" /> - <Copy Condition="$(OS) != 'Windows_NT'" SourceFiles="$(CompiledSmapiPath)\StardewModdingAPI.config.json" DestinationFolder="$(CompiledInstallerPath)\Mono" /> - <Copy Condition="$(OS) != 'Windows_NT'" SourceFiles="$(CompiledSmapiPath)\StardewModdingAPI.data.json" DestinationFolder="$(CompiledInstallerPath)\Mono" /> - <Copy Condition="$(OS) != 'Windows_NT'" SourceFiles="$(CompiledSmapiPath)\System.Numerics.dll" DestinationFolder="$(CompiledInstallerPath)\Mono" /> - <Copy Condition="$(OS) != 'Windows_NT'" SourceFiles="$(CompiledSmapiPath)\System.Runtime.Caching.dll" DestinationFolder="$(CompiledInstallerPath)\Mono" /> - <Copy Condition="$(OS) != 'Windows_NT'" SourceFiles="$(CompiledSmapiPath)\unix-launcher.sh" DestinationFiles="$(CompiledInstallerPath)\Mono\StardewModdingAPI" /> - <Copy Condition="$(OS) != 'Windows_NT'" SourceFiles="$(CompiledSmapiPath)\steam_appid.txt" DestinationFolder="$(CompiledInstallerPath)\Mono" /> - <Copy Condition="$(OS) != 'Windows_NT'" SourceFiles="@(CompiledMods)" DestinationFolder="$(CompiledInstallerPath)\Mono\Mods\%(RecursiveDir)" /> - <!-- copy SMAPI files for Windows --> - <Copy Condition="$(OS) == 'Windows_NT'" SourceFiles="$(CompiledSmapiPath)\Mono.Cecil.dll" DestinationFolder="$(CompiledInstallerPath)\Windows" /> - <Copy Condition="$(OS) == 'Windows_NT'" SourceFiles="$(CompiledSmapiPath)\Mono.Cecil.Rocks.dll" DestinationFolder="$(CompiledInstallerPath)\Windows" /> - <Copy Condition="$(OS) == 'Windows_NT'" SourceFiles="$(CompiledSmapiPath)\Newtonsoft.Json.dll" DestinationFolder="$(CompiledInstallerPath)\Windows" /> - <Copy Condition="$(OS) == 'Windows_NT'" SourceFiles="$(CompiledSmapiPath)\StardewModdingAPI.exe" DestinationFolder="$(CompiledInstallerPath)\Windows" /> - <Copy Condition="$(OS) == 'Windows_NT'" SourceFiles="$(CompiledSmapiPath)\StardewModdingAPI.pdb" DestinationFolder="$(CompiledInstallerPath)\Windows" /> - <Copy Condition="$(OS) == 'Windows_NT'" SourceFiles="$(CompiledSmapiPath)\StardewModdingAPI.xml" DestinationFolder="$(CompiledInstallerPath)\Windows" /> - <Copy Condition="$(OS) == 'Windows_NT'" SourceFiles="$(CompiledSmapiPath)\StardewModdingAPI.AssemblyRewriters.dll" DestinationFolder="$(CompiledInstallerPath)\Windows" /> - <Copy Condition="$(OS) == 'Windows_NT'" SourceFiles="$(CompiledSmapiPath)\StardewModdingAPI.config.json" DestinationFolder="$(CompiledInstallerPath)\Windows" /> - <Copy Condition="$(OS) == 'Windows_NT'" SourceFiles="$(CompiledSmapiPath)\StardewModdingAPI.data.json" DestinationFolder="$(CompiledInstallerPath)\Windows" /> - <Copy Condition="$(OS) == 'Windows_NT'" SourceFiles="$(CompiledSmapiPath)\steam_appid.txt" DestinationFolder="$(CompiledInstallerPath)\Windows" /> - <Copy Condition="$(OS) == 'Windows_NT'" SourceFiles="@(CompiledMods)" DestinationFolder="$(CompiledInstallerPath)\Windows\Mods\%(RecursiveDir)" /> - </Target> + <Import Project="$(SolutionDir)\crossplatform.targets" /> + <Import Project="$(SolutionDir)\prepare-install-package.targets" /> </Project>
\ No newline at end of file diff --git a/src/StardewModdingAPI.Installer/readme.txt b/src/StardewModdingAPI.Installer/readme.txt index c5a1caa6..4756099e 100644 --- a/src/StardewModdingAPI.Installer/readme.txt +++ b/src/StardewModdingAPI.Installer/readme.txt @@ -1,4 +1,25 @@ -On Windows, double-click install.exe. -On Linux or Mac, open a terminal and run `mono install.exe`. + ___ ___ ___ ___ + / /\ /__/\ / /\ / /\ ___ + / /:/_ | |::\ / /::\ / /::\ / /\ + / /:/ /\ | |:|:\ / /:/\:\ / /:/\:\ / /:/ + / /:/ /::\ __|__|:|\:\ / /:/~/::\ / /:/~/:/ /__/::\ + /__/:/ /:/\:\ /__/::::| \:\ /__/:/ /:/\:\ /__/:/ /:/ \__\/\:\__ + \ \:\/:/~/:/ \ \:\~~\__\/ \ \:\/:/__\/ \ \:\/:/ \ \:\/\ + \ \::/ /:/ \ \:\ \ \::/ \ \::/ \__\::/ + \__\/ /:/ \ \:\ \ \:\ \ \:\ /__/:/ + /__/:/ \ \:\ \ \:\ \ \:\ \__\/ + \__\/ \__\/ \__\/ \__\/ -For more detailed instructions, see http://canimod.com/guides/using-mods#installing-smapi.
\ No newline at end of file + +SMAPI lets you run Stardew Valley with mods. Don't forget to download mods separately. + + +To install: + - Windows: double-click install.exe. + - Linux or Mac: open a terminal and run `mono install.exe`. + + +Need help? See: + - Install guide: http://canimod.com/guides/using-mods#installing-smapi + - Troubleshooting: http://canimod.com/guides/smapi-faq#troubleshooting + - Ask for help: https://discord.gg/kH55QXP diff --git a/src/StardewModdingAPI.sln b/src/StardewModdingAPI.sln index 7229cf30..8ab297ed 100644 --- a/src/StardewModdingAPI.sln +++ b/src/StardewModdingAPI.sln @@ -14,6 +14,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "metadata", "metadata", "{86 crossplatform.targets = crossplatform.targets GlobalAssemblyInfo.cs = GlobalAssemblyInfo.cs ..\LICENSE = ..\LICENSE + prepare-install-package.targets = prepare-install-package.targets ..\README.md = ..\README.md ..\release-notes.md = ..\release-notes.md EndProjectSection diff --git a/src/StardewModdingAPI/Constants.cs b/src/StardewModdingAPI/Constants.cs index df527dfe..a62a0d58 100644 --- a/src/StardewModdingAPI/Constants.cs +++ b/src/StardewModdingAPI/Constants.cs @@ -30,7 +30,7 @@ namespace StardewModdingAPI public static readonly Version Version = (Version)Constants.ApiVersion; /// <summary>SMAPI's current semantic version.</summary> - public static ISemanticVersion ApiVersion => new Version(1, 7, 0, null, suppressDeprecationWarning: true); + public static ISemanticVersion ApiVersion => new Version(1, 8, 0, null, suppressDeprecationWarning: true); /// <summary>The minimum supported version of Stardew Valley.</summary> public const string MinimumGameVersion = "1.1"; diff --git a/src/StardewModdingAPI/Events/EventArgsCurrentLocationChanged.cs b/src/StardewModdingAPI/Events/EventArgsCurrentLocationChanged.cs index 443429aa..aa0bb377 100644 --- a/src/StardewModdingAPI/Events/EventArgsCurrentLocationChanged.cs +++ b/src/StardewModdingAPI/Events/EventArgsCurrentLocationChanged.cs @@ -9,10 +9,10 @@ namespace StardewModdingAPI.Events /********* ** Accessors *********/ - /// <summary>The player's previous location.</summary> + /// <summary>The player's current location.</summary> public GameLocation NewLocation { get; private set; } - /// <summary>The player's current location.</summary> + /// <summary>The player's previous location.</summary> public GameLocation PriorLocation { get; private set; } diff --git a/src/StardewModdingAPI/Extensions.cs b/src/StardewModdingAPI/Extensions.cs index 1229ca97..0e9dbbf7 100644 --- a/src/StardewModdingAPI/Extensions.cs +++ b/src/StardewModdingAPI/Extensions.cs @@ -27,7 +27,7 @@ namespace StardewModdingAPI { get { - Program.DeprecationManager.Warn($"{nameof(Extensions)}.{nameof(Extensions.Random)}", "1.0", DeprecationLevel.Info); + Program.DeprecationManager.Warn($"{nameof(Extensions)}.{nameof(Extensions.Random)}", "1.0", DeprecationLevel.PendingRemoval); return Extensions._random; } } @@ -40,7 +40,7 @@ namespace StardewModdingAPI /// <param name="key">The key to check.</param> public static bool IsKeyDown(this Keys key) { - Program.DeprecationManager.Warn($"{nameof(Extensions)}.{nameof(Extensions.IsKeyDown)}", "1.0", DeprecationLevel.Info); + Program.DeprecationManager.Warn($"{nameof(Extensions)}.{nameof(Extensions.IsKeyDown)}", "1.0", DeprecationLevel.PendingRemoval); return Keyboard.GetState().IsKeyDown(key); } @@ -48,7 +48,7 @@ namespace StardewModdingAPI /// <summary>Get a random color.</summary> public static Color RandomColour() { - Program.DeprecationManager.Warn($"{nameof(Extensions)}.{nameof(Extensions.RandomColour)}", "1.0", DeprecationLevel.Info); + Program.DeprecationManager.Warn($"{nameof(Extensions)}.{nameof(Extensions.RandomColour)}", "1.0", DeprecationLevel.PendingRemoval); return new Color(Extensions.Random.Next(0, 255), Extensions.Random.Next(0, 255), Extensions.Random.Next(0, 255)); } @@ -69,7 +69,7 @@ namespace StardewModdingAPI /// <param name="split">The value separator.</param> public static string ToSingular<T>(this IEnumerable<T> ienum, string split = ", ") { - Program.DeprecationManager.Warn($"{nameof(Extensions)}.{nameof(Extensions.ToSingular)}", "1.0", DeprecationLevel.Info); + Program.DeprecationManager.Warn($"{nameof(Extensions)}.{nameof(Extensions.ToSingular)}", "1.0", DeprecationLevel.PendingRemoval); //Apparently Keys[] won't split normally :l if (typeof(T) == typeof(Keys)) @@ -83,7 +83,7 @@ namespace StardewModdingAPI /// <param name="o">The value.</param> public static bool IsInt32(this object o) { - Program.DeprecationManager.Warn($"{nameof(Extensions)}.{nameof(Extensions.IsInt32)}", "1.0", DeprecationLevel.Info); + Program.DeprecationManager.Warn($"{nameof(Extensions)}.{nameof(Extensions.IsInt32)}", "1.0", DeprecationLevel.PendingRemoval); int i; return int.TryParse(o.ToString(), out i); @@ -93,7 +93,7 @@ namespace StardewModdingAPI /// <param name="o">The value.</param> public static int AsInt32(this object o) { - Program.DeprecationManager.Warn($"{nameof(Extensions)}.{nameof(Extensions.AsInt32)}", "1.0", DeprecationLevel.Info); + Program.DeprecationManager.Warn($"{nameof(Extensions)}.{nameof(Extensions.AsInt32)}", "1.0", DeprecationLevel.PendingRemoval); return int.Parse(o.ToString()); } @@ -102,7 +102,7 @@ namespace StardewModdingAPI /// <param name="o">The value.</param> public static bool IsBool(this object o) { - Program.DeprecationManager.Warn($"{nameof(Extensions)}.{nameof(Extensions.IsBool)}", "1.0", DeprecationLevel.Info); + Program.DeprecationManager.Warn($"{nameof(Extensions)}.{nameof(Extensions.IsBool)}", "1.0", DeprecationLevel.PendingRemoval); bool b; return bool.TryParse(o.ToString(), out b); @@ -112,7 +112,7 @@ namespace StardewModdingAPI /// <param name="o">The value.</param> public static bool AsBool(this object o) { - Program.DeprecationManager.Warn($"{nameof(Extensions)}.{nameof(Extensions.AsBool)}", "1.0", DeprecationLevel.Info); + Program.DeprecationManager.Warn($"{nameof(Extensions)}.{nameof(Extensions.AsBool)}", "1.0", DeprecationLevel.PendingRemoval); return bool.Parse(o.ToString()); } @@ -121,7 +121,7 @@ namespace StardewModdingAPI /// <param name="enumerable">The values to hash.</param> public static int GetHash(this IEnumerable enumerable) { - Program.DeprecationManager.Warn($"{nameof(Extensions)}.{nameof(Extensions.GetHash)}", "1.0", DeprecationLevel.Info); + Program.DeprecationManager.Warn($"{nameof(Extensions)}.{nameof(Extensions.GetHash)}", "1.0", DeprecationLevel.PendingRemoval); var hash = 0; foreach (var v in enumerable) @@ -134,7 +134,7 @@ namespace StardewModdingAPI /// <param name="o">The value.</param> public static T Cast<T>(this object o) where T : class { - Program.DeprecationManager.Warn($"{nameof(Extensions)}.{nameof(Extensions.Cast)}", "1.0", DeprecationLevel.Info); + Program.DeprecationManager.Warn($"{nameof(Extensions)}.{nameof(Extensions.Cast)}", "1.0", DeprecationLevel.PendingRemoval); return o as T; } @@ -143,7 +143,7 @@ namespace StardewModdingAPI /// <param name="o">The object to scan.</param> public static FieldInfo[] GetPrivateFields(this object o) { - Program.DeprecationManager.Warn($"{nameof(Extensions)}.{nameof(Extensions.GetPrivateFields)}", "1.0", DeprecationLevel.Info); + Program.DeprecationManager.Warn($"{nameof(Extensions)}.{nameof(Extensions.GetPrivateFields)}", "1.0", DeprecationLevel.PendingRemoval); return o.GetType().GetFields(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Static); } @@ -152,7 +152,7 @@ namespace StardewModdingAPI /// <param name="name">The name of the field to find.</param> public static FieldInfo GetBaseFieldInfo(this Type t, string name) { - Program.DeprecationManager.Warn($"{nameof(Extensions)}.{nameof(Extensions.GetBaseFieldValue)}", "1.0", DeprecationLevel.Info); + Program.DeprecationManager.Warn($"{nameof(Extensions)}.{nameof(Extensions.GetBaseFieldValue)}", "1.0", DeprecationLevel.PendingRemoval); return t.GetField(name, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Static); } @@ -162,7 +162,7 @@ namespace StardewModdingAPI /// <param name="name">The name of the field to find.</param> public static T GetBaseFieldValue<T>(this Type t, object o, string name) where T : class { - Program.DeprecationManager.Warn($"{nameof(Extensions)}.{nameof(Extensions.GetBaseFieldValue)}", "1.0", DeprecationLevel.Info); + Program.DeprecationManager.Warn($"{nameof(Extensions)}.{nameof(Extensions.GetBaseFieldValue)}", "1.0", DeprecationLevel.PendingRemoval); return t.GetBaseFieldInfo(name).GetValue(o) as T; } @@ -173,7 +173,7 @@ namespace StardewModdingAPI /// <param name="newValue">The value to set.</param> public static void SetBaseFieldValue<T>(this Type t, object o, string name, object newValue) where T : class { - Program.DeprecationManager.Warn($"{nameof(Extensions)}.{nameof(Extensions.SetBaseFieldValue)}", "1.0", DeprecationLevel.Info); + Program.DeprecationManager.Warn($"{nameof(Extensions)}.{nameof(Extensions.SetBaseFieldValue)}", "1.0", DeprecationLevel.PendingRemoval); t.GetBaseFieldInfo(name).SetValue(o, newValue as T); } @@ -181,7 +181,7 @@ namespace StardewModdingAPI /// <param name="st">The string to copy.</param> public static string RemoveNumerics(this string st) { - Program.DeprecationManager.Warn($"{nameof(Extensions)}.{nameof(Extensions.RemoveNumerics)}", "1.0", DeprecationLevel.Info); + Program.DeprecationManager.Warn($"{nameof(Extensions)}.{nameof(Extensions.RemoveNumerics)}", "1.0", DeprecationLevel.PendingRemoval); var s = st; foreach (var c in s) { diff --git a/src/StardewModdingAPI/Framework/AssemblyDefinitionResolver.cs b/src/StardewModdingAPI/Framework/AssemblyDefinitionResolver.cs new file mode 100644 index 00000000..b4e69fcd --- /dev/null +++ b/src/StardewModdingAPI/Framework/AssemblyDefinitionResolver.cs @@ -0,0 +1,61 @@ +using System.Collections.Generic; +using Mono.Cecil; + +namespace StardewModdingAPI.Framework +{ + /// <summary>A minimal assembly definition resolver which resolves references to known assemblies.</summary> + internal class AssemblyDefinitionResolver : DefaultAssemblyResolver + { + /********* + ** Properties + *********/ + /// <summary>The known assemblies.</summary> + private readonly IDictionary<string, AssemblyDefinition> Loaded = new Dictionary<string, AssemblyDefinition>(); + + + /********* + ** Public methods + *********/ + /// <summary>Add known assemblies to the resolver.</summary> + /// <param name="assemblies">The known assemblies.</param> + public void Add(params AssemblyDefinition[] assemblies) + { + foreach (AssemblyDefinition assembly in assemblies) + { + this.Loaded[assembly.Name.Name] = assembly; + this.Loaded[assembly.Name.FullName] = assembly; + } + } + + /// <summary>Resolve an assembly reference.</summary> + /// <param name="name">The assembly name.</param> + public override AssemblyDefinition Resolve(AssemblyNameReference name) => this.ResolveName(name.Name) ?? base.Resolve(name); + + /// <summary>Resolve an assembly reference.</summary> + /// <param name="name">The assembly name.</param> + /// <param name="parameters">The assembly reader parameters.</param> + public override AssemblyDefinition Resolve(AssemblyNameReference name, ReaderParameters parameters) => this.ResolveName(name.Name) ?? base.Resolve(name, parameters); + + /// <summary>Resolve an assembly reference.</summary> + /// <param name="fullName">The assembly full name (including version, etc).</param> + public override AssemblyDefinition Resolve(string fullName) => this.ResolveName(fullName) ?? base.Resolve(fullName); + + /// <summary>Resolve an assembly reference.</summary> + /// <param name="fullName">The assembly full name (including version, etc).</param> + /// <param name="parameters">The assembly reader parameters.</param> + public override AssemblyDefinition Resolve(string fullName, ReaderParameters parameters) => this.ResolveName(fullName) ?? base.Resolve(fullName, parameters); + + + /********* + ** Private methods + *********/ + /// <summary>Resolve a known assembly definition based on its short or full name.</summary> + /// <param name="name">The assembly's short or full name.</param> + private AssemblyDefinition ResolveName(string name) + { + return this.Loaded.ContainsKey(name) + ? this.Loaded[name] + : null; + } + } +} diff --git a/src/StardewModdingAPI/Framework/AssemblyRewriting/AssemblyTypeRewriter.cs b/src/StardewModdingAPI/Framework/AssemblyLoader.cs index 9d4d6b11..123211b9 100644 --- a/src/StardewModdingAPI/Framework/AssemblyRewriting/AssemblyTypeRewriter.cs +++ b/src/StardewModdingAPI/Framework/AssemblyLoader.cs @@ -1,4 +1,6 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; +using System.IO; using System.Linq; using System.Reflection; using Mono.Cecil; @@ -6,15 +8,15 @@ using Mono.Cecil.Cil; using Mono.Cecil.Rocks; using StardewModdingAPI.AssemblyRewriters; -namespace StardewModdingAPI.Framework.AssemblyRewriting +namespace StardewModdingAPI.Framework |
