Fix DarkTardMissingNamespacePatch, add some compiler stuff from normal plugin loader, and some code cleanup

This commit is contained in:
2023-07-03 16:23:42 -04:00
parent 856e7dce59
commit 40fa225b1c
11 changed files with 57 additions and 25 deletions

View File

@@ -7,7 +7,7 @@ namespace CringeLauncher.Patches;
[HarmonyPatch(typeof(MyScriptManager), nameof(MyScriptManager.Init))] [HarmonyPatch(typeof(MyScriptManager), nameof(MyScriptManager.Init))]
public static class DarkTardMissingNamespacePatch public static class DarkTardMissingNamespacePatch
{ {
private static void Postfix(Dictionary<string, string> ___m_compatibilityChanges) private static void Prefix(Dictionary<string, string> ___m_compatibilityChanges)
{ {
___m_compatibilityChanges["using System.Runtime.Remoting.Metadata.W3cXsd2001;"] = ""; ___m_compatibilityChanges["using System.Runtime.Remoting.Metadata.W3cXsd2001;"] = "";
___m_compatibilityChanges["using System.IO.Ports;"] = ""; ___m_compatibilityChanges["using System.IO.Ports;"] = "";

View File

@@ -35,7 +35,7 @@ public class RoslynCompiler
RoslynReferences.EnumerateAllReferences(), RoslynReferences.EnumerateAllReferences(),
new( new(
OutputKind.DynamicallyLinkedLibrary, OutputKind.DynamicallyLinkedLibrary,
optimizationLevel: debugBuild ? OptimizationLevel.Debug : OptimizationLevel.Release)); optimizationLevel: debugBuild ? OptimizationLevel.Debug : OptimizationLevel.Release, allowUnsafe: true));
using (var pdb = new MemoryStream()) using (var pdb = new MemoryStream())
using (var ms = new MemoryStream()) using (var ms = new MemoryStream())

View File

@@ -43,6 +43,12 @@ public static class RoslynReferences
AddAssemblyReference(a); AddAssemblyReference(a);
sb.AppendLine(a.FullName); sb.AppendLine(a.FullName);
} }
foreach(var a in GetOtherReferences())
{
AddAssemblyReference(a);
sb.AppendLine(a.FullName);
}
sb.AppendLine(line); sb.AppendLine(line);
while (loadedAssemblies.Count > 0) while (loadedAssemblies.Count > 0)
@@ -77,6 +83,14 @@ public static class RoslynReferences
LogFile.WriteLine(sb.ToString(), false); LogFile.WriteLine(sb.ToString(), false);
} }
/// <summary>
/// This method is used to load references that otherwise would not exist or be optimized out
/// </summary>
private static IEnumerable<Assembly> GetOtherReferences()
{
yield return typeof(Microsoft.CSharp.RuntimeBinder.Binder).Assembly;
}
private static bool ContainsReference(AssemblyName name) private static bool ContainsReference(AssemblyName name)
{ {

View File

@@ -68,12 +68,12 @@ public class GitHubPlugin : PluginData
return sb.ToString(); return sb.ToString();
} }
public override Assembly GetAssembly() public override Assembly? GetAssembly()
{ {
if (!Directory.Exists(cacheDir)) if (!Directory.Exists(cacheDir))
Directory.CreateDirectory(cacheDir); Directory.CreateDirectory(cacheDir);
Assembly a; Assembly? a;
var dllFile = Path.Combine(cacheDir, pluginFile); var dllFile = Path.Combine(cacheDir, pluginFile);
var commitFile = Path.Combine(cacheDir, commitHashFile); var commitFile = Path.Combine(cacheDir, commitHashFile);

View File

@@ -38,7 +38,7 @@ public class LocalFolderPlugin : PluginData
public Config FolderSettings { get; } public Config FolderSettings { get; }
public override Assembly GetAssembly() public override Assembly? GetAssembly()
{ {
if (Directory.Exists(Id)) if (Directory.Exists(Id))
{ {

View File

@@ -30,14 +30,26 @@ public class LocalPlugin : PluginData
} }
} }
public override Assembly GetAssembly() public override Assembly? GetAssembly()
{ {
if (File.Exists(Id)) if (!File.Exists(Id)) return null;
//prevent random unloading if being used by another process
int maxRetries = 10;
while (maxRetries > 0)
{ {
AppDomain.CurrentDomain.AssemblyResolve += LoadFromSameFolder; try
var a = Assembly.LoadFile(Id); {
Version = a.GetName().Version; AppDomain.CurrentDomain.AssemblyResolve += LoadFromSameFolder;
return a; var a = Assembly.LoadFile(Id);
Version = a?.GetName()?.Version ?? Version;
return a;
}
catch (IOException)
{
LogFile.WriteLine($"Waiting to load {Id} because it's being used by another process");
Thread.Sleep(250);
maxRetries--;
}
} }
return null; return null;
@@ -55,27 +67,28 @@ public class LocalPlugin : PluginData
Process.Start("explorer.exe", $"/select, \"{file}\""); Process.Start("explorer.exe", $"/select, \"{file}\"");
} }
private Assembly LoadFromSameFolder(object sender, ResolveEventArgs args) private Assembly? LoadFromSameFolder(object sender, ResolveEventArgs args)
{ {
if (args.RequestingAssembly.IsDynamic) if (args.RequestingAssembly?.IsDynamic ?? false)
return null; return null;
if (args.Name.Contains("0Harmony") || args.Name.Contains("SEPluginManager")) if (args.Name.Contains("0Harmony") || args.Name.Contains("SEPluginManager"))
return null; return null;
var location = args.RequestingAssembly.Location; var location = args.RequestingAssembly?.Location;
if (string.IsNullOrWhiteSpace(location) || !Path.GetFullPath(location) if (string.IsNullOrWhiteSpace(location) || !Path.GetFullPath(location)
.StartsWith(Path.GetDirectoryName(Id), .StartsWith(Path.GetDirectoryName(Id)!,
StringComparison.OrdinalIgnoreCase)) StringComparison.OrdinalIgnoreCase))
return null; return null;
var folderPath = Path.GetDirectoryName(location); var folderPath = Path.GetDirectoryName(Id);
if (string.IsNullOrEmpty(folderPath)) return null;
var assemblyPath = Path.Combine(folderPath, new AssemblyName(args.Name).Name + ".dll"); var assemblyPath = Path.Combine(folderPath, new AssemblyName(args.Name).Name + ".dll");
if (!File.Exists(assemblyPath)) if (!File.Exists(assemblyPath))
return null; return null;
var assembly = Assembly.LoadFile(assemblyPath); var assembly = Assembly.LoadFile(assemblyPath);
LogFile.WriteLine("Resolving " + assembly.GetName().Name + " for " + args.RequestingAssembly.FullName); LogFile.WriteLine("Resolving " + assembly.GetName().Name + " for " + args.RequestingAssembly?.FullName);
var main = Main.Instance; var main = Main.Instance;
if (!main.Config.IsEnabled(assemblyPath)) if (!main.Config.IsEnabled(assemblyPath))

View File

@@ -58,12 +58,12 @@ public class ModPlugin : PluginData, ISteamItem
} }
} }
public override Assembly GetAssembly() public override Assembly? GetAssembly()
{ {
return null; return null;
} }
public override bool TryLoadAssembly(out Assembly a) public override bool TryLoadAssembly(out Assembly? a)
{ {
a = null; a = null;
return false; return false;

View File

@@ -72,9 +72,9 @@ public abstract class PluginData : IEquatable<PluginData>
Id == other.Id; Id == other.Id;
} }
public abstract Assembly GetAssembly(); public abstract Assembly? GetAssembly();
public virtual bool TryLoadAssembly(out Assembly a) public virtual bool TryLoadAssembly(out Assembly? a)
{ {
if (Status == PluginStatus.Error) if (Status == PluginStatus.Error)
{ {

View File

@@ -53,7 +53,7 @@ public abstract class SteamPlugin : PluginData, ISteamItem
} }
} }
public override Assembly GetAssembly() public override Assembly? GetAssembly()
{ {
if (Status == PluginStatus.PendingUpdate) if (Status == PluginStatus.PendingUpdate)
{ {

View File

@@ -82,7 +82,7 @@ public class Main : IHandleInputPlugin
sw.Stop(); sw.Stop();
// FIXME: It can potentially run in the background speeding up the game's startup // FIXME: It can potentially run in the background speeding up the game's startup
ReportEnabledPlugins(); //ReportEnabledPlugins();
LogFile.WriteLine($"Finished startup. Took {sw.ElapsedMilliseconds}ms"); LogFile.WriteLine($"Finished startup. Took {sw.ElapsedMilliseconds}ms");
@@ -220,6 +220,11 @@ public class Main : IHandleInputPlugin
return typeof(Harmony).Assembly; return typeof(Harmony).Assembly;
} }
if (args.Name.Contains("MonoMod.RuntimeDetour"))
{
return typeof(MonoMod.RuntimeDetour.NativeHook).Assembly;
}
if (args.Name.Contains("SEPluginManager")) if (args.Name.Contains("SEPluginManager"))
{ {
if (assembly != null) if (assembly != null)

View File

@@ -11,13 +11,13 @@ namespace PluginLoader;
public class PluginInstance public class PluginInstance
{ {
private readonly PluginData data; private readonly PluginData data;
private readonly Assembly mainAssembly; private readonly Assembly? mainAssembly;
private readonly Type mainType; private readonly Type mainType;
private IHandleInputPlugin inputPlugin; private IHandleInputPlugin inputPlugin;
private MethodInfo openConfigDialog; private MethodInfo openConfigDialog;
private IPlugin plugin; private IPlugin plugin;
private PluginInstance(PluginData data, Assembly mainAssembly, Type mainType) private PluginInstance(PluginData data, Assembly? mainAssembly, Type mainType)
{ {
this.data = data; this.data = data;
this.mainAssembly = mainAssembly; this.mainAssembly = mainAssembly;