Skip to content
This repository was archived by the owner on Oct 29, 2022. It is now read-only.

Commit 60cf144

Browse files
committed
Improved DynModLib.
1 parent b4d1fef commit 60cf144

2 files changed

Lines changed: 67 additions & 29 deletions

File tree

source/DynModLib.csproj

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,6 @@
1717
<Copy SourceFiles="$(TargetPath)" DestinationFolder="$(SolutionDir)/.." />
1818
</Target>
1919
<ItemGroup>
20-
<Reference Include="System" />
21-
<Reference Include="System.Core" />
2220
<Reference Include="0Harmony">
2321
<Private>False</Private>
2422
</Reference>

source/Main.cs

Lines changed: 67 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,14 @@
88
using System.Text;
99
using BattleTech;
1010
using HBS.Logging;
11+
using Mono.CSharp;
1112

1213
namespace DynModLib
1314
{
1415
public static class Main
1516
{
1617
internal static Mod lib;
18+
internal static Assembly compilerAssembly;
1719

1820
public static void Start(string modDirectory, string json)
1921
{
@@ -23,17 +25,16 @@ public static void Start(string modDirectory, string json)
2325
lib.SetupLogging();
2426
try
2527
{
26-
var compilerAssembly = Assembly.LoadFrom(Path.Combine(lib.Directory, "Mono.CSharp.dll"));
28+
compilerAssembly = Assembly.LoadFrom(Path.Combine(lib.Directory, "Mono.CSharp.dll"));
2729

28-
{
29-
// fix for misbehaving of AssemblyDefinition CheckReferencesPublicToken
30-
var harmony = HarmonyInstance.Create("DynModLib.CSharp");
31-
var mOriginal = compilerAssembly.GetType("Mono.CSharp.AssemblyDefinition").GetMethod("CheckReferencesPublicToken", BindingFlags.Instance | BindingFlags.NonPublic);
32-
var mPrefix = typeof(Main).GetMethod(nameof(Prefix), BindingFlags.Static | BindingFlags.Public);
33-
harmony.Patch(mOriginal, new HarmonyMethod(mPrefix));
34-
}
30+
HarmonyInstance.Create("DynModLib.CSharp").PatchAll();
3531

3632
var references = CollectReferences();
33+
lib.Logger.LogDebug($"Found references:");
34+
foreach (var reference in references)
35+
{
36+
lib.Logger.LogDebug($"\t{reference}");
37+
}
3738
var compiler = new ModCompiler(compilerAssembly, references);
3839

3940
foreach (var d in Directory.GetDirectories(lib.ModsPath)
@@ -54,16 +55,12 @@ public static void Start(string modDirectory, string json)
5455
}
5556
}
5657

57-
public static bool Prefix()
58-
{
59-
return false;
60-
}
61-
6258
private static List<string> CollectReferences()
6359
{
6460
var references = GetManagedAssemblyPaths();
6561
references.Add(Assembly.GetExecutingAssembly().Location);
66-
references.Add(GetAssemblyByName("0Harmony").Location);
62+
references.RemoveAll(x=> x.Contains("System.Runtime."));
63+
references.RemoveAll(x=> x.Contains("System.ValueTuple."));
6764
return references;
6865
}
6966

@@ -85,15 +82,51 @@ public static void Reset()
8582
}
8683
}
8784

85+
[HarmonyPatch(typeof(MetadataImporter), nameof(MetadataImporter.GetAssemblyDefinition))]
86+
internal static class MetadataImporter_GetAssemblyDefinition_Patch
87+
{
88+
private static Assembly lastLoadingAssembly;
89+
public static void Prefix(Assembly assembly)
90+
{
91+
lastLoadingAssembly = assembly;
92+
}
93+
94+
public static void Postfix()
95+
{
96+
lastLoadingAssembly = null;
97+
}
98+
99+
internal static void LogIfError()
100+
{
101+
if (lastLoadingAssembly != null)
102+
{
103+
Main.lib.Logger.LogError($"Couldn't load {lastLoadingAssembly} from {lastLoadingAssembly.Location}!");
104+
}
105+
}
106+
}
107+
108+
[HarmonyPatch]
109+
internal static class AssemblyDefinition_CheckReferencesPublicToken_Patch
110+
{
111+
public static MethodInfo TargetMethod()
112+
{
113+
return Main.compilerAssembly.GetType("Mono.CSharp.AssemblyDefinition")
114+
.GetMethod("CheckReferencesPublicToken", BindingFlags.Instance | BindingFlags.NonPublic);
115+
}
116+
117+
public static bool Prefix()
118+
{
119+
return false;
120+
}
121+
}
122+
88123
internal class ModCompiler
89124
{
90-
private readonly Assembly compilerAssembly;
91125
private readonly List<string> references;
92126
private readonly DateTime lastestAssemblyWriteTime;
93127

94128
internal ModCompiler(Assembly compilerAssembly, List<string> references)
95129
{
96-
this.compilerAssembly = compilerAssembly;
97130
this.references = references;
98131

99132
var latestWriteTime = DateTime.MinValue;
@@ -131,7 +164,7 @@ internal void CheckAndCompile(string modDirectory)
131164
}
132165

133166
Compile();
134-
167+
135168
sw.Stop();
136169
Main.lib.Logger.Log($"{mod.Name}: prepared assembly in {sw.Elapsed.TotalMilliseconds}ms");
137170
}
@@ -162,19 +195,25 @@ private void CompileAssembly(string outPath, List<string> refPaths, List<string>
162195

163196
try
164197
{
165-
var arguments = new List<string>();
166-
arguments.Add("/target:library");
167-
arguments.Add("/nostdlib+");
168-
arguments.Add("/noconfig");
169-
arguments.Add("/debug-");
170-
arguments.Add("/optimize+");
171-
arguments.Add("/out:" + outPath);
198+
var arguments = new List<string>
199+
{
200+
"/target:library",
201+
"/nostdlib+",
202+
"/noconfig",
203+
"/debug-",
204+
"/optimize+",
205+
// "/platform:anycpu",
206+
"/langversion:latest",
207+
// "/unsafe+",
208+
// "/checked-",
209+
"/out:" + outPath
210+
};
172211
refPaths.ForEach(r => arguments.Add("/r:" + r));
173212
srcPaths.ForEach(s => arguments.Add(s));
174213

175214
var memory = new MemoryStream();
176215
var writer = new StreamWriter(memory, Encoding.UTF8);
177-
var type = compilerAssembly.GetType("Mono.CSharp.CompilerCallableEntryPoint");
216+
var type = Main.compilerAssembly.GetType("Mono.CSharp.CompilerCallableEntryPoint");
178217
var method = type.GetMethod("InvokeCompiler");
179218
// CompilerCallableEntryPoint.InvokeCompiler(arguments.ToArray(), writer)
180219
var result = (bool)method.Invoke(method, new object[] { arguments.ToArray(), writer });
@@ -193,6 +232,7 @@ private void CompileAssembly(string outPath, List<string> refPaths, List<string>
193232
}
194233
catch (Exception e)
195234
{
235+
MetadataImporter_GetAssemblyDefinition_Patch.LogIfError();
196236
throw new Exception("DynModLib: Could not call Mono.CSharp compiler", e);
197237
}
198238
}
@@ -249,7 +289,7 @@ public void LoadSettings<T>(T settings) where T : ModSettings
249289
{
250290
return;
251291
}
252-
292+
253293
using (var reader = new StreamReader(SettingsPath))
254294
{
255295
var json = reader.ReadToEnd();
@@ -273,7 +313,7 @@ public void SaveSettings<T>(T settings) where T : ModSettings
273313
writer.Write(json);
274314
}
275315
}
276-
316+
277317
internal bool DependsOnDynModLib => ModTekInfo.DependsOn.Contains(Main.lib.Name);
278318
internal string AssemblyPath => string.IsNullOrEmpty(ModTekInfo.DLL) ? null : Path.Combine(Directory, ModTekInfo.DLL);
279319

0 commit comments

Comments
 (0)