Compare commits

...

41 Commits

Author SHA1 Message Date
fae85c2968 Bump version 2021-08-23 18:35:36 +10:00
fc8fa9aa7a Fix TestClass init mistake 2021-08-23 18:35:31 +10:00
bcf9a801a9 Fix suggestions still being given in comments sometimes 2021-08-23 18:35:22 +10:00
20298aa47b Make Type and Member names selectable / copy+paste-able 2021-08-23 18:35:08 +10:00
e2c1c186c3 Add wrapper to handle LemonAction issue 2021-08-23 18:31:26 +10:00
9ce6508828 Update README.md 2021-08-19 16:20:41 +10:00
506e75c5fe Handle Unhollowed modules path through IExplorerLoader. Allow Standalone release to specify manually. 2021-08-19 16:20:25 +10:00
a2f22051f0 Cleanup 2021-08-19 16:19:49 +10:00
4e3203a91b Make Assembly.GetTypes patch a finalizer instead of prefix 2021-08-10 17:31:12 +10:00
a411ce2dba Add patch for Assembly.GetTypes to catch exceptions 2021-08-10 17:17:44 +10:00
48132b3d46 Cleanup ILRepack 2021-08-10 17:17:21 +10:00
e49ed3028f Cleanup 2021-08-06 18:44:13 +10:00
31dd54d25c Reduce string alloc 2021-08-06 16:02:58 +10:00
3cfdd6fa43 Update readme -noci 2021-08-04 01:16:52 +10:00
1fa1283a68 Cleanup and update readme 2021-08-03 18:30:07 +10:00
afa4135b67 Update ML lib for "LemonCleanup" breaking changes 2021-08-03 16:12:28 +10:00
48d1cf574d Fix evaluate exception logic with methods that have arguments 2021-08-03 16:11:54 +10:00
df0abbc847 Small optimizations/cleanup 2021-08-03 16:11:16 +10:00
5c9dcb1d43 Bump HarmonyX to 2.5.2 2021-07-28 19:14:37 +10:00
602770d980 Cleanup 2021-07-28 19:01:43 +10:00
f26371f95f Go back to previous panel transform saving, no need to change 2021-07-28 18:27:10 +10:00
a673c39f4a Include arial in legacy bundles 2021-07-28 18:26:53 +10:00
40583cae3d Include arial in legacy bundles, cleanup 2021-07-28 06:41:02 +10:00
20018a9ba9 Use invariant decimal separator for NumberFormatString 2021-07-28 06:40:05 +10:00
dabf92a1a5 Use CurrentCulture, and use whitespace instead of comma as separator 2021-07-27 22:17:26 +10:00
b7e275f02c Cleanup 2021-07-27 22:12:48 +10:00
f393e0d706 Include Arial font, don't rely on built-in resource
TODO add font to legacy bundles
2021-07-27 18:14:44 +10:00
ab8acc9e84 Change directory case 2021-07-21 20:53:03 +10:00
66c30ee70e Cleanup 2021-07-21 20:48:21 +10:00
ddd271c00d Cleanup 2021-07-21 20:12:34 +10:00
30fe9e4dde Cleanup 2021-07-21 18:37:01 +10:00
fa3a436037 Cleanup 2021-07-21 18:29:01 +10:00
ca27d2b20f Update CursorUnlocker.cs 2021-07-21 05:18:22 +10:00
4315e0c547 Merge branch 'master' of https://github.com/sinai-dev/UnityExplorer 2021-07-21 04:23:55 +10:00
3e19e74329 Update readme -noci 2021-07-21 04:17:41 +10:00
5a3ffebadc Remove legacy build 2021-07-21 04:16:53 +10:00
6e6b6239d8 Do patching in CursorUnlocker, add patch for SetSelectedGameObject 2021-07-21 04:14:34 +10:00
03c8e5a8bd Add Harmony instance to ExplorerCore, bump version 2021-07-21 04:14:12 +10:00
44f7209843 Remove ML 0.3 builds 2021-07-21 04:13:54 +10:00
734e45cf9f Remove patching in mod loader classes 2021-07-21 04:13:42 +10:00
97838e0b3a Update Unhollower 2021-07-21 04:13:15 +10:00
54 changed files with 671 additions and 969 deletions

View File

@ -24,10 +24,8 @@ body:
- BepInEx IL2CPP - BepInEx IL2CPP
- BepInEx 6.X Mono - BepInEx 6.X Mono
- BepInEx 5.X Mono - BepInEx 5.X Mono
- MelonLoader 0.4+ IL2CPP - MelonLoader IL2CPP
- MelonLoader 0.4+ Mono - MelonLoader Mono
- MelonLoader 0.3 IL2CPP
- MelonLoader 0.3 Mono
- Standalone IL2CPP - Standalone IL2CPP
- Standalone Mono - Standalone Mono
validations: validations:

View File

@ -79,22 +79,6 @@ jobs:
name: UnityExplorer.MelonLoader.Mono name: UnityExplorer.MelonLoader.Mono
path: ./Release/UnityExplorer.MelonLoader.Mono/* path: ./Release/UnityExplorer.MelonLoader.Mono/*
# MelonLoader 0.3.0 Il2Cpp
- run: msbuild src\UnityExplorer.csproj -t:Rebuild -p:Platform="AnyCPU" -p:Configuration=Release_MLLegacy_Cpp
- uses: actions/upload-artifact@v2
with:
name: UnityExplorer.MelonLoader_Legacy.Il2Cpp
path: ./Release/UnityExplorer.MelonLoader_Legacy.Il2Cpp/*
# MelonLoader 0.3.0 Mono
- run: msbuild src\UnityExplorer.csproj -t:Rebuild -p:Platform="AnyCPU" -p:Configuration=Release_MLLegacy_Mono
- uses: actions/upload-artifact@v2
with:
name: UnityExplorer.MelonLoader_Legacy.Mono
path: ./Release/UnityExplorer.MelonLoader_Legacy.Mono/*
# Standalone Il2Cpp # Standalone Il2Cpp
- run: msbuild src\UnityExplorer.csproj -t:Rebuild -p:Platform="AnyCPU" -p:Configuration=Release_STANDALONE_Cpp - run: msbuild src\UnityExplorer.csproj -t:Rebuild -p:Platform="AnyCPU" -p:Configuration=Release_STANDALONE_Cpp

View File

@ -33,7 +33,6 @@
| Release | IL2CPP | Mono | | Release | IL2CPP | Mono |
| ------- | ------ | ---- | | ------- | ------ | ---- |
| ML 0.4+ | ✅ [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) | | ML 0.4+ | ✅ [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) |
| ML 0.3 | ✅ [link](https://github.com/sinai-dev/UnityExplorer/releases/latest/download/UnityExplorer.MelonLoader_Legacy.Il2Cpp.zip) | ✅ [link](https://github.com/sinai-dev/UnityExplorer/releases/latest/download/UnityExplorer.MelonLoader_Legacy.Mono.zip) |
1. Take the `UnityExplorer.ML.[version].dll` file and put it in the `Mods\` folder created by MelonLoader. 1. Take the `UnityExplorer.ML.[version].dll` file and put it in the `Mods\` folder created by MelonLoader.

Binary file not shown.

Binary file not shown.

View File

@ -121,16 +121,15 @@ namespace UnityExplorer.CSConsole
{ {
while (input.Length - 1 >= matchEndIdx) while (input.Length - 1 >= matchEndIdx)
{ {
matchEndIdx++;
if (IsNewLine(input[matchEndIdx])) if (IsNewLine(input[matchEndIdx]))
break; break;
matchEndIdx++;
} }
} }
// check caretIdx to determine inStringOrComment state // check caretIdx to determine inStringOrComment state
if (caretIdx >= match.startIndex && (caretIdx <= matchEndIdx || (caretIdx >= input.Length && matchEndIdx >= input.Length - 1))) if (caretIdx >= match.startIndex && (caretIdx <= (matchEndIdx+1) || (caretIdx >= input.Length && matchEndIdx >= input.Length - 1)))
caretInStringOrComment = match.isStringOrComment; caretInStringOrComment = match.isStringOrComment;
} }
// Append trailing unhighlighted input // Append trailing unhighlighted input

View File

@ -12,11 +12,11 @@ namespace UnityExplorer.CacheObject
public CacheConfigEntry(IConfigElement configElement) public CacheConfigEntry(IConfigElement configElement)
{ {
this.RefConfigElement = configElement; this.RefConfigElement = configElement;
this.FallbackType = configElement.ElementType;
this.NameLabelText = $"<color=cyan>{configElement.Name}</color>" + this.NameLabelText = $"<color=cyan>{configElement.Name}</color>" +
$"\r\n<color=grey><i>{configElement.Description}</i></color>"; $"\r\n<color=grey><i>{configElement.Description}</i></color>";
this.NameLabelTextRaw = string.Empty;
this.FallbackType = configElement.ElementType;
configElement.OnValueChangedNotify += UpdateValueFromSource; configElement.OnValueChangedNotify += UpdateValueFromSource;
} }

View File

@ -61,6 +61,7 @@ namespace UnityExplorer.CacheObject
var kvpCell = cell as CacheKeyValuePairCell; var kvpCell = cell as CacheKeyValuePairCell;
kvpCell.NameLabel.text = $"{DictIndex}:"; kvpCell.NameLabel.text = $"{DictIndex}:";
kvpCell.HiddenNameLabel.Text = "";
kvpCell.Image.color = DictIndex % 2 == 0 ? CacheListEntryCell.EvenColor : CacheListEntryCell.OddColor; kvpCell.Image.color = DictIndex % 2 == 0 ? CacheListEntryCell.EvenColor : CacheListEntryCell.OddColor;
if (KeyInputWanted) if (KeyInputWanted)

View File

@ -28,6 +28,7 @@ namespace UnityExplorer.CacheObject
var listCell = cell as CacheListEntryCell; var listCell = cell as CacheListEntryCell;
listCell.NameLabel.text = $"{ListIndex}:"; listCell.NameLabel.text = $"{ListIndex}:";
listCell.HiddenNameLabel.Text = "";
listCell.Image.color = ListIndex % 2 == 0 ? CacheListEntryCell.EvenColor : CacheListEntryCell.OddColor; listCell.Image.color = ListIndex % 2 == 0 ? CacheListEntryCell.EvenColor : CacheListEntryCell.OddColor;
} }

View File

@ -34,6 +34,7 @@ namespace UnityExplorer.CacheObject
this.Owner = inspector; this.Owner = inspector;
this.NameLabelText = SignatureHighlighter.Parse(member.DeclaringType, false, member); this.NameLabelText = SignatureHighlighter.Parse(member.DeclaringType, false, member);
this.NameForFiltering = $"{member.DeclaringType.Name}.{member.Name}"; this.NameForFiltering = $"{member.DeclaringType.Name}.{member.Name}";
this.NameLabelTextRaw = NameForFiltering;
} }
public override void ReleasePooledObjects() public override void ReleasePooledObjects()

View File

@ -30,15 +30,14 @@ namespace UnityExplorer.CacheObject
try try
{ {
var methodInfo = MethodInfo; var methodInfo = MethodInfo;
if (methodInfo.IsGenericMethod) if (methodInfo.IsGenericMethod)
methodInfo = MethodInfo.MakeGenericMethod(Evaluator.TryParseGenericArguments()); methodInfo = MethodInfo.MakeGenericMethod(Evaluator.TryParseGenericArguments());
if (Arguments.Length > 0) object ret;
return methodInfo.Invoke(DeclaringInstance, Evaluator.TryParseArguments()); if (HasArguments)
ret = methodInfo.Invoke(DeclaringInstance, Evaluator.TryParseArguments());
var ret = methodInfo.Invoke(DeclaringInstance, ArgumentUtility.EmptyArgs); else
ret = methodInfo.Invoke(DeclaringInstance, ArgumentUtility.EmptyArgs);
HadException = false; HadException = false;
LastException = null; LastException = null;
return ret; return ret;

View File

@ -47,6 +47,7 @@ namespace UnityExplorer.CacheObject
public bool SubContentShowWanted { get; private set; } public bool SubContentShowWanted { get; private set; }
public string NameLabelText { get; protected set; } public string NameLabelText { get; protected set; }
public string NameLabelTextRaw { get; protected set; }
public string ValueLabelText { get; protected set; } public string ValueLabelText { get; protected set; }
public abstract bool ShouldAutoEvaluate { get; } public abstract bool ShouldAutoEvaluate { get; }
@ -260,6 +261,8 @@ namespace UnityExplorer.CacheObject
public virtual void SetDataToCell(CacheObjectCell cell) public virtual void SetDataToCell(CacheObjectCell cell)
{ {
cell.NameLabel.text = NameLabelText; cell.NameLabel.text = NameLabelText;
if (cell.HiddenNameLabel != null)
cell.HiddenNameLabel.Text = NameLabelTextRaw;
cell.ValueLabel.gameObject.SetActive(true); cell.ValueLabel.gameObject.SetActive(true);
cell.SubContentHolder.gameObject.SetActive(SubContentShowWanted); cell.SubContentHolder.gameObject.SetActive(SubContentShowWanted);

View File

@ -45,6 +45,7 @@ namespace UnityExplorer.CacheObject.Views
public LayoutElement RightGroupLayout; public LayoutElement RightGroupLayout;
public Text NameLabel; public Text NameLabel;
public InputFieldRef HiddenNameLabel;
public Text TypeLabel; public Text TypeLabel;
public Text ValueLabel; public Text ValueLabel;
public Toggle Toggle; public Toggle Toggle;
@ -116,8 +117,19 @@ namespace UnityExplorer.CacheObject.Views
NameLabel = UIFactory.CreateLabel(horiRow, "NameLabel", "<notset>", TextAnchor.MiddleLeft); NameLabel = UIFactory.CreateLabel(horiRow, "NameLabel", "<notset>", TextAnchor.MiddleLeft);
NameLabel.horizontalOverflow = HorizontalWrapMode.Wrap; NameLabel.horizontalOverflow = HorizontalWrapMode.Wrap;
UIFactory.SetLayoutElement(NameLabel.gameObject, minHeight: 25, minWidth: 20, flexibleHeight: 300, flexibleWidth: 0); NameLayout = UIFactory.SetLayoutElement(NameLabel.gameObject, minHeight: 25, minWidth: 20, flexibleHeight: 300, flexibleWidth: 0);
NameLayout = NameLabel.GetComponent<LayoutElement>(); UIFactory.SetLayoutGroup<VerticalLayoutGroup>(NameLabel.gameObject, true, true, true, true);
HiddenNameLabel = UIFactory.CreateInputField(NameLabel.gameObject, "HiddenNameLabel", "");
var hiddenRect = HiddenNameLabel.Component.GetComponent<RectTransform>();
hiddenRect.anchorMin = Vector2.zero;
hiddenRect.anchorMax = Vector2.one;
HiddenNameLabel.Component.readOnly = true;
HiddenNameLabel.Component.lineType = UnityEngine.UI.InputField.LineType.MultiLineNewline;
HiddenNameLabel.Component.textComponent.horizontalOverflow = HorizontalWrapMode.Wrap;
HiddenNameLabel.Component.gameObject.GetComponent<Image>().color = Color.clear;
HiddenNameLabel.Component.textComponent.color = Color.clear;
UIFactory.SetLayoutElement(HiddenNameLabel.Component.gameObject, minHeight: 25, minWidth: 20, flexibleHeight: 300, flexibleWidth: 0);
// Right vertical group // Right vertical group

View File

@ -1,4 +1,5 @@
using System; using HarmonyLib;
using System;
using System.Collections; using System.Collections;
using UnityEngine; using UnityEngine;
using UnityEngine.EventSystems; using UnityEngine.EventSystems;
@ -6,8 +7,6 @@ using UnityExplorer.Core;
using UnityExplorer.Core.Config; using UnityExplorer.Core.Config;
using UnityExplorer.Core.Input; using UnityExplorer.Core.Input;
using UnityExplorer.UI; using UnityExplorer.UI;
using BF = System.Reflection.BindingFlags;
namespace UnityExplorer.Core.Input namespace UnityExplorer.Core.Input
{ {
@ -149,18 +148,97 @@ namespace UnityExplorer.Core.Input
// Patches // Patches
private static void SetupPatches() public static void SetupPatches()
{ {
try try
{ {
ExplorerCore.Loader.SetupCursorPatches(); PrefixPropertySetter(typeof(Cursor),
"lockState",
new HarmonyMethod(typeof(CursorUnlocker).GetMethod(nameof(CursorUnlocker.Prefix_set_lockState))));
PrefixPropertySetter(typeof(Cursor),
"visible",
new HarmonyMethod(typeof(CursorUnlocker).GetMethod(nameof(CursorUnlocker.Prefix_set_visible))));
PrefixPropertySetter(typeof(EventSystem),
"current",
new HarmonyMethod(typeof(CursorUnlocker).GetMethod(nameof(CursorUnlocker.Prefix_EventSystem_set_current))));
PrefixMethod(typeof(EventSystem),
"SetSelectedGameObject",
// some games use a modified version of uGUI that includes this extra int argument on this method.
new Type[] { typeof(GameObject), typeof(BaseEventData), typeof(int) },
new HarmonyMethod(typeof(CursorUnlocker).GetMethod(nameof(CursorUnlocker.Prefix_EventSystem_SetSelectedGameObject))),
// most games use these arguments, we'll use them as our "backup".
new Type[] { typeof(GameObject), typeof(BaseEventData) });
//// Not sure if this one is needed.
//PrefixMethod(typeof(PointerInputModule),
// "ClearSelection",
// new Type[0],
// new HarmonyMethod(typeof(CursorUnlocker).GetMethod(nameof(CursorUnlocker.Prefix_PointerInputModule_ClearSelection))));
}
catch (Exception ex)
{
ExplorerCore.Log($"Exception setting up Harmony patches:\r\n{ex.ReflectionExToString()}");
}
}
private static void PrefixMethod(Type type, string method, Type[] arguments, HarmonyMethod prefix, Type[] backupArgs = null)
{
try
{
var methodInfo = type.GetMethod(method, ReflectionUtility.FLAGS, null, arguments, null);
if (methodInfo == null)
{
if (backupArgs != null)
methodInfo = type.GetMethod(method, ReflectionUtility.FLAGS, null, backupArgs, null);
if (methodInfo == null)
throw new MissingMethodException($"Could not find method for patching - '{type.FullName}.{method}'!");
}
var processor = ExplorerCore.Harmony.CreateProcessor(methodInfo);
processor.AddPrefix(prefix);
processor.Patch();
} }
catch (Exception e) catch (Exception e)
{ {
ExplorerCore.Log($"Exception setting up Cursor patches: {e.GetType()}, {e.Message}"); ExplorerCore.LogWarning($"Unable to patch {type.Name}.{method}: {e.Message}");
} }
} }
private static void PrefixPropertySetter(Type type, string property, HarmonyMethod prefix)
{
try
{
var processor = ExplorerCore.Harmony.CreateProcessor(type.GetProperty(property, ReflectionUtility.FLAGS).GetSetMethod());
processor.AddPrefix(prefix);
processor.Patch();
}
catch (Exception e)
{
ExplorerCore.Log($"Unable to patch {type.Name}.set_{property}: {e.Message}");
}
}
// Prevent setting non-UnityExplorer objects as selected when menu is open
public static bool Prefix_EventSystem_SetSelectedGameObject(GameObject __0)
{
if (!UIManager.ShowMenu || !UIManager.CanvasRoot)
return true;
return __0 && __0.transform.root.gameObject.GetInstanceID() == UIManager.CanvasRoot.GetInstanceID();
}
//public static bool Prefix_PointerInputModule_ClearSelection()
//{
// return !(UIManager.ShowMenu && UIManager.CanvasRoot);
//}
// Force EventSystem.current to be UnityExplorer's when menu is open
public static void Prefix_EventSystem_set_current(ref EventSystem value) public static void Prefix_EventSystem_set_current(ref EventSystem value)
{ {
if (!settingEventSystem && value) if (!settingEventSystem && value)

View File

@ -134,6 +134,9 @@ namespace UnityExplorer
var type = obj.GetType(); var type = obj.GetType();
try try
{ {
if (type.IsGenericType)
return type;
if (IsString(obj)) if (IsString(obj))
return typeof(string); return typeof(string);
@ -178,7 +181,8 @@ namespace UnityExplorer
if (fullname.StartsWith("System.")) if (fullname.StartsWith("System."))
fullname = $"Il2Cpp{fullname}"; fullname = $"Il2Cpp{fullname}";
AllTypes.TryGetValue(fullname, out Type monoType); if (!AllTypes.TryGetValue(fullname, out Type monoType))
ExplorerCore.LogWarning($"Failed to get type by name '{fullname}'!");
return monoType; return monoType;
} }
@ -477,59 +481,38 @@ namespace UnityExplorer
#region Force-loading game modules #region Force-loading game modules
internal static string UnhollowedFolderPath => Path.GetFullPath(
#if ML
Path.Combine("MelonLoader", "Managed")
#elif BIE
Path.Combine(BepInEx.Paths.BepInExRootPath, "unhollowed")
#else
Path.Combine(ExplorerCore.Loader.ExplorerFolder, "Modules")
#endif
);
// Helper for IL2CPP to try to make sure the Unhollowed game assemblies are actually loaded. // Helper for IL2CPP to try to make sure the Unhollowed game assemblies are actually loaded.
// Force loading all il2cpp modules // Force loading all il2cpp modules
internal void TryLoadGameModules() internal void TryLoadGameModules()
{ {
if (Directory.Exists(UnhollowedFolderPath)) var dir = ExplorerCore.Loader.UnhollowedModulesFolder;
if (Directory.Exists(dir))
{ {
var files = Directory.GetFiles(UnhollowedFolderPath); foreach (var filePath in Directory.GetFiles(dir, "*.dll"))
foreach (var filePath in files) DoLoadModule(filePath);
{
try
{
DoLoadModule(filePath, true);
}
catch //(Exception ex)
{
//ExplorerCore.LogWarning($"Failed to force-load module '{name}': {ex.ReflectionExToString()}");
}
}
} }
else else
ExplorerCore.LogWarning($"Expected Unhollowed folder path does not exist: '{UnhollowedFolderPath}'"); ExplorerCore.LogWarning($"Expected Unhollowed folder path does not exist: '{dir}'. " +
$"If you are using the standalone release, you can specify the Unhollowed modules path when you call CreateInstance().");
} }
internal bool DoLoadModule(string fullPath, bool suppressWarning = false) internal bool DoLoadModule(string fullPath)
{ {
if (!File.Exists(fullPath)) if (string.IsNullOrEmpty(fullPath) || !File.Exists(fullPath))
return false; return false;
try try
{ {
Assembly.LoadFile(fullPath); Assembly.LoadFile(fullPath);
//Assembly.Load(File.ReadAllBytes(fullPath));
return true; return true;
} }
catch (Exception e) catch //(Exception e)
{ {
if (!suppressWarning) //ExplorerCore.LogWarning($"Failed loading module '{Path.GetFileName(fullPath)}'! {e.ReflectionExToString()}");
Console.WriteLine($"Failed loading module '{Path.GetFileName(fullPath)}'! {e.ReflectionExToString()}"); return false;
} }
return false;
} }
#endregion #endregion

View File

@ -0,0 +1,57 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using HarmonyLib;
namespace UnityExplorer
{
public static class ReflectionPatches
{
public static void Init()
{
try
{
var method = typeof(Assembly).GetMethod(nameof(Assembly.GetTypes), new Type[0]);
var processor = ExplorerCore.Harmony.CreateProcessor(method);
processor.AddFinalizer(typeof(ReflectionPatches).GetMethod(nameof(Assembly_GetTypes)));
processor.Patch();
}
catch (Exception ex)
{
ExplorerCore.LogWarning($"Exception setting up Reflection patch: {ex}");
}
}
private static readonly Type[] emptyTypes = new Type[0];
public static Exception Assembly_GetTypes(Assembly __instance, Exception __exception, ref Type[] __result)
{
if (__exception != null)
{
try
{
__result = __instance.GetExportedTypes();
}
catch (ReflectionTypeLoadException e)
{
try
{
__result = e.Types.Where(it => it != null).ToArray();
}
catch
{
__result = emptyTypes;
}
}
catch
{
__result = emptyTypes;
}
}
return null;
}
}
}

View File

@ -27,6 +27,8 @@ namespace UnityExplorer
new ReflectionUtility(); new ReflectionUtility();
#endif #endif
Instance.Initialize(); Instance.Initialize();
ReflectionPatches.Init();
} }
protected virtual void Initialize() protected virtual void Initialize()

View File

@ -32,16 +32,6 @@ namespace UnityExplorer
return new AssetBundle(ptr); return new AssetBundle(ptr);
} }
// static void UnloadAllAssetBundles(bool unloadAllObjects);
internal delegate void d_UnloadAllAssetBundles(bool unloadAllObjects);
public static void UnloadAllAssetBundles(bool unloadAllObjects)
{
var iCall = ICallManager.GetICall<d_UnloadAllAssetBundles>("UnityEngine.AssetBundle::UnloadAllAssetBundles");
iCall.Invoke(unloadAllObjects);
}
// ~~~~~~~~~~~~ Instance ~~~~~~~~~~~~ // ~~~~~~~~~~~~ Instance ~~~~~~~~~~~~
private readonly IntPtr m_bundlePtr = IntPtr.Zero; private readonly IntPtr m_bundlePtr = IntPtr.Zero;
@ -78,7 +68,8 @@ namespace UnityExplorer
return new UnityEngine.Object(ptr).TryCast<T>(); return new UnityEngine.Object(ptr).TryCast<T>();
} }
// public extern void Unload(bool unloadAllLoadedObjects); // Unload(bool unloadAllLoadedObjects);
internal delegate void d_Unload(IntPtr _this, bool unloadAllLoadedObjects); internal delegate void d_Unload(IntPtr _this, bool unloadAllLoadedObjects);
public void Unload(bool unloadAssets = true) public void Unload(bool unloadAssets = true)

View File

@ -7,7 +7,6 @@ using System.Runtime.InteropServices;
namespace UnityExplorer.Core.Runtime.Il2Cpp namespace UnityExplorer.Core.Runtime.Il2Cpp
{ {
[SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "External methods")]
public static class ICallManager public static class ICallManager
{ {
[DllImport("GameAssembly", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] [DllImport("GameAssembly", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]

View File

@ -6,8 +6,8 @@ using System.Linq;
using UnhollowerBaseLib; using UnhollowerBaseLib;
using UnityEngine; using UnityEngine;
// CREDIT HerpDerpenstine // Credit to HerpDerpenstine and knah
// https://github.com/LavaGang/MelonLoader/blob/master/MelonLoader.Support.Il2Cpp/MelonCoroutines.cs // https://github.com/LavaGang/MelonLoader/blob/master/SM_Il2Cpp/Coroutines.cs
namespace UnityExplorer.Core.Runtime.Il2Cpp namespace UnityExplorer.Core.Runtime.Il2Cpp
{ {

View File

@ -73,6 +73,7 @@ namespace UnityExplorer.Core.Runtime.Il2Cpp
return ScriptableObject.CreateInstance(Il2CppType.From(type)); return ScriptableObject.CreateInstance(Il2CppType.From(type));
} }
// Pretty disgusting but couldn't figure out a cleaner way yet unfortunately
public override void GraphicRaycast(GraphicRaycaster raycaster, PointerEventData data, List<RaycastResult> list) public override void GraphicRaycast(GraphicRaycaster raycaster, PointerEventData data, List<RaycastResult> list)
{ {
var il2cppList = new Il2CppSystem.Collections.Generic.List<RaycastResult>(); var il2cppList = new Il2CppSystem.Collections.Generic.List<RaycastResult>();
@ -97,15 +98,17 @@ namespace UnityExplorer.Core.Runtime.Il2Cpp
internal delegate IntPtr d_FindObjectsOfTypeAll(IntPtr type); internal delegate IntPtr d_FindObjectsOfTypeAll(IntPtr type);
internal static readonly string[] findObjectsOfTypeAllSignatures = new[]
{
"UnityEngine.Resources::FindObjectsOfTypeAll",
"UnityEngine.ResourcesAPIInternal::FindObjectsOfTypeAll" // Unity 2020+ updated to this
};
public override UnityEngine.Object[] FindObjectsOfTypeAll(Type type) public override UnityEngine.Object[] FindObjectsOfTypeAll(Type type)
{ {
var iCall = ICallManager.GetICallUnreliable<d_FindObjectsOfTypeAll>(new[] return new Il2CppReferenceArray<UnityEngine.Object>(
{ ICallManager.GetICallUnreliable<d_FindObjectsOfTypeAll>(findObjectsOfTypeAllSignatures)
"UnityEngine.Resources::FindObjectsOfTypeAll", .Invoke(Il2CppType.From(type).Pointer));
"UnityEngine.ResourcesAPIInternal::FindObjectsOfTypeAll" // Unity 2020+ updated to this
});
return new Il2CppReferenceArray<UnityEngine.Object>(iCall.Invoke(Il2CppType.From(type).Pointer));
} }
// Scene.GetRootGameObjects(); // Scene.GetRootGameObjects();
@ -117,22 +120,17 @@ namespace UnityExplorer.Core.Runtime.Il2Cpp
if (!scene.isLoaded) if (!scene.isLoaded)
return new GameObject[0]; return new GameObject[0];
int handle = scene.handle; if (scene.handle == -1)
if (handle == -1)
return new GameObject[0]; return new GameObject[0];
int count = GetRootCount(handle); int count = GetRootCount(scene.handle);
if (count < 1) if (count < 1)
return new GameObject[0]; return new GameObject[0];
var list = new Il2CppSystem.Collections.Generic.List<GameObject>(count); var list = new Il2CppSystem.Collections.Generic.List<GameObject>(count);
var iCall = ICallManager.GetICall<d_GetRootGameObjects>("UnityEngine.SceneManagement.Scene::GetRootGameObjectsInternal"); var iCall = ICallManager.GetICall<d_GetRootGameObjects>("UnityEngine.SceneManagement.Scene::GetRootGameObjectsInternal");
iCall.Invoke(scene.handle, list.Pointer);
iCall.Invoke(handle, list.Pointer);
return list.ToArray(); return list.ToArray();
} }

View File

@ -38,19 +38,6 @@ namespace UnityExplorer.Core.Runtime.Il2Cpp
return new Il2CppStructArray<byte>(ptr); return new Il2CppStructArray<byte>(ptr);
} }
// bool ImageConversion.LoadImage(this Texture2D tex, byte[] data, bool markNonReadable);
internal delegate bool d_LoadImage(IntPtr tex, IntPtr data, bool markNonReadable);
public override bool LoadImage(Texture2D tex, byte[] data, bool markNonReadable)
{
var il2cppArray = (Il2CppStructArray<byte>)data;
var iCall = ICallManager.GetICall<d_LoadImage>("UnityEngine.ImageConversion::LoadImage");
return iCall.Invoke(tex.Pointer, il2cppArray.Pointer, markNonReadable);
}
// Sprite Sprite.Create // Sprite Sprite.Create
public override Sprite CreateSprite(Texture2D texture) public override Sprite CreateSprite(Texture2D texture)

View File

@ -10,6 +10,7 @@ using UnityEngine.Events;
using UnityEngine.EventSystems; using UnityEngine.EventSystems;
using UnityEngine.SceneManagement; using UnityEngine.SceneManagement;
using UnityEngine.UI; using UnityEngine.UI;
using UnityExplorer;
namespace UnityExplorer.Core.Runtime.Mono namespace UnityExplorer.Core.Runtime.Mono
{ {
@ -18,7 +19,6 @@ namespace UnityExplorer.Core.Runtime.Mono
public override void Initialize() public override void Initialize()
{ {
ExplorerCore.Context = RuntimeContext.Mono; ExplorerCore.Context = RuntimeContext.Mono;
//Reflection = new MonoReflection();
TextureUtil = new MonoTextureUtil(); TextureUtil = new MonoTextureUtil();
} }
@ -28,60 +28,35 @@ namespace UnityExplorer.Core.Runtime.Mono
} }
private void Application_logMessageReceived(string condition, string stackTrace, LogType type) private void Application_logMessageReceived(string condition, string stackTrace, LogType type)
{ => ExplorerCore.LogUnity(condition, type);
ExplorerCore.LogUnity(condition, type);
}
public override void StartCoroutine(IEnumerator routine) public override void StartCoroutine(IEnumerator routine)
{ => ExplorerBehaviour.Instance.StartCoroutine(routine);
ExplorerBehaviour.Instance.StartCoroutine(routine);
}
public override void Update() public override void Update()
{ {
} }
public override T AddComponent<T>(GameObject obj, Type type) public override T AddComponent<T>(GameObject obj, Type type)
{ => (T)obj.AddComponent(type);
return (T)obj.AddComponent(type);
}
public override ScriptableObject CreateScriptable(Type type) public override ScriptableObject CreateScriptable(Type type)
{ => ScriptableObject.CreateInstance(type);
return ScriptableObject.CreateInstance(type);
}
public override void GraphicRaycast(GraphicRaycaster raycaster, PointerEventData data, List<RaycastResult> list) public override void GraphicRaycast(GraphicRaycaster raycaster, PointerEventData data, List<RaycastResult> list)
{ => raycaster.Raycast(data, list);
raycaster.Raycast(data, list);
}
public override string LayerToName(int layer) public override string LayerToName(int layer)
=> LayerMask.LayerToName(layer); => LayerMask.LayerToName(layer);
public override UnityEngine.Object[] FindObjectsOfTypeAll(Type type) public override UnityEngine.Object[] FindObjectsOfTypeAll(Type type)
=> Resources.FindObjectsOfTypeAll(type); => Resources.FindObjectsOfTypeAll(type);
//private static readonly FieldInfo fi_Scene_handle = typeof(Scene).GetField("m_Handle", ReflectionUtility.AllFlags); public override GameObject[] GetRootGameObjects(Scene scene)
=> scene.isLoaded ? scene.GetRootGameObjects() : new GameObject[0];
//public override int GetSceneHandle(Scene scene) public override int GetRootCount(Scene scene)
//{ => scene.rootCount;
// return (int)fi_Scene_handle.GetValue(scene);
//}
public override GameObject[] GetRootGameObjects(Scene scene)
{
if (!scene.isLoaded)
return new GameObject[0];
return scene.GetRootGameObjects();
}
public override int GetRootCount(Scene scene)
{
return scene.rootCount;
}
public override void SetColorBlock(Selectable selectable, Color? normal = null, Color? highlighted = null, Color? pressed = null, public override void SetColorBlock(Selectable selectable, Color? normal = null, Color? highlighted = null, Color? pressed = null,
Color? disabled = null) Color? disabled = null)
@ -103,59 +78,42 @@ namespace UnityExplorer.Core.Runtime.Mono
SetColorBlock(selectable, colors); SetColorBlock(selectable, colors);
} }
public override void SetColorBlock(Selectable selectable, ColorBlock colors) public override void SetColorBlock(Selectable selectable, ColorBlock colors)
{ => selectable.colors = colors;
selectable.colors = colors;
}
} }
} }
public static class MonoExtensions public static class MonoExtensions
{ {
// Helpers to use the same style of AddListener that IL2CPP uses.
public static void AddListener(this UnityEvent _event, Action listener) public static void AddListener(this UnityEvent _event, Action listener)
{ => _event.AddListener(new UnityAction(listener));
_event.AddListener(new UnityAction(listener));
}
public static void AddListener<T>(this UnityEvent<T> _event, Action<T> listener) public static void AddListener<T>(this UnityEvent<T> _event, Action<T> listener)
{ => _event.AddListener(new UnityAction<T>(listener));
_event.AddListener(new UnityAction<T>(listener));
}
public static void RemoveListener(this UnityEvent _event, Action listener) public static void RemoveListener(this UnityEvent _event, Action listener)
{ => _event.RemoveListener(new UnityAction(listener));
_event.RemoveListener(new UnityAction(listener));
}
public static void RemoveListener<T>(this UnityEvent<T> _event, Action<T> listener) public static void RemoveListener<T>(this UnityEvent<T> _event, Action<T> listener)
{ => _event.RemoveListener(new UnityAction<T>(listener));
_event.RemoveListener(new UnityAction<T>(listener));
}
public static void Clear(this StringBuilder sb) // Doesn't exist in NET 3.5
{
sb.Remove(0, sb.Length);
}
private static PropertyInfo pi_childControlHeight; public static void Clear(this StringBuilder sb)
=> sb.Remove(0, sb.Length);
// These properties don't exist in some earlier games, so null check before trying to set them.
public static void SetChildControlHeight(this HorizontalOrVerticalLayoutGroup group, bool value) public static void SetChildControlHeight(this HorizontalOrVerticalLayoutGroup group, bool value)
{ => ReflectionUtility.GetPropertyInfo(typeof(HorizontalOrVerticalLayoutGroup), "childControlHeight")
if (pi_childControlHeight == null) ?.SetValue(group, value, null);
pi_childControlHeight = group.GetType().GetProperty("childControlHeight");
pi_childControlHeight?.SetValue(group, value, null);
}
private static PropertyInfo pi_childControlWidth;
public static void SetChildControlWidth(this HorizontalOrVerticalLayoutGroup group, bool value) public static void SetChildControlWidth(this HorizontalOrVerticalLayoutGroup group, bool value)
{ => ReflectionUtility.GetPropertyInfo(typeof(HorizontalOrVerticalLayoutGroup), "childControlWidth")
if (pi_childControlWidth == null) ?.SetValue(group, value, null);
pi_childControlWidth = group.GetType().GetProperty("childControlWidth");
pi_childControlWidth?.SetValue(group, value, null);
}
} }
#endif #endif

View File

@ -12,41 +12,28 @@ namespace UnityExplorer.Core.Runtime.Mono
public class MonoTextureUtil : TextureUtilProvider public class MonoTextureUtil : TextureUtilProvider
{ {
public override void Blit(Texture2D tex, RenderTexture rt) public override void Blit(Texture2D tex, RenderTexture rt)
{ => Graphics.Blit(tex, rt);
Graphics.Blit(tex, rt);
}
public override Sprite CreateSprite(Texture2D texture) public override Sprite CreateSprite(Texture2D texture)
{ => Sprite.Create(texture, new Rect(0, 0, texture.width, texture.height), Vector2.zero);
return Sprite.Create(texture, new Rect(0, 0, texture.width, texture.height), Vector2.zero);
}
public override bool LoadImage(Texture2D tex, byte[] data, bool markNonReadable) //public override bool LoadImage(Texture2D tex, byte[] data, bool markNonReadable)
{ // => tex.LoadImage(data, markNonReadable);
return tex.LoadImage(data, markNonReadable);
}
public override Texture2D NewTexture2D(int width, int height) public override Texture2D NewTexture2D(int width, int height)
{ => new Texture2D(width, height);
return new Texture2D(width, height);
}
public override byte[] EncodeToPNG(Texture2D tex) public override byte[] EncodeToPNG(Texture2D tex)
{ => EncodeToPNGSafe(tex);
return EncodeToPNGSafe(tex);
}
private static MethodInfo EncodeToPNGMethod => m_encodeToPNGMethod ?? GetEncodeToPNGMethod(); private static MethodInfo EncodeToPNGMethod => m_encodeToPNGMethod ?? GetEncodeToPNGMethod();
private static MethodInfo m_encodeToPNGMethod; private static MethodInfo m_encodeToPNGMethod;
public static byte[] EncodeToPNGSafe(Texture2D tex) public static byte[] EncodeToPNGSafe(Texture2D tex)
{ {
var method = EncodeToPNGMethod; return EncodeToPNGMethod.IsStatic
? (byte[])EncodeToPNGMethod.Invoke(null, new object[] { tex })
if (method.IsStatic) : (byte[])EncodeToPNGMethod.Invoke(tex, ArgumentUtility.EmptyArgs);
return (byte[])method.Invoke(null, new object[] { tex });
else
return (byte[])method.Invoke(tex, ArgumentUtility.EmptyArgs);
} }
private static MethodInfo GetEncodeToPNGMethod() private static MethodInfo GetEncodeToPNGMethod()

View File

@ -40,8 +40,6 @@ namespace UnityExplorer
public abstract void Update(); public abstract void Update();
//public virtual bool IsReferenceEqual(object a, object b) => ReferenceEquals(a, b);
// Unity API handlers // Unity API handlers
public abstract T AddComponent<T>(GameObject obj, Type type) where T : Component; public abstract T AddComponent<T>(GameObject obj, Type type) where T : Component;
@ -54,8 +52,6 @@ namespace UnityExplorer
public abstract void GraphicRaycast(GraphicRaycaster raycaster, PointerEventData data, List<RaycastResult> list); public abstract void GraphicRaycast(GraphicRaycaster raycaster, PointerEventData data, List<RaycastResult> list);
//public abstract int GetSceneHandle(Scene scene);
public abstract GameObject[] GetRootGameObjects(Scene scene); public abstract GameObject[] GetRootGameObjects(Scene scene);
public abstract int GetRootCount(Scene scene); public abstract int GetRootCount(Scene scene);

View File

@ -22,7 +22,7 @@ namespace UnityExplorer.Core.Runtime
public abstract void Blit(Texture2D tex, RenderTexture rt); public abstract void Blit(Texture2D tex, RenderTexture rt);
public abstract bool LoadImage(Texture2D tex, byte[] data, bool markNonReadable); //public abstract bool LoadImage(Texture2D tex, byte[] data, bool markNonReadable);
public abstract Sprite CreateSprite(Texture2D texture); public abstract Sprite CreateSprite(Texture2D texture);
@ -43,27 +43,22 @@ namespace UnityExplorer.Core.Runtime
} }
} }
public static bool LoadImage(Texture2D tex, string filePath, bool markNonReadable) //public static bool LoadImage(Texture2D tex, string filePath, bool markNonReadable)
{ //{
if (!File.Exists(filePath)) // if (!File.Exists(filePath))
return false; // return false;
//
return Instance.LoadImage(tex, File.ReadAllBytes(filePath), markNonReadable); // return Instance.LoadImage(tex, File.ReadAllBytes(filePath), markNonReadable);
} //}
public static Texture2D Copy(Texture2D orig, Rect rect) public static Texture2D Copy(Texture2D orig, Rect rect)
{ {
Color[] pixels;
if (!IsReadable(orig)) if (!IsReadable(orig))
orig = ForceReadTexture(orig); orig = ForceReadTexture(orig);
pixels = orig.GetPixels((int)rect.x, (int)rect.y, (int)rect.width, (int)rect.height); Color[] pixels = orig.GetPixels((int)rect.x, (int)rect.y, (int)rect.width, (int)rect.height);
Texture2D newTex = Instance.NewTexture2D((int)rect.width, (int)rect.height); Texture2D newTex = Instance.NewTexture2D((int)rect.width, (int)rect.height);
newTex.SetPixels(pixels); newTex.SetPixels(pixels);
return newTex; return newTex;
} }
@ -92,7 +87,7 @@ namespace UnityExplorer.Core.Runtime
} }
catch (Exception e) catch (Exception e)
{ {
ExplorerCore.Log("Exception on ForceReadTexture: " + e.ToString()); ExplorerCore.Log($"Exception on ForceReadTexture: {e.ToString()}");
return default; return default;
} }
} }
@ -103,13 +98,11 @@ namespace UnityExplorer.Core.Runtime
Directory.CreateDirectory(dir); Directory.CreateDirectory(dir);
byte[] data; byte[] data;
string savepath = dir + @"\" + name + ".png"; string savepath = $@"{dir}\{name}.png";
// Make sure we can EncodeToPNG it. // Make sure we can EncodeToPNG it.
if (tex.format != TextureFormat.ARGB32 || !IsReadable(tex)) if (tex.format != TextureFormat.ARGB32 || !IsReadable(tex))
{
tex = ForceReadTexture(tex); tex = ForceReadTexture(tex);
}
if (isDTXnmNormal) if (isDTXnmNormal)
{ {
@ -120,13 +113,9 @@ namespace UnityExplorer.Core.Runtime
data = Instance.EncodeToPNG(tex); data = Instance.EncodeToPNG(tex);
if (data == null || !data.Any()) if (data == null || !data.Any())
{
ExplorerCore.LogWarning("Couldn't get any data for the texture!"); ExplorerCore.LogWarning("Couldn't get any data for the texture!");
}
else else
{
File.WriteAllBytes(savepath, data); File.WriteAllBytes(savepath, data);
}
} }
// Converts DTXnm-format Normal Map to RGBA-format Normal Map. // Converts DTXnm-format Normal Map to RGBA-format Normal Map.

View File

@ -14,112 +14,31 @@ using UnhollowerBaseLib;
namespace UnityExplorer.Tests namespace UnityExplorer.Tests
{ {
public class TestIndexer : IList<int>
{
private readonly List<int> list = new List<int>() { 1, 2, 3, 4, 5 };
public int Count => list.Count;
public bool IsReadOnly => false;
int IList<int>.this[int index]
{
get => list[index];
set => list[index] = value;
}
public int IndexOf(int item) => list.IndexOf(item);
public bool Contains(int item) => list.Contains(item);
public void Add(int item) => list.Add(item);
public void Insert(int index, int item) => list.Insert(index, item);
public bool Remove(int item) => list.Remove(item);
public void RemoveAt(int index) => list.RemoveAt(index);
public void Clear() => list.Clear();
public void CopyTo(int[] array, int arrayIndex) => list.CopyTo(array, arrayIndex);
public IEnumerator<int> GetEnumerator() => list.GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() => list.GetEnumerator();
}
public static class TestClass public static class TestClass
{ {
public static readonly TestIndexer AAAAATest = new TestIndexer(); static TestClass()
public static void ATestMethod(string s, float f, Vector3 vector, DateTime date, Quaternion quater, bool b, CameraClearFlags enumvalue)
{ {
ExplorerCore.Log($"{s}, {f}, {vector.ToString()}, {date}, {quater.eulerAngles.ToString()}, {b}, {enumvalue}"); Init_Mono();
#if CPP
Init_IL2CPP();
#endif
} }
public static List<int> AWritableList = new List<int> { 1, 2, 3, 4, 5 }; // Test enumerables
public static Dictionary<string, int> AWritableDict = new Dictionary<string, int> { { "one", 1 }, { "two", 2 } }; public static List<object> ListOfInts;
public static List<List<List<string>>> NestedList;
public static IEnumerable ANestedList = new List<List<List<string>>> public static IDictionary MixedDictionary;
{ public static Hashtable Hashtable;
new List<List<string>>
{
new List<string>
{
"one",
"two",
"one",
"two",
"one",
"two",
"one",
"two",
"one",
"two",
"one",
"two",
"one",
"two",
"one",
"two",
},
new List<string>
{
"three",
"four",
}
},
new List<List<string>>
{
new List<string>
{
"five"
}
}
};
public static IDictionary ARandomDictionary = new Dictionary<object, object>
{
{ 1, 2 },
{ "one", "two" },
{ true, false },
{ new Vector3(0,1,2), new Vector3(1,2,3) },
{ CameraClearFlags.Depth, CameraClearFlags.Color },
{ "################################################\r\n##########", null },
{ "subdict", new Dictionary<object,object> { { "key", "value" } } }
};
public static Hashtable TestHashtable = new Hashtable
{
{ "one", "value" },
{ "two", "value" },
{ "three", "value" },
};
public const int ConstantInt = 5;
public static Color AColor = Color.magenta;
public static Color32 AColor32 = Color.red;
public static byte[] ByteArray = new byte[16]; public static byte[] ByteArray = new byte[16];
public static string LongString = new string('#', 10000); public static List<short> ABigList = new List<short>(10000);
public static List<string> BigList = new List<string>(10000);
// Test const behaviour (should be a readonly field)
public const int ConstantInt5 = 5;
// Testing other InteractiveValues
public static Color Color = Color.magenta;
public static Color32 Color32 = Color.red;
public static string ALongString = new string('#', 10000);
public static List<object> RandomList public static List<object> RandomList
{ {
@ -133,25 +52,7 @@ namespace UnityExplorer.Tests
} }
} }
private static void TestGeneric<T>() // Test methods
{
ExplorerCore.Log("Test1 " + typeof(T).FullName);
}
private static void TestGenericClass<T>() where T : class
{
ExplorerCore.Log("Test2 " + typeof(T).FullName);
}
private static void TestComponent<T>() where T : Component
{
ExplorerCore.Log("Test3 " + typeof(T).FullName);
}
private static void TestStruct<T>() where T : struct
{
ExplorerCore.Log("Test3 " + typeof(T).FullName);
}
private static object GetRandomObject() private static object GetRandomObject()
{ {
@ -165,109 +66,133 @@ namespace UnityExplorer.Tests
case 2: return true; case 2: return true;
case 3: return "hello"; case 3: return "hello";
case 4: return 50.5f; case 4: return 50.5f;
case 5: return UnityEngine.CameraClearFlags.Color; case 5: return CameraClearFlags.Color;
case 6: return new List<string> { "sub list", "lol" }; case 6: return new List<string> { "one", "two" };
} }
return ret; return ret;
} }
public static void TestComponent<T>() where T : Component
{
ExplorerCore.Log($"Test3 {typeof(T).FullName}");
}
public static void TestArgumentParse(string s, int i, Color color, CameraClearFlags flags, Vector3 vector, Quaternion quaternion)
{
ExplorerCore.Log($"{s}, {i}, {color.ToString()}, {flags}, {vector.ToString()}, {quaternion.ToString()}");
}
private static void Init_Mono()
{
ExplorerCore.Log($"1: Basic list");
ListOfInts = new List<object> { 1, 2, 3, 4, 5 };
ExplorerCore.Log($"2: Nested list");
NestedList = new List<List<List<string>>>
{
new List<List<string>> {
new List<string> { "1", "2", "3" },
new List<string> { "4", "5", "6" },
},
new List<List<string>>
{
new List<string> { "7", "8", "9" }
}
};
ExplorerCore.Log($"3: Dictionary");
MixedDictionary = new Dictionary<object, object>
{
{ 1, 2 },
{ "one", "two" },
{ true, false },
{ new Vector3(0,1,2), new Vector3(1,2,3) },
{ CameraClearFlags.Depth, CameraClearFlags.Color },
{ "################################################\r\n##########", null },
{ "subdict", new Dictionary<object,object> { { "key", "value" } } }
};
ExplorerCore.Log($"4: Hashtable");
Hashtable = new Hashtable { { "One", 1 }, { "Two", 2 } };
ExplorerCore.Log($"5: Big list");
for (int i = 0; i < ABigList.Capacity; i++)
ABigList.Add((short)UnityEngine.Random.Range(0, short.MaxValue));
ExplorerCore.Log("Finished TestClass Init_Mono");
}
#if CPP #if CPP
public static Il2CppSystem.Collections.IList IL2CPP_IList;
public static Il2CppSystem.Collections.Generic.List<string> IL2CPP_ListString; public static Il2CppSystem.Collections.Generic.List<string> IL2CPP_ListString;
public static Il2CppSystem.Collections.Generic.HashSet<string> IL2CPP_HashSet;
public static Il2CppSystem.Collections.Generic.Dictionary<string, string> IL2CPP_Dict;
public static Il2CppSystem.Collections.Hashtable IL2CPP_HashTable;
public static Il2CppSystem.Collections.IDictionary IL2CPP_IDict;
public static string IL2CPP_systemString = "Test";
public static Il2CppSystem.Object IL2CPP_objectString = "string boxed as cpp object";
public static Il2CppSystem.String IL2CPP_il2cppString = "string boxed as cpp string";
public static string nullString = null;
public static List<Il2CppSystem.Object> IL2CPP_listOfBoxedObjects; public static List<Il2CppSystem.Object> IL2CPP_listOfBoxedObjects;
public static Il2CppStructArray<int> IL2CPP_structArray; public static Il2CppStructArray<int> IL2CPP_structArray;
public static Il2CppStringArray IL2CPP_stringArray;
public static Il2CppReferenceArray<Il2CppSystem.Object> IL2CPP_ReferenceArray; public static Il2CppReferenceArray<Il2CppSystem.Object> IL2CPP_ReferenceArray;
public static Il2CppSystem.Collections.IDictionary IL2CPP_IDict;
public static Il2CppSystem.Collections.IList IL2CPP_IList;
public static Dictionary<Il2CppSystem.String, Il2CppSystem.Object> CppBoxedDict;
public static Il2CppSystem.Collections.Generic.HashSet<string> IL2CPP_HashSet;
public static Il2CppSystem.Collections.Generic.Dictionary<string, string> IL2CPP_Dict;
public static Il2CppSystem.Collections.Hashtable IL2CPP_HashTable;
public static Il2CppSystem.Object cppBoxedInt; public static Il2CppSystem.Object cppBoxedInt;
public static Il2CppSystem.Int32 cppInt; public static Il2CppSystem.Int32 cppInt;
public static Il2CppSystem.Decimal cppDecimal; public static Il2CppSystem.Decimal cppDecimal;
public static Il2CppSystem.Object cppDecimalBoxed; public static Il2CppSystem.Object cppDecimalBoxed;
public static Il2CppSystem.Object cppVector3Boxed; public static Il2CppSystem.Object cppVector3Boxed;
public static string IL2CPP_systemString = "Test";
public static Il2CppSystem.Object IL2CPP_objectString = "string boxed as cpp object";
public static Il2CppSystem.String IL2CPP_il2cppString = "string boxed as cpp string";
public static string nullString = null;
public static Il2CppSystem.Object RandomBoxedColor private static void Init_IL2CPP()
{ {
get ExplorerCore.Log($"IL2CPP 1: Il2Cpp Dictionary<string, string>");
{
int ran = UnityEngine.Random.Range(0, 3);
switch (ran)
{
case 1: return new Color32().BoxIl2CppObject();
case 2: return Color.magenta.BoxIl2CppObject();
default:
return null;
}
}
}
public static Il2CppSystem.Collections.Hashtable cppHashset;
public static Dictionary<Il2CppSystem.String, Il2CppSystem.Object> CppBoxedDict;
#endif
static TestClass()
{
for (int i = 0; i < BigList.Capacity; i++)
BigList.Add(i.ToString());
#if CPP
IL2CPP_Dict = new Il2CppSystem.Collections.Generic.Dictionary<string, string>(); IL2CPP_Dict = new Il2CppSystem.Collections.Generic.Dictionary<string, string>();
IL2CPP_Dict.Add("key1", "value1"); IL2CPP_Dict.Add("key1", "value1");
IL2CPP_Dict.Add("key2", "value2"); IL2CPP_Dict.Add("key2", "value2");
IL2CPP_Dict.Add("key3", "value3"); IL2CPP_Dict.Add("key3", "value3");
ExplorerCore.Log($"IL2CPP 2: Il2Cpp Hashtable");
IL2CPP_HashTable = new Il2CppSystem.Collections.Hashtable(); IL2CPP_HashTable = new Il2CppSystem.Collections.Hashtable();
IL2CPP_HashTable.Add("key1", "value1"); IL2CPP_HashTable.Add("key1", "value1");
IL2CPP_HashTable.Add("key2", "value2"); IL2CPP_HashTable.Add("key2", "value2");
IL2CPP_HashTable.Add("key3", "value3"); IL2CPP_HashTable.Add("key3", "value3");
ExplorerCore.Log($"IL2CPP 3: Il2Cpp IDictionary");
var dict2 = new Il2CppSystem.Collections.Generic.Dictionary<string, string>(); var dict2 = new Il2CppSystem.Collections.Generic.Dictionary<string, string>();
dict2.Add("key1", "value1"); dict2.Add("key1", "value1");
IL2CPP_IDict = dict2.TryCast<Il2CppSystem.Collections.IDictionary>(); IL2CPP_IDict = dict2.TryCast<Il2CppSystem.Collections.IDictionary>();
ExplorerCore.Log($"IL2CPP 4: Il2Cpp List of Il2Cpp Object");
var list = new Il2CppSystem.Collections.Generic.List<Il2CppSystem.Object>(5); var list = new Il2CppSystem.Collections.Generic.List<Il2CppSystem.Object>(5);
list.Add("one"); list.Add("one");
list.Add("two"); list.Add("two");
IL2CPP_IList = list.TryCast<Il2CppSystem.Collections.IList>(); IL2CPP_IList = list.TryCast<Il2CppSystem.Collections.IList>();
ExplorerCore.Log($"IL2CPP 5: Il2Cpp List of strings");
IL2CPP_ListString = new Il2CppSystem.Collections.Generic.List<string>(); IL2CPP_ListString = new Il2CppSystem.Collections.Generic.List<string>();
IL2CPP_ListString.Add("hello,"); IL2CPP_ListString.Add("hello,");
IL2CPP_ListString.Add("world!"); IL2CPP_ListString.Add("world!");
ExplorerCore.Log($"IL2CPP 6: Il2Cpp HashSet of strings");
IL2CPP_HashSet = new Il2CppSystem.Collections.Generic.HashSet<string>(); IL2CPP_HashSet = new Il2CppSystem.Collections.Generic.HashSet<string>();
IL2CPP_HashSet.Add("one"); IL2CPP_HashSet.Add("one");
IL2CPP_HashSet.Add("two"); IL2CPP_HashSet.Add("two");
ExplorerCore.Log($"IL2CPP 7: Dictionary of Il2Cpp String and Il2Cpp Object");
CppBoxedDict = new Dictionary<Il2CppSystem.String, Il2CppSystem.Object>(); CppBoxedDict = new Dictionary<Il2CppSystem.String, Il2CppSystem.Object>();
CppBoxedDict.Add("1", new Il2CppSystem.Int32 { m_value = 1 }.BoxIl2CppObject()); CppBoxedDict.Add("1", new Il2CppSystem.Int32 { m_value = 1 }.BoxIl2CppObject());
CppBoxedDict.Add("2", new Il2CppSystem.Int32 { m_value = 2 }.BoxIl2CppObject()); CppBoxedDict.Add("2", new Il2CppSystem.Int32 { m_value = 2 }.BoxIl2CppObject());
CppBoxedDict.Add("3", new Il2CppSystem.Int32 { m_value = 3 }.BoxIl2CppObject()); CppBoxedDict.Add("3", new Il2CppSystem.Int32 { m_value = 3 }.BoxIl2CppObject());
CppBoxedDict.Add("4", new Il2CppSystem.Int32 { m_value = 4 }.BoxIl2CppObject()); CppBoxedDict.Add("4", new Il2CppSystem.Int32 { m_value = 4 }.BoxIl2CppObject());
cppDecimal = new Il2CppSystem.Decimal(1f); ExplorerCore.Log($"IL2CPP 8: List of boxed Il2Cpp Objects");
cppDecimalBoxed = new Il2CppSystem.Decimal(1f).BoxIl2CppObject();
cppVector3Boxed = Vector3.down.BoxIl2CppObject();
IL2CPP_listOfBoxedObjects = new List<Il2CppSystem.Object>(); IL2CPP_listOfBoxedObjects = new List<Il2CppSystem.Object>();
IL2CPP_listOfBoxedObjects.Add((Il2CppSystem.String)"boxedString"); IL2CPP_listOfBoxedObjects.Add((Il2CppSystem.String)"boxedString");
IL2CPP_listOfBoxedObjects.Add(new Il2CppSystem.Int32 { m_value = 5 }.BoxIl2CppObject()); IL2CPP_listOfBoxedObjects.Add(new Il2CppSystem.Int32 { m_value = 5 }.BoxIl2CppObject());
IL2CPP_listOfBoxedObjects.Add(Color.red.BoxIl2CppObject()); IL2CPP_listOfBoxedObjects.Add(Color.red.BoxIl2CppObject());
// boxed enum test
try try
{ {
var cppType = Il2CppType.Of<CameraClearFlags>(); var cppType = Il2CppType.Of<CameraClearFlags>();
@ -283,9 +208,10 @@ namespace UnityExplorer.Tests
} }
catch (Exception ex) catch (Exception ex)
{ {
ExplorerCore.LogWarning($"Test fail: {ex}"); ExplorerCore.LogWarning($"Boxed enum test fail: {ex}");
} }
ExplorerCore.Log($"IL2CPP 9: Il2Cpp struct array of ints");
IL2CPP_structArray = new UnhollowerBaseLib.Il2CppStructArray<int>(5); IL2CPP_structArray = new UnhollowerBaseLib.Il2CppStructArray<int>(5);
IL2CPP_structArray[0] = 0; IL2CPP_structArray[0] = 0;
IL2CPP_structArray[1] = 1; IL2CPP_structArray[1] = 1;
@ -293,24 +219,21 @@ namespace UnityExplorer.Tests
IL2CPP_structArray[3] = 3; IL2CPP_structArray[3] = 3;
IL2CPP_structArray[4] = 4; IL2CPP_structArray[4] = 4;
IL2CPP_stringArray = new UnhollowerBaseLib.Il2CppStringArray(2); ExplorerCore.Log($"IL2CPP 10: Il2Cpp reference array of boxed objects");
IL2CPP_stringArray[0] = "hello, ";
IL2CPP_stringArray[1] = "world!";
IL2CPP_ReferenceArray = new UnhollowerBaseLib.Il2CppReferenceArray<Il2CppSystem.Object>(3); IL2CPP_ReferenceArray = new UnhollowerBaseLib.Il2CppReferenceArray<Il2CppSystem.Object>(3);
IL2CPP_ReferenceArray[0] = new Il2CppSystem.Int32 { m_value = 5 }.BoxIl2CppObject(); IL2CPP_ReferenceArray[0] = new Il2CppSystem.Int32 { m_value = 5 }.BoxIl2CppObject();
IL2CPP_ReferenceArray[1] = null; IL2CPP_ReferenceArray[1] = null;
IL2CPP_ReferenceArray[2] = (Il2CppSystem.String)"whats up"; IL2CPP_ReferenceArray[2] = (Il2CppSystem.String)"whats up";
ExplorerCore.Log($"IL2CPP 11: Misc il2cpp members");
cppBoxedInt = new Il2CppSystem.Int32() { m_value = 5 }.BoxIl2CppObject(); cppBoxedInt = new Il2CppSystem.Int32() { m_value = 5 }.BoxIl2CppObject();
cppInt = new Il2CppSystem.Int32 { m_value = 420 }; cppInt = new Il2CppSystem.Int32 { m_value = 420 };
cppDecimal = new Il2CppSystem.Decimal(1f);
cppDecimalBoxed = new Il2CppSystem.Decimal(1f).BoxIl2CppObject();
cppVector3Boxed = Vector3.down.BoxIl2CppObject();
cppHashset = new Il2CppSystem.Collections.Hashtable(); ExplorerCore.Log($"Finished Init_Il2Cpp");
cppHashset.Add("key1", "itemOne");
cppHashset.Add("key2", "itemTwo");
cppHashset.Add("key3", "itemThree");
#endif
} }
#endif
} }
} }

View File

@ -13,7 +13,7 @@ namespace UnityExplorer
/// </summary> /// </summary>
public static bool ContainsIgnoreCase(this string _this, string s) public static bool ContainsIgnoreCase(this string _this, string s)
{ {
return ParseUtility.en_US.CompareInfo.IndexOf(_this, s, CompareOptions.IgnoreCase) >= 0; return CultureInfo.CurrentCulture.CompareInfo.IndexOf(_this, s, CompareOptions.IgnoreCase) >= 0;
} }
/// <summary> /// <summary>

View File

@ -10,8 +10,6 @@ namespace UnityExplorer
{ {
public static class ParseUtility public static class ParseUtility
{ {
public static CultureInfo en_US = new CultureInfo("en-US");
private static readonly HashSet<Type> nonPrimitiveTypes = new HashSet<Type> private static readonly HashSet<Type> nonPrimitiveTypes = new HashSet<Type>
{ {
typeof(string), typeof(string),
@ -19,20 +17,18 @@ namespace UnityExplorer
typeof(DateTime), typeof(DateTime),
}; };
public const string NUMBER_FORMAT = "0.####"; // Helper for formatting float/double/decimal numbers to maximum of 4 decimal points.
// And also for formatting a sequence of those numbers, ie a Vector3, Color etc
public static readonly string NumberFormatString = $"0.####";
private static readonly Dictionary<int, string> numSequenceStrings = new Dictionary<int, string>(); private static readonly Dictionary<int, string> numSequenceStrings = new Dictionary<int, string>();
// Helper for formatting float/double/decimal numbers to maximum of 4 decimal points.
public static string FormatDecimalSequence(params object[] numbers) public static string FormatDecimalSequence(params object[] numbers)
{ {
if (numbers.Length <= 0) if (numbers.Length <= 0)
return null; return null;
int count = numbers.Length; return string.Format(CultureInfo.CurrentCulture, GetSequenceFormatString(numbers.Length), numbers);
var formatString = GetSequenceFormatString(count);
return string.Format(en_US, formatString, numbers);
} }
public static string GetSequenceFormatString(int count) public static string GetSequenceFormatString(int count)
@ -46,19 +42,19 @@ namespace UnityExplorer
string[] strings = new string[count]; string[] strings = new string[count];
for (int i = 0; i < count; i++) for (int i = 0; i < count; i++)
strings[i] = $"{{{i}:{NUMBER_FORMAT}}}"; strings[i] = $"{{{i}:{NumberFormatString}}}";
string s = string.Join(", ", strings); string ret = string.Join(" ", strings);
numSequenceStrings.Add(count, ret);
numSequenceStrings.Add(count, s); return ret;
return s;
} }
// Main parsing API
public static bool CanParse(Type type) public static bool CanParse(Type type)
{ {
if (string.IsNullOrEmpty(type.FullName)) return !string.IsNullOrEmpty(type?.FullName)
return false; && (type.IsPrimitive || type.IsEnum || nonPrimitiveTypes.Contains(type) || customTypes.ContainsKey(type.FullName));
return type.IsPrimitive || type.IsEnum || nonPrimitiveTypes.Contains(type) || customTypes.ContainsKey(type.FullName);
} }
public static bool TryParse(string input, Type type, out object obj, out Exception parseException) public static bool TryParse(string input, Type type, out object obj, out Exception parseException)
@ -143,7 +139,7 @@ namespace UnityExplorer
else if (formattedTypes.Contains(type)) else if (formattedTypes.Contains(type))
{ {
return ReflectionUtility.GetMethodInfo(type, "ToString", new Type[] { typeof(string), typeof(IFormatProvider) }) return ReflectionUtility.GetMethodInfo(type, "ToString", new Type[] { typeof(string), typeof(IFormatProvider) })
.Invoke(obj, new object[] { NUMBER_FORMAT, en_US }) .Invoke(obj, new object[] { NumberFormatString, CultureInfo.CurrentCulture })
as string; as string;
} }
else else
@ -166,9 +162,7 @@ namespace UnityExplorer
try try
{ {
if (type.IsEnum) if (type.IsEnum)
{
typeInputExamples.Add(type.AssemblyQualifiedName, Enum.GetNames(type).First()); typeInputExamples.Add(type.AssemblyQualifiedName, Enum.GetNames(type).First());
}
else else
{ {
var instance = Activator.CreateInstance(type); var instance = Activator.CreateInstance(type);
@ -222,10 +216,10 @@ namespace UnityExplorer
{ {
Vector2 vector = default; Vector2 vector = default;
var split = input.Split(','); var split = input.Split(' ');
vector.x = float.Parse(split[0].Trim(), en_US); vector.x = float.Parse(split[0].Trim(), CultureInfo.CurrentCulture);
vector.y = float.Parse(split[1].Trim(), en_US); vector.y = float.Parse(split[1].Trim(), CultureInfo.CurrentCulture);
return vector; return vector;
} }
@ -244,11 +238,11 @@ namespace UnityExplorer
{ {
Vector3 vector = default; Vector3 vector = default;
var split = input.Split(','); var split = input.Split(' ');
vector.x = float.Parse(split[0].Trim(), en_US); vector.x = float.Parse(split[0].Trim(), CultureInfo.CurrentCulture);
vector.y = float.Parse(split[1].Trim(), en_US); vector.y = float.Parse(split[1].Trim(), CultureInfo.CurrentCulture);
vector.z = float.Parse(split[2].Trim(), en_US); vector.z = float.Parse(split[2].Trim(), CultureInfo.CurrentCulture);
return vector; return vector;
} }
@ -267,12 +261,12 @@ namespace UnityExplorer
{ {
Vector4 vector = default; Vector4 vector = default;
var split = input.Split(','); var split = input.Split(' ');
vector.x = float.Parse(split[0].Trim(), en_US); vector.x = float.Parse(split[0].Trim(), CultureInfo.CurrentCulture);
vector.y = float.Parse(split[1].Trim(), en_US); vector.y = float.Parse(split[1].Trim(), CultureInfo.CurrentCulture);
vector.z = float.Parse(split[2].Trim(), en_US); vector.z = float.Parse(split[2].Trim(), CultureInfo.CurrentCulture);
vector.w = float.Parse(split[3].Trim(), en_US); vector.w = float.Parse(split[3].Trim(), CultureInfo.CurrentCulture);
return vector; return vector;
} }
@ -291,22 +285,22 @@ namespace UnityExplorer
{ {
Vector3 vector = default; Vector3 vector = default;
var split = input.Split(','); var split = input.Split(' ');
if (split.Length == 4) if (split.Length == 4)
{ {
Quaternion quat = default; Quaternion quat = default;
quat.x = float.Parse(split[0].Trim(), en_US); quat.x = float.Parse(split[0].Trim(), CultureInfo.CurrentCulture);
quat.y = float.Parse(split[1].Trim(), en_US); quat.y = float.Parse(split[1].Trim(), CultureInfo.CurrentCulture);
quat.z = float.Parse(split[2].Trim(), en_US); quat.z = float.Parse(split[2].Trim(), CultureInfo.CurrentCulture);
quat.w = float.Parse(split[3].Trim(), en_US); quat.w = float.Parse(split[3].Trim(), CultureInfo.CurrentCulture);
return quat; return quat;
} }
else else
{ {
vector.x = float.Parse(split[0].Trim(), en_US); vector.x = float.Parse(split[0].Trim(), CultureInfo.CurrentCulture);
vector.y = float.Parse(split[1].Trim(), en_US); vector.y = float.Parse(split[1].Trim(), CultureInfo.CurrentCulture);
vector.z = float.Parse(split[2].Trim(), en_US); vector.z = float.Parse(split[2].Trim(), CultureInfo.CurrentCulture);
return Quaternion.Euler(vector); return Quaternion.Euler(vector);
} }
} }
@ -327,12 +321,12 @@ namespace UnityExplorer
{ {
Rect rect = default; Rect rect = default;
var split = input.Split(','); var split = input.Split(' ');
rect.x = float.Parse(split[0].Trim(), en_US); rect.x = float.Parse(split[0].Trim(), CultureInfo.CurrentCulture);
rect.y = float.Parse(split[1].Trim(), en_US); rect.y = float.Parse(split[1].Trim(), CultureInfo.CurrentCulture);
rect.width = float.Parse(split[2].Trim(), en_US); rect.width = float.Parse(split[2].Trim(), CultureInfo.CurrentCulture);
rect.height = float.Parse(split[3].Trim(), en_US); rect.height = float.Parse(split[3].Trim(), CultureInfo.CurrentCulture);
return rect; return rect;
} }
@ -351,13 +345,13 @@ namespace UnityExplorer
{ {
Color color = default; Color color = default;
var split = input.Split(','); var split = input.Split(' ');
color.r = float.Parse(split[0].Trim(), en_US); color.r = float.Parse(split[0].Trim(), CultureInfo.CurrentCulture);
color.g = float.Parse(split[1].Trim(), en_US); color.g = float.Parse(split[1].Trim(), CultureInfo.CurrentCulture);
color.b = float.Parse(split[2].Trim(), en_US); color.b = float.Parse(split[2].Trim(), CultureInfo.CurrentCulture);
if (split.Length > 3) if (split.Length > 3)
color.a = float.Parse(split[3].Trim(), en_US); color.a = float.Parse(split[3].Trim(), CultureInfo.CurrentCulture);
else else
color.a = 1; color.a = 1;
@ -378,13 +372,13 @@ namespace UnityExplorer
{ {
Color32 color = default; Color32 color = default;
var split = input.Split(','); var split = input.Split(' ');
color.r = byte.Parse(split[0].Trim(), en_US); color.r = byte.Parse(split[0].Trim(), CultureInfo.CurrentCulture);
color.g = byte.Parse(split[1].Trim(), en_US); color.g = byte.Parse(split[1].Trim(), CultureInfo.CurrentCulture);
color.b = byte.Parse(split[2].Trim(), en_US); color.b = byte.Parse(split[2].Trim(), CultureInfo.CurrentCulture);
if (split.Length > 3) if (split.Length > 3)
color.a = byte.Parse(split[3].Trim(), en_US); color.a = byte.Parse(split[3].Trim(), CultureInfo.CurrentCulture);
else else
color.a = 255; color.a = 255;
@ -397,7 +391,7 @@ namespace UnityExplorer
return null; return null;
// ints, this is fine // ints, this is fine
return $"{color.r}, {color.g}, {color.b}, {color.a}"; return $"{color.r} {color.g} {color.b} {color.a}";
} }
// Layermask (Int32) // Layermask (Int32)

View File

@ -20,13 +20,15 @@ namespace UnityExplorer
public static class ExplorerCore public static class ExplorerCore
{ {
public const string NAME = "UnityExplorer"; public const string NAME = "UnityExplorer";
public const string VERSION = "4.1.11"; public const string VERSION = "4.2.1";
public const string AUTHOR = "Sinai"; public const string AUTHOR = "Sinai";
public const string GUID = "com.sinai.unityexplorer"; public const string GUID = "com.sinai.unityexplorer";
public static IExplorerLoader Loader { get; private set; } public static IExplorerLoader Loader { get; private set; }
public static RuntimeContext Context { get; internal set; } public static RuntimeContext Context { get; internal set; }
public static HarmonyLib.Harmony Harmony { get; } = new HarmonyLib.Harmony(GUID);
/// <summary> /// <summary>
/// Initialize UnityExplorer with the provided Loader implementation. /// Initialize UnityExplorer with the provided Loader implementation.
/// </summary> /// </summary>

View File

@ -8,20 +8,10 @@
<InputAssemblies Include="..\lib\mcs-unity\mcs\bin\Release\mcs.dll" /> <InputAssemblies Include="..\lib\mcs-unity\mcs\bin\Release\mcs.dll" />
<InputAssemblies Include="packages\ini-parser.2.5.2\lib\net20\INIFileParser.dll" /> <InputAssemblies Include="packages\ini-parser.2.5.2\lib\net20\INIFileParser.dll" />
</ItemGroup> </ItemGroup>
<!-- MonoMod for MelonLoader 0.3.0 -->
<ItemGroup Condition="'$(IsMelonLoaderLegacy)'=='true'">
<InputAssemblies Include="packages\Mono.Cecil.0.10.4\lib\net35\Mono.Cecil.dll" />
<InputAssemblies Include="packages\Mono.Cecil.0.10.4\lib\net35\Mono.Cecil.Mdb.dll" />
<InputAssemblies Include="packages\Mono.Cecil.0.10.4\lib\net35\Mono.Cecil.Pdb.dll" />
<InputAssemblies Include="packages\Mono.Cecil.0.10.4\lib\net35\Mono.Cecil.Rocks.dll" />
<InputAssemblies Include="packages\MonoMod.RuntimeDetour.20.1.1.4\lib\net35\MonoMod.RuntimeDetour.dll" />
<InputAssemblies Include="packages\MonoMod.Utils.20.1.1.4\lib\net35\MonoMod.Utils.dll" />
</ItemGroup>
<!-- Required references for ILRepack --> <!-- Required references for ILRepack -->
<ItemGroup> <ItemGroup>
<ReferenceFolders Include="packages\HarmonyX.2.4.2\lib\net35\" /> <ReferenceFolders Include="packages\HarmonyX.2.5.2\lib\net35\" />
<ReferenceFolders Include="..\lib\BepInEx.6.IL2CPP\" /> <ReferenceFolders Include="..\lib\BepInEx.6.IL2CPP\" />
<ReferenceFolders Include="..\lib\BepInEx.6.Mono\" /> <ReferenceFolders Include="..\lib\BepInEx.6.Mono\" />
<ReferenceFolders Include="..\lib\BepInEx.5\" /> <ReferenceFolders Include="..\lib\BepInEx.5\" />

View File

@ -47,6 +47,7 @@ namespace UnityExplorer.Inspectors
public ScrollPool<CacheMemberCell> MemberScrollPool { get; private set; } public ScrollPool<CacheMemberCell> MemberScrollPool { get; private set; }
public InputFieldRef HiddenNameText;
public Text NameText; public Text NameText;
public Text AssemblyText; public Text AssemblyText;
private Toggle autoUpdateToggle; private Toggle autoUpdateToggle;
@ -125,6 +126,7 @@ namespace UnityExplorer.Inspectors
currentBaseTabText = $"{prefix} {SignatureHighlighter.Parse(TargetType, false)}"; currentBaseTabText = $"{prefix} {SignatureHighlighter.Parse(TargetType, false)}";
Tab.TabText.text = currentBaseTabText; Tab.TabText.text = currentBaseTabText;
NameText.text = SignatureHighlighter.Parse(TargetType, true); NameText.text = SignatureHighlighter.Parse(TargetType, true);
HiddenNameText.Text = TargetType.FullName;
string asmText; string asmText;
if (TargetType.Assembly is AssemblyBuilder || string.IsNullOrEmpty(TargetType.Assembly.Location)) if (TargetType.Assembly is AssemblyBuilder || string.IsNullOrEmpty(TargetType.Assembly.Location))
@ -332,8 +334,27 @@ namespace UnityExplorer.Inspectors
// Class name, assembly // Class name, assembly
NameText = UIFactory.CreateLabel(UIRoot, "Title", "not set", TextAnchor.MiddleLeft, fontSize: 17); var titleHolder = UIFactory.CreateUIObject("TitleHolder", UIRoot);
UIFactory.SetLayoutElement(NameText.gameObject, minHeight: 25, flexibleHeight: 0); UIFactory.SetLayoutElement(titleHolder, minHeight: 35, flexibleHeight: 0, flexibleWidth: 9999);
NameText = UIFactory.CreateLabel(titleHolder, "VisibleTitle", "NotSet", TextAnchor.MiddleLeft);
var namerect = NameText.GetComponent<RectTransform>();
namerect.anchorMin = new Vector2(0, 0);
namerect.anchorMax = new Vector2(1, 1);
NameText.fontSize = 17;
UIFactory.SetLayoutElement(NameText.gameObject, minHeight: 35, flexibleHeight: 0, minWidth: 300, flexibleWidth: 9999);
HiddenNameText = UIFactory.CreateInputField(titleHolder, "Title", "not set");
var hiddenrect = HiddenNameText.Component.gameObject.GetComponent<RectTransform>();
hiddenrect.anchorMin = new Vector2(0, 0);
hiddenrect.anchorMax = new Vector2(1, 1);
HiddenNameText.Component.readOnly = true;
HiddenNameText.Component.lineType = InputField.LineType.MultiLineNewline;
HiddenNameText.Component.gameObject.GetComponent<Image>().color = Color.clear;
HiddenNameText.Component.textComponent.horizontalOverflow = HorizontalWrapMode.Wrap;
HiddenNameText.Component.textComponent.fontSize = 17;
HiddenNameText.Component.textComponent.color = Color.clear;
UIFactory.SetLayoutElement(HiddenNameText.Component.gameObject, minHeight: 35, flexibleHeight: 0, flexibleWidth: 9999);
AssemblyText = UIFactory.CreateLabel(UIRoot, "AssemblyLabel", "not set", TextAnchor.MiddleLeft); AssemblyText = UIFactory.CreateLabel(UIRoot, "AssemblyLabel", "not set", TextAnchor.MiddleLeft);
UIFactory.SetLayoutElement(AssemblyText.gameObject, minHeight: 25, flexibleWidth: 9999); UIFactory.SetLayoutElement(AssemblyText.gameObject, minHeight: 25, flexibleWidth: 9999);

View File

@ -39,6 +39,8 @@ namespace UnityExplorer
=> Log; => Log;
#endif #endif
public string UnhollowedModulesFolder => Path.Combine(Paths.BepInExRootPath, "unhollowed");
public ConfigHandler ConfigHandler => _configHandler; public ConfigHandler ConfigHandler => _configHandler;
private BepInExConfigHandler _configHandler; private BepInExConfigHandler _configHandler;
@ -51,8 +53,7 @@ namespace UnityExplorer
public Action<object> OnLogWarning => LogSource.LogWarning; public Action<object> OnLogWarning => LogSource.LogWarning;
public Action<object> OnLogError => LogSource.LogError; public Action<object> OnLogError => LogSource.LogError;
// Init common to Mono and Il2Cpp private void Init()
internal void UniversalInit()
{ {
Instance = this; Instance = this;
_configHandler = new BepInExConfigHandler(); _configHandler = new BepInExConfigHandler();
@ -62,57 +63,15 @@ namespace UnityExplorer
#if MONO // Mono #if MONO // Mono
internal void Awake() internal void Awake()
{ {
UniversalInit(); Init();
} }
#else // Il2Cpp #else // Il2Cpp
public override void Load() public override void Load()
{ {
UniversalInit(); Init();
} }
#endif #endif
public void SetupCursorPatches()
{
try
{
this.HarmonyInstance.PatchAll();
}
catch (Exception ex)
{
ExplorerCore.Log($"Exception setting up Harmony patches:\r\n{ex.ReflectionExToString()}");
}
}
[HarmonyPatch(typeof(EventSystem), "current", MethodType.Setter)]
public class PATCH_EventSystem_current
{
[HarmonyPrefix]
public static void Prefix_EventSystem_set_current(ref EventSystem value)
{
CursorUnlocker.Prefix_EventSystem_set_current(ref value);
}
}
[HarmonyPatch(typeof(Cursor), "lockState", MethodType.Setter)]
public class PATCH_Cursor_lockState
{
[HarmonyPrefix]
public static void Prefix_set_lockState(ref CursorLockMode value)
{
CursorUnlocker.Prefix_set_lockState(ref value);
}
}
[HarmonyPatch(typeof(Cursor), "visible", MethodType.Setter)]
public class PATCH_Cursor_visible
{
[HarmonyPrefix]
public static void Prefix_set_visible(ref bool value)
{
CursorUnlocker.Prefix_set_visible(ref value);
}
}
} }
} }
#endif #endif

View File

@ -9,13 +9,12 @@ namespace UnityExplorer
public interface IExplorerLoader public interface IExplorerLoader
{ {
string ExplorerFolder { get; } string ExplorerFolder { get; }
string UnhollowedModulesFolder { get; }
ConfigHandler ConfigHandler { get; } ConfigHandler ConfigHandler { get; }
Action<object> OnLogMessage { get; } Action<object> OnLogMessage { get; }
Action<object> OnLogWarning { get; } Action<object> OnLogWarning { get; }
Action<object> OnLogError { get; } Action<object> OnLogError { get; }
void SetupCursorPatches();
} }
} }

View File

@ -1,86 +0,0 @@
#if ML
using System;
using System.IO;
using MelonLoader;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityExplorer;
using UnityExplorer.Core;
using UnityExplorer.Core.Config;
using UnityExplorer.Core.Input;
using UnityExplorer.Loader.ML;
#if ML_LEGACY
using Harmony;
#else
using HarmonyLib;
[assembly: MelonPlatformDomain(MelonPlatformDomainAttribute.CompatibleDomains.UNIVERSAL)]
#endif
[assembly: MelonInfo(typeof(ExplorerMelonMod), ExplorerCore.NAME, ExplorerCore.VERSION, ExplorerCore.AUTHOR)]
[assembly: MelonGame(null, null)]
[assembly: MelonColor(ConsoleColor.DarkCyan)]
namespace UnityExplorer
{
public class ExplorerMelonMod : MelonMod, IExplorerLoader
{
public static ExplorerMelonMod Instance;
public string ExplorerFolder => Path.Combine("Mods", ExplorerCore.NAME);
public ConfigHandler ConfigHandler => _configHandler;
public MelonLoaderConfigHandler _configHandler;
public Action<object> OnLogMessage => MelonLogger.Msg;
public Action<object> OnLogWarning => MelonLogger.Warning;
public Action<object> OnLogError => MelonLogger.Error;
public override void OnApplicationStart()
{
Instance = this;
_configHandler = new MelonLoaderConfigHandler();
ExplorerCore.Init(this);
}
public void SetupCursorPatches()
{
try
{
PrefixProperty(typeof(Cursor),
"lockState",
new HarmonyMethod(typeof(CursorUnlocker).GetMethod(nameof(CursorUnlocker.Prefix_set_lockState))));
PrefixProperty(typeof(Cursor),
"visible",
new HarmonyMethod(typeof(CursorUnlocker).GetMethod(nameof(CursorUnlocker.Prefix_set_visible))));
PrefixProperty(typeof(EventSystem),
"current",
new HarmonyMethod(typeof(CursorUnlocker).GetMethod(nameof(CursorUnlocker.Prefix_EventSystem_set_current))));
}
catch (Exception ex)
{
ExplorerCore.Log($"Exception setting up Harmony patches:\r\n{ex.ReflectionExToString()}");
}
}
private void PrefixProperty(Type type, string property, HarmonyMethod prefix)
{
try
{
var prop = type.GetProperty(property);
#if ML_LEGACY
this.Harmony.Patch(prop.GetSetMethod(), prefix: prefix);
#else
HarmonyInstance.Patch(prop.GetSetMethod(), prefix: prefix);
#endif
}
catch (Exception e)
{
ExplorerCore.Log($"Unable to patch {type.Name}.set_{property}: {e.Message}");
}
}
}
}
#endif

View File

@ -1,206 +0,0 @@
#if ML
#if !ML_LEGACY // ML 0.3.1+ config handler
using MelonLoader;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;
using UnityExplorer.Core;
using UnityExplorer.Core.Config;
namespace UnityExplorer.Loader.ML
{
public class MelonLoaderConfigHandler : ConfigHandler
{
internal const string CTG_NAME = "UnityExplorer";
internal MelonPreferences_Category prefCategory;
public override void Init()
{
prefCategory = MelonPreferences.CreateCategory(CTG_NAME, $"{CTG_NAME} Settings", false, true);
}
public override void LoadConfig()
{
foreach (var entry in ConfigManager.ConfigElements)
{
var key = entry.Key;
if (prefCategory.GetEntry(key) is MelonPreferences_Entry)
{
var config = entry.Value;
config.BoxedValue = config.GetLoaderConfigValue();
}
}
}
public override void RegisterConfigElement<T>(ConfigElement<T> config)
{
var entry = prefCategory.CreateEntry(config.Name, config.Value, null, config.Description, config.IsInternal, false);
entry.OnValueChangedUntyped += () =>
{
if ((entry.Value == null && config.Value == null) || config.Value.Equals(entry.Value))
return;
config.Value = entry.Value;
};
}
public override void SetConfigValue<T>(ConfigElement<T> config, T value)
{
if (prefCategory.GetEntry<T>(config.Name) is MelonPreferences_Entry<T> entry)
{
entry.Value = value;
//entry.Save();
}
}
public override T GetConfigValue<T>(ConfigElement<T> config)
{
if (prefCategory.GetEntry<T>(config.Name) is MelonPreferences_Entry<T> entry)
return entry.Value;
return default;
}
public override void OnAnyConfigChanged()
{
}
public override void SaveConfig()
{
MelonPreferences.Save();
}
}
}
#else // ML 0.3.0 config handler
using MelonLoader;
using MelonLoader.Tomlyn.Model;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;
using UnityExplorer.Core;
using UnityExplorer.Core.Config;
namespace UnityExplorer.Loader.ML
{
public class MelonLoaderConfigHandler : ConfigHandler
{
internal const string CTG_NAME = "UnityExplorer";
internal MelonPreferences_Category prefCategory;
public override void Init()
{
prefCategory = MelonPreferences.CreateCategory(CTG_NAME, $"{CTG_NAME} Settings");
try { MelonPreferences.Mapper.RegisterMapper(KeycodeReader, KeycodeWriter); } catch { }
try { MelonPreferences.Mapper.RegisterMapper(AnchorReader, AnchorWriter); } catch { }
}
public override void LoadConfig()
{
foreach (var entry in ConfigManager.ConfigElements)
{
var key = entry.Key;
if (prefCategory.GetEntry(key) is MelonPreferences_Entry)
{
var config = entry.Value;
config.BoxedValue = config.GetLoaderConfigValue();
}
}
}
public override void RegisterConfigElement<T>(ConfigElement<T> config)
{
var entry = prefCategory.CreateEntry(config.Name, config.Value, null, config.IsInternal) as MelonPreferences_Entry<T>;
entry.OnValueChangedUntyped += () =>
{
if ((entry.Value == null && config.Value == null) || config.Value.Equals(entry.Value))
return;
config.Value = entry.Value;
};
}
public override void SetConfigValue<T>(ConfigElement<T> config, T value)
{
if (prefCategory.GetEntry<T>(config.Name) is MelonPreferences_Entry<T> entry)
{
entry.Value = value;
entry.Save();
}
}
public override T GetConfigValue<T>(ConfigElement<T> config)
{
if (prefCategory.GetEntry<T>(config.Name) is MelonPreferences_Entry<T> entry)
return entry.Value;
return default;
}
public override void OnAnyConfigChanged()
{
}
public override void SaveConfig()
{
MelonPreferences.Save();
}
// Enum config handlers
public static KeyCode KeycodeReader(TomlObject value)
{
try
{
KeyCode kc = (KeyCode)Enum.Parse(typeof(KeyCode), (value as TomlString).Value);
if (kc == default)
throw new Exception();
return kc;
}
catch
{
return KeyCode.F7;
}
}
public static TomlObject KeycodeWriter(KeyCode value)
{
return MelonPreferences.Mapper.ToToml(value.ToString());
}
public static UI.UIManager.VerticalAnchor AnchorReader(TomlObject value)
{
try
{
return (UI.UIManager.VerticalAnchor)Enum.Parse(typeof(UI.UIManager.VerticalAnchor), (value as TomlString).Value);
}
catch
{
return UI.UIManager.VerticalAnchor.Top;
}
}
public static TomlObject AnchorWriter(UI.UIManager.VerticalAnchor anchor)
{
return MelonPreferences.Mapper.ToToml(anchor.ToString());
}
}
}
#endif
#endif

View File

@ -0,0 +1,47 @@
#if ML
using System;
using System.IO;
using MelonLoader;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityExplorer;
using UnityExplorer.Core;
using UnityExplorer.Core.Config;
using UnityExplorer.Core.Input;
using UnityExplorer.Loader.ML;
using HarmonyLib;
[assembly: MelonPlatformDomain(MelonPlatformDomainAttribute.CompatibleDomains.UNIVERSAL)]
[assembly: MelonInfo(typeof(ExplorerMelonMod), ExplorerCore.NAME, ExplorerCore.VERSION, ExplorerCore.AUTHOR)]
[assembly: MelonGame(null, null)]
[assembly: MelonColor(ConsoleColor.DarkCyan)]
namespace UnityExplorer
{
public class ExplorerMelonMod : MelonMod, IExplorerLoader
{
public static ExplorerMelonMod Instance;
public string ExplorerFolder => Path.Combine("Mods", ExplorerCore.NAME);
public string UnhollowedModulesFolder => Path.Combine(
Path.GetDirectoryName(MelonHandler.ModsDirectory),
Path.Combine("MelonLoader", "Managed"));
public ConfigHandler ConfigHandler => _configHandler;
public MelonLoaderConfigHandler _configHandler;
public Action<object> OnLogMessage => MelonLogger.Msg;
public Action<object> OnLogWarning => MelonLogger.Warning;
public Action<object> OnLogError => MelonLogger.Error;
public override void OnApplicationStart()
{
Instance = this;
_configHandler = new MelonLoaderConfigHandler();
ExplorerCore.Init(this);
}
}
}
#endif

View File

@ -0,0 +1,94 @@
#if ML
using MelonLoader;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;
using UnityExplorer.Core;
using UnityExplorer.Core.Config;
namespace UnityExplorer.Loader.ML
{
public class MelonLoaderConfigHandler : ConfigHandler
{
internal const string CTG_NAME = "UnityExplorer";
internal MelonPreferences_Category prefCategory;
public override void Init()
{
prefCategory = MelonPreferences.CreateCategory(CTG_NAME, $"{CTG_NAME} Settings", false, true);
}
public override void LoadConfig()
{
foreach (var entry in ConfigManager.ConfigElements)
{
var key = entry.Key;
if (prefCategory.GetEntry(key) is MelonPreferences_Entry)
{
var config = entry.Value;
config.BoxedValue = config.GetLoaderConfigValue();
}
}
}
// This wrapper exists to handle the arbitrary "LemonAction" delegates which ML now uses in 0.4.4+.
// Reflection is required since the delegate type changed between 0.4.3 and 0.4.4.
// A wrapper class is required to link the MelonPreferences_Entry and the delegate instance.
public class EntryDelegateWrapper<T>
{
public MelonPreferences_Entry<T> entry;
public ConfigElement<T> config;
public EntryDelegateWrapper(MelonPreferences_Entry<T> entry, ConfigElement<T> config)
{
this.entry = entry;
this.config = config;
var evt = entry.GetType().GetEvent("OnValueChangedUntyped");
evt.AddEventHandler(entry, Delegate.CreateDelegate(evt.EventHandlerType, this, GetType().GetMethod("OnChanged")));
}
public void OnChanged()
{
if ((entry.Value == null && config.Value == null) || config.Value.Equals(entry.Value))
return;
config.Value = entry.Value;
}
}
public override void RegisterConfigElement<T>(ConfigElement<T> config)
{
var entry = prefCategory.CreateEntry(config.Name, config.Value, null, config.Description, config.IsInternal, false);
new EntryDelegateWrapper<T>(entry, config);
}
public override void SetConfigValue<T>(ConfigElement<T> config, T value)
{
if (prefCategory.GetEntry<T>(config.Name) is MelonPreferences_Entry<T> entry)
{
entry.Value = value;
//entry.Save();
}
}
public override T GetConfigValue<T>(ConfigElement<T> config)
{
if (prefCategory.GetEntry<T>(config.Name) is MelonPreferences_Entry<T> entry)
return entry.Value;
return default;
}
public override void OnAnyConfigChanged()
{
}
public override void SaveConfig()
{
MelonPreferences.Save();
}
}
}
#endif

View File

@ -18,26 +18,43 @@ namespace UnityExplorer
public class ExplorerStandalone : IExplorerLoader public class ExplorerStandalone : IExplorerLoader
{ {
/// <summary> /// <summary>
/// Call this to initialize UnityExplorer without adding a log listener. /// Call this to initialize UnityExplorer without adding a log listener or Unhollowed modules path.
/// The default Unhollowed path "UnityExplorer\Modules\" will be used.
/// </summary> /// </summary>
/// <returns>The new (or active, if one exists) instance of ExplorerStandalone.</returns> /// <returns>The new (or active, if one exists) instance of ExplorerStandalone.</returns>
public static ExplorerStandalone CreateInstance() public static ExplorerStandalone CreateInstance() => CreateInstance(null, null);
=> CreateInstance(null);
/// <summary> /// <summary>
/// Call this to initialize UnityExplorer and add a listener for UnityExplorer's log messages. /// Call this to initialize UnityExplorer and add a listener for UnityExplorer's log messages, without specifying an Unhollowed modules path.
/// The default Unhollowed path "UnityExplorer\Modules\" will be used.
/// </summary> /// </summary>
/// <param name="logListener">Your log listener to handle UnityExplorer logs.</param> /// <param name="logListener">Your log listener to handle UnityExplorer logs.</param>
/// <returns>The new (or active, if one exists) instance of ExplorerStandalone.</returns> /// <returns>The new (or active, if one exists) instance of ExplorerStandalone.</returns>
public static ExplorerStandalone CreateInstance(Action<string, LogType> logListener) public static ExplorerStandalone CreateInstance(Action<string, LogType> logListener) => CreateInstance(logListener, null);
/// <summary>
/// Call this to initialize UnityExplorer with the provided log listener and Unhollowed modules path.
/// </summary>
/// <param name="logListener">Your log listener to handle UnityExplorer logs.</param>
/// <param name="unhollowedModulesPath">The path of the Unhollowed modules, either relative or absolute.</param>
/// <returns>The new (or active, if one exists) instance of ExplorerStandalone.</returns>
public static ExplorerStandalone CreateInstance(Action<string, LogType> logListener, string unhollowedModulesPath)
{ {
if (Instance != null) if (Instance != null)
return Instance; return Instance;
OnLog += logListener;
var instance = new ExplorerStandalone(); var instance = new ExplorerStandalone();
instance.Init(); instance.Init();
instance.CheckExplorerFolder();
if (logListener != null)
OnLog += logListener;
if (string.IsNullOrEmpty(unhollowedModulesPath) || !Directory.Exists(unhollowedModulesPath))
instance._unhollowedPath = Path.Combine(instance.ExplorerFolder, "Modules");
else
instance._unhollowedPath = unhollowedModulesPath;
return instance; return instance;
} }
@ -48,8 +65,8 @@ namespace UnityExplorer
/// </summary> /// </summary>
public static event Action<string, LogType> OnLog; public static event Action<string, LogType> OnLog;
public Harmony HarmonyInstance => s_harmony; public string UnhollowedModulesFolder => _unhollowedPath;
public static readonly Harmony s_harmony = new Harmony(ExplorerCore.GUID); private string _unhollowedPath;
public ConfigHandler ConfigHandler => _configHandler; public ConfigHandler ConfigHandler => _configHandler;
private StandaloneConfigHandler _configHandler; private StandaloneConfigHandler _configHandler;
@ -58,19 +75,7 @@ namespace UnityExplorer
{ {
get get
{ {
if (s_explorerFolder == null) CheckExplorerFolder();
{
s_explorerFolder =
Path.Combine(
Path.GetDirectoryName(
Uri.UnescapeDataString(new Uri(Assembly.GetExecutingAssembly().CodeBase)
.AbsolutePath)),
"UnityExplorer");
if (!Directory.Exists(s_explorerFolder))
Directory.CreateDirectory(s_explorerFolder);
}
return s_explorerFolder; return s_explorerFolder;
} }
} }
@ -88,45 +93,18 @@ namespace UnityExplorer
ExplorerCore.Init(this); ExplorerCore.Init(this);
} }
public void SetupCursorPatches() private void CheckExplorerFolder()
{ {
try if (s_explorerFolder == null)
{ {
this.HarmonyInstance.PatchAll(); s_explorerFolder =
} Path.Combine(
catch (Exception ex) Path.GetDirectoryName(
{ Uri.UnescapeDataString(new Uri(Assembly.GetExecutingAssembly().CodeBase).AbsolutePath)),
ExplorerCore.Log($"Exception setting up Harmony patches:\r\n{ex.ReflectionExToString()}"); "UnityExplorer");
}
}
[HarmonyPatch(typeof(EventSystem), "current", MethodType.Setter)] if (!Directory.Exists(s_explorerFolder))
public class PATCH_EventSystem_current Directory.CreateDirectory(s_explorerFolder);
{
[HarmonyPrefix]
public static void Prefix_EventSystem_set_current(ref EventSystem value)
{
CursorUnlocker.Prefix_EventSystem_set_current(ref value);
}
}
[HarmonyPatch(typeof(Cursor), "lockState", MethodType.Setter)]
public class PATCH_Cursor_lockState
{
[HarmonyPrefix]
public static void Prefix_set_lockState(ref CursorLockMode value)
{
CursorUnlocker.Prefix_set_lockState(ref value);
}
}
[HarmonyPatch(typeof(Cursor), "visible", MethodType.Setter)]
public class PATCH_Cursor_visible
{
[HarmonyPrefix]
public static void Prefix_set_visible(ref bool value)
{
CursorUnlocker.Prefix_set_visible(ref value);
} }
} }
} }

View File

@ -56,13 +56,7 @@ namespace UnityExplorer.ObjectExplorer
else if (m_context == SearchContext.Class) else if (m_context == SearchContext.Class)
currentResults = SearchProvider.ClassSearch(nameInputField.Text); currentResults = SearchProvider.ClassSearch(nameInputField.Text);
else else
{ currentResults = SearchProvider.UnityObjectSearch(nameInputField.Text, desiredTypeInput, m_context, m_childFilter, m_sceneFilter);
string compType = "";
if (m_context == SearchContext.UnityObject)
compType = this.desiredTypeInput;
currentResults = SearchProvider.UnityObjectSearch(nameInputField.Text, compType, m_context, m_childFilter, m_sceneFilter);
}
dataHandler.RefreshData(); dataHandler.RefreshData();
resultsScrollPool.Refresh(true); resultsScrollPool.Refresh(true);

View File

@ -40,14 +40,12 @@ namespace UnityExplorer.ObjectExplorer
/// <summary> /// <summary>
/// The names of all scenes in the build settings, if they could be retrieved. /// The names of all scenes in the build settings, if they could be retrieved.
/// </summary> /// </summary>
public static ReadOnlyCollection<string> AllSceneNames => new ReadOnlyCollection<string>(allScenesInBuild); public static readonly List<string> AllSceneNames = new List<string>();
private static readonly List<string> allScenesInBuild = new List<string>();
/// <summary> /// <summary>
/// Whether or not we successfuly retrieved the names of the scenes in the build settings. /// Whether or not we successfuly retrieved the names of the scenes in the build settings.
/// </summary> /// </summary>
public static bool WasAbleToGetScenesInBuild => gotAllScenesInBuild; public static bool WasAbleToGetScenesInBuild { get; private set; }
private static bool gotAllScenesInBuild = true;
/// <summary> /// <summary>
/// Invoked when the currently inspected Scene changes. The argument is the new scene. /// Invoked when the currently inspected Scene changes. The argument is the new scene.
@ -97,12 +95,12 @@ namespace UnityExplorer.ObjectExplorer
for (int i = 0; i < sceneCount; i++) for (int i = 0; i < sceneCount; i++)
{ {
var scenePath = (string)method.Invoke(null, new object[] { i }); var scenePath = (string)method.Invoke(null, new object[] { i });
allScenesInBuild.Add(scenePath); AllSceneNames.Add(scenePath);
} }
} }
catch (Exception ex) catch (Exception ex)
{ {
gotAllScenesInBuild = false; WasAbleToGetScenesInBuild = false;
ExplorerCore.LogWarning($"Unable to generate list of all Scenes in the build: {ex}"); ExplorerCore.LogWarning($"Unable to generate list of all Scenes in the build: {ex}");
} }
} }

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -209,6 +209,10 @@ namespace UnityExplorer.UI.Panels
{ {
ExplorerCore.LogWarning("Invalid or corrupt panel save data! Restoring to default."); ExplorerCore.LogWarning("Invalid or corrupt panel save data! Restoring to default.");
SetTransformDefaults(); SetTransformDefaults();
UIManager.Initializing = false;
DoSaveToConfigElement();
ConfigManager.InternalHandler.SaveConfig();
UIManager.Initializing = true;
} }
} }
@ -335,7 +339,7 @@ namespace UnityExplorer.UI.Panels
if (!rect) if (!rect)
throw new ArgumentNullException("rect"); throw new ArgumentNullException("rect");
return string.Format(ParseUtility.en_US, "{0},{1},{2},{3}", new object[] return string.Format(CultureInfo.InvariantCulture, "{0},{1},{2},{3}", new object[]
{ {
rect.anchorMin.x, rect.anchorMin.x,
rect.anchorMin.y, rect.anchorMin.y,
@ -349,16 +353,20 @@ namespace UnityExplorer.UI.Panels
if (string.IsNullOrEmpty(stringAnchors)) if (string.IsNullOrEmpty(stringAnchors))
throw new ArgumentNullException("stringAnchors"); throw new ArgumentNullException("stringAnchors");
if (stringAnchors.Contains(" "))
// outdated save data, not worth recovering just reset it.
throw new Exception("invalid save data, resetting.");
var split = stringAnchors.Split(','); var split = stringAnchors.Split(',');
if (split.Length != 4) if (split.Length != 4)
throw new Exception($"stringAnchors split is unexpected length: {split.Length}"); throw new Exception($"stringAnchors split is unexpected length: {split.Length}");
Vector4 anchors; Vector4 anchors;
anchors.x = float.Parse(split[0], ParseUtility.en_US); anchors.x = float.Parse(split[0], CultureInfo.InvariantCulture);
anchors.y = float.Parse(split[1], ParseUtility.en_US); anchors.y = float.Parse(split[1], CultureInfo.InvariantCulture);
anchors.z = float.Parse(split[2], ParseUtility.en_US); anchors.z = float.Parse(split[2], CultureInfo.InvariantCulture);
anchors.w = float.Parse(split[3], ParseUtility.en_US); anchors.w = float.Parse(split[3], CultureInfo.InvariantCulture);
panel.anchorMin = new Vector2(anchors.x, anchors.y); panel.anchorMin = new Vector2(anchors.x, anchors.y);
panel.anchorMax = new Vector2(anchors.z, anchors.w); panel.anchorMax = new Vector2(anchors.z, anchors.w);
@ -369,7 +377,7 @@ namespace UnityExplorer.UI.Panels
if (!rect) if (!rect)
throw new ArgumentNullException("rect"); throw new ArgumentNullException("rect");
return string.Format(ParseUtility.en_US, "{0},{1}", new object[] return string.Format(CultureInfo.InvariantCulture, "{0},{1}", new object[]
{ {
rect.localPosition.x, rect.localPosition.y rect.localPosition.x, rect.localPosition.y
}); });
@ -377,14 +385,21 @@ namespace UnityExplorer.UI.Panels
internal static void SetPositionFromString(this RectTransform rect, string stringPosition) internal static void SetPositionFromString(this RectTransform rect, string stringPosition)
{ {
if (string.IsNullOrEmpty(stringPosition))
throw new ArgumentNullException(stringPosition);
if (stringPosition.Contains(" "))
// outdated save data, not worth recovering just reset it.
throw new Exception("invalid save data, resetting.");
var split = stringPosition.Split(','); var split = stringPosition.Split(',');
if (split.Length != 2) if (split.Length != 2)
throw new Exception($"stringPosition split is unexpected length: {split.Length}"); throw new Exception($"stringPosition split is unexpected length: {split.Length}");
Vector3 vector = rect.localPosition; Vector3 vector = rect.localPosition;
vector.x = float.Parse(split[0], ParseUtility.en_US); vector.x = float.Parse(split[0], CultureInfo.InvariantCulture);
vector.y = float.Parse(split[1], ParseUtility.en_US); vector.y = float.Parse(split[1], CultureInfo.InvariantCulture);
rect.localPosition = vector; rect.localPosition = vector;
} }
} }

View File

@ -16,12 +16,6 @@ namespace UnityExplorer.UI
internal static Vector2 _largeElementSize = new Vector2(100, 30); internal static Vector2 _largeElementSize = new Vector2(100, 30);
internal static Vector2 _smallElementSize = new Vector2(25, 25); internal static Vector2 _smallElementSize = new Vector2(25, 25);
internal static Color _defaultTextColor = Color.white; internal static Color _defaultTextColor = Color.white;
internal static Font _defaultFont;
public static void Init()
{
_defaultFont = Resources.GetBuiltinResource<Font>("Arial.ttf");
}
public static GameObject CreateUIObject(string name, GameObject parent, Vector2 size = default) public static GameObject CreateUIObject(string name, GameObject parent, Vector2 size = default)
{ {
@ -48,7 +42,7 @@ namespace UnityExplorer.UI
internal static void SetDefaultTextValues(Text text) internal static void SetDefaultTextValues(Text text)
{ {
text.color = _defaultTextColor; text.color = _defaultTextColor;
text.font = _defaultFont; text.font = UIManager.DefaultFont;
text.fontSize = 14; text.fontSize = 14;
} }

View File

@ -36,7 +36,7 @@ namespace UnityExplorer.UI
Bottom Bottom
} }
public static bool Initializing { get; private set; } = true; public static bool Initializing { get; internal set; } = true;
private static readonly Dictionary<Panels, UIPanel> UIPanels = new Dictionary<Panels, UIPanel>(); private static readonly Dictionary<Panels, UIPanel> UIPanels = new Dictionary<Panels, UIPanel>();
@ -52,6 +52,7 @@ namespace UnityExplorer.UI
internal static GameObject PanelHolder { get; private set; } internal static GameObject PanelHolder { get; private set; }
internal static Font ConsoleFont { get; private set; } internal static Font ConsoleFont { get; private set; }
internal static Font DefaultFont { get; private set; }
internal static Shader BackupShader { get; private set; } internal static Shader BackupShader { get; private set; }
public static RectTransform NavBarRect; public static RectTransform NavBarRect;
@ -92,8 +93,6 @@ namespace UnityExplorer.UI
{ {
LoadBundle(); LoadBundle();
UIFactory.Init();
CreateRootCanvas(); CreateRootCanvas();
// Global UI Pool Holder // Global UI Pool Holder
@ -423,11 +422,11 @@ namespace UnityExplorer.UI
int minor = int.Parse(split[1]); int minor = int.Parse(split[1]);
// Use appropriate AssetBundle for Unity version // Use appropriate AssetBundle for Unity version
// >= 2017.3 // >= 2017
if (major > 2017 || (major == 2017 && minor >= 3)) if (major >= 2017)
bundle = LoadBundle("modern"); bundle = LoadBundle("modern");
// 5.6.0 to 2017.3 // 5.6.0 to <2017
else if (major == 2017 || (major == 5 && minor >= 6)) else if (major == 5 && minor >= 6)
bundle = LoadBundle("legacy.5.6"); bundle = LoadBundle("legacy.5.6");
// < 5.6.0 // < 5.6.0
else else
@ -452,11 +451,15 @@ namespace UnityExplorer.UI
{ {
ExplorerCore.LogWarning("Could not load the ExplorerUI Bundle!"); ExplorerCore.LogWarning("Could not load the ExplorerUI Bundle!");
ConsoleFont = Resources.GetBuiltinResource<Font>("Arial.ttf"); ConsoleFont = Resources.GetBuiltinResource<Font>("Arial.ttf");
DefaultFont = ConsoleFont;
return; return;
} }
BackupShader = bundle.LoadAsset<Shader>("DefaultUI"); // Bundle loaded
ConsoleFont = bundle.LoadAsset<Font>("CONSOLA");
DefaultFont = bundle.LoadAsset<Font>("arial");
BackupShader = bundle.LoadAsset<Shader>("DefaultUI");
// Fix for games which don't ship with 'UI/Default' shader. // Fix for games which don't ship with 'UI/Default' shader.
if (Graphic.defaultGraphicMaterial.shader?.name != "UI/Default") if (Graphic.defaultGraphicMaterial.shader?.name != "UI/Default")
{ {
@ -466,7 +469,6 @@ namespace UnityExplorer.UI
else else
BackupShader = Graphic.defaultGraphicMaterial.shader; BackupShader = Graphic.defaultGraphicMaterial.shader;
ConsoleFont = bundle.LoadAsset<Font>("CONSOLA");
} }
private static byte[] ReadFully(Stream input) private static byte[] ReadFully(Stream input)

View File

@ -93,24 +93,6 @@
<IsCpp>true</IsCpp> <IsCpp>true</IsCpp>
<IsStandalone>true</IsStandalone> <IsStandalone>true</IsStandalone>
</PropertyGroup> </PropertyGroup>
<!-- ML 0.3.0 CPP -->
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release_MLLegacy_Cpp|AnyCPU'">
<OutputPath>..\Release\UnityExplorer.MelonLoader_Legacy.Il2Cpp\</OutputPath>
<DefineConstants>CPP,ML,ML_LEGACY</DefineConstants>
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
<AssemblyName>UnityExplorer.MLLEGACY.IL2CPP</AssemblyName>
<IsCpp>true</IsCpp>
<IsMelonLoaderLegacy>true</IsMelonLoaderLegacy>
</PropertyGroup>
<!-- ML 0.3.0 Mono -->
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release_MLLegacy_Mono|AnyCPU'">
<OutputPath>..\Release\UnityExplorer.MelonLoader_Legacy.Mono\</OutputPath>
<DefineConstants>MONO,ML,ML_LEGACY</DefineConstants>
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
<AssemblyName>UnityExplorer.MLLEGACY.Mono</AssemblyName>
<IsCpp>false</IsCpp>
<IsMelonLoaderLegacy>true</IsMelonLoaderLegacy>
</PropertyGroup>
<!-- Global refs, Mono and Il2Cpp --> <!-- Global refs, Mono and Il2Cpp -->
<ItemGroup> <ItemGroup>
<Reference Include="System" /> <Reference Include="System" />
@ -135,17 +117,10 @@
<Private>False</Private> <Private>False</Private>
</Reference> </Reference>
</ItemGroup> </ItemGroup>
<!-- MelonLoader Legacy refs -->
<ItemGroup Condition="'$(IsMelonLoaderLegacy)'=='true'">
<Reference Include="MelonLoader">
<HintPath>..\lib\MelonLoader_Legacy\MelonLoader.dll</HintPath>
<Private>False</Private>
</Reference>
</ItemGroup>
<!-- BepInEx universal refs --> <!-- BepInEx universal refs -->
<ItemGroup Condition="'$(IsBepInEx)'=='true'"> <ItemGroup Condition="'$(IsBepInEx)'=='true'">
<Reference Include="0Harmony"> <Reference Include="0Harmony">
<HintPath>packages\HarmonyX.2.4.2\lib\net35\0Harmony.dll</HintPath> <HintPath>packages\HarmonyX.2.5.2\lib\net35\0Harmony.dll</HintPath>
<Private>False</Private> <Private>False</Private>
</Reference> </Reference>
</ItemGroup> </ItemGroup>
@ -181,7 +156,7 @@
<!-- Standalone refs --> <!-- Standalone refs -->
<ItemGroup Condition="'$(IsStandalone)'=='true'"> <ItemGroup Condition="'$(IsStandalone)'=='true'">
<Reference Include="0Harmony"> <Reference Include="0Harmony">
<HintPath>packages\HarmonyX.2.4.2\lib\net35\0Harmony.dll</HintPath> <HintPath>packages\HarmonyX.2.5.2\lib\net35\0Harmony.dll</HintPath>
<Private>False</Private> <Private>False</Private>
</Reference> </Reference>
</ItemGroup> </ItemGroup>
@ -243,6 +218,7 @@
<Compile Include="Core\Config\InternalConfigHandler.cs" /> <Compile Include="Core\Config\InternalConfigHandler.cs" />
<Compile Include="CacheObject\CacheConfigEntry.cs" /> <Compile Include="CacheObject\CacheConfigEntry.cs" />
<Compile Include="CacheObject\Views\CacheConfigCell.cs" /> <Compile Include="CacheObject\Views\CacheConfigCell.cs" />
<Compile Include="Core\Reflection\Patches.cs" />
<Compile Include="CSConsole\CSAutoCompleter.cs" /> <Compile Include="CSConsole\CSAutoCompleter.cs" />
<Compile Include="CSConsole\LexerBuilder.cs" /> <Compile Include="CSConsole\LexerBuilder.cs" />
<Compile Include="CSConsole\Lexers\CommentLexer.cs" /> <Compile Include="CSConsole\Lexers\CommentLexer.cs" />
@ -323,13 +299,13 @@
<Compile Include="Core\Tests\TestClass.cs" /> <Compile Include="Core\Tests\TestClass.cs" />
<Compile Include="Core\Utility\UnityHelpers.cs" /> <Compile Include="Core\Utility\UnityHelpers.cs" />
<Compile Include="ExplorerCore.cs" /> <Compile Include="ExplorerCore.cs" />
<Compile Include="Loader\BIE\BepInExConfigHandler.cs" /> <Compile Include="Loader\BepInEx\BepInExConfigHandler.cs" />
<Compile Include="Loader\BIE\ExplorerBepInPlugin.cs" /> <Compile Include="Loader\BepInEx\ExplorerBepInPlugin.cs" />
<Compile Include="Loader\IExplorerLoader.cs" /> <Compile Include="Loader\IExplorerLoader.cs" />
<Compile Include="Loader\ML\ExplorerMelonMod.cs" /> <Compile Include="Loader\MelonLoader\ExplorerMelonMod.cs" />
<Compile Include="Loader\ML\MelonLoaderConfigHandler.cs" /> <Compile Include="Loader\MelonLoader\MelonLoaderConfigHandler.cs" />
<Compile Include="Loader\STANDALONE\ExplorerStandalone.cs" /> <Compile Include="Loader\Standalone\ExplorerStandalone.cs" />
<Compile Include="Loader\STANDALONE\StandaloneConfigHandler.cs" /> <Compile Include="Loader\Standalone\StandaloneConfigHandler.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="UI\Models\UIBehaviourModel.cs" /> <Compile Include="UI\Models\UIBehaviourModel.cs" />
<Compile Include="UI\Models\UIModel.cs" /> <Compile Include="UI\Models\UIModel.cs" />

View File

@ -16,8 +16,6 @@ Global
Release_BIE6_Mono|Any CPU = Release_BIE6_Mono|Any CPU Release_BIE6_Mono|Any CPU = Release_BIE6_Mono|Any CPU
Release_ML_Cpp|Any CPU = Release_ML_Cpp|Any CPU Release_ML_Cpp|Any CPU = Release_ML_Cpp|Any CPU
Release_ML_Mono|Any CPU = Release_ML_Mono|Any CPU Release_ML_Mono|Any CPU = Release_ML_Mono|Any CPU
Release_MLLegacy_Cpp|Any CPU = Release_MLLegacy_Cpp|Any CPU
Release_MLLegacy_Mono|Any CPU = Release_MLLegacy_Mono|Any CPU
Release_STANDALONE_Cpp|Any CPU = Release_STANDALONE_Cpp|Any CPU Release_STANDALONE_Cpp|Any CPU = Release_STANDALONE_Cpp|Any CPU
Release_STANDALONE_Mono|Any CPU = Release_STANDALONE_Mono|Any CPU Release_STANDALONE_Mono|Any CPU = Release_STANDALONE_Mono|Any CPU
EndGlobalSection EndGlobalSection
@ -32,10 +30,6 @@ Global
{7B7E5024-385D-4A46-9196-A6AF8F7FBDD5}.Release_ML_Cpp|Any CPU.Build.0 = Release|Any CPU {7B7E5024-385D-4A46-9196-A6AF8F7FBDD5}.Release_ML_Cpp|Any CPU.Build.0 = Release|Any CPU
{7B7E5024-385D-4A46-9196-A6AF8F7FBDD5}.Release_ML_Mono|Any CPU.ActiveCfg = Release|Any CPU {7B7E5024-385D-4A46-9196-A6AF8F7FBDD5}.Release_ML_Mono|Any CPU.ActiveCfg = Release|Any CPU
{7B7E5024-385D-4A46-9196-A6AF8F7FBDD5}.Release_ML_Mono|Any CPU.Build.0 = Release|Any CPU {7B7E5024-385D-4A46-9196-A6AF8F7FBDD5}.Release_ML_Mono|Any CPU.Build.0 = Release|Any CPU
{7B7E5024-385D-4A46-9196-A6AF8F7FBDD5}.Release_MLLegacy_Cpp|Any CPU.ActiveCfg = Release|Any CPU
{7B7E5024-385D-4A46-9196-A6AF8F7FBDD5}.Release_MLLegacy_Cpp|Any CPU.Build.0 = Release|Any CPU
{7B7E5024-385D-4A46-9196-A6AF8F7FBDD5}.Release_MLLegacy_Mono|Any CPU.ActiveCfg = Release|Any CPU
{7B7E5024-385D-4A46-9196-A6AF8F7FBDD5}.Release_MLLegacy_Mono|Any CPU.Build.0 = Release|Any CPU
{7B7E5024-385D-4A46-9196-A6AF8F7FBDD5}.Release_STANDALONE_Cpp|Any CPU.ActiveCfg = Release|Any CPU {7B7E5024-385D-4A46-9196-A6AF8F7FBDD5}.Release_STANDALONE_Cpp|Any CPU.ActiveCfg = Release|Any CPU
{7B7E5024-385D-4A46-9196-A6AF8F7FBDD5}.Release_STANDALONE_Cpp|Any CPU.Build.0 = Release|Any CPU {7B7E5024-385D-4A46-9196-A6AF8F7FBDD5}.Release_STANDALONE_Cpp|Any CPU.Build.0 = Release|Any CPU
{7B7E5024-385D-4A46-9196-A6AF8F7FBDD5}.Release_STANDALONE_Mono|Any CPU.ActiveCfg = Release|Any CPU {7B7E5024-385D-4A46-9196-A6AF8F7FBDD5}.Release_STANDALONE_Mono|Any CPU.ActiveCfg = Release|Any CPU
@ -50,10 +44,6 @@ Global
{E4989E4C-0875-4528-9031-08E2C0E70103}.Release_ML_Cpp|Any CPU.Build.0 = Release|Any CPU {E4989E4C-0875-4528-9031-08E2C0E70103}.Release_ML_Cpp|Any CPU.Build.0 = Release|Any CPU
{E4989E4C-0875-4528-9031-08E2C0E70103}.Release_ML_Mono|Any CPU.ActiveCfg = Release|Any CPU {E4989E4C-0875-4528-9031-08E2C0E70103}.Release_ML_Mono|Any CPU.ActiveCfg = Release|Any CPU
{E4989E4C-0875-4528-9031-08E2C0E70103}.Release_ML_Mono|Any CPU.Build.0 = Release|Any CPU {E4989E4C-0875-4528-9031-08E2C0E70103}.Release_ML_Mono|Any CPU.Build.0 = Release|Any CPU
{E4989E4C-0875-4528-9031-08E2C0E70103}.Release_MLLegacy_Cpp|Any CPU.ActiveCfg = Release|Any CPU
{E4989E4C-0875-4528-9031-08E2C0E70103}.Release_MLLegacy_Cpp|Any CPU.Build.0 = Release|Any CPU
{E4989E4C-0875-4528-9031-08E2C0E70103}.Release_MLLegacy_Mono|Any CPU.ActiveCfg = Release|Any CPU
{E4989E4C-0875-4528-9031-08E2C0E70103}.Release_MLLegacy_Mono|Any CPU.Build.0 = Release|Any CPU
{E4989E4C-0875-4528-9031-08E2C0E70103}.Release_STANDALONE_Cpp|Any CPU.ActiveCfg = Release|Any CPU {E4989E4C-0875-4528-9031-08E2C0E70103}.Release_STANDALONE_Cpp|Any CPU.ActiveCfg = Release|Any CPU
{E4989E4C-0875-4528-9031-08E2C0E70103}.Release_STANDALONE_Cpp|Any CPU.Build.0 = Release|Any CPU {E4989E4C-0875-4528-9031-08E2C0E70103}.Release_STANDALONE_Cpp|Any CPU.Build.0 = Release|Any CPU
{E4989E4C-0875-4528-9031-08E2C0E70103}.Release_STANDALONE_Mono|Any CPU.ActiveCfg = Release|Any CPU {E4989E4C-0875-4528-9031-08E2C0E70103}.Release_STANDALONE_Mono|Any CPU.ActiveCfg = Release|Any CPU
@ -68,10 +58,6 @@ Global
{B21DBDE3-5D6F-4726-93AB-CC3CC68BAE7D}.Release_ML_Cpp|Any CPU.Build.0 = Release_ML_Cpp|Any CPU {B21DBDE3-5D6F-4726-93AB-CC3CC68BAE7D}.Release_ML_Cpp|Any CPU.Build.0 = Release_ML_Cpp|Any CPU
{B21DBDE3-5D6F-4726-93AB-CC3CC68BAE7D}.Release_ML_Mono|Any CPU.ActiveCfg = Release_ML_Mono|Any CPU {B21DBDE3-5D6F-4726-93AB-CC3CC68BAE7D}.Release_ML_Mono|Any CPU.ActiveCfg = Release_ML_Mono|Any CPU
{B21DBDE3-5D6F-4726-93AB-CC3CC68BAE7D}.Release_ML_Mono|Any CPU.Build.0 = Release_ML_Mono|Any CPU {B21DBDE3-5D6F-4726-93AB-CC3CC68BAE7D}.Release_ML_Mono|Any CPU.Build.0 = Release_ML_Mono|Any CPU
{B21DBDE3-5D6F-4726-93AB-CC3CC68BAE7D}.Release_MLLegacy_Cpp|Any CPU.ActiveCfg = Release_MLLegacy_Cpp|Any CPU
{B21DBDE3-5D6F-4726-93AB-CC3CC68BAE7D}.Release_MLLegacy_Cpp|Any CPU.Build.0 = Release_MLLegacy_Cpp|Any CPU
{B21DBDE3-5D6F-4726-93AB-CC3CC68BAE7D}.Release_MLLegacy_Mono|Any CPU.ActiveCfg = Release_MLLegacy_Mono|Any CPU
{B21DBDE3-5D6F-4726-93AB-CC3CC68BAE7D}.Release_MLLegacy_Mono|Any CPU.Build.0 = Release_MLLegacy_Mono|Any CPU
{B21DBDE3-5D6F-4726-93AB-CC3CC68BAE7D}.Release_STANDALONE_Cpp|Any CPU.ActiveCfg = Release_STANDALONE_Cpp|Any CPU {B21DBDE3-5D6F-4726-93AB-CC3CC68BAE7D}.Release_STANDALONE_Cpp|Any CPU.ActiveCfg = Release_STANDALONE_Cpp|Any CPU
{B21DBDE3-5D6F-4726-93AB-CC3CC68BAE7D}.Release_STANDALONE_Cpp|Any CPU.Build.0 = Release_STANDALONE_Cpp|Any CPU {B21DBDE3-5D6F-4726-93AB-CC3CC68BAE7D}.Release_STANDALONE_Cpp|Any CPU.Build.0 = Release_STANDALONE_Cpp|Any CPU
{B21DBDE3-5D6F-4726-93AB-CC3CC68BAE7D}.Release_STANDALONE_Mono|Any CPU.ActiveCfg = Release_STANDALONE_Mono|Any CPU {B21DBDE3-5D6F-4726-93AB-CC3CC68BAE7D}.Release_STANDALONE_Mono|Any CPU.ActiveCfg = Release_STANDALONE_Mono|Any CPU

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<packages> <packages>
<package id="HarmonyX" version="2.4.2" targetFramework="net35" /> <package id="HarmonyX" version="2.5.2" targetFramework="net35" />
<package id="ILRepack.Lib.MSBuild.Task" version="2.0.18.2" targetFramework="net35" /> <package id="ILRepack.Lib.MSBuild.Task" version="2.0.18.2" targetFramework="net35" />
<package id="ini-parser" version="2.5.2" targetFramework="net35" /> <package id="ini-parser" version="2.5.2" targetFramework="net35" />
<package id="Mono.Cecil" version="0.10.4" targetFramework="net35" /> <package id="Mono.Cecil" version="0.10.4" targetFramework="net35" />