Decompiled source of TwitchTrolling v1.6.0

com.github.zehsteam.MetadataUtils.dll

Decompiled a week ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Logging;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.SceneManagement;
using com.github.zehsteam.MetadataUtils.Modules;
using com.github.zehsteam.MetadataUtils.Objects;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("Zehs")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyCopyright("Copyright © 2025 Zehs")]
[assembly: AssemblyFileVersion("1.1.0.0")]
[assembly: AssemblyInformationalVersion("1.1.0+45627603d3869d4ee4f5fb1b7e7df530461a2c7c")]
[assembly: AssemblyProduct("MetadataUtils")]
[assembly: AssemblyTitle("com.github.zehsteam.MetadataUtils")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.1.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.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 com.github.zehsteam.MetadataUtils
{
	internal static class Logger
	{
		public static ManualLogSource ManualLogSource { get; private set; }

		public static void Initialize(ManualLogSource manualLogSource)
		{
			ManualLogSource = manualLogSource;
		}

		public static void LogDebug(object data)
		{
			Log((LogLevel)32, data);
		}

		public static void LogInfo(object data)
		{
			Log((LogLevel)16, data);
		}

		public static void LogWarning(object data)
		{
			Log((LogLevel)4, data);
		}

		public static void LogError(object data)
		{
			Log((LogLevel)2, data);
		}

		public static void LogFatal(object data)
		{
			Log((LogLevel)1, data);
		}

		public static void Log(LogLevel logLevel, object data)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			ManualLogSource manualLogSource = ManualLogSource;
			if (manualLogSource != null)
			{
				manualLogSource.Log(logLevel, data);
			}
		}
	}
	[BepInPlugin("com.github.zehsteam.MetadataUtils", "MetadataUtils", "1.1.0")]
	internal class Plugin : BaseUnityPlugin
	{
		internal static Plugin Instance { get; private set; }

		private void Awake()
		{
			Instance = this;
			Logger.Initialize(Logger.CreateLogSource("com.github.zehsteam.MetadataUtils"));
			Logger.LogInfo("MetadataUtils has awoken!");
			MetadataRegistry.Initialize();
		}
	}
	public static class MyPluginInfo
	{
		public const string PLUGIN_GUID = "com.github.zehsteam.MetadataUtils";

		public const string PLUGIN_NAME = "MetadataUtils";

		public const string PLUGIN_VERSION = "1.1.0";
	}
}
namespace com.github.zehsteam.MetadataUtils.Objects
{
	public class Metadata
	{
		private Dictionary<string, object> _entries = new Dictionary<string, object>();

		public Scene Scene { get; private set; }

		public Metadata(Scene scene)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			Scene = scene;
		}

		public bool Has(string key)
		{
			return _entries.ContainsKey(key);
		}

		public T Get<T>(string key, T defaultValue = default(T))
		{
			if (TryGet<T>(key, out var value))
			{
				return value;
			}
			return defaultValue;
		}

		public bool TryGet<T>(string key, out T value)
		{
			if (_entries.TryGetValue(key, out var value2) && value2 is T val)
			{
				value = val;
				return true;
			}
			value = default(T);
			return false;
		}

		public void Set<T>(string key, T value)
		{
			_entries[key] = value;
		}

		public void Set(Metadata metadata)
		{
			if (metadata != null)
			{
				_entries = metadata._entries;
			}
		}

		public bool Remove(string key)
		{
			return _entries.Remove(key);
		}
	}
}
namespace com.github.zehsteam.MetadataUtils.Modules
{
	public static class MetadataRegistry
	{
		private static readonly Dictionary<Object, Metadata> _entries = new Dictionary<Object, Metadata>();

		internal static void Initialize()
		{
			SceneManager.sceneUnloaded += HandleSceneUnloaded;
		}

		public static bool HasMetadata(Object obj)
		{
			return _entries.ContainsKey(obj);
		}

		public static Metadata GetOrCreate(Object obj)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			if (_entries.TryGetValue(obj, out var value))
			{
				return value;
			}
			Scene scene = ExtractScene(obj);
			Metadata metadata = new Metadata(scene);
			_entries[obj] = metadata;
			return metadata;
		}

		public static bool TryGet(Object obj, out Metadata metadata)
		{
			return _entries.TryGetValue(obj, out metadata);
		}

		public static bool Remove(Object obj)
		{
			return _entries.Remove(obj);
		}

		private static Scene ExtractScene(Object obj)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = (GameObject)(object)((obj is GameObject) ? obj : null);
			if (val != null)
			{
				return val.scene;
			}
			Component val2 = (Component)(object)((obj is Component) ? obj : null);
			if (val2 != null)
			{
				return val2.gameObject.scene;
			}
			return default(Scene);
		}

		private static void RemoveMetadataForScene(Scene scene)
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			Dictionary<Object, Metadata> dictionary = new Dictionary<Object, Metadata>(_entries);
			foreach (KeyValuePair<Object, Metadata> item in dictionary)
			{
				if (item.Value.Scene == scene)
				{
					_entries.Remove(item.Key);
				}
			}
		}

		private static void HandleSceneUnloaded(Scene scene)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			RemoveMetadataForScene(scene);
		}
	}
}
namespace com.github.zehsteam.MetadataUtils.Extensions
{
	public static class ComponentExtensions
	{
		private const bool _defaultTargetGameObject = true;

		public static bool HasMetadata(this Component component, bool targetGameObject = true)
		{
			return MetadataRegistry.HasMetadata(GetObject(component, targetGameObject));
		}

		public static Metadata GetOrCreateMetadata(this Component component, bool targetGameObject = true)
		{
			return MetadataRegistry.GetOrCreate(GetObject(component, targetGameObject));
		}

		public static bool TryGetMetadata(this Component component, out Metadata metadata, bool targetGameObject = true)
		{
			return MetadataRegistry.TryGet(GetObject(component, targetGameObject), out metadata);
		}

		public static bool RemoveMetadata(this Component component, bool targetGameObject = true)
		{
			return MetadataRegistry.Remove(GetObject(component, targetGameObject));
		}

		private static Object GetObject(Component component, bool targetGameObject)
		{
			if (!targetGameObject)
			{
				return (Object)(object)component;
			}
			return (Object)(object)component.gameObject;
		}
	}
	public static class GameObjectExtensions
	{
		public static bool HasMetadata(this GameObject gameObject)
		{
			return MetadataRegistry.HasMetadata((Object)(object)gameObject);
		}

		public static Metadata GetOrCreateMetadata(this GameObject gameObject)
		{
			return MetadataRegistry.GetOrCreate((Object)(object)gameObject);
		}

		public static bool TryGetMetadata(this GameObject gameObject, out Metadata metadata)
		{
			return MetadataRegistry.TryGet((Object)(object)gameObject, out metadata);
		}

		public static bool RemoveMetadata(this GameObject gameObject)
		{
			return MetadataRegistry.Remove((Object)(object)gameObject);
		}
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		public IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
}

com.github.zehsteam.PlayerDamageTracker.dll

Decompiled a week ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Threading;
using System.Threading.Tasks;
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Mono.Cecil;
using Mono.Cecil.Cil;
using Photon.Pun;
using UnityEngine;
using com.github.zehsteam.MetadataUtils.Extensions;
using com.github.zehsteam.MetadataUtils.Objects;
using com.github.zehsteam.PlayerDamageTracker.Extensions;
using com.github.zehsteam.PlayerDamageTracker.Helpers;
using com.github.zehsteam.PlayerDamageTracker.Modules;
using com.github.zehsteam.PlayerDamageTracker.Patches;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("Zehs")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyCopyright("Copyright © 2025 Zehs")]
[assembly: AssemblyFileVersion("1.1.0.0")]
[assembly: AssemblyInformationalVersion("1.1.0+a499261de8bc0668ccaabdb241bb139052d1cd57")]
[assembly: AssemblyProduct("PlayerDamageTracker")]
[assembly: AssemblyTitle("com.github.zehsteam.PlayerDamageTracker")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.1.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.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 com.github.zehsteam.PlayerDamageTracker
{
	internal static class Logger
	{
		public static ManualLogSource ManualLogSource { get; private set; }

		public static void Initialize(ManualLogSource manualLogSource)
		{
			ManualLogSource = manualLogSource;
		}

		public static void LogDebug(object data)
		{
			Log((LogLevel)32, data);
		}

		public static void LogInfo(object data)
		{
			Log((LogLevel)16, data);
		}

		public static void LogWarning(object data)
		{
			Log((LogLevel)4, data);
		}

		public static void LogError(object data)
		{
			Log((LogLevel)2, data);
		}

		public static void LogFatal(object data)
		{
			Log((LogLevel)1, data);
		}

		public static void Log(LogLevel logLevel, object data)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			ManualLogSource manualLogSource = ManualLogSource;
			if (manualLogSource != null)
			{
				manualLogSource.Log(logLevel, data);
			}
		}
	}
	[BepInPlugin("com.github.zehsteam.PlayerDamageTracker", "PlayerDamageTracker", "1.1.0")]
	internal class Plugin : BaseUnityPlugin
	{
		private readonly Harmony _harmony = new Harmony("com.github.zehsteam.PlayerDamageTracker");

		internal static Plugin Instance { get; private set; }

		private void Awake()
		{
			Instance = this;
			Logger.Initialize(Logger.CreateLogSource("com.github.zehsteam.PlayerDamageTracker"));
			Logger.LogInfo("PlayerDamageTracker has awoken!");
			_harmony.PatchAll(typeof(PlayerHealthPatch));
			_harmony.PatchAll(typeof(HurtColliderPatch));
			_harmony.PatchAll(typeof(ParticleScriptExplosionPatch));
			_harmony.PatchAll(typeof(ItemGrenadeDuctTapedPatch));
			((Object)this).hideFlags = (HideFlags)61;
			Object.DontDestroyOnLoad((Object)(object)this);
		}

		private void Start()
		{
			HurtOtherPatcher.PatchAll(_harmony);
		}
	}
	public static class MyPluginInfo
	{
		public const string PLUGIN_GUID = "com.github.zehsteam.PlayerDamageTracker";

		public const string PLUGIN_NAME = "PlayerDamageTracker";

		public const string PLUGIN_VERSION = "1.1.0";
	}
}
namespace com.github.zehsteam.PlayerDamageTracker.Patches
{
	[HarmonyPatch(typeof(HurtCollider))]
	internal static class HurtColliderPatch
	{
		[HarmonyPatch("PlayerHurt")]
		[HarmonyTranspiler]
		private static IEnumerable<CodeInstruction> PlayerHurtTranspiler(IEnumerable<CodeInstruction> instructions)
		{
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Expected O, but got Unknown
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Expected O, but got Unknown
			string text = "HurtColliderPatch: [PlayerHurt Transpiler]";
			MethodInfo methodInfo = AccessTools.Method(typeof(PlayerHealth), "Hurt", (Type[])null, (Type[])null);
			MethodInfo methodInfo2 = AccessTools.Method(typeof(PlayerHealthExtensions), "HurtWithCaller", (Type[])null, (Type[])null);
			if (methodInfo == null || methodInfo2 == null)
			{
				Logger.LogError(text + " Failed to create transpiler. Required methods not found.");
				return instructions;
			}
			List<CodeInstruction> list = new List<CodeInstruction>();
			foreach (CodeInstruction instruction in instructions)
			{
				if (CodeInstructionExtensions.Calls(instruction, methodInfo))
				{
					list.Add(new CodeInstruction(OpCodes.Ldarg_0, (object)null));
					list.Add(new CodeInstruction(OpCodes.Call, (object)methodInfo2));
					Logger.LogDebug(text + " Replaced calls to " + methodInfo.Name + " with " + methodInfo2.Name);
				}
				else
				{
					list.Add(instruction);
				}
			}
			return list.AsEnumerable();
		}
	}
	internal static class HurtOtherPatcher
	{
		private static readonly MethodInfo _hurtOtherMethod = AccessTools.Method(typeof(PlayerHealth), "HurtOther", (Type[])null, (Type[])null);

		private static readonly FieldInfo _hurtOtherCallerField = AccessTools.Field(typeof(PlayerHealthPatch), "HurtOtherCaller");

		private static bool _patched;

		private static int _transpilersCreated;

		public static void PatchAll(Harmony harmony)
		{
			if (_patched)
			{
				return;
			}
			_patched = true;
			LogInfo("Running patcher...");
			if (_hurtOtherMethod == null)
			{
				LogError("Required methods not found for patcher.");
				return;
			}
			IEnumerable<Assembly> validAssemblies = GetValidAssemblies();
			LogInfo($"Found {validAssemblies.Count()} valid assemblies.");
			foreach (Assembly item in validAssemblies)
			{
				LogDebug("Found assembly: " + item.FullName);
			}
			_transpilersCreated = 0;
			Parallel.ForEach(validAssemblies, delegate(Assembly assembly)
			{
				PatchAssembly(assembly, harmony);
			});
			LogInfo($"Created {_transpilersCreated} transpilers.");
			LogInfo("Patcher finished.");
		}

		private static void PatchAssembly(Assembly assembly, Harmony harmony)
		{
			LogDebug("Patching assembly: " + assembly.FullName);
			IEnumerable<Type> validClasses = GetValidClasses(assembly);
			Parallel.ForEach(validClasses, delegate(Type type)
			{
				PatchClass(type, harmony);
			});
		}

		private static void PatchClass(Type type, Harmony harmony)
		{
			LogDebug("Patching class: " + type.FullName);
			IEnumerable<MethodInfo> validMethods = GetValidMethods(type);
			Parallel.ForEach(validMethods, delegate(MethodInfo method)
			{
				PatchMethod(method, harmony);
			});
		}

		private static void PatchMethod(MethodInfo method, Harmony harmony)
		{
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Expected O, but got Unknown
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Expected O, but got Unknown
			try
			{
				if (ReflectionHelper.IsCoroutineMethod(method))
				{
					MethodInfo coroutineMoveNextMethod = ReflectionHelper.GetCoroutineMoveNextMethod(method);
					if (coroutineMoveNextMethod == null)
					{
						return;
					}
					harmony.Patch((MethodBase)coroutineMoveNextMethod, (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(typeof(HurtOtherPatcher), "Transpiler", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null);
					LogDebug($"Patched coroutine: {coroutineMoveNextMethod}");
				}
				else
				{
					harmony.Patch((MethodBase)method, (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(typeof(HurtOtherPatcher), "Transpiler", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null);
					LogDebug("Patched method: " + method.Name);
				}
				Interlocked.Increment(ref _transpilersCreated);
			}
			catch (Exception arg)
			{
				LogError($"Failed to patch method: {method}\n\n{arg}");
			}
		}

		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Expected O, but got Unknown
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Expected O, but got Unknown
			if (_hurtOtherMethod == null)
			{
				LogError("Required methods not found for transpiler.");
				return instructions;
			}
			List<CodeInstruction> list = new List<CodeInstruction>(instructions);
			for (int num = list.Count - 1; num >= 0; num--)
			{
				CodeInstruction val = list[num];
				if (CodeInstructionExtensions.Calls(val, _hurtOtherMethod))
				{
					int num2 = ILHelper.FindArgLoadStart(list, _hurtOtherMethod, num);
					list.Insert(num2, new CodeInstruction(OpCodes.Ldarg_0, (object)null));
					list.Insert(num2 + 1, new CodeInstruction(OpCodes.Stsfld, (object)_hurtOtherCallerField));
				}
			}
			return list.AsEnumerable();
		}

		private static IEnumerable<Assembly> GetValidAssemblies()
		{
			return AppDomain.CurrentDomain.GetAssemblies().Where(IsValidAssembly);
		}

		private static bool IsValidAssembly(Assembly assembly)
		{
			if (assembly == null || assembly.IsDynamic)
			{
				return false;
			}
			if (assembly == Assembly.GetExecutingAssembly())
			{
				return false;
			}
			string[] values = new string[6] { "System.", "giosuel.Imperium", "giosuel.Librarium", "MMHOOK_", "UnityExplorer.", "UniverseLib.Mono" };
			if (assembly.FullName.StartsWithAny(values, StringComparison.OrdinalIgnoreCase))
			{
				return false;
			}
			if (assembly.Location.StartsWith(Paths.PluginPath, StringComparison.OrdinalIgnoreCase))
			{
				return true;
			}
			if (assembly.FullName.StartsWith("Assembly-CSharp"))
			{
				return true;
			}
			return false;
		}

		private static IEnumerable<Type> GetValidClasses(Assembly assembly)
		{
			if (assembly == null)
			{
				return Array.Empty<Type>();
			}
			try
			{
				return assembly.GetTypes().Where(IsValidClass);
			}
			catch (ReflectionTypeLoadException ex)
			{
				LogWarning("Error loading types from assembly " + assembly.FullName + ": " + ex.Message);
				return Array.Empty<Type>();
			}
		}

		private static bool IsValidClass(Type type)
		{
			if (type == null)
			{
				return false;
			}
			if (!type.IsClass || type.IsAbstract)
			{
				return false;
			}
			if (type == typeof(PlayerHealth))
			{
				return false;
			}
			if (typeof(MonoBehaviour).IsAssignableFrom(type))
			{
				return true;
			}
			return false;
		}

		private static IEnumerable<MethodInfo> GetValidMethods(Type type)
		{
			return type.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).Where(IsValidMethod);
		}

		private static bool IsValidMethod(MethodInfo method)
		{
			if (method == null)
			{
				return false;
			}
			if (method.IsGenericMethod || method.DeclaringType.IsGenericType)
			{
				return false;
			}
			return ILHelper.MethodCallsMethod(method, _hurtOtherMethod);
		}

		private static void LogDebug(object data)
		{
			Log((LogLevel)32, data);
		}

		private static void LogInfo(object data)
		{
			Log((LogLevel)16, data);
		}

		private static void LogWarning(object data)
		{
			Log((LogLevel)4, data);
		}

		private static void LogError(object data)
		{
			Log((LogLevel)2, data);
		}

		private static void Log(LogLevel logLevel, object data)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			Logger.Log(logLevel, string.Format("{0}: {1}", "HurtOtherPatcher", data));
		}
	}
	[HarmonyPatch(typeof(ItemGrenadeDuctTaped))]
	internal static class ItemGrenadeDuctTapedPatch
	{
		[HarmonyPatch("Explosion")]
		[HarmonyTranspiler]
		private static IEnumerable<CodeInstruction> ExplosionTranspiler(IEnumerable<CodeInstruction> instructions)
		{
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ff: Expected O, but got Unknown
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_0111: Expected O, but got Unknown
			//IL_015b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0165: Expected O, but got Unknown
			//IL_016e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0178: Expected O, but got Unknown
			string text = "ItemGrenadeDuctTapedPatch: [Explosion Transpiler]";
			MethodInfo methodInfo = AccessTools.Method(typeof(Object), "Instantiate", new Type[3]
			{
				typeof(GameObject),
				typeof(Vector3),
				typeof(Quaternion)
			}, (Type[])null);
			MethodInfo methodInfo2 = AccessTools.Method(typeof(ItemGrenadeDuctTapedPatch), "InstantiateReplacement", (Type[])null, (Type[])null);
			MethodInfo methodInfo3 = AccessTools.Method(typeof(PhotonNetwork), "Instantiate", (Type[])null, (Type[])null);
			MethodInfo methodInfo4 = AccessTools.Method(typeof(ItemGrenadeDuctTapedPatch), "PhotonNetworkInstantiateReplacement", (Type[])null, (Type[])null);
			if (methodInfo == null || methodInfo2 == null || methodInfo3 == null || methodInfo4 == null)
			{
				Logger.LogError(text + " Failed to create transpiler. Required methods not found.");
				return instructions;
			}
			List<CodeInstruction> list = new List<CodeInstruction>();
			foreach (CodeInstruction instruction in instructions)
			{
				if (CodeInstructionExtensions.Calls(instruction, methodInfo))
				{
					list.Add(new CodeInstruction(OpCodes.Ldarg_0, (object)null));
					list.Add(new CodeInstruction(OpCodes.Call, (object)methodInfo2));
					Logger.LogDebug(text + " Replaced calls to " + methodInfo.Name + " with " + methodInfo2.Name);
				}
				else if (CodeInstructionExtensions.Calls(instruction, methodInfo3))
				{
					list.Add(new CodeInstruction(OpCodes.Ldarg_0, (object)null));
					list.Add(new CodeInstruction(OpCodes.Call, (object)methodInfo4));
					Logger.LogDebug(text + " Replaced calls to " + methodInfo3.Name + " with " + methodInfo4.Name);
				}
				else
				{
					list.Add(instruction);
				}
			}
			return list.AsEnumerable();
		}

		private static GameObject InstantiateReplacement(GameObject prefab, Vector3 position, Quaternion rotation, object caller = null)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = Object.Instantiate<GameObject>(prefab, position, rotation);
			AddMetadata(caller, val);
			return val;
		}

		private static GameObject PhotonNetworkInstantiateReplacement(string prefabName, Vector3 position, Quaternion rotation, byte group = 0, object[] data = null, object caller = null)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = PhotonNetwork.Instantiate(prefabName, position, rotation, group, data);
			AddMetadata(caller, val);
			return val;
		}

		private static void AddMetadata(object caller, GameObject gameObject)
		{
			if (caller != null && !((Object)(object)gameObject == (Object)null))
			{
				ItemGrenadeDuctTaped val = (ItemGrenadeDuctTaped)((caller is ItemGrenadeDuctTaped) ? caller : null);
				PhysGrabObject val2 = default(PhysGrabObject);
				PhysGrabObject val3 = default(PhysGrabObject);
				if (val != null && ((Component)val).TryGetComponent<PhysGrabObject>(ref val2) && ComponentExtensions.HasMetadata((Component)(object)val2, true) && gameObject.TryGetComponent<PhysGrabObject>(ref val3))
				{
					Metadata orCreateMetadata = ComponentExtensions.GetOrCreateMetadata((Component)(object)val2, true);
					Metadata orCreateMetadata2 = ComponentExtensions.GetOrCreateMetadata((Component)(object)val3, true);
					orCreateMetadata2.Set(orCreateMetadata);
				}
			}
		}
	}
	[HarmonyPatch(typeof(ParticleScriptExplosion))]
	internal static class ParticleScriptExplosionPatch
	{
		private class Cleanup : MonoBehaviour
		{
			private ParticlePrefabExplosion _particlePrefabExplosion;

			private void Awake()
			{
				_particlePrefabExplosion = ((Component)this).GetComponent<ParticlePrefabExplosion>();
			}

			private void OnDestroy()
			{
				Explosions.Remove(_particlePrefabExplosion.HurtCollider);
			}
		}

		public static Dictionary<HurtCollider, Metadata> Explosions { get; private set; } = new Dictionary<HurtCollider, Metadata>();


		[HarmonyPatch("Start")]
		[HarmonyPostfix]
		private static void StartPatch(ParticleScriptExplosion __instance)
		{
			Metadata val = null;
			PhysGrabObject val2 = default(PhysGrabObject);
			if (((Component)__instance).TryGetComponent<PhysGrabObject>(ref val2) && ComponentExtensions.HasMetadata((Component)(object)val2, true))
			{
				val = ComponentExtensions.GetOrCreateMetadata((Component)(object)val2, true);
			}
			EnemyBang val3 = default(EnemyBang);
			if (((Component)__instance).TryGetComponent<EnemyBang>(ref val3) && ComponentExtensions.HasMetadata((Component)(object)val3, true))
			{
				val = ComponentExtensions.GetOrCreateMetadata((Component)(object)val3, true);
			}
			if (val != null)
			{
				Metadata orCreateMetadata = ComponentExtensions.GetOrCreateMetadata((Component)(object)__instance, true);
				orCreateMetadata.Set<Metadata>("ParentMetadata", val);
			}
		}

		[HarmonyPatch("Spawn")]
		[HarmonyPostfix]
		private static void SpawnPatch(ParticleScriptExplosion __instance, ref ParticlePrefabExplosion __result)
		{
			Metadata val = default(Metadata);
			Metadata value = default(Metadata);
			if (ComponentExtensions.TryGetMetadata((Component)(object)__instance, ref val, true) && val.TryGet<Metadata>("ParentMetadata", ref value))
			{
				Explosions[__result.HurtCollider] = value;
				((Component)__result).gameObject.AddComponent<Cleanup>();
			}
		}
	}
	[HarmonyPatch(typeof(PlayerHealth))]
	internal static class PlayerHealthPatch
	{
		public static object HurtOtherCaller;

		[HarmonyPatch("HurtOther")]
		[HarmonyTranspiler]
		private static IEnumerable<CodeInstruction> HurtOtherTranspiler(IEnumerable<CodeInstruction> instructions)
		{
			return GetHurtOtherTranspilerInstructions("PlayerHealthPatch: [HurtOther Transpiler]", instructions);
		}

		[HarmonyPatch("HurtOtherRPC")]
		[HarmonyTranspiler]
		private static IEnumerable<CodeInstruction> HurtOtherRPCTranspiler(IEnumerable<CodeInstruction> instructions)
		{
			return GetHurtOtherTranspilerInstructions("PlayerHealthPatch: [HurtOtherRPC Transpiler]", instructions);
		}

		private static IEnumerable<CodeInstruction> GetHurtOtherTranspilerInstructions(string logHeader, IEnumerable<CodeInstruction> instructions)
		{
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Expected O, but got Unknown
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Expected O, but got Unknown
			MethodInfo methodInfo = AccessTools.Method(typeof(PlayerHealth), "Hurt", (Type[])null, (Type[])null);
			MethodInfo methodInfo2 = AccessTools.Method(typeof(PlayerHealthExtensions), "HurtWithCaller", (Type[])null, (Type[])null);
			FieldInfo fieldInfo = AccessTools.Field(typeof(PlayerHealthPatch), "HurtOtherCaller");
			if (methodInfo == null || methodInfo2 == null || fieldInfo == null)
			{
				Logger.LogError(logHeader + " Failed to create transpiler. Required methods not found.");
				return instructions;
			}
			List<CodeInstruction> list = new List<CodeInstruction>();
			foreach (CodeInstruction instruction in instructions)
			{
				if (CodeInstructionExtensions.Calls(instruction, methodInfo))
				{
					list.Add(new CodeInstruction(OpCodes.Ldsfld, (object)fieldInfo));
					list.Add(new CodeInstruction(OpCodes.Call, (object)methodInfo2));
					Logger.LogDebug(logHeader + " Replaced calls to " + methodInfo.Name + " with " + methodInfo2.Name);
				}
				else
				{
					list.Add(instruction);
				}
			}
			return list.AsEnumerable();
		}
	}
}
namespace com.github.zehsteam.PlayerDamageTracker.Modules
{
	public static class Events
	{
		public static event Action<EnemyParent> OnDamagedByEnemy;

		public static event Action<PhysGrabObject> OnDamagedByPhysGrabObject;

		public static event Action<Metadata> OnDamagedByExplosion;

		public static event Action<HurtCollider> OnDamagedByOther;

		public static event Action<EnemyParent> OnKilledByEnemy;

		public static event Action<PhysGrabObject> OnKilledByPhysGrabObject;

		public static event Action<Metadata> OnKilledByExplosion;

		public static event Action<HurtCollider> OnKilledByOther;

		internal static void InvokeOnDamagedByEnemy(EnemyParent enemyParent)
		{
			Events.OnDamagedByEnemy?.Invoke(enemyParent);
		}

		internal static void InvokeOnDamagedByPhysGrabObject(PhysGrabObject physGrabObject)
		{
			Events.OnDamagedByPhysGrabObject?.Invoke(physGrabObject);
		}

		internal static void InvokeOnDamagedByExplosion(Metadata metadata)
		{
			Events.OnDamagedByExplosion?.Invoke(metadata);
		}

		internal static void InvokeOnDamagedByOther(HurtCollider hurtCollider)
		{
			Events.OnDamagedByOther?.Invoke(hurtCollider);
		}

		internal static void InvokeOnKilledByEnemy(EnemyParent enemyParent)
		{
			Events.OnKilledByEnemy?.Invoke(enemyParent);
		}

		internal static void InvokeOnKilledByPhysGrabObject(PhysGrabObject physGrabObject)
		{
			Events.OnKilledByPhysGrabObject?.Invoke(physGrabObject);
		}

		internal static void InvokeOnKilledByExplosion(Metadata metadata)
		{
			Events.OnKilledByExplosion?.Invoke(metadata);
		}

		internal static void InvokeOnKilledByOther(HurtCollider hurtCollider)
		{
			Events.OnKilledByOther?.Invoke(hurtCollider);
		}
	}
}
namespace com.github.zehsteam.PlayerDamageTracker.Helpers
{
	internal static class ILHelper
	{
		private static DefaultAssemblyResolver _cachedResolver;

		private static Dictionary<string, ModuleDefinition> _cachedModules = new Dictionary<string, ModuleDefinition>();

		private static DefaultAssemblyResolver GetCachedResolver()
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Expected O, but got Unknown
			if (_cachedResolver != null)
			{
				return _cachedResolver;
			}
			DefaultAssemblyResolver val = new DefaultAssemblyResolver();
			((BaseAssemblyResolver)val).AddSearchDirectory(Paths.ManagedPath);
			((BaseAssemblyResolver)val).AddSearchDirectory(Paths.BepInExAssemblyDirectory);
			((BaseAssemblyResolver)val).AddSearchDirectory(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location));
			string[] directories = Directory.GetDirectories(Paths.PluginPath, "*", SearchOption.AllDirectories);
			foreach (string text in directories)
			{
				((BaseAssemblyResolver)val).AddSearchDirectory(text);
			}
			_cachedResolver = val;
			return _cachedResolver;
		}

		public static IEnumerable<Instruction> GetInstructions(MethodInfo method)
		{
			if (method == null)
			{
				return Array.Empty<Instruction>();
			}
			try
			{
				ModuleDefinition moduleDefinition = GetModuleDefinition(method.DeclaringType.Assembly);
				if (moduleDefinition == null)
				{
					return Array.Empty<Instruction>();
				}
				TypeDefinition type = moduleDefinition.GetType(method.DeclaringType.FullName);
				MethodDefinition val = ((type != null) ? ((IEnumerable<MethodDefinition>)type.Methods).FirstOrDefault((Func<MethodDefinition, bool>)((MethodDefinition m) => ((MemberReference)m).Name == method.Name)) : null);
				if (val == null || val.Body == null)
				{
					Logger.LogWarning("ILHelper: Failed to get IL for method: " + method.Name);
					return Array.Empty<Instruction>();
				}
				return (IEnumerable<Instruction>)val.Body.Instructions;
			}
			catch (Exception arg)
			{
				Logger.LogWarning($"ILHelper: Exception while processing method {method.Name}: {arg}");
				return Array.Empty<Instruction>();
			}
		}

		public static IEnumerable<Instruction> GetCoroutineInstructions(MethodInfo method)
		{
			if (method == null)
			{
				return Array.Empty<Instruction>();
			}
			try
			{
				ModuleDefinition moduleDefinition = GetModuleDefinition(method.DeclaringType.Assembly);
				if (moduleDefinition == null)
				{
					return Array.Empty<Instruction>();
				}
				TypeDefinition type = moduleDefinition.GetType(method.DeclaringType.FullName);
				TypeDefinition val = ((IEnumerable<TypeDefinition>)type.NestedTypes).FirstOrDefault((Func<TypeDefinition, bool>)((TypeDefinition t) => ((MemberReference)t).Name.Contains("<" + method.Name + ">")));
				if (val == null)
				{
					Logger.LogWarning("ILHelper: State machine type for " + method.Name + " not found.");
					return Array.Empty<Instruction>();
				}
				MethodDefinition val2 = ((IEnumerable<MethodDefinition>)val.Methods).FirstOrDefault((Func<MethodDefinition, bool>)((MethodDefinition m) => ((MemberReference)m).Name == "MoveNext"));
				if (val2 == null)
				{
					Logger.LogWarning("ILHelper: MoveNext method not found in state machine: " + ((MemberReference)val).Name);
					return Array.Empty<Instruction>();
				}
				return (IEnumerable<Instruction>)val2.Body.Instructions;
			}
			catch (Exception arg)
			{
				Logger.LogWarning($"ILHelper: Exception while processing coroutine method {method.Name}: {arg}");
				return Array.Empty<Instruction>();
			}
		}

		public static ModuleDefinition GetModuleDefinition(Assembly assembly)
		{
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Expected O, but got Unknown
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Expected O, but got Unknown
			//IL_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_012b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0137: Expected O, but got Unknown
			if (assembly == null)
			{
				return null;
			}
			try
			{
				if (TryGetCachedModuleDefinition(assembly, out var module))
				{
					return module;
				}
				DefaultAssemblyResolver cachedResolver = GetCachedResolver();
				if (!string.IsNullOrEmpty(assembly.Location) && File.Exists(assembly.Location))
				{
					ModuleDefinition val = ModuleDefinition.ReadModule(assembly.Location, new ReaderParameters
					{
						AssemblyResolver = (IAssemblyResolver)(object)cachedResolver
					});
					CacheModuleDefinition(assembly, val);
					return val;
				}
				string text = assembly.GetName().Name + ".dll";
				string text2 = Path.Combine(Paths.ManagedPath, text);
				if (File.Exists(text2))
				{
					Logger.LogDebug("ILHelper: Attempting to load " + text + " from Managed path: " + text2);
					ModuleDefinition val2 = ModuleDefinition.ReadModule(text2, new ReaderParameters
					{
						AssemblyResolver = (IAssemblyResolver)(object)cachedResolver
					});
					CacheModuleDefinition(assembly, val2);
					return val2;
				}
				Logger.LogWarning("ILHelper: Assembly location for " + assembly.FullName + " is null or invalid. Attempting to load from memory.");
				if (assembly.IsDynamic)
				{
					Logger.LogWarning("ILHelper: Cannot process dynamic assembly: " + assembly.FullName);
					return null;
				}
				byte[] buffer = File.ReadAllBytes(assembly.ManifestModule.FullyQualifiedName);
				using MemoryStream memoryStream = new MemoryStream(buffer);
				ModuleDefinition val3 = ModuleDefinition.ReadModule((Stream)memoryStream, new ReaderParameters
				{
					AssemblyResolver = (IAssemblyResolver)(object)cachedResolver
				});
				CacheModuleDefinition(assembly, val3);
				return val3;
			}
			catch (Exception arg)
			{
				Logger.LogWarning($"ILHelper: Failed to get ModuleDefinition for assembly {assembly.FullName}. {arg}");
				return null;
			}
		}

		private static ModuleDefinition GetCachedModuleDefinition(Assembly assembly)
		{
			if (assembly == null)
			{
				return null;
			}
			if (_cachedModules.TryGetValue(assembly.FullName, out var value))
			{
				return value;
			}
			return null;
		}

		private static bool TryGetCachedModuleDefinition(Assembly assembly, out ModuleDefinition module)
		{
			module = GetCachedModuleDefinition(assembly);
			return module != null;
		}

		private static void CacheModuleDefinition(Assembly assembly, ModuleDefinition module)
		{
			if (!(assembly == null) && module != null && assembly.FullName.StartsWith("Assembly-CSharp"))
			{
				_cachedModules[assembly.FullName] = module;
			}
		}

		public static bool MethodCallsMethod(MethodInfo method, MethodInfo targetMethod)
		{
			return InstructionsCallsMethod(GetInstructions(method), targetMethod);
		}

		public static bool MethodCallsEitherMethods(MethodInfo method, MethodInfo[] targetMethods)
		{
			if (ReflectionHelper.IsCoroutineMethod(method))
			{
				return InstructionsCallsEitherMethods(GetCoroutineInstructions(method), targetMethods);
			}
			return InstructionsCallsEitherMethods(GetInstructions(method), targetMethods);
		}

		public static bool InstructionsCallsMethod(IEnumerable<Instruction> instructions, MethodInfo targetMethod)
		{
			return InstructionsCallsEitherMethods(instructions, new MethodInfo[1] { targetMethod });
		}

		public static bool InstructionsCallsEitherMethods(IEnumerable<Instruction> instructions, MethodInfo[] targetMethods)
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Invalid comparison between Unknown and I4
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Invalid comparison between Unknown and I4
			if (instructions == null || targetMethods == null || targetMethods.Length == 0)
			{
				return false;
			}
			foreach (Instruction instruction in instructions)
			{
				OpCode opCode = instruction.OpCode;
				if ((int)((OpCode)(ref opCode)).Code != 39)
				{
					opCode = instruction.OpCode;
					if ((int)((OpCode)(ref opCode)).Code != 110)
					{
						continue;
					}
				}
				object operand = instruction.Operand;
				MethodReference val = (MethodReference)((operand is MethodReference) ? operand : null);
				if (val == null)
				{
					continue;
				}
				try
				{
					MethodDefinition val2 = val.Resolve();
					if (val2 == null)
					{
						continue;
					}
					foreach (MethodInfo methodInfo in targetMethods)
					{
						if (!(methodInfo == null) && ((MemberReference)val2).Name == methodInfo.Name && ((MemberReference)val2.DeclaringType).FullName == methodInfo.DeclaringType.FullName)
						{
							return true;
						}
					}
				}
				catch (Exception arg)
				{
					Logger.LogWarning($"ILHelper: Error while processing IL instructions. {arg}");
				}
			}
			return false;
		}

		public static int FindArgLoadStart(List<CodeInstruction> instructions, MethodInfo method, int callIndex)
		{
			if (method == null)
			{
				return -1;
			}
			int num = method.GetParameters().Length;
			int num2 = 0;
			for (int num3 = callIndex - 1; num3 >= 0; num3--)
			{
				CodeInstruction val = instructions[num3];
				if (val.opcode.Name.StartsWith("ld"))
				{
					num2++;
					if (num2 == num)
					{
						return num3;
					}
				}
			}
			return callIndex;
		}
	}
	internal static class ReflectionHelper
	{
		public static object GetClassInstanceFromCaller(object caller)
		{
			if (caller == null)
			{
				return null;
			}
			Type type = caller.GetType();
			Type declaringType = type.DeclaringType;
			if (declaringType == null)
			{
				return caller;
			}
			Logger.LogDebug("ReflectionHelper: Analyzing caller type: " + type.FullName + ", parent type: " + declaringType.FullName);
			FieldInfo[] fields = type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			FieldInfo[] array = fields;
			foreach (FieldInfo fieldInfo in array)
			{
				object value = fieldInfo.GetValue(caller);
				if (value != null && declaringType.IsAssignableFrom(value.GetType()))
				{
					Logger.LogDebug("ReflectionHelper: Found parent instance of type " + value.GetType().FullName + " in field " + fieldInfo.Name);
					return value;
				}
				if (value != null && IsCompilerGeneratedClass(value.GetType()))
				{
					object classInstanceFromCaller = GetClassInstanceFromCaller(value);
					if (classInstanceFromCaller != null)
					{
						return classInstanceFromCaller;
					}
				}
			}
			Logger.LogDebug("ReflectionHelper: No parent instance found for " + type.FullName + ", returning original caller.");
			return caller;
		}

		private static bool IsCompilerGeneratedClass(Type type)
		{
			if (type.Name.Contains("<") && type.Name.Contains(">"))
			{
				return Attribute.IsDefined(type, typeof(CompilerGeneratedAttribute));
			}
			return false;
		}

		public static bool IsCoroutineMethod(MethodInfo method)
		{
			return method?.ReturnType == typeof(IEnumerator);
		}

		public static MethodInfo GetCoroutineMoveNextMethod(MethodInfo method)
		{
			return method?.DeclaringType.GetNestedTypes(BindingFlags.Instance | BindingFlags.NonPublic).FirstOrDefault((Type t) => t.Name.Contains("<" + method.Name + ">"))?.GetMethod("MoveNext", BindingFlags.Instance | BindingFlags.NonPublic);
		}
	}
}
namespace com.github.zehsteam.PlayerDamageTracker.Extensions
{
	internal static class HurtColliderExtensions
	{
		public static bool TryGetEnemyParent(this HurtCollider hurtCollider, out EnemyParent enemyParent)
		{
			if ((Object)(object)hurtCollider == (Object)null)
			{
				enemyParent = null;
				return false;
			}
			return ((Object)(object)hurtCollider).TryGetComponentInParents<EnemyParent>(out enemyParent);
		}

		public static bool TryGetPhysGrabObject(this HurtCollider hurtCollider, out PhysGrabObject physGrabObject)
		{
			if ((Object)(object)hurtCollider == (Object)null)
			{
				physGrabObject = null;
				return false;
			}
			return ((Object)(object)hurtCollider).TryGetComponentInParents<PhysGrabObject>(out physGrabObject);
		}

		public static bool TryGetExplosionMetadata(this HurtCollider hurtCollider, out Metadata metadata)
		{
			if ((Object)(object)hurtCollider == (Object)null)
			{
				metadata = null;
				return false;
			}
			return ParticleScriptExplosionPatch.Explosions.TryGetValue(hurtCollider, out metadata);
		}
	}
	internal static class ObjectExtensions
	{
		public static bool TryGetComponentInParent<T>(this Object obj, out T result) where T : Component
		{
			if (!TryGetTransform(obj, out var transform))
			{
				result = default(T);
				return false;
			}
			result = ((Component)transform).GetComponentInParent<T>();
			return (Object)(object)result != (Object)null;
		}

		public static T GetComponentInParents<T>(this Object obj) where T : Component
		{
			Transform val = GetTransform(obj);
			T result = default(T);
			while ((Object)(object)val != (Object)null)
			{
				if (((Component)val).TryGetComponent<T>(ref result))
				{
					return result;
				}
				val = val.parent;
			}
			return default(T);
		}

		public static bool TryGetComponentInParents<T>(this Object obj, out T result) where T : Component
		{
			result = obj.GetComponentInParents<T>();
			return (Object)(object)result != (Object)null;
		}

		public static string GetHierarchyPath(this Object obj)
		{
			if (!TryGetTransform(obj, out var transform))
			{
				return string.Empty;
			}
			return transform.GetHierarchyPath();
		}

		private static Transform GetTransform(Object obj)
		{
			Component val = (Component)(object)((obj is Component) ? obj : null);
			if (val == null)
			{
				GameObject val2 = (GameObject)(object)((obj is GameObject) ? obj : null);
				if (val2 != null)
				{
					return val2.transform;
				}
				return null;
			}
			return val.transform;
		}

		private static bool TryGetTransform(Object obj, out Transform transform)
		{
			transform = GetTransform(obj);
			return (Object)(object)transform != (Object)null;
		}
	}
	internal static class PlayerHealthExtensions
	{
		public static void HurtWithCaller(this PlayerHealth playerHealth, int damage, bool savingGrace, int enemyIndex, object caller)
		{
			if ((Object)(object)playerHealth == (Object)null)
			{
				return;
			}
			playerHealth.Hurt(damage, savingGrace, enemyIndex);
			if (damage <= 0 || caller == null)
			{
				return;
			}
			Logger.LogDebug($"PlayerHealthExtensions: HurtWithCaller() player: \"{SemiFunc.PlayerGetName(playerHealth.playerAvatar)}\", damage: {damage}, savingGrace: {savingGrace}, enemyIndex: {enemyIndex}, caller: \"{caller.GetType().FullName}\"");
			HurtCollider val = (HurtCollider)((caller is HurtCollider) ? caller : null);
			if (val != null)
			{
				HurtByHurtCollider(playerHealth, damage, savingGrace, enemyIndex, val);
				return;
			}
			Component val2 = (Component)((caller is Component) ? caller : null);
			Enemy enemy = default(Enemy);
			if (val2 != null && val2.TryGetComponent<Enemy>(ref enemy))
			{
				HurtByEnemy(playerHealth, damage, savingGrace, enemyIndex, enemy);
			}
			else
			{
				Logger.LogDebug("PlayerHealthExtensions: HurtWithCaller() Failed to identify caller.");
			}
		}

		private static void HurtByHurtCollider(PlayerHealth playerHealth, int damage, bool savingGrace, int enemyIndex, HurtCollider hurtCollider)
		{
			bool deadSet = playerHealth.playerAvatar.deadSet;
			PhysGrabObject physGrabObject;
			Metadata metadata;
			if (hurtCollider.TryGetEnemyParent(out var enemyParent))
			{
				Logger.LogDebug("PlayerHealthExtensions: HurtByHurtCollider() You were damaged by an enemy! \"" + enemyParent.enemyName + "\"");
				Events.InvokeOnDamagedByEnemy(enemyParent);
				if (deadSet)
				{
					Events.InvokeOnKilledByEnemy(enemyParent);
				}
			}
			else if (hurtCollider.TryGetPhysGrabObject(out physGrabObject))
			{
				Logger.LogDebug("PlayerHealthExtensions: HurtByHurtCollider() You were damaged by a PhysGrabObject! \"" + ((Object)physGrabObject).name + "\"");
				Events.InvokeOnDamagedByPhysGrabObject(physGrabObject);
				if (deadSet)
				{
					Events.InvokeOnKilledByPhysGrabObject(physGrabObject);
				}
			}
			else if (hurtCollider.TryGetExplosionMetadata(out metadata))
			{
				Logger.LogDebug("PlayerHealthExtensions: HurtByHurtCollider() You were damaged by an explosion!");
				Events.InvokeOnDamagedByExplosion(metadata);
				if (deadSet)
				{
					Events.InvokeOnKilledByExplosion(metadata);
				}
			}
			else
			{
				Logger.LogDebug("PlayerHealthExtensions: HurtByHurtCollider() You were damaged by something else. \"" + ((Object)(object)hurtCollider).GetHierarchyPath() + "\"");
				Events.InvokeOnDamagedByOther(hurtCollider);
				if (deadSet)
				{
					Events.InvokeOnKilledByOther(hurtCollider);
				}
			}
		}

		private static void HurtByEnemy(PlayerHealth playerHealth, int damage, bool savingGrace, int enemyIndex, Enemy enemy)
		{
			bool deadSet = playerHealth.playerAvatar.deadSet;
			EnemyParent enemyParent = enemy.EnemyParent;
			Logger.LogDebug("PlayerHealthExtensions: HurtByEnemy() You were damaged by an enemy! \"" + enemyParent.enemyName + "\"");
			Events.InvokeOnDamagedByEnemy(enemyParent);
			if (deadSet)
			{
				Events.InvokeOnKilledByEnemy(enemyParent);
			}
		}
	}
	public static class StringExtensions
	{
		public static bool EqualsAny(this string input, string[] values, StringComparison comparisonType = StringComparison.CurrentCulture)
		{
			if (input == null)
			{
				throw new ArgumentNullException("input");
			}
			if (values == null)
			{
				throw new ArgumentNullException("values");
			}
			foreach (string value in values)
			{
				if (input.Equals(value, comparisonType))
				{
					return true;
				}
			}
			return false;
		}

		public static bool ContainsAny(this string input, string[] values, StringComparison comparisonType = StringComparison.CurrentCulture)
		{
			if (input == null)
			{
				throw new ArgumentNullException("input");
			}
			if (values == null)
			{
				throw new ArgumentNullException("values");
			}
			foreach (string value in values)
			{
				if (input.Contains(value, comparisonType))
				{
					return true;
				}
			}
			return false;
		}

		public static bool StartsWithAny(this string input, string[] values, StringComparison comparisonType = StringComparison.CurrentCulture)
		{
			if (input == null)
			{
				throw new ArgumentNullException("input");
			}
			if (values == null)
			{
				throw new ArgumentNullException("values");
			}
			foreach (string value in values)
			{
				if (input.StartsWith(value, comparisonType))
				{
					return true;
				}
			}
			return false;
		}
	}
	internal static class TransformExtensions
	{
		public static string GetHierarchyPath(this Transform transform)
		{
			if ((Object)(object)transform.parent == (Object)null)
			{
				return ((Object)transform).name;
			}
			return transform.parent.GetHierarchyPath() + "/" + ((Object)transform).name;
		}
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		public IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
}

com.github.zehsteam.TwitchTrolling.dll

Decompiled a week ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using MenuLib;
using MenuLib.MonoBehaviors;
using MenuLib.Structs;
using Microsoft.CodeAnalysis;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Photon.Pun;
using REPOLib.Extensions;
using REPOLib.Modules;
using TMPro;
using TwitchChatAPI;
using TwitchChatAPI.Enums;
using TwitchChatAPI.Objects;
using UnityEngine;
using UnityEngine.AI;
using UnityEngine.Networking;
using UnityEngine.Serialization;
using UnityEngine.UI;
using com.github.zehsteam.MetadataUtils.Extensions;
using com.github.zehsteam.MetadataUtils.Objects;
using com.github.zehsteam.PlayerDamageTracker.Modules;
using com.github.zehsteam.TwitchTrolling.Dependencies;
using com.github.zehsteam.TwitchTrolling.Extensions;
using com.github.zehsteam.TwitchTrolling.Helpers;
using com.github.zehsteam.TwitchTrolling.MEvents;
using com.github.zehsteam.TwitchTrolling.MEvents.BaseEvents;
using com.github.zehsteam.TwitchTrolling.Managers;
using com.github.zehsteam.TwitchTrolling.MonoBehaviours;
using com.github.zehsteam.TwitchTrolling.Objects;
using com.github.zehsteam.TwitchTrolling.Patches;
using com.github.zehsteam.TwitchTrolling.Twitch;
using com.github.zehsteam.TwitchTrolling.Twitch.Commands;
using com.github.zehsteam.TwitchTrolling.Twitch.Commands.Objects;
using com.github.zehsteam.TwitchTrolling.Twitch.Helpers;
using com.github.zehsteam.TwitchTrolling.Twitch.Objects;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: IgnoresAccessChecksTo("REPOLib")]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("Zehs")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyCopyright("Copyright © 2025 Zehs")]
[assembly: AssemblyDescription("Let Twitch chat spawn monsters and trigger events with custom bit amounts and subs. Highly configurable, easy to use, no extension or app needed.")]
[assembly: AssemblyFileVersion("1.6.0.0")]
[assembly: AssemblyInformationalVersion("1.6.0+4b5bcb8df9a0bbbf787f384c0be7c0de7018a372")]
[assembly: AssemblyProduct("TwitchTrolling")]
[assembly: AssemblyTitle("com.github.zehsteam.TwitchTrolling")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.6.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.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 com.github.zehsteam.TwitchTrolling
{
	internal static class Assets
	{
		public static GameObject PluginManagerPrefab { get; private set; }

		public static GameObject PluginHUDPrefab { get; private set; }

		public static GameObject EnemyNametagWorldCanvasPrefab { get; private set; }

		public static GameObject TruckPropsPrefab { get; private set; }

		public static GameObject AudioEnemySpawnPrefab { get; private set; }

		public static PrefabRef ModCreditsPrefabRef { get; private set; }

		public static EnemyConfigEntryDefaultValuesList EnemyConfigEntryDefaultValuesList { get; private set; }

		public static EnemySpawnSFXList EnemySpawnSFXList { get; private set; }

		public static MEventSFXList MEventSFXList { get; private set; }

		public static void Load()
		{
			string directoryName = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
			string text = "twitchtrolling_assets";
			string text2 = Path.Combine(directoryName, text);
			if (!File.Exists(text2))
			{
				Logger.LogFatal("Failed to load assets. AssetBundle file could not be found at path \"" + text2 + "\". Make sure the \"" + text + "\" file is in the same folder as the mod's DLL file.");
			}
			else
			{
				AssetBundle val = AssetBundle.LoadFromFile(text2);
				if ((Object)(object)val == (Object)null)
				{
					Logger.LogFatal("Failed to load assets. AssetBundle is null.");
				}
				else
				{
					OnAssetBundleLoaded(val);
				}
			}
		}

		private static void OnAssetBundleLoaded(AssetBundle assetBundle)
		{
			PluginManagerPrefab = LoadAsset<GameObject>("PluginManager", assetBundle);
			PluginHUDPrefab = LoadAsset<GameObject>("PluginHUD", assetBundle);
			EnemyNametagWorldCanvasPrefab = LoadAsset<GameObject>("EnemyNametagWorldCanvas", assetBundle);
			TruckPropsPrefab = LoadAsset<GameObject>("TruckProps", assetBundle);
			AudioEnemySpawnPrefab = LoadAsset<GameObject>("AudioEnemySpawn", assetBundle);
			Utilities.FixAudioMixerGroups(AudioEnemySpawnPrefab);
			ModCreditsPrefabRef = NetworkPrefabs.RegisterNetworkPrefab(LoadAsset<GameObject>("TwitchTrolling ModCredits", assetBundle));
			EnemyConfigEntryDefaultValuesList = LoadAsset<EnemyConfigEntryDefaultValuesList>("EnemyConfigEntryDefaultValuesList", assetBundle);
			EnemySpawnSFXList = LoadAsset<EnemySpawnSFXList>("EnemySpawnSFXList", assetBundle);
			MEventSFXList = LoadAsset<MEventSFXList>("MEventSFXList", assetBundle);
		}

		private static T LoadAsset<T>(string name, AssetBundle assetBundle) where T : Object
		{
			if (string.IsNullOrWhiteSpace(name))
			{
				Logger.LogError("Failed to load asset of type \"" + typeof(T).Name + "\" from AssetBundle. Name is null or whitespace.");
				return default(T);
			}
			if ((Object)(object)assetBundle == (Object)null)
			{
				Logger.LogError("Failed to load asset of type \"" + typeof(T).Name + "\" with name \"" + name + "\" from AssetBundle. AssetBundle is null.");
				return default(T);
			}
			T val = assetBundle.LoadAsset<T>(name);
			if ((Object)(object)val == (Object)null)
			{
				Logger.LogError("Failed to load asset of type \"" + typeof(T).Name + "\" with name \"" + name + "\" from AssetBundle. No asset found with that type and name.");
				return default(T);
			}
			return val;
		}

		private static bool TryLoadAsset<T>(string name, AssetBundle assetBundle, out T asset) where T : Object
		{
			asset = LoadAsset<T>(name, assetBundle);
			return (Object)(object)asset != (Object)null;
		}
	}
	internal static class Logger
	{
		public static ManualLogSource ManualLogSource { get; private set; }

		public static void Initialize(ManualLogSource manualLogSource)
		{
			ManualLogSource = manualLogSource;
		}

		public static void LogDebug(object data)
		{
			Log((LogLevel)32, data);
		}

		public static void LogInfo(object data, bool extended = false)
		{
			Log((LogLevel)16, data, extended);
		}

		public static void LogWarning(object data, bool extended = false)
		{
			Log((LogLevel)4, data, extended);
		}

		public static void LogError(object data, bool extended = false, bool showMessage = false)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			Log((LogLevel)2, data, extended);
			if (showMessage)
			{
				MessageManager.Instance?.ShowMessage(data.ToString(), Color.red);
			}
		}

		public static void LogFatal(object data, bool extended = false)
		{
			Log((LogLevel)1, data, extended);
		}

		public static void Log(LogLevel logLevel, object data, bool extended = false)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			if (!extended || IsExtendedLoggingEnabled())
			{
				ManualLogSource manualLogSource = ManualLogSource;
				if (manualLogSource != null)
				{
					manualLogSource.Log(logLevel, data);
				}
			}
		}

		public static bool IsExtendedLoggingEnabled()
		{
			if (ConfigManager.ExtendedLogging == null)
			{
				return false;
			}
			return ConfigManager.ExtendedLogging.Value;
		}
	}
	internal static class Menu
	{
		[Serializable]
		[CompilerGenerated]
		private sealed class <>c
		{
			public static readonly <>c <>9 = new <>c();

			public static BuilderDelegate <>9__5_0;

			public static BuilderDelegate <>9__5_1;

			public static BuilderDelegate <>9__5_2;

			public static Action <>9__5_3;

			internal void <Initialize>b__5_0(Transform parent)
			{
				CreateMainButtonForMainMenu(parent);
			}

			internal void <Initialize>b__5_1(Transform parent)
			{
				CreateMainButtonForLobbyAndEscapeMenu(parent);
			}

			internal void <Initialize>b__5_2(Transform parent)
			{
				CreateMainButtonForLobbyAndEscapeMenu(parent);
			}

			internal void <Initialize>b__5_3()
			{
				PageManager.OnPageStatusChanged -= HandlePageStatusChanged;
				PageManager.OnPageCreated -= HandlePageCreated;
			}
		}

		private static REPOPopupPage _popupPage;

		private static REPOLabel _pageStatusLabel;

		private static REPOLabel _pageUrlLabel;

		private static REPOButton _createPageButton;

		private static REPOButton _copyPageURLButton;

		public static void Initialize()
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Expected O, but got Unknown
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Expected O, but got Unknown
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Expected O, but got Unknown
			object obj = <>c.<>9__5_0;
			if (obj == null)
			{
				BuilderDelegate val = delegate(Transform parent)
				{
					CreateMainButtonForMainMenu(parent);
				};
				<>c.<>9__5_0 = val;
				obj = (object)val;
			}
			MenuAPI.AddElementToMainMenu((BuilderDelegate)obj);
			object obj2 = <>c.<>9__5_1;
			if (obj2 == null)
			{
				BuilderDelegate val2 = delegate(Transform parent)
				{
					CreateMainButtonForLobbyAndEscapeMenu(parent);
				};
				<>c.<>9__5_1 = val2;
				obj2 = (object)val2;
			}
			MenuAPI.AddElementToLobbyMenu((BuilderDelegate)obj2);
			object obj3 = <>c.<>9__5_2;
			if (obj3 == null)
			{
				BuilderDelegate val3 = delegate(Transform parent)
				{
					CreateMainButtonForLobbyAndEscapeMenu(parent);
				};
				<>c.<>9__5_2 = val3;
				obj3 = (object)val3;
			}
			MenuAPI.AddElementToEscapeMenu((BuilderDelegate)obj3);
			PageManager.OnPageStatusChanged += HandlePageStatusChanged;
			PageManager.OnPageCreated += HandlePageCreated;
			Application.quitting += delegate
			{
				PageManager.OnPageStatusChanged -= HandlePageStatusChanged;
				PageManager.OnPageCreated -= HandlePageCreated;
			};
		}

		private static REPOButton CreateMainButtonForMainMenu(Transform parent)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			float num = 35f;
			float num2 = 0f;
			if (SpawnManagerProxy.Enabled)
			{
				num2 += 55f;
			}
			return CreateMainButton(parent, Vector2.op_Implicit(new Vector2(550f, num + num2)));
		}

		private static REPOButton CreateMainButtonForLobbyAndEscapeMenu(Transform parent)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			float num = 0f;
			num += 145f;
			if (MoreHeadProxy.Enabled)
			{
				num += 100f;
			}
			return CreateMainButton(parent, Vector2.op_Implicit(new Vector2(num, 0f)));
		}

		private static REPOButton CreateMainButton(Transform parent, Vector3 localPosition)
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			return MenuAPI.CreateREPOButton("Twitch Trolling", (Action)HandleMainButtonClick, parent, Vector2.op_Implicit(localPosition));
		}

		private static void CreateMenu()
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Expected O, but got Unknown
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Expected O, but got Unknown
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Expected O, but got Unknown
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Expected O, but got Unknown
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: Expected O, but got Unknown
			_popupPage = MenuAPI.CreateREPOPopupPage("Twitch Trolling", (PresetSide)0, false, true, 0f);
			REPOPopupPage popupPage = _popupPage;
			Padding maskPadding = _popupPage.maskPadding;
			maskPadding.top = 35f;
			popupPage.maskPadding = maskPadding;
			float xPosition = 75f;
			float yPosition = 270f;
			_popupPage.AddElement((BuilderDelegate)delegate(Transform parent)
			{
				//IL_0012: Unknown result type (might be due to invalid IL or missing references)
				//IL_002b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0035: Unknown result type (might be due to invalid IL or missing references)
				_pageStatusLabel = MenuAPI.CreateREPOLabel("Page Status:", parent, new Vector2(xPosition, yPosition));
				((Component)_pageStatusLabel).transform.localScale = Vector3.one * 0.7f;
			});
			yPosition -= 40f;
			_popupPage.AddElement((BuilderDelegate)delegate(Transform parent)
			{
				//IL_0012: Unknown result type (might be due to invalid IL or missing references)
				//IL_002b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0035: Unknown result type (might be due to invalid IL or missing references)
				_pageUrlLabel = MenuAPI.CreateREPOLabel(string.Empty, parent, new Vector2(xPosition, yPosition));
				((Component)_pageUrlLabel).transform.localScale = Vector3.one * 0.5f;
			});
			yPosition -= 60f;
			_popupPage.AddElement((BuilderDelegate)delegate(Transform parent)
			{
				//IL_002d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0032: Unknown result type (might be due to invalid IL or missing references)
				_createPageButton = MenuAPI.CreateREPOButton("Create Page", (Action)HandleCreatePageButtonClick, parent, Vector2.op_Implicit(new Vector3(xPosition, yPosition)));
			});
			_popupPage.AddElement((BuilderDelegate)delegate(Transform parent)
			{
				//IL_002d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0032: Unknown result type (might be due to invalid IL or missing references)
				_copyPageURLButton = MenuAPI.CreateREPOButton("Copy Page URL", (Action)HandleCopyPageURLButtonClick, parent, Vector2.op_Implicit(new Vector3(xPosition, yPosition)));
				((Component)_copyPageURLButton).gameObject.SetActive(false);
			});
			yPosition = 35f;
			_popupPage.AddElement((BuilderDelegate)delegate(Transform parent)
			{
				//IL_002d: Unknown result type (might be due to invalid IL or missing references)
				MenuAPI.CreateREPOButton("Close", (Action)HandleCloseButtonClick, parent, new Vector2(xPosition, yPosition));
			});
			_popupPage.OpenPage(false);
			HandlePageStatusChanged();
			PageManager.CheckPageStatus();
			PageManager.VerifyTwitchChannel();
		}

		private static void HandleMainButtonClick()
		{
			CreateMenu();
		}

		private static void HandleCloseButtonClick()
		{
			REPOPopupPage popupPage = _popupPage;
			if (popupPage != null)
			{
				popupPage.ClosePage(true);
			}
		}

		private static void HandleCreatePageButtonClick()
		{
			REPOButton createPageButton = _createPageButton;
			if (createPageButton != null)
			{
				((Component)createPageButton).gameObject.SetActive(false);
			}
			PageManager.CreatePage();
		}

		private static void HandleCopyPageURLButtonClick()
		{
			if (PageManager.HasPage)
			{
				GUIUtility.systemCopyBuffer = PageManager.PageURL;
			}
		}

		private static void HandlePageStatusChanged()
		{
			if ((Object)(object)_popupPage == (Object)null)
			{
				return;
			}
			bool hasPage = PageManager.HasPage;
			((Component)_createPageButton).gameObject.SetActive(!hasPage);
			((Component)_copyPageURLButton).gameObject.SetActive(hasPage);
			if (hasPage)
			{
				((TMP_Text)_pageStatusLabel.labelTMP).text = "Page Status: <color=#00FF00>ONLINE</color>";
				string text = PageManager.PageURL.Replace("?id", "\n?id");
				((TMP_Text)_pageUrlLabel.labelTMP).text = "<color=#FFFFFF>" + text + "</color>";
				return;
			}
			((TMP_Text)_pageStatusLabel.labelTMP).text = "Page Status: <color=#FF0000>OFFLINE</color>";
			if (!PageManager.IsCreatePageEnabled(out var reason))
			{
				string text2 = "<size=25><color=#FF0000>" + reason + "</color></size>";
				((TMP_Text)_pageUrlLabel.labelTMP).text = "You are unable to create a page! Reason:\n" + text2;
				((Component)_createPageButton).gameObject.SetActive(false);
			}
			else
			{
				((TMP_Text)_pageUrlLabel.labelTMP).text = "Create a page to share your prices\nwith your viewers!";
			}
		}

		private static void HandlePageCreated(string pageUrl)
		{
			HandlePageStatusChanged();
		}
	}
	[BepInPlugin("com.github.zehsteam.TwitchTrolling", "TwitchTrolling", "1.6.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	internal class Plugin : BaseUnityPlugin
	{
		private readonly Harmony _harmony = new Harmony("com.github.zehsteam.TwitchTrolling");

		internal static Plugin Instance { get; private set; }

		internal static JsonSave GlobalSave { get; private set; }

		internal static JsonSave LocalSave { get; private set; }

		private void Awake()
		{
			Instance = this;
			Logger.Initialize(Logger.CreateLogSource("com.github.zehsteam.TwitchTrolling"));
			Logger.LogInfo("TwitchTrolling has awoken!");
			_harmony.PatchAll(typeof(RunManagerPatch));
			_harmony.PatchAll(typeof(LevelGeneratorPatch));
			_harmony.PatchAll(typeof(EnemyDirectorPatch));
			_harmony.PatchAll(typeof(HUDCanvasPatch));
			_harmony.PatchAll(typeof(TruckScreenTextPatch));
			_harmony.PatchAll(typeof(PlayerControllerPatch));
			_harmony.PatchAll(typeof(ItemDronePatch));
			_harmony.PatchAll(typeof(FanTrapPatch));
			_harmony.PatchAll(typeof(ItemRubberDuckPatch));
			_harmony.PatchAll(typeof(EnemyDuckPatch));
			GlobalSave = new JsonSave(Utils.GetPluginPersistentDataPath(), "GlobalSave");
			LocalSave = new JsonSave(Paths.ConfigPath, "TwitchTrolling_Save.json");
			Assets.Load();
			ConfigManager.Initialize(((BaseUnityPlugin)this).Config);
			PluginManager.Spawn();
			TwitchIntegrationManager.Initialize();
			Menu.Initialize();
			PageManager.Initialize();
			PlayerHelper.Initialize();
			TwitchSimulateCheerCommand.Register();
			TwitchSimulateSubCommand.Register();
		}
	}
	internal static class Utils
	{
		[CompilerGenerated]
		private sealed class <InvokeAfterDurationCoroutine>d__5 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public TimeSpan duration;

			public Action action;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <InvokeAfterDurationCoroutine>d__5(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_0024: Unknown result type (might be due to invalid IL or missing references)
				//IL_002e: Expected O, but got Unknown
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<>2__current = (object)new WaitForSeconds((float)duration.TotalSeconds);
					<>1__state = 1;
					return true;
				case 1:
					<>1__state = -1;
					action?.Invoke();
					return false;
				}
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		public static string GetPluginPersistentDataPath()
		{
			return Path.Combine(Application.persistentDataPath, "TwitchTrolling");
		}

		public static ConfigFile CreateConfigFile(BaseUnityPlugin plugin, string path, string name = null, bool saveOnInit = false)
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Expected O, but got Unknown
			BepInPlugin metadata = MetadataHelper.GetMetadata((object)plugin);
			if (name == null)
			{
				name = metadata.GUID;
			}
			name += ".cfg";
			return new ConfigFile(Path.Combine(path, name), saveOnInit, metadata);
		}

		public static ConfigFile CreateLocalConfigFile(BaseUnityPlugin plugin, string name = null, bool saveOnInit = false)
		{
			return CreateConfigFile(plugin, Paths.ConfigPath, name, saveOnInit);
		}

		public static ConfigFile CreateGlobalConfigFile(BaseUnityPlugin plugin, string name = null, bool saveOnInit = false)
		{
			string pluginPersistentDataPath = GetPluginPersistentDataPath();
			if (name == null)
			{
				name = "global";
			}
			return CreateConfigFile(plugin, pluginPersistentDataPath, name, saveOnInit);
		}

		public static string GetTextWithReadableColor(string text, string hexColor, string backgroundHexColor = "#000000")
		{
			if (string.IsNullOrWhiteSpace(hexColor))
			{
				hexColor = "#FFFFFF";
			}
			if (string.IsNullOrWhiteSpace(backgroundHexColor))
			{
				backgroundHexColor = "#000000";
			}
			string readableColor = ColorHelper.GetReadableColor(hexColor, backgroundHexColor);
			return "<color=" + readableColor + ">" + text + "</color>";
		}

		[IteratorStateMachine(typeof(<InvokeAfterDurationCoroutine>d__5))]
		public static IEnumerator InvokeAfterDurationCoroutine(TimeSpan duration, Action action)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <InvokeAfterDurationCoroutine>d__5(0)
			{
				duration = duration,
				action = action
			};
		}
	}
	public static class MyPluginInfo
	{
		public const string PLUGIN_GUID = "com.github.zehsteam.TwitchTrolling";

		public const string PLUGIN_NAME = "TwitchTrolling";

		public const string PLUGIN_VERSION = "1.6.0";
	}
}
namespace com.github.zehsteam.TwitchTrolling.Twitch
{
	internal static class TwitchEventHandler
	{
		public static void Initialize()
		{
			try
			{
				API.OnMessage += HandleMessage;
				API.OnCheer += HandleCheer;
				API.OnSub += HandleSub;
				API.OnRaid += HandleRaid;
				Application.quitting += delegate
				{
					API.OnMessage -= HandleMessage;
					API.OnCheer -= HandleCheer;
					API.OnSub -= HandleSub;
					API.OnRaid -= HandleRaid;
				};
			}
			catch
			{
				Logger.LogFatal("TwitchEventHandler: Failed to initialize.");
				throw;
			}
		}

		public static void HandleMessage(TwitchMessage twitchMessage)
		{
		}

		public static void HandleCheer(TwitchCheerEvent cheerEvent)
		{
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			if (!TwitchIntegrationManager.IsCheerEventEnabled)
			{
				return;
			}
			if (cheerEvent == null)
			{
				Logger.LogError("TwitchEventHandler: Failed to handle cheer. TwitchCheerEvent is null.");
				return;
			}
			if (!CanHandleEvents())
			{
				ShowUnableToHandleEventsMessage();
				return;
			}
			if (!TwitchIntegrationManager.CanPlayEvents())
			{
				TwitchEventQueue.Enqueue(cheerEvent);
				return;
			}
			bool value = ConfigManager.Enemy_Enabled.Value;
			ViewerData viewerData = new ViewerData(((TwitchEvent)cheerEvent).User);
			int cheerAmount = cheerEvent.CheerAmount;
			int spawnCount = 1;
			int bitsUsed;
			if (value && EnemyConfigManager.HasEnemies() && EnemyConfigManager.TryGetConfigEntriesThatMatchBitsAmount(cheerAmount, out var list))
			{
				string targetEnemyName = string.Empty;
				if (list.TryGetRandom(out var enemyConfigEntry))
				{
					targetEnemyName = enemyConfigEntry.EnemyName;
				}
				bitsUsed = cheerAmount;
				SpawnEnemyFromBits(viewerData, bitsUsed, spawnCount, targetEnemyName);
				return;
			}
			if (MEventManager.Enabled && MEventManager.HasEvents())
			{
				float num = ConfigManager.Event_BitsForRandomEvent.Value;
				if (MEventManager.TryGetEvent(cheerAmount, out var mEvent))
				{
					mEvent.ExecuteEvent(viewerData, PlayerAvatar.instance, cheerAmount);
					return;
				}
				if (ConfigManager.Event_EnableBitsForRandomEvent.Value && (float)cheerAmount == num && MEventManager.TryGetRandomEvent(out mEvent))
				{
					mEvent.ExecuteEvent(viewerData, PlayerAvatar.instance, cheerAmount);
					return;
				}
			}
			bool value2 = ConfigManager.TwitchCheerEvent_EnableBitsForRandomEnemy.Value;
			if (!value || !value2 || !EnemyConfigManager.HasEnemies())
			{
				TwitchIntegrationManager.AddAccumulatedBits(viewerData, cheerAmount);
				return;
			}
			int accumulatedBits = TwitchIntegrationManager.GetAccumulatedBits(viewerData);
			cheerAmount += accumulatedBits;
			int value3 = ConfigManager.TwitchCheerEvent_BitsForRandomEnemy.Value;
			if (cheerAmount < value3)
			{
				TwitchIntegrationManager.SetAccumulatedBits(viewerData, cheerAmount);
				return;
			}
			spawnCount = Mathf.FloorToInt((float)(cheerAmount / value3));
			int num2 = cheerAmount % value3;
			bitsUsed = cheerAmount - num2;
			TwitchIntegrationManager.SetAccumulatedBits(viewerData, num2);
			SpawnEnemyFromBits(viewerData, bitsUsed, spawnCount, string.Empty);
		}

		public static void HandleSub(TwitchSubEvent subEvent)
		{
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Invalid comparison between Unknown and I4
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Invalid comparison between Unknown and I4
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Invalid comparison between Unknown and I4
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Invalid comparison between Unknown and I4
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			if (!TwitchIntegrationManager.IsSubEventEnabled || !ConfigManager.Enemy_Enabled.Value)
			{
				return;
			}
			if (subEvent == null)
			{
				Logger.LogError("Failed to handle sub. TwitchSubEvent is null.");
				return;
			}
			if (!CanHandleEvents())
			{
				ShowUnableToHandleEventsMessage();
				return;
			}
			if (!TwitchIntegrationManager.CanPlayEvents())
			{
				TwitchEventQueue.Enqueue(subEvent);
				return;
			}
			int num = 1;
			if ((int)subEvent.Type == 3)
			{
				num = subEvent.GiftCount;
			}
			string targetEnemyName = string.Empty;
			int num2 = 1;
			if (EnemyConfigManager.TryGetConfigEntriesThatMatchSubsAmount(num, out var list))
			{
				if (list.TryGetRandom(out var enemyConfigEntry))
				{
					targetEnemyName = enemyConfigEntry.EnemyName;
				}
			}
			else
			{
				num2 = num;
			}
			if ((int)subEvent.Tier < 2)
			{
				num2 *= ConfigManager.TwitchSubEvent_Tier1EnemySpawnCountMultiplier.Value;
			}
			else if ((int)subEvent.Tier == 2)
			{
				num2 *= ConfigManager.TwitchSubEvent_Tier2EnemySpawnCountMultiplier.Value;
			}
			else if ((int)subEvent.Tier == 3)
			{
				num2 *= ConfigManager.TwitchSubEvent_Tier3EnemySpawnCountMultiplier.Value;
			}
			ViewerSpawnData viewerSpawnData = new ViewerSpawnData(((TwitchEvent)subEvent).User, num2, GetSpawnReason(subEvent), targetEnemyName);
			Logger.LogInfo("HandleSub:\n" + JsonConvert.SerializeObject((object)viewerSpawnData, (Formatting)1), extended: true);
			EnemyManager.SpawnEnemy(viewerSpawnData);
		}

		public static void HandleRaid(TwitchRaidEvent raidEvent)
		{
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			if (TwitchIntegrationManager.IsRaidEventEnabled && ConfigManager.Enemy_Enabled.Value)
			{
				if (raidEvent == null)
				{
					Logger.LogError("TwitchEventHandler: Failed to handle raid. TwitchRaidEvent is null.");
					return;
				}
				if (!CanHandleEvents())
				{
					ShowUnableToHandleEventsMessage();
					return;
				}
				if (!TwitchIntegrationManager.CanPlayEvents())
				{
					TwitchEventQueue.Enqueue(raidEvent);
					return;
				}
				int value = ConfigManager.TwitchRaidEvent_ViewersPerRandomEnemy.Value;
				int value2 = ConfigManager.TwitchRaidEvent_MaxEnemySpawnCount.Value;
				int spawnCount = Mathf.Clamp(raidEvent.ViewerCount / value, 1, value2);
				string spawnReason = $"by raiding with {raidEvent.ViewerCount} viewers";
				ViewerSpawnData viewerSpawnData = new ViewerSpawnData(((TwitchEvent)raidEvent).User, spawnCount, spawnReason);
				Logger.LogInfo("HandleRaid:\n" + JsonConvert.SerializeObject((object)viewerSpawnData, (Formatting)1), extended: true);
				EnemyManager.SpawnEnemy(viewerSpawnData);
			}
		}

		private static string GetSpawnReason(TwitchSubEvent subEvent)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Invalid comparison between Unknown and I4
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Invalid comparison between Unknown and I4
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Expected I4, but got Unknown
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Invalid comparison between Unknown and I4
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Expected I4, but got Unknown
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Expected I4, but got Unknown
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Expected I4, but got Unknown
			if (subEvent == null)
			{
				return string.Empty;
			}
			string result = string.Empty;
			if ((int)subEvent.Type == 0)
			{
				result = (((int)subEvent.Tier != 0) ? $"by subbing at tier {(int)subEvent.Tier}" : "by subbing with prime");
			}
			else if ((int)subEvent.Type == 1)
			{
				result = (((int)subEvent.Tier != 0) ? $"by resubbing at tier {(int)subEvent.Tier} for {subEvent.CumulativeMonths} months" : $"by resubbing with prime for {subEvent.CumulativeMonths} months");
			}
			else if ((int)subEvent.Type == 2)
			{
				result = $"by gifting a tier {(int)subEvent.Tier} sub to {subEvent.RecipientUser}";
			}
			else if ((int)subEvent.Type == 3)
			{
				result = $"by gifting {subEvent.GiftCount} tier {(int)subEvent.Tier} subs";
			}
			return result;
		}

		private static void SpawnEnemyFromBits(ViewerData viewer, int bitsUsed, int spawnCount, string targetEnemyName)
		{
			string spawnReason = $"by cheering {bitsUsed} bits";
			ViewerSpawnData viewerSpawnData = new ViewerSpawnData(viewer, spawnCount, spawnReason, targetEnemyName);
			EnemyManager.SpawnEnemy(viewerSpawnData);
		}

		public static void ShowUnableToHandleEventsMessage()
		{
			MessageManager.Instance?.ShowMessage("<color=#FFFF00>Warning!</color> Triggering Twitch events is not currently supported on non-host clients\nDisable Twitch Chat API to hide these warnings");
		}

		public static bool CanHandleEvents()
		{
			if (!PhotonNetwork.InRoom)
			{
				return true;
			}
			return SemiFunc.IsMasterClientOrSingleplayer();
		}
	}
	internal static class TwitchEventQueue
	{
		[CompilerGenerated]
		private sealed class <PlayQueuedEventsCoroutine>d__17 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public TimeSpan initialDelay;

			private TimeSpan <delayBetweenEvents>5__2;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <PlayQueuedEventsCoroutine>d__17(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_0063: Unknown result type (might be due to invalid IL or missing references)
				//IL_006d: Expected O, but got Unknown
				//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
				//IL_0109: Expected O, but got Unknown
				//IL_0143: Unknown result type (might be due to invalid IL or missing references)
				//IL_014d: Expected O, but got Unknown
				//IL_0187: Unknown result type (might be due to invalid IL or missing references)
				//IL_0191: Expected O, but got Unknown
				TwitchCheerEvent result;
				TwitchSubEvent result2;
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					Logger.LogInfo("TwitchEventQueue: Started playing queued events.", extended: true);
					Logger.LogInfo($"TwitchEventQueue: Playing queued events after {(float)initialDelay.TotalSeconds} seconds.", extended: true);
					<>2__current = (object)new WaitForSeconds((float)initialDelay.TotalSeconds);
					<>1__state = 1;
					return true;
				case 1:
					<>1__state = -1;
					if (!TwitchEventHandler.CanHandleEvents())
					{
						return false;
					}
					if (!TwitchIntegrationManager.CanPlayEvents())
					{
						Logger.LogWarning("TwitchEventQueue: Failed to play queued events. You are not allowed to play events at this time.");
						return false;
					}
					if (!HasQueuedEvents())
					{
						Logger.LogInfo("TwitchEventQueue: No events in the queue to play.", extended: true);
						return false;
					}
					MessageManager.Instance?.ShowMessage("Playing Twitch events from the queue");
					<delayBetweenEvents>5__2 = TimeSpan.FromSeconds(0.5);
					goto IL_00d7;
				case 2:
					<>1__state = -1;
					goto IL_00d7;
				case 3:
					<>1__state = -1;
					goto IL_011b;
				case 4:
					{
						<>1__state = -1;
						break;
					}
					IL_00d7:
					if (TwitchIntegrationManager.IsCheerEventEnabled && CheerQueue.TryDequeue(out result))
					{
						TwitchEventHandler.HandleCheer(result);
						<>2__current = (object)new WaitForSeconds((float)<delayBetweenEvents>5__2.TotalSeconds);
						<>1__state = 2;
						return true;
					}
					goto IL_011b;
					IL_011b:
					if (TwitchIntegrationManager.IsSubEventEnabled && SubQueue.TryDequeue(out result2))
					{
						TwitchEventHandler.HandleSub(result2);
						<>2__current = (object)new WaitForSeconds((float)<delayBetweenEvents>5__2.TotalSeconds);
						<>1__state = 3;
						return true;
					}
					break;
				}
				if (TwitchIntegrationManager.IsRaidEventEnabled && RaidQueue.TryDequeue(out var result3))
				{
					TwitchEventHandler.HandleRaid(result3);
					<>2__current = (object)new WaitForSeconds((float)<delayBetweenEvents>5__2.TotalSeconds);
					<>1__state = 4;
					return true;
				}
				Logger.LogInfo("TwitchEventQueue: Finished plyaing queued events.", extended: true);
				SaveData();
				_playQueuedEventsCoroutine = null;
				return false;
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		private static Coroutine _playQueuedEventsCoroutine;

		public static Queue<TwitchCheerEvent> CheerQueue { get; private set; } = new Queue<TwitchCheerEvent>();


		public static Queue<TwitchSubEvent> SubQueue { get; private set; } = new Queue<TwitchSubEvent>();


		public static Queue<TwitchRaidEvent> RaidQueue { get; private set; } = new Queue<TwitchRaidEvent>();


		public static void LoadData()
		{
			Logger.LogInfo("TwitchEventQueue: Loading saved data...");
			try
			{
				if (Plugin.GlobalSave.TryLoad<string>("CheerQueue", out var value))
				{
					CheerQueue = JsonConvertHelper.DeserializeQueue<TwitchCheerEvent>(value);
					Logger.LogInfo("TwitchEventQueue: Loaded CheerQueue JSON data:\n\n" + value, extended: true);
				}
				if (Plugin.GlobalSave.TryLoad<string>("SubQueue", out value))
				{
					SubQueue = JsonConvertHelper.DeserializeQueue<TwitchSubEvent>(value);
					Logger.LogInfo("TwitchEventQueue: Loaded SubQueue JSON data:\n\n" + value, extended: true);
				}
				if (Plugin.GlobalSave.TryLoad<string>("RaidQueue", out value))
				{
					RaidQueue = JsonConvertHelper.DeserializeQueue<TwitchRaidEvent>(value);
					Logger.LogInfo("TwitchEventQueue: Loaded RaidQueue JSON data:\n\n" + value, extended: true);
				}
				Logger.LogInfo("TwitchEventQueue: Finished loading saved data.");
			}
			catch (Exception arg)
			{
				Logger.LogError($"TwitchEventQueue: Failed to load saved data. {arg}");
			}
		}

		public static void SaveData()
		{
			Logger.LogInfo("TwitchEventQueue: Saving data...", extended: true);
			try
			{
				Plugin.GlobalSave.Save("CheerQueue", JsonConvertHelper.SerializeQueue(CheerQueue));
				Plugin.GlobalSave.Save("SubQueue", JsonConvertHelper.SerializeQueue(SubQueue));
				Plugin.GlobalSave.Save("RaidQueue", JsonConvertHelper.SerializeQueue(RaidQueue));
				Logger.LogInfo("TwitchEventQueue: Saved data.", extended: true);
			}
			catch (Exception arg)
			{
				Logger.LogError($"TwitchEventQueue: Failed to save data. {arg}");
			}
		}

		public static void PlayQueuedEvents()
		{
			PlayQueuedEvents(TimeSpan.Zero);
		}

		public static void PlayQueuedEvents(TimeSpan initialDelay)
		{
			if (!TwitchIntegrationManager.IsEnabled)
			{
				Logger.LogWarning("TwitchEventQueue: Failed to play queued events. Twitch integration is not enabled.");
				return;
			}
			if ((Object)(object)PluginManager.Instance == (Object)null)
			{
				Logger.LogError("TwitchEventQueue: Failed to play queued events. PluginManager instance is null.");
				return;
			}
			if (!TwitchIntegrationManager.CanPlayEvents())
			{
				Logger.LogWarning("TwitchEventQueue: Failed to play queued events. You are not allowed to play events at this time.");
				return;
			}
			if (_playQueuedEventsCoroutine != null)
			{
				((MonoBehaviour)PluginManager.Instance).StopCoroutine(_playQueuedEventsCoroutine);
			}
			_playQueuedEventsCoroutine = ((MonoBehaviour)PluginManager.Instance).StartCoroutine(PlayQueuedEventsCoroutine(initialDelay));
		}

		[IteratorStateMachine(typeof(<PlayQueuedEventsCoroutine>d__17))]
		private static IEnumerator PlayQueuedEventsCoroutine(TimeSpan initialDelay)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <PlayQueuedEventsCoroutine>d__17(0)
			{
				initialDelay = initialDelay
			};
		}

		public static bool HasQueuedEvents()
		{
			if (CheerQueue.Count <= 0 && SubQueue.Count <= 0)
			{
				return RaidQueue.Count > 0;
			}
			return true;
		}

		public static void Enqueue(TwitchCheerEvent cheerEvent)
		{
			if (!CheerQueue.Contains(cheerEvent))
			{
				CheerQueue.Enqueue(cheerEvent);
				SaveData();
				ShowEnqueueMessage((TwitchEvent)(object)cheerEvent, "cheer");
			}
		}

		public static void Enqueue(TwitchSubEvent subEvent)
		{
			if (!SubQueue.Contains(subEvent))
			{
				SubQueue.Enqueue(subEvent);
				SaveData();
				ShowEnqueueMessage((TwitchEvent)(object)subEvent, "sub");
			}
		}

		public static void Enqueue(TwitchRaidEvent raidEvent)
		{
			if (!RaidQueue.Contains(raidEvent))
			{
				RaidQueue.Enqueue(raidEvent);
				SaveData();
				ShowEnqueueMessage((TwitchEvent)(object)raidEvent, "raid");
			}
		}

		private static void ShowEnqueueMessage(TwitchEvent twitchEvent, string eventName)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			string displayNameWithColor = twitchEvent.User.GetDisplayNameWithColor();
			string message = "Added Twitch " + eventName + " event from " + displayNameWithColor + " to queue";
			MessageManager.Instance?.ShowMessage(message);
		}
	}
	internal static class TwitchIntegrationManager
	{
		public static Dictionary<string, int> AccumulatedBits { get; private set; } = new Dictionary<string, int>();


		public static bool IsEnabled => ConfigManager.TwitchIntegration_Enabled.Value;

		public static bool IsCheerEventEnabled
		{
			get
			{
				if (IsEnabled)
				{
					return ConfigManager.TwitchCheerEvent_Enabled.Value;
				}
				return false;
			}
		}

		public static bool IsSubEventEnabled
		{
			get
			{
				if (IsEnabled)
				{
					return ConfigManager.TwitchSubEvent_Enabled.Value;
				}
				return false;
			}
		}

		public static bool IsRaidEventEnabled
		{
			get
			{
				if (IsEnabled)
				{
					return ConfigManager.TwitchRaidEvent_Enabled.Value;
				}
				return false;
			}
		}

		public static void Initialize()
		{
			LoadData();
			Application.quitting += SaveData;
			TwitchEventHandler.Initialize();
		}

		private static void LoadData()
		{
			Logger.LogInfo("TwitchIntegrationManager: Loading saved data...");
			try
			{
				TwitchEventQueue.LoadData();
				LoadAccumulatedBits();
				Logger.LogInfo("TwitchIntegrationManager: Finished loading saved data.");
			}
			catch (Exception arg)
			{
				Logger.LogError($"TwitchIntegrationManager: Failed to load saved data. {arg}");
			}
		}

		public static void SaveData()
		{
			Logger.LogInfo("TwitchIntegrationManager: Saving data...");
			try
			{
				TwitchEventQueue.SaveData();
				SaveAccumulatedBits();
				Logger.LogInfo("TwitchIntegrationManager: Saved data.");
			}
			catch (Exception arg)
			{
				Logger.LogError($"TwitchIntegrationManager: Failed to save data. {arg}");
			}
		}

		private static void LoadAccumulatedBits()
		{
			try
			{
				if (Plugin.GlobalSave.TryLoad<string>("AccumulatedBits", out var value))
				{
					AccumulatedBits = JsonConvert.DeserializeObject<Dictionary<string, int>>(value);
					Logger.LogInfo("TwitchIntegrationManager: Loaded AccumulatedBits JSON data:\n\n" + value, extended: true);
				}
			}
			catch (Exception arg)
			{
				Logger.LogError($"TwitchIntegrationManager: Failed to load AccumulatedBits from saved data. {arg}");
			}
		}

		public static void SaveAccumulatedBits()
		{
			Plugin.GlobalSave.Save("AccumulatedBits", JsonConvert.SerializeObject((object)AccumulatedBits));
		}

		public static int GetAccumulatedBits(ViewerData viewer)
		{
			if (viewer == null)
			{
				return 0;
			}
			return GetAccumulatedBits(viewer.Username);
		}

		public static int GetAccumulatedBits(string username)
		{
			return AccumulatedBits.GetValueOrDefault(username.ToLower(), 0);
		}

		public static void SetAccumulatedBits(ViewerData viewer, int value)
		{
			if (viewer != null)
			{
				if (value <= 0)
				{
					AccumulatedBits.Remove(viewer.Username);
				}
				else
				{
					AccumulatedBits[viewer.Username] = value;
				}
				SaveAccumulatedBits();
			}
		}

		public static void AddAccumulatedBits(ViewerData viewer, int value)
		{
			int accumulatedBits = GetAccumulatedBits(viewer);
			SetAccumulatedBits(viewer, accumulatedBits + value);
		}

		public static bool CanPlayEvents()
		{
			if (!IsEnabled)
			{
				return false;
			}
			return EnemyManager.CanSpawnEnemies();
		}
	}
}
namespace com.github.zehsteam.TwitchTrolling.Twitch.Objects
{
	[Serializable]
	public class ViewerData
	{
		public string UserId { get; }

		public string Username => DisplayName.ToLower();

		public string DisplayName { get; }

		public string Color { get; }

		public ViewerData(string userId, string displayName, string color)
		{
			UserId = userId;
			DisplayName = displayName;
			Color = color;
		}

		public ViewerData(TwitchUser twitchUser)
		{
			UserId = ((TwitchUser)(ref twitchUser)).UserId;
			DisplayName = ((TwitchUser)(ref twitchUser)).DisplayName;
			Color = ((TwitchUser)(ref twitchUser)).Color;
		}

		public string GetDisplayNameWithColor()
		{
			return Utils.GetTextWithReadableColor(DisplayName, Color);
		}
	}
	[Serializable]
	public class ViewerSpawnData
	{
		public ViewerData Viewer { get; private set; }

		public int SpawnCount { get; private set; }

		public string SpawnReason { get; private set; }

		public string TargetEnemyName { get; private set; }

		public int TotalSpawnCount { get; private set; }

		public ViewerSpawnData(ViewerData viewer, int spawnCount, string spawnReason, string targetEnemyName = "")
		{
			Viewer = viewer;
			SpawnCount = spawnCount;
			SpawnReason = spawnReason;
			TargetEnemyName = targetEnemyName;
		}

		public ViewerSpawnData(TwitchUser twitchUser, int spawnCount, string spawnReason, string targetEnemyName = "")
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			Viewer = new ViewerData(twitchUser);
			SpawnCount = spawnCount;
			SpawnReason = spawnReason;
			TargetEnemyName = targetEnemyName;
		}

		public void SetTargetEnemyName(string value)
		{
			TargetEnemyName = value;
		}

		public void SetTotalSpawnCount(int value)
		{
			TotalSpawnCount = value;
		}
	}
}
namespace com.github.zehsteam.TwitchTrolling.Twitch.Helpers
{
	internal static class TwitchHelper
	{
		public static TwitchUser CreateTwitchUser(bool isVIP = false, bool isSubscriber = false, bool isModerator = false, bool isBroadcaster = false)
		{
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			if (PlayerHelper.TryGetLocalPlayer(out var playerAvatar))
			{
				string steamID = playerAvatar.steamID;
				string displayName = SemiFunc.PlayerGetName(playerAvatar);
				string color = ColorHelper.ColorToHex(SemiFunc.PlayerGetColorFromSteamID(steamID));
				return CreateTwitchUser(steamID, displayName, color, isVIP, isSubscriber, isModerator, isBroadcaster);
			}
			return CreateTwitchUser("0", "Unknown", "#FFFFFF", isVIP, isSubscriber, isModerator, isBroadcaster);
		}

		public static TwitchUser CreateTwitchUser(string userId, string displayName, string color = "#FFFFFF", bool isVIP = false, bool isSubscriber = false, bool isModerator = false, bool isBroadcaster = false)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			TwitchUser result = default(TwitchUser);
			((TwitchUser)(ref result)).UserId = userId;
			((TwitchUser)(ref result)).Username = displayName.ToLower();
			((TwitchUser)(ref result)).DisplayName = displayName;
			((TwitchUser)(ref result)).Color = color;
			((TwitchUser)(ref result)).IsVIP = isVIP;
			((TwitchUser)(ref result)).IsSubscriber = isSubscriber;
			((TwitchUser)(ref result)).IsModerator = isModerator;
			((TwitchUser)(ref result)).IsBroadcaster = isBroadcaster;
			return result;
		}
	}
}
namespace com.github.zehsteam.TwitchTrolling.Twitch.Commands
{
	internal static class TwitchSimulateCheerCommand
	{
		public static void Register()
		{
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Expected O, but got Unknown
			ChatCommand val = new ChatCommand("cheer", "Simulate a Twitch cheer for TwitchTrolling", (Action<bool, string[]>)Execute, (Func<bool, string, string[], List<string>>)Suggest, (Func<bool>)IsEnabled, false);
			Commands.RegisterCommand(val);
		}

		private static void Execute(bool isDebugConsole, string[] args)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Expected O, but got Unknown
			int cheerAmount = ConfigManager.TwitchCheerEvent_BitsForRandomEnemy.Value;
			if (args.Length >= 1 && int.TryParse(args[0], out var result))
			{
				cheerAmount = result;
			}
			TwitchCheerEvent cheerEvent = new TwitchCheerEvent
			{
				User = TwitchHelper.CreateTwitchUser(),
				CheerAmount = cheerAmount
			};
			TwitchEventHandler.HandleCheer(cheerEvent);
			DebugCommandHandler instance = DebugCommandHandler.instance;
			if (instance != null)
			{
				instance.CommandSuccessEffect();
			}
		}

		private static List<string> Suggest(bool isDebugConsole, string partial, string[] args)
		{
			List<SuggestEntry> list = new List<SuggestEntry>();
			List<CombinedSuggestEntry> list2 = new List<CombinedSuggestEntry>();
			foreach (EnemyConfigEntry enabledConfigEntry in EnemyConfigManager.EnabledConfigEntries)
			{
				list.Add(new SuggestEntry(enabledConfigEntry.EnemyName, enabledConfigEntry.BitsToSpawn.Value));
			}
			foreach (MEvent enabledEvent in MEventManager.EnabledEvents)
			{
				list.Add(new SuggestEntry(enabledEvent.Name, enabledEvent.BitsPrice.Value));
			}
			foreach (SuggestEntry item in list)
			{
				int price = item.Price;
				string name = item.Name;
				bool flag = true;
				foreach (CombinedSuggestEntry item2 in list2)
				{
					if (item2.Price == price)
					{
						item2.Names.Add(name);
						flag = false;
						break;
					}
				}
				if (flag)
				{
					list2.Add(new CombinedSuggestEntry(name, price));
				}
			}
			List<string> list3 = (from x in list2
				where x.Matches(args)
				orderby x.Price
				select x.GetText()).ToList();
			if (ConfigManager.Event_EnableBitsForRandomEvent.Value)
			{
				CombinedSuggestEntry combinedSuggestEntry = new CombinedSuggestEntry("RANDOM EVENT", ConfigManager.Event_BitsForRandomEvent.Value);
				if (combinedSuggestEntry.Matches(args))
				{
					list3.Insert(0, combinedSuggestEntry.GetText());
				}
			}
			if (ConfigManager.TwitchCheerEvent_EnableBitsForRandomEnemy.Value)
			{
				CombinedSuggestEntry combinedSuggestEntry2 = new CombinedSuggestEntry("RANDOM ENEMY", ConfigManager.TwitchCheerEvent_BitsForRandomEnemy.Value);
				if (combinedSuggestEntry2.Matches(args))
				{
					list3.Insert(0, combinedSuggestEntry2.GetText());
				}
			}
			return list3;
		}

		private static bool IsEnabled()
		{
			if (SemiFunc.IsSplashScreen() || SemiFunc.IsMainMenu())
			{
				return false;
			}
			if (SemiFunc.RunIsLobbyMenu())
			{
				return false;
			}
			if (SemiFunc.RunIsTutorial())
			{
				return false;
			}
			if (!SemiFunc.IsMasterClientOrSingleplayer())
			{
				return false;
			}
			return true;
		}
	}
	internal static class TwitchSimulateSubCommand
	{
		public static void Register()
		{
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Expected O, but got Unknown
			ChatCommand val = new ChatCommand("sub", "Simulate a Twitch sub or gift subs for TwitchTrolling", (Action<bool, string[]>)Execute, (Func<bool, string, string[], List<string>>)Suggest, (Func<bool>)IsEnabled, false);
			Commands.RegisterCommand(val);
		}

		private static void Execute(bool isDebugConsole, string[] args)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Expected O, but got Unknown
			int giftCount = 1;
			if (args.Length != 0 && int.TryParse(args[0], out var result))
			{
				giftCount = result;
			}
			TwitchSubEvent subEvent = new TwitchSubEvent
			{
				User = TwitchHelper.CreateTwitchUser(),
				Type = (SubType)3,
				Tier = (SubTier)1,
				GiftCount = giftCount
			};
			TwitchEventHandler.HandleSub(subEvent);
			DebugCommandHandler instance = DebugCommandHandler.instance;
			if (instance != null)
			{
				instance.CommandSuccessEffect();
			}
		}

		private static List<string> Suggest(bool isDebugConsole, string partial, string[] args)
		{
			List<SuggestEntry> list = new List<SuggestEntry>();
			List<CombinedSuggestEntry> list2 = new List<CombinedSuggestEntry>();
			foreach (EnemyConfigEntry enabledConfigEntry in EnemyConfigManager.EnabledConfigEntries)
			{
				list.Add(new SuggestEntry(enabledConfigEntry.EnemyName, enabledConfigEntry.SubsToSpawn.Value));
			}
			foreach (SuggestEntry item in list)
			{
				int price = item.Price;
				string name = item.Name;
				bool flag = true;
				foreach (CombinedSuggestEntry item2 in list2)
				{
					if (item2.Price == price)
					{
						item2.Names.Add(name);
						flag = false;
						break;
					}
				}
				if (flag)
				{
					list2.Add(new CombinedSuggestEntry(name, price));
				}
			}
			return (from x in list2
				where x.Matches(args)
				orderby x.Price
				select x.GetText()).ToList();
		}

		private static bool IsEnabled()
		{
			if (SemiFunc.IsSplashScreen() || SemiFunc.IsMainMenu())
			{
				return false;
			}
			if (SemiFunc.RunIsLobbyMenu())
			{
				return false;
			}
			if (SemiFunc.RunIsTutorial())
			{
				return false;
			}
			if (!SemiFunc.IsMasterClientOrSingleplayer())
			{
				return false;
			}
			return true;
		}
	}
}
namespace com.github.zehsteam.TwitchTrolling.Twitch.Commands.Objects
{
	internal class CombinedSuggestEntry
	{
		public List<string> Names = new List<string>();

		public int Price;

		public CombinedSuggestEntry(string name, int price)
		{
			Names = new List<string>(1) { name };
			Price = price;
		}

		public string GetText()
		{
			return $"{Price} - {GetNames()}";
		}

		public string GetNames()
		{
			if (Names.Count == 1)
			{
				return Names[0];
			}
			string text = string.Empty;
			int num = 60;
			int num2 = Names.Count;
			for (int i = 0; i < Names.Count; i++)
			{
				string text2 = string.Empty;
				if (i > 0)
				{
					text2 += ", ";
				}
				text2 += Names[i];
				if ((text + text2).Length > num)
				{
					break;
				}
				text += text2;
				num2--;
			}
			if (num2 > 0)
			{
				text = text.Substring(0, Math.Min(text.Length, num));
				text += $"... +{num2}";
			}
			return text;
		}

		public bool Matches(string[] args)
		{
			string value = string.Join(" ", args);
			if (Price.ToString().StartsWith(value))
			{
				return true;
			}
			if (Names.Any((string x) => x.Contains(value, StringComparison.OrdinalIgnoreCase)))
			{
				return true;
			}
			if (value.StartsWith(Price.ToString(), StringComparison.OrdinalIgnoreCase) && GetText().StartsWith(value, StringComparison.OrdinalIgnoreCase))
			{
				return true;
			}
			return false;
		}
	}
	internal struct SuggestEntry
	{
		public string Name { get; set; }

		public int Price { get; set; }

		public SuggestEntry(string name, int price)
		{
			Name = name;
			Price = price;
		}
	}
}
namespace com.github.zehsteam.TwitchTrolling.Patches
{
	[HarmonyPatch(typeof(EnemyDirector))]
	internal static class EnemyDirectorPatch
	{
		private static bool _patchedStart;

		[HarmonyPatch("Start")]
		[HarmonyPostfix]
		private static void StartPatch()
		{
			if (!_patchedStart)
			{
				_patchedStart = true;
				EnemyConfigManager.Initialize();
				PageManager.UpdatePageFirstTime();
			}
		}
	}
	[HarmonyPatch(typeof(EnemyDuck))]
	internal static class EnemyDuckPatch
	{
		public static List<EnemyDuck> DucksToBypassStunAggroOnce = new List<EnemyDuck>();

		public static void Reset()
		{
			DucksToBypassStunAggroOnce = new List<EnemyDuck>();
		}

		[HarmonyPatch("StateStun")]
		[HarmonyTranspiler]
		private static IEnumerable<CodeInstruction> StateStunTranspiler(IEnumerable<CodeInstruction> instructions)
		{
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Expected O, but got Unknown
			string text = "EnemyDuckPatch: [StateStun Transpiler]";
			MethodInfo methodInfo = AccessTools.Method(typeof(EnemyDuck), "UpdateState", (Type[])null, (Type[])null);
			MethodInfo methodInfo2 = AccessTools.Method(typeof(EnemyDuckPatch), "StateStun_UpdateState", (Type[])null, (Type[])null);
			if (methodInfo == null || methodInfo2 == null)
			{
				Logger.LogError(text + " Failed to create transpiler. Required methods not found.");
				return instructions;
			}
			List<CodeInstruction> list = new List<CodeInstruction>();
			foreach (CodeInstruction instruction in instructions)
			{
				if (CodeInstructionExtensions.Calls(instruction, methodInfo))
				{
					list.Add(new CodeInstruction(OpCodes.Call, (object)methodInfo2));
					Logger.LogInfo(text + " Replaced " + methodInfo.Name + " call with " + methodInfo2.Name + ".", extended: true);
				}
				else
				{
					list.Add(instruction);
				}
			}
			return list.AsEnumerable();
		}

		private static void StateStun_UpdateState(EnemyDuck enemyDuck, State state)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Invalid comparison between Unknown and I4
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			if ((int)state == 11 && DucksToBypassStunAggroOnce.Contains(enemyDuck))
			{
				DucksToBypassStunAggroOnce.Remove(enemyDuck);
				enemyDuck.UpdateState((State)1);
			}
			else
			{
				enemyDuck.UpdateState(state);
			}
		}
	}
	[HarmonyPatch(typeof(FanTrap))]
	internal static class FanTrapPatch
	{
		public static List<FanTrap> FansToBypassIdle = new List<FanTrap>();

		[HarmonyPatch("SetState")]
		[HarmonyPrefix]
		private static bool SetStatePatch(FanTrap __instance, States state)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			if ((int)state != 0)
			{
				return true;
			}
			if (FansToBypassIdle.Contains(__instance))
			{
				return false;
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(HUDCanvas))]
	internal static class HUDCanvasPatch
	{
		[HarmonyPatch("Awake")]
		[HarmonyPostfix]
		private static void AwakePatch(HUDCanvas __instance)
		{
			Transform parent = ((Component)__instance).transform.Find("HUD");
			PluginHUD.Spawn(parent);
		}
	}
	[HarmonyPatch(typeof(ItemDrone))]
	internal static class ItemDronePatch
	{
		public static List<PhysGrabObject> IgnorePhysGrabObjects = new List<PhysGrabObject>();

		[HarmonyPatch("NewRayHitPointLogic")]
		[HarmonyPrefix]
		private static bool NewRayHitPointLogicPatch(ItemDrone __instance, int photonViewId, Transform newMagnetTarget)
		{
			PhysGrabObject physGrabObject = ((!((Object)(object)newMagnetTarget != (Object)null)) ? ((Component)PhotonView.Find(photonViewId)).gameObject.GetComponent<PhysGrabObject>() : ((Component)newMagnetTarget).GetComponent<PhysGrabObject>());
			return CanAttachToPhysGrabObject(__instance, physGrabObject);
		}

		[HarmonyPatch("GetHighestParentWithRigidbody")]
		[HarmonyPostfix]
		private static void GetHighestParentWithRigidbodyPatch(ItemDrone __instance, ref Transform __result)
		{
			PhysGrabObject physGrabObject = default(PhysGrabObject);
			if (!((Object)(object)__result == (Object)null) && ((Component)__result).TryGetComponent<PhysGrabObject>(ref physGrabObject) && !CanAttachToPhysGrabObject(__instance, physGrabObject))
			{
				__result = null;
			}
		}

		private static bool CanAttachToPhysGrabObject(ItemDrone itemDrone, PhysGrabObject physGrabObject)
		{
			if ((Object)(object)itemDrone == (Object)null || (Object)(object)physGrabObject == (Object)null)
			{
				return true;
			}
			if (IsSameDroneType(itemDrone, physGrabObject))
			{
				return false;
			}
			if (IgnorePhysGrabObjects.Contains(physGrabObject))
			{
				return false;
			}
			return true;
		}

		private static bool IsSameDroneType(ItemDrone itemDrone, PhysGrabObject physGrabObject)
		{
			if ((Object)(object)itemDrone == (Object)null || (Object)(object)physGrabObject == (Object)null)
			{
				return false;
			}
			ItemAttributes val = default(ItemAttributes);
			if (!((Component)physGrabObject).TryGetComponent<ItemAttributes>(ref val))
			{
				return false;
			}
			return itemDrone.itemAttributes.itemName == val.itemName;
		}
	}
	[HarmonyPatch(typeof(ItemRubberDuck))]
	internal static class ItemRubberDuckPatch
	{
		public static List<ItemRubberDuck> SpecialRubberDucks = new List<ItemRubberDuck>();

		[HarmonyPatch("Quack")]
		[HarmonyPostfix]
		private static void QuackPatch(ItemRubberDuck __instance)
		{
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			if (SpecialRubberDucks.Contains(__instance) && SemiFunc.IsMasterClientOrSingleplayer() && !(__instance.itemBattery.batteryLife <= 0f) && !__instance.physGrabObject.grabbed)
			{
				Vector3 velocity = __instance.rb.velocity;
				if (((Vector3)(ref velocity)).magnitude >= 20f)
				{
					Rigidbody rb = __instance.rb;
					rb.velocity *= 5f;
					__instance.rb.AddTorque(Random.insideUnitSphere * 40f);
				}
			}
		}
	}
	[HarmonyPatch(typeof(LevelGenerator))]
	internal static class LevelGeneratorPatch
	{
		[HarmonyPatch("EnemySetup")]
		[HarmonyPostfix]
		private static void EnemySetupPatch()
		{
			EnemyManager.ResetViewerEnemies();
			EnemyDuckPatch.Reset();
			if (TwitchIntegrationManager.CanPlayEvents())
			{
				TwitchEventQueue.PlayQueuedEvents(TimeSpan.FromSeconds(10.0));
			}
		}
	}
	[HarmonyPatch(typeof(PlayerController))]
	internal static class PlayerControllerPatch
	{
		private static bool _usingCustomSpeed;

		private static float _timeCustomSpeedEnd = float.NegativeInfinity;

		private static bool _usingCustomGravity;

		private static float _timeCustomGravityEnd = float.NegativeInfinity;

		[HarmonyPatch("Update")]
		[HarmonyPostfix]
		private static void UpdatePatch()
		{
			if (_usingCustomSpeed && !IsSpeedOverwritten())
			{
				_usingCustomSpeed = false;
				ResetSpeed();
			}
			if (_usingCustomGravity && !IsGravityOverwritten())
			{
				_usingCustomGravity = false;
				ResetGravity();
			}
		}

		public static void OverrideSpeed(float value, TimeSpan duration)
		{
			if (!((Object)(object)PlayerController.instance == (Object)null))
			{
				_usingCustomSpeed = true;
				SetSpeed(value);
				_timeCustomSpeedEnd = Time.realtimeSinceStartup + (float)duration.TotalSeconds;
			}
		}

		private static bool IsSpeedOverwritten()
		{
			return Time.realtimeSinceStartup < _timeCustomSpeedEnd;
		}

		private static void SetSpeed(float value)
		{
			if (!((Object)(object)PlayerController.instance == (Object)null))
			{
				value += 5f;
				PlayerController.instance.CrouchSpeed = value;
				PlayerController.instance.MoveSpeed = value;
				PlayerController.instance.SprintSpeed = value;
			}
		}

		private static void ResetSpeed()
		{
			if (!((Object)(object)PlayerAvatar.instance == (Object)null) && !((Object)(object)StatsManager.instance == (Object)null))
			{
				PlayerController.instance.OverrideSpeed(1f, 0.1f);
				MessageManager.Instance?.ShowMessage("Your speed has been reset");
			}
		}

		public static void OverrideGravity(float value, TimeSpan duration)
		{
			if (!((Object)(object)PlayerController.instance == (Object)null))
			{
				_usingCustomGravity = true;
				SetGravity(value);
				_timeCustomGravityEnd = Time.realtimeSinceStartup + (float)duration.TotalSeconds;
			}
		}

		private static bool IsGravityOverwritten()
		{
			return Time.realtimeSinceStartup < _timeCustomGravityEnd;
		}

		private static void SetGravity(float value)
		{
			if (!((Object)(object)PlayerController.instance == (Object)null))
			{
				PlayerController.instance.CustomGravity = value;
			}
		}

		private static void ResetGravity()
		{
			if (!((Object)(object)PlayerAvatar.instance == (Object)null) && !((Object)(object)StatsManager.instance == (Object)null))
			{
				PlayerController.instance.CustomGravity = PlayerController.instance.playerOriginalCustomGravity;
			}
		}
	}
	[HarmonyPatch(typeof(RunManager))]
	internal static class RunManagerPatch
	{
		private static bool _patchedAwake;

		[HarmonyPatch("Awake")]
		[HarmonyPostfix]
		private static void AwakePatch(RunManager __instance)
		{
			if (!_patchedAwake)
			{
				_patchedAwake = true;
				MEventManager.Initialize();
			}
		}
	}
	[HarmonyPatch(typeof(TruckScreenText))]
	internal static class TruckScreenTextPatch
	{
		[HarmonyPatch("Start")]
		[HarmonyPostfix]
		private static void StartPatch()
		{
			SpawnTruckProps();
		}

		private static void SpawnTruckProps()
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			if (TryGetTruckMeshTransform(out var transform))
			{
				GameObject val = Object.Instantiate<GameObject>(Assets.TruckPropsPrefab);
				val.transform.SetParent(transform);
				val.transform.SetLocalPositionAndRotation(Vector3.zero, Quaternion.identity);
				Logger.LogInfo("TruckScreenTextPatch: Spawned truck props.", extended: true);
			}
		}

		private static bool TryGetTruckMeshTransform(out Transform transform)
		{
			transform = null;
			if ((Object)(object)TruckScreenText.instance == (Object)null)
			{
				Logger.LogInfo("TruckScreenTextPatch: Failed to get truck mesh transform. TruckScreenText instance is null.");
				return false;
			}
			try
			{
				transform = ((Component)TruckScreenText.instance).transform.parent.Find("Mesh");
				return true;
			}
			catch (Exception arg)
			{
				Logger.LogInfo($"TruckScreenTextPatch: Failed to get truck mesh transform. {arg}");
				return false;
			}
		}
	}
}
namespace com.github.zehsteam.TwitchTrolling.Objects
{
	[Serializable]
	public class AudioPlayerFactory
	{
		public enum AudioUseMode
		{
			Single,
			Reuse
		}

		private static Dictionary<AudioPlayerType, Queue<AudioPlayer>> _audioPlayerPool = new Dictionary<AudioPlayerType, Queue<AudioPlayer>>();

		public AudioPlayer AudioPlayer;

		public AudioPlayerType Type;

		public AudioUseMode UseMode;

		public float Volume = 1f;

		public float MaxDistance = 15f;

		public bool IsPlaying => AudioPlayer?.IsPlaying ?? false;

		public float Play(AudioClip audioClip, Vector3 position, bool loop = false)
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			AssignAudioPlayer();
			if (UseMode != AudioUseMode.Reuse)
			{
				loop = false;
			}
			return AudioPlayer?.Play(audioClip, position, Volume, MaxDistance, loop) ?? 0f;
		}

		public float Play(AudioClip audioClip, Transform transform, bool loop = false)
		{
			AssignAudioPlayer();
			if (UseMode != AudioUseMode.Reuse)
			{
				loop = false;
			}
			return AudioPlayer?.Play(audioClip, transform, Volume, MaxDistance, loop) ?? 0f;
		}

		public void Stop()
		{
			AudioPlayer?.Stop();
		}

		public void SetTargetTransform(Transform targetTransform)
		{
			AudioPlayer?.SetTargetTransform(targetTransform);
		}

		public void SetTargetPosition(Vector3 targetPosition)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			AudioPlayer?.SetTargetPosition(targetPosition);
		}

		private void AssignAudioPlayer()
		{
			if (UseMode == AudioUseMode.Single)
			{
				AudioPlayer = GetAudioPlayer();
			}
			else if (UseMode == AudioUseMode.Reuse)
			{
				if ((Object)(object)AudioPlayer == (Object)null || (Object)(object)((Component)AudioPlayer).gameObject == (Object)null)
				{
					AudioPlayer = GetAudioPlayer();
				}
				if (!((Object)(object)AudioPlayer == (Object)null) && !((Component)AudioPlayer).gameObject.activeSelf)
				{
					((Component)AudioPlayer).gameObject.SetActive(true);
				}
			}
		}

		private GameObject GetAudioPrefab()
		{
			if ((Object)(object)AudioManager.instance == (Object)null)
			{
				return null;
			}
			return (GameObject)(Type switch
			{
				AudioPlayerType.Default => AudioManager.instance.AudioDefault, 
				AudioPlayerType.EnemySpawn => Assets.AudioEnemySpawnPrefab, 
				_ => null, 
			});
		}

		private AudioPlayer GetAudioPlayer()
		{
			if (!_audioPlayerPool.TryGetValue(Type, out var value) || value.Count == 0)
			{
				return CreateAudioPlayer();
			}
			AudioPlayer audioPlayer = value.Dequeue();
			if ((Object)(object)audioPlayer == (Object)null || (Object)(object)((Component)audioPlayer).gameObject == (Object)null)
			{
				return CreateAudioPlayer();
			}
			((Component)audioPlayer).gameObject.SetActive(false);
			((Component)audioPlayer).gameObject.SetActive(true);
			return audioPlayer;
		}

		private AudioPlayer CreateAudioPlayer()
		{
			if ((Object)(object)AudioManager.instance == (Object)null)
			{
				return null;
			}
			GameObject audioPrefab = GetAudioPrefab();
			if ((Object)(object)audioPrefab == (Object)null)
			{
				return null;
			}
			GameObject val = Object.Instantiate<GameObject>(audioPrefab);
			((Object)val).name = $"AudioPlayer {Type}";
			AudioPlayer audioPlayer = val.AddComponent<AudioPlayer>();
			audioPlayer.Type = Type;
			if ((Object)(object)PluginManager.Instance != (Object)null)
			{
				val.transform.SetParent(PluginManager.Instance.AudioPlayerContainerTransform);
			}
			return audioPlayer;
		}

		public static void AddToPool(AudioPlayer audioPlayer)
		{
			if (!((Object)(object)audioPlayer == (Object)null) && !((Object)(object)((Component)audioPlayer).gameObject == (Object)null))
			{
				if (!_audioPlayerPool.TryGetValue(audioPlayer.Type, out var value))
				{
					value = new Queue<AudioPlayer>();
					_audioPlayerPool.Add(audioPlayer.Type, value);
				}
				value.Enqueue(audioPlayer);
				((Component)audioPlayer).gameObject.SetActive(false);
			}
		}
	}
	public class EnemyConfigEntry
	{
		private readonly EnemyConfigEntryDefaultValues _defaultValues;

		public string EnemyName { get; private set; }

		public ConfigEntry<bool> Enabled { get; private set; }

		public ConfigEntry<int> SpawnCount { get; private set; }

		public ConfigEntry<int> BitsToSpawn { get; private set; }

		public ConfigEntry<int> SubsToSpawn { get; private set; }

		public EnemyConfigEntry(string enemyName)
		{
			_defaultValues = new EnemyConfigEntryDefaultValues(enemyName);
			Initialize();
		}

		public EnemyConfigEntry(EnemyConfigEntryDefaultValues defaultValues)
		{
			_defaultValues = defaultValues;
			Initialize();
		}

		private void Initialize()
		{
			if (_defaultValues != null)
			{
				EnemyName = _defaultValues.EnemyName;
				BindConfigs();
			}
		}

		private void BindConfigs()
		{
			string text = "Enemy: " + EnemyName;
			Enabled = EnemyConfigManager.ConfigFile.Bind<bool>(text, "Enabled", _defaultValues.Enabled, "Enable the " + EnemyName + " to be able to spawn.");
			SpawnCount = EnemyConfigManager.ConfigFile.Bind(text, "SpawnCount", _defaultValues.SpawnCount, "The amount of " + EnemyName + " to spawn.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 20));
			BitsToSpawn = EnemyConfigManager.ConfigFile.Bind(text, "BitsToSpawn", _defaultValues.BitsToSpawn, "The amount of bits to spawn " + EnemyName + ".", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 1000));
			SubsToSpawn = EnemyConfigManager.ConfigFile.Bind(text, "SubsToSpawn", _defaultValues.SubsToSpawn, "The amount of subs to spawn " + EnemyName + ".", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 10));
			Enabled.SettingChanged += delegate
			{
				PageManager.UpdatePage();
			};
			SpawnCount.SettingChanged += delegate
			{
				PageManager.UpdatePage();
			};
			BitsToSpawn.SettingChanged += delegate
			{
				PageManager.UpdatePage();
			};
			SubsToSpawn.SettingChanged += delegate
			{
				PageManager.UpdatePage();
			};
		}

		public bool EnemyNameEquals(string enemyName)
		{
			return EnemyName.Equals(enemyName, StringComparison.OrdinalIgnoreCase);
		}

		public JObject GetCardJSON()
		{
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Expected O, but got Unknown
			int num = 1;
			int value = SpawnCount.Value;
			if (EnemyName.Equals("Banger", StringComparison.OrdinalIgnoreCase))
			{
				num = 3;
			}
			if (EnemyName.Equals("Gnome", StringComparison.OrdinalIgnoreCase))
			{
				num = 4;
			}
			JObject val = new JObject
			{
				["name"] = JToken.op_Implicit(EnemyName),
				["price"] = JToken.op_Implicit(BitsToSpawn.Value),
				["spawnCount"] = JToken.op_Implicit(num * value)
			};
			if (ConfigManager.TwitchSubEvent_Enabled.Value)
			{
				val.Add("subPrice", JToken.op_Implicit(SubsToSpawn.Value));
			}
			return val;
		}
	}
	[Serializable]
	public class EnemyConfigEntryDefaultValues
	{
		public string EnemyName;

		public bool Enabled = true;

		public int SpawnCount = 1;

		public int BitsToSpawn = 350;

		public int SubsToSpawn = 1;

		public EnemyConfigEntryDefaultValues(string enemyName)
		{
			EnemyName = enemyName;
		}

		public EnemyConfigEntryDefaultValues(string enemyName, bool enabled, int spawnCount, int bitsToSpawn, int subsToSpawn)
			: this(enemyName)
		{
			Enabled = enabled;
			SpawnCount = spawnCount;
			BitsToSpawn = bitsToSpawn;
			SubsToSpawn = subsToSpawn;
		}
	}
	[CreateAssetMenu(fileName = "EnemyConfigEntryDefaultValuesList", menuName = "TwitchTrolling/EnemyConfigEntryDefaultValuesList")]
	public class EnemyConfigEntryDefaultValuesList : ScriptableObject
	{
		public EnemyConfigEntryDefaultValues[] List = Array.Empty<EnemyConfigEntryDefaultValues>();
	}
	[Serializable]
	public class EnemySpawnSFX
	{
		public string EnemyName;

		public AudioClip SpawnSFX;

		public EnemySpawnSFX(string enemyName, AudioClip spawnSFX)
		{
			EnemyName = enemyName;
			SpawnSFX = spawnSFX;
		}
	}
	[CreateAssetMenu(fileName = "EnemySpawnSFXList", menuName = "TwitchTrolling/EnemySpawnSFXList")]
	public class EnemySpawnSFXList : ScriptableObject
	{
		public AudioClip GenericSpawnSFX;

		public EnemySpawnSFX[] List = Array.Empty<EnemySpawnSFX>();

		public AudioClip GetSpawnSFX(string enemyName)
		{
			EnemySpawnSFX[] list = List;
			foreach (EnemySpawnSFX enemySpawnSFX in list)
			{
				if (enemySpawnSFX.EnemyName.Equals(enemyName, StringComparison.OrdinalIgnoreCase))
				{
					return enemySpawnSFX.SpawnSFX;
				}
			}
			return GenericSpawnSFX;
		}
	}
	internal class JsonSave
	{
		private JObject _data;

		public string DirectoryPath { get; private set; }

		public string FileName { get; private set; }

		public string FilePath => Path.Combine(DirectoryPath, FileName);

		public JsonSave(string directoryPath, string fileName)
		{
			DirectoryPath = directoryPath;
			FileName = fileName;
			_data = ReadFile();
		}

		public bool KeyExists(string key)
		{
			if (_data == null)
			{
				Logger.LogError("KeyExists: Data is null. Ensure the save file is properly loaded.");
				return false;
			}
			return _data.ContainsKey(key);
		}

		public T Load<T>(string key, T defaultValue = default(T), bool readFile = false)
		{
			if (TryLoad<T>(key, out var value, readFile))
			{
				return value;
			}
			return defaultValue;
		}

		public bool TryLoad<T>(string key, out T value, bool readFile = false)
		{
			//IL_0058: Expected O, but got Unknown
			value = default(T);
			if (readFile)
			{
				_data = ReadFile();
			}
			if (_data == null)
			{
				Logger.LogError("Load: Data is null. Returning default value for key: " + key + ".");
				return false;
			}
			JToken val = default(JToken);
			if (_data.TryGetValue(key, ref val))
			{
				try
				{
					value = val.ToObject<T>();
					return true;
				}
				catch (JsonException val2)
				{
					JsonException val3 = val2;
					Logger.LogError("Load: JSON Conversion Error for key: " + key + ". " + ((Exception)(object)val3).Message);
				}
				catch (ArgumentNullException ex)
				{
					Logger.LogError("Load: Argument Null Error for key: " + key + ". " + ex.Message);
				}
				catch (Exception ex2)
				{
					Logger.LogError("Load: Unexpected Error for key: " + key + ". " + ex2.Message);
				}
				return false;
			}
			Logger.LogWarning("Load: Key '" + key + "' does not exist. Returning default value.", extended: true);
			return false;
		}

		public bool Save<T>(string key, T value)
		{
			if (_data == null)
			{
				Logger.LogError("Save: Data is null. Cannot save key: " + key + ".");
				return false;
			}
			try
			{
				JToken val = JToken.FromObject((object)value);
				if (_data.ContainsKey(key))
				{
					_data[key] = val;
				}
				else
				{
					_data.Add(key, val);
				}
				return WriteFile(_data);
			}
			catch (Exception ex)
			{
				Logger.LogError("Save: Error saving key: " + key + ". " + ex.Message);
				return false;
			}
		}

		private JObject ReadFile()
		{
			//IL_0070: Expected O, but got Unknown
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Expected O, but got Unknown
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Expected O, but got Unknown
			try
			{
				if (!File.Exists(FilePath))
				{
					Logger.LogWarning("ReadFile: Save file does not exist at \"" + FilePath + "\". Initializing with an empty file.", extended: true);
					return new JObject();
				}
				using FileStream stream = new FileStream(FilePath, FileMode.Open, FileAccess.Read);
				using StreamReader streamReader = new StreamReader(stream, Encoding.UTF8);
				return JObject.Parse(streamReader.ReadToEnd());
			}
			catch (JsonException val)
			{
				JsonException val2 = val;
				Logger.LogError("ReadFile: JSON Parsing Error for file: \"" + FilePath + "\". " + ((Exception)(object)val2).Message);
			}
			catch (Exception ex)
			{
				Logger.LogError("ReadFile: Unexpected Error for file: \"" + FilePath + "\". " + ex.Message);
			}
			return new JObject();
		}

		private bool WriteFile(JObject data)
		{
			try
			{
				if (!Directory.Exists(DirectoryPath))
				{
					Directory.CreateDirectory(DirectoryPath);
				}
				File.WriteAllText(FilePath, ((object)data).ToString(), Encoding.UTF8);
				return true;
			}
			catch (Exception ex)
			{
				Logger.LogError("WriteFile: Unexpected Error for file: \"" + FilePath + "\". " + ex.Message);
			}
			return false;
		}
	}
	internal class JsonSaveValue<T> : ObservableValue<T>
	{
		public JsonSave JsonSave { get; private set; }

		public string Key { get; private set; }

		public T DefaultValue { get; private set; }

		public bool ReadFile { get; private set; }

		public bool HasValue
		{
			get
			{
				T value;
				return TryLoad(out value);
			}
		}

		public JsonSaveValue(JsonSave jsonSave, string key, T defaultValue = default(T), bool readFile = false)
			: base(default(T))
		{
			JsonSave = jsonSave;
			Key = key;
			DefaultValue = defaultValue;
			ReadFile = readFile;
			CustomValueGetter = Load;
			CustomValueSetter = Save;
		}

		private T Load()
		{
			return JsonSave.Load(Key, DefaultValue, ReadFile);
		}

		private bool TryLoad(out T value)
		{
			return JsonSave.TryLoad<T>(Key, out value, ReadFile);
		}

		private void Save(T value)
		{
			if (!object.Equals(value, base.Value))
			{
				JsonSave.Save(Key, value);
			}
		}
	}
	internal class ObservableValue<T>
	{
		protected T _value;

		protected Func<T> CustomValueGetter;

		protected Action<T> CustomValueSetter;

		public T Value
		{
			get
			{
				return GetValue();
			}
			set
			{
				SetValue(value);
			}
		}

		public event Action<T> OnValueChanged;

		public ObservableValue(T initialValue = default(T))
		{
			_value = initialValue;
		}

		private T GetValue()
		{
			if (CustomValueGetter != null)
			{
				_value = CustomValueGetter();
			}
			return _value;
		}

		private void SetValue(T value)
		{
			if (!object.Equals(_value, value))
			{
				_value = value;
				CustomValueSetter?.Invoke(value);
				this.OnValueChanged?.Invoke(value);
			}
		}
	}
	public class QueueJsonConverter<T> : JsonConverter
	{
		public override bool CanConvert(Type objectType)
		{
			return objectType == typeof(Queue<T>);
		}

		public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
		{
			Queue<T> source = (Queue<T>)value;
			serializer.Serialize(writer, (object)source.ToList());
		}

		public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
		{
			List<T> collection = serializer.Deserialize<List<T>>(reader);
			return new Queue<T>(collection);
		}
	}
}
namespace com.github.zehsteam.TwitchTrolling.MonoBehaviours
{
	public enum AudioPlayerType
	{
		Default,
		EnemySpawn
	}
	public class AudioPlayer : MonoBehaviour
	{
		[CompilerGenerated]
		private sealed class <PoolAfterDurationCoroutine>d__18 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public TimeSpan duration;

			public AudioPlayer <>4__this;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <PoolAfterDurationCoroutine>d__18(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_002b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0035: Expected O, but got Unknown
				int num = <>1__state;
				AudioPlayer audioPlayer = <>4__this;
				switch (num)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<>2__current = (object)new WaitForSeconds((float)duration.TotalSeconds);
					<>1__state = 1;
					return true;
				case 1:
					<>1__state = -1;
					AudioPlayerFactory.AddToPool(audioPlayer);
					return false;
				}
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		public const float DefaultVolume = 1f;

		public const float DefaultMaxDistance = 15f;

		private AudioSource _audioSource;

		public AudioPlayerType Type;

		public Transform TargetTransform;

		public Vector3 TargetPosition;

		public AudioSource AudioSource
		{
			get
			{
				if (_audioSource == null)
				{
					_audioSource = ((Component)this).GetComponent<AudioSource>();
				}
				return _audioSource;
			}
			private set
			{
				_audioSource = value;
			}
		}

		public bool IsPlaying
		{
			get
			{
				AudioSource audioSource = AudioSource;
				if (audioSource == null)
				{
					return false;
				}
				return audioSource.isPlaying;
			}
		}

		private void Start()
		{
			AudioSource.dopplerLevel = 0f;
		}

		private void Update()
		{
			UpdatePosition();
			UpdateSpatialBlend();
		}

		private void UpdatePosition()
		{
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)TargetTransform != (Object)null)
			{
				TargetPosition = TargetTransform.position;
			}
			((Component)this).transform.position = TargetPosition;
		}

		private void UpdateSpatialBlend()
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			float spatialBlend = 1f;
			PlayerAvatar localPlayer = PlayerHelper.GetLocalPlayer();
			if (!((Object)(object)localPlayer == (Object)null))
			{
				float num = Vector3.Distance(((Component)this).transform.position, ((Component)localPlayer.localCamera).transform.position);
				if (num <= 0.5f)
				{
					spatialBlend = 0f;
				}
				AudioSource.spatialBlend = spatialBlend;
			}
		}

		public float Play(AudioClip audioClip, Vector3 position, float volume = 1f, float maxDistance = 15f, bool loop = false)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			SetTargetPosition(position);
			return Play(audioClip, volume, maxDistance, loop);
		}

		public float Play(AudioClip audioClip, Transform transform, float volume = 1f, float maxDistance = 15f, bool loop = false)
		{
			SetTargetTransform(transform);
			return Play(audioClip, volume, maxDistance, loop);
		}

		private float Play(AudioClip audioClip, float volume = 1f, float maxDistance = 15f, bool loop = false)
		{
			if ((Object)(object)AudioSource == (Object)null)
			{
				if ((Object)(object)((Component)this).gameObject != (Object)null)
				{
					Object.Destroy((Object)(object)((Component)this).gameObject);
				}
				return 0f;
			}
			if ((Object)(object)audioClip == (Object)null)
			{
				AudioPlayerFactory.AddToPool(this);
				return 0f;
			}
			AudioSource.clip = audioClip;
			AudioSource.volume = volume;
			AudioSource.maxDistance = maxDistance;
			AudioSource.loop = loop;
			if (loop)
			{
				if (!AudioSource.isPlaying)
				{
					AudioSource.Play();
				}
			}
			else
			{
				AudioSource.PlayOneShot(audioClip, volume);
				TimeSpan duration = TimeSpan.FromSeconds(audioClip.length + 0.1f);
				((MonoBehaviour)this).StartCoroutine(PoolAfterDurationCoroutine(duration));
			}
			return audioClip.length;
		}

		[IteratorStateMachine(typeof(<PoolAfterDurationCoroutine>d__18))]
		private IEnumerator PoolAfterDurationCoroutine(TimeSpan duration)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <PoolAfterDurationCoroutine>d__18(0)
			{
				<>4__this = this,
				duration = duration
			};
		}

		public void Stop()
		{
			AudioSource audioSource = AudioSource;
			if (audioSource != null)
			{
				audioSource.Stop();
			}
		}

		public void SetTargetTransform(Transform targetTransform)
		{
			TargetTransform = targetTransform;
		}

		public void SetTargetPosition(Vector3 targetPosition)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			TargetTransform = null;
			TargetPosition = targetPosition;
		}
	}
	public class BrowserLink : MonoBehaviour
	{
		[SerializeField]
		public string _url;

		public void OpenLink()
		{
			Application.OpenURL(_url);
		}
	}
	public class DeathMessage : MonoBehaviour
	{
		[CompilerGenerated]
		private sealed class <ShowCoroutine>d__26 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public DeathMessage <>4__this;

			public TimeSpan duration;

			private float <fadeOutDuration>5__2;

			private float <timer>5__3;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <ShowCoroutine>d__26(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_0046: Unknown result type (might be due to invalid IL or missing references)
				//IL_0050: Expected O, but got Unknown
				int num = <>1__state;
				DeathMessage deathMessage = <>4__this;
				switch (num)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					deathMessage._canvasGroup.alpha = 1f;
					<>2__current = (object)new WaitForSeconds((float)duration.TotalSeconds);
					<>1__state = 1;
					return true;
				case 1:
					<>1__state = -1;
					<fadeOutDuration>5__2 = 1f;
					<timer>5__3 = 0f;
					break;
				case 2:
					<>1__state = -1;
					<timer>5__3 += Time.deltaTime;
					break;
				}
				if (<timer>5__3 < <fadeOutDuration>5__2)
				{
					float num2 = 1f / <fadeOutDuration>5__2 * <timer>5__3;
					float alpha = 1f + -1f * num2;
					deathMessage._canvasGroup.alpha = alpha;
					<>2__current = null;
					<>1__state = 2;
					return true;
				}
				deathMessage._canvasGroup.alpha = 0f;
				deathMessage._showCoroutine = null;
				return false;
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		[SerializeField]
		private TextMeshProUGUI _textUGUI;

		[SerializeField]
		private Image _backgroundImage;

		[SerializeField]
		private CanvasGroup _canvasGroup;

		private Coroutine _showCoroutine;

		public static DeathMessage Instance { get; private set; }

		public static bool IsEnabled => ConfigManager.DeathMessage_Enabled.Value;

		public static bool ShowPlatformIcon => ConfigManager.DeathMessage_ShowPlatformIcon.Value;

		public static float Duration => ConfigManager.DeathMessage_Duration.Value;

		public static float FontSize => ConfigManager.DeathMessage_FontSize.Value;

		public static int BackgroundTransparency => ConfigManager.DeathMessage_BackgroundTransparency.Value;

		private void Awake()
		{
			if ((Object)(object)Instance != (Object)null && (Object)(object)Instance != (Object)(object)this)
			{
				Object.Destroy((Object)(object)((Component)this).gameObject);
			}
			else
			{
				Instance = this;
			}
		}

		private void Start()
		{
			_canvasGroup.alpha = 0f;
		}

		public void Show(EnemyParent enemyParent, ViewerData viewerData)
		{
			if (!((Object)(object)enemyParent == (Object)null) && viewerData != null)
			{
				string text = (ShowPlatformIcon ? "<sprite=0>" : string.Empty);
				string message = ("You died to a <color=#FF0000>" + enemyParent.enemyName + "</color> from " + viewerData.GetDisplayNameWithColor() + " " + text).Trim();
				Show(message);
			}
		}

		public void Show(PhysGrabObject physGrabObject, ViewerData viewerData)
		{
			if (!((Object)(object)physGrabObject == (Object)null) && viewerData != null)
			{
				string text = ((Object)physGrabObject).name.TrimStart("Valuable ").TrimEnd("(Clone)").Trim();
				string text2 = (ShowPlatformIcon ? "<sprite=0>" : string.Empty);
				string message = ("You died to a <color=#FF0000>" + text + "</color> from " + viewerData.GetDisplayNameWithColor() + " " + text2).Trim();
				Show(message);
			}
		}

		public void ShowForExplosion(ViewerData viewerData, string sourceName = "")
		{
			if (viewerData != null)
			{
				string text = (ShowPlatformIcon ? "<sprite=0>" : string.Empty);
				string text2 = ((!string.IsNullOrEmpty(sourceName)) ? ("<color=#FF0000>" + sourceName + " (Explosion)</color>") : "<color=#FF0000>explosion</color>");
				string message = ("You died to an " + text2 + " from " + viewerData.GetDisplayNameWithColor() + " " + text).Trim();
				Show(message);
			}
		}

		public void Show(string message)
		{
			Show(message, TimeSpan.FromSeconds(Duration));
		}

		public void Show(string message, TimeSpan duration)
		{
			if (IsEnabled)
			{
				UseConfigSettings();
				if (_showCoroutine != null)
				{
					((MonoBehaviour)this).StopCoroutine(_showCoroutine);
				}
				((TMP_Text)_textUGUI).text = message;
				_showCoroutine = ((MonoBehaviour)this).StartCoroutine(ShowCoroutine(duration));
			}
		}

		private void UseConfigSettings()
		{
			((TMP_Text)_textUGUI).fontSize = FontSize;
			_backgroundImage.SetAlpha(BackgroundTransparency);
		}

		[IteratorStateMachine(typeof(<ShowCoroutine>d__26))]
		private IEnumerator ShowCoroutine(TimeSpan duration)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <ShowCoroutine>d__26(0)
			{
				<>4__this = this,
				duration = duration
			};
		}
	}
	public class EnemyNametag : MonoBehaviour
	{
		[SerializeField]
		private TextMeshProUGUI _usernameText;

		[SerializeField]
		public Image _backgroundImage;

		[SerializeField]
		public CanvasGroup _canvasGroup;

		private static readonly float _heightOffset = 0.5f;

		private static readonly float _minSize = 0.75f;

		private static readonly float _maxSize = 1.5f;

		private RectTransform _rectTransform;

		private Transform _enemyTransform;

		private object _enemyScript;

		private bool _continuouslyCalculatePosition;

		private float _continuouslyCalculatePositionTimer;

		private float _continuouslyCalculatePositionCooldown = 0.1f;

		public static List<EnemyNametag> Instances { get; private set; } = new List<EnemyNametag>();


		public static bool ShowPlatformIcon => ConfigManager.EnemyNametag_ShowPlatformIcon.Value;

		public static float SizeMultiplier => ConfigManager.EnemyNametag_SizeMultiplier.Value;

		public static int BackgroundTransparency => ConfigManager.EnemyNametag_BackgroundTransparency.Value;

		public EnemyParent EnemyParent { get; private set; }

		public ViewerData Viewer { get; private set; }

		private void OnEnable()
		{
			Instances.AddSingleInstance(this);
		}

		private void OnDisable()
		{
			Instances.Remove(this);
		}

		public void SetData(EnemyParent enemyParent, ViewerData viewerData)
		{
			EnemyParent = enemyParent;
			Viewer = viewerData;
			if (IsEnemyTypeElsa())
			{
				_enemyScript = ((Component)enemyParent).GetComponentInChildren<EnemyElsa>(true);
				_continuouslyCalculatePosition = true;
			}
			if (IsEnemyTypeOogly())
			{
				_enemyScript = ((Component)enemyParent).GetComponentInChildren<EnemyOogly>(true);
				_continuouslyCalculatePosition = true;
			}
		}

		private void Start()
		{
			if ((Object)(object)EnemyParent == (Object)null)
			{
				Object.Destroy((Object)(object)((Component)this).gameObject);
				return;
			}
			_rectTransform = ((Component)this).GetComponent<RectTransform>();
			_enemyTransform = GetEnemyTransform();
			bool flag = false;
			if (IsEnemyTypePeeper())
			{
				flag = true;
				((Transform)_rectTransform).SetParent(((Component)EnemyParent.Enemy).transform);
			}
			if (!flag)
			{
				((Transform)_rectTransform).SetParent(_enemyTransform);
			}
			CalculatePosition();
			UseConfigSettings();
		}

		private void Update()
		{
			if ((Object)(object)EnemyParent == (Object)null)
			{
				Object.Destroy((Object)(object)((Component)this).gameObject);
				return;
			}
			if (!IsEnemyEnabled())
			{
				_canvasGroup.alpha = 0f;
				return;
			}
			if (IsEnemyTypeHidden())
			{
				Update_HiddenEnemy();
			}
			else
			{
				_canvasGroup.alpha = 1f;
			}
			if (_continuouslyCalculatePosition)
			{
				_continuouslyCalculatePositionTimer += Time.deltaTime;
				if (_continuouslyCalculatePositionTimer >= _continuouslyCalculatePositionCooldown)
				{
					CalculatePosition();
					_continuouslyCalculatePositionTimer = 0f;
				}
			}
		}

		private void Update_HiddenEnemy()
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			float alpha = 0f;
			if (TryGetEnemyTransform(out var transform))
			{
				Vector3 origin = transform.position + new Vector3(0f, 1f, 0f);
				if (PlayerHelper.AnyPlayersNearby(origin, 5f))
				{
					alpha = 1f;
				}
			}
			_canvasGroup.alpha = alpha;
		}

		private void LateUpdate()
		{
			LookAtLocalCamera();
		}

		private bool IsEnemyTypeHidden()
		{
			return EnemyParent.enemyName.Equals("Hidden", StringComparison.OrdinalIgnoreCase);
		}

		private bool IsEnemyTypePeeper()
		{
			return EnemyParent.enemyName.Equals("Peeper", StringComparison.OrdinalIgnoreCase);
		}

		private bool IsEnemyTypeElsa()
		{
			return EnemyParent.enemyName.Equals("Elsa", StringComparison.OrdinalIgnoreCase);
		}

		private bool IsEnemyTypeOogly()
		{
			return EnemyParent.enemyName.Equals("Oogly", StringComparison.OrdinalIgnoreCase);
		}

		private bool IsEnemyEnabled()
		{
			return EnemyParent.EnableObject.activeSelf;
		}

		private Transform GetEnemyTransform()
		{
			if ((Object)(object)EnemyParent == (Object)null || (Object)(object)EnemyParent.EnableObject == (Object)null)
			{
				return null;
			}
			EnemyRigidbody componentInChildren = EnemyParent.EnableObject.GetComponentInChildren<EnemyRigidbody>();
			if ((Object)(object)componentInChildren != (Object)null)
			{
				return ((Component)componentInChildren).transform;
			}
			return ((Component)EnemyParent).transform;
		}

		private bool TryGetEnemyTransform(out Transform transform)
		{
			transform = GetEnemyTransform();
			return (Object)(object)transform != (Object)null;
		}

		private void LookAtLocalCamera()
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			PlayerAvatar localPlayer = PlayerHelper.GetLocalPlayer();
			if (!((Object)(object)localPlayer == (Object)null))
			{
				((Component)this).transform.LookAt(((Component)this).transform.position + ((Component)localPlayer.localCamera).transform.forward);
			}
		}

		private void CalculatePosition()
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_012b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0146: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			if (IsEnemyTypePeeper())
			{
				((Transform)_rectTransform).localPosition = new Vector3(0f, 0f, 0.85f);
				return;
			}
			Transform val = _enemyTransform;
			if (IsEnemyTypeElsa() && _enemyScript != null)
			{
				object enemyScript = _enemyScript;
				EnemyElsa val2 = (EnemyElsa)((enemyScript is EnemyElsa) ? enemyScript : null);
				if (val2 != null && !val2.IsBig())
				{
					val = val2.smallColliderTransform;
				}
			}
			if (IsEnemyTypeOogly() && _enemyScript != null)
			{
				object enemyScript2 = _enemyScript;
				EnemyOogly val3 = (EnemyOogly)((enemyScript2 is EnemyOogly) ? enemyScript2 : null);
				if (val3 != null && (Object)(object)val3.targetPlayer == (Object)null)
				{
					((Transform)_rectTransform).localPosition = new Vector3(0f, -1.5f, 0f);
					return;
				}
			}
			Collider[] componentsInChildren = ((Component)val).GetComponentsInChildren<Collider>();
			if (componentsInChildren == null || componentsInChildren.Length == 0)
			{
				Logger.LogWarning("EnemyNametag: No colliders found on the enemy.");
				return;
			}
			float num = float.MinValue;
			Collider[] array = componentsInChildren;
			foreach (Collider val4 in array)
			{
				if (!val4.isTrigger)
				{
					Bounds bounds = val4.bounds;
					float y = ((Bounds)(ref bounds)).max.y;
					if (y > num)
					{
						num = y;
					}
				}
			}
			float num2 = num + _heightOffset;
			Vector3 localPosition = default(Vector3);
			((Vector3)(ref localPosition))..ctor(0f, num2 - _enemyTransform.position.y, 0f);
			((Transform)_rectTransform).localPosition = localPosition;
		}

		public void CalculateScale()
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			Collider[] componentsInChildren = ((Component)_enemyTransform).GetComponentsInChildren<Collider>(true);
			if (componentsInChildren == null || componentsInChildren.Length == 0)
			{
				Logger.LogWarning("EnemyNametag: No colliders found on the enemy.");
				return;
			}
			Bounds bounds = componentsInChildren[0].bounds;
			Collider[] array = componentsInChildren;
			foreach (Collider val in array)
			{
				if (!val.isTrigger)
				{
					(