Skip to content
This repository has been archived by the owner on May 9, 2023. It is now read-only.

Commit

Permalink
1.8.0, merging Mono and Il2Cpp builds, adding BepInEx support
Browse files Browse the repository at this point in the history
* Project renamed to Explorer to reflect the new scope
* Merged Mono and Il2Cpp builds
* Merged BepInEx and MelonLoader builds
* Some minor changes to accommodate for this
* The release DLL and the config file now use "Explorer" in place of "CppExplorer" for file and folder names
  • Loading branch information
sinai-dev committed Sep 27, 2020
1 parent 8c6202c commit b550356
Show file tree
Hide file tree
Showing 47 changed files with 1,226 additions and 519 deletions.
76 changes: 43 additions & 33 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,23 +1,20 @@
# CppExplorer [![Version](https://img.shields.io/badge/MelonLoader-0.2.7.1-green.svg)](https://github.com/HerpDerpinstine/MelonLoader)
# Explorer [![Version](https://img.shields.io/badge/MelonLoader-0.2.7.1-green.svg)](https://github.com/HerpDerpinstine/MelonLoader) [![Version](https://img.shields.io/badge/BepInEx-5.3.0.svg)](https://github.com/BepInEx/BepInEx)

<p align="center">
<img align="center" src="icon.png">
</p>

<p align="center">
An in-game explorer and a suite of debugging tools for <a href="https://docs.unity3d.com/Manual/IL2CPP.html">IL2CPP</a> Unity games, using <a href="https://github.com/HerpDerpinstine/MelonLoader">MelonLoader</a>.<br><br>
An in-game explorer and a suite of debugging tools for <a href="https://docs.unity3d.com/Manual/IL2CPP.html">IL2CPP</a> and <b>Mono</b> Unity games, using <a href="https://github.com/HerpDerpinstine/MelonLoader">MelonLoader</a> and <a href="https://github.com/BepInEx/BepInEx">BepInEx</a>.<br><br>

<a href="../../releases/latest">
<img src="https://img.shields.io/github/release/sinai-dev/CppExplorer.svg" />
<img src="https://img.shields.io/github/release/sinai-dev/Explorer.svg" />
</a>

<img src="https://img.shields.io/github/downloads/sinai-dev/CppExplorer/total.svg" />
</p>
<p align="center">
<a href="https://github.com/sinai-dev/MonoExplorer">Looking for a Mono version?</a>
<img src="https://img.shields.io/github/downloads/sinai-dev/Explorer/total.svg" />
</p>

- [Known issues](#known-issues)
- [Current status](#current-status)
- [How to install](#how-to-install)
- [How to use](#how-to-use)
- [Mod Config](#mod-config)
Expand All @@ -26,21 +23,34 @@
- [Building](#building)
- [Credits](#credits)

## Known issues
As of version 1.7+, CppExplorer has reached a fairly stable state for most Il2Cpp games.
## Current status

| Mod Loader | Il2Cpp | Mono |
| ----------- | ------ | ---- |
| MelonLoader |||
| BepInEx | <b>?</b> (WIP) ||

<B>IL2CPP Issues:</b>
* .NET 3.5 is not currently supported (Unity 5.6.1 and older), this might change in the future.
* Some methods may still fail with a `MissingMethodException`, please let me know if you experience this (with full MelonLoader log please).
* Reflection may fail with certain types, see [here](https://github.com/knah/Il2CppAssemblyUnhollower#known-issues) for more details.
* Scrolling with mouse wheel in the CppExplorer menu may not work on all games at the moment.
* Scrolling with mouse wheel in the Explorer menu may not work on all games at the moment.

## How to install

### MelonLoader
Requires [MelonLoader](https://github.com/HerpDerpinstine/MelonLoader) to be installed for your game.

1. Download <b>CppExplorer.zip</b> from [Releases](https://github.com/sinai-dev/CppExplorer/releases).
1. Download the relevant <b>Explorer_MelonLoader_.zip</b> from [Releases](https://github.com/sinai-dev/Explorer/releases).
2. Unzip the file into the `Mods` folder in your game's installation directory, created by MelonLoader.
3. Make sure it's not in a sub-folder, `CppExplorer.dll` and `mcs.dll` should be directly in the `Mods\` folder.
3. Make sure it's not in a sub-folder, `Explorer.dll` and `mcs.dll` should be directly in the `Mods\` folder.

### BepInEx
Requires [BepInEx](https://github.com/BepInEx/BepInEx) to be installed for your game.

1. Download the relevant <b>Explorer_BepInEx_.zip</b> from [Releases](https://github.com/sinai-dev/Explorer/releases).
2. Unzip the file into the `BepInEx\plugins\` folder in your game's installation directory, created by MelonLoader.
3. Make sure it's not in a sub-folder, `Explorer.dll` and `mcs.dll` should be directly in the `plugins\` folder.

## How to use

Expand All @@ -50,24 +60,24 @@ Requires [MelonLoader](https://github.com/HerpDerpinstine/MelonLoader) to be ins

### Mod Config

There is a simple Mod Config for the CppExplorer, which is generated the first time you run it.
There is a simple Mod Config for the Explorer, which is generated the first time you run it.

This config is generated to `Mods\CppExplorer\config.xml`. Edit the config while the game is closed if you wish to change it.
This config is generated to `[Game_Directory]\Mods\Explorer\config.xml`. Edit the config while the game is closed if you wish to change it.

`Main_Menu_Toggle` (KeyCode)
* Sets the keybinding for the Main Menu toggle (show/hide all CppExplorer windows)
* Sets the keybinding for the Main Menu toggle (show/hide all Explorer windows)
* See [this article](https://docs.unity3d.com/ScriptReference/KeyCode.html) for a full list of all accepted KeyCodes.
* Default: `F7`

`Default_Window_Size` (Vector2)
* Sets the default width and height for all CppExplorer windows when created.
* Sets the default width and height for all Explorer windows when created.
* `x` is width, `y` is height.
* Default: `<x>550</x> <y>700</y>`

## Features
[![](overview.png)](https://raw.githubusercontent.com/sinai-dev/CppExplorer/master/overview.png)
[![](overview.png)](https://raw.githubusercontent.com/sinai-dev/Explorer/master/overview.png)

<i>An overview of the different CppExplorer menus.</i>
<i>An overview of the different Explorer menus.</i>

### Scene Explorer

Expand All @@ -76,7 +86,7 @@ This config is generated to `Mods\CppExplorer\config.xml`. Edit the config while

### Inspectors

CppExplorer has two main inspector modes: <b>GameObject Inspector</b>, and <b>Reflection Inspector</b>.
Explorer has two main inspector modes: <b>GameObject Inspector</b>, and <b>Reflection Inspector</b>.

<b>Tips:</b>
* When in Tab View, GameObjects are denoted by a [G] prefix, and Reflection objects are denoted by a [R] prefix.
Expand Down Expand Up @@ -105,13 +115,13 @@ CppExplorer has two main inspector modes: <b>GameObject Inspector</b>, and <b>Re

### Inspect-under-mouse

* Press Shift+RMB (Right Mouse Button) while the CppExplorer menu is open to begin Inspect-Under-Mouse.
* Press Shift+RMB (Right Mouse Button) while the Explorer menu is open to begin Inspect-Under-Mouse.
* Hover over your desired object, if you see the name appear then you can click on it to inspect it.
* Only objects with Colliders are supported.

### Mouse Control

CppExplorer can force the mouse to be visible and unlocked when the menu is open, if you have enabled "Force Unlock Mouse" (Left-Alt toggle). However, you may also want to prevent the mouse clicking-through onto the game behind CppExplorer, this is possible but it requires specific patches for that game.
Explorer can force the mouse to be visible and unlocked when the menu is open, if you have enabled "Force Unlock Mouse" (Left-Alt toggle). However, you may also want to prevent the mouse clicking-through onto the game behind Explorer, this is possible but it requires specific patches for that game.

* For VRChat, use [VRCExplorerMouseControl](https://github.com/sinai-dev/VRCExplorerMouseControl)
* For Hellpoint, use [HPExplorerMouseControl](https://github.com/sinai-dev/Hellpoint-Mods/tree/master/HPExplorerMouseControl/HPExplorerMouseControl)
Expand All @@ -125,12 +135,12 @@ using Harmony;
[HarmonyPatch(typeof(MyGame.MenuClass), nameof(MyGame.MenuClass.CursorUpdate)]
public class MenuClass_CursorUpdate
{
[HarmonyPrefix]
public static bool Prefix()
{
// prevent method running if menu open, let it run if not.
return !CppExplorer.ShowMenu;
}
[HarmonyPrefix]
public static bool Prefix()
{
// prevent method running if menu open, let it run if not.
return !ExplorerCore.ShowMenu;
}
}
```

Expand All @@ -139,11 +149,11 @@ public class MenuClass_CursorUpdate
If you'd like to build this yourself, everything you need (other than MelonLoader) is included with this repository, there is no need for recursive cloning etc.

1. Install MelonLoader for your game.
2. Open the `src\CppExplorer.csproj` file in a text editor.
3. Scroll down until you see the `<ItemGroup>` containing the References.
4. Fix all of the paths in the `..\Steam\` directory for your game (use the full path if you need to).
5. Open the `src\CppExplorer.sln` project and build it.
6. The dll is built to the `Release\` folder in the root of the repository.
2. Open the `src\Explorer.csproj` file in a text editor.
3. Set the relevant `GameFolder` value(s) for the version(s) you want to build, eg. set `MLCppGameFolder` if you want to build for a MelonLoader Il2Cpp game.
4. Open the `src\Explorer.sln` project.
5. Select `Solution 'Explorer' (1 of 1 project)` in the Solution Explorer panel, and set the <b>Active config</b> to the version you want to build, then build it.
5. The DLLs are built to the `Release\` folder in the root of the repository.

## Credits

Expand Down
Binary file modified icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added lib/UnityEngine.dll
Binary file not shown.
Binary file modified overview.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
47 changes: 28 additions & 19 deletions src/CachedObjects/CacheObjectBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using MelonLoader;
using UnityEngine;

namespace Explorer
Expand Down Expand Up @@ -272,13 +271,13 @@ public object[] ParseArguments()
}
catch
{
MelonLogger.Log($"Argument #{i} '{m_arguments[i].Name}' ({type.Name}), could not parse input '{input}'.");
ExplorerCore.Log($"Argument #{i} '{m_arguments[i].Name}' ({type.Name}), could not parse input '{input}'.");
}
}
}

// Didn't use input, see if there is a default value.
if (m_arguments[i].HasDefaultValue)
if (HasDefaultValue(m_arguments[i]))
{
parsedArgs.Add(m_arguments[i].DefaultValue);
continue;
Expand All @@ -291,6 +290,16 @@ public object[] ParseArguments()
return parsedArgs.ToArray();
}

public static bool HasDefaultValue(ParameterInfo arg)
{
return
#if NET35
arg.DefaultValue != null; // rip null default args in NET35
#else
arg.HasDefaultValue;
#endif
}

public virtual void UpdateValue()
{
if (MemInfo == null)
Expand Down Expand Up @@ -348,13 +357,13 @@ public void SetValue()
}
else
{
pi.SetValue(pi.GetAccessors()[0].IsStatic ? null : DeclaringInstance, Value);
pi.SetValue(pi.GetAccessors()[0].IsStatic ? null : DeclaringInstance, Value, null);
}
}
}
catch (Exception e)
{
MelonLogger.LogWarning($"Error setting value: {e.GetType()}, {e.Message}");
ExplorerCore.LogWarning($"Error setting value: {e.GetType()}, {e.Message}");
}
}

Expand Down Expand Up @@ -391,13 +400,13 @@ public void Draw(Rect window, float labelWidth = 215f)

if (HasParameters)
{
GUILayout.BeginVertical(null);
GUILayout.BeginVertical(new GUILayoutOption[0]);

if (m_isEvaluating)
{
if (cm != null && cm.GenericArgs.Length > 0)
{
GUILayout.Label($"<b><color=orange>Generic Arguments:</color></b>", null);
GUILayout.Label($"<b><color=orange>Generic Arguments:</color></b>", new GUILayoutOption[0]);

for (int i = 0; i < cm.GenericArgs.Length; i++)
{
Expand All @@ -424,21 +433,21 @@ public void Draw(Rect window, float labelWidth = 215f)
}
var input = cm.GenericArgInput[i];

GUILayout.BeginHorizontal(null);
GUILayout.BeginHorizontal(new GUILayoutOption[0]);

GUI.skin.label.alignment = TextAnchor.MiddleCenter;
GUILayout.Label($"<color={UIStyles.Syntax.StructGreen}>{cm.GenericArgs[i].Name}</color>", new GUILayoutOption[] { GUILayout.Width(15) });
cm.GenericArgInput[i] = GUILayout.TextField(input, new GUILayoutOption[] { GUILayout.Width(150) });
GUI.skin.label.alignment = TextAnchor.MiddleLeft;
GUILayout.Label(types, null);
GUILayout.Label(types, new GUILayoutOption[0]);

GUILayout.EndHorizontal();
}
}

if (m_arguments.Length > 0)
{
GUILayout.Label($"<b><color=orange>Arguments:</color></b>", null);
GUILayout.Label($"<b><color=orange>Arguments:</color></b>", new GUILayoutOption[0]);
for (int i = 0; i < m_arguments.Length; i++)
{
var name = m_arguments[i].Name;
Expand All @@ -447,24 +456,24 @@ public void Draw(Rect window, float labelWidth = 215f)

var label = $"<color={UIStyles.Syntax.Class_Instance}>{type}</color> ";
label += $"<color={UIStyles.Syntax.Local}>{name}</color>";
if (m_arguments[i].HasDefaultValue)
if (HasDefaultValue(m_arguments[i]))
{
label = $"<i>[{label} = {m_arguments[i].DefaultValue ?? "null"}]</i>";
}

GUILayout.BeginHorizontal(null);
GUILayout.BeginHorizontal(new GUILayoutOption[0]);

GUI.skin.label.alignment = TextAnchor.MiddleCenter;
GUILayout.Label(i.ToString(), new GUILayoutOption[] { GUILayout.Width(15) });
m_argumentInput[i] = GUILayout.TextField(input, new GUILayoutOption[] { GUILayout.Width(150) });
GUI.skin.label.alignment = TextAnchor.MiddleLeft;
GUILayout.Label(label, null);
GUILayout.Label(label, new GUILayoutOption[0]);

GUILayout.EndHorizontal();
}
}

GUILayout.BeginHorizontal(null);
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
if (GUILayout.Button(EVALUATE_LABEL, new GUILayoutOption[] { GUILayout.Width(70) }))
{
if (cm != null)
Expand Down Expand Up @@ -499,7 +508,7 @@ public void Draw(Rect window, float labelWidth = 215f)

// new line and space
GUILayout.EndHorizontal();
GUILayout.BeginHorizontal(null);
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
GUIUnstrip.Space(labelWidth);
}
else if (cm != null)
Expand All @@ -513,23 +522,23 @@ public void Draw(Rect window, float labelWidth = 215f)

// new line and space
GUILayout.EndHorizontal();
GUILayout.BeginHorizontal(null);
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
GUIUnstrip.Space(labelWidth);
}

string typeName = $"<color={UIStyles.Syntax.Class_Instance}>{ValueType.FullName}</color>";

if (!string.IsNullOrEmpty(ReflectionException))
{
GUILayout.Label("<color=red>Reflection failed!</color> (" + ReflectionException + ")", null);
GUILayout.Label("<color=red>Reflection failed!</color> (" + ReflectionException + ")", new GUILayoutOption[0]);
}
else if ((HasParameters || this is CacheMethod) && !m_evaluated)
{
GUILayout.Label($"<color=grey><i>Not yet evaluated</i></color> ({typeName})", null);
GUILayout.Label($"<color=grey><i>Not yet evaluated</i></color> ({typeName})", new GUILayoutOption[0]);
}
else if (Value == null && !(this is CacheMethod))
{
GUILayout.Label($"<i>null ({typeName})</i>", null);
GUILayout.Label($"<i>null ({typeName})</i>", new GUILayoutOption[0]);
}
else
{
Expand Down
Loading

0 comments on commit b550356

Please sign in to comment.