Decompiled source of BOMBANANA Library v1.0.0

plugins/BOMBANANA.Library-1.0.0.dll

Decompiled 2 weeks ago
using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.ExceptionServices;
using System.Runtime.Versioning;
using System.Text;
using BOMBANANA.Library.Reflection;
using BepInEx;
using BepInEx.Logging;
using BepInEx.Unity.IL2CPP;
using Microsoft.CodeAnalysis;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("BOMBANANA.Library")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("BOMBANANA.Library")]
[assembly: AssemblyTitle("BOMBANANA.Library")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace BOMBANANA.Library
{
	[BepInPlugin("bombanana.library", "BOMBANANA Library", "1.0.0")]
	public sealed class LibraryPlugin : BasePlugin
	{
		internal static ManualLogSource Log;

		public override void Load()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Expected O, but got Unknown
			Log = new ManualLogSource("BOMBANANA Library");
			Log.LogInfo((object)"BOMBANANA Library v1.0.0 loaded — resolver ready");
		}
	}
}
namespace BOMBANANA.Library.Reflection
{
	internal static class ArgumentCoercer
	{
		public static bool Match(ParameterInfo[] parameters, object?[] args)
		{
			if (parameters.Length != args.Length)
			{
				return false;
			}
			for (int i = 0; i < parameters.Length; i++)
			{
				if (!CanCoerce(args[i], parameters[i].ParameterType))
				{
					return false;
				}
			}
			return true;
		}

		public static object?[] Coerce(MethodBase method, object?[] args)
		{
			ParameterInfo[] parameters = method.GetParameters();
			object[] array = new object[parameters.Length];
			for (int i = 0; i < parameters.Length; i++)
			{
				array[i] = CoerceValue(args[i], parameters[i].ParameterType);
			}
			return array;
		}

		public static object? CoerceValue(object? value, Type target)
		{
			if (value == null)
			{
				return null;
			}
			Type type = value.GetType();
			if (target.IsAssignableFrom(type))
			{
				return value;
			}
			if (target.IsEnum)
			{
				if (!(value is string value2))
				{
					return Enum.ToObject(target, value);
				}
				return Enum.Parse(target, value2, ignoreCase: true);
			}
			if (target.IsArray && value is Array array)
			{
				Type elementType = target.GetElementType();
				Array array2 = Array.CreateInstance(elementType, array.Length);
				for (int i = 0; i < array.Length; i++)
				{
					array2.SetValue(CoerceValue(array.GetValue(i), elementType), i);
				}
				return array2;
			}
			if (IsIl2CppArrayType(target) && value is IEnumerable items)
			{
				return BuildIl2CppArray(target, items);
			}
			if (value is IConvertible)
			{
				return Convert.ChangeType(value, target, CultureInfo.InvariantCulture);
			}
			return value;
		}

		private static bool IsIl2CppArrayType(Type target)
		{
			bool flag = (object)target != null && target.IsGenericType && target.Namespace == "Il2CppInterop.Runtime.InteropTypes.Arrays";
			if (flag)
			{
				string name = target.Name;
				bool flag2 = ((name == "Il2CppReferenceArray`1" || name == "Il2CppStructArray`1") ? true : false);
				flag = flag2;
			}
			return flag;
		}

		private static object BuildIl2CppArray(Type target, IEnumerable items)
		{
			MethodInfo methodInfo = target.GetProperty("Item")?.GetSetMethod();
			if ((object)methodInfo == null)
			{
				throw new InvalidOperationException($"No indexer setter on interop array type {target}.");
			}
			Type target2 = target.GetGenericArguments()[0];
			object[] array = items.Cast<object>().ToArray();
			object obj = Activator.CreateInstance(target, array.Length) ?? throw new InvalidOperationException($"Cannot create interop array {target}.");
			int num = 0;
			object[] array2 = array;
			foreach (object value in array2)
			{
				methodInfo.Invoke(obj, new object[2]
				{
					num,
					CoerceValue(value, target2)
				});
				num++;
			}
			return obj;
		}

		private static bool CanCoerce(object? value, Type target)
		{
			if (value == null)
			{
				if (target.IsValueType)
				{
					return (object)Nullable.GetUnderlyingType(target) != null;
				}
				return true;
			}
			Type type = value.GetType();
			if (target.IsAssignableFrom(type))
			{
				return true;
			}
			if (target.IsEnum && value is IConvertible)
			{
				return true;
			}
			if (target.IsPrimitive && value is IConvertible)
			{
				return true;
			}
			if (IsIl2CppArrayType(target) && value is IEnumerable)
			{
				return true;
			}
			return target == typeof(string);
		}
	}
	public static class ReflectionHelpers
	{
		private const BindingFlags All = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;

		private static readonly TypeResolver Resolver = TypeResolver.Default;

		public static Type? GetType(params string[] candidateNames)
		{
			foreach (string typeName in candidateNames)
			{
				Type type = Resolver.Resolve(typeName);
				if ((object)type != null)
				{
					return type;
				}
			}
			return null;
		}

		public static object? GetValue(object instance, string name)
		{
			if (instance == null)
			{
				throw new ArgumentNullException("instance");
			}
			Type type = instance.GetType();
			PropertyInfo propertyInfo = FindProperty(type, name);
			if ((object)propertyInfo != null)
			{
				return propertyInfo.GetValue(instance);
			}
			return FindField(type, name)?.GetValue(instance);
		}

		public static void SetValue(object instance, string name, object? value)
		{
			if (instance == null)
			{
				throw new ArgumentNullException("instance");
			}
			Type type = instance.GetType();
			PropertyInfo propertyInfo = FindProperty(type, name);
			if ((object)propertyInfo != null)
			{
				propertyInfo.SetValue(instance, Coerce(value, propertyInfo.PropertyType));
				return;
			}
			FieldInfo fieldInfo = FindField(type, name) ?? throw new MissingMemberException(type.FullName, name);
			fieldInfo.SetValue(instance, Coerce(value, fieldInfo.FieldType));
		}

		public static object? GetStaticValue(Type type, string name)
		{
			PropertyInfo propertyInfo = FindProperty(type, name);
			if ((object)propertyInfo != null)
			{
				return propertyInfo.GetValue(null);
			}
			return FindField(type, name)?.GetValue(null);
		}

		public static void SetStaticValue(Type type, string name, object? value)
		{
			PropertyInfo propertyInfo = FindProperty(type, name);
			if ((object)propertyInfo != null)
			{
				propertyInfo.SetValue(null, Coerce(value, propertyInfo.PropertyType));
				return;
			}
			FieldInfo fieldInfo = FindField(type, name) ?? throw new MissingMemberException(type.FullName, name);
			fieldInfo.SetValue(null, Coerce(value, fieldInfo.FieldType));
		}

		public static int GetInt(object instance, string name)
		{
			return Convert.ToInt32(GetValue(instance, name));
		}

		public static uint GetUInt(object instance, string name)
		{
			return Convert.ToUInt32(GetValue(instance, name));
		}

		public static ushort GetUShort(object instance, string name)
		{
			return Convert.ToUInt16(GetValue(instance, name));
		}

		public static bool GetBool(object instance, string name)
		{
			return Convert.ToBoolean(GetValue(instance, name));
		}

		public static string? GetString(object instance, string name)
		{
			object value = GetValue(instance, name);
			object obj;
			if (value != null)
			{
				obj = value as string;
				if (obj == null)
				{
					return value.ToString();
				}
			}
			else
			{
				obj = null;
			}
			return (string?)obj;
		}

		public static MethodInfo? FindMethod(Type type, string name, int paramCount)
		{
			return type.GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic).FirstOrDefault((MethodInfo m) => m.Name == name && !m.IsGenericMethod && m.GetParameters().Length == paramCount);
		}

		public static MethodInfo? FindMethod(Type type, string name, Type[] paramTypes)
		{
			return type.GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic).FirstOrDefault((MethodInfo m) => m.Name == name && !m.IsGenericMethod && (from p in m.GetParameters()
				select p.ParameterType).SequenceEqual(paramTypes));
		}

		public static MethodInfo? FindMethod(Type type, string name, params object?[] args)
		{
			return (from m in type.GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)
				where m.Name == name && !m.IsGenericMethod
				orderby m.IsStatic
				select m).FirstOrDefault((MethodInfo m) => Match(m.GetParameters(), args));
		}

		public static object? Invoke(object instance, string name, params object?[] args)
		{
			MethodInfo methodInfo = FindMethod(instance.GetType(), name, args) ?? throw new MissingMethodException(instance.GetType().FullName, name);
			return methodInfo.Invoke(methodInfo.IsStatic ? null : instance, Coerce(methodInfo, args));
		}

		public static object? InvokeStatic(Type type, string name, params object?[] args)
		{
			MethodInfo methodInfo = FindMethod(type, name, args) ?? throw new MissingMethodException(type.FullName, name);
			return methodInfo.Invoke(null, Coerce(methodInfo, args));
		}

		public static object? InvokeGeneric(object instance, string name, Type typeArg, params object?[] args)
		{
			MethodInfo methodInfo = FindGenericMethod(instance.GetType(), name, typeArg, args) ?? throw new MissingMethodException(instance.GetType().FullName, name);
			return methodInfo.Invoke(methodInfo.IsStatic ? null : instance, Coerce(methodInfo, args));
		}

		public static object? InvokeStaticGeneric(Type type, string name, Type typeArg, params object?[] args)
		{
			MethodInfo methodInfo = FindGenericMethod(type, name, typeArg, args) ?? throw new MissingMethodException(type.FullName, name);
			return methodInfo.Invoke(null, Coerce(methodInfo, args));
		}

		public static object CreateInstance(Type type, params object?[] args)
		{
			return Activator.CreateInstance(type, args) ?? throw new MissingMethodException(type.FullName, ".ctor");
		}

		public static object?[]? ToObjects(object? value)
		{
			if (value is Array source)
			{
				return source.Cast<object>().ToArray();
			}
			if (value is IEnumerable source2)
			{
				return source2.Cast<object>().ToArray();
			}
			return null;
		}

		public static object BuildArray(Type arrayType, object?[] items)
		{
			if (arrayType.IsArray)
			{
				Type elementType = arrayType.GetElementType();
				Array array = Array.CreateInstance(elementType, items.Length);
				for (int i = 0; i < items.Length; i++)
				{
					array.SetValue(Coerce(items[i], elementType), i);
				}
				return array;
			}
			return BuildIl2CppArray(arrayType, items);
		}

		public static bool Match(ParameterInfo[] parameters, object?[] args)
		{
			if (parameters.Length != args.Length)
			{
				return false;
			}
			for (int i = 0; i < parameters.Length; i++)
			{
				if (!CanCoerce(args[i], parameters[i].ParameterType))
				{
					return false;
				}
			}
			return true;
		}

		public static object?[] Coerce(MethodBase method, object?[] args)
		{
			ParameterInfo[] parameters = method.GetParameters();
			object[] array = new object[parameters.Length];
			for (int i = 0; i < parameters.Length; i++)
			{
				array[i] = CoerceValue(args[i], parameters[i].ParameterType);
			}
			return array;
		}

		public static object? Coerce(object? value, Type target)
		{
			return CoerceValue(value, target);
		}

		private static MethodInfo? FindGenericMethod(Type type, string name, Type typeArg, object?[] args)
		{
			foreach (MethodInfo item in from m in type.GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)
				where m.Name == name && m.IsGenericMethod
				select m)
			{
				try
				{
					MethodInfo methodInfo = item.MakeGenericMethod(typeArg);
					if (Match(methodInfo.GetParameters(), args))
					{
						return methodInfo;
					}
				}
				catch (Exception ex) when (((ex is InvalidOperationException || ex is NotSupportedException || ex is TypeLoadException || ex is TypeInitializationException || ex is ArgumentException) ? 1 : 0) != 0)
				{
				}
			}
			return null;
		}

		private static PropertyInfo? FindProperty(Type type, string name)
		{
			Type type2 = type;
			while ((object)type2 != null)
			{
				PropertyInfo property = type2.GetProperty(name, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
				if ((object)property != null)
				{
					return property;
				}
				type2 = type2.BaseType;
			}
			return null;
		}

		private static FieldInfo? FindField(Type type, string name)
		{
			Type type2 = type;
			while ((object)type2 != null)
			{
				FieldInfo field = type2.GetField(name, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
				if ((object)field != null)
				{
					return field;
				}
				type2 = type2.BaseType;
			}
			return null;
		}

		private static object BuildIl2CppArray(Type target, object?[] items)
		{
			MethodInfo methodInfo = target.GetProperty("Item")?.GetSetMethod() ?? throw new InvalidOperationException($"No indexer setter on interop array type {target}.");
			Type target2 = target.GetGenericArguments()[0];
			object obj = Activator.CreateInstance(target, items.Length) ?? throw new InvalidOperationException($"Cannot create interop array {target}.");
			for (int i = 0; i < items.Length; i++)
			{
				methodInfo.Invoke(obj, new object[2]
				{
					i,
					CoerceValue(items[i], target2)
				});
			}
			return obj;
		}

		private static object? CoerceValue(object? value, Type target)
		{
			if (value == null)
			{
				return null;
			}
			Type type = value.GetType();
			if (target.IsAssignableFrom(type))
			{
				return value;
			}
			if (target.IsEnum)
			{
				if (!(value is string value2))
				{
					return Enum.ToObject(target, value);
				}
				return Enum.Parse(target, value2, ignoreCase: true);
			}
			if (target.IsArray && value is Array array)
			{
				Type elementType = target.GetElementType();
				Array array2 = Array.CreateInstance(elementType, array.Length);
				for (int i = 0; i < array.Length; i++)
				{
					array2.SetValue(CoerceValue(array.GetValue(i), elementType), i);
				}
				return array2;
			}
			if (IsIl2CppArrayType(target) && value is IEnumerable value3)
			{
				return BuildIl2CppArray(target, ToObjects(value3) ?? Array.Empty<object>());
			}
			if (value is IConvertible)
			{
				return Convert.ChangeType(value, target, CultureInfo.InvariantCulture);
			}
			return value;
		}

		private static bool IsIl2CppArrayType(Type target)
		{
			bool flag = (object)target != null && target.IsGenericType && target.Namespace == "Il2CppInterop.Runtime.InteropTypes.Arrays";
			if (flag)
			{
				string name = target.Name;
				bool flag2 = ((name == "Il2CppReferenceArray`1" || name == "Il2CppStructArray`1") ? true : false);
				flag = flag2;
			}
			return flag;
		}

		private static bool CanCoerce(object? value, Type target)
		{
			if (value == null)
			{
				if (target.IsValueType)
				{
					return (object)Nullable.GetUnderlyingType(target) != null;
				}
				return true;
			}
			Type type = value.GetType();
			if (target.IsAssignableFrom(type))
			{
				return true;
			}
			if (target.IsEnum && value is IConvertible)
			{
				return true;
			}
			if (target.IsPrimitive && value is IConvertible)
			{
				return true;
			}
			if (IsIl2CppArrayType(target) && value is IEnumerable)
			{
				return true;
			}
			return target == typeof(string);
		}
	}
	public sealed class RefObj
	{
		private const BindingFlags AllBindings = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;

		public object Instance { get; }

		public RefType Type { get; }

		public RefObj(object instance)
		{
			Instance = instance ?? throw new ArgumentNullException("instance");
			Type = new RefType(instance.GetType());
		}

		public object? GetField(string name)
		{
			FieldInfo fieldInfo = FindField(name);
			try
			{
				if ((object)fieldInfo != null)
				{
					return fieldInfo.GetValue(Instance);
				}
			}
			catch (Exception ex) when (((ex is TargetInvocationException || ex is NullReferenceException || ex is ArgumentException || ex is TypeInitializationException) ? 1 : 0) != 0)
			{
				return null;
			}
			return FindProperty(name)?.GetValue(Instance);
		}

		public void SetField(string name, object? value)
		{
			FieldInfo fieldInfo = FindField(name);
			if ((object)fieldInfo != null)
			{
				fieldInfo.SetValue(Instance, ArgumentCoercer.CoerceValue(value, fieldInfo.FieldType));
				return;
			}
			PropertyInfo propertyInfo = FindProperty(name) ?? throw new MissingMemberException(Type.FullName, name);
			propertyInfo.SetValue(Instance, ArgumentCoercer.CoerceValue(value, propertyInfo.PropertyType));
		}

		public object? GetProperty(string name)
		{
			PropertyInfo propertyInfo = FindProperty(name);
			try
			{
				if ((object)propertyInfo != null)
				{
					return propertyInfo.GetValue(Instance);
				}
			}
			catch (Exception ex) when (((ex is TargetInvocationException || ex is NullReferenceException || ex is ArgumentException || ex is TypeInitializationException) ? 1 : 0) != 0)
			{
				return null;
			}
			return FindField(name)?.GetValue(Instance);
		}

		public void SetProperty(string name, object? value)
		{
			PropertyInfo propertyInfo = FindProperty(name);
			if ((object)propertyInfo != null)
			{
				propertyInfo.SetValue(Instance, ArgumentCoercer.CoerceValue(value, propertyInfo.PropertyType));
				return;
			}
			FieldInfo fieldInfo = FindField(name) ?? throw new MissingMemberException(Type.FullName, name);
			fieldInfo.SetValue(Instance, ArgumentCoercer.CoerceValue(value, fieldInfo.FieldType));
		}

		public object? Call(string name, params object?[] args)
		{
			MethodInfo methodInfo = FindMethod(name, args);
			if ((object)methodInfo == null)
			{
				throw new MissingMethodException(Type.FullName, name);
			}
			try
			{
				return methodInfo.Invoke(methodInfo.IsStatic ? null : Instance, ArgumentCoercer.Coerce(methodInfo, args));
			}
			catch (TargetInvocationException ex) when (ex.InnerException != null)
			{
				ExceptionDispatchInfo.Capture(ex.InnerException).Throw();
				throw;
			}
		}

		public void AddEvent(string name, Delegate handler)
		{
			(FindEvent(name) ?? throw new MissingMemberException(Type.FullName, name)).AddEventHandler(Instance, handler);
		}

		public void RemoveEvent(string name, Delegate handler)
		{
			(FindEvent(name) ?? throw new MissingMemberException(Type.FullName, name)).RemoveEventHandler(Instance, handler);
		}

		private MethodInfo? FindMethod(string name, object?[] args)
		{
			MethodInfo[] array = (from m in Type.Type.GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)
				where m.Name == name && !m.IsGenericMethod
				orderby m.IsStatic
				select m).ToArray();
			foreach (MethodInfo methodInfo in array)
			{
				if (ArgumentCoercer.Match(methodInfo.GetParameters(), args))
				{
					return methodInfo;
				}
			}
			return null;
		}

		private FieldInfo? FindField(string name)
		{
			Type type = Type.Type;
			while ((object)type != null)
			{
				FieldInfo field = type.GetField(name, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
				if ((object)field != null)
				{
					return field;
				}
				type = type.BaseType;
			}
			return null;
		}

		private PropertyInfo? FindProperty(string name)
		{
			Type type = Type.Type;
			while ((object)type != null)
			{
				PropertyInfo property = type.GetProperty(name, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
				if ((object)property != null)
				{
					return property;
				}
				type = type.BaseType;
			}
			return null;
		}

		public object? GetIndex(string name, params object?[] indexArgs)
		{
			return FindProperty(name)?.GetValue(Instance, indexArgs);
		}

		private EventInfo? FindEvent(string name)
		{
			Type type = Type.Type;
			while ((object)type != null)
			{
				EventInfo eventInfo = type.GetEvent(name, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
				if ((object)eventInfo != null)
				{
					return eventInfo;
				}
				type = type.BaseType;
			}
			return null;
		}
	}
	public sealed class RefType
	{
		private const BindingFlags AllBindings = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;

		public Type Type { get; }

		public string FullName => Type.FullName ?? Type.Name;

		public bool IsEnum => Type.IsEnum;

		public string[] EnumNames
		{
			get
			{
				if (!IsEnum)
				{
					return Array.Empty<string>();
				}
				return Enum.GetNames(Type);
			}
		}

		public RefType(Type type)
		{
			Type = type ?? throw new ArgumentNullException("type");
		}

		public object ParseEnum(string name)
		{
			return Enum.Parse(Type, name, ignoreCase: true);
		}

		public object EnumFromValue(object value)
		{
			return Enum.ToObject(Type, value);
		}

		public object? GetStaticField(string name)
		{
			FieldInfo fieldInfo = FindField(name);
			if ((object)fieldInfo != null)
			{
				return fieldInfo.GetValue(null);
			}
			return FindProperty(name)?.GetValue(null);
		}

		public void SetStaticField(string name, object? value)
		{
			FieldInfo fieldInfo = FindField(name);
			if ((object)fieldInfo != null)
			{
				fieldInfo.SetValue(null, ArgumentCoercer.CoerceValue(value, fieldInfo.FieldType));
				return;
			}
			PropertyInfo propertyInfo = FindProperty(name) ?? throw new MissingMemberException(Type.FullName, name);
			propertyInfo.SetValue(null, ArgumentCoercer.CoerceValue(value, propertyInfo.PropertyType));
		}

		public object? GetStaticProperty(string name)
		{
			PropertyInfo propertyInfo = FindProperty(name);
			if ((object)propertyInfo != null)
			{
				return propertyInfo.GetValue(null);
			}
			return FindField(name)?.GetValue(null);
		}

		public object? InvokeStatic(string name, params object?[] args)
		{
			MethodInfo methodInfo = FindMethod(name, args);
			return methodInfo?.Invoke(null, ArgumentCoercer.Coerce(methodInfo, args));
		}

		public object CreateInstance(params object?[] args)
		{
			return Activator.CreateInstance(Type, args) ?? throw new MissingMethodException(Type.FullName, ".ctor");
		}

		public RefObj? Singleton(string fieldName)
		{
			object staticField = GetStaticField(fieldName);
			if (staticField != null)
			{
				return new RefObj(staticField);
			}
			return null;
		}

		private MethodInfo? FindMethod(string name, object?[] args)
		{
			MethodInfo[] array = (from m in Type.GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)
				where m.Name == name && !m.IsGenericMethod
				orderby m.IsStatic
				select m).ToArray();
			foreach (MethodInfo methodInfo in array)
			{
				if (ArgumentCoercer.Match(methodInfo.GetParameters(), args))
				{
					return methodInfo;
				}
			}
			return null;
		}

		private FieldInfo? FindField(string name)
		{
			Type type = Type;
			while ((object)type != null)
			{
				FieldInfo field = type.GetField(name, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
				if ((object)field != null)
				{
					return field;
				}
				type = type.BaseType;
			}
			return null;
		}

		private PropertyInfo? FindProperty(string name)
		{
			Type type = Type;
			while ((object)type != null)
			{
				PropertyInfo property = type.GetProperty(name, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
				if ((object)property != null)
				{
					return property;
				}
				type = type.BaseType;
			}
			return null;
		}
	}
	public sealed class TypeResolver
	{
		private sealed class MissSentinelMarker
		{
		}

		private readonly ConcurrentDictionary<string, Type> _cache = new ConcurrentDictionary<string, Type>(StringComparer.OrdinalIgnoreCase);

		private readonly Func<string, Type?>? _external;

		private static readonly Type? MissSentinel = typeof(MissSentinelMarker);

		public static TypeResolver Default { get; } = new TypeResolver();

		public TypeResolver(Func<string, Type?>? external = null)
		{
			_external = external;
		}

		public Type? Resolve(string typeName)
		{
			if (typeName == null)
			{
				throw new ArgumentNullException("typeName");
			}
			if (_cache.TryGetValue(typeName, out Type value))
			{
				if ((object)value != MissSentinel)
				{
					return value;
				}
				return null;
			}
			Type type = ResolveCore(typeName);
			_cache[typeName] = type ?? MissSentinel;
			return type;
		}

		public void Clear()
		{
			_cache.Clear();
		}

		private Type? ResolveCore(string typeName)
		{
			Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
			for (int i = 0; i < assemblies.Length; i++)
			{
				Type type = assemblies[i].GetType(typeName, throwOnError: false);
				if ((object)type != null)
				{
					return type;
				}
			}
			if (_external != null)
			{
				Type type2 = _external(typeName);
				if ((object)type2 != null)
				{
					return type2;
				}
			}
			return FindUniqueBySimpleName(typeName);
		}

		private static Type? FindUniqueBySimpleName(string simpleName)
		{
			Type result = null;
			int num = 0;
			Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
			for (int i = 0; i < assemblies.Length; i++)
			{
				foreach (Type item in SafeGetTypes(assemblies[i]))
				{
					if (string.Equals(item.Name, simpleName, StringComparison.OrdinalIgnoreCase) || string.Equals(item.FullName, simpleName, StringComparison.OrdinalIgnoreCase))
					{
						result = item;
						num++;
						if (num > 1)
						{
							return null;
						}
					}
				}
			}
			if (num != 1)
			{
				return null;
			}
			return result;
		}

		private static IEnumerable<Type> SafeGetTypes(Assembly assembly)
		{
			try
			{
				return assembly.GetTypes();
			}
			catch (ReflectionTypeLoadException ex)
			{
				return ex.Types.Where((Type t) => (object)t != null).Cast<Type>();
			}
			catch
			{
				return Array.Empty<Type>();
			}
		}
	}
}
namespace BOMBANANA.Library.Game
{
	public static class AudioApi
	{
		private static readonly TypeResolver Resolver = TypeResolver.Default;

		public static RefType? Type
		{
			get
			{
				Type type = Resolver.Resolve("BombGame.Audio.GameAudioMixer");
				if ((object)type == null)
				{
					return null;
				}
				return new RefType(type);
			}
		}

		public static void SetMasterVolume(float linearVolume)
		{
			Type?.InvokeStatic("SetMasterVolume", linearVolume);
		}

		public static void EnsureLoaded()
		{
			Type?.InvokeStatic("EnsureLoaded");
		}

		public static float LinearToDb(float linearVolume)
		{
			object obj = Type?.InvokeStatic("LinearToDb", linearVolume);
			if (obj is float)
			{
				return (float)obj;
			}
			return 0f;
		}
	}
	public static class UISoundPlayerApi
	{
		private static readonly TypeResolver Resolver = TypeResolver.Default;

		public static RefType? Type
		{
			get
			{
				Type type = Resolver.Resolve("BombGame.Audio.UISoundPlayer");
				if ((object)type == null)
				{
					return null;
				}
				return new RefType(type);
			}
		}

		public static RefObj? Instance
		{
			get
			{
				object obj = Type?.GetStaticProperty("Instance");
				if (obj == null)
				{
					return null;
				}
				return new RefObj(obj);
			}
		}

		public static void Play(string key)
		{
			Type?.InvokeStatic("Play", key);
		}

		public static void PlayOrDefault(string key, string fallbackKey)
		{
			Type?.InvokeStatic("PlayOrDefault", key, fallbackKey);
		}

		public static void PlayMusic(string key)
		{
			Type?.InvokeStatic("PlayMusic", key);
		}

		public static void StopMusic()
		{
			Type?.InvokeStatic("StopMusic");
		}

		public static void SetMusicVolume(float linearVolume)
		{
			Type?.InvokeStatic("SetMusicVolume", linearVolume);
		}

		public static bool? HasKey(string key)
		{
			return Type?.InvokeStatic("HasKey", key) as bool?;
		}
	}
	public static class UISoundToolkitApi
	{
		private static readonly TypeResolver Resolver = TypeResolver.Default;

		public static RefType? Type
		{
			get
			{
				Type type = Resolver.Resolve("BombGame.Audio.UISoundToolkit");
				if ((object)type == null)
				{
					return null;
				}
				return new RefType(type);
			}
		}

		public static void Bind(object root)
		{
			Type?.InvokeStatic("Bind", root);
		}

		public static void SetClickSound(object button, string soundKey)
		{
			Type?.InvokeStatic("SetClickSound", button, soundKey);
		}

		public static void SetHoverSound(object button, string soundKey)
		{
			Type?.InvokeStatic("SetHoverSound", button, soundKey);
		}

		public static string? ResolveSoundKeyFromName(string elementName)
		{
			return Type?.InvokeStatic("ResolveSoundKeyFromName", elementName) as string;
		}
	}
	public static class SoundPlaybackApi
	{
		private static readonly TypeResolver Resolver = TypeResolver.Default;

		public static RefType? Type
		{
			get
			{
				Type type = Resolver.Resolve("BombGame.Audio.SoundPlayback");
				if ((object)type == null)
				{
					return null;
				}
				return new RefType(type);
			}
		}

		public static void Play(object soundList, object soundData, object parent)
		{
			Type?.InvokeStatic("Play", soundList, soundData, parent);
		}
	}
	public static class NetworkAudioSourceApi
	{
		private static readonly TypeResolver Resolver = TypeResolver.Default;

		public static RefType? Type
		{
			get
			{
				Type type = Resolver.Resolve("BombGame.Audio.NetworkAudioSource");
				if ((object)type == null)
				{
					return null;
				}
				return new RefType(type);
			}
		}

		public static void PlayNetworked(RefObj audioSource, string key)
		{
			audioSource?.Call("PlayNetworked", key);
		}
	}
	public static class AudioVolumeGainApi
	{
		private static readonly TypeResolver Resolver = TypeResolver.Default;

		public static RefType? Type
		{
			get
			{
				Type type = Resolver.Resolve("BombGame.Audio.AudioVolumeGain");
				if ((object)type == null)
				{
					return null;
				}
				return new RefType(type);
			}
		}

		public static RefObj[] FindAll()
		{
			return GameApi.FindInstances("BombGame.Audio.AudioVolumeGain");
		}

		public static void SetGain(RefObj gain, float volume)
		{
			gain?.Call("SetGain", volume);
		}
	}
	public static class AudioGateApi
	{
		private static readonly TypeResolver Resolver = TypeResolver.Default;

		public static RefType? Type
		{
			get
			{
				Type type = Resolver.Resolve("BombGame.Audio.LocalPlayerAudioGate");
				if ((object)type == null)
				{
					return null;
				}
				return new RefType(type);
			}
		}

		public static bool ShouldSuppressWorldSfx => Type?.GetStaticProperty("ShouldSuppressWorldSfx") as bool? == true;
	}
	public static class BlindedsApi
	{
		private static readonly TypeResolver Resolver = TypeResolver.Default;

		public static RefType? Type
		{
			get
			{
				Type type = Resolver.Resolve("BombGame.Blindeds");
				if ((object)type == null)
				{
					return null;
				}
				return new RefType(type);
			}
		}

		public static RefObj[] FindAll()
		{
			return GameApi.FindInstances("BombGame.Blindeds");
		}

		public static object? GetBlindedMaterial(RefObj blindeds)
		{
			return blindeds?.GetField("BlindedMaterial");
		}

		public static object? GetPermaBlindedMaterial(RefObj blindeds)
		{
			return blindeds?.GetField("PermaBlindedMaterial");
		}

		public static object? GetHandBlindedMaterial(RefObj blindeds)
		{
			return blindeds?.GetField("HandBlindedMaterial");
		}

		public static RefObj[] FindObjectsByLayer(int layerMask)
		{
			object obj = Type?.InvokeStatic("FindObjectsByLayer", layerMask);
			if (obj == null)
			{
				return Array.Empty<RefObj>();
			}
			return GameApi.EnumerateObjects(obj)?.Select((object o) => new RefObj(o)).ToArray() ?? Array.Empty<RefObj>();
		}
	}
	public static class BombApi
	{
		private sealed class EventSubscription : IDisposable
		{
			private readonly EventInfo _event;

			private readonly object _target;

			private readonly Delegate _handler;

			public EventSubscription(EventInfo evt, object target, Delegate handler)
			{
				_event = evt;
				_target = target;
				_handler = handler;
			}

			public void Dispose()
			{
				try
				{
					_event.RemoveEventHandler(_target, _handler);
				}
				catch (Exception)
				{
				}
			}
		}

		private sealed class NoOpDisposable : IDisposable
		{
			public void Dispose()
			{
			}
		}

		private static readonly TypeResolver Resolver = TypeResolver.Default;

		private static RefType? BombType
		{
			get
			{
				Type type = Resolver.Resolve("BombGame.Bomb");
				if ((object)type == null)
				{
					return null;
				}
				return new RefType(type);
			}
		}

		public static RefObj? Bomb => GameApi.Bomb;

		public static bool? IsActive => Bomb?.GetProperty("Active") as bool?;

		public static ushort? Health
		{
			get
			{
				RefObj bomb = Bomb;
				if (bomb == null)
				{
					return null;
				}
				try
				{
					return Convert.ToUInt16(bomb.GetProperty("Health"));
				}
				catch
				{
					return null;
				}
			}
			set
			{
				if (value.HasValue)
				{
					RefObj bomb = Bomb;
					if (bomb != null)
					{
						ushort max = MaxHealth ?? ushort.MaxValue;
						bomb.SetProperty("Health", Math.Clamp(value.Value, (ushort)0, max));
					}
				}
			}
		}

		public static ushort? MaxHealth
		{
			get
			{
				RefObj bomb = Bomb;
				if (bomb == null)
				{
					return null;
				}
				try
				{
					return Convert.ToUInt16(bomb.GetProperty("MaxHealth"));
				}
				catch
				{
					return null;
				}
			}
		}

		public static uint? Timer
		{
			get
			{
				RefObj bomb = Bomb;
				if (bomb == null)
				{
					return null;
				}
				try
				{
					return Convert.ToUInt32(bomb.GetProperty("Timer"));
				}
				catch
				{
					return null;
				}
			}
		}

		public static RefObj? Screen
		{
			get
			{
				object obj = Bomb?.GetField("Screen");
				if (obj == null)
				{
					return null;
				}
				return new RefObj(obj);
			}
		}

		public static RefObj? SocketsContainer
		{
			get
			{
				object obj = Bomb?.GetField("SocketsContainer");
				if (obj == null)
				{
					return null;
				}
				return new RefObj(obj);
			}
		}

		public static int? SocketCount => SocketsContainer?.GetProperty("childCount") as int?;

		public static RefObj[] ActiveModules
		{
			get
			{
				if (Bomb == null)
				{
					return Array.Empty<RefObj>();
				}
				object field = Bomb.GetField("ActiveModules");
				if (field == null)
				{
					return Array.Empty<RefObj>();
				}
				return GameApi.EnumerateObjects(field)?.Select((object o) => new RefObj(o)).ToArray() ?? Array.Empty<RefObj>();
			}
		}

		public static int ModuleCount => ActiveModules.Length;

		public static RefObj? Random
		{
			get
			{
				object obj = Bomb?.GetField("Random");
				if (obj == null)
				{
					return null;
				}
				return new RefObj(obj);
			}
		}

		public static RefObj? FocusableCamera
		{
			get
			{
				object obj = Bomb?.GetField("FocusableCamera");
				if (obj == null)
				{
					return null;
				}
				return new RefObj(obj);
			}
		}

		public static IDisposable SubscribeOnExplode(Action callback)
		{
			return SubscribeEvent("OnExplode", callback);
		}

		public static IDisposable SubscribeOnDisarm(Action callback)
		{
			return SubscribeEvent("OnDisarm", callback);
		}

		public static IDisposable SubscribeOnDamage(Action<int> callback)
		{
			return SubscribeEvent("OnDamage", callback);
		}

		public static IDisposable SubscribeOnTick(Action<int> callback)
		{
			return SubscribeEvent("OnTick", callback);
		}

		public static void SilentTerminate()
		{
			Bomb?.Call("SilentTerminate");
		}

		public static bool CanFocus(PlayerRoleInfo role)
		{
			if (Bomb == null)
			{
				return false;
			}
			object obj = Bomb.Call("CanFocus", (int)role);
			if (obj is bool)
			{
				return (bool)obj;
			}
			return false;
		}

		public static (float x, float y, float z)? FocusedPosition()
		{
			if (Bomb == null)
			{
				return null;
			}
			object obj = Bomb.Call("FocusedPosition");
			if (obj == null)
			{
				return null;
			}
			return UnityTypesApi.GetVector3Components(obj);
		}

		public static (float x, float y, float z)? FocusedEulerAngles()
		{
			if (Bomb == null)
			{
				return null;
			}
			object obj = Bomb.Call("FocusedEulerAngles");
			if (obj == null)
			{
				return null;
			}
			return UnityTypesApi.GetVector3Components(obj);
		}

		public static string DescribeBomb()
		{
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.AppendLine("=== Bomb ===");
			StringBuilder stringBuilder2 = stringBuilder;
			StringBuilder stringBuilder3 = stringBuilder2;
			StringBuilder.AppendInterpolatedStringHandler handler = new StringBuilder.AppendInterpolatedStringHandler(8, 1, stringBuilder2);
			handler.AppendLiteral("Active: ");
			handler.AppendFormatted(IsActive);
			stringBuilder3.AppendLine(ref handler);
			stringBuilder2 = stringBuilder;
			StringBuilder stringBuilder4 = stringBuilder2;
			handler = new StringBuilder.AppendInterpolatedStringHandler(9, 2, stringBuilder2);
			handler.AppendLiteral("Health: ");
			handler.AppendFormatted(Health);
			handler.AppendLiteral("/");
			handler.AppendFormatted(MaxHealth);
			stringBuilder4.AppendLine(ref handler);
			stringBuilder2 = stringBuilder;
			StringBuilder stringBuilder5 = stringBuilder2;
			handler = new StringBuilder.AppendInterpolatedStringHandler(8, 1, stringBuilder2);
			handler.AppendLiteral("Timer: ");
			handler.AppendFormatted(Timer);
			handler.AppendLiteral("s");
			stringBuilder5.AppendLine(ref handler);
			stringBuilder2 = stringBuilder;
			StringBuilder stringBuilder6 = stringBuilder2;
			handler = new StringBuilder.AppendInterpolatedStringHandler(9, 1, stringBuilder2);
			handler.AppendLiteral("Modules: ");
			handler.AppendFormatted(ModuleCount);
			stringBuilder6.AppendLine(ref handler);
			stringBuilder2 = stringBuilder;
			StringBuilder stringBuilder7 = stringBuilder2;
			handler = new StringBuilder.AppendInterpolatedStringHandler(9, 1, stringBuilder2);
			handler.AppendLiteral("Sockets: ");
			handler.AppendFormatted(SocketCount);
			stringBuilder7.AppendLine(ref handler);
			RefObj[] activeModules = ActiveModules;
			foreach (RefObj obj in activeModules)
			{
				string value = obj.GetProperty("name")?.ToString() ?? "Unknown";
				string value2 = obj.Instance?.GetType()?.Name ?? "Unknown";
				stringBuilder2 = stringBuilder;
				StringBuilder stringBuilder8 = stringBuilder2;
				handler = new StringBuilder.AppendInterpolatedStringHandler(5, 2, stringBuilder2);
				handler.AppendLiteral("  [");
				handler.AppendFormatted(value2);
				handler.AppendLiteral("] ");
				handler.AppendFormatted(value);
				stringBuilder8.AppendLine(ref handler);
			}
			return stringBuilder.ToString();
		}

		private static IDisposable SubscribeEvent(string eventName, Delegate callback)
		{
			if (Bomb == null)
			{
				return new NoOpDisposable();
			}
			EventInfo eventInfo = FindEvent(Bomb.Type.Type, eventName);
			if ((object)eventInfo == null)
			{
				return new NoOpDisposable();
			}
			if ((object)eventInfo.EventHandlerType == null)
			{
				return new NoOpDisposable();
			}
			try
			{
				eventInfo.AddEventHandler(Bomb.Instance, callback);
				return new EventSubscription(eventInfo, Bomb.Instance, callback);
			}
			catch (Exception)
			{
				return new NoOpDisposable();
			}
		}

		private static EventInfo? FindEvent(Type type, string name)
		{
			Type type2 = type;
			while ((object)type2 != null)
			{
				EventInfo eventInfo = type2.GetEvent(name, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
				if ((object)eventInfo != null)
				{
					return eventInfo;
				}
				type2 = type2.BaseType;
			}
			return null;
		}
	}
	public enum CableColor
	{
		Red,
		Blue,
		Green,
		Yellow
	}
	public enum Direction
	{
		Up,
		Right,
		Down,
		Left
	}
	public readonly record struct CableInfo
	{
		public int Index { get; }

		public CableColor Color { get; }

		public bool IsCut { get; }

		internal CableInfo(int index, string colorName, bool isCut)
		{
			Index = index;
			Color = colorName switch
			{
				"RED" => CableColor.Red, 
				"BLUE" => CableColor.Blue, 
				"GREEN" => CableColor.Green, 
				"YELLOW" => CableColor.Yellow, 
				_ => CableColor.Red, 
			};
			IsCut = isCut;
		}
	}
	public readonly record struct CalculatorButtonInfo(int index, int number);
	public readonly record struct ColorSwitchInfo(int index, bool isOn);
	public readonly record struct SymbolInfo(int index, int symbolId);
	public readonly record struct ColorCombination(string[] colors);
	public static class BombModuleApi
	{
		private static readonly TypeResolver Resolver = TypeResolver.Default;

		private static RefType? Type
		{
			get
			{
				Type type = Resolver.Resolve("BombGame.BombModule");
				if ((object)type == null)
				{
					return null;
				}
				return new RefType(type);
			}
		}

		public static RefObj[] CurrentModules
		{
			get
			{
				RefObj[] activeModules = BombApi.ActiveModules;
				if (activeModules == null)
				{
					return Array.Empty<RefObj>();
				}
				return activeModules;
			}
		}

		public static int ModuleCount => CurrentModules.Length;

		public static int SolvedCount => CurrentModules.Count((RefObj m) => IsSolved(m));

		public static int UnsolvedCount => ModuleCount - SolvedCount;

		public static float CompletionPercentage
		{
			get
			{
				if (ModuleCount == 0)
				{
					return 0f;
				}
				return (float)SolvedCount / (float)ModuleCount * 100f;
			}
		}

		public static string GetModuleName(RefObj module)
		{
			return module.GetProperty("name")?.ToString() ?? "Unknown";
		}

		public static bool IsActive(RefObj module)
		{
			return module.GetField("Active") as bool? == true;
		}

		public static bool IsSolved(RefObj module)
		{
			uint num = Convert.ToUInt32(module.GetField("Step") ?? ((object)0u));
			uint num2 = Convert.ToUInt32(module.GetField("MaxStep") ?? ((object)1u));
			return num >= num2;
		}

		public static uint GetCurrentStep(RefObj module)
		{
			return Convert.ToUInt32(module.GetField("Step") ?? ((object)0u));
		}

		public static uint GetMaxStep(RefObj module)
		{
			return Convert.ToUInt32(module.GetField("MaxStep") ?? ((object)1u));
		}

		public static int GetModuleSeed(RefObj module)
		{
			return Convert.ToInt32(module.GetField("moduleSeed") ?? ((object)0));
		}

		public static RefObj? GetBomb(RefObj module)
		{
			object field = module.GetField("Bomb");
			if (field == null)
			{
				return null;
			}
			return new RefObj(field);
		}

		public static RefObj[] GetStepLeds(RefObj module)
		{
			object field = module.GetField("StepLeds");
			if (field == null)
			{
				return Array.Empty<RefObj>();
			}
			return GameApi.EnumerateObjects(field)?.Select((object o) => new RefObj(o)).ToArray() ?? Array.Empty<RefObj>();
		}

		public static string GetModuleType(RefObj module)
		{
			string name = module.Instance.GetType().Name;
			return name switch
			{
				"BombCableModule" => "Cable", 
				"BombCalculatorModule" => "Calculator", 
				"BombDirectionModule" => "Direction", 
				"BombSymbolModule" => "Symbol", 
				"BombColorSwitchModule" => "ColorSwitch", 
				_ => name, 
			};
		}

		public static void MarkSolved(RefObj module)
		{
			module.SetField("Step", GetMaxStep(module));
			module.SetField("Active", false);
			try
			{
				module.Call("DisarmModuleServerRpc");
			}
			catch
			{
			}
		}

		public static void Reset(RefObj module)
		{
			module.SetField("Step", 0u);
			module.SetField("Active", true);
		}

		public static RefObj? FindByName(string name)
		{
			return CurrentModules.FirstOrDefault((RefObj m) => GetModuleName(m).Equals(name, StringComparison.OrdinalIgnoreCase));
		}

		public static RefObj[] FindUnsolved()
		{
			return CurrentModules.Where((RefObj m) => !IsSolved(m)).ToArray();
		}

		public static RefObj[] FindSolved()
		{
			return CurrentModules.Where((RefObj m) => IsSolved(m)).ToArray();
		}

		public static RefObj[] FindByType(string typeName)
		{
			return CurrentModules.Where((RefObj m) => GetModuleType(m).Equals(typeName, StringComparison.OrdinalIgnoreCase)).ToArray();
		}

		public static RefObj[] FindCableModules()
		{
			return FindByType("Cable");
		}

		public static RefObj[] FindCalculatorModules()
		{
			return FindByType("Calculator");
		}

		public static RefObj[] FindDirectionModules()
		{
			return FindByType("Direction");
		}

		public static RefObj[] FindSymbolModules()
		{
			return FindByType("Symbol");
		}

		public static RefObj[] FindColorSwitchModules()
		{
			return FindByType("ColorSwitch");
		}

		public static bool AllSolved()
		{
			return UnsolvedCount == 0;
		}

		public static string[] GetModuleNames()
		{
			return CurrentModules.Select(GetModuleName).ToArray();
		}

		public static string DescribeModules()
		{
			StringBuilder stringBuilder = new StringBuilder();
			StringBuilder stringBuilder2 = stringBuilder;
			StringBuilder stringBuilder3 = stringBuilder2;
			StringBuilder.AppendInterpolatedStringHandler handler = new StringBuilder.AppendInterpolatedStringHandler(23, 1, stringBuilder2);
			handler.AppendLiteral("=== Bomb Modules (");
			handler.AppendFormatted(ModuleCount);
			handler.AppendLiteral(") ===");
			stringBuilder3.AppendLine(ref handler);
			RefObj[] currentModules = CurrentModules;
			foreach (RefObj module in currentModules)
			{
				string moduleName = GetModuleName(module);
				string moduleType = GetModuleType(module);
				bool flag = IsSolved(module);
				uint currentStep = GetCurrentStep(module);
				uint maxStep = GetMaxStep(module);
				string value = (flag ? "SOLVED" : $"OPEN (step {currentStep}/{maxStep})");
				stringBuilder2 = stringBuilder;
				StringBuilder stringBuilder4 = stringBuilder2;
				handler = new StringBuilder.AppendInterpolatedStringHandler(7, 3, stringBuilder2);
				handler.AppendLiteral("  [");
				handler.AppendFormatted(moduleType);
				handler.AppendLiteral("] ");
				handler.AppendFormatted(moduleName);
				handler.AppendLiteral(": ");
				handler.AppendFormatted(value);
				stringBuilder4.AppendLine(ref handler);
			}
			stringBuilder2 = stringBuilder;
			StringBuilder stringBuilder5 = stringBuilder2;
			handler = new StringBuilder.AppendInterpolatedStringHandler(15, 3, stringBuilder2);
			handler.AppendLiteral("Progress: ");
			handler.AppendFormatted(SolvedCount);
			handler.AppendLiteral("/");
			handler.AppendFormatted(ModuleCount);
			handler.AppendLiteral(" (");
			handler.AppendFormatted(CompletionPercentage, "F1");
			handler.AppendLiteral("%)");
			stringBuilder5.AppendLine(ref handler);
			return stringBuilder.ToString();
		}
	}
	public static class CableModuleApi
	{
		public static int GetCableCount(RefObj module)
		{
			return (module.GetField("CableCount") as int?).GetValueOrDefault();
		}

		public static CableInfo[] GetCables(RefObj module)
		{
			object field = module.GetField("Cables");
			if (field == null)
			{
				return Array.Empty<CableInfo>();
			}
			int cableCount = GetCableCount(module);
			List<CableInfo> list = new List<CableInfo>();
			for (int i = 0; i < cableCount; i++)
			{
				object index = new RefObj(field).GetIndex("Item", i);
				if (index != null)
				{
					RefObj refObj = new RefObj(index);
					int index2 = (refObj.GetProperty("index") as int?) ?? i;
					string colorName = refObj.GetProperty("color")?.ToString() ?? "RED";
					RefObj t = Wrap(refObj.GetProperty("cut"));
					RefObj refObj2 = Wrap(refObj.GetProperty("normal"));
					bool isCut = Active(t) || (refObj2 != null && !Active(refObj2));
					list.Add(new CableInfo(index2, colorName, isCut));
				}
			}
			return list.ToArray();
			static bool Active(RefObj? refObj3)
			{
				object obj = refObj3?.GetProperty("gameObject");
				if (obj != null)
				{
					object property = new RefObj(obj).GetProperty("activeInHierarchy");
					if (property is bool)
					{
						return (bool)property;
					}
					return false;
				}
				return false;
			}
			static RefObj? Wrap(object? o)
			{
				if (o != null)
				{
					return new RefObj(o);
				}
				return null;
			}
		}

		public static object[]? GetCablePositions(RefObj module)
		{
			object field = module.GetField("CablePositions");
			if (field == null)
			{
				return null;
			}
			return GameApi.EnumerateObjects(field);
		}

		public static CableInfo[] GetCablesByColor(RefObj module, CableColor color)
		{
			return (from c in GetCables(module)
				where c.Color == color
				select c).ToArray();
		}

		public static CableInfo[] GetCutCables(RefObj module)
		{
			return (from c in GetCables(module)
				where c.IsCut
				select c).ToArray();
		}

		public static CableInfo[] GetUncutCables(RefObj module)
		{
			return (from c in GetCables(module)
				where !c.IsCut
				select c).ToArray();
		}

		public static int GetCutCount(RefObj module)
		{
			return GetCutCables(module).Length;
		}

		public static string DescribeModule(RefObj module)
		{
			StringBuilder stringBuilder = new StringBuilder();
			StringBuilder stringBuilder2 = stringBuilder;
			StringBuilder stringBuilder3 = stringBuilder2;
			StringBuilder.AppendInterpolatedStringHandler handler = new StringBuilder.AppendInterpolatedStringHandler(22, 1, stringBuilder2);
			handler.AppendLiteral("=== Cable Module: ");
			handler.AppendFormatted(BombModuleApi.GetModuleName(module));
			handler.AppendLiteral(" ===");
			stringBuilder3.AppendLine(ref handler);
			stringBuilder2 = stringBuilder;
			StringBuilder stringBuilder4 = stringBuilder2;
			handler = new StringBuilder.AppendInterpolatedStringHandler(8, 1, stringBuilder2);
			handler.AppendLiteral("Cables: ");
			handler.AppendFormatted(GetCableCount(module));
			stringBuilder4.AppendLine(ref handler);
			CableInfo[] cables = GetCables(module);
			for (int i = 0; i < cables.Length; i++)
			{
				CableInfo cableInfo = cables[i];
				string value = (cableInfo.IsCut ? "CUT" : "intact");
				stringBuilder2 = stringBuilder;
				StringBuilder stringBuilder5 = stringBuilder2;
				handler = new StringBuilder.AppendInterpolatedStringHandler(13, 3, stringBuilder2);
				handler.AppendLiteral("  [");
				handler.AppendFormatted(cableInfo.Color);
				handler.AppendLiteral("] Cable ");
				handler.AppendFormatted(cableInfo.Index);
				handler.AppendLiteral(": ");
				handler.AppendFormatted(value);
				stringBuilder5.AppendLine(ref handler);
			}
			return stringBuilder.ToString();
		}
	}
	public static class CalculatorModuleApi
	{
		public static (int numA, int numB, int operation, int result) GetExpression(RefObj module)
		{
			int valueOrDefault = (module.GetField("numA") as int?).GetValueOrDefault();
			int valueOrDefault2 = (module.GetField("numB") as int?).GetValueOrDefault();
			int valueOrDefault3 = (module.GetField("operation") as int?).GetValueOrDefault();
			int valueOrDefault4 = (module.GetField("res") as int?).GetValueOrDefault();
			return (numA: valueOrDefault, numB: valueOrDefault2, operation: valueOrDefault3, result: valueOrDefault4);
		}

		public static (int pendingDigit, int pendingNumber) GetPendingInput(RefObj module)
		{
			int valueOrDefault = (module.GetField("pendingDigit") as int?).GetValueOrDefault();
			int valueOrDefault2 = (module.GetField("pendingNumber") as int?).GetValueOrDefault();
			return (pendingDigit: valueOrDefault, pendingNumber: valueOrDefault2);
		}

		public static int CalculateAnswer(RefObj module)
		{
			(int numA, int numB, int operation, int result) expression = GetExpression(module);
			var (num, num2, _, _) = expression;
			return expression.operation switch
			{
				0 => num + num2, 
				1 => num - num2, 
				2 => num * num2, 
				_ => num + num2, 
			};
		}

		public static string? GetLabelText(RefObj module)
		{
			object field = module.GetField("Label");
			if (field == null)
			{
				return null;
			}
			return new RefObj(field).GetProperty("text")?.ToString();
		}

		public static int[] GetButtonIndexes(RefObj module)
		{
			object obj = module.GetField("buttonsIndexes") ?? module.GetProperty("buttonsIndexes");
			if (obj == null)
			{
				return Array.Empty<int>();
			}
			RefObj refObj = new RefObj(obj);
			List<int> list = new List<int>();
			int valueOrDefault = (refObj.GetProperty("Count") as int?).GetValueOrDefault();
			for (int i = 0; i < valueOrDefault; i++)
			{
				if (refObj.GetIndex("Item", i) is int item)
				{
					list.Add(item);
				}
			}
			return list.ToArray();
		}

		public static bool HasCalculated(RefObj module)
		{
			return module.GetField("hasCalculated") as bool? == true;
		}

		public static string DescribeModule(RefObj module)
		{
			(int numA, int numB, int operation, int result) expression = GetExpression(module);
			int item = expression.numA;
			int item2 = expression.numB;
			int item3 = expression.operation;
			int item4 = expression.result;
			(int pendingDigit, int pendingNumber) pendingInput = GetPendingInput(module);
			int item5 = pendingInput.pendingDigit;
			int item6 = pendingInput.pendingNumber;
			string labelText = GetLabelText(module);
			string value = item3 switch
			{
				0 => "+", 
				1 => "-", 
				2 => "*", 
				_ => "?", 
			};
			StringBuilder stringBuilder2;
			StringBuilder stringBuilder = (stringBuilder2 = new StringBuilder());
			StringBuilder stringBuilder3 = stringBuilder2;
			StringBuilder.AppendInterpolatedStringHandler handler = new StringBuilder.AppendInterpolatedStringHandler(27, 1, stringBuilder2);
			handler.AppendLiteral("=== Calculator Module: ");
			handler.AppendFormatted(BombModuleApi.GetModuleName(module));
			handler.AppendLiteral(" ===");
			stringBuilder3.AppendLine(ref handler);
			stringBuilder2 = stringBuilder;
			StringBuilder stringBuilder4 = stringBuilder2;
			handler = new StringBuilder.AppendInterpolatedStringHandler(17, 4, stringBuilder2);
			handler.AppendLiteral("Expression: ");
			handler.AppendFormatted(item);
			handler.AppendLiteral(" ");
			handler.AppendFormatted(value);
			handler.AppendLiteral(" ");
			handler.AppendFormatted(item2);
			handler.AppendLiteral(" = ");
			handler.AppendFormatted(item4);
			stringBuilder4.AppendLine(ref handler);
			stringBuilder2 = stringBuilder;
			StringBuilder stringBuilder5 = stringBuilder2;
			handler = new StringBuilder.AppendInterpolatedStringHandler(7, 1, stringBuilder2);
			handler.AppendLiteral("Label: ");
			handler.AppendFormatted(labelText);
			stringBuilder5.AppendLine(ref handler);
			stringBuilder2 = stringBuilder;
			StringBuilder stringBuilder6 = stringBuilder2;
			handler = new StringBuilder.AppendInterpolatedStringHandler(24, 2, stringBuilder2);
			handler.AppendLiteral("Pending: digit=");
			handler.AppendFormatted(item5);
			handler.AppendLiteral(", number=");
			handler.AppendFormatted(item6);
			stringBuilder6.AppendLine(ref handler);
			stringBuilder2 = stringBuilder;
			StringBuilder stringBuilder7 = stringBuilder2;
			handler = new StringBuilder.AppendInterpolatedStringHandler(12, 1, stringBuilder2);
			handler.AppendLiteral("Calculated: ");
			handler.AppendFormatted(HasCalculated(module));
			stringBuilder7.AppendLine(ref handler);
			return stringBuilder.ToString();
		}
	}
	public static class DirectionModuleApi
	{
		public static int GetNumber(RefObj module)
		{
			return (module.GetField("number") as int?).GetValueOrDefault();
		}

		public static int[] GetAvailableNumbers(RefObj module)
		{
			object field = module.GetField("NUMS");
			if (field == null)
			{
				return Array.Empty<int>();
			}
			RefObj refObj = new RefObj(field);
			List<int> list = new List<int>();
			int valueOrDefault = (refObj.GetProperty("Length") as int?).GetValueOrDefault();
			for (int i = 0; i < valueOrDefault; i++)
			{
				if (refObj.GetIndex("Item", i) is int item)
				{
					list.Add(item);
				}
			}
			return list.ToArray();
		}

		public static string[] GetAvailableColors(RefObj module)
		{
			object field = module.GetField("COLORS");
			if (field == null)
			{
				return Array.Empty<string>();
			}
			RefObj refObj = new RefObj(field);
			List<string> list = new List<string>();
			int valueOrDefault = (refObj.GetProperty("Length") as int?).GetValueOrDefault();
			for (int i = 0; i < valueOrDefault; i++)
			{
				object index = refObj.GetIndex("Item", i);
				if (index != null)
				{
					list.Add(index.ToString());
				}
			}
			return list.ToArray();
		}

		public static int[] GetBrailleDots(RefObj module)
		{
			object field = module.GetField("BrailleDot");
			if (field == null)
			{
				return Array.Empty<int>();
			}
			RefObj refObj = new RefObj(field);
			object obj = refObj.GetField("generatedDots") ?? refObj.GetProperty("generatedDots");
			if (obj == null)
			{
				return Array.Empty<int>();
			}
			RefObj refObj2 = new RefObj(obj);
			List<int> list = new List<int>();
			int valueOrDefault = (refObj2.GetProperty("Length") as int?).GetValueOrDefault();
			bool flag = default(bool);
			for (int i = 0; i < valueOrDefault; i++)
			{
				object index = refObj2.GetIndex("Item", i);
				int num;
				if (index is bool)
				{
					flag = (bool)index;
					num = 1;
				}
				else
				{
					num = 0;
				}
				if (((uint)num & (flag ? 1u : 0u)) != 0)
				{
					list.Add(i);
				}
			}
			return list.ToArray();
		}

		public static (float x, float y, float z)? GetBraillePosition(RefObj module)
		{
			object field = module.GetField("BrailleContainer");
			if (field == null)
			{
				return null;
			}
			return UnityTypesApi.GetPosition(new RefObj(field));
		}

		public static string? GetLightColor(RefObj module)
		{
			return module.GetField("color")?.ToString();
		}

		public static float GetInteractionCooldown(RefObj module)
		{
			return (module.GetField("interactionCooldown") as float?).GetValueOrDefault();
		}

		public static string DescribeModule(RefObj module)
		{
			int number = GetNumber(module);
			int[] brailleDots = GetBrailleDots(module);
			string lightColor = GetLightColor(module);
			StringBuilder stringBuilder2;
			StringBuilder stringBuilder = (stringBuilder2 = new StringBuilder());
			StringBuilder stringBuilder3 = stringBuilder2;
			StringBuilder.AppendInterpolatedStringHandler handler = new StringBuilder.AppendInterpolatedStringHandler(26, 1, stringBuilder2);
			handler.AppendLiteral("=== Direction Module: ");
			handler.AppendFormatted(BombModuleApi.GetModuleName(module));
			handler.AppendLiteral(" ===");
			stringBuilder3.AppendLine(ref handler);
			stringBuilder2 = stringBuilder;
			StringBuilder stringBuilder4 = stringBuilder2;
			handler = new StringBuilder.AppendInterpolatedStringHandler(8, 1, stringBuilder2);
			handler.AppendLiteral("Number: ");
			handler.AppendFormatted(number);
			stringBuilder4.AppendLine(ref handler);
			stringBuilder2 = stringBuilder;
			StringBuilder stringBuilder5 = stringBuilder2;
			handler = new StringBuilder.AppendInterpolatedStringHandler(16, 1, stringBuilder2);
			handler.AppendLiteral("Braille dots: [");
			handler.AppendFormatted(string.Join(", ", brailleDots));
			handler.AppendLiteral("]");
			stringBuilder5.AppendLine(ref handler);
			stringBuilder2 = stringBuilder;
			StringBuilder stringBuilder6 = stringBuilder2;
			handler = new StringBuilder.AppendInterpolatedStringHandler(13, 1, stringBuilder2);
			handler.AppendLiteral("Light color: ");
			handler.AppendFormatted(lightColor);
			stringBuilder6.AppendLine(ref handler);
			stringBuilder2 = stringBuilder;
			StringBuilder stringBuilder7 = stringBuilder2;
			handler = new StringBuilder.AppendInterpolatedStringHandler(11, 1, stringBuilder2);
			handler.AppendLiteral("Cooldown: ");
			handler.AppendFormatted(GetInteractionCooldown(module));
			handler.AppendLiteral("s");
			stringBuilder7.AppendLine(ref handler);
			return stringBuilder.ToString();
		}
	}
	public static class SymbolModuleApi
	{
		public static int GetChosenSymbolIndex(RefObj module)
		{
			return (module.GetField("symbolChosenIndex") as int?).GetValueOrDefault();
		}

		public static int GetKnobDirection(RefObj module)
		{
			return (module.GetField("knobCurrentDirection") as int?).GetValueOrDefault();
		}

		public static int[] GetButtonIndexes(RefObj module)
		{
			object field = module.GetField("buttonsIndexes");
			if (field == null)
			{
				return Array.Empty<int>();
			}
			RefObj refObj = new RefObj(field);
			List<int> list = new List<int>();
			int valueOrDefault = (refObj.GetProperty("Length") as int?).GetValueOrDefault();
			for (int i = 0; i < valueOrDefault; i++)
			{
				if (refObj.GetIndex("Item", i) is int item)
				{
					list.Add(item);
				}
			}
			return list.ToArray();
		}

		public static int[][] GetSymbolInfoTable(RefObj module)
		{
			object field = module.GetField("SymbolInfoTable");
			if (field == null)
			{
				return Array.Empty<int[]>();
			}
			RefObj refObj = new RefObj(field);
			List<int[]> list = new List<int[]>();
			int valueOrDefault = (refObj.GetProperty("Length") as int?).GetValueOrDefault();
			for (int i = 0; i < valueOrDefault; i++)
			{
				object index = refObj.GetIndex("Item", i);
				if (index == null)
				{
					list.Add(Array.Empty<int>());
					continue;
				}
				RefObj refObj2 = new RefObj(index);
				int valueOrDefault2 = (refObj2.GetProperty("Length") as int?).GetValueOrDefault();
				List<int> list2 = new List<int>();
				for (int j = 0; j < valueOrDefault2; j++)
				{
					if (refObj2.GetIndex("Item", j) is int item)
					{
						list2.Add(item);
					}
				}
				list.Add(list2.ToArray());
			}
			return list.ToArray();
		}

		public static int GetPossibleSymbolCount(RefObj module)
		{
			object field = module.GetField("PossibleSymbols");
			if (field == null)
			{
				return 0;
			}
			return (new RefObj(field).GetProperty("Count") as int?).GetValueOrDefault();
		}

		public static int GetSpawnedSymbolCount(RefObj module)
		{
			object field = module.GetField("SpawnedSymbols");
			if (field == null)
			{
				return 0;
			}
			return (new RefObj(field).GetProperty("Count") as int?).GetValueOrDefault();
		}

		public static (float x, float y, float z)? GetKnobPosition(RefObj module)
		{
			object field = module.GetField("Knob");
			if (field == null)
			{
				return null;
			}
			return UnityTypesApi.GetPosition(new RefObj(field));
		}

		public static string DescribeModule(RefObj module)
		{
			int chosenSymbolIndex = GetChosenSymbolIndex(module);
			int knobDirection = GetKnobDirection(module);
			int possibleSymbolCount = GetPossibleSymbolCount(module);
			int spawnedSymbolCount = GetSpawnedSymbolCount(module);
			StringBuilder stringBuilder2;
			StringBuilder stringBuilder = (stringBuilder2 = new StringBuilder());
			StringBuilder stringBuilder3 = stringBuilder2;
			StringBuilder.AppendInterpolatedStringHandler handler = new StringBuilder.AppendInterpolatedStringHandler(23, 1, stringBuilder2);
			handler.AppendLiteral("=== Symbol Module: ");
			handler.AppendFormatted(BombModuleApi.GetModuleName(module));
			handler.AppendLiteral(" ===");
			stringBuilder3.AppendLine(ref handler);
			stringBuilder2 = stringBuilder;
			StringBuilder stringBuilder4 = stringBuilder2;
			handler = new StringBuilder.AppendInterpolatedStringHandler(21, 1, stringBuilder2);
			handler.AppendLiteral("Chosen symbol index: ");
			handler.AppendFormatted(chosenSymbolIndex);
			stringBuilder4.AppendLine(ref handler);
			stringBuilder2 = stringBuilder;
			StringBuilder stringBuilder5 = stringBuilder2;
			handler = new StringBuilder.AppendInterpolatedStringHandler(16, 1, stringBuilder2);
			handler.AppendLiteral("Knob direction: ");
			handler.AppendFormatted(knobDirection);
			stringBuilder5.AppendLine(ref handler);
			stringBuilder2 = stringBuilder;
			StringBuilder stringBuilder6 = stringBuilder2;
			handler = new StringBuilder.AppendInterpolatedStringHandler(18, 1, stringBuilder2);
			handler.AppendLiteral("Possible symbols: ");
			handler.AppendFormatted(possibleSymbolCount);
			stringBuilder6.AppendLine(ref handler);
			stringBuilder2 = stringBuilder;
			StringBuilder stringBuilder7 = stringBuilder2;
			handler = new StringBuilder.AppendInterpolatedStringHandler(17, 1, stringBuilder2);
			handler.AppendLiteral("Spawned symbols: ");
			handler.AppendFormatted(spawnedSymbolCount);
			stringBuilder7.AppendLine(ref handler);
			stringBuilder2 = stringBuilder;
			StringBuilder stringBuilder8 = stringBuilder2;
			handler = new StringBuilder.AppendInterpolatedStringHandler(11, 1, stringBuilder2);
			handler.AppendLiteral("Buttons: [");
			handler.AppendFormatted(string.Join(", ", GetButtonIndexes(module)));
			handler.AppendLiteral("]");
			stringBuilder8.AppendLine(ref handler);
			return stringBuilder.ToString();
		}
	}
	public static class ColorSwitchModuleApi
	{
		public static int GetSwitchCount(RefObj module)
		{
			object field = module.GetField("Switches");
			if (field == null)
			{
				return 0;
			}
			return (new RefObj(field).GetProperty("Count") as int?).GetValueOrDefault();
		}

		public static ColorSwitchInfo[] GetSwitchStates(RefObj module)
		{
			object field = module.GetField("states");
			if (field == null)
			{
				return Array.Empty<ColorSwitchInfo>();
			}
			RefObj refObj = new RefObj(field);
			int valueOrDefault = (refObj.GetProperty("Length") as int?).GetValueOrDefault();
			List<ColorSwitchInfo> list = new List<ColorSwitchInfo>();
			bool flag = default(bool);
			for (int i = 0; i < valueOrDefault; i++)
			{
				object index = refObj.GetIndex("Item", i);
				int index2 = i;
				int num;
				if (index is bool)
				{
					flag = (bool)index;
					num = 1;
				}
				else
				{
					num = 0;
				}
				list.Add(new ColorSwitchInfo(index2, (byte)((uint)num & (flag ? 1u : 0u)) != 0));
			}
			return list.ToArray();
		}

		public static int GetLightCount(RefObj module)
		{
			object field = module.GetField("Lights");
			if (field == null)
			{
				return 0;
			}
			return (new RefObj(field).GetProperty("Length") as int?).GetValueOrDefault();
		}

		public static int[] GetBrailleNumbers(RefObj module)
		{
			object field = module.GetField("brailleNumbers");
			if (field == null)
			{
				return Array.Empty<int>();
			}
			RefObj refObj = new RefObj(field);
			List<int> list = new List<int>();
			int valueOrDefault = (refObj.GetProperty("Length") as int?).GetValueOrDefault();
			for (int i = 0; i < valueOrDefault; i++)
			{
				if (refObj.GetIndex("Item", i) is int item)
				{
					list.Add(item);
				}
			}
			return list.ToArray();
		}

		public static int GetCombinationCount(RefObj module)
		{
			object field = module.GetField("Combinations");
			if (field == null)
			{
				return 0;
			}
			return (new RefObj(field).GetProperty("Count") as int?).GetValueOrDefault();
		}

		public static int GetChosenCombination(RefObj module)
		{
			return (module.GetField("chosenCombination") as int?).GetValueOrDefault();
		}

		public static string DescribeModule(RefObj module)
		{
			StringBuilder stringBuilder = new StringBuilder();
			StringBuilder stringBuilder2 = stringBuilder;
			StringBuilder stringBuilder3 = stringBuilder2;
			StringBuilder.AppendInterpolatedStringHandler handler = new StringBuilder.AppendInterpolatedStringHandler(28, 1, stringBuilder2);
			handler.AppendLiteral("=== ColorSwitch Module: ");
			handler.AppendFormatted(BombModuleApi.GetModuleName(module));
			handler.AppendLiteral(" ===");
			stringBuilder3.AppendLine(ref handler);
			stringBuilder2 = stringBuilder;
			StringBuilder stringBuilder4 = stringBuilder2;
			handler = new StringBuilder.AppendInterpolatedStringHandler(10, 1, stringBuilder2);
			handler.AppendLiteral("Switches: ");
			handler.AppendFormatted(GetSwitchCount(module));
			stringBuilder4.AppendLine(ref handler);
			stringBuilder2 = stringBuilder;
			StringBuilder stringBuilder5 = stringBuilder2;
			handler = new StringBuilder.AppendInterpolatedStringHandler(8, 1, stringBuilder2);
			handler.AppendLiteral("Lights: ");
			handler.AppendFormatted(GetLightCount(module));
			stringBuilder5.AppendLine(ref handler);
			stringBuilder2 = stringBuilder;
			StringBuilder stringBuilder6 = stringBuilder2;
			handler = new StringBuilder.AppendInterpolatedStringHandler(14, 1, stringBuilder2);
			handler.AppendLiteral("Combinations: ");
			handler.AppendFormatted(GetCombinationCount(module));
			stringBuilder6.AppendLine(ref handler);
			stringBuilder2 = stringBuilder;
			StringBuilder stringBuilder7 = stringBuilder2;
			handler = new StringBuilder.AppendInterpolatedStringHandler(20, 1, stringBuilder2);
			handler.AppendLiteral("Chosen combination: ");
			handler.AppendFormatted(GetChosenCombination(module));
			stringBuilder7.AppendLine(ref handler);
			ColorSwitchInfo[] switchStates = GetSwitchStates(module);
			for (int i = 0; i < switchStates.Length; i++)
			{
				ColorSwitchInfo colorSwitchInfo = switchStates[i];
				stringBuilder2 = stringBuilder;
				StringBuilder stringBuilder8 = stringBuilder2;
				handler = new StringBuilder.AppendInterpolatedStringHandler(11, 2, stringBuilder2);
				handler.AppendLiteral("  Switch ");
				handler.AppendFormatted(colorSwitchInfo.Index);
				handler.AppendLiteral(": ");
				handler.AppendFormatted(colorSwitchInfo.IsOn ? "ON" : "OFF");
				stringBuilder8.AppendLine(ref handler);
			}
			int[] brailleNumbers = GetBrailleNumbers(module);
			if (brailleNumbers.Length != 0)
			{
				stringBuilder2 = stringBuilder;
				StringBuilder stringBuilder9 = stringBuilder2;
				handler = new StringBuilder.AppendInterpolatedStringHandler(19, 1, stringBuilder2);
				handler.AppendLiteral("Braille numbers: [");
				handler.AppendFormatted(string.Join(", ", brailleNumbers));
				handler.AppendLiteral("]");
				stringBuilder9.AppendLine(ref handler);
			}
			return stringBuilder.ToString();
		}
	}
	public static class BrailleApi
	{
		private static readonly TypeResolver Resolver = TypeResolver.Default;

		public static RefType? ObjectType
		{
			get
			{
				Type type = Resolver.Resolve("BombGame.BrailleObject");
				if ((object)type == null)
				{
					return null;
				}
				return new RefType(type);
			}
		}

		public static RefType? KeyType
		{
			get
			{
				Type type = Resolver.Resolve("BombGame.BrailleKey");
				if ((object)type == null)
				{
					return null;
				}
				return new RefType(type);
			}
		}

		public static RefType? NumberType
		{
			get
			{
				Type type = Resolver.Resolve("BombGame.BrailleNumber");
				if ((object)type == null)
				{
					return null;
				}
				return new RefType(type);
			}
		}

		public static RefType? UIType
		{
			get
			{
				Type type = Resolver.Resolve("BombGame.BrailleUI");
				if ((object)type == null)
				{
					return null;
				}
				return new RefType(type);
			}
		}

		public static RefObj? UIInstance
		{
			get
			{
				object obj = UIType?.GetStaticField("Instance");
				if (obj == null)
				{
					return null;
				}
				return new RefObj(obj);
			}
		}

		public static BrailleNumberInfo? CreateNumber(int value)
		{
			object obj = NumberType?.InvokeStatic("Of", value);
			if (obj == null)
			{
				return null;
			}
			RefObj refObj = new RefObj(obj);
			return new BrailleNumberInfo
			{
				Value = ((refObj.GetProperty("Value") is int num) ? num : value),
				Pattern = (byte)((refObj.GetProperty("Pattern") is int num2) ? ((byte)num2) : 0)
			};
		}

		public static void ShowMessage(string message)
		{
			UIInstance?.Call("ShowMessage", message);
		}

		public static void HideMessage()
		{
			UIInstance?.Call("HideMessage");
		}

		public static RefObj[] FindAllObjects()
		{
			return GameApi.FindInstances("BombGame.BrailleObject");
		}

		public static void GenerateNumber(RefObj brailleObject, BrailleNumberInfo number)
		{
			if (brailleObject != null)
			{
				object obj = NumberType?.InvokeStatic("Of", number.Value);
				if (obj != null)
				{
					brailleObject.Call("GenerateNumber", obj);
				}
			}
		}

		public static void SetBlindedness(RefObj brailleObject, float amount)
		{
			brailleObject?.Call("SetBlindedness", amount);
		}

		public static RefObj[] FindAllKeys()
		{
			return GameApi.FindInstances("BombGame.BrailleKey");
		}

		public static void SetupKey(RefObj key, int index)
		{
			key?.Call("SetupKey", index);
		}
	}
	public readonly record struct BrailleNumberInfo
	{
		public int Value { get; init; }

		public byte Pattern { get; init; }
	}
	public static class ColorApi
	{
		private static readonly TypeResolver Resolver = TypeResolver.Default;

		private static readonly RefObj? _white = Create(1f, 1f, 1f);

		private static readonly RefObj? _black = Create(0f, 0f, 0f);

		private static readonly RefObj? _red = Create(1f, 0f, 0f);

		private static readonly RefObj? _green = Create(0f, 1f, 0f);

		private static readonly RefObj? _blue = Create(0f, 0f, 1f);

		private static readonly RefObj? _yellow = Create(1f, 1f, 0f);

		private static readonly RefObj? _cyan = Create(0f, 1f, 1f);

		private static readonly RefObj? _magenta = Create(1f, 0f, 1f);

		private static readonly RefObj? _gray = Create(0.5f, 0.5f, 0.5f);

		private static readonly RefObj? _transparent = Create(0f, 0f, 0f, 0f);

		public static RefType? ColorType
		{
			get
			{
				Type type = Resolver.Resolve("UnityEngine.Color");
				if ((object)type == null)
				{
					return null;
				}
				return new RefType(type);
			}
		}

		public static RefObj? White => _white;

		public static RefObj? Black => _black;

		public static RefObj? Red => _red;

		public static RefObj? Green => _green;

		public static RefObj? Blue => _blue;

		public static RefObj? Yellow => _yellow;

		public static RefObj? Cyan => _cyan;

		public static RefObj? Magenta => _magenta;

		public static RefObj? Gray => _gray;

		public static RefObj? Transparent => _transparent;

		public static RefObj? Create(float r, float g, float b, float a = 1f)
		{
			RefType colorType = ColorType;
			if (colorType == null)
			{
				return null;
			}
			ConstructorInfo constructor = colorType.Type.GetConstructor(new Type[4]
			{
				typeof(float),
				typeof(float),
				typeof(float),
				typeof(float)
			});
			if ((object)constructor == null)
			{
				return null;
			}
			object obj = constructor.Invoke(new object[4] { r, g, b, a });
			if (obj == null)
			{
				return null;
			}
			return new RefObj(obj);
		}

		public static RefObj? CreateFromBytes(byte r, byte g, byte b, byte a = byte.MaxValue)
		{
			return Create((float)(int)r / 255f, (float)(int)g / 255f, (float)(int)b / 255f, (float)(int)a / 255f);
		}

		private static bool IsValidHex(string hex)
		{
			foreach (char c in hex)
			{
				if ((c < '0' || c > '9') && (c < 'a' || c > 'f') && (c < 'A' || c > 'F'))
				{
					return false;
				}
			}
			return true;
		}

		public static RefObj? CreateFromHex(string hex)
		{
			if (string.IsNullOrEmpty(hex))
			{
				return null;
			}
			hex = hex.TrimStart('#');
			if (!IsValidHex(hex))
			{
				return null;
			}
			return hex.Length switch
			{
				6 => CreateFromBytes(Convert.ToByte(hex.Substring(0, 2), 16), Convert.ToByte(hex.Substring(2, 2), 16), Convert.ToByte(hex.Substring(4, 2), 16)), 
				8 => CreateFromBytes(Convert.ToByte(hex.Substring(0, 2), 16), Convert.ToByte(hex.Substring(2, 2), 16), Convert.ToByte(hex.Substring(4, 2), 16), Convert.ToByte(hex.Substring(6, 2), 16)), 
				_ => null, 
			};
		}

		public static (float r, float g, float b, float a)? GetComponents(RefObj color)
		{
			if (color == null)
			{
				return null;
			}
			float valueOrDefault = (color.GetProperty("r") as float?).GetValueOrDefault();
			float valueOrDefault2 = (color.GetProperty("g") as float?).GetValueOrDefault();
			float valueOrDefault3 = (color.GetProperty("b") as float?).GetValueOrDefault();
			float item = (color.GetProperty("a") as float?) ?? 1f;
			return (valueOrDefault, valueOrDefault2, valueOrDefault3, item);
		}

		public static RefObj? WithAlpha(RefObj color, float alpha)
		{
			if (color == null)
			{
				return null;
			}
			(float, float, float, float)? components = GetComponents(color);
			if (!components.HasValue)
			{
				return null;
			}
			(float, float, float, float) value = components.Value;
			return Create(value.Item1, value.Item2, value.Item3, alpha);
		}
	}
	public static class CoroutineApi
	{
		private static readonly TypeResolver Resolver = TypeResolver.Default;

		private static RefObj? _runner;

		private static RefObj? Runner
		{
			get
			{
				if (_runner != null)
				{
					return _runner;
				}
				Type type = Resolver.Resolve("UnityEngine.GameObject");
				if ((object)type == null)
				{
					return null;
				}
				ConstructorInfo constructor = type.GetConstructor(new Type[1] { typeof(string) });
				if ((object)constructor == null)
				{
					return null;
				}
				object obj = constructor.Invoke(new object[1] { "BOMBANANA_CoroutineRunner" });
				if (obj == null)
				{
					return null;
				}
				RefObj runner = new RefObj(obj);
				Type type2 = Resolver.Resolve("UnityEngine.Object");
				if ((object)type2 != null)
				{
					MethodInfo? method = type2.GetMethod("DontDestroyOnLoad", new Type[1] { type });
					if ((object)method == null)
					{
						Console.Error.WriteLine("[GameLibrary] DontDestroyOnLoad method not found");
					}
					method?.Invoke(null, new object[1] { obj });
				}
				_runner = runner;
				return _runner;
			}
		}

		public static void Start(IEnumerator coroutine)
		{
			RefObj runner = Runner;
			runner?.Type.Type.GetMethod("StartCoroutine", new Type[1] { typeof(IEnumerator) })?.Invoke(runner.Instance, new object[1] { coroutine });
		}

		public static void Delay(float delaySeconds, Action action)
		{
			if (delaySeconds < 0f)
			{
				throw new ArgumentOutOfRangeException("delaySeconds", delaySeconds, "Delay must be non-negative.");
			}
			Start(DelayCoroutine(delaySeconds, action));
		}

		public static void Repeat(float intervalSeconds, float durationSeconds, Action action)
		{
			if (intervalSeconds <= 0f)
			{
				throw new ArgumentOutOfRangeException("intervalSeconds", intervalSeconds, "Interval must be positive.");
			}
			if (!(durationSeconds <= 0f))
			{
				Start(RepeatCoroutine(intervalSeconds, durationSeconds, action));
			}
		}

		private static IEnumerator DelayCoroutine(float delay, Action action)
		{
			Type type = Resolver.Resolve("UnityEngine.WaitForSeconds");
			if ((object)type != null)
			{
				ConstructorInfo constructor = type.GetConstructor(new Type[1] { typeof(float) });
				if ((object)constructor != null)
				{
					yield return constructor.Invoke(new object[1] { delay });
					action?.Invoke();
				}
			}
		}

		private static IEnumerator RepeatCoroutine(float interval, float duration, Action action)
		{
			Type type = Resolver.Resolve("UnityEngine.WaitForSeconds");
			if ((object)type == null)
			{
				yield break;
			}
			ConstructorInfo ctor = type.GetConstructor(new Type[1] { typeof(float) });
			if ((object)ctor != null)
			{
				float elapsed = 0f;
				while (elapsed < duration)
				{
					yield return ctor.Invoke(new object[1] { interval });
					elapsed += interval;
					action?.Invoke();
				}
			}
		}
	}
	public static class DiscordApi
	{
		private static readonly TypeResolver Resolver = TypeResolver.Default;

		public const string DiscordInviteUrl = "https://discord.gg/zJrY2ZbSUX";

		public static RefType? Type
		{
			get
			{
				Type type = Resolver.Resolve("BombGame.DiscordPresenceController");
				if ((object)type == null)
				{
					return null;
				}
				return new RefType(type);
			}
		}

		public static RefObj[] FindAll()
		{
			return GameApi.FindInstances("BombGame.DiscordPresenceController");
		}

		public static void UpdatePresence(RefObj controller, int gameStateIndex)
		{
			if (controller != null)
			{
				Type type = Resolver.Resolve("BombGame.GameState");
				if ((object)type != null)
				{
					object obj = Enum.ToObject(type, gameStateIndex);
					controller.Call("UpdatePresence", obj);
				}
			}
		}
	}
	public static class FeedbackApi
	{
		private static readonly TypeResolver Resolver = TypeResolver.Default;

		public static RefType? Type
		{
			get
			{
				Type type = Resolver.Resolve("BombGame.FeedbackPanel");
				if ((object)type == null)
				{
					return null;
				}
				return new RefType(type);
			}
		}

		public static RefObj[] FindAll()
		{
			return GameApi.FindInstances("BombGame.FeedbackPanel");
		}

		public static void Show(RefObj panel)
		{
			panel?.Call("Show");
		}

		public static void Hide(RefObj panel)
		{
			panel?.Call("Hide");
		}

		public static string? GetWebhookUrl(RefObj panel)
		{
			return panel?.GetField("webhookUrl") as string;
		}
	}
	public static class CrashReporterApi
	{
		private static readonly TypeResolver Resolver = TypeResolver.Default;

		public const float TrackingPercentage = 5f;

		public static RefType? Type
		{
			get
			{
				Type type = Resolver.Resolve("CrashReporterSystem.CrashReporter");
				if ((object)type == null)
				{
					return null;
				}
				return new RefType(type);
			}
		}

		public static RefObj[] FindAll()
		{
			return GameApi.FindInstances("CrashReporterSystem.CrashReporter");
		}
	}
	public static class EmoteApi
	{
		private static readonly TypeResolver Resolver = TypeResolver.Default;

		public static RefType? EmoteType
		{
			get
			{
				Type type = Resolver.Resolve("BombGame.Tool.Emote");
				if ((object)type == null)
				{
					return null;
				}
				return new RefType(type);
			}
		}

		public static RefType? WheelType
		{
			get
			{
				Type type = Resolver.Resolve("BombGame.Tool.EmotesWheel");
				if ((object)type == null)
				{
					return null;
				}
				return new RefType(type);
			}
		}

		public static RefType? ProfileType
		{
			get
			{
				Type type = Resolver.Resolve("BombGame.Tool.EmotesProfile");
				if ((object)type == null)
				{
					return null;
				}
				return new RefType(type);
			}
		}

		public static RefType? CategoryType
		{
			get
			{
				Type type = Resolver.Resolve("BombGame.Tool.EmoteCategory");
				if ((object)type == null)
				{
					return null;
				}
				return new RefType(type);
			}
		}

		public static RefObj[] FindAllEmotes()
		{
			return GameApi.FindInstances("BombGame.Tool.Emote");
		}

		public static string? GetIdentifier(RefObj emote)
		{
			object obj = emote.GetField("identifier")?.ToString();
			if (obj == null)
			{
				object? property = emote.GetProperty("identifier");
				if (property == null)
				{
					return null;
				}
				obj = property.ToString();
			}
			return (string?)obj;
		}

		public static string? GetAnimation(RefObj emote)
		{
			object obj = emote.GetField("animation")?.ToString();
			if (obj == null)
			{
				object? property = emote.GetProperty("animation");
				if (property == null)
				{
					return null;
				}
				obj = property.ToString();
			}
			return (string?)obj;
		}

		public static bool? GetTwoHanded(RefObj emote)
		{
			return (emote.GetField("twoHanded") as bool?) ?? (emote.GetProperty("twoHanded") as bool?);
		}

		public static object? GetIcon(RefObj emote)
		{
			return emote.GetField("icon") ?? emote.GetProperty("icon");
		}

		public static RefObj? FindWheel()
		{
			RefObj[] array = GameApi.FindInstances("BombGame.Tool.EmotesWheel");
			if (array.Length == 0)
			{
				return null;
			}
			return array[0];
		}

		public static object[]? GetProfileCategories(RefObj profile)
		{
			return GameApi.EnumerateObjects(profile.GetField("categories"));
		}

		public static object[]? GetCategoryEmotes(RefObj category)
		{
			return GameApi.EnumerateObjects(category.GetField("emotes"));
		}
	}
	public static class ExplosionApi
	{
		private static readonly TypeResolver Resolver = TypeResolver.Default;

		public static RefType? Type
		{
			get
			{
				Type type = Resolver.Resolve("BombGame.Explosion");
				if ((object)type == null)
				{
					return null;
				}
				return new RefType(type);
			}
		}

		public static RefObj[] FindAll()
		{
			return GameApi.FindInstances("BombGame.Explosion");
		}

		public static RefObj? FindFirst()
		{
			RefObj[] array = FindAll();
			if (array.Length == 0)
			{
				return null;
			}
			return array[0];
		}

		public static string DescribeExplosion()
		{
			StringBuilder stringBuilder = new StringBuilder();
			RefObj[] array = FindAll();
			StringBuilder stringBuilder2 = stringBuilder;
			StringBuilder stringBuilder3 = stringBuilder2;
			StringBuilder.AppendInterpolatedStringHandler handler = new StringBuilder.AppendInterpolatedStringHandler(30, 1, stringBuilder2);
			handler.AppendLiteral("=== Explosion (");
			handler.AppendFormatted(array.Length);
			handler.AppendLiteral(" instances) ===");
			stringBuilder3.AppendLine(ref handler);
			RefObj[] array2 = array;
			for (int i = 0; i < array2.Length; i++)
			{
				string gameObjectName = UnityTypesApi.GetGameObjectName(array2[i]);
				stringBuilder2 = stringBuilder;
				StringBuilder stringBuilder4 = stringBuilder2;
				handler = new StringBuilder.AppendInterpolatedStringHandler(4, 1, stringBuilder2);
				handler.AppendLiteral("  - ");
				handler.AppendFormatted(gameObjectName);
				stringBuilder4.AppendLine(ref handler);
			}
			return stringBuilder.ToString();
		}
	}
	public static class PlayerInteractionApi
	{
		private static readonly TypeResolver Resolver = TypeResolver.Default;

		public static RefType? Type
		{
			get
			{
				Type type = Resolver.Resolve("BombGame.PlayerInteractionController");
				if ((object)type == null)
				{
					return null;
				}
				return new RefType(type);
			}
		}

		public static RefObj? LocalInteraction
		{
			get
			{
				RefObj refObj = PlayerApi.FindLocal();
				if (refObj == null)
				{
					return null;
				}
				return PlayerApi.GetInteraction(refObj);
			}
		}

		public static RefObj[] FindAll()
		{
			return GameApi.FindInstances("BombGame.PlayerInteractionController");
		}

		public static RefObj? GetInteraction(RefObj player)
		{
			return PlayerApi.GetInteraction(player);
		}

		public static string DescribeInteraction()
		{
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.AppendLine("=== PlayerInteractionController ===");
			RefObj localInteraction = LocalInteraction;
			if (localInteraction != null)
			{
				StringBuilder stringBuilder2 = stringBuilder;
				StringBuilder.AppendInterpolatedStringHandler handler = new StringBuilder.AppendInterpolatedStringHandler(25, 1, stringBuilder2);
				handler.AppendLiteral("Local interaction found: ");
				handler.AppendFormatted(localInteraction.Instance?.GetType().Name ?? "unknown");
				stringBuilder2.AppendLine(ref handler);
			}
			else
			{
				stringBuilder.AppendLine("No local interaction found");
			}
			return stringBuilder.ToString();
		}
	}
	public static class ExtensionsApi
	{
		private static readonly TypeResolver Resolver = TypeResolver.Default;

		public static RefType? Type
		{
			get
			{
				Type type = Resolver.Resolve("BombGame.Utility.MethodExtensions");
				if ((object)type == null)
				{
					return null;
				}
				return new RefType(type);
			}
		}

		public static float Map(float value, float inMin, float inMax, float outMin, float outMax)
		{
			if (MathF.Abs(inMax - inMin) < float.Epsilon)
			{
				return (outMin + outMax) * 0.5f;
			}
			return outMin + (value - inMin) * (outMax - outMin) / (inMax - inMin);
		}

		public static RefObj[] GetAllChildren(RefObj transform)
		{
			if (transform == null)
			{
				return Array.Empty<RefObj>();
			}
			object obj;
			try
			{
				obj = transform.Call("GetAllChildren");
			}
			catch (MissingMethodException)
			{
				return Array.Empty<RefObj>();
			}
			if (obj == null)
			{
				return Array.Empty<RefObj>();
			}
			if (obj is IEnumerable enumerable)
			{
				List<RefObj> list = new List<RefObj>();
				foreach (object item in enumerable)
				{
					if (item != null)
					{
						list.Add(new RefObj(item));
					}
				}
				return list.ToArray();
			}
			return Array.Empty<RefObj>();
		}
	}
	public static class UIAnimatorApi
	{
		private static readonly TypeResolver Resolver = TypeResolver.Default;

		public static RefType? ScrollingType
		{
			get
			{
				Type type = Resolver.Resolve("BombGame.ScrollingPatternBackgroundAnimator");
				if ((object)type == null)
				{
					return null;
				}
				return new RefType(type);
			}
		}

		public static RefType? SpriteType
		{
			get
			{
				Type type = Resolver.Resolve("BombGame.SpriteSequenceBackgroundAnimator");
				if ((object)type == null)
				{
					return null;
				}
				return new RefType(type);
			}
		}

		public static RefObj? CreateScrolling()
		{
			RefType scrollingType = ScrollingType;
			if (scrollingType == null)
			{
				return null;
			}
			object obj = scrollingType.CreateInstance();
			if (obj == null)
			{
				return null;
			}
			return new RefObj(obj);
		}

		public static RefObj? CreateSpriteSequence()
		{
			RefType spriteType = SpriteType;
			if (spriteType == null)
			{
				return null;
			}
			object obj = spriteType.CreateInstance();
			if (obj == null)
			{
				return null;
			}
			return new RefObj(obj);
		}

		public static void StartScrolling(RefObj animator, RefObj visualElement)
		{
			animator?.Call("Start", visualElement?.Instance);
		}

		public static void Stop(RefObj animator)
		{
			animator?.Call("Stop");
		}
	}
	public static class GameApi
	{
		private sealed class EventSubscription : IDisposable
		{
			private readonly EventInfo _event;

			private readonly object _target;

			private readonly Delegate _handler;

			public EventSubscription(EventInfo evt, object target, Delegate handler)
			{
				_event = evt;
				_target = target;
				_handler = handler;
			}

			public void Dispose()
			{
				_stateCallbacks.TryRemove(_handler, out Action<string, string> _);
				try
				{
					_event.RemoveEventHandler(_target, _handler);
				}
				catch (Exception)
				{
				}
			}
		}

		private static class NoOp
		{
			private sealed class NullDisposable : IDisposable
			{
				public void Dispose()
				{
				}
			}

			public static readonly IDisposable Disposable = new NullDisposable();
		}

		private static readonly TypeResolver Resolver = TypeResolver.Default;

		private static readonly ConcurrentDictionary<Delegate, Action<string, string>> _stateCallbacks = new ConcurrentDictionary<Delegate, Action<string, string>>();

		public static RefType? DataManager => Type("DataManager");

		public static RefType? GameManagerType => Type("BombGame.GameManager");

		public static RefType? GameNetworkManagerType => Type("BombGame.GameNetworkManager");

		public static RefObj? GameManager => Singleton("BombGame.GameManager", "Singleton");

		public static RefObj? GameNetworkManager => Singleton("BombGame.GameNetworkManager", "Singleton");

		public static RefObj? Bomb
		{
			get
			{
				object obj = MissionHandler?.GetProperty("Bomb");
				if (obj == null)
				{
					return null;
				}
				return new RefObj(obj);
			}
		}

		public static int? BombSocketCount
		{
			get
			{
				object obj = Bomb?.GetField("SocketsContainer");
				if (obj == null)
				{
					return null;
				}
				return new RefObj(obj).GetProperty("childCount") as int?;
			}
		}

		public static bool IsAvailable
		{
			get
			{
				if (GameManagerType == null)
				{
					return GameNetworkManagerType != null;
				}
				return true;
			}
		}

		public static RefObj? LobbyHandler => Lobby.Handler;

		public static PlayerInfo[] Players => Lobby.Players;

		public static ulong? LocalClientId => Lobby.LocalClientId;

		public static PlayerInfo? LocalPlayer => Lobby.LocalPlayer;

		public static object? CurrentMission => MissionHandlerType?.GetStaticField("Mission");

		public static int? MissionId => MissionHandlerType?.GetStaticField("MissionId") as int?;

		public static int? MissionSeed => MissionHandler?.GetField("Seed") as int?;

		public static ushort? MissionHealth
		{
			get
			{
				object currentMission = CurrentMission;
				if (currentMission == null)
				{
					return null;
				}
				try
				{
					return Convert.ToUInt16(new RefObj(currentMission).GetField("Health"));
				}
				catch
				{
					return null;
				}
			}
		}

		public static uint? MissionLength
		{
			get
			{
				object currentMission = CurrentMission;
				if (currentMission == null)
				{
					return null;
				}
				try
				{
					return Convert.ToUInt32(new RefObj(currentMission).GetField("Length"));
				}
				catch
				{
					return null;
				}
			}
		}

		public static int? MissionModuleCount => MissionModules?.Length;

		public static object[]? MissionModules
		{
			get
			{
				object currentMission = CurrentMission;
				if (currentMission == null)
				{
					return null;
				}
				return EnumerateObjects(new RefObj(currentMission).GetField("Modules"));
			}
		}

		public static ushort? BombHealth
		{
			get
			{
				RefObj bomb = Bomb;
				if (bomb == null)
				{
					return null;
				}
				try
				{
					return Convert.ToUInt16(bomb.GetProperty("Health"));
				}
				catch
				{
					return null;
				}
			}
		}

		public static ushort? BombMaxHealth
		{
			get
			{
				RefObj bomb = Bomb;
				if (bomb == null)
				{
					return null;
				}
				try
				{
					return Convert.ToUInt16(bomb.GetProperty("MaxHealth"));
				}
				catch
				{
					return null;
				}
			}
		}

		public static uint? BombTimer
		{
			get
			{
				RefObj bomb = Bomb;
				if (bomb == null)
				{
					return null;
				}
				try
				{
					return Convert.ToUInt32(bomb.GetProperty("Timer"));
				}
				catch
				{
					return null;
				}
			}
		}

		public static bool? BombActive
		{
			get
			{
				RefObj bomb = Bomb;
				if (bomb == null)
				{
					return null;
				}
				object property = bomb.GetProperty("Active");
				bool flag = default(bool);
				int num;
				if (property is bool)
				{
					flag = (bool)property;
					num = 1;
				}
				else
				{
					num = 0;
				}
				return (byte)((uint)num & (flag ? 1u : 0u)) != 0;
			}
		}

		public static RefObj? LocalPlayerController
		{
			get
			{
				RefObj[] array = FindInstances("BombGame.PlayerController");
				if (array.Length == 0)
				{
					return null;
				}
				RefObj[] array2 = array;
				foreach (RefObj refObj in array2)
				{
					object property = refObj.GetProperty("Camera");
					if (property != null)
					{
						object property2 = new RefObj(property).GetProperty("isActiveAndEnabled");
						if (property2 is bool && (bool)property2)
						{
							return refObj;
						}
					}
				}
				return array[0];
			}
		}

		public static PlayerRoleInfo? LocalPlayerRole => GameEnums.ParseRole(LocalPlayerController?.GetProperty("PlayerRole")?.ToString());

		public static string? CurrentStateName => GameManager?.GetProperty("State")?.ToString();

		public static int? CurrentStateIndex
		{
			get
			{
				object obj = GameManager?.GetProperty("State");
				if (obj == null)
				{
					return null;
				}
				try
				{
					return Convert.ToInt32(obj);
				}
				catch
				{
					return null;
				}
			}
		}

		public static bool IsInMission => CurrentStateName == "Mission";

		public static bool IsInLobby => CurrentStateName == "Lobby";

		public static string SavePath => (DataManager?.GetStaticProperty("Path") as string) ?? string.Empty;

		private static RefObj? MissionHandler => Type("MissionHandler")?.Singleton("Handler");

		private static RefType? MissionHandlerType => Type("MissionHandler");

		public static void SetMissionHealth(ushort health)
		{
			object currentMission = CurrentMission;
			if (currentMission != null)
			{
				new RefObj(currentMission).SetField("Health", health);
			}
		}

		public static void SetMissionLength(uint length)
		{
			object currentMission = CurrentMission;
			if (currentMission != null)
			{
				new RefObj(currentMission).SetField("Length", length);
			}
		}

		public static string DescribeSnapshot()
		{
			StringBuilder sb = new StringBuilder();
			Line("state", CurrentStateName);
			Line("stateIndex", CurrentStateIndex);
			Line("isInMission", IsInMission);
			Line("savePath", SavePath);
			Line("localClientId", LocalClientId);
			Line("localPlayer", LocalPlayer);
			Line("players", Players.Length);
			PlayerInfo[] players = Players;
			for (int i = 0; i < players.Length; i++)
			{
				PlayerInfo playerInfo = players[i];
				Line($"player[{playerInfo.NetworkId}]", $"{playerInfo.Name} role={playerInfo.Role} ready={playerInfo.Ready}");
			}
			Line("selectedLevel", Lobby.SelectedLevel);
			Line("missionId", MissionId);
			Line("missionSeed", MissionSeed);
			Line("missionHealth", MissionHealth);
			Line("missionLength", MissionLength);
			Line("missionModules", MissionModuleCount);
			Line("bombActive", BombActive);
			Line("bombHealth", BombHealth);
			Line("bombMaxHealth", BombMaxHealth);
			Line("bombTimer", BombTimer);
			Line("settings.mouseSensitivity", GameSettings.MouseSensitivity);
			Line("settings.volume", GameSettings.Volume);
			Line("settings.musicVolume", GameSettings.MusicVolume);
			Line("settings.microphoneInputLevel", GameSettings.MicrophoneInputLevel);
			return sb.ToString().TrimEnd();
			void Line(string name, object? value)
			{
				StringBuilder stringBuilder = sb;
				StringBuilder.AppendInterpolatedStringHandler handler = new StringBuilder.AppendInterpolatedStringHandler(4, 2, stringBuilder);
				handler.AppendLiteral("  ");
				handler.AppendFormatted(name);
				handler.AppendLiteral(": ");
				handler.AppendFormatted<object>(value ?? "<n/a>");
				stringBuilder.AppendLine(ref handler);
			}
		}

		public static object[]? EnumerateObjects(object? collection)
		{
			if (collection == null)
			{
				return null;
			}
			return ToObjects(collection) ?? TryIndexCollection(collection);
		}

		public static void SaveGame()
		{
			DataManager?.InvokeStatic("Save");
		}

		public static void LoadGame()
		{
			DataManager?.InvokeStatic("Load");
		}

		public static bool HasUnlockedLevel(int level)
		{
			object obj = DataManager?.InvokeStatic("HasUnlockedLevel", level);
			if (obj is bool)
			{
				return (bool)obj;
			}
			return false;
		}

		public static void UnlockLevel(int level)
		{
			DataManager?.InvokeStatic("UnlockLevel", level);
		}

		public static RefObj? FindInstance(string typeName)
		{
			RefObj[] array = FindInstances(typeName);
			if (array.Length == 0)
			{
				return null;
			}
			return array[0];
		}

		public static RefObj[] FindInstances(string typeName)
		{
			if (string.IsNullOrWhiteSpace(typeName))
			{
				return Array.Empty<RefObj>();
			}
			Type type = Resolver.Resolve(typeName);
			if ((object)type == null)
			{
				return Array.Empty<RefObj>();
			}
			Type type2 = Resolver.Resolve("UnityEngine.Object");
			if ((object)type2 == null)
			{
				return Array.Empty<RefObj>();
			}
			try
			{
				MethodInfo methodInfo = type2.GetMethods(BindingFlags.Static | BindingFlags.Public).FirstOrDefault(delegate(MethodInfo m)
				{
					bool flag = (object)m != null && m.IsGenericMethod && m.ContainsGenericParameters;
					if (flag)
					{
						string name = m.Name;
						bool flag2 = ((name == "FindObjectsByType" || name == "FindObjectsOfType") ? true : false);
						flag = flag2;
					}
					return flag && m.GetGenericArguments().Length == 1;
				});
				if ((object)methodInfo == null)
				{
					return Array.Empty<RefObj>();
				}
				MethodInfo methodInfo2 = methodInfo.MakeGenericMethod(type);
				object[] array = methodInfo2.GetParameters().Length switch
				{
					2 => TwoEnumArgs(), 
					3 => ThreeEnumArgs(type), 
					_ => Array.Empty<object>(), 
				};
				if (array == null)
				{
					return Array.Empty<RefObj>();
				}
				object obj = methodInfo2.Invoke(null, array);
				return (obj is Array source) ? (from object o in source
					where o != null
					select new RefObj(o)).ToArray() : ((!(obj is IEnumerable source2)) ? Array.Empty<RefObj>() : (from object o in source2
					where o != null
					select new RefObj(o)).ToArray());
			}
			catch (Exception ex) when (((ex is TargetParameterCountException || ex is NullReferenceException || ex is ArgumentException || ex is TargetInvocationException || ex is InvalidOperationException || ex is NotSupportedException || ex is TypeLoadException || ex is TypeInitializationException) ? 1 : 0) != 0)
			{
				return Array.Empty<RefObj>();
			}
		}

		public static IDisposable SubscribeStateChanged(Action<string, string> onChanged)
		{
			RefObj gameManager = GameManager;
			if (gameManager == null)
			{
				return NoOp.Disposable;
			}
			EventInfo eventInfo = FindEvent(gameManager.Type.Type, "OnStateChanged");
			if ((object)eventInfo == null)
			{
				return NoOp.Disposable;
			}
			Type eventHandlerType = eventInfo.EventHandlerType;
			if ((object)eventHandlerType == null)
			{
				return NoOp.Disposable;
			}
			Delegate obj = BuildStateBridge(eventHandlerType, onChanged);
			if ((object)obj =