diff options
author | Jesse Plamondon-Willard <github@jplamondonw.com> | 2018-02-17 16:38:45 -0500 |
---|---|---|
committer | Jesse Plamondon-Willard <github@jplamondonw.com> | 2018-02-17 16:38:45 -0500 |
commit | e64326f9fe5a388e3a0638567bf4bdf8aab4b639 (patch) | |
tree | dbca53624a15a30186591ec4209f8f0eeb1ee0c7 /src/SMAPI/Framework/ModLoading/AssemblyLoader.cs | |
parent | 754e356adc8fa23f4cecef588406f126a3e1a4a4 (diff) | |
download | SMAPI-e64326f9fe5a388e3a0638567bf4bdf8aab4b639.tar.gz SMAPI-e64326f9fe5a388e3a0638567bf4bdf8aab4b639.tar.bz2 SMAPI-e64326f9fe5a388e3a0638567bf4bdf8aab4b639.zip |
Revert "rewrite all mod assemblies to let SMAPI proxy into their internal classes (#435)"
This reverts commit 032997650010a9b6cd3378cb1a2b8273fb3f56ff.
Diffstat (limited to 'src/SMAPI/Framework/ModLoading/AssemblyLoader.cs')
-rw-r--r-- | src/SMAPI/Framework/ModLoading/AssemblyLoader.cs | 80 |
1 files changed, 42 insertions, 38 deletions
diff --git a/src/SMAPI/Framework/ModLoading/AssemblyLoader.cs b/src/SMAPI/Framework/ModLoading/AssemblyLoader.cs index ac849971..3a7b214a 100644 --- a/src/SMAPI/Framework/ModLoading/AssemblyLoader.cs +++ b/src/SMAPI/Framework/ModLoading/AssemblyLoader.cs @@ -3,7 +3,6 @@ using System.Collections.Generic; using System.IO; using System.Linq; using System.Reflection; -using System.Runtime.CompilerServices; using Mono.Cecil; using Mono.Cecil.Cil; using StardewModdingAPI.Framework.Exceptions; @@ -95,14 +94,23 @@ namespace StardewModdingAPI.Framework.ModLoading if (assembly.Status == AssemblyLoadStatus.AlreadyLoaded) continue; - this.RewriteAssembly(mod, assembly.Definition, assumeCompatible, loggedMessages, logPrefix: " "); - if (!oneAssembly) - this.Monitor.Log($" Loading {assembly.File.Name}...", LogLevel.Trace); - using (MemoryStream outStream = new MemoryStream()) + bool changed = this.RewriteAssembly(mod, assembly.Definition, assumeCompatible, loggedMessages, logPrefix: " "); + if (changed) { - assembly.Definition.Write(outStream); - byte[] bytes = outStream.ToArray(); - lastAssembly = Assembly.Load(bytes); + if (!oneAssembly) + this.Monitor.Log($" Loading {assembly.File.Name} (rewritten in memory)...", LogLevel.Trace); + using (MemoryStream outStream = new MemoryStream()) + { + assembly.Definition.Write(outStream); + byte[] bytes = outStream.ToArray(); + lastAssembly = Assembly.Load(bytes); + } + } + else + { + if (!oneAssembly) + this.Monitor.Log($" Loading {assembly.File.Name}...", LogLevel.Trace); + lastAssembly = Assembly.UnsafeLoadFrom(assembly.File.FullName); } } @@ -184,48 +192,38 @@ namespace StardewModdingAPI.Framework.ModLoading /// <param name="logPrefix">A string to prefix to log messages.</param> /// <returns>Returns whether the assembly was modified.</returns> /// <exception cref="IncompatibleInstructionException">An incompatible CIL instruction was found while rewriting the assembly.</exception> - private void RewriteAssembly(IModMetadata mod, AssemblyDefinition assembly, bool assumeCompatible, HashSet<string> loggedMessages, string logPrefix) + private bool RewriteAssembly(IModMetadata mod, AssemblyDefinition assembly, bool assumeCompatible, HashSet<string> loggedMessages, string logPrefix) { ModuleDefinition module = assembly.MainModule; string filename = $"{assembly.Name.Name}.dll"; - // let SMAPI proxy mod internals for mod-provided APIs - { - MethodReference attributeConstructor = module.Import(typeof(InternalsVisibleToAttribute).GetConstructor(new[] { typeof(string) })); - CustomAttribute attribute = new CustomAttribute(attributeConstructor); - attribute.ConstructorArguments.Add(new CustomAttributeArgument(module.TypeSystem.String, "StardewModdingAPI.Proxies")); - assembly.CustomAttributes.Add(attribute); - } - // swap assembly references if needed (e.g. XNA => MonoGame) bool platformChanged = false; + for (int i = 0; i < module.AssemblyReferences.Count; i++) { - for (int i = 0; i < module.AssemblyReferences.Count; i++) + // remove old assembly reference + if (this.AssemblyMap.RemoveNames.Any(name => module.AssemblyReferences[i].Name == name)) { - // remove old assembly reference - if (this.AssemblyMap.RemoveNames.Any(name => module.AssemblyReferences[i].Name == name)) - { - this.Monitor.LogOnce(loggedMessages, $"{logPrefix}Rewriting {filename} for OS..."); - platformChanged = true; - module.AssemblyReferences.RemoveAt(i); - i--; - } - } - - if (platformChanged) - { - // add target assembly references - foreach (AssemblyNameReference target in this.AssemblyMap.TargetReferences.Values) - module.AssemblyReferences.Add(target); - - // rewrite type scopes to use target assemblies - IEnumerable<TypeReference> typeReferences = module.GetTypeReferences().OrderBy(p => p.FullName); - foreach (TypeReference type in typeReferences) - this.ChangeTypeScope(type); + this.Monitor.LogOnce(loggedMessages, $"{logPrefix}Rewriting {filename} for OS..."); + platformChanged = true; + module.AssemblyReferences.RemoveAt(i); + i--; } } + if (platformChanged) + { + // add target assembly references + foreach (AssemblyNameReference target in this.AssemblyMap.TargetReferences.Values) + module.AssemblyReferences.Add(target); + + // rewrite type scopes to use target assemblies + IEnumerable<TypeReference> typeReferences = module.GetTypeReferences().OrderBy(p => p.FullName); + foreach (TypeReference type in typeReferences) + this.ChangeTypeScope(type); + } // find (and optionally rewrite) incompatible instructions + bool anyRewritten = false; IInstructionHandler[] handlers = new InstructionMetadata().GetHandlers().ToArray(); foreach (MethodDefinition method in this.GetMethods(module)) { @@ -234,6 +232,8 @@ namespace StardewModdingAPI.Framework.ModLoading { InstructionHandleResult result = handler.Handle(module, method, this.AssemblyMap, platformChanged); this.ProcessInstructionHandleResult(mod, handler, result, loggedMessages, logPrefix, assumeCompatible, filename); + if (result == InstructionHandleResult.Rewritten) + anyRewritten = true; } // check CIL instructions @@ -244,9 +244,13 @@ namespace StardewModdingAPI.Framework.ModLoading { InstructionHandleResult result = handler.Handle(module, cil, instruction, this.AssemblyMap, platformChanged); this.ProcessInstructionHandleResult(mod, handler, result, loggedMessages, logPrefix, assumeCompatible, filename); + if (result == InstructionHandleResult.Rewritten) + anyRewritten = true; } } } + + return platformChanged || anyRewritten; } /// <summary>Process the result from an instruction handler.</summary> |