using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using MelonLoader;
using UnhollowerBaseLib;
using UnityEngine;
namespace Explorer
{
public abstract class CacheObject
{
public object Value;
public string ValueType;
// Reflection window only
public MemberInfo MemberInfo { get; set; }
public ReflectionWindow.MemberInfoType MemberInfoType { get; set; }
public Type DeclaringType { get; set; }
public object DeclaringInstance { get; set; }
public abstract void DrawValue(Rect window, float width);
public abstract void SetValue();
public static CacheObject GetCacheObject(object obj)
{
return GetCacheObject(obj, null, null);
}
public static CacheObject GetCacheObject(object obj, MemberInfo memberInfo, object declaringInstance)
{
CacheObject holder;
var type = ReflectionHelpers.GetActualType(obj) ?? (memberInfo as FieldInfo)?.FieldType ?? (memberInfo as PropertyInfo)?.PropertyType;
if (obj is Il2CppSystem.Object || typeof(Il2CppSystem.Object).IsAssignableFrom(type))
{
var name = type.FullName;
if (name == "UnityEngine.GameObject" || name == "UnityEngine.Transform")
{
holder = new CacheGameObject(obj);
}
else
{
holder = new CacheIl2CppObject();
}
}
else
{
if (type.IsPrimitive || type == typeof(string))
{
holder = new CachePrimitive(obj);
}
else if (type.IsEnum)
{
holder = new CacheEnum(obj);
}
else if (typeof(System.Collections.IEnumerable).IsAssignableFrom(type) || ReflectionHelpers.IsList(type))
{
holder = new CacheList(obj);
}
else if (type.IsValueType)
{
holder = new CacheStruct(obj);
}
else
{
holder = new CacheOther();
}
}
if (holder == null)
{
return null;
}
if (memberInfo != null)
{
holder.MemberInfo = memberInfo;
holder.DeclaringType = memberInfo.DeclaringType;
if (declaringInstance is Il2CppSystem.Object ilInstance && ilInstance.GetType() != memberInfo.DeclaringType)
{
try
{
holder.DeclaringInstance = ilInstance.Il2CppCast(holder.DeclaringType);
}
catch
{
holder.DeclaringInstance = declaringInstance;
}
}
else
{
holder.DeclaringInstance = declaringInstance;
}
if (memberInfo.MemberType == MemberTypes.Field)
{
holder.MemberInfoType = ReflectionWindow.MemberInfoType.Field;
}
else if (memberInfo.MemberType == MemberTypes.Property)
{
holder.MemberInfoType = ReflectionWindow.MemberInfoType.Property;
}
else if (memberInfo.MemberType == MemberTypes.Method)
{
holder.MemberInfoType = ReflectionWindow.MemberInfoType.Method;
}
}
holder.Value = obj;
holder.ValueType = type.FullName;
return holder;
}
public void Draw(Rect window, float labelWidth = 180f)
{
if (MemberInfo != null)
{
GUILayout.Label("" + MemberInfo.Name + ":", new GUILayoutOption[] { GUILayout.Width(labelWidth) });
}
else
{
GUILayout.Space(labelWidth);
}
if (Value == null)
{
GUILayout.Label("null (" + this.ValueType + ")", null);
}
else
{
DrawValue(window, window.width - labelWidth - 90);
}
}
public virtual void UpdateValue(object obj)
{
if (MemberInfo == null)
{
return;
}
try
{
if (MemberInfo.MemberType == MemberTypes.Field)
{
var fi = MemberInfo as FieldInfo;
Value = fi.GetValue(fi.IsStatic ? null : DeclaringInstance);
}
else if (MemberInfo.MemberType == MemberTypes.Property)
{
var pi = MemberInfo as PropertyInfo;
Value = pi.GetValue(pi.GetAccessors()[0].IsStatic ? null : DeclaringInstance, null);
}
}
catch //(Exception e)
{
//MelonLogger.Log($"Error updating MemberInfo value | {e.GetType()}: {e.Message}\r\n{e.StackTrace}");
}
}
public void SetValue(object value, MemberInfo memberInfo, object declaringInstance)
{
try
{
if (memberInfo.MemberType == MemberTypes.Field)
{
var fi = memberInfo as FieldInfo;
if (!(fi.IsLiteral && !fi.IsInitOnly))
{
fi.SetValue(fi.IsStatic ? null : declaringInstance, value);
}
}
else if (memberInfo.MemberType == MemberTypes.Property)
{
var pi = memberInfo as PropertyInfo;
if (pi.CanWrite)
{
pi.SetValue(pi.GetAccessors()[0].IsStatic ? null : declaringInstance, value);
}
}
}
catch (Exception e)
{
MelonLogger.LogWarning($"Error setting value: {e.GetType()}, {e.Message}");
}
}
}
}