using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using UnityEngine;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("ReflectionPlugin")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Nth Dimension")]
[assembly: AssemblyProduct("ReflectionPlugin")]
[assembly: AssemblyCopyright("Copyright © 2026")]
[assembly: AssemblyTrademark("ReflectionPlugin")]
[assembly: ComVisible(false)]
[assembly: Guid("c303405d-e66c-4316-9cdb-4e3ca15c6360")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace LordAshes;
[BepInPlugin("org.lordashes.plugins.reflection", "Reflection Plugin", "1.0.0.0")]
public class ReflectionPlugin : BaseUnityPlugin
{
public class Reflection
{
public static Type Type(string typeName, string[] has = null, string[] hasType = null, int resultIndex = 0)
{
Type[] array = Types(typeName, has, hasType);
return (array.Length != 0) ? array[resultIndex] : null;
}
public static Type[] Types(string typeName, string[] has = null, string[] hasType = null)
{
List<Type> list = new List<Type>();
Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
foreach (Assembly assembly in assemblies)
{
foreach (Type item in from t in assembly.GetTypes()
where t != null && t.Name == typeName
select t)
{
if (has == null)
{
list.Add(item);
continue;
}
for (int j = 0; j < has.Length; j++)
{
if (HasField(item, has[j], (hasType == null) ? null : hasType[j]) || HasProperty(item, has[j], (hasType == null) ? null : hasType[j]))
{
list.Add(item);
}
}
}
}
return list.ToArray();
}
public static object New(Type type, object[] constructorParamaters)
{
//IL_002d: Unknown result type (might be due to invalid IL or missing references)
//IL_0033: Invalid comparison between Unknown and I4
LoggingPlugin.LogInfo(type.Name + " Build With " + ((constructorParamaters != null) ? constructorParamaters.Length : 0) + " Parameters");
if ((int)LoggingPlugin.GetLogLevel() >= 4)
{
for (int i = 0; i < type.GetConstructors().Length; i++)
{
LoggingPlugin.LogInfo(type.Name + " Constructor #" + i + " (" + type.GetConstructors().ElementAt(i).GetParameters()
.Length + " Parameters)");
ParameterInfo[] parameters = type.GetConstructors().ElementAt(i).GetParameters();
foreach (ParameterInfo parameterInfo in parameters)
{
LoggingPlugin.LogInfo(type.Name + " Constructor #" + i + " Parameter: " + parameterInfo.Name + " (" + parameterInfo.ParameterType?.ToString() + ")");
}
}
}
return Activator.CreateInstance(type, constructorParamaters);
}
public static bool HasMethod(Type type, string methodName, string[] parameterTypes = null)
{
return Method(type, methodName, parameterTypes) != null;
}
public static MethodInfo Method(Type type, string methodName, string[] parameterTypes = null)
{
return Methods(type, methodName, parameterTypes).FirstOrDefault();
}
public static MethodInfo[] Methods(Type type, string methodName, string[] parameterTypes)
{
List<MethodInfo> list = new List<MethodInfo>();
list = ((methodName == null) ? type.GetRuntimeMethods().ToList() : ((parameterTypes != null) ? (from mi in type.GetRuntimeMethods()
where mi.Name == methodName && mi.GetParameters().Length == parameterTypes.Length
select mi).ToList() : (from mi in type.GetRuntimeMethods()
where mi.Name == methodName
select mi).ToList()));
for (int i = 0; i < list.Count; i++)
{
for (int j = 0; j < list[i].GetParameters().Length; j++)
{
if (parameterTypes != null && parameterTypes[j] != null && parameterTypes[j] != list[i].GetParameters()[j].ParameterType.ToString())
{
LoggingPlugin.LogDebug("Type '" + type.Name + "' Method '" + methodName + "' Variation " + i + " Parameter " + j + ": No Match (Have " + list[i].GetParameters()[j].ParameterType.ToString() + ", Need " + parameterTypes[j] + ")");
list.RemoveAt(i);
i--;
break;
}
}
}
LoggingPlugin.LogDebug("Type '" + type.Name + "' " + ((methodName != null && methodName != "") ? ("Method '" + methodName + "'") : "") + ": Found " + list.Count + " Matches");
return list.ToArray();
}
public static object Execute(MethodInfo method, object instance, object[] parameters, int resultIndex = 0)
{
List<object> list = new List<object>();
if (method.ReturnType != typeof(void))
{
list.Add(method.Invoke(instance, parameters));
}
else
{
method.Invoke(instance, parameters);
}
list.AddRange(parameters);
return list.ElementAt(resultIndex);
}
public static bool HasField(Type type, string fieldName, string fieldType = null)
{
return Field(type, fieldName, fieldType) != null;
}
public static FieldInfo Field(Type type, string fieldName, string fieldType = null)
{
return Fields(type, fieldName, fieldType = null).FirstOrDefault();
}
public static FieldInfo[] Fields(Type type, string fieldName, string fieldType = null)
{
List<FieldInfo> list = new List<FieldInfo>();
list = ((fieldName == null) ? type.GetRuntimeFields().ToList() : (from fi in type.GetRuntimeFields()
where fi.Name == fieldName && (fieldType == null || fi.FieldType.Name == fieldType)
select fi).ToList());
LoggingPlugin.LogDebug("Type '" + type.Name + "' " + ((fieldName != null && fieldName != "") ? ("Field '" + fieldName + "'") : "") + ": Found " + list.Count + " Matches");
return list.ToArray();
}
public static bool HasProperty(Type type, string propertyName, string propertyType = null)
{
return Property(type, propertyName, propertyType) != null;
}
public static PropertyInfo Property(Type type, string propertyName, string propertyType = null)
{
return Properties(type, propertyName, propertyType).FirstOrDefault();
}
public static PropertyInfo[] Properties(Type type, string propertyName, string propertyType = null)
{
List<PropertyInfo> list = new List<PropertyInfo>();
list = ((propertyName == null) ? type.GetRuntimeProperties().ToList() : (from fi in type.GetRuntimeProperties()
where fi.Name == propertyName && (propertyType == null || fi.PropertyType.Name == propertyType)
select fi).ToList());
LoggingPlugin.LogDebug("Type '" + type.Name + "' " + ((propertyName != null && propertyName != "") ? ("Field '" + propertyName + "'") : "") + ": Found " + list.Count + " Matches");
return list.ToArray();
}
public static void Info(Type type, object instance)
{
LoggingPlugin.LogInfo("Name: " + type.Name);
LoggingPlugin.LogInfo("Namespace: " + type.Namespace);
LoggingPlugin.LogInfo("Full Name: " + type.FullName);
LoggingPlugin.LogInfo("Assembly: " + type.Assembly.FullName);
LoggingPlugin.LogInfo("Type: " + ((instance == null) ? "Static" : "Instance"));
if (HasField(type, "Name"))
{
LoggingPlugin.LogInfo("Instance: " + Field(type, "Name").GetValue(instance));
}
if (HasProperty(type, "Name"))
{
LoggingPlugin.LogInfo("Instance: " + Property(type, "Name").GetValue(instance));
}
LoggingPlugin.LogInfo("Methods:");
MethodInfo[] array = Methods(type, null, null);
if (array.Length == 0)
{
LoggingPlugin.LogInfo(" {No Methods}");
}
MethodInfo[] array2 = array;
foreach (MethodInfo methodInfo in array2)
{
try
{
LoggingPlugin.LogInfo(" Method Name: " + methodInfo.Name);
LoggingPlugin.LogInfo(" Returns:" + methodInfo.ReturnParameter.Name + " (" + methodInfo.ReturnType.Name + ")");
ParameterInfo[] parameters = methodInfo.GetParameters();
foreach (ParameterInfo parameterInfo in parameters)
{
try
{
string text = " Parameter (";
if (parameterInfo.IsIn)
{
text += "In/";
}
if (parameterInfo.IsOut)
{
text += "Out/";
}
if (parameterInfo.ParameterType.IsByRef)
{
text += "Ref/";
}
if (parameterInfo.IsOptional)
{
text += "Op/";
}
if (text.EndsWith("/"))
{
text = text.Substring(0, text.Length - 1);
}
text = text + "): " + parameterInfo.Name + " (" + parameterInfo.ParameterType?.ToString() + ")";
text = text.Replace(" ()", "");
LoggingPlugin.LogInfo(text);
}
catch (Exception ex)
{
CatchFullError(ex);
}
}
}
catch (Exception ex2)
{
LoggingPlugin.LogInfo("Exception Analyzing Method");
CatchFullError(ex2);
}
}
LoggingPlugin.LogInfo("Fields:");
FieldInfo[] array3 = Fields(type, null);
if (array3.Length == 0)
{
LoggingPlugin.LogInfo(" {No Fields}");
}
FieldInfo[] array4 = array3;
foreach (FieldInfo fieldInfo in array4)
{
try
{
string text2 = " Field Name: " + fieldInfo.Name + " (" + fieldInfo.FieldType?.ToString() + ")";
try
{
text2 = ((fieldInfo.GetValue(instance) == null) ? (text2 + " = {NULL}") : (text2 + " = " + fieldInfo.GetValue(instance)));
}
catch (Exception ex3)
{
text2 = text2 + " = " + ex3.Message;
}
LoggingPlugin.LogInfo(text2);
}
catch (Exception ex4)
{
LoggingPlugin.LogInfo("Exception Analyzing Field");
CatchFullError(ex4);
}
}
LoggingPlugin.LogInfo("Properties:");
PropertyInfo[] array5 = Properties(type, null);
if (array5.Length == 0)
{
LoggingPlugin.LogInfo(" {No Properties}");
}
PropertyInfo[] array6 = array5;
foreach (PropertyInfo propertyInfo in array6)
{
try
{
string text3 = " Property Name:" + propertyInfo.Name + " (" + propertyInfo.PropertyType?.ToString() + ")";
try
{
text3 = ((propertyInfo.GetValue(instance) == null) ? (text3 + " = {NULL}") : (text3 + " = " + propertyInfo.GetValue(instance)));
}
catch (Exception ex5)
{
text3 = text3 + " = " + ex5.Message;
}
LoggingPlugin.LogInfo(text3);
}
catch (Exception ex6)
{
LoggingPlugin.LogInfo("Exception Analyzing Property");
CatchFullError(ex6);
}
}
}
public static bool HasEvent(Type type, string eventName)
{
return Event(type, eventName) != null;
}
public static EventInfo Event(Type type, string eventName, string eventType = null)
{
return Events(type, eventName).FirstOrDefault();
}
public static EventInfo[] Events(Type type, string eventName)
{
EventInfo[] array = (from ei in type.GetRuntimeEvents()
where ei.Name == eventName
select ei).ToArray();
LoggingPlugin.LogDebug("Type '" + type.Name + "' Event '" + eventName + "': Found " + array.Length + " Matches");
return array;
}
public static void AddEvent(Type type, string eventName, Delegate handler, object instance)
{
EventInfo eventInfo = Event(type, eventName);
if (eventInfo == null)
{
LoggingPlugin.LogError(type.Name + ": Event '" + eventName + "' Not Found In '" + type.Name + "'");
throw new Exception(type.Name + ": Event '" + eventName + "' Not Found In '" + type.Name + "'");
}
Type eventHandlerType = eventInfo.EventHandlerType;
Delegate handler2 = CreateCompatibleDelegate(eventHandlerType, handler);
eventInfo.AddEventHandler(instance, handler2);
}
private static Delegate CreateCompatibleDelegate(Type targetType, Delegate handler)
{
MethodInfo method = targetType.GetMethod("Invoke");
ParameterInfo[] parameters = method.GetParameters();
MethodInfo method2 = handler.Method;
object target = handler.Target;
ParameterInfo[] parameters2 = method2.GetParameters();
ParameterExpression[] array = parameters.Select((ParameterInfo p) => Expression.Parameter(p.ParameterType, p.Name)).ToArray();
Expression expression;
if (parameters2.Length == 0)
{
expression = Expression.Call((target == null) ? null : Expression.Constant(target), method2);
}
else if (parameters2.Length == 1 && parameters2[0].ParameterType == typeof(object))
{
Expression expression2 = ((array.Length != 0) ? ((Expression)Expression.Convert(array[0], typeof(object))) : ((Expression)Expression.Constant(null)));
expression = Expression.Call((target == null) ? null : Expression.Constant(target), method2, expression2);
}
else
{
if (parameters2.Length != 1 || !(parameters2[0].ParameterType == typeof(object[])))
{
throw new Exception("Handler signature not supported. Expected: (), (object), or (object[]). Got (" + string.Join(", ", parameters2.Select((ParameterInfo p) => p.ParameterType.Name)) + ")");
}
NewArrayExpression newArrayExpression = Expression.NewArrayInit(typeof(object), array.Select((ParameterExpression p) => Expression.Convert(p, typeof(object))));
expression = Expression.Call((target == null) ? null : Expression.Constant(target), method2, newArrayExpression);
}
if (!(method.ReturnType == typeof(void)))
{
expression = Expression.Convert(expression, method.ReturnType);
}
LambdaExpression lambdaExpression = Expression.Lambda(targetType, expression, array);
return lambdaExpression.Compile();
}
public static void CatchFullError(Exception ex)
{
LoggingPlugin.LogError(ex.Message);
while (ex.InnerException != null)
{
ex = ex.InnerException;
LoggingPlugin.LogError(ex.Message);
}
}
}
public const string Name = "Reflection Plugin";
public const string Guid = "org.lordashes.plugins.reflection";
public const string Version = "1.0.0.0";
public const string Author = "Lord Ashes";
public static ReflectionPlugin _self;
private void Awake()
{
//IL_001e: Unknown result type (might be due to invalid IL or missing references)
//IL_0039: Unknown result type (might be due to invalid IL or missing references)
//IL_003e: Unknown result type (might be due to invalid IL or missing references)
_self = this;
LoggingPlugin.SetLogLevel(((BaseUnityPlugin)this).Config.Bind<DiagnosticLevel>("Settings", "Diagnostic Level", (DiagnosticLevel)3, (ConfigDescription)null).Value);
string? assemblyQualifiedName = ((object)this).GetType().AssemblyQualifiedName;
DiagnosticLevel logLevel = LoggingPlugin.GetLogLevel();
Debug.Log((object)(assemblyQualifiedName + ": Active. (Diagnostic Mode = " + ((object)(DiagnosticLevel)(ref logLevel)).ToString() + ")"));
}
}