commit 0b37bae7040378aea917290020b5827c3137394d Author: hzhang Date: Fri Feb 21 05:05:44 2025 +0000 add: godot editor patcher diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..597439f --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +bin/ +obj/ +/packages/ +riderModule.iml +/_ReSharper.Caches/ +/VersionInfo.props diff --git a/Polonium.Godot.Patcher.csproj b/Polonium.Godot.Patcher.csproj new file mode 100644 index 0000000..92f1e39 --- /dev/null +++ b/Polonium.Godot.Patcher.csproj @@ -0,0 +1,43 @@ + + + + Exe + net9.0 + enable + enable + $(PoloniumSdkVersion) + true + true + bin/ + $(OutputPath)publish/ + + + + + + + + + $(PublishDir)AppDir/ + $(ProjectDir)appimagetool + Polonium.Godot.Patcher + + + + + + + + + + + + + + + + + + + + diff --git a/Polonium.Godot.Patcher.png b/Polonium.Godot.Patcher.png new file mode 100644 index 0000000..4c52a2f Binary files /dev/null and b/Polonium.Godot.Patcher.png differ diff --git a/Polonium.Godot.Patcher.sln b/Polonium.Godot.Patcher.sln new file mode 100644 index 0000000..6c2cb46 --- /dev/null +++ b/Polonium.Godot.Patcher.sln @@ -0,0 +1,16 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Polonium.Godot.Patcher", "Polonium.Godot.Patcher.csproj", "{85B54825-8E92-4C32-ADCE-5CD713F972D7}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {85B54825-8E92-4C32-ADCE-5CD713F972D7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {85B54825-8E92-4C32-ADCE-5CD713F972D7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {85B54825-8E92-4C32-ADCE-5CD713F972D7}.Release|Any CPU.ActiveCfg = Release|Any CPU + {85B54825-8E92-4C32-ADCE-5CD713F972D7}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection +EndGlobal diff --git a/Program.cs b/Program.cs new file mode 100644 index 0000000..beef637 --- /dev/null +++ b/Program.cs @@ -0,0 +1,169 @@ +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 ""; + } +} \ No newline at end of file diff --git a/appimagetool b/appimagetool new file mode 100755 index 0000000..25365df Binary files /dev/null and b/appimagetool differ diff --git a/publish b/publish new file mode 100644 index 0000000..04d6340 --- /dev/null +++ b/publish @@ -0,0 +1,2 @@ +#!/bin/bash +dotnet publish -c Release -r linux-x64