using System.Reflection; using Mono.Cecil; using Mono.Cecil.Cil; public class Program { public static void Main(string[] args) { string dllPath = "."; if (args.Length != 0) { Console.WriteLine(args[0]); dllPath = args[0]; } if (dllPath.EndsWith("/")) dllPath = $"{dllPath}GodotTools.ProjectEditor.dll"; else if (!dllPath.EndsWith("GodotTools.ProjectEditor.dll")) dllPath = $"{dllPath}/GodotTools.ProjectEditor.dll"; if (!File.Exists(dllPath)) { Console.WriteLine(dllPath); Console.WriteLine("GodotTools.ProjectEditor.dll not found"); return; } string backupPath = $"{dllPath}.bak"; if (!File.Exists(backupPath)) File.Copy(dllPath, backupPath); string? version = Assembly.GetEntryAssembly()? .GetCustomAttribute()? .InformationalVersion; AssemblyDefinition assembly = AssemblyDefinition.ReadAssembly(dllPath, new ReaderParameters { }); TypeDefinition targetType = assembly.MainModule.Types.First(t => t.Name == "ProjectUtils"); MethodDefinition method = targetType.Methods.First(m => m.Name == "EnsureGodotSdkIsUpToDate"); TypeReference? stringType = assembly.MainModule.ImportReference(typeof(string)); VariableDefinition? root = method.Body.Variables.FirstOrDefault(t => t.VariableType.FullName == "Microsoft.Build.Construction.ProjectRootElement"); TypeDefinition msBuildProjectTypeDef = assembly.MainModule.GetType("GodotTools.ProjectEditor.MSBuildProject"); TypeDefinition projectGeneratorTypeDef = assembly.MainModule.GetType("GodotTools.ProjectEditor.ProjectGenerator"); MethodDefinition? msBuildProjectGetRoot = msBuildProjectTypeDef.Methods .FirstOrDefault(m => m.Name == "get_Root"); MethodDefinition? projectGeneratorGetGodotSdk = projectGeneratorTypeDef.Methods .FirstOrDefault(m => m.Name == "get_GodotSdkAttrValue"); MethodDefinition? msBuildProjectSetHasUnsavedChanges = msBuildProjectTypeDef.Methods .FirstOrDefault(m => m.Name == "set_HasUnsavedChanges"); MethodReference? preGetSdk = method.Body.Instructions .Select(i => i.Operand) .OfType() .FirstOrDefault(m => m.Name == "get_Sdk"); MethodReference? preSetSdk = method.Body.Instructions .Select(i => i.Operand) .OfType() .FirstOrDefault(m => m.Name == "set_Sdk"); foreach (Instruction instruction in method.Body.Instructions) { } method.Body.Instructions.Clear(); method.Body.ExceptionHandlers.Clear(); method.Body.Variables.Clear(); ILProcessor il = method.Body.GetILProcessor(); //VariableDefinition root = new VariableDefinition(projectRootElementTypeDef); method.Body.Variables.Add(root); VariableDefinition godotSdk = new VariableDefinition(stringType); method.Body.Variables.Add(godotSdk); method.Body.InitLocals = true; il.Append(il.Create(OpCodes.Ldarg_0)); il.Append(il.Create(OpCodes.Callvirt, msBuildProjectGetRoot)); il.Append(il.Create(OpCodes.Stloc_0)); il.Append(il.Create(OpCodes.Call, projectGeneratorGetGodotSdk)); il.Append(il.Create(OpCodes.Stloc_1)); il.Append(il.Create(OpCodes.Ldloc_0)); il.Append(il.Create(OpCodes.Callvirt, preGetSdk)); il.Append(il.Create(OpCodes.Call, method.Module .ImportReference( typeof(string).GetMethod("IsNullOrEmpty", [typeof(string)])) ) ); Instruction setSdk = il.Create(OpCodes.Nop); il.Append(il.Create(OpCodes.Brtrue_S, setSdk)); il.Append(il.Create(OpCodes.Ldloc_0)); il.Append(il.Create(OpCodes.Callvirt, preGetSdk)); il.Append(il.Create(OpCodes.Callvirt, method.Module .ImportReference(typeof(string).GetMethod("Trim", Type.EmptyTypes))) ); il.Append(il.Create(OpCodes.Ldloc_1)); il.Append(il.Create(OpCodes.Ldc_I4_5)); il.Append(il.Create(OpCodes.Callvirt, method.Module .ImportReference( typeof(string).GetMethod("Equals", [typeof(string), typeof(StringComparison)])) ) ); Instruction notMatch = il.Create(OpCodes.Nop); il.Append(il.Create(OpCodes.Brfalse_S, notMatch)); il.Append(il.Create(OpCodes.Ret)); il.Append(notMatch); il.Append(il.Create(OpCodes.Ldloc_0)); il.Append(il.Create(OpCodes.Callvirt, preGetSdk)); il.Append(il.Create(OpCodes.Callvirt, method.Module .ImportReference(typeof(string).GetMethod("Trim", Type.EmptyTypes))) ); il.Append(il.Create(OpCodes.Ldstr, $"Polonium.Sdk/{version}")); il.Append(il.Create(OpCodes.Ldc_I4_5)); il.Append(il.Create(OpCodes.Callvirt, method.Module .ImportReference( typeof(string).GetMethod("Equals", [typeof(string), typeof(StringComparison)])) ) ); il.Append(il.Create(OpCodes.Brfalse_S, setSdk)); il.Append(il.Create(OpCodes.Ret)); il.Append(setSdk); il.Append(il.Create(OpCodes.Ldloc_0)); il.Append(il.Create(OpCodes.Ldloc_1)); il.Append(il.Create(OpCodes.Callvirt, preSetSdk)); il.Append(il.Create(OpCodes.Ldarg_0)); il.Append(il.Create(OpCodes.Ldc_I4_1)); il.Append(il.Create(OpCodes.Callvirt, msBuildProjectSetHasUnsavedChanges)); il.Append(il.Create(OpCodes.Ret)); assembly.Write($"{dllPath}.2.dll"); File.Replace($"{dllPath}.2.dll", dllPath, null); } private static string GetAppImagePath() { try { string exePath = "/proc/self/exe"; if (File.Exists(exePath)) { return Path.GetFullPath(new FileInfo(exePath).FullName); } } catch (Exception ex) { return ""; } return ""; } }