Compare commits

...

6 Commits
3.1.7 ... 3.1.8

Author SHA1 Message Date
d4dac58fc8 Fix for deobfuscated unhollowed types not being properly resolved 2021-02-20 19:39:19 +11:00
77b97cbe17 Update README.md 2021-02-03 18:31:29 +11:00
c6f0f34ac0 Update README.md 2021-01-28 02:09:40 +11:00
d1f4f74d32 some ui cleanups (minor) 2021-01-22 21:56:00 +11:00
f13068bf01 Update README.md 2021-01-20 23:05:04 +11:00
dfc288a101 Update README.md 2021-01-20 19:10:13 +11:00
8 changed files with 182 additions and 145 deletions

View File

@ -17,7 +17,6 @@
- [Features](#features)
- [How to install](#how-to-install)
- [Mod Config](#mod-config)
- [Mouse Control](#mouse-control)
- [Building](#building)
- [Credits](#credits)
@ -25,8 +24,9 @@
| Mod Loader | IL2CPP | Mono |
| ----------- | ------ | ---- |
| [MelonLoader](https://github.com/HerpDerpinstine/MelonLoader) | ✔️ [link](https://github.com/sinai-dev/UnityExplorer/releases/latest/download/UnityExplorer.MelonLoader.Il2Cpp.zip) | ✔️ [link](https://github.com/sinai-dev/UnityExplorer/releases/latest/download/UnityExplorer.MelonLoader.Mono.zip) |
| [BepInEx](https://github.com/BepInEx/BepInEx) | ✔️ [link](https://github.com/sinai-dev/UnityExplorer/releases/latest/download/UnityExplorer.BepInEx.Il2Cpp.zip) | ✔️ [link](https://github.com/sinai-dev/UnityExplorer/releases/latest/download/UnityExplorer.BepInEx.Mono.zip) |
| [MelonLoader](https://github.com/HerpDerpinstine/MelonLoader) | ✔️ [link](https://github.com/sinai-dev/UnityExplorer/releases/latest/download/UnityExplorer.MelonLoader.Il2Cpp.zip) | ✔️ [link](https://github.com/sinai-dev/UnityExplorer/releases/latest/download/UnityExplorer.MelonLoader.Mono.zip) |
| Standalone | ✔️ [link](https://github.com/sinai-dev/UnityExplorer/releases/latest/download/UnityExplorer.Standalone.Il2Cpp.zip) | ✔️ [link](https://github.com/sinai-dev/UnityExplorer/releases/latest/download/UnityExplorer.Standalone.Mono.zip) |
## Features
@ -50,7 +50,7 @@
0. Install [BepInEx](https://github.com/BepInEx/BepInEx) for your game.
1. Download the UnityExplorer release for BepInEx IL2CPP or Mono above.
2. Take the `UnityExplorer.BIE.___.dll` file and put it in `[GameFolder]\BepInEx\plugins\`
3. In IL2CPP, it is highly recommended to get the base Unity libs for the game's Unity version and put them in the `BepInEx\unhollowed\base\` folder.
3. In IL2CPP, it is highly recommended to get the base Unity libs for the game's Unity version and put them in the `BepInEx\unity-libs\` folder.
### MelonLoader
@ -58,6 +58,13 @@
1. Download the UnityExplorer release for MelonLoader IL2CPP or Mono above.
2. Take the contents of the release and put it in the `[GameFolder]\Mods\` folder. It should look like `[GameFolder]\Mods\UnityExplorer.ML.___.dll`
### Standalone
0. Load the DLL from your mod or inject it.
1. Create an instance of Unity Explorer with `new ExplorerCore();`
2. You will need to call ExplorerCore.Update() (static method) from your Update method.
3. Subscribe to the `ExplorerCore.OnLog__` methods for logging.
## Mod Config
You can access the settings via the "Options" page of the main menu, or directly from the config at `Mods\UnityExplorer\config.ini` (generated after first launch).
@ -88,7 +95,7 @@ You can access the settings via the "Options" page of the main menu, or directly
If you'd like to build this yourself, you will need to have installed BepInEx and/or MelonLoader for at least one Unity game. If you want to build all 4 versions, you will need at least one IL2CPP and one Mono game, with BepInEx and MelonLoader installed for both.
1. Install BepInEx or MelonLoader for your game.
1. Install BepInEx or MelonLoader for your game, or use the standalone build.
2. Open the `src\UnityExplorer.csproj` file in a text editor.
3. For IL2CPP builds, make sure you set `BIECppGameFolder` (for BepInEx) and/or `MLCppGameFolder` (for MelonLoader) so the project can locate the necessary references.
4. Open the `src\UnityExplorer.sln` project.

View File

@ -17,7 +17,7 @@ namespace UnityExplorer
public class ExplorerCore
{
public const string NAME = "UnityExplorer";
public const string VERSION = "3.1.7";
public const string VERSION = "3.1.8";
public const string AUTHOR = "Sinai";
public const string GUID = "com.sinai.unityexplorer";

View File

@ -101,8 +101,24 @@ namespace UnityExplorer.Helpers
return Il2CppToMonoType[cppType];
var getType = Type.GetType(cppType.AssemblyQualifiedName);
Il2CppToMonoType.Add(cppType, getType);
return getType;
if (getType != null)
{
Il2CppToMonoType.Add(cppType, getType);
return getType;
}
else
{
string baseName = cppType.FullName;
string baseAssembly = cppType.Assembly.GetName().name;
Type unhollowedType = AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault(a => a.GetName().Name == baseAssembly)?.GetTypes().FirstOrDefault(t =>
t.CustomAttributes.Any(ca =>
ca.AttributeType.Name == "ObfuscatedNameAttribute" && (string)ca.ConstructorArguments[0].Value == baseName));
Il2CppToMonoType.Add(cppType, unhollowedType);
return unhollowedType;
}
}
private static readonly Dictionary<Type, IntPtr> CppClassPointers = new Dictionary<Type, IntPtr>();

View File

@ -229,13 +229,9 @@ namespace UnityExplorer.Inspectors.Reflection
string toString;
if (m_toStringFormatMethod != null)
{
toString = (string)m_toStringFormatMethod.Invoke(Value, new object[] { "F3" });
}
else
{
toString = (string)m_toStringMethod.Invoke(Value, new object[0]);
}
var fullnametemp = valueType.ToString();
if (fullnametemp.StartsWith("Il2CppSystem"))

View File

@ -153,7 +153,7 @@ namespace UnityExplorer.UI.Modules
{
var name = UISyntaxHighlight.ParseFullSyntax(obj.GetActualType(), true);
if (unityObj && m_context != SearchContext.Singleton && m_context != SearchContext.StaticClass)
if (unityObj && m_context != SearchContext.Singleton)
{
if (unityObj && !string.IsNullOrEmpty(unityObj.name))
name += $": {unityObj.name}";
@ -301,8 +301,8 @@ namespace UnityExplorer.UI.Modules
foreach (var asm in AppDomain.CurrentDomain.GetAssemblies())
{
// All non-static classes
foreach (var type in asm.TryGetTypes().Where(it => !it.IsSealed && !it.IsAbstract))
// Search all non-static, non-enum classes.
foreach (var type in asm.TryGetTypes().Where(it => !(it.IsSealed && it.IsAbstract) && !it.IsEnum))
{
try
{
@ -336,7 +336,7 @@ namespace UnityExplorer.UI.Modules
if (instance != null)
{
instances.Add(instance);
continue;
break;
}
}
}

View File

@ -33,6 +33,8 @@ namespace UnityExplorer.UI.Shared
this.sliderScroller = sliderScroller;
this.inputField = inputField;
sliderScroller.m_parentInputScroller = this;
inputField.onValueChanged.AddListener(OnTextChanged);
inputRect = inputField.GetComponent<RectTransform>();
@ -68,6 +70,17 @@ namespace UnityExplorer.UI.Shared
}
}
internal bool CheckDestroyed()
{
if (sliderScroller == null || sliderScroller.CheckDestroyed())
{
Instances.Remove(this);
return true;
}
return false;
}
internal void OnTextChanged(string text)
{
m_lastText = text;

View File

@ -8,150 +8,154 @@ using UnityExplorer;
using UnityExplorer.Helpers;
using UnityExplorer.UI;
// Basically just to fix an issue with Scrollbars, instead we use a Slider as the scrollbar.
public class SliderScrollbar
namespace UnityExplorer.UI.Shared
{
internal static readonly List<SliderScrollbar> Instances = new List<SliderScrollbar>();
public bool IsActive { get; private set; }
internal readonly Scrollbar m_scrollbar;
internal readonly Slider m_slider;
internal readonly RectTransform m_scrollRect;
public SliderScrollbar(Scrollbar scrollbar, Slider slider)
// Basically just to fix an issue with Scrollbars, instead we use a Slider as the scrollbar.
public class SliderScrollbar
{
Instances.Add(this);
internal static readonly List<SliderScrollbar> Instances = new List<SliderScrollbar>();
this.m_scrollbar = scrollbar;
this.m_slider = slider;
this.m_scrollRect = scrollbar.transform.parent.GetComponent<RectTransform>();
public bool IsActive { get; private set; }
this.m_scrollbar.onValueChanged.AddListener(this.OnScrollbarValueChanged);
this.m_slider.onValueChanged.AddListener(this.OnSliderValueChanged);
internal readonly Scrollbar m_scrollbar;
internal readonly Slider m_slider;
internal readonly RectTransform m_scrollRect;
this.RefreshVisibility();
this.m_slider.Set(1f, false);
}
internal InputFieldScroller m_parentInputScroller;
internal bool CheckDestroyed()
{
if (!m_slider || !m_scrollbar)
public SliderScrollbar(Scrollbar scrollbar, Slider slider)
{
Instances.Remove(this);
return true;
Instances.Add(this);
this.m_scrollbar = scrollbar;
this.m_slider = slider;
this.m_scrollRect = scrollbar.transform.parent.GetComponent<RectTransform>();
this.m_scrollbar.onValueChanged.AddListener(this.OnScrollbarValueChanged);
this.m_slider.onValueChanged.AddListener(this.OnSliderValueChanged);
this.RefreshVisibility();
this.m_slider.Set(1f, false);
}
return false;
}
internal void Update()
{
this.RefreshVisibility();
}
internal void RefreshVisibility()
{
if (!m_slider.gameObject.activeInHierarchy)
internal bool CheckDestroyed()
{
IsActive = false;
return;
if (!m_slider || !m_scrollbar)
{
Instances.Remove(this);
return true;
}
return false;
}
bool shouldShow = !Mathf.Approximately(this.m_scrollbar.size, 1);
var obj = this.m_slider.handleRect.gameObject;
if (IsActive != shouldShow)
internal void Update()
{
IsActive = shouldShow;
obj.SetActive(IsActive);
if (IsActive)
this.m_slider.Set(this.m_scrollbar.value, false);
else
m_slider.Set(1f, false);
this.RefreshVisibility();
}
internal void RefreshVisibility()
{
if (!m_slider.gameObject.activeInHierarchy)
{
IsActive = false;
return;
}
bool shouldShow = !Mathf.Approximately(this.m_scrollbar.size, 1);
var obj = this.m_slider.handleRect.gameObject;
if (IsActive != shouldShow)
{
IsActive = shouldShow;
obj.SetActive(IsActive);
if (IsActive)
this.m_slider.Set(this.m_scrollbar.value, false);
else
m_slider.Set(1f, false);
}
}
public void OnScrollbarValueChanged(float _value)
{
if (this.m_slider.value != _value)
this.m_slider.Set(_value, false);
}
public void OnSliderValueChanged(float _value)
{
this.m_scrollbar.value = _value;
}
#region UI CONSTRUCTION
public static GameObject CreateSliderScrollbar(GameObject parent, out Slider slider)
{
GameObject sliderObj = UIFactory.CreateUIObject("Slider", parent, UIFactory.thinSize);
GameObject bgObj = UIFactory.CreateUIObject("Background", sliderObj);
GameObject fillAreaObj = UIFactory.CreateUIObject("Fill Area", sliderObj);
GameObject fillObj = UIFactory.CreateUIObject("Fill", fillAreaObj);
GameObject handleSlideAreaObj = UIFactory.CreateUIObject("Handle Slide Area", sliderObj);
GameObject handleObj = UIFactory.CreateUIObject("Handle", handleSlideAreaObj);
Image bgImage = bgObj.AddComponent<Image>();
bgImage.type = Image.Type.Sliced;
bgImage.color = new Color(0.05f, 0.05f, 0.05f, 1.0f);
RectTransform bgRect = bgObj.GetComponent<RectTransform>();
bgRect.anchorMin = Vector2.zero;
bgRect.anchorMax = Vector2.one;
bgRect.sizeDelta = Vector2.zero;
bgRect.offsetMax = new Vector2(-10f, 0f);
RectTransform fillAreaRect = fillAreaObj.GetComponent<RectTransform>();
fillAreaRect.anchorMin = new Vector2(0f, 0.25f);
fillAreaRect.anchorMax = new Vector2(1f, 0.75f);
fillAreaRect.anchoredPosition = new Vector2(-5f, 0f);
fillAreaRect.sizeDelta = new Vector2(-20f, 0f);
Image fillImage = fillObj.AddComponent<Image>();
fillImage.type = Image.Type.Sliced;
fillImage.color = Color.clear;
fillObj.GetComponent<RectTransform>().sizeDelta = new Vector2(10f, 0f);
RectTransform handleSlideRect = handleSlideAreaObj.GetComponent<RectTransform>();
handleSlideRect.anchorMin = new Vector2(0f, 0f);
handleSlideRect.anchorMax = new Vector2(1f, 1f);
handleSlideRect.offsetMin = new Vector2(15f, 30f);
handleSlideRect.offsetMax = new Vector2(-15f, 0f);
handleSlideRect.sizeDelta = new Vector2(-30f, -30f);
Image handleImage = handleObj.AddComponent<Image>();
handleImage.color = new Color(0.5f, 0.5f, 0.5f, 1.0f);
var handleRect = handleObj.GetComponent<RectTransform>();
handleRect.sizeDelta = new Vector2(15f, 30f);
handleRect.offsetMin = new Vector2(-13f, -28f);
handleRect.offsetMax = new Vector2(3f, -2f);
var sliderBarLayout = sliderObj.AddComponent<LayoutElement>();
sliderBarLayout.minWidth = 25;
sliderBarLayout.flexibleWidth = 0;
sliderBarLayout.minHeight = 30;
sliderBarLayout.flexibleHeight = 5000;
slider = sliderObj.AddComponent<Slider>();
slider.fillRect = fillObj.GetComponent<RectTransform>();
slider.handleRect = handleObj.GetComponent<RectTransform>();
slider.targetGraphic = handleImage;
slider.direction = Slider.Direction.BottomToTop;
UIFactory.SetDefaultColorTransitionValues(slider);
return sliderObj;
}
#endregion
}
public void OnScrollbarValueChanged(float _value)
{
if (this.m_slider.value != _value)
this.m_slider.Set(_value, false);
}
public void OnSliderValueChanged(float _value)
{
this.m_scrollbar.value = _value;
}
#region UI CONSTRUCTION
public static GameObject CreateSliderScrollbar(GameObject parent, out Slider slider)
{
GameObject sliderObj = UIFactory.CreateUIObject("Slider", parent, UIFactory.thinSize);
GameObject bgObj = UIFactory.CreateUIObject("Background", sliderObj);
GameObject fillAreaObj = UIFactory.CreateUIObject("Fill Area", sliderObj);
GameObject fillObj = UIFactory.CreateUIObject("Fill", fillAreaObj);
GameObject handleSlideAreaObj = UIFactory.CreateUIObject("Handle Slide Area", sliderObj);
GameObject handleObj = UIFactory.CreateUIObject("Handle", handleSlideAreaObj);
Image bgImage = bgObj.AddComponent<Image>();
bgImage.type = Image.Type.Sliced;
bgImage.color = new Color(0.05f, 0.05f, 0.05f, 1.0f);
RectTransform bgRect = bgObj.GetComponent<RectTransform>();
bgRect.anchorMin = Vector2.zero;
bgRect.anchorMax = Vector2.one;
bgRect.sizeDelta = Vector2.zero;
bgRect.offsetMax = new Vector2(-10f, 0f);
RectTransform fillAreaRect = fillAreaObj.GetComponent<RectTransform>();
fillAreaRect.anchorMin = new Vector2(0f, 0.25f);
fillAreaRect.anchorMax = new Vector2(1f, 0.75f);
fillAreaRect.anchoredPosition = new Vector2(-5f, 0f);
fillAreaRect.sizeDelta = new Vector2(-20f, 0f);
Image fillImage = fillObj.AddComponent<Image>();
fillImage.type = Image.Type.Sliced;
fillImage.color = Color.clear;
fillObj.GetComponent<RectTransform>().sizeDelta = new Vector2(10f, 0f);
RectTransform handleSlideRect = handleSlideAreaObj.GetComponent<RectTransform>();
handleSlideRect.anchorMin = new Vector2(0f, 0f);
handleSlideRect.anchorMax = new Vector2(1f, 1f);
handleSlideRect.offsetMin = new Vector2(15f, 30f);
handleSlideRect.offsetMax = new Vector2(-15f, 0f);
handleSlideRect.sizeDelta = new Vector2(-30f, -30f);
Image handleImage = handleObj.AddComponent<Image>();
handleImage.color = new Color(0.5f, 0.5f, 0.5f, 1.0f);
var handleRect = handleObj.GetComponent<RectTransform>();
handleRect.sizeDelta = new Vector2(15f, 30f);
handleRect.offsetMin = new Vector2(-13f, -28f);
handleRect.offsetMax = new Vector2(3f, -2f);
var sliderBarLayout = sliderObj.AddComponent<LayoutElement>();
sliderBarLayout.minWidth = 25;
sliderBarLayout.flexibleWidth = 0;
sliderBarLayout.minHeight = 30;
sliderBarLayout.flexibleHeight = 5000;
slider = sliderObj.AddComponent<Slider>();
slider.fillRect = fillObj.GetComponent<RectTransform>();
slider.handleRect = handleObj.GetComponent<RectTransform>();
slider.targetGraphic = handleImage;
slider.direction = Slider.Direction.BottomToTop;
UIFactory.SetDefaultColorTransitionValues(slider);
return sliderObj;
}
#endregion
}
#if MONO
public static class SliderExtensions
{
@ -175,4 +179,5 @@ public static class SliderExtensions
SetMethod.Invoke(slider, new object[] { value, invokeCallback });
}
}
#endif
#endif
}

View File

@ -81,7 +81,7 @@ namespace UnityExplorer.UI
{
var input = InputFieldScroller.Instances[i];
if (input.sliderScroller.CheckDestroyed())
if (input.CheckDestroyed())
i--;
else
input.Update();