summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJesse Plamondon-Willard <github@jplamondonw.com>2016-11-27 15:56:47 -0500
committerJesse Plamondon-Willard <github@jplamondonw.com>2016-11-27 15:56:47 -0500
commitf7b8879011873fa8f7a3d5dd7db27254bfc90469 (patch)
tree7c4e42901614ede42621fd4265c89e131eea4f19 /src
parent0d94c628bbc1d1ab098e0a90ee5758ee69694887 (diff)
downloadSMAPI-f7b8879011873fa8f7a3d5dd7db27254bfc90469.tar.gz
SMAPI-f7b8879011873fa8f7a3d5dd7db27254bfc90469.tar.bz2
SMAPI-f7b8879011873fa8f7a3d5dd7db27254bfc90469.zip
supplement assembly resolution for Mono (#166)
Diffstat (limited to 'src')
-rw-r--r--src/StardewModdingAPI/Framework/AssemblyRewriting/AssemblyTypeRewriter.cs21
-rw-r--r--src/StardewModdingAPI/Framework/AssemblyRewriting/PlatformAssemblyMap.cs35
-rw-r--r--src/StardewModdingAPI/Framework/ModAssemblyLoader.cs20
-rw-r--r--src/StardewModdingAPI/Program.cs4
-rw-r--r--src/StardewModdingAPI/StardewModdingAPI.csproj1
5 files changed, 63 insertions, 18 deletions
diff --git a/src/StardewModdingAPI/Framework/AssemblyRewriting/AssemblyTypeRewriter.cs b/src/StardewModdingAPI/Framework/AssemblyRewriting/AssemblyTypeRewriter.cs
index 7081df15..66c36c03 100644
--- a/src/StardewModdingAPI/Framework/AssemblyRewriting/AssemblyTypeRewriter.cs
+++ b/src/StardewModdingAPI/Framework/AssemblyRewriting/AssemblyTypeRewriter.cs
@@ -11,11 +11,8 @@ namespace StardewModdingAPI.Framework.AssemblyRewriting
/*********
** Properties
*********/
- /// <summary>The assemblies to target. Equivalent types will be rewritten to use these assemblies.</summary>
- private readonly Assembly[] TargetAssemblies;
-
- /// <summary>>The short assembly names to remove as assembly reference, and replace with the <see cref="TargetAssemblies"/>.</summary>
- private readonly string[] RemoveAssemblyNames;
+ /// <summary>Metadata for mapping assemblies to the current <see cref="Platform"/>.</summary>
+ private readonly PlatformAssemblyMap AssemblyMap;
/// <summary>A type => assembly lookup for types which should be rewritten.</summary>
private readonly IDictionary<string, Assembly> TypeAssemblies;
@@ -31,22 +28,20 @@ namespace StardewModdingAPI.Framework.AssemblyRewriting
** Public methods
*********/
/// <summary>Construct an instance.</summary>
- /// <param name="targetAssemblies">The assembly filenames to target. Equivalent types will be rewritten to use these assemblies.</param>
- /// <param name="removeAssemblyNames">The short assembly names to remove as assembly reference, and replace with the <paramref name="targetAssemblies"/>.</param>
+ /// <param name="assemblyMap">Metadata for mapping assemblies to the current <see cref="Platform"/>.</param>
/// <param name="monitor">Encapsulates monitoring and logging.</param>
- public AssemblyTypeRewriter(Assembly[] targetAssemblies, string[] removeAssemblyNames, IMonitor monitor)
+ public AssemblyTypeRewriter(PlatformAssemblyMap assemblyMap, IMonitor monitor)
{
// save config
- this.TargetAssemblies = targetAssemblies;
- this.RemoveAssemblyNames = removeAssemblyNames;
+ this.AssemblyMap = assemblyMap;
this.Monitor = monitor;
// cache assembly metadata
- this.AssemblyNameReferences = targetAssemblies.ToDictionary(assembly => assembly, assembly => AssemblyNameReference.Parse(assembly.FullName));
+ this.AssemblyNameReferences = assemblyMap.Targets.ToDictionary(assembly => assembly, assembly => AssemblyNameReference.Parse(assembly.FullName));
// collect type => assembly lookup
this.TypeAssemblies = new Dictionary<string, Assembly>();
- foreach (Assembly assembly in targetAssemblies)
+ foreach (Assembly assembly in assemblyMap.Targets)
{
foreach (Module assemblyModule in assembly.Modules)
{
@@ -73,7 +68,7 @@ namespace StardewModdingAPI.Framework.AssemblyRewriting
// remove old assembly references
for (int i = 0; i < module.AssemblyReferences.Count; i++)
{
- bool shouldRemove = this.RemoveAssemblyNames.Any(name => module.AssemblyReferences[i].Name == name);
+ bool shouldRemove = this.AssemblyMap.RemoveNames.Any(name => module.AssemblyReferences[i].Name == name);
if (shouldRemove)
{
this.Monitor.Log($"removing reference to {module.AssemblyReferences[i]}", LogLevel.Trace);
diff --git a/src/StardewModdingAPI/Framework/AssemblyRewriting/PlatformAssemblyMap.cs b/src/StardewModdingAPI/Framework/AssemblyRewriting/PlatformAssemblyMap.cs
new file mode 100644
index 00000000..3e6cec8a
--- /dev/null
+++ b/src/StardewModdingAPI/Framework/AssemblyRewriting/PlatformAssemblyMap.cs
@@ -0,0 +1,35 @@
+using System.Reflection;
+
+namespace StardewModdingAPI.Framework.AssemblyRewriting
+{
+ /// <summary>Metadata for mapping assemblies to the current <see cref="Platform"/>.</summary>
+ internal class PlatformAssemblyMap
+ {
+ /*********
+ ** Accessors
+ *********/
+ /// <summary>The target game platform.</summary>
+ public readonly Platform TargetPlatform;
+
+ /// <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>
+ public readonly Assembly[] Targets;
+
+
+ /*********
+ ** Public methods
+ *********/
+ /// <summary>Construct an instance.</summary>
+ /// <param name="targetPlatform">The target game platform.</param>
+ /// <param name="removeAssemblyNames">The assembly short names to remove (like <c>Stardew Valley</c>).</param>
+ /// <param name="targetAssemblies">The assemblies to target.</param>
+ public PlatformAssemblyMap(Platform targetPlatform, string[] removeAssemblyNames, Assembly[] targetAssemblies)
+ {
+ this.TargetPlatform = targetPlatform;
+ this.RemoveNames = removeAssemblyNames;
+ this.Targets = targetAssemblies;
+ }
+ }
+} \ No newline at end of file
diff --git a/src/StardewModdingAPI/Framework/ModAssemblyLoader.cs b/src/StardewModdingAPI/Framework/ModAssemblyLoader.cs
index 7de48649..3d08ec64 100644
--- a/src/StardewModdingAPI/Framework/ModAssemblyLoader.cs
+++ b/src/StardewModdingAPI/Framework/ModAssemblyLoader.cs
@@ -17,6 +17,9 @@ namespace StardewModdingAPI.Framework
/// <summary>The directory in which to cache data.</summary>
private readonly string CacheDirPath;
+ /// <summary>Metadata for mapping assemblies to the current <see cref="Platform"/>.</summary>
+ private readonly PlatformAssemblyMap AssemblyMap;
+
/// <summary>Rewrites assembly types to match the current platform.</summary>
private readonly AssemblyTypeRewriter AssemblyTypeRewriter;
@@ -35,7 +38,8 @@ namespace StardewModdingAPI.Framework
{
this.CacheDirPath = cacheDirPath;
this.Monitor = monitor;
- this.AssemblyTypeRewriter = this.GetAssemblyRewriter(targetPlatform);
+ this.AssemblyMap = this.GetAssemblyMap(targetPlatform);
+ this.AssemblyTypeRewriter = new AssemblyTypeRewriter(this.AssemblyMap, monitor);
}
/// <summary>Preprocess an assembly and cache the modified version.</summary>
@@ -97,6 +101,14 @@ namespace StardewModdingAPI.Framework
return Assembly.UnsafeLoadFrom(cachePaths.Assembly); // unsafe load allows DLLs downloaded from the Internet without the user needing to 'unblock' them
}
+ /// <summary>Resolve an assembly from its name.</summary>
+ /// <param name="name">The assembly name.</param>
+ public Assembly ResolveAssembly(string name)
+ {
+ string shortName = name.Split(new[] { ',' }, 2).First();
+ return this.AssemblyMap.Targets.FirstOrDefault(p => p.GetName().Name == shortName);
+ }
+
/*********
** Private methods
@@ -112,9 +124,9 @@ namespace StardewModdingAPI.Framework
return new CachePaths(dirPath, cacheAssemblyPath, cacheHashPath);
}
- /// <summary>Get an assembly rewriter for the target platform.</summary>
+ /// <summary>Get metadata for mapping assemblies to the current platform.</summary>
/// <param name="targetPlatform">The target game platform.</param>
- private AssemblyTypeRewriter GetAssemblyRewriter(Platform targetPlatform)
+ private PlatformAssemblyMap GetAssemblyMap(Platform targetPlatform)
{
// get assembly changes needed for platform
string[] removeAssemblyReferences;
@@ -155,7 +167,7 @@ namespace StardewModdingAPI.Framework
throw new InvalidOperationException($"Unknown target platform '{targetPlatform}'.");
}
- return new AssemblyTypeRewriter(targetAssemblies, removeAssemblyReferences, this.Monitor);
+ return new PlatformAssemblyMap(targetPlatform, removeAssemblyReferences, targetAssemblies);
}
}
}
diff --git a/src/StardewModdingAPI/Program.cs b/src/StardewModdingAPI/Program.cs
index eba89981..bed4cafc 100644
--- a/src/StardewModdingAPI/Program.cs
+++ b/src/StardewModdingAPI/Program.cs
@@ -303,6 +303,8 @@ namespace StardewModdingAPI
Program.Monitor.Log("Loading mods...");
ModAssemblyLoader modAssemblyLoader = new ModAssemblyLoader(Program.CachePath, Program.TargetPlatform, Program.Monitor);
+ AppDomain.CurrentDomain.AssemblyResolve += (sender, e) => modAssemblyLoader.ResolveAssembly(e.Name); // supplement Mono's assembly resolution which doesn't handle assembly rewrites very well
+
foreach (string directory in Directory.GetDirectories(Program.ModPath))
{
// ignore internal directory
@@ -391,7 +393,7 @@ namespace StardewModdingAPI
}
catch (Exception ex)
{
- Program.Monitor.Log($"{errorPrefix}: couldm't create the per-save configuration directory ('psconfigs') requested by this mod.\n{ex.GetLogSummary()}", LogLevel.Error);
+ Program.Monitor.Log($"{errorPrefix}: couldn't create the per-save configuration directory ('psconfigs') requested by this mod.\n{ex.GetLogSummary()}", LogLevel.Error);
continue;
}
}
diff --git a/src/StardewModdingAPI/StardewModdingAPI.csproj b/src/StardewModdingAPI/StardewModdingAPI.csproj
index 2abcdc23..fd02f802 100644
--- a/src/StardewModdingAPI/StardewModdingAPI.csproj
+++ b/src/StardewModdingAPI/StardewModdingAPI.csproj
@@ -215,6 +215,7 @@
<Compile Include="Extensions.cs" />
<Compile Include="Framework\AssemblyRewriting\CachePaths.cs" />
<Compile Include="Framework\AssemblyRewriting\AssemblyTypeRewriter.cs" />
+ <Compile Include="Framework\AssemblyRewriting\PlatformAssemblyMap.cs" />
<Compile Include="Framework\DeprecationLevel.cs" />
<Compile Include="Framework\DeprecationManager.cs" />
<Compile Include="Framework\InternalExtensions.cs" />