diff options
author | Jesse Plamondon-Willard <github@jplamondonw.com> | 2016-11-21 19:25:53 -0500 |
---|---|---|
committer | Jesse Plamondon-Willard <github@jplamondonw.com> | 2016-11-25 23:41:19 -0500 |
commit | 517a9d82fc1234b6c6ae6f1e45ef7c0f160ee6c5 (patch) | |
tree | 5ef7e0890758783d9107650fefe36429debc7154 /src/StardewModdingAPI/Framework/ModAssemblyLoader.cs | |
parent | 00a3c14446b716fc32c63bccf12c79bdbee436d1 (diff) | |
download | SMAPI-517a9d82fc1234b6c6ae6f1e45ef7c0f160ee6c5.tar.gz SMAPI-517a9d82fc1234b6c6ae6f1e45ef7c0f160ee6c5.tar.bz2 SMAPI-517a9d82fc1234b6c6ae6f1e45ef7c0f160ee6c5.zip |
preprocess mods through Mono.Cecil to allow rewriting later (#166)
Diffstat (limited to 'src/StardewModdingAPI/Framework/ModAssemblyLoader.cs')
-rw-r--r-- | src/StardewModdingAPI/Framework/ModAssemblyLoader.cs | 65 |
1 files changed, 65 insertions, 0 deletions
diff --git a/src/StardewModdingAPI/Framework/ModAssemblyLoader.cs b/src/StardewModdingAPI/Framework/ModAssemblyLoader.cs new file mode 100644 index 00000000..2615e1f7 --- /dev/null +++ b/src/StardewModdingAPI/Framework/ModAssemblyLoader.cs @@ -0,0 +1,65 @@ +using System.IO; +using System.Linq; +using System.Reflection; +using System.Security.Cryptography; +using Mono.Cecil; + +namespace StardewModdingAPI.Framework +{ + /// <summary>Loads mod assemblies.</summary> + internal class ModAssemblyLoader + { + /********* + ** Properties + *********/ + /// <summary>The directory in which to cache data.</summary> + private readonly string CacheDirPath; + + + /********* + ** Public methods + *********/ + /// <summary>Construct an instance.</summary> + /// <param name="cacheDirPath">The cache directory.</param> + public ModAssemblyLoader(string cacheDirPath) + { + this.CacheDirPath = cacheDirPath; + } + + /// <summary>Read an assembly from the given path.</summary> + /// <param name="assemblyPath">The assembly file path.</param> + public Assembly ProcessAssembly(string assemblyPath) + { + // read assembly data + byte[] assemblyBytes = File.ReadAllBytes(assemblyPath); + byte[] hash = MD5.Create().ComputeHash(assemblyBytes); + + // get cache data + string key = Path.GetFileNameWithoutExtension(assemblyPath); + string cachePath = Path.Combine(this.CacheDirPath, $"{key}.dll"); + string cacheHashPath = Path.Combine(this.CacheDirPath, $"{key}-hash.txt"); + bool canUseCache = File.Exists(cachePath) && File.Exists(cacheHashPath) && hash.SequenceEqual(File.ReadAllBytes(cacheHashPath)); + + // process assembly if not cached + if (!canUseCache) + { + // read assembly definition + AssemblyDefinition definition; + using (Stream readStream = new MemoryStream(assemblyBytes)) + definition = AssemblyDefinition.ReadAssembly(readStream); + + // write cache + using (MemoryStream outStream = new MemoryStream()) + { + definition.Write(outStream); + byte[] outBytes = outStream.ToArray(); + File.WriteAllBytes(cachePath, outBytes); + File.WriteAllBytes(cacheHashPath, hash); + } + } + + // load assembly + return Assembly.UnsafeLoadFrom(cachePath); + } + } +} |