Decompiled source of BOMBANANA Library v1.0.0
plugins/BOMBANANA.Library-1.0.0.dll
Decompiled 2 weeks ago
The result has been truncated due to the large size, download it to view full contents!
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 =