diff options
-rw-r--r-- | src/SMAPI.Installer/InteractiveInstaller.cs | 8 | ||||
-rw-r--r-- | src/SMAPI.Toolkit/Utilities/FileUtilities.cs | 13 | ||||
-rw-r--r-- | src/SMAPI/Program.cs | 16 |
3 files changed, 37 insertions, 0 deletions
diff --git a/src/SMAPI.Installer/InteractiveInstaller.cs b/src/SMAPI.Installer/InteractiveInstaller.cs index 714a959b..d8c27a2d 100644 --- a/src/SMAPI.Installer/InteractiveInstaller.cs +++ b/src/SMAPI.Installer/InteractiveInstaller.cs @@ -410,6 +410,14 @@ namespace StardewModdingApi.Installer } } + // copy the game's deps.json file + // (This is needed to resolve native DLLs like libSkiaSharp.) + File.Copy( + sourceFileName: Path.Combine(paths.GamePath, "Stardew Valley.deps.json"), + destFileName: Path.Combine(paths.GamePath, "StardewModdingAPI.deps.json"), + overwrite: true + ); + // create mods directory (if needed) if (!paths.ModsDir.Exists) { diff --git a/src/SMAPI.Toolkit/Utilities/FileUtilities.cs b/src/SMAPI.Toolkit/Utilities/FileUtilities.cs index 7856fdb1..a6bf5929 100644 --- a/src/SMAPI.Toolkit/Utilities/FileUtilities.cs +++ b/src/SMAPI.Toolkit/Utilities/FileUtilities.cs @@ -1,4 +1,6 @@ +using System; using System.IO; +using System.Security.Cryptography; using System.Threading; namespace StardewModdingAPI.Toolkit.Utilities @@ -42,5 +44,16 @@ namespace StardewModdingAPI.Toolkit.Utilities if (entry.Exists) throw new IOException($"Timed out trying to delete {entry.FullName}"); } + + /// <summary>Get the MD5 hash for a file.</summary> + /// <param name="absolutePath">The absolute file path.</param> + public static string GetFileHash(string absolutePath) + { + using FileStream stream = File.OpenRead(absolutePath); + using MD5 md5 = MD5.Create(); + + byte[] hash = md5.ComputeHash(stream); + return BitConverter.ToString(hash).Replace("-", "").ToLowerInvariant(); + } } } diff --git a/src/SMAPI/Program.cs b/src/SMAPI/Program.cs index 0417697b..67ff8322 100644 --- a/src/SMAPI/Program.cs +++ b/src/SMAPI/Program.cs @@ -5,6 +5,7 @@ using System.Reflection; using System.Threading; using StardewModdingAPI.Framework; using StardewModdingAPI.Toolkit.Serialization.Models; +using StardewModdingAPI.Toolkit.Utilities; namespace StardewModdingAPI { @@ -33,6 +34,7 @@ namespace StardewModdingAPI Program.AssertGamePresent(); Program.AssertGameVersion(); Program.AssertSmapiVersions(); + Program.AssertDepsJson(); Program.Start(args); } catch (BadImageFormatException ex) when (ex.FileName == EarlyConstants.GameAssemblyName) @@ -130,6 +132,20 @@ namespace StardewModdingAPI } } + /// <summary>Assert that SMAPI's <c>StardewModdingAPI.deps.json</c> matches <c>Stardew Valley.deps.json</c>, fixing it if necessary.</summary> + /// <remarks>This is needed to resolve native DLLs like libSkiaSharp.</remarks> + private static void AssertDepsJson() + { + string sourcePath = Path.Combine(Constants.ExecutionPath, "Stardew Valley.deps.json"); + string targetPath = Path.Combine(Constants.ExecutionPath, "StardewModdingAPI.deps.json"); + + if (!File.Exists(targetPath) || FileUtilities.GetFileHash(sourcePath) != FileUtilities.GetFileHash(targetPath)) + { + File.Copy(sourcePath, targetPath, overwrite: true); + Program.PrintErrorAndExit($"The '{Path.GetFileName(targetPath)}' file didn't match the game's version. SMAPI fixed it automatically, but you must restart SMAPI for the change to take effect."); + } + } + /// <summary>Initialize SMAPI and launch the game.</summary> /// <param name="args">The command-line arguments.</param> /// <remarks>This method is separate from <see cref="Main"/> because that can't contain any references to assemblies loaded by <see cref="CurrentDomain_AssemblyResolve"/> (e.g. via <see cref="Constants"/>), or Mono will incorrectly show an assembly resolution error before assembly resolution is set up.</remarks> |