Decompiled source of TwitchTrolling v1.9.0

BepInEx/plugins/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.Serialization;
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.Converters;
using Newtonsoft.Json.Linq;
using Photon.Pun;
using REPOConfig;
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.Dependencies.MenuLibMod.MonoBehaviours;
using com.github.zehsteam.TwitchTrolling.Dependencies.MenuLibMod.Patches;
using com.github.zehsteam.TwitchTrolling.Dependencies.REPOConfigMod;
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;
using com.github.zehsteam.TwitchTrolling.Website;
using com.github.zehsteam.TwitchTrolling.Website.Objects;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: IgnoresAccessChecksTo("MenuLib")]
[assembly: IgnoresAccessChecksTo("REPOConfig")]
[assembly: IgnoresAccessChecksTo("REPOLib")]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("Zehs")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyCopyright("Copyright © 2026 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.9.0.0")]
[assembly: AssemblyInformationalVersion("1.9.0+22c7ddd753dd9f4476ca7995a4f1aa2c47deedbc")]
[assembly: AssemblyProduct("TwitchTrolling")]
[assembly: AssemblyTitle("com.github.zehsteam.TwitchTrolling")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.9.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace 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 bool IsExtendedLoggingEnabled => ConfigManager.Misc_ExtendedLogging?.Value ?? false;

		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 LogMessage(object data, bool extended = false)
		{
			Log((LogLevel)8, 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)
		{
			Log((LogLevel)2, data, extended, showMessage);
		}

		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, bool showMessage = false)
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//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_0026: 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_003e: Expected I4, but got Unknown
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: 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)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			if (extended && !IsExtendedLoggingEnabled)
			{
				return;
			}
			ManualLogSource manualLogSource = ManualLogSource;
			if (manualLogSource != null)
			{
				manualLogSource.Log(logLevel, data);
			}
			if (showMessage)
			{
				Color color = Color.white;
				switch (logLevel - 1)
				{
				case 0:
					color = Color.red;
					break;
				case 1:
					color = Color.red;
					break;
				case 3:
					color = Color.yellow;
					break;
				}
				MessageManager.Instance?.ShowMessage(data.ToString(), color);
			}
		}
	}
	internal static class Menu
	{
		[Serializable]
		[CompilerGenerated]
		private sealed class <>c
		{
			public static readonly <>c <>9 = new <>c();

			public static BuilderDelegate <>9__6_0;

			public static BuilderDelegate <>9__6_1;

			public static BuilderDelegate <>9__6_2;

			public static Action <>9__6_3;

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

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

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

			internal void <Initialize>b__6_3()
			{
				PageManager.OnValidateTwitchChannelResult -= HandleValidateTwitchChannelResult;
				PageManager.OnCheckPageExistsResult -= HandleCheckPageExistsResult;
				PageManager.OnCreatePageResult -= HandleCreatePageResult;
			}
		}

		private static REPOPopupPage _popupPage;

		private static REPOLabel _pageStatusLabel;

		private static REPOLabel _pageUrlLabel;

		private static REPOButton _createPageButton;

		private static REPOButton _copyPageURLButton;

		private static REPOButton _settingsButton;

		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__6_0;
			if (obj == null)
			{
				BuilderDelegate val = delegate(Transform parent)
				{
					CreateMainButtonForMainMenu(parent);
				};
				<>c.<>9__6_0 = val;
				obj = (object)val;
			}
			MenuAPI.AddElementToMainMenu((BuilderDelegate)obj);
			object obj2 = <>c.<>9__6_1;
			if (obj2 == null)
			{
				BuilderDelegate val2 = delegate(Transform parent)
				{
					CreateMainButtonForLobbyAndEscapeMenu(parent);
				};
				<>c.<>9__6_1 = val2;
				obj2 = (object)val2;
			}
			MenuAPI.AddElementToLobbyMenu((BuilderDelegate)obj2);
			object obj3 = <>c.<>9__6_2;
			if (obj3 == null)
			{
				BuilderDelegate val3 = delegate(Transform parent)
				{
					CreateMainButtonForLobbyAndEscapeMenu(parent);
				};
				<>c.<>9__6_2 = val3;
				obj3 = (object)val3;
			}
			MenuAPI.AddElementToEscapeMenu((BuilderDelegate)obj3);
			PageManager.OnValidateTwitchChannelResult += HandleValidateTwitchChannelResult;
			PageManager.OnCheckPageExistsResult += HandleCheckPageExistsResult;
			PageManager.OnCreatePageResult += HandleCreatePageResult;
			Application.quitting += delegate
			{
				PageManager.OnValidateTwitchChannelResult -= HandleValidateTwitchChannelResult;
				PageManager.OnCheckPageExistsResult -= HandleCheckPageExistsResult;
				PageManager.OnCreatePageResult -= HandleCreatePageResult;
			};
		}

		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_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: Expected O, but got Unknown
			//IL_0110: Unknown result type (might be due to invalid IL or missing references)
			//IL_011a: 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 -= 40f;
			_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)
				_settingsButton = MenuAPI.CreateREPOButton("Settings", (Action)HandleSettingsButtonClick, parent, Vector2.op_Implicit(new Vector3(xPosition, yPosition)));
			});
			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);
			UpdateMenu();
			PageManager.CheckPageExists();
			if (SemiFunc.IsMasterClientOrSingleplayer())
			{
				PageManager.ValidateTwitchChannel();
			}
		}

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

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

		private static void HandleCreatePageButtonClick()
		{
			if (!SemiFunc.IsMasterClientOrSingleplayer())
			{
				Logger.LogError("You are unable to create a page because you are not the host!", extended: false, showMessage: true);
				return;
			}
			REPOButton createPageButton = _createPageButton;
			if (createPageButton != null)
			{
				((Component)createPageButton).gameObject.SetActive(false);
			}
			PageManager.CreatePage();
		}

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

		private static void HandleSettingsButtonClick()
		{
			HandleCloseButtonClick();
			REPOConfigHelper.OpenSettingsMenu("TwitchTrolling");
		}

		private static void SetPageStatus(bool isOnline)
		{
			if (isOnline)
			{
				((TMP_Text)_pageStatusLabel.labelTMP).text = "Page Status: <color=#00FF00>ONLINE</color>";
			}
			else
			{
				((TMP_Text)_pageStatusLabel.labelTMP).text = "Page Status: <color=#FF0000>OFFLINE</color>";
			}
		}

		private static void SetMessagePageUrl(string url)
		{
			string text = url.Replace("?id", "\n?id");
			((TMP_Text)_pageUrlLabel.labelTMP).text = "<color=#FFFFFF>" + text + "</color>";
			((TMP_Text)_pageUrlLabel.labelTMP).fontStyle = (FontStyles)1;
		}

		private static void SetMessageCreatePageError(string reason)
		{
			SetMessageError("You are unable to create a page! Reason:", reason);
		}

		private static void SetMessageError(string header, string reason)
		{
			SetMessage(header + "\n<size=25><color=#FF0000>" + reason + "</color></size>");
		}

		private static void SetMessage(string message)
		{
			((TMP_Text)_pageUrlLabel.labelTMP).text = message;
			((TMP_Text)_pageUrlLabel.labelTMP).fontStyle = (FontStyles)17;
		}

		private static void UpdateMenu(object serverResponseObj = null)
		{
			if ((Object)(object)_popupPage == (Object)null)
			{
				return;
			}
			bool hasPage = PageManager.HasPage;
			((Component)_createPageButton).gameObject.SetActive(!hasPage);
			((Component)_copyPageURLButton).gameObject.SetActive(hasPage);
			SetPageStatus(hasPage);
			if (hasPage)
			{
				SetMessagePageUrl(PageManager.CurrentPage.PageUrl);
			}
			ValidateTwitchChannelResponse lastValidateTwitchChannelResponse = PageManager.LastValidateTwitchChannelResponse;
			if (lastValidateTwitchChannelResponse != null && !lastValidateTwitchChannelResponse.Success)
			{
				SetMessageError("Twitch validation error:", lastValidateTwitchChannelResponse.Error + "\n");
				((Component)_createPageButton).gameObject.SetActive(false);
				((Component)_copyPageURLButton).gameObject.SetActive(false);
			}
			else
			{
				if (hasPage)
				{
					return;
				}
				if (!SemiFunc.IsMasterClientOrSingleplayer())
				{
					SetMessageCreatePageError("You are not the host");
					((Component)_createPageButton).gameObject.SetActive(false);
				}
				else if (serverResponseObj is ServerResponse<CreatePageResult> serverResponse)
				{
					if (!serverResponse.Success)
					{
						SetMessageCreatePageError(serverResponse.Error);
						((Component)_createPageButton).gameObject.SetActive(false);
					}
				}
				else
				{
					SetMessage("Create a page to share your prices\nwith your viewers!");
				}
			}
		}

		private static void HandleValidateTwitchChannelResult(ValidateTwitchChannelResponse response)
		{
			UpdateMenu(response);
		}

		private static void HandleCheckPageExistsResult(CheckPageExistsRequestResponse response)
		{
			UpdateMenu();
		}

		private static void HandleCreatePageResult(ServerResponse<CreatePageResult> response)
		{
			UpdateMenu(response);
		}
	}
	[BepInPlugin("com.github.zehsteam.TwitchTrolling", "TwitchTrolling", "1.9.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!");
			GlobalSave = new JsonSave(Utils.GetPluginPersistentDataPath(), "GlobalSave");
			LocalSave = new JsonSave(Paths.ConfigPath, "TwitchTrolling_Save.json");
			ConfigManager.Initialize(((BaseUnityPlugin)this).Config);
			_harmony.PatchAll(typeof(NetworkManager_Patches));
			_harmony.PatchAll(typeof(NetworkConnect_Patches));
			_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));
			_harmony.PatchAll(typeof(REPOPopupPage_Patches));
			Assets.Load();
			CoroutineRunner.Spawn();
			PluginManager.Spawn();
			TwitchIntegrationManager.Initialize();
			Menu.Initialize();
			PlayerHelper.Initialize();
			TwitchSimulateCheerCommand.Register();
			TwitchSimulateSubCommand.Register();
			PageManager.Initialize();
		}
	}
	internal static class Utils
	{
		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 text.RichColor(readableColor);
		}

		public static IEnumerator InvokeAfterDurationCoroutine(TimeSpan duration, Action action)
		{
			yield return (object)new WaitForSeconds((float)duration.TotalSeconds);
			action?.Invoke();
		}
	}
	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.9.0";
	}
}
namespace com.github.zehsteam.TwitchTrolling.Website
{
	internal class PageDataSaveHelper
	{
		public static PageData LoadData()
		{
			if (!Plugin.GlobalSave.TryLoad<string>("UrlId", out var value) || string.IsNullOrWhiteSpace(value))
			{
				return null;
			}
			if (!Plugin.GlobalSave.TryLoad<string>("AccessToken", out var value2) || string.IsNullOrWhiteSpace(value2))
			{
				return null;
			}
			return new PageData(value, value2);
		}

		public static bool TryLoadData(out PageData pageData)
		{
			pageData = LoadData();
			return pageData != null;
		}

		public static void SaveData(PageData pageData)
		{
			if (pageData != null)
			{
				Plugin.GlobalSave.Save("UrlId", pageData.UrlId);
				Plugin.GlobalSave.Save("AccessToken", pageData.AccessToken);
			}
		}

		public static void DeleteData()
		{
			Plugin.GlobalSave.Delete("UrlId");
			Plugin.GlobalSave.Delete("AccessToken");
		}
	}
	internal static class PageManager
	{
		public static readonly string ConvexUrl = "https://brainy-mockingbird-121.convex.site";

		public static readonly string WebsiteUrl = "https://twitchtrolling.com";

		public static readonly string CreatePageToken = "f404cdd4-f52d-45cf-9147-f3775f73b02f";

		private static string _previousChannel;

		private static PagePayload _lastSentPagePayload;

		private static List<EffectPayload> _lastSentEffectsPayload = new List<EffectPayload>();

		private static float _timeSincePageUpdateCalled;

		private static float _pageUpdateCooldown = 0.1f;

		public static PageData CurrentPage { get; private set; }

		public static bool HasPage => CurrentPage != null;

		public static ValidateTwitchChannelResponse LastValidateTwitchChannelResponse { get; private set; }

		public static event Action<ValidateTwitchChannelResponse> OnValidateTwitchChannelResult;

		public static event Action<CheckPageExistsRequestResponse> OnCheckPageExistsResult;

		public static event Action<ServerResponse<CreatePageResult>> OnCreatePageResult;

		public static void Initialize()
		{
			API.OnConnect += HandleTwitchChatAPIOnConnect;
			Application.quitting += delegate
			{
				API.OnConnect -= HandleTwitchChatAPIOnConnect;
			};
			_previousChannel = API.Channel;
			CheckPageExists();
			ValidateTwitchChannel();
		}

		public static void ValidateTwitchChannel()
		{
			TwitchRequestHelper.ValidateTwitchChannel(API.Channel, HandleValidateTwitchChannelResult);
		}

		public static void CheckPageExists()
		{
			PageData pageData;
			if (HasPage)
			{
				PageRequestHelper.CheckPageExists(CurrentPage, HandleCheckPageExistsResult);
			}
			else if (PageDataSaveHelper.TryLoadData(out pageData))
			{
				PageRequestHelper.CheckPageExists(pageData, HandleCheckPageExistsResult);
			}
		}

		public static void CreatePage()
		{
			if (!HasPage)
			{
				PageRequestHelper.CreatePage(GetPagePayload(), HandleCreatePageResult);
			}
		}

		public static void UpdatePage()
		{
			UpdatePage(updateEffects: true, EffectsAction.Update);
		}

		private static void UpdatePage(bool updateEffects, EffectsAction effectsAction)
		{
			if (HasPage)
			{
				float pageUpdateCooldown = _pageUpdateCooldown;
				float realtimeSinceStartup = Time.realtimeSinceStartup;
				if (!(realtimeSinceStartup - _timeSincePageUpdateCalled < pageUpdateCooldown))
				{
					_timeSincePageUpdateCalled = realtimeSinceStartup;
					CoroutineRunner.Start(UpdatePageAfterDelay_Coroutine(pageUpdateCooldown, updateEffects, effectsAction));
				}
			}
		}

		private static IEnumerator UpdatePageAfterDelay_Coroutine(float delay, bool updateEffects = true, EffectsAction effectsAction = EffectsAction.Update)
		{
			yield return (object)new WaitForSeconds(delay);
			PagePayload pagePayload = GetPagePayload();
			if (!pagePayload.Equals(_lastSentPagePayload))
			{
				PageRequestHelper.UpdatePage(CurrentPage, pagePayload, HandleUpdatePageResult);
			}
			if (updateEffects)
			{
				SetOrUpdateEffects(effectsAction);
			}
		}

		public static void SetEffects()
		{
			SetOrUpdateEffects(EffectsAction.Set);
		}

		private static void SetOrUpdateEffects(EffectsAction action)
		{
			if (!HasPage)
			{
				return;
			}
			List<EffectPayload> list;
			if (action == EffectsAction.Set)
			{
				list = GetEffectsPayload();
			}
			else
			{
				list = GetChangedEffectsPayload();
				if (list.Count == 0)
				{
					return;
				}
			}
			PageRequestHelper.SetOrUpdateEffects(action, CurrentPage, list, HandleSetOrUpdateEffectsResult);
		}

		private static void HandleTwitchChatAPIOnConnect()
		{
			string channel = API.Channel;
			if (!channel.Equals(_previousChannel, StringComparison.OrdinalIgnoreCase))
			{
				_previousChannel = channel;
				ValidateTwitchChannel();
				UpdatePage();
			}
		}

		private static void HandleValidateTwitchChannelResult(ValidateTwitchChannelResponse response)
		{
			LastValidateTwitchChannelResponse = response;
			PageManager.OnValidateTwitchChannelResult?.Invoke(response);
		}

		private static void HandleCheckPageExistsResult(CheckPageExistsRequestResponse response)
		{
			if (response.ServerResponse.Success)
			{
				if (!HasPage)
				{
					CurrentPage = response.PageData;
					UpdatePage(updateEffects: true, EffectsAction.Set);
				}
			}
			else
			{
				CurrentPage = null;
				PageDataSaveHelper.DeleteData();
			}
			PageManager.OnCheckPageExistsResult?.Invoke(response);
		}

		private static void HandleCreatePageResult(ServerResponse<CreatePageResult> response)
		{
			if (response.Success)
			{
				CurrentPage = response.Data.ToPageData();
				_lastSentPagePayload = GetPagePayload();
				_lastSentEffectsPayload = new List<EffectPayload>();
				PageDataSaveHelper.SaveData(CurrentPage);
				SetOrUpdateEffects(EffectsAction.Set);
				MessageManager.Instance?.ShowMessage("Please share the page url with your viewers");
				MessageManager.Instance?.ShowMessage("It is recommended that you pin it in your chat");
			}
			PageManager.OnCreatePageResult?.Invoke(response);
		}

		private static void HandleUpdatePageResult(UpdatePageResponse response)
		{
			if (response.ServerResponse.Success)
			{
				_lastSentPagePayload = response.PagePayload;
			}
		}

		private static void HandleSetOrUpdateEffectsResult(EffectRequestResponse response)
		{
			if (response.ServerResponse.Success)
			{
				_lastSentEffectsPayload = response.EffectsPayload;
			}
		}

		private static PagePayload GetPagePayload()
		{
			return new PagePayload
			{
				Username = API.Channel,
				IsHost = SemiFunc.IsMasterClientOrSingleplayer(),
				IsEnemiesEnabled = ConfigManager.Enemy_Enabled.Value,
				IsEventsEnabled = MEventManager.Enabled,
				IsCheerEnabled = TwitchIntegrationManager.IsCheerEventEnabled,
				IsSubEnabled = TwitchIntegrationManager.IsSubEventEnabled,
				IsRaidEnabled = TwitchIntegrationManager.IsRaidEventEnabled,
				Tier1SubEnemyMultiplier = ConfigManager.TwitchSubEvent_Tier1EnemySpawnCountMultiplier.Value,
				Tier2SubEnemyMultiplier = ConfigManager.TwitchSubEvent_Tier2EnemySpawnCountMultiplier.Value,
				Tier3SubEnemyMultiplier = ConfigManager.TwitchSubEvent_Tier3EnemySpawnCountMultiplier.Value,
				RaidViewersPerEnemy = ConfigManager.TwitchRaidEvent_ViewersPerRandomEnemy.Value,
				RaidMaxEnemySpawnCount = ConfigManager.TwitchRaidEvent_MaxEnemySpawnCount.Value
			};
		}

		private static List<EffectPayload> GetEffectsPayload()
		{
			List<EffectPayload> effectsPayload = EnemyConfigManager.GetEffectsPayload();
			List<EffectPayload> effectsPayload2 = MEventManager.GetEffectsPayload();
			List<EffectPayload> list = new List<EffectPayload>(effectsPayload.Count + effectsPayload2.Count);
			list.AddRange(effectsPayload);
			list.AddRange(effectsPayload2);
			return list;
		}

		private static List<EffectPayload> GetChangedEffectsPayload()
		{
			List<EffectPayload> lastSentEffectsPayload = _lastSentEffectsPayload;
			List<EffectPayload> effectsPayload = GetEffectsPayload();
			List<EffectPayload> list = new List<EffectPayload>();
			foreach (EffectPayload currentEffect in effectsPayload)
			{
				if (!lastSentEffectsPayload.Any((EffectPayload x) => x.Equals(currentEffect)))
				{
					list.Add(currentEffect);
				}
			}
			return list;
		}
	}
	internal static class PageRequestHelper
	{
		public static void CheckPageExists(PageData pageData, Action<CheckPageExistsRequestResponse> resultCallback)
		{
			CoroutineRunner.Start(CheckPageExists_Coroutine(pageData, resultCallback));
		}

		private static IEnumerator CheckPageExists_Coroutine(PageData pageData, Action<CheckPageExistsRequestResponse> resultCallback)
		{
			if (pageData == null)
			{
				yield break;
			}
			string text = PageManager.ConvexUrl + "/page/exists?urlId=" + Uri.EscapeDataString(pageData.UrlId);
			UnityWebRequest request = UnityWebRequest.Get(text);
			try
			{
				request.downloadHandler = (DownloadHandler)new DownloadHandlerBuffer();
				yield return request.SendWebRequest();
				if ((int)request.result == 2)
				{
					Failed("Failed to connect to server");
					yield break;
				}
				if ((int)request.result == 4)
				{
					Failed("Failed to process response from server");
					yield break;
				}
				string text2 = request.downloadHandler.text;
				if (Logger.IsExtendedLoggingEnabled)
				{
					Logger.LogInfo("[CheckPageExists_Coroutine] Server response:\n\n" + text2 + "\n", extended: true);
				}
				if (!TryParseResponse(text2, out var response, out var errorMessage))
				{
					Failed(errorMessage);
					yield break;
				}
				if (Logger.IsExtendedLoggingEnabled)
				{
					Logger.LogInfo("[CheckPageExists_Coroutine] Parsed response:\n\n" + JsonConvert.SerializeObject((object)response, (Formatting)1) + "\n", extended: true);
				}
				resultCallback?.Invoke(new CheckPageExistsRequestResponse(response, pageData));
			}
			finally
			{
				((IDisposable)request)?.Dispose();
			}
			void Failed(string message)
			{
				Logger.LogError("Failed to check page exists: " + message, extended: false, showMessage: true);
				resultCallback?.Invoke(new CheckPageExistsRequestResponse(ServerResponse.Failed(message), null));
			}
		}

		public static void CreatePage(PagePayload payload, Action<ServerResponse<CreatePageResult>> resultCallback)
		{
			CoroutineRunner.Start(CreatePage_Coroutine(payload, resultCallback));
		}

		private static IEnumerator CreatePage_Coroutine(PagePayload payload, Action<ServerResponse<CreatePageResult>> resultCallback)
		{
			string s = JsonConvert.SerializeObject((object)payload);
			string text = PageManager.ConvexUrl + "/page";
			UnityWebRequest request = new UnityWebRequest(text, "POST");
			try
			{
				byte[] bytes = Encoding.UTF8.GetBytes(s);
				request.uploadHandler = (UploadHandler)new UploadHandlerRaw(bytes);
				request.downloadHandler = (DownloadHandler)new DownloadHandlerBuffer();
				request.SetRequestHeader("Content-Type", "application/json");
				request.SetRequestHeader("Authorization", "Bearer " + PageManager.CreatePageToken);
				yield return request.SendWebRequest();
				if ((int)request.result == 2)
				{
					Failed("Failed to connect to server");
					yield break;
				}
				if ((int)request.result == 4)
				{
					Failed("Failed to process response from server");
					yield break;
				}
				string text2 = request.downloadHandler.text;
				if (Logger.IsExtendedLoggingEnabled)
				{
					Logger.LogInfo("[CreatePage_Coroutine] Server response:\n\n" + text2 + "\n", extended: true);
				}
				if (!TryParseResponse(text2, out ServerResponse<CreatePageResult> response, out string errorMessage))
				{
					Failed(errorMessage);
					yield break;
				}
				if (Logger.IsExtendedLoggingEnabled)
				{
					Logger.LogInfo("[CreatePage_Coroutine] Parsed response:\n\n" + JsonConvert.SerializeObject((object)response, (Formatting)1) + "\n", extended: true);
				}
				resultCallback?.Invoke(response);
			}
			finally
			{
				((IDisposable)request)?.Dispose();
			}
			void Failed(string message)
			{
				Logger.LogError("Failed to create page: " + message, extended: false, showMessage: true);
				resultCallback?.Invoke(ServerResponse<CreatePageResult>.Failed(message));
			}
		}

		public static void UpdatePage(PageData pageData, PagePayload payload, Action<UpdatePageResponse> resultCallback)
		{
			CoroutineRunner.Start(UpdatePage_Coroutine(pageData, payload, resultCallback));
		}

		private static IEnumerator UpdatePage_Coroutine(PageData pageData, PagePayload payload, Action<UpdatePageResponse> resultCallback)
		{
			if (pageData == null)
			{
				yield break;
			}
			string s = JsonConvert.SerializeObject((object)payload);
			string text = PageManager.ConvexUrl + "/page?urlId=" + Uri.EscapeDataString(pageData.UrlId);
			UnityWebRequest request = new UnityWebRequest(text, "PATCH");
			try
			{
				byte[] bytes = Encoding.UTF8.GetBytes(s);
				request.uploadHandler = (UploadHandler)new UploadHandlerRaw(bytes);
				request.downloadHandler = (DownloadHandler)new DownloadHandlerBuffer();
				request.SetRequestHeader("Content-Type", "application/json");
				request.SetRequestHeader("Authorization", "Bearer " + pageData.AccessToken);
				yield return request.SendWebRequest();
				if ((int)request.result == 2)
				{
					Failed("Failed to connect to server");
					yield break;
				}
				if ((int)request.result == 4)
				{
					Failed("Failed to process response from server");
					yield break;
				}
				string text2 = request.downloadHandler.text;
				if (Logger.IsExtendedLoggingEnabled)
				{
					Logger.LogInfo("[UpdatePage_Coroutine] Server response:\n\n" + text2 + "\n", extended: true);
				}
				if (!TryParseResponse(text2, out var response, out var errorMessage))
				{
					Failed(errorMessage);
					yield break;
				}
				if (Logger.IsExtendedLoggingEnabled)
				{
					Logger.LogInfo("[UpdatePage_Coroutine] Parsed response:\n\n" + JsonConvert.SerializeObject((object)response, (Formatting)1) + "\n", extended: true);
				}
				resultCallback?.Invoke(new UpdatePageResponse(response, payload));
			}
			finally
			{
				((IDisposable)request)?.Dispose();
			}
			void Failed(string message)
			{
				Logger.LogError("Failed to update page: " + message, extended: false, showMessage: true);
				resultCallback?.Invoke(new UpdatePageResponse(ServerResponse.Failed(message), payload));
			}
		}

		public static void SetOrUpdateEffects(EffectsAction action, PageData pageData, List<EffectPayload> payload, Action<EffectRequestResponse> resultCallback)
		{
			CoroutineRunner.Start(SetOrUpdateEffects_Coroutine(action, pageData, payload, resultCallback));
		}

		private static IEnumerator SetOrUpdateEffects_Coroutine(EffectsAction action, PageData pageData, List<EffectPayload> payload, Action<EffectRequestResponse> resultCallback)
		{
			if (pageData == null || (action == EffectsAction.Update && payload.Count == 0))
			{
				yield break;
			}
			string s = JsonConvert.SerializeObject((object)payload);
			string text = PageManager.ConvexUrl + "/page/effects?urlId=" + Uri.EscapeDataString(pageData.UrlId);
			UnityWebRequest request = new UnityWebRequest(text, action switch
			{
				EffectsAction.Set => "PUT", 
				EffectsAction.Update => "PATCH", 
				_ => throw new ArgumentOutOfRangeException("action", $"Unsupported action: {action}"), 
			});
			try
			{
				byte[] bytes = Encoding.UTF8.GetBytes(s);
				request.uploadHandler = (UploadHandler)new UploadHandlerRaw(bytes);
				request.downloadHandler = (DownloadHandler)new DownloadHandlerBuffer();
				request.SetRequestHeader("Content-Type", "application/json");
				request.SetRequestHeader("Authorization", "Bearer " + pageData.AccessToken);
				yield return request.SendWebRequest();
				if ((int)request.result == 2)
				{
					Failed("Failed to connect to server");
					yield break;
				}
				if ((int)request.result == 4)
				{
					Failed("Failed to process response from server");
					yield break;
				}
				string text2 = request.downloadHandler.text;
				if (Logger.IsExtendedLoggingEnabled)
				{
					Logger.LogInfo("[SetOrUpdateEffects_Coroutine] Server response:\n\n" + text2 + "\n", extended: true);
				}
				if (!TryParseResponse(text2, out var response, out var errorMessage))
				{
					Failed(errorMessage);
					yield break;
				}
				if (Logger.IsExtendedLoggingEnabled)
				{
					Logger.LogInfo("[SetOrUpdateEffects_Coroutine] Parsed response:\n\n" + JsonConvert.SerializeObject((object)response, (Formatting)1) + "\n", extended: true);
				}
				resultCallback?.Invoke(new EffectRequestResponse(response, payload));
			}
			finally
			{
				((IDisposable)request)?.Dispose();
			}
			void Failed(string message)
			{
				Logger.LogError("Failed to " + action.ToString().ToLower() + " page effects: " + message, extended: false, showMessage: true);
				resultCallback?.Invoke(new EffectRequestResponse(ServerResponse.Failed(message), payload));
			}
		}

		private static bool TryParseResponse<T>(string json, out ServerResponse<T> response, out string errorMessage)
		{
			try
			{
				response = JsonConvert.DeserializeObject<ServerResponse<T>>(json);
				errorMessage = null;
				return true;
			}
			catch (Exception ex)
			{
				response = null;
				errorMessage = "Failed to parse response from server: " + ex.Message;
				return false;
			}
		}

		private static bool TryParseResponse(string json, out ServerResponse response, out string errorMessage)
		{
			try
			{
				response = JsonConvert.DeserializeObject<ServerResponse>(json);
				errorMessage = null;
				return true;
			}
			catch (Exception ex)
			{
				response = null;
				errorMessage = "Failed to parse response from server: " + ex.Message;
				return false;
			}
		}
	}
	internal static class TwitchRequestHelper
	{
		public static void ValidateTwitchChannel(string username, Action<ValidateTwitchChannelResponse> resultCallback)
		{
			CoroutineRunner.Start(ValidateTwitchChannel_Coroutine(username, resultCallback));
		}

		private static IEnumerator ValidateTwitchChannel_Coroutine(string username, Action<ValidateTwitchChannelResponse> resultCallback)
		{
			if (username.Equals("CritHaxXoG", StringComparison.OrdinalIgnoreCase))
			{
				resultCallback?.Invoke(ValidateTwitchChannelResponse.Succeeded());
				yield break;
			}
			string text = "https://api.ivr.fi/v2/twitch/user?login=" + Uri.EscapeDataString(username);
			UnityWebRequest request = UnityWebRequest.Get(text);
			try
			{
				request.SetRequestHeader("User-Agent", "TwitchTrolling/1.9.0");
				request.downloadHandler = (DownloadHandler)new DownloadHandlerBuffer();
				yield return request.SendWebRequest();
				if ((int)request.result == 2)
				{
					Failed("Failed to connect to Twitch API server");
					yield break;
				}
				if ((int)request.result == 4)
				{
					Failed("Failed to process response from Twitch API server");
					yield break;
				}
				if ((int)request.result == 3)
				{
					Failed($"Twitch API server returned error {request.responseCode}");
					yield break;
				}
				if ((int)request.result != 1)
				{
					Failed($"Twitch API server returned error {request.responseCode}");
					yield break;
				}
				string text2 = request.downloadHandler.text;
				JObject val2;
				try
				{
					JArray val = JArray.Parse(text2);
					if (((JContainer)val).Count == 0)
					{
						Failed("Twitch user not found");
						yield break;
					}
					val2 = (JObject)val[0];
				}
				catch (Exception data)
				{
					Failed("Failed to parse response from Twitch API server");
					Logger.LogError(data);
					yield break;
				}
				if (((JToken)val2).Value<bool>((object)"banned"))
				{
					Failed("Twitch user is banned");
					yield break;
				}
				JObject val3 = (JObject)(((object)((JToken)val2).Value<JObject>((object)"roles")) ?? ((object)new JObject()));
				bool valueOrDefault = ((JToken)val3).Value<bool?>((object)"isAffiliate") == true;
				bool valueOrDefault2 = ((JToken)val3).Value<bool?>((object)"isPartner") == true;
				if (!valueOrDefault && !valueOrDefault2)
				{
					Failed("Twitch user is not affiliate or partner");
					yield break;
				}
				JObject val4 = ((JToken)val2).Value<JObject>((object)"stream");
				if (val4 == null)
				{
					Failed("Twitch user is not live");
					yield break;
				}
				JObject val5 = (JObject)(((object)((JToken)val4).Value<JObject>((object)"game")) ?? ((object)new JObject()));
				string text3 = ((JToken)val5).Value<string>((object)"displayName") ?? string.Empty;
				string text4 = "R.E.P.O.";
				if (!text3.Equals(text4, StringComparison.OrdinalIgnoreCase))
				{
					Failed("Twitch user is not in the " + text4 + " category");
				}
				else
				{
					resultCallback?.Invoke(ValidateTwitchChannelResponse.Succeeded());
				}
			}
			finally
			{
				((IDisposable)request)?.Dispose();
			}
			void Failed(string message)
			{
				Logger.LogError("Twitch validation error: " + message, extended: false, showMessage: true);
				resultCallback?.Invoke(ValidateTwitchChannelResponse.Failed(message));
			}
		}
	}
}
namespace com.github.zehsteam.TwitchTrolling.Website.Objects
{
	public class CheckPageExistsRequestResponse
	{
		public ServerResponse ServerResponse { get; private set; }

		public PageData PageData { get; private set; }

		public CheckPageExistsRequestResponse(ServerResponse serverResponse, PageData pageData)
		{
			ServerResponse = serverResponse;
			PageData = pageData;
		}
	}
	public record struct CreatePageResult
	{
		[JsonProperty("urlId")]
		public string UrlId { get; set; }

		[JsonProperty("accessToken")]
		public string AccessToken { get; set; }

		public readonly PageData ToPageData()
		{
			return new PageData(UrlId, AccessToken);
		}
	}
	[JsonConverter(typeof(StringEnumConverter))]
	public enum EffectType
	{
		[EnumMember(Value = "enemy")]
		Enemy,
		[EnumMember(Value = "event")]
		Event
	}
	public record struct EffectPayload
	{
		[JsonProperty("type")]
		public EffectType Type { get; set; }

		[JsonProperty("name")]
		public string Name { get; set; }

		[JsonProperty("isEnabled")]
		public bool IsEnabled { get; set; }

		[JsonProperty(/*Could not decode attribute arguments.*/)]
		public int? SpawnCount { get; set; }

		[JsonProperty("bitPrice")]
		public int BitPrice { get; set; }

		[JsonProperty(/*Could not decode attribute arguments.*/)]
		public int? SubPrice { get; set; }
	}
	public class EffectRequestResponse
	{
		public ServerResponse ServerResponse { get; set; }

		public List<EffectPayload> EffectsPayload { get; set; } = new List<EffectPayload>();

		public EffectRequestResponse(ServerResponse serverResponse, List<EffectPayload> effectsPayload)
		{
			ServerResponse = serverResponse;
			EffectsPayload = effectsPayload;
		}
	}
	public enum EffectsAction
	{
		Set,
		Update
	}
	public class PageData
	{
		public string UrlId { get; set; }

		public string AccessToken { get; set; }

		public string PageUrl => PageManager.WebsiteUrl + "/page?id=" + UrlId;

		public PageData(string urlId, string accessToken)
		{
			UrlId = urlId;
			AccessToken = accessToken;
		}
	}
	public record struct PagePayload
	{
		[JsonProperty("username")]
		public string Username { get; set; }

		[JsonProperty("isHost")]
		public bool IsHost { get; set; }

		[JsonProperty("isEnemiesEnabled")]
		public bool IsEnemiesEnabled { get; set; }

		[JsonProperty("isEventsEnabled")]
		public bool IsEventsEnabled { get; set; }

		[JsonProperty("isCheerEnabled")]
		public bool IsCheerEnabled { get; set; }

		[JsonProperty("isSubEnabled")]
		public bool IsSubEnabled { get; set; }

		[JsonProperty("isRaidEnabled")]
		public bool IsRaidEnabled { get; set; }

		[JsonProperty("tier1SubEnemyMultiplier")]
		public int Tier1SubEnemyMultiplier { get; set; }

		[JsonProperty("tier2SubEnemyMultiplier")]
		public int Tier2SubEnemyMultiplier { get; set; }

		[JsonProperty("tier3SubEnemyMultiplier")]
		public int Tier3SubEnemyMultiplier { get; set; }

		[JsonProperty("raidViewersPerEnemy")]
		public int RaidViewersPerEnemy { get; set; }

		[JsonProperty("raidMaxEnemySpawnCount")]
		public int RaidMaxEnemySpawnCount { get; set; }
	}
	public class ServerResponse<T>
	{
		[JsonProperty("success")]
		public bool Success { get; set; }

		[JsonProperty("data")]
		public T Data { get; set; }

		[JsonProperty("error")]
		public string Error { get; set; }

		public static ServerResponse<T> Succeeded()
		{
			return new ServerResponse<T>
			{
				Success = true
			};
		}

		public static ServerResponse<T> Succeeded(T data)
		{
			return new ServerResponse<T>
			{
				Success = true,
				Data = data
			};
		}

		public static ServerResponse<T> Failed(string error)
		{
			return new ServerResponse<T>
			{
				Success = false,
				Error = error
			};
		}
	}
	public class ServerResponse : ServerResponse<JObject>
	{
		public new static ServerResponse Succeeded()
		{
			return new ServerResponse
			{
				Success = true
			};
		}

		public new static ServerResponse Succeeded(JObject data)
		{
			return new ServerResponse
			{
				Success = true,
				Data = data
			};
		}

		public new static ServerResponse Failed(string error)
		{
			return new ServerResponse
			{
				Success = false,
				Error = error
			};
		}
	}
	public class UpdatePageResponse
	{
		public ServerResponse ServerResponse { get; private set; }

		public PagePayload PagePayload { get; private set; }

		public UpdatePageResponse(ServerResponse serverResponse, PagePayload pagePayload)
		{
			ServerResponse = serverResponse;
			PagePayload = pagePayload;
		}
	}
	public class ValidateTwitchChannelResponse
	{
		public bool Success { get; set; }

		public string Error { get; set; }

		public static ValidateTwitchChannelResponse Succeeded()
		{
			return new ValidateTwitchChannelResponse
			{
				Success = true
			};
		}

		public static ValidateTwitchChannelResponse Failed(string error)
		{
			return new ValidateTwitchChannelResponse
			{
				Success = false,
				Error = error
			};
		}
	}
}
namespace com.github.zehsteam.TwitchTrolling.Twitch
{
	internal static class TwitchCheerHandler
	{
		public static bool IsEnemySpawnEnabled
		{
			get
			{
				if (ConfigManager.Enemy_Enabled.Value)
				{
					return EnemyConfigManager.HasEnemies();
				}
				return false;
			}
		}

		public static bool IsEventSpawnEnabled
		{
			get
			{
				if (MEventManager.Enabled)
				{
					return MEventManager.HasEvents();
				}
				return false;
			}
		}

		public static void HandleCheer(TwitchCheerEvent cheerEvent)
		{
			//IL_0034: 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 (!TwitchEventHandler.CanHandleEvents())
			{
				TwitchEventHandler.ShowUnableToHandleEventsMessage();
				return;
			}
			if (!TwitchIntegrationManager.CanPlayEvents())
			{
				TwitchEventQueue.Enqueue(cheerEvent);
				return;
			}
			ViewerData viewerData = new ViewerData(((TwitchEvent)cheerEvent).User);
			int cheerAmount = cheerEvent.CheerAmount;
			if (!IsEnemySpawnEnabled && !IsEventSpawnEnabled)
			{
				MessageManager.Instance?.ShowMessage("Enemy and event spawns are disabled. " + GetAddingAccumulatedBitsMessage(viewerData, cheerAmount));
				TwitchIntegrationManager.AddAccumulatedBits(viewerData, cheerAmount);
				return;
			}
			if (TryGetRandomProductForPrice(cheerAmount, out var product))
			{
				switch (product.Type)
				{
				case ProductType.Enemy:
					HandleEnemySpawn(cheerEvent, viewerData, product.ToEnemyConfigEntry());
					return;
				case ProductType.Event:
					HandleEventSpawn(cheerEvent, viewerData, product.ToMEvent());
					return;
				case ProductType.RandomEnemy:
					HandleRandomEnemySpawn(cheerEvent, viewerData);
					return;
				case ProductType.RandomEvent:
					HandleRandomEventSpawn(cheerEvent, viewerData);
					return;
				}
			}
			if (!IsEnemySpawnEnabled)
			{
				MessageManager.Instance?.ShowMessage("Enemy spawns are disabled. " + GetAddingAccumulatedBitsMessage(viewerData, cheerAmount));
				TwitchIntegrationManager.AddAccumulatedBits(viewerData, cheerAmount);
				return;
			}
			if (!ConfigManager.TwitchCheerEvent_EnableBitsForRandomEnemy.Value)
			{
				MessageManager.Instance?.ShowMessage("Random enemy spawns are disabled. " + GetAddingAccumulatedBitsMessage(viewerData, cheerAmount));
				TwitchIntegrationManager.AddAccumulatedBits(viewerData, cheerAmount);
				return;
			}
			int accumulatedBits = TwitchIntegrationManager.GetAccumulatedBits(viewerData);
			int num = accumulatedBits + cheerAmount;
			int value = ConfigManager.TwitchCheerEvent_BitsForRandomEnemy.Value;
			if (num < value)
			{
				MessageManager.Instance?.ShowMessage(viewerData.GetDisplayNameWithColor() + " didn't cheer enough to spawn anything. " + GetAddingAccumulatedBitsMessage(viewerData, cheerAmount));
				TwitchIntegrationManager.AddAccumulatedBits(viewerData, cheerAmount);
				return;
			}
			int spawnCount = Mathf.FloorToInt((float)(num / value));
			int num2 = num % value;
			int accumulatedBitsUsedAmount = Mathf.Max(accumulatedBits - num2, 0);
			TwitchIntegrationManager.SetAccumulatedBits(viewerData, num2);
			HandleRandomEnemySpawn(cheerEvent, viewerData, spawnCount, accumulatedBitsUsedAmount);
		}

		private static string GetAddingAccumulatedBitsMessage(ViewerData viewer, int addedAmount)
		{
			int accumulatedBits = TwitchIntegrationManager.GetAccumulatedBits(viewer);
			int value = ConfigManager.TwitchCheerEvent_BitsForRandomEnemy.Value;
			return $"Adding {addedAmount} accumulated bits to {viewer.GetDisplayNameWithColor()} ({accumulatedBits + addedAmount}/{value})";
		}

		private static void HandleEnemySpawn(TwitchCheerEvent cheerEvent, ViewerData viewer, EnemyConfigEntry enemyConfigEntry)
		{
			string spawnReason = $"by cheering {cheerEvent.CheerAmount} bits";
			ViewerSpawnData viewerSpawnData = new ViewerSpawnData(viewer, 1, spawnReason, enemyConfigEntry.EnemyName);
			EnemyManager.SpawnEnemy(viewerSpawnData);
		}

		private static void HandleRandomEnemySpawn(TwitchCheerEvent cheerEvent, ViewerData viewer, int spawnCount = 1, int accumulatedBitsUsedAmount = 0)
		{
			string spawnReason;
			if (accumulatedBitsUsedAmount > 0)
			{
				int accumulatedBits = TwitchIntegrationManager.GetAccumulatedBits(viewer);
				spawnReason = $"by cheering {cheerEvent.CheerAmount} bits + {accumulatedBitsUsedAmount} accumulated bits. {accumulatedBits} accumulated bits remaining";
			}
			else
			{
				spawnReason = $"by cheering {cheerEvent.CheerAmount} bits";
			}
			ViewerSpawnData viewerSpawnData = new ViewerSpawnData(viewer, spawnCount, spawnReason);
			EnemyManager.SpawnEnemy(viewerSpawnData);
		}

		private static void HandleEventSpawn(TwitchCheerEvent cheerEvent, ViewerData viewer, MEvent mEvent)
		{
			mEvent.ExecuteEvent(viewer, PlayerAvatar.instance, cheerEvent.CheerAmount);
		}

		private static void HandleRandomEventSpawn(TwitchCheerEvent cheerEvent, ViewerData viewer)
		{
			if (!MEventManager.TryGetRandomEvent(out var mEvent))
			{
				MessageManager.Instance?.ShowMessage("Failed to find random event. " + GetAddingAccumulatedBitsMessage(viewer, cheerEvent.CheerAmount));
			}
			else
			{
				mEvent.ExecuteEvent(viewer, PlayerAvatar.instance, cheerEvent.CheerAmount);
			}
		}

		private static bool TryGetRandomProductForPrice(int value, out Product product)
		{
			List<Product> productsForPrice = GetProductsForPrice(value);
			if (productsForPrice == null || productsForPrice.Count == 0)
			{
				product = default(Product);
				return false;
			}
			product = productsForPrice[Random.Range(0, productsForPrice.Count)];
			return true;
		}

		private static List<Product> GetProductsForPrice(int value)
		{
			List<Product> list = new List<Product>();
			bool value2 = ConfigManager.TwitchCheerEvent_EnableBitsForRandomEnemy.Value;
			int value3 = ConfigManager.TwitchCheerEvent_BitsForRandomEnemy.Value;
			if (value2 && value3 == value)
			{
				list.Add(new Product(ProductType.RandomEnemy));
			}
			foreach (EnemyConfigEntry enabledConfigEntry in EnemyConfigManager.EnabledConfigEntries)
			{
				if (enabledConfigEntry.BitsToSpawn.Value == value)
				{
					list.Add(new Product(enabledConfigEntry));
				}
			}
			bool value4 = ConfigManager.Event_EnableBitsForRandomEvent.Value;
			int value5 = ConfigManager.Event_BitsForRandomEvent.Value;
			if (value4 && value5 == value)
			{
				list.Add(new Product(ProductType.RandomEvent));
			}
			foreach (MEvent enabledEvent in MEventManager.EnabledEvents)
			{
				if (enabledEvent.BitsPrice.Value == value)
				{
					list.Add(new Product(enabledEvent));
				}
			}
			return list;
		}
	}
	internal enum ProductType
	{
		Enemy,
		Event,
		RandomEnemy,
		RandomEvent
	}
	internal struct Product
	{
		public ProductType Type { get; set; }

		public object Data { get; set; }

		public Product(EnemyConfigEntry enemyConfigEntry)
		{
			this = default(Product);
			Type = ProductType.Enemy;
			Data = enemyConfigEntry;
		}

		public Product(MEvent mEvent)
		{
			this = default(Product);
			Type = ProductType.Event;
			Data = mEvent;
		}

		public Product(ProductType type)
		{
			this = default(Product);
			Type = type;
		}

		public EnemyConfigEntry ToEnemyConfigEntry()
		{
			return Data as EnemyConfigEntry;
		}

		public MEvent ToMEvent()
		{
			return Data as MEvent;
		}
	}
	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)
		{
			TwitchCheerHandler.HandleCheer(cheerEvent);
		}

		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;
		}

		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
	{
		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));
		}

		private static IEnumerator PlayQueuedEventsCoroutine(TimeSpan initialDelay)
		{
			Logger.LogInfo("TwitchEventQueue: Started playing queued events.", extended: true);
			Logger.LogInfo($"TwitchEventQueue: Playing queued events after {(float)initialDelay.TotalSeconds} seconds.", extended: true);
			yield return (object)new WaitForSeconds((float)initialDelay.TotalSeconds);
			if (!TwitchEventHandler.CanHandleEvents())
			{
				yield break;
			}
			if (!TwitchIntegrationManager.CanPlayEvents())
			{
				Logger.LogWarning("TwitchEventQueue: Failed to play queued events. You are not allowed to play events at this time.");
				yield break;
			}
			if (!HasQueuedEvents())
			{
				Logger.LogInfo("TwitchEventQueue: No events in the queue to play.", extended: true);
				yield break;
			}
			MessageManager.Instance?.ShowMessage("Playing Twitch events from the queue");
			TimeSpan delayBetweenEvents = TimeSpan.FromSeconds(0.5);
			TwitchCheerEvent result;
			while (TwitchIntegrationManager.IsCheerEventEnabled && CheerQueue.TryDequeue(out result))
			{
				TwitchEventHandler.HandleCheer(result);
				yield return (object)new WaitForSeconds((float)delayBetweenEvents.TotalSeconds);
			}
			TwitchSubEvent result2;
			while (TwitchIntegrationManager.IsSubEventEnabled && SubQueue.TryDequeue(out result2))
			{
				TwitchEventHandler.HandleSub(result2);
				yield return (object)new WaitForSeconds((float)delayBetweenEvents.TotalSeconds);
			}
			TwitchRaidEvent result3;
			while (TwitchIntegrationManager.IsRaidEventEnabled && RaidQueue.TryDequeue(out result3))
			{
				TwitchEventHandler.HandleRaid(result3);
				yield return (object)new WaitForSeconds((float)delayBetweenEvents.TotalSeconds);
			}
			Logger.LogInfo("TwitchEventQueue: Finished plyaing queued events.", extended: true);
			SaveData();
			_playQueuedEventsCoroutine = null;
		}

		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_003d: 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)
			if (PlayerHelper.TryGetLocalPlayer(out var playerAvatar))
			{
				string steamID = playerAvatar.steamID;
				string displayName = SemiFunc.PlayerGetName(playerAvatar);
				string color = "#FFFFFF";
				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.SetEffects();
			}
		}
	}
	[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(NetworkConnect))]
	internal static class NetworkConnect_Patches
	{
		[HarmonyPatch("OnJoinedRoom")]
		[HarmonyPostfix]
		private static void OnJoinedRoom_Patch()
		{
			PageManager.UpdatePage();
		}
	}
	[HarmonyPatch(typeof(NetworkManager))]
	internal static class NetworkManager_Patches
	{
		[HarmonyPatch("LeavePhotonRoom")]
		[HarmonyPostfix]
		private static void LeavePhotonRoom_Patch()
		{
			PageManager.UpdatePage();
		}
	}
	[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).gameObj

BepInEx/plugins/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.Bootstrap;
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.MonoBehaviours;
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 © 2026 Zehs")]
[assembly: AssemblyFileVersion("1.2.0.0")]
[assembly: AssemblyInformationalVersion("1.2.0+93b733fc51d3908dc7613f65dfd81b662bb274ab")]
[assembly: AssemblyProduct("PlayerDamageTracker")]
[assembly: AssemblyTitle("com.github.zehsteam.PlayerDamageTracker")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.2.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
[CompilerGenerated]
internal sealed class <>z__ReadOnlyList<T> : IEnumerable, ICollection, IList, IEnumerable<T>, IReadOnlyCollection<T>, IReadOnlyList<T>, ICollection<T>, IList<T>
{
	int ICollection.Count => _items.Count;

	bool ICollection.IsSynchronized => false;

	object ICollection.SyncRoot => this;

	object IList.this[int index]
	{
		get
		{
			return _items[index];
		}
		set
		{
			throw new NotSupportedException();
		}
	}

	bool IList.IsFixedSize => true;

	bool IList.IsReadOnly => true;

	int IReadOnlyCollection<T>.Count => _items.Count;

	T IReadOnlyList<T>.this[int index] => _items[index];

	int ICollection<T>.Count => _items.Count;

	bool ICollection<T>.IsReadOnly => true;

	T IList<T>.this[int index]
	{
		get
		{
			return _items[index];
		}
		set
		{
			throw new NotSupportedException();
		}
	}

	public <>z__ReadOnlyList(List<T> items)
	{
		_items = items;
	}

	IEnumerator IEnumerable.GetEnumerator()
	{
		return ((IEnumerable)_items).GetEnumerator();
	}

	void ICollection.CopyTo(Array array, int index)
	{
		((ICollection)_items).CopyTo(array, index);
	}

	int IList.Add(object value)
	{
		throw new NotSupportedException();
	}

	void IList.Clear()
	{
		throw new NotSupportedException();
	}

	bool IList.Contains(object value)
	{
		return ((IList)_items).Contains(value);
	}

	int IList.IndexOf(object value)
	{
		return ((IList)_items).IndexOf(value);
	}

	void IList.Insert(int index, object value)
	{
		throw new NotSupportedException();
	}

	void IList.Remove(object value)
	{
		throw new NotSupportedException();
	}

	void IList.RemoveAt(int index)
	{
		throw new NotSupportedException();
	}

	IEnumerator<T> IEnumerable<T>.GetEnumerator()
	{
		return ((IEnumerable<T>)_items).GetEnumerator();
	}

	void ICollection<T>.Add(T item)
	{
		throw new NotSupportedException();
	}

	void ICollection<T>.Clear()
	{
		throw new NotSupportedException();
	}

	bool ICollection<T>.Contains(T item)
	{
		return _items.Contains(item);
	}

	void ICollection<T>.CopyTo(T[] array, int arrayIndex)
	{
		_items.CopyTo(array, arrayIndex);
	}

	bool ICollection<T>.Remove(T item)
	{
		throw new NotSupportedException();
	}

	int IList<T>.IndexOf(T item)
	{
		return _items.IndexOf(item);
	}

	void IList<T>.Insert(int index, T item)
	{
		throw new NotSupportedException();
	}

	void IList<T>.RemoveAt(int index)
	{
		throw new NotSupportedException();
	}
}
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 LogMessage(object data)
		{
			Log((LogLevel)8, 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.2.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!");
			((Object)this).hideFlags = (HideFlags)61;
			Object.DontDestroyOnLoad((Object)(object)this);
			_harmony.PatchAll(typeof(PlayerHealthPatch));
			_harmony.PatchAll(typeof(HurtColliderPatch));
			_harmony.PatchAll(typeof(ParticleScriptExplosionPatch));
			_harmony.PatchAll(typeof(ItemGrenadeDuctTapedPatch));
			PluginHelper.OnStart = (Action)Delegate.Combine(PluginHelper.OnStart, (Action)delegate
			{
				HurtOtherPatcher.PatchAll(_harmony);
			});
			PluginHelper.Spawn();
		}

		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.2.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);
				}
			}
			Logger.LogInfo(text + " Created transpiler!");
			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 int _transpilersCreated;

		private static bool _patched;

		public static int TranspilersCreated => _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);
				}
				LogInfo("Created transpiler for " + method.GetFullName());
				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()
		{
			List<Assembly> list = new List<Assembly>();
			list.Add(typeof(MenuManager).Assembly);
			list.AddRange(DependencyHelper.GetModAssemblies());
			return new <>z__ReadOnlyList<Assembly>(list);
		}

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

		private static bool IsValidClass(Type type)
		{
			try
			{
				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;
			}
			catch (Exception ex)
			{
				LogWarning("Error loading type " + type.FullName + " from assembly " + type.Assembly.FullName + ": " + ex.Message);
				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);
				}
			}
			Logger.LogInfo(text + " Created transpiler!");
			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);
				}
			}
			Logger.LogInfo(logHeader + " Created transpiler!");
			return list.AsEnumerable();
		}
	}
}
namespace com.github.zehsteam.PlayerDamageTracker.MonoBehaviours
{
	internal class PluginHelper : MonoBehaviour
	{
		private static PluginHelper _instance;

		public static Action OnStart;

		public static void Spawn()
		{
			//IL_0026: 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_0034: Expected O, but got Unknown
			if (!((Object)(object)_instance != (Object)null))
			{
				GameObject val = new GameObject("PlayerDamageTracker PluginHelper", new Type[1] { typeof(PluginHelper) })
				{
					hideFlags = (HideFlags)61
				};
				Object.DontDestroyOnLoad((Object)(object)val);
			}
		}

		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()
		{
			OnStart?.Invoke();
		}
	}
}
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
{
	public static class DependencyHelper
	{
		public static IEnumerable<Assembly> GetModAssemblies()
		{
			List<Assembly> list = new List<Assembly>();
			foreach (PluginInfo value in Chainloader.PluginInfos.Values)
			{
				if (value == null || (Object)(object)value.Instance == (Object)null)
				{
					continue;
				}
				try
				{
					Assembly assembly = ((object)value.Instance).GetType().Assembly;
					if (!(assembly == null))
					{
						list.Add(assembly);
					}
				}
				catch (Exception arg)
				{
					Logger.LogError($"Failed to get loaded assembly: {arg}");
				}
			}
			return list;
		}
	}
	internal static class ILHelper
	{
		private static DefaultAssemblyResolver _cachedResolver;

		private static readonly 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.GetFullName());
					return Array.Empty<Instruction>();
				}
				return (IEnumerable<Instruction>)val.Body.Instructions;
			}
			catch (Exception arg)
			{
				Logger.LogWarning(string.Format("[{0}] Exception while processing method {1}: {2}", "ILHelper", method.GetFullName(), 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.GetFullName() + " 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(string.Format("[{0}] Exception while processing coroutine method {1}: {2}", "ILHelper", method.GetFullName(), 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(string.Format("[{0}] Failed to get ModuleDefinition for assembly {1}. {2}", "ILHelper", 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(string.Format("[{0}] Error while processing IL instructions. {1}", "ILHelper", 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 AssemblyExtensions
	{
		public static bool IsLocatedInPluginsFolder(this Assembly assembly)
		{
			if (assembly == null)
			{
				return false;
			}
			if (assembly.IsDynamic)
			{
				return false;
			}
			return assembly.Location.StartsWith(Paths.PluginPath, StringComparison.OrdinalIgnoreCase);
		}

		public static IEnumerable<Type> GetLoadableTypes(this Assembly assembly)
		{
			if (assembly == null)
			{
				return Array.Empty<Type>();
			}
			try
			{
				return assembly.GetTypes();
			}
			catch (ReflectionTypeLoadException ex)
			{
				return ex.Types.Where((Type type) => type != null);
			}
		}
	}
	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, bool hurtByHeal, object caller)
		{
			if ((Object)(object)playerHealth == (Object)null)
			{
				return;
			}
			playerHealth.Hurt(damage, savingGrace, enemyIndex, hurtByHeal);
			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);
			}
		}
	}
	internal static class ReflectionExtensions
	{
		public static string GetFullName(this MethodInfo methodInfo)
		{
			if (methodInfo == null)
			{
				return "Method is null";
			}
			Type declaringType = methodInfo.DeclaringType;
			string name = methodInfo.Name;
			string name2 = declaringType.Name;
			string name3 = declaringType.Assembly.GetName().Name;
			return methodInfo.ReturnType.Name + " " + name + "(), class: " + name2 + ", assembly: " + name3;
		}
	}
	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)
		{
		}
	}
}

BepInEx/plugins/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 © 2026 Zehs")]
[assembly: AssemblyFileVersion("1.1.1.0")]
[assembly: AssemblyInformationalVersion("1.1.1+45627603d3869d4ee4f5fb1b7e7df530461a2c7c")]
[assembly: AssemblyProduct("MetadataUtils")]
[assembly: AssemblyTitle("com.github.zehsteam.MetadataUtils")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.1.1.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 LogMessage(object data)
		{
			Log((LogLevel)8, 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.1")]
	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.1";
	}
}
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)
		{
		}
	}
}