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;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("GenericClassPlugin")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Nth Dimension")]
[assembly: AssemblyProduct("GenericClassPlugin")]
[assembly: AssemblyCopyright("Copyright © 2026")]
[assembly: AssemblyTrademark("GenericClassPlugin")]
[assembly: ComVisible(false)]
[assembly: Guid("c303405d-e66c-4316-9cdb-4e3ca15c6360")]
[assembly: AssemblyFileVersion("1.0.4.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyVersion("1.0.4.0")]
namespace LordAshes;
[BepInPlugin("org.lordashes.plugins.genclass", "Generic Class Plugin", "1.0.4.0")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public class GenClassPlugin : BaseUnityPlugin
{
public class Generic
{
private Type _type = null;
private object _instance = null;
private string _name { get; } = "";
private string _location { get; } = "";
public Generic(Generic source, object instance = null)
{
_type = source._type;
if (_type != null)
{
_name = _type.FullName;
_location = _type.AssemblyQualifiedName;
_instance = instance;
return;
}
LoggingPlugin.LogError("Cloning From '" + source._name + "'");
throw new Exception("Cloning From '" + source._name + "'");
}
public Generic(Generic source, object[] constructorParms)
{
_type = source._type;
if (_type != null)
{
_name = _type.FullName;
_location = _type.AssemblyQualifiedName;
try
{
LoggingPlugin.LogDebug("Creature Default Instance With " + constructorParms.Length + " Construction Parameters");
_instance = Activator.CreateInstance(_type, constructorParms);
LoggingPlugin.LogTrace("Generic Class Has Instance? " + (_instance != null));
return;
}
catch (Exception innerException)
{
LoggingPlugin.LogError("Error In Constructing Type Instance");
LoggingPlugin.LogError(innerException.Message);
while (innerException.InnerException != null)
{
innerException = innerException.InnerException;
LoggingPlugin.LogError(innerException.Message);
}
LoggingPlugin.LogError("Constructor Parameters Provided:");
foreach (object obj in constructorParms)
{
LoggingPlugin.LogError(" Constructor Parameter: " + obj.GetType().Name);
}
ConstructorInfo[] constructors = _type.GetConstructors();
foreach (ConstructorInfo constructorInfo in constructors)
{
LoggingPlugin.LogError("Constructor Needed:");
ParameterInfo[] parameters = constructorInfo.GetParameters();
foreach (ParameterInfo parameterInfo in parameters)
{
LoggingPlugin.LogError(" Constructor Parameter: " + parameterInfo.ParameterType.Name + " (" + parameterInfo.Name + ")");
}
}
return;
}
}
LoggingPlugin.LogError("Cloning From '" + source._name + "'");
throw new Exception("Cloning From '" + source._name + "'");
}
public Generic(Type type, object instance = null)
{
_type = type;
_instance = instance;
}
public Generic(string typeName, object instance = null)
{
_type = GetType(typeName, null);
if (_type != null)
{
_name = _type.FullName;
_location = _type.AssemblyQualifiedName;
_instance = instance;
return;
}
LoggingPlugin.LogError("Type '" + typeName + "' Not Found");
throw new Exception("Type '" + typeName + "' Not Found");
}
public Generic(string typeName, string[] has, object instance = null)
{
_type = GetType(typeName, has);
if (_type != null)
{
_name = _type.FullName;
_location = _type.AssemblyQualifiedName;
_instance = instance;
return;
}
LoggingPlugin.LogError("Type '" + typeName + "' Not Found");
throw new Exception("Type '" + typeName + "' Not Found");
}
public Generic(string typeName, string[] has, object[] constructorParms)
{
_type = GetType(typeName, has);
if (_type != null)
{
_name = _type.FullName;
_location = _type.AssemblyQualifiedName;
try
{
LoggingPlugin.LogDebug("Creature Default Instance With " + constructorParms.Length + " Construction Parameters");
_instance = Activator.CreateInstance(_type, constructorParms);
LoggingPlugin.LogTrace("Generic Class Has Instance? " + (_instance != null));
return;
}
catch (Exception innerException)
{
LoggingPlugin.LogError("Error In Constructing Type Instance");
LoggingPlugin.LogError(innerException.Message);
while (innerException.InnerException != null)
{
innerException = innerException.InnerException;
LoggingPlugin.LogError(innerException.Message);
}
LoggingPlugin.LogError("Constructor Parameters Provided:");
foreach (object obj in constructorParms)
{
LoggingPlugin.LogError(" Constructor Parameter: " + obj.GetType().Name);
}
ConstructorInfo[] constructors = _type.GetConstructors();
foreach (ConstructorInfo constructorInfo in constructors)
{
LoggingPlugin.LogError("Constructor Needed:");
ParameterInfo[] parameters = constructorInfo.GetParameters();
foreach (ParameterInfo parameterInfo in parameters)
{
LoggingPlugin.LogError(" Constructor Parameter: " + parameterInfo.ParameterType.Name + " (" + parameterInfo.Name + ")");
}
}
return;
}
}
LoggingPlugin.LogError("Type '" + typeName + "' Not Found");
throw new Exception("Type '" + typeName + "' Not Found");
}
public static Generic Close(string baseTypeName, string closeTypeName, object instance = null)
{
Generic generic = new Generic(baseTypeName, null);
Generic generic2 = new Generic(closeTypeName, null);
Type type = generic.Type().MakeGenericType(generic2.Type());
return new Generic(type, instance);
}
public string Name()
{
return _name;
}
public string Location()
{
return _location;
}
public object Instance()
{
return _instance;
}
public Type Type()
{
return _type;
}
public object[] Invoke(string methodName, params object[] paramList)
{
LoggingPlugin.LogDebug("Invoking '" + methodName + "' On '" + _type.Name + "'");
MethodInfo methodInfo = Method(methodName);
if (methodInfo != null)
{
return DoInvoke(methodInfo, paramList);
}
LoggingPlugin.LogDebug("Suitable Method '" + methodName + "' Not Found. Unable To Invoke.");
return null;
}
public object[] Invoke(string methodName, string[] paramTypes, object[] paramList)
{
LoggingPlugin.LogDebug("Invoking '" + methodName + "' On '" + _type.Name + "'");
MethodInfo methodInfo = Method(methodName, paramTypes);
if (methodInfo != null)
{
return DoInvoke(methodInfo, paramList);
}
LoggingPlugin.LogDebug("Suitable Method '" + methodName + "' Not Found. Unable To Invoke.");
return null;
}
public Generic Invoke(string methodName, string[] paramTypes, object[] paramList, string resultType, int resultIndex = 0)
{
LoggingPlugin.LogDebug("Invoking '" + methodName + "' On '" + _type.Name + "'");
MethodInfo methodInfo = Method(methodName, paramTypes);
if (methodInfo != null)
{
return new Generic(resultType, DoInvoke(methodInfo, paramList)[resultIndex]);
}
LoggingPlugin.LogDebug("Suitable Method '" + methodName + "' Not Found. Unable To Invoke.");
return null;
}
private object[] DoInvoke(MethodInfo method, params object[] paramList)
{
if (method != null)
{
LoggingPlugin.LogTrace(_type.Name + ": Setting Types For Output Parameters Type.");
ParameterInfo[] parameters = method.GetParameters();
for (int i = 0; i < parameters.Length; i++)
{
try
{
Type parameterType = parameters[i].ParameterType;
if (typeof(Delegate).IsAssignableFrom(parameterType) && paramList[i] is Delegate handler)
{
LoggingPlugin.LogTrace(_type.Name + ": Adapting delegate parameter " + i);
paramList[i] = CreateCompatibleDelegate(parameterType, handler);
}
}
catch (Exception ex)
{
LoggingPlugin.LogError(_type.Name + ": Exception Adapting Delegate Parameter " + i + " (" + parameters[i].ParameterType?.ToString() + ")");
LoggingPlugin.LogError(ex.Message);
if (ex.InnerException != null)
{
LoggingPlugin.LogError(ex.InnerException.Message);
}
}
}
for (int j = 0; j < method.GetParameters().Length; j++)
{
if (method.GetParameters()[j].IsOut && paramList[j] == null)
{
try
{
paramList[j] = Activator.CreateInstance(method.GetParameters()[j].ParameterType);
}
catch (Exception ex2)
{
paramList[j] = null;
LoggingPlugin.LogWarning(_type.Name + ": Exception Setting Ouput Parameters Type. " + ex2.Message);
}
}
}
LoggingPlugin.LogTrace(_type.Name + ": Invoking Compatible Method '" + method.Name + "'.");
List<object> list = new List<object>();
try
{
if (method.ReturnType != typeof(void))
{
list.Add(method.Invoke(_instance, paramList));
LoggingPlugin.LogTrace(_type.Name + ": Invoke Of " + method.Name + " With Results Successful");
}
else
{
method.Invoke(_instance, paramList);
LoggingPlugin.LogTrace(_type.Name + ": Invoke Of " + method.Name + " Without Results Successful");
}
}
catch (Exception ex3)
{
LoggingPlugin.LogError(_type.Name + ": Exception Invoking Compatible Method. " + ex3.Message);
if (ex3.InnerException != null)
{
LoggingPlugin.LogError(_type.Name + ": Exception Invoking Compatible Method. " + ex3.InnerException.Message);
}
}
LoggingPlugin.LogTrace(_type.Name + ": Gathering Output Parameters.");
for (int k = 0; k < paramList.Length; k++)
{
if (method.GetParameters()[k].IsOut)
{
list.Add(paramList[k]);
}
}
LoggingPlugin.LogTrace(_type.Name + ": Returning Output Parameters.");
if (list.Count > 0)
{
return list.ToArray();
}
return null;
}
LoggingPlugin.LogError(_type.Name + ": No Compatible Method '" + method.Name + "' Found.");
throw new Exception(_type.Name + ": No Compatible Method '" + method.Name + "' Found.");
}
public object Get(string name)
{
FieldInfo[] array = (from fi in _type.GetRuntimeFields()
where fi.Name == name
select fi).ToArray();
if (array.Length != 0)
{
LoggingPlugin.LogTrace(_type?.ToString() + " Entry '" + name + "' Get As Field");
return array[0].GetValue(_instance);
}
PropertyInfo[] array2 = (from pi in _type.GetRuntimeProperties()
where pi.Name == name
select pi).ToArray();
if (array2.Length != 0)
{
LoggingPlugin.LogTrace(_type?.ToString() + " Entry '" + name + "' Get As Property");
return array2[0].GetValue(_instance);
}
LoggingPlugin.LogTrace(_type?.ToString() + " Entry '" + name + "' Not Found (Get)");
return null;
}
public T Get<T>(string name)
{
return (T)Get(name);
}
public Generic GetAsGeneric(string name)
{
if (HasField(_type, name))
{
return new Generic(_type.GetField(name).FieldType.Name, _type.GetField(name).GetValue(_instance));
}
if (HasProperty(_type, name))
{
return new Generic(_type.GetProperty(name).PropertyType.Name, _type.GetProperty(name).GetValue(_instance));
}
return new Generic(null, null);
}
public void Set(string name, object value)
{
FieldInfo[] array = (from fi in _type.GetRuntimeFields()
where fi.Name == name
select fi).ToArray();
if (array.Length != 0)
{
LoggingPlugin.LogTrace(_type?.ToString() + " Entry '" + name + "' Set As Field");
array[0].SetValue(_instance, value);
return;
}
PropertyInfo[] array2 = (from pi in _type.GetRuntimeProperties()
where pi.Name == name
select pi).ToArray();
if (array2.Length != 0)
{
LoggingPlugin.LogTrace(_type?.ToString() + " Entry '" + name + "' Set As Property");
array2[0].SetValue(_instance, value);
}
else
{
LoggingPlugin.LogTrace(_type?.ToString() + " Entry '" + name + "' Not Found (Set)");
}
}
public void AddEvent(string eventName, Delegate handler)
{
EventInfo @event = _type.GetEvent(eventName, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
if (@event == null)
{
LoggingPlugin.LogError(_type.Name + ": Event '" + _name + "' Not Found In '" + _type.Name + "'");
throw new Exception(_type.Name + ": Event '" + _name + "' Not Found In '" + _type.Name + "'");
}
Type eventHandlerType = @event.EventHandlerType;
Delegate handler2 = CreateCompatibleDelegate(eventHandlerType, handler);
@event.AddEventHandler(_instance, handler2);
}
public static void Info(object obj)
{
LoggingPlugin.LogInfo("Object Type: " + obj.GetType());
Type type = obj.GetType();
Info(type, obj);
}
public static void Info(Type type, object obj)
{
foreach (MethodInfo runtimeMethod in type.GetRuntimeMethods())
{
string text = type.Name + " Method: " + runtimeMethod.Name + " (";
ParameterInfo[] parameters = runtimeMethod.GetParameters();
foreach (ParameterInfo parameterInfo in parameters)
{
text = text + parameterInfo.Name + ":" + parameterInfo.ParameterType.Name + ",";
}
if (text.EndsWith(","))
{
text = text.Substring(0, text.Length - 1);
}
text += ")";
LoggingPlugin.LogInfo(text);
}
foreach (FieldInfo runtimeField in type.GetRuntimeFields())
{
string text2 = type.Name + " Field: " + runtimeField.Name + " (" + runtimeField.FieldType?.ToString() + ") ";
try
{
text2 = text2 + " = " + runtimeField.GetValue(obj);
}
catch
{
}
LoggingPlugin.LogInfo(text2);
}
foreach (PropertyInfo runtimeProperty in type.GetRuntimeProperties())
{
string text3 = type.Name + " Property: " + runtimeProperty.Name + " (" + runtimeProperty.PropertyType?.ToString() + ")";
try
{
text3 = text3 + " = " + runtimeProperty.GetValue(obj);
}
catch
{
}
LoggingPlugin.LogInfo(text3);
}
}
public MethodInfo Method(string methodName)
{
return Method(methodName, null);
}
public MethodInfo Method(string methodName, string[] paramTypes)
{
LoggingPlugin.LogDebug(_type.Name + ": Found " + _type.GetRuntimeMethods().Count() + " Methods On Type " + _type.Name);
foreach (MethodInfo item in from mi in _type.GetRuntimeMethods()
where mi.Name == methodName
select mi)
{
bool flag = true;
if (paramTypes != null)
{
if (item.GetParameters().Length == paramTypes.Length)
{
for (int i = 0; i < paramTypes.Length; i++)
{
if (paramTypes != null && paramTypes[i] != null && item.GetParameters()[i].ParameterType.Name.ToUpper() != paramTypes[i].ToUpper())
{
LoggingPlugin.LogTrace(_type.Name + ": Incompatible Method '" + item.Name + "' Parameter Type (Has " + item.GetParameters()[i].ParameterType.Name + " But Needs " + paramTypes[i] + ")");
flag = false;
}
else
{
LoggingPlugin.LogTrace(_type.Name + ": Compatible Method '" + item.Name + "' Parameter Type (Is " + item.GetParameters()[i].ParameterType.Name + " Vs " + ((paramTypes[i] != null) ? paramTypes[i] : "(Any)") + ")");
}
}
}
else
{
LoggingPlugin.LogTrace(_type.Name + ": Incompatible Method '" + item.Name + "' Due To Parameter Count (Has " + item.GetParameters().Length + " But Needs " + paramTypes.Length + ")");
flag = false;
}
}
if (flag)
{
return item;
}
}
return null;
}
public MethodInfo[] Methods(string methodName, string[] paramTypes)
{
LoggingPlugin.LogDebug(_type.Name + ": Found " + _type.GetRuntimeMethods().Count() + " Methods On Type " + _type.Name);
List<MethodInfo> list = new List<MethodInfo>();
foreach (MethodInfo item in from mi in _type.GetRuntimeMethods()
where mi.Name == methodName
select mi)
{
bool flag = true;
if (paramTypes != null)
{
if (item.GetParameters().Length == paramTypes.Length)
{
for (int i = 0; i < paramTypes.Length; i++)
{
if (paramTypes != null && paramTypes[i] != null && item.GetParameters()[i].ParameterType.Name.ToUpper() != paramTypes[i].ToUpper())
{
LoggingPlugin.LogTrace(_type.Name + ": Incompatible Method '" + item.Name + "' Parameter Type (Has " + item.GetParameters()[i].ParameterType.Name + " But Needs " + paramTypes[i] + ")");
flag = false;
}
else
{
LoggingPlugin.LogTrace(_type.Name + ": Compatible Method '" + item.Name + "' Parameter Type (Is " + item.GetParameters()[i].ParameterType.Name + " Vs " + ((paramTypes[i] != null) ? paramTypes[i] : "(Any)") + ")");
}
}
}
else
{
LoggingPlugin.LogTrace(_type.Name + ": Incompatible Method '" + item.Name + "' Due To Parameter Count (Has " + item.GetParameters().Length + " But Needs " + paramTypes.Length + ")");
flag = false;
}
}
if (flag)
{
list.Add(item);
}
}
return list.ToArray();
}
public FieldInfo Field(string fieldName, string paramType = null)
{
FieldInfo[] source = (from fi in _type.GetRuntimeFields()
where fi.Name == fieldName
select fi).ToArray();
if (paramType != null)
{
source = source.Where((FieldInfo fi) => fi.FieldType.Name == paramType).ToArray();
}
return source.FirstOrDefault();
}
public PropertyInfo Property(string propertyName, string paramType = null)
{
PropertyInfo[] source = (from pi in _type.GetRuntimeProperties()
where pi.Name == propertyName
select pi).ToArray();
if (paramType != null)
{
source = source.Where((PropertyInfo fi) => fi.PropertyType.Name == paramType).ToArray();
}
return source.FirstOrDefault();
}
private 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 Type GetType(string typeName, string[] has)
{
Type[] array = AppDomain.CurrentDomain.GetAssemblies().SelectMany(delegate(Assembly a)
{
try
{
return a.GetTypes();
}
catch (ReflectionTypeLoadException ex)
{
return ex.Types.Where((Type t) => t != null);
}
}).ToArray();
if (has == null)
{
LoggingPlugin.LogDebug("Found " + array.Length + " Possible '" + typeName + "' Definitions. Using First.");
return array.FirstOrDefault((Type t) => t.FullName == typeName || t.Name == typeName);
}
LoggingPlugin.LogDebug("Found " + array.Length + " Possible '" + typeName + "' Definitions. Looking For Conditions.");
for (int i = 0; i < array.Length; i++)
{
LoggingPlugin.LogTrace("Testing Type '" + typeName + "' #" + (i + 1));
bool flag = true;
foreach (string text in has)
{
if (!HasField(array[i], text) && !HasProperty(array[i], text))
{
LoggingPlugin.LogTrace("Failed Conditions '" + text + "'");
flag = false;
break;
}
}
if (flag)
{
LoggingPlugin.LogDebug("Found '" + typeName + "' Definitions That Matches All Conditions.");
return array[i];
}
}
LoggingPlugin.LogDebug("Type '" + typeName + "' Not Found.");
return null;
}
public static bool HasField(Type type, string fieldName)
{
return (from fi in type.GetRuntimeFields()
where fi.Name == fieldName
select fi).Count() > 0;
}
public static bool HasProperty(Type type, string propertyName)
{
return (from fi in type.GetRuntimeProperties()
where fi.Name == propertyName
select fi).Count() > 0;
}
}
public const string Name = "Generic Class Plugin";
public const string Guid = "org.lordashes.plugins.genclass";
public const string Version = "1.0.4.0";
public const string Author = "Lord Ashes";
private void Awake()
{
//IL_0018: Unknown result type (might be due to invalid IL or missing references)
//IL_0033: Unknown result type (might be due to invalid IL or missing references)
//IL_0038: Unknown result type (might be due to invalid IL or missing references)
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();
LoggingPlugin.LogInfo(assemblyQualifiedName + ": Active. (Diagnostic Mode = " + ((object)(DiagnosticLevel)(ref logLevel)).ToString() + ")");
}
}