@@ -20,14 +20,16 @@ You should have received a copy of the GNU General Public License
2020using Avalonia . Controls ;
2121using Avalonia . Interactivity ;
2222using Avalonia . Markup . Xaml ;
23- using Newtonsoft . Json . Linq ;
23+ using Mono . Cecil ;
24+ using Mono . Cecil . Cil ;
2425using OTAPI . Client . Launcher . Targets ;
2526using OTAPI . Common ;
2627using OTAPI . Patcher . Targets ;
2728using System ;
28- using System . ComponentModel ;
2929using System . IO ;
30+ using System . Linq ;
3031using System . Runtime . InteropServices ;
32+ using System . Threading . Tasks ;
3133
3234namespace OTAPI . Client . Launcher ;
3335
@@ -80,6 +82,8 @@ public MainWindow()
8082
8183 if ( Program . ConsoleWriter is not null )
8284 Program . ConsoleWriter . LineReceived += OnConsoleLineReceived ;
85+
86+ PatchMonoMod ( ) ;
8387 }
8488
8589 private void OnConsoleLineReceived ( string line )
@@ -204,13 +208,17 @@ public void OpenFolder(string folder)
204208 process . Start ( ) ;
205209 }
206210
211+ System . Threading . CancellationTokenSource CancellationTokenSource { get ; set ; } = new System . Threading . CancellationTokenSource ( ) ;
212+
207213 public void OnInstall ( object sender , RoutedEventArgs e )
208214 {
209215 if ( Context . IsInstalling || Context . InstallPath ? . Path is null || Context . LaunchTarget is null ) return ;
210216 Context . IsInstalling = true ;
211217
212- new System . Threading . Thread ( ( ) =>
218+ Task . Run ( async ( ) =>
213219 {
220+ CancellationTokenSource . Cancel ( ) ;
221+ CancellationTokenSource = new ( ) ;
214222 try
215223 {
216224 var target = new PCClientTarget ( ) ;
@@ -221,7 +229,7 @@ public void OnInstall(object sender, RoutedEventArgs e)
221229 Context . InstallStatus = "Patching completed, installing to existing installation..." ;
222230
223231 Context . InstallPath . Target . StatusUpdate += ( sender , e ) => Context . InstallStatus = e . Text ;
224- Context . InstallPath . Target . Install ( Context . InstallPath . Path ) ;
232+ await Context . InstallPath . Target . InstallAsync ( Context . InstallPath . Path , CancellationTokenSource . Token ) ;
225233
226234 Context . InstallStatus = "Install completed" ;
227235
@@ -235,6 +243,49 @@ public void OnInstall(object sender, RoutedEventArgs e)
235243 Context . InstallStatus = "Err: " + ex . ToString ( ) ;
236244 OnConsoleLineReceived ( ex . ToString ( ) ) ;
237245 }
238- } ) . Start ( ) ;
246+ } ) ;
247+ }
248+
249+ /// <summary>
250+ /// Current MonoMod is outdated, and the new reorg is not ready yet, however we need v25 RD for NET9, yet Patcher v22 is the latest, and is not compatible with v25.
251+ /// Ultimately the problem is OTAPI Client using both at once, unlike the server setup which doesnt.
252+ /// For now, the intention is to replace the entire both with "return new string[0];" to prevent the GAC IL from being used (which it isn't anyway)
253+ /// </summary>
254+ void PatchMonoMod ( )
255+ {
256+ var bin = File . ReadAllBytes ( "MonoMod.dll" ) ;
257+ using MemoryStream ms = new ( bin ) ;
258+ var asm = AssemblyDefinition . ReadAssembly ( ms ) ;
259+ var modder = asm . MainModule . Types . Single ( x => x . FullName == "MonoMod.MonoModder" ) ;
260+ var gacPaths = modder . Methods . Single ( m => m . Name == "get_GACPaths" ) ;
261+ var il = gacPaths . Body . GetILProcessor ( ) ;
262+ if ( il . Body . Instructions . Count != 3 )
263+ {
264+ il . Body . Instructions . Clear ( ) ;
265+ il . Emit ( OpCodes . Ldc_I4_0 ) ;
266+ il . Emit ( OpCodes . Newarr , asm . MainModule . ImportReference ( typeof ( string ) ) ) ;
267+ il . Emit ( OpCodes . Ret ) ;
268+
269+ // clear MonoModder.MatchingConditionals(cap, asmName), with "return false;"
270+ var mc = modder . Methods . Single ( m => m . Name == "MatchingConditionals" && m . Parameters . Count == 2 && m . Parameters [ 1 ] . ParameterType . Name == "AssemblyNameReference" ) ;
271+ il = mc . Body . GetILProcessor ( ) ;
272+ mc . Body . Instructions . Clear ( ) ;
273+ mc . Body . Variables . Clear ( ) ;
274+ mc . Body . ExceptionHandlers . Clear ( ) ;
275+ il . Emit ( OpCodes . Ldc_I4_1 ) ;
276+ il . Emit ( OpCodes . Ret ) ;
277+
278+ var writerParams = modder . Methods . Single ( m => m . Name == "get_WriterParameters" ) ;
279+ il = writerParams . Body . GetILProcessor ( ) ;
280+ var get_Current = writerParams . Body . Instructions . Single ( x => x . Operand is MethodReference mref && mref . Name == "get_Current" ) ;
281+ // replace get_Current with a number, and remove the bitwise checks
282+ il . Remove ( get_Current . Next ) ;
283+ il . Remove ( get_Current . Next ) ;
284+ il . Replace ( get_Current , Instruction . Create (
285+ OpCodes . Ldc_I4 , RuntimeInformation . IsOSPlatform ( OSPlatform . Windows ) ? 37 : 0
286+ ) ) ;
287+
288+ asm . Write ( "MonoMod.dll" ) ;
289+ }
239290 }
240291}
0 commit comments