From fad5fe0620f9a361f6b51a6045b157500b5487e9 Mon Sep 17 00:00:00 2001 From: KurobaM <86230463+KurobaM@users.noreply.github.com> Date: Sat, 17 Dec 2022 15:40:36 +0800 Subject: [PATCH 1/4] Update HookInstance.cs --- src/Hooks/HookInstance.cs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/Hooks/HookInstance.cs b/src/Hooks/HookInstance.cs index d0c771ea..31a19e7b 100644 --- a/src/Hooks/HookInstance.cs +++ b/src/Hooks/HookInstance.cs @@ -46,6 +46,19 @@ public HookInstance(MethodInfo targetMethod) if (CompileAndGenerateProcessor(PatchSourceCode)) Patch(); } + + public HookInstance(MethodInfo targetMethod, string code) + { + this.TargetMethod = targetMethod; + this.signature = TargetMethod.FullDescription(); + + PatchSourceCode = code; + + if (CompileAndGenerateProcessor(PatchSourceCode)) + { + Patch(); + } + } // Evaluator.source_file private static readonly FieldInfo fi_sourceFile = AccessTools.Field(typeof(Evaluator), "source_file"); From 7c3443267d638c48b0e8b9315ac03ac18ae5a1e6 Mon Sep 17 00:00:00 2001 From: KurobaM <86230463+KurobaM@users.noreply.github.com> Date: Sat, 17 Dec 2022 15:58:16 +0800 Subject: [PATCH 2/4] Update HookCreator.cs --- src/Hooks/HookCreator.cs | 89 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 88 insertions(+), 1 deletion(-) diff --git a/src/Hooks/HookCreator.cs b/src/Hooks/HookCreator.cs index 17abccd5..c8b876fb 100644 --- a/src/Hooks/HookCreator.cs +++ b/src/Hooks/HookCreator.cs @@ -1,4 +1,6 @@ -using HarmonyLib; +using System.Linq; +using System.Xml.Serialization; +using HarmonyLib; using UnityExplorer.CSConsole; using UnityExplorer.Runtime; using UnityExplorer.UI.Panels; @@ -225,12 +227,97 @@ internal static void EditorInputSave() CurrentEditedHook.Patch(); CurrentEditedHook.PatchSourceCode = input; + SaveHooks(CurrentEditedHook); CurrentEditedHook = null; HookManagerPanel.Instance.SetPage(HookManagerPanel.Pages.ClassMethodSelector); } HookList.HooksScrollPool.Refresh(true, false); } + // Persistent hooks + public struct HookData + { + public string Description; + public string SourceCode; + public string ReflectedType; + } + + public static void SaveHooks(HookInstance hook) + { + HookData data = new HookData(); + data.Description = hook.TargetMethod.FullDescription(); + data.ReflectedType = hook.TargetMethod.ReflectedType.ToString(); + data.SourceCode = hook.PatchSourceCode; + string filename = data.Description.GetHashCode().ToString("X8") + ".txt"; + string folderpath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "UnityExplorerHarmonyHooks"); + Directory.CreateDirectory(folderpath); + string fpath = Path.Combine(folderpath, filename); + XmlSerializer xs = new XmlSerializer(typeof(HookData)); + TextWriter tw = new StreamWriter(fpath); + xs.Serialize(tw, data); + tw.Close(); + ExplorerCore.Log("Save hook: " + data.Description + " to: " + filename); + } + + public void LoadSavedHooks() + { + string folderpath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "UnityExplorerHarmonyHooks"); + Directory.CreateDirectory(folderpath); + ExplorerCore.Log("Hooks path: " + folderpath); + XmlSerializer xs = new XmlSerializer(typeof(HookData)); + xs.UnknownNode += new XmlNodeEventHandler(xs_UnknownNode); + xs.UnknownAttribute += new XmlAttributeEventHandler(xs_UnknownAttribute); + DirectoryInfo di = new DirectoryInfo(folderpath); + FileInfo[] fs = di.GetFiles("*.txt"); + foreach (FileInfo fi in fs) + { + ExplorerCore.Log("Load: " + fi.Name); + try + { + FileStream fileStream = new FileStream(fi.FullName, FileMode.Open, FileAccess.Read); + HookData hookData; + hookData = (HookData)xs.Deserialize(fileStream); + ExplorerCore.Log("+> Hook: " + hookData.Description); + Type type = ReflectionUtility.GetTypeByName(hookData.ReflectedType); + IEnumerable ms = type.GetMethods().Where( + mi => mi.FullDescription() == hookData.Description + ) + ); + + MethodInfo method = ms.First(); + HookManagerPanel.Instance.SetPage(HookManagerPanel.Pages.ClassMethodSelector); + + if (HookList.hookedSignatures.Contains(hookData.Description)) + { + ExplorerCore.LogWarning($"Method is already hooked!"); + return; + } + + HookInstance hook = new(method, hookData.SourceCode); + HookList.hookedSignatures.Add(hookData.Description); + HookList.currentHooks.Add(hookData.Description, hook); + + AddHooksScrollPool.Refresh(true, false); + HookList.HooksScrollPool.Refresh(true, false); + } + catch (Exception ex) + { + ExplorerCore.LogError("Exception when load: " + fi.Name + " ---------\n" + ex.Message); + } + } + } + + + private void xs_UnknownNode(object sender, XmlNodeEventArgs e) + { + ExplorerCore.LogWarning("Unknown Node in hooks:" + e.Name + "\t" + e.Text); + } + + private void xs_UnknownAttribute(object sender, XmlAttributeEventArgs e) + { + System.Xml.XmlAttribute attr = e.Attr; + ExplorerCore.LogWarning("Unknown attribute in hooks:" + attr.Name + "='" + attr.Value + "'"); + } // UI Construction From 85c88a0fd7f1deccf9deebdffec16b1de0167faa Mon Sep 17 00:00:00 2001 From: KurobaM <86230463+KurobaM@users.noreply.github.com> Date: Sat, 17 Dec 2022 16:01:45 +0800 Subject: [PATCH 3/4] Update HookManagerPanel.cs --- src/UI/Panels/HookManagerPanel.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/UI/Panels/HookManagerPanel.cs b/src/UI/Panels/HookManagerPanel.cs index f4f60300..7f0f6ba5 100644 --- a/src/UI/Panels/HookManagerPanel.cs +++ b/src/UI/Panels/HookManagerPanel.cs @@ -97,6 +97,8 @@ protected override void ConstructPanelContent() genericArgsHandler.ConstructUI(ContentRoot); genericArgsHandler.UIRoot.SetActive(false); + + hookCreator.LoadSavedHooks(); } } } From 56601ac0bdf92b1e3ce2d04f0c33f26d731a4604 Mon Sep 17 00:00:00 2001 From: KurobaM <86230463+KurobaM@users.noreply.github.com> Date: Sat, 17 Dec 2022 16:42:39 +0800 Subject: [PATCH 4/4] Update HookCreator.cs --- src/Hooks/HookCreator.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Hooks/HookCreator.cs b/src/Hooks/HookCreator.cs index c8b876fb..ffbb3456 100644 --- a/src/Hooks/HookCreator.cs +++ b/src/Hooks/HookCreator.cs @@ -281,7 +281,6 @@ public void LoadSavedHooks() Type type = ReflectionUtility.GetTypeByName(hookData.ReflectedType); IEnumerable ms = type.GetMethods().Where( mi => mi.FullDescription() == hookData.Description - ) ); MethodInfo method = ms.First();