From 56d1507aff73df0ee8f6f2e505b8874fb9bfa7d2 Mon Sep 17 00:00:00 2001 From: sinaioutlander <49360850+sinaioutlander@users.noreply.github.com> Date: Mon, 7 Sep 2020 20:28:33 +1000 Subject: [PATCH] 1.6.2 * Fix for a crash that can occur when inspecting unsupported Dictionaries * Added a scroll bar to the REPL console input area, fixes the issue of the code just being cut off when it goes too long. --- src/CachedObjects/Object/CacheDictionary.cs | 88 +++++++++++++++++++++ src/MainMenu/Pages/ConsolePage.cs | 9 ++- 2 files changed, 96 insertions(+), 1 deletion(-) diff --git a/src/CachedObjects/Object/CacheDictionary.cs b/src/CachedObjects/Object/CacheDictionary.cs index 266e0d2..868e090 100644 --- a/src/CachedObjects/Object/CacheDictionary.cs +++ b/src/CachedObjects/Object/CacheDictionary.cs @@ -7,6 +7,7 @@ using System.Threading.Tasks; using MelonLoader; using UnityEngine; using System.Reflection; +using UnhollowerBaseLib; namespace Explorer { @@ -130,6 +131,13 @@ namespace Explorer public override void UpdateValue() { + // first make sure we won't run into a TypeInitializationException. + if (!EnsureDictionaryIsSupported()) + { + ReflectionException = "Dictionary Type not supported with Reflection!"; + return; + } + base.UpdateValue(); // reset @@ -160,6 +168,86 @@ namespace Explorer m_cachedValues = values.ToArray(); } + private bool EnsureDictionaryIsSupported() + { + try + { + //var ilTypes = new List(); + var monoTypes = new Type[] { TypeOfKeys, TypeOfValues }; + + foreach (var type in monoTypes) + { + var generic = typeof(Il2CppClassPointerStore<>).MakeGenericType(type); + if (generic == null) return false; + + var genericPtr = (IntPtr)generic.GetField("NativeClassPtr").GetValue(null); + if (genericPtr == null) return false; + + var classPtr = IL2CPP.il2cpp_class_get_type(genericPtr); + if (classPtr == null) return false; + + var internalType = Il2CppSystem.Type.internal_from_handle(classPtr); + if (internalType == null) return false; + + //ilTypes.Add(internalType); + } + } + catch + { + return false; + } + + // Should be fine if we got this far, but I'll leave the rest below commented out just in case. + return true; + + //MelonLogger.Log("Got both generic types, continuing..."); + + //var dictIlClass = IL2CPP.GetIl2CppClass("mscorlib.dll", "System.Collections.Generic", "Dictionary`2"); + //if (dictIlClass == null) return; + + //MelonLogger.Log("Got base dictionary Il2Cpp type"); + + //var ilClassFromType = IL2CPP.il2cpp_class_get_type(dictIlClass); + //if (ilClassFromType == null) return; + + //MelonLogger.Log("got IntPtr from base dictionary type"); + + //var internalHandle = Il2CppSystem.Type.internal_from_handle(ilClassFromType); + //if (internalHandle == null) return; + + //var generic = internalHandle.MakeGenericType(new Il2CppReferenceArray(new Il2CppSystem.Type[] + //{ + // ilTypes[0], ilTypes[1] + //})); + //if (generic == null) return; + + //MelonLogger.Log("Made generic handle for our entry types"); + + //var nativeClassPtr = generic.TypeHandle.value; + //if (nativeClassPtr == null) return; + + //MelonLogger.Log("Got the actual nativeClassPtr for the handle"); + + //var dictType = typeof(Il2CppSystem.Collections.Generic.Dictionary<,>).MakeGenericType(TypeOfKeys, TypeOfValues); + //if (dictType == null) return; + + //MelonLogger.Log("Made the generic type for the dictionary"); + + //var pointerStoreType = typeof(Il2CppClassPointerStore<>).MakeGenericType(dictType); + //if (pointerStoreType == null) return; + + //MelonLogger.Log("Made the generic PointerStoreType for our dict"); + + //var ptrToSet = IL2CPP.il2cpp_class_from_type(nativeClassPtr); + //if (ptrToSet == null) return; + + //MelonLogger.Log("Got class from nativeClassPtr, setting value..."); + + //pointerStoreType.GetField("NativeClassPtr").SetValue(null, ptrToSet); + + //MelonLogger.Log("Ok"); + } + // ============= GUI Draw ============= public override void DrawValue(Rect window, float width) diff --git a/src/MainMenu/Pages/ConsolePage.cs b/src/MainMenu/Pages/ConsolePage.cs index 1162a30..df9690f 100644 --- a/src/MainMenu/Pages/ConsolePage.cs +++ b/src/MainMenu/Pages/ConsolePage.cs @@ -19,6 +19,8 @@ namespace Explorer private ScriptEvaluator _evaluator; private readonly StringBuilder _sb = new StringBuilder(); + private Vector2 inputAreaScroll; + private string MethodInput = ""; private string UsingInput = ""; @@ -124,7 +126,12 @@ MelonLogger.Log(""hello world"");"; GUI.skin.label.alignment = TextAnchor.UpperLeft; GUILayout.Label("Enter code here as though it is a method body:", null); - MethodInput = GUILayout.TextArea(MethodInput, new GUILayoutOption[] { GUILayout.Height(250) }); + + inputAreaScroll = GUIUnstrip.BeginScrollView(inputAreaScroll, new GUILayoutOption[] { GUILayout.Height(250) }); + + MethodInput = GUILayout.TextArea(MethodInput, new GUILayoutOption[] { GUILayout.ExpandHeight(true) }); + + GUIUnstrip.EndScrollView(); if (GUILayout.Button("Execute", null)) {