summaryrefslogtreecommitdiff
path: root/src/StardewModdingAPI/Framework/ModAssemblyLoader.cs
diff options
context:
space:
mode:
authorJesse Plamondon-Willard <github@jplamondonw.com>2016-11-21 19:25:53 -0500
committerJesse Plamondon-Willard <github@jplamondonw.com>2016-11-25 23:41:19 -0500
commit517a9d82fc1234b6c6ae6f1e45ef7c0f160ee6c5 (patch)
tree5ef7e0890758783d9107650fefe36429debc7154 /src/StardewModdingAPI/Framework/ModAssemblyLoader.cs
parent00a3c14446b716fc32c63bccf12c79bdbee436d1 (diff)
downloadSMAPI-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.cs65
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);
+ }
+ }
+}