Decompiled source of MonsterHotkeys v2.7.0

com.github.zehsteam.MonsterHotkeys.dll

Decompiled 3 weeks ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using BepinControl;
using ControlValley;
using GameNetcodeStuff;
using HarmonyLib;
using LethalCompanyInputUtils.Api;
using LethalConfig;
using LethalConfig.ConfigItems;
using LethalConfig.ConfigItems.Options;
using Microsoft.CodeAnalysis;
using Mono.Cecil;
using Mono.Cecil.Cil;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using TMPro;
using TwitchChatAPI;
using TwitchChatAPI.Objects;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.AI;
using UnityEngine.InputSystem;
using UnityEngine.UI;
using com.github.zehsteam.MonsterHotkeys.Data;
using com.github.zehsteam.MonsterHotkeys.Dependencies;
using com.github.zehsteam.MonsterHotkeys.Dependencies.CrowdControl;
using com.github.zehsteam.MonsterHotkeys.Dependencies.CrowdControl.Patches;
using com.github.zehsteam.MonsterHotkeys.Enums;
using com.github.zehsteam.MonsterHotkeys.Extensions;
using com.github.zehsteam.MonsterHotkeys.Helpers;
using com.github.zehsteam.MonsterHotkeys.MonoBehaviours;
using com.github.zehsteam.MonsterHotkeys.NetcodePatcher;
using com.github.zehsteam.MonsterHotkeys.Patches;
using com.github.zehsteam.MonsterHotkeys.Twitch;
using com.github.zehsteam.MonsterHotkeys.Twitch.Commands;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("Zehs")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyCopyright("Copyright © 2025 Zehs")]
[assembly: AssemblyDescription("Spawn Monsters and Monster Plushies using Hotkeys or from Twitch Subs, Cheers, and Raids. Supports Modded Monsters. Highly Configurable. (Twitch and CrowdControl Integration)")]
[assembly: AssemblyFileVersion("2.7.0.0")]
[assembly: AssemblyInformationalVersion("2.7.0+2bc0cda330e0e05d74569bf51f81753e37b0a7df")]
[assembly: AssemblyProduct("MonsterHotkeys")]
[assembly: AssemblyTitle("com.github.zehsteam.MonsterHotkeys")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("2.7.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
[module: NetcodePatchedAssembly]
internal class <Module>
{
	static <Module>()
	{
	}
}
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.MonsterHotkeys
{
	internal static class Assets
	{
		public static GameObject NetworkHandlerPrefab { get; private set; }

		public static GameObject MessageCanvasPrefab { get; private set; }

		public static EnemyDataList EnemyDataList { get; private set; }

		public static void Load()
		{
			string directoryName = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
			string text = "monsterhotkeys_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)
		{
			NetworkHandlerPrefab = LoadAsset<GameObject>("NetworkHandler", assetBundle);
			MessageCanvasPrefab = LoadAsset<GameObject>("MonsterHotkeysCanvas", assetBundle);
			EnemyDataList = LoadAsset<EnemyDataList>("EnemyDataList", 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 ConfigManager
	{
		public static ConfigFile ConfigFile { get; private set; }

		public static ConfigEntry<bool> ExtendedLogging { get; private set; }

		public static ConfigEntry<bool> Enemy_OnlyHostSpawnEnemies { get; private set; }

		public static ConfigEntry<bool> Enemy_MuteSpawnSFX { get; private set; }

		public static ConfigEntry<bool> Enemy_SpawnStunned { get; private set; }

		public static ConfigEntry<float> Enemy_StunDuration { get; private set; }

		public static SyncedConfigEntry<int> Plushie_SpawnCount { get; private set; }

		public static SyncedConfigEntry<float> Plushie_DespawnDuration { get; private set; }

		public static ConfigEntry<float> Plushie_SFXVolume { get; private set; }

		public static ConfigEntry<bool> Plushie_PlaySFXOnCollision { get; private set; }

		public static SyncedConfigEntry<bool> Plushie_AttractDogs { get; private set; }

		public static SyncedConfigEntry<float> Plushie_Scale { get; private set; }

		public static ConfigEntry<bool> Message_ShowMessages { get; private set; }

		public static ConfigEntry<bool> Message_ShowSpawnEnemyMessages { get; private set; }

		public static ConfigEntry<bool> Message_ShowLocalSpawnEnemyMessages { get; private set; }

		public static ConfigEntry<bool> Message_ShowDetailedTwitchEventSpawnEnemyMessages { get; private set; }

		public static ConfigEntry<float> Message_Duration { get; private set; }

		public static ConfigEntry<int> Message_FontSize { get; private set; }

		public static ConfigEntry<int> Message_BackgroundTransparency { get; private set; }

		public static ConfigEntry<bool> CrowdControl_Enabled { get; private set; }

		public static ConfigEntry<bool> CrowdControl_RewardSpawnPoints { get; private set; }

		public static ConfigEntry<bool> TwitchIntegration_Enabled { get; private set; }

		public static ConfigEntry<bool> TwitchIntegration_SpawnAllOfTheSameEnemy { get; private set; }

		public static ConfigEntry<bool> TwitchSubEvent_Enabled { get; private set; }

		public static ConfigEntry<int> TwitchSubEvent_EnemiesPerSub { get; private set; }

		public static ConfigEntry<int> TwitchSubEvent_Tier2EnemyMultiplier { get; private set; }

		public static ConfigEntry<int> TwitchSubEvent_Tier3EnemyMultiplier { get; private set; }

		public static ConfigEntry<bool> TwitchCheerEvent_Enabled { get; private set; }

		public static ConfigEntry<int> TwitchCheerEvent_AmountToSpawnEnemy { get; private set; }

		public static ConfigEntry<int> TwitchCheerEvent_AmountToSpawnPlushies { get; private set; }

		public static ConfigEntry<bool> TwitchRaidEvent_Enabled { get; private set; }

		public static ConfigEntry<int> TwitchRaidEvent_ViewersPerEnemy { get; private set; }

		public static ConfigEntry<int> TwitchRaidEvent_MaxSpawnCount { get; private set; }

		public static ConfigEntry<bool> SpawnPoints_Enabled { get; private set; }

		public static ConfigEntry<int> SpawnPoints_MaxSpawnsPerDay { get; private set; }

		public static ConfigEntry<int> SpawnPoints_RewardPointsPerDeath { get; private set; }

		public static ConfigEntry<int> SpawnPoints_RewardPointsPerCrewmateDeath { get; private set; }

		public static ConfigEntry<bool> TwitchCommandGiveSpawnRandom_ExcludeBroadcaster { get; private set; }

		public static ConfigEntry<bool> TwitchCommandGiveSpawnRandom_ExcludeExecutingUser { get; private set; }

		public static ConfigEntry<string> TwitchCommandGiveSpawnRandom_ExcludeUsersList { get; private set; }

		public static ConfigEntry<bool> EnemyNametag_Enabled { get; private set; }

		public static ConfigEntry<bool> EnemyNametag_ShowPlatform { get; private set; }

		public static ConfigEntry<float> EnemyNametag_ScaleMultiplier { get; private set; }

		public static ConfigEntry<int> EnemyNametag_BackgroundTransparency { get; private set; }

		public static void Initialize(ConfigFile configFile)
		{
			ConfigFile = configFile;
			BindConfigs();
			MigrateOldConfigEntries();
		}

		private static void BindConfigs()
		{
			ConfigHelper.SkipAutoGen();
			ExtendedLogging = ConfigHelper.Bind("- General -", "ExtendedLogging", defaultValue: false, "Enable extended logging.");
			Enemy_OnlyHostSpawnEnemies = ConfigHelper.Bind("- Enemy -", "OnlyHostSpawnEnemies", defaultValue: false, "If enabled, only the host can spawn enemies.");
			Enemy_MuteSpawnSFX = ConfigHelper.Bind("- Enemy -", "MuteSpawnSFX", defaultValue: false, "If enabled, the enemy spawn sfx will not play.");
			Enemy_SpawnStunned = ConfigHelper.Bind("- Enemy -", "SpawnStunned", defaultValue: false, "If enabled, spawned enemies will be stunned for StunDuration seconds.");
			Enemy_StunDuration = ConfigHelper.Bind("- Enemy -", "StunDuration", 6f, "The duration enemies will be stunned for in seconds.");
			Enemy_MuteSpawnSFX.SettingChanged += AudioPlayerManager.OnSettingsChanged;
			Plushie_SpawnCount = ConfigHelper.BindSynced("- Plushie -", "SpawnCount", 30, "The amount of plushies to spawn.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100));
			Plushie_DespawnDuration = ConfigHelper.BindSynced("- Plushie -", "DespawnDuration", 15f, "The duration in seconds until a plushie gets despawned.");
			Plushie_SFXVolume = ConfigHelper.Bind("- Plushie -", "SFXVolume", 25f, "The volume of the plushie's squeak sound effect.", requiresRestart: false, (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f));
			Plushie_PlaySFXOnCollision = ConfigHelper.Bind("- Plushie -", "PlaySFXOnCollision", defaultValue: true, "If enabled, the plushies will play a sound effect when colliding with the environment.");
			Plushie_AttractDogs = ConfigHelper.BindSynced("- Plushie -", "AttractDogs", defaultValue: true, "If enabled, the plushies will attract dogs when making noise.");
			Plushie_Scale = ConfigHelper.BindSynced("- Plushie -", "Scale", 4f, "The size of the plushies.");
			Message_ShowMessages = ConfigHelper.Bind("- Message -", "ShowMessages", defaultValue: true, "If enabled, will show messages in the bottom right.");
			Message_ShowSpawnEnemyMessages = ConfigHelper.Bind("- Message -", "ShowSpawnEnemyMessages", defaultValue: true, "If enabled, will show a message when someone else spawns an enemy.");
			Message_ShowLocalSpawnEnemyMessages = ConfigHelper.Bind("- Message -", "ShowLocalSpawnEnemyMessages", defaultValue: true, "If enabled, will show a message when you spawn an enemy.");
			Message_ShowDetailedTwitchEventSpawnEnemyMessages = ConfigHelper.Bind("- Message -", "ShowDetailedTwitchEventSpawnEnemyMessages", defaultValue: true, "If enabled, will show a detailed Twitch event spawn enemy messages.");
			Message_Duration = ConfigHelper.Bind("- Message -", "Duration", 8f, "The duration of a message in seconds.");
			Message_FontSize = ConfigHelper.Bind("- Message -", "FontSize", 25, "The font size of the messages.");
			Message_BackgroundTransparency = ConfigHelper.Bind("- Message -", "BackgroundTransparency", 192, "The transparency of the message background.", requiresRestart: false, (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 255));
			Message_FontSize.SettingChanged += MessageItem.OnSettingsChanged;
			Message_BackgroundTransparency.SettingChanged += MessageItem.OnSettingsChanged;
			CrowdControl_Enabled = ConfigHelper.Bind("- Crowd Control Integration -", "Enabled", defaultValue: true, "If enabled, Crowd Control will be able to spawn enemies anywhere and spawned enemies will have a nametag with the name of the viewer that spawned that enemy.");
			CrowdControl_RewardSpawnPoints = ConfigHelper.Bind("- Crowd Control Integration -", "RewardSpawnPoints", defaultValue: true, "If you die to an enemy spawned by a viewer, they will gain a spawn point to spawn a free enemy by writing !spawn in your Twitch chat. (Requries Spawn Points to be enabled, Twitch Integration to be enabled, and the TwitchChatAPI mod)");
			TwitchIntegration_Enabled = ConfigHelper.Bind("- Twitch Integration -", "Enabled", defaultValue: true, "If enabled, Twitch integration will be enabled to spawn enemies from Subs, Cheers, and Raids. (Requires the TwitchChatAPI mod)");
			TwitchIntegration_SpawnAllOfTheSameEnemy = ConfigHelper.Bind("- Twitch Integration -", "SpawnAllOfTheSameEnemy", defaultValue: false, "If enabled, when spawning multiple enemies from a single event, all enemies spawned will be of the same type.");
			TwitchSubEvent_Enabled = ConfigHelper.Bind("- Twitch Sub Event -", "Enabled", defaultValue: true, "If enabled, Twitch subs will be able to spawn enemies. (Requires Twitch Integration to be enabled and the TwitchChatAPI mod)");
			TwitchSubEvent_EnemiesPerSub = ConfigHelper.Bind("- Twitch Sub Event -", "EnemiesPerSub", 1, "The amount of enemies that will spawn per sub.");
			TwitchSubEvent_Tier2EnemyMultiplier = ConfigHelper.Bind("- Twitch Sub Event -", "Tier2EnemyMultiplier", 3, "The amount to multiply the enemy spawn count for tier 2 subs.");
			TwitchSubEvent_Tier3EnemyMultiplier = ConfigHelper.Bind("- Twitch Sub Event -", "Tier3EnemyMultiplier", 6, "The amount to multiply the enemy spawn count for tier 3 subs.");
			TwitchCheerEvent_Enabled = ConfigHelper.Bind("- Twitch Cheer Event -", "Enabled", defaultValue: true, "If enabled, Twitch cheers will be able to spawn enemies. (Requires Twitch Integration to be enabled and the TwitchChatAPI mod)");
			TwitchCheerEvent_AmountToSpawnEnemy = ConfigHelper.Bind("- Twitch Cheer Event -", "AmountToSpawnEnemy", 350, "The amount of bits to spawn an enemy.");
			TwitchCheerEvent_AmountToSpawnPlushies = ConfigHelper.Bind("- Twitch Cheer Event -", "AmountToSpawnPlushies", 100, "The amount of bits to spawn plushies that create noise and block your view.");
			TwitchRaidEvent_Enabled = ConfigHelper.Bind("- Twitch Raid Event -", "Enabled", defaultValue: true, "If enabled, Twitch raids will be able to spawn enemies. (Requires Twitch Integration to be enabled and the TwitchChatAPI mod)");
			TwitchRaidEvent_ViewersPerEnemy = ConfigHelper.Bind("- Twitch Raid Event -", "ViewersPerEnemy", 5, "The amount of viewers for each enemy spawn.");
			TwitchRaidEvent_MaxSpawnCount = ConfigHelper.Bind("- Twitch Raid Event -", "MaxSpawnCount", 20, "The max amount of enemies that can spawn.");
			SpawnPoints_Enabled = ConfigHelper.Bind("- Spawn Points -", "Enabled", defaultValue: true, "If you die to an enemy spawned by a viewer, they will gain a spawn point to spawn a free enemy by writing !spawn in your Twitch chat. (Requires Twitch Integration to be enabled and the TwitchChatAPI mod)");
			SpawnPoints_MaxSpawnsPerDay = ConfigHelper.Bind("- Spawn Points -", "MaxSpawnsPerDay", 100, "The max amount of spawn points that can be redeemed per in-game day.");
			SpawnPoints_RewardPointsPerDeath = ConfigHelper.Bind("- Spawn Points -", "RewardPointsPerDeath", 1, "The amount of spawn points a viewer will receive from your death.");
			SpawnPoints_RewardPointsPerCrewmateDeath = ConfigHelper.Bind("- Spawn Points -", "RewardPointsPerCrewmateDeath", 0, "The amount of spawn points a viewer will receive from a crewmate's death.");
			ConfigHelper.AddButton("- Spawn Points -", "Reset all spawn points", "Reset", "Reset all viewers spawn points.", TwitchIntegrationManager.ResetAllSpawnPoints);
			TwitchCommandGiveSpawnRandom_ExcludeBroadcaster = ConfigHelper.Bind("- Twitch Command !givespawnrandom -", "ExcludeBroadcaster", defaultValue: true, "If enabled, the !givespawnrandom command will exclude the broadcaster from winning.");
			TwitchCommandGiveSpawnRandom_ExcludeExecutingUser = ConfigHelper.Bind("- Twitch Command !givespawnrandom -", "ExcludeExecutingUser", defaultValue: true, "If enabled, the !givespawnrandom command will exclude the user that wrote the command from winning.");
			TwitchCommandGiveSpawnRandom_ExcludeUsersList = ConfigHelper.Bind("- Twitch Command !givespawnrandom -", "ExcludeUsersList", "", "The list of Twitch users to exclude from winning the !givespawnrandom command.");
			EnemyNametag_Enabled = ConfigHelper.Bind("- Enemy Nametag -", "Enabled", defaultValue: true, "If enabled, enemies will spawn with a nametag of the viewer that spawned that enemy.");
			EnemyNametag_ShowPlatform = ConfigHelper.Bind("- Enemy Nametag -", "ShowPlatform", defaultValue: true, "If enabled, nametags will show which platform the enemy was spawned from.");
			EnemyNametag_ScaleMultiplier = ConfigHelper.Bind("- Enemy Nametag -", "ScaleMultiplier", 1f, "The scale multiplier for enemy nametags.", requiresRestart: false, (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.25f, 5f));
			EnemyNametag_BackgroundTransparency = ConfigHelper.Bind("- Enemy Nametag -", "BackgroundTransparency", 192, "The transparency of the nametag background.", requiresRestart: false, (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 255));
			EnemyNametag_ScaleMultiplier.SettingChanged += EnemyNametag.OnSettingsChanged;
			EnemyNametag_ShowPlatform.SettingChanged += EnemyNametag.OnSettingsChanged;
			EnemyNametag_BackgroundTransparency.SettingChanged += EnemyNametag.OnSettingsChanged;
		}

		private static void MigrateOldConfigEntries()
		{
			ConfigSectionMigration[] migrations = new ConfigSectionMigration[12]
			{
				new ConfigSectionMigration("General", "- General -"),
				new ConfigSectionMigration("Enemy", "- Enemy -"),
				new ConfigSectionMigration("Plushie", "- Plushie -"),
				new ConfigSectionMigration("Message", "- Message -"),
				new ConfigSectionMigration("Crowd Control Integration", "- Crowd Control Integration -"),
				new ConfigSectionMigration("Twitch Integration", "- Twitch Integration -"),
				new ConfigSectionMigration("Twitch Sub Event", "- Twitch Sub Event -"),
				new ConfigSectionMigration("Twitch Cheer Event", "- Twitch Cheer Event -"),
				new ConfigSectionMigration("Twitch Raid Event", "- Twitch Raid Event -"),
				new ConfigSectionMigration("Spawn Points", "- Spawn Points -"),
				new ConfigSectionMigration("Twitch Command !givespawnrandom", "- Twitch Command !givespawnrandom -"),
				new ConfigSectionMigration("Enemy Nametag", "- Enemy Nametag -")
			};
			ConfigFile.MigrateConfigEntries(migrations);
		}
	}
	internal class HotkeyInputClass : LcInputActions
	{
		[InputAction(/*Could not decode attribute arguments.*/)]
		public InputAction MonsterPrefixKey { get; set; }

		[InputAction(/*Could not decode attribute arguments.*/)]
		public InputAction PlushiePrefixKey { get; set; }

		[InputAction(/*Could not decode attribute arguments.*/)]
		public InputAction SpawnRandomKey { get; set; }

		[InputAction(/*Could not decode attribute arguments.*/)]
		public InputAction SpawnBaboonHawkKey { get; set; }

		[InputAction(/*Could not decode attribute arguments.*/)]
		public InputAction SpawnBarberKey { get; set; }

		[InputAction(/*Could not decode attribute arguments.*/)]
		public InputAction SpawnBlobKey { get; set; }

		[InputAction(/*Could not decode attribute arguments.*/)]
		public InputAction SpawnBrackenKey { get; set; }

		[InputAction(/*Could not decode attribute arguments.*/)]
		public InputAction SpawnBunkerSpiderKey { get; set; }

		[InputAction(/*Could not decode attribute arguments.*/)]
		public InputAction SpawnButlerKey { get; set; }

		[InputAction(/*Could not decode attribute arguments.*/)]
		public InputAction SpawnCoilHeadKey { get; set; }

		[InputAction(/*Could not decode attribute arguments.*/)]
		public InputAction SpawnEarthLeviathanKey { get; set; }

		[InputAction(/*Could not decode attribute arguments.*/)]
		public InputAction SpawnEyelessDogKey { get; set; }

		[InputAction(/*Could not decode attribute arguments.*/)]
		public InputAction SpawnForestGiantKey { get; set; }

		[InputAction(/*Could not decode attribute arguments.*/)]
		public InputAction SpawnGhostGirlKey { get; set; }

		[InputAction(/*Could not decode attribute arguments.*/)]
		public InputAction SpawnHoardingBugKey { get; set; }

		[InputAction(/*Could not decode attribute arguments.*/)]
		public InputAction SpawnJesterKey { get; set; }

		[InputAction(/*Could not decode attribute arguments.*/)]
		public InputAction SpawnKidnapperFoxKey { get; set; }

		[InputAction(/*Could not decode attribute arguments.*/)]
		public InputAction SpawnManeaterKey { get; set; }

		[InputAction(/*Could not decode attribute arguments.*/)]
		public InputAction SpawnManticoilKey { get; set; }

		[InputAction(/*Could not decode attribute arguments.*/)]
		public InputAction SpawnMaskedKey { get; set; }

		[InputAction(/*Could not decode attribute arguments.*/)]
		public InputAction SpawnNutcrackerKey { get; set; }

		[InputAction(/*Could not decode attribute arguments.*/)]
		public InputAction SpawnOldBirdKey { get; set; }

		[InputAction(/*Could not decode attribute arguments.*/)]
		public InputAction SpawnSnareFleaKey { get; set; }

		[InputAction(/*Could not decode attribute arguments.*/)]
		public InputAction SpawnSporeLizardKey { get; set; }

		[InputAction(/*Could not decode attribute arguments.*/)]
		public InputAction SpawnThumperKey { get; set; }

		[InputAction(/*Could not decode attribute arguments.*/)]
		public InputAction SpawnTulipSnakeKey { get; set; }
	}
	public static class HotkeyListener
	{
		public static bool DisableHotkeys;

		public static bool IsMonsterPrefixKeyPressed => Plugin.InputActionsInstance.MonsterPrefixKey.IsPressed();

		public static bool IsPlushiePrefixKeyPressed => Plugin.InputActionsInstance.PlushiePrefixKey.IsPressed();

		internal static void SetupKeybindCallbacks()
		{
			Plugin.InputActionsInstance.SpawnRandomKey.performed += OnSpawnRandomKeyPressed;
			Plugin.InputActionsInstance.SpawnBaboonHawkKey.performed += OnSpawnKeyPressed;
			Plugin.InputActionsInstance.SpawnBarberKey.performed += OnSpawnKeyPressed;
			Plugin.InputActionsInstance.SpawnBlobKey.performed += OnSpawnKeyPressed;
			Plugin.InputActionsInstance.SpawnBrackenKey.performed += OnSpawnKeyPressed;
			Plugin.InputActionsInstance.SpawnBunkerSpiderKey.performed += OnSpawnKeyPressed;
			Plugin.InputActionsInstance.SpawnButlerKey.performed += OnSpawnKeyPressed;
			Plugin.InputActionsInstance.SpawnCoilHeadKey.performed += OnSpawnKeyPressed;
			Plugin.InputActionsInstance.SpawnEarthLeviathanKey.performed += OnSpawnKeyPressed;
			Plugin.InputActionsInstance.SpawnEyelessDogKey.performed += OnSpawnKeyPressed;
			Plugin.InputActionsInstance.SpawnForestGiantKey.performed += OnSpawnKeyPressed;
			Plugin.InputActionsInstance.SpawnGhostGirlKey.performed += OnSpawnKeyPressed;
			Plugin.InputActionsInstance.SpawnHoardingBugKey.performed += OnSpawnKeyPressed;
			Plugin.InputActionsInstance.SpawnJesterKey.performed += OnSpawnKeyPressed;
			Plugin.InputActionsInstance.SpawnKidnapperFoxKey.performed += OnSpawnKeyPressed;
			Plugin.InputActionsInstance.SpawnManeaterKey.performed += OnSpawnKeyPressed;
			Plugin.InputActionsInstance.SpawnManticoilKey.performed += OnSpawnKeyPressed;
			Plugin.InputActionsInstance.SpawnMaskedKey.performed += OnSpawnKeyPressed;
			Plugin.InputActionsInstance.SpawnNutcrackerKey.performed += OnSpawnKeyPressed;
			Plugin.InputActionsInstance.SpawnOldBirdKey.performed += OnSpawnKeyPressed;
			Plugin.InputActionsInstance.SpawnSnareFleaKey.performed += OnSpawnKeyPressed;
			Plugin.InputActionsInstance.SpawnSporeLizardKey.performed += OnSpawnKeyPressed;
			Plugin.InputActionsInstance.SpawnThumperKey.performed += OnSpawnKeyPressed;
			Plugin.InputActionsInstance.SpawnTulipSnakeKey.performed += OnSpawnKeyPressed;
			Logger.LogInfo("Setup keybind callbacks.");
		}

		private static void OnSpawnKeyPressed(CallbackContext context)
		{
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			if (!((CallbackContext)(ref context)).performed)
			{
				return;
			}
			string name = ((CallbackContext)(ref context)).action.name;
			Logger.LogInfo(name + " key pressed.", extended: true);
			if (!Utils.CanPerformHotkeys())
			{
				return;
			}
			if (DisableHotkeys && (IsMonsterPrefixKeyPressed || IsPlushiePrefixKeyPressed))
			{
				MessageCanvas.Instance.ShowMessage_LocalClient("Hotkeys have been disabled by another mod", Color.red);
				Logger.LogInfo("Hotkeys have been disabled by another mod.");
				return;
			}
			string text = name.Replace("Spawn", "").Replace("Key", "");
			switch (text)
			{
			case "BaboonHawk":
				text = "Baboon hawk";
				break;
			case "BunkerSpider":
				text = "Bunker Spider";
				break;
			case "Bracken":
				text = "Flowerman";
				break;
			case "CoilHead":
				text = "Spring";
				break;
			case "EarthLeviathan":
				text = "Earth Leviathan";
				break;
			case "EyelessDog":
				text = "MouthDog";
				break;
			case "GhostGirl":
				text = "Girl";
				break;
			case "HoardingBug":
				text = "Hoarding bug";
				break;
			case "OldBird":
				text = "RadMech";
				break;
			case "SnareFlea":
				text = "Centipede";
				break;
			case "SporeLizard":
				text = "Puffer";
				break;
			case "Thumper":
				text = "Crawler";
				break;
			case "TulipSnake":
				text = "Tulip Snake";
				break;
			case "KidnapperFox":
				text = "Bush Wolf";
				break;
			case "Barber":
				text = "Clay Surgeon";
				break;
			}
			EnemyData byEnemyName = Assets.EnemyDataList.GetByEnemyName(text);
			if (byEnemyName == null)
			{
				Logger.LogError("Failed to find EnemyData from key name \"" + name + "\".");
				return;
			}
			if (Plugin.InputActionsInstance.MonsterPrefixKey.IsPressed())
			{
				EnemyHelper.SpawnEnemy(byEnemyName);
			}
			if (Plugin.InputActionsInstance.PlushiePrefixKey.IsPressed())
			{
				PlushieManager.Instance.SpawnPlushies(byEnemyName.EnemyName);
			}
		}

		private static void OnSpawnRandomKeyPressed(CallbackContext context)
		{
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			if (!((CallbackContext)(ref context)).performed)
			{
				return;
			}
			Logger.LogInfo(((CallbackContext)(ref context)).action.name + " key pressed.", extended: true);
			if (!Utils.CanPerformHotkeys())
			{
				return;
			}
			if (DisableHotkeys && (IsMonsterPrefixKeyPressed || IsPlushiePrefixKeyPressed))
			{
				MessageCanvas.Instance.ShowMessage_LocalClient("Hotkeys have been disabled by another mod", Color.red);
				Logger.LogInfo("Hotkeys have been disabled by another mod.");
				return;
			}
			if (IsMonsterPrefixKeyPressed)
			{
				EnemyHelper.SpawnRandomEnemy();
			}
			if (IsPlushiePrefixKeyPressed)
			{
				PlushieManager.Instance.SpawnRandomPlushies();
			}
		}
	}
	internal static class Logger
	{
		public static ManualLogSource ManualLogSource { get; private set; }

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

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

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

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

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

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

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

		public static bool IsExtendedLoggingEnabled()
		{
			if (ConfigManager.ExtendedLogging == null)
			{
				return false;
			}
			return ConfigManager.ExtendedLogging.Value;
		}
	}
	internal static class NetworkUtils
	{
		public static bool IsConnected
		{
			get
			{
				if ((Object)(object)NetworkManager.Singleton == (Object)null)
				{
					return false;
				}
				return NetworkManager.Singleton.IsConnectedClient;
			}
		}

		public static bool IsServer
		{
			get
			{
				if ((Object)(object)NetworkManager.Singleton == (Object)null)
				{
					return false;
				}
				return NetworkManager.Singleton.IsServer;
			}
		}

		public static bool IsHost
		{
			get
			{
				if ((Object)(object)NetworkManager.Singleton == (Object)null)
				{
					return false;
				}
				return NetworkManager.Singleton.IsHost;
			}
		}

		public static ulong GetLocalClientId()
		{
			return NetworkManager.Singleton.LocalClientId;
		}

		public static bool IsLocalClientId(ulong clientId)
		{
			return clientId == GetLocalClientId();
		}

		public static bool IsNetworkPrefab(GameObject prefab)
		{
			foreach (NetworkPrefab prefab2 in NetworkManager.Singleton.NetworkConfig.Prefabs.Prefabs)
			{
				if ((Object)(object)prefab2.Prefab == (Object)(object)prefab)
				{
					return true;
				}
			}
			return false;
		}
	}
	internal static class PlayerUtils
	{
		public static PlayerControllerB GetLocalPlayerScript()
		{
			if ((Object)(object)GameNetworkManager.Instance == (Object)null)
			{
				return null;
			}
			return GameNetworkManager.Instance.localPlayerController;
		}

		public static bool IsLocalPlayer(PlayerControllerB playerScript)
		{
			return (Object)(object)playerScript == (Object)(object)GetLocalPlayerScript();
		}

		public static PlayerControllerB GetPlayerScriptByClientId(ulong clientId)
		{
			PlayerControllerB[] allPlayerScripts = StartOfRound.Instance.allPlayerScripts;
			foreach (PlayerControllerB val in allPlayerScripts)
			{
				if (!((Object)(object)val == (Object)null) && val.actualClientId == clientId)
				{
					return val;
				}
			}
			return null;
		}

		public static List<PlayerControllerB> GetPlayerScripts()
		{
			List<PlayerControllerB> list = new List<PlayerControllerB>();
			PlayerControllerB[] allPlayerScripts = StartOfRound.Instance.allPlayerScripts;
			foreach (PlayerControllerB val in allPlayerScripts)
			{
				if (!((Object)(object)val == (Object)null) && (val.isInHangarShipRoom || val.isInsideFactory || val.isInElevator))
				{
					list.Add(val);
				}
			}
			return list;
		}

		public static PlayerControllerB GetRandomPlayerScript(bool onlyAlivePlayers = true, bool excludeLocalPlayer = false)
		{
			List<PlayerControllerB> list = new List<PlayerControllerB>();
			foreach (PlayerControllerB playerScript in GetPlayerScripts())
			{
				if ((!onlyAlivePlayers || !playerScript.isPlayerDead) && (!excludeLocalPlayer || !IsLocalPlayer(playerScript)))
				{
					list.Add(playerScript);
				}
			}
			if (list.Count == 0)
			{
				return null;
			}
			return list[Random.Range(0, list.Count)];
		}
	}
	[BepInPlugin("com.github.zehsteam.MonsterHotkeys", "MonsterHotkeys", "2.7.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.MonsterHotkeys");

		internal static Plugin Instance { get; private set; }

		internal static HotkeyInputClass InputActionsInstance { 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.MonsterHotkeys"));
			Logger.LogInfo("MonsterHotkeys has awoken!");
			_harmony.PatchAll(typeof(GameNetworkManagerPatch));
			_harmony.PatchAll(typeof(StartOfRoundPatch));
			_harmony.PatchAll(typeof(RoundManagerPatch));
			_harmony.PatchAll(typeof(HUDManagerPatch));
			_harmony.PatchAll(typeof(EnemyAIPatch));
			_harmony.PatchAll(typeof(RadMechAIPatch));
			_harmony.PatchAll(typeof(ButlerEnemyAIPatch));
			_harmony.PatchAll(typeof(LandminePatch));
			if (CrowdControlProxy.Enabled)
			{
				CrowdControlProxy.PatchAll(_harmony);
			}
			GlobalSave = new JsonSave(Utils.GetPluginPersistentDataPath(), "GlobalSave");
			LocalSave = new JsonSave(Paths.ConfigPath, "MonsterHotkeys_Save.json");
			((Object)this).hideFlags = (HideFlags)61;
			Object.DontDestroyOnLoad((Object)(object)this);
			Assets.Load();
			ConfigManager.Initialize(((BaseUnityPlugin)this).Config);
			InputActionsInstance = new HotkeyInputClass();
			HotkeyListener.SetupKeybindCallbacks();
			Assets.EnemyDataList.Initialize();
			TwitchIntegrationManager.Initialize();
			NetcodePatcherAwake();
		}

		private void Start()
		{
			PlayerDamagePatcher.PatchAll(_harmony);
		}

		private void NetcodePatcherAwake()
		{
			try
			{
				Assembly executingAssembly = Assembly.GetExecutingAssembly();
				Type[] types = executingAssembly.GetTypes();
				Type[] array = types;
				foreach (Type type in array)
				{
					MethodInfo[] methods = type.GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic);
					MethodInfo[] array2 = methods;
					foreach (MethodInfo methodInfo in array2)
					{
						try
						{
							object[] customAttributes = methodInfo.GetCustomAttributes(typeof(RuntimeInitializeOnLoadMethodAttribute), inherit: false);
							if (customAttributes.Length != 0)
							{
								try
								{
									methodInfo.Invoke(null, null);
								}
								catch (TargetInvocationException ex)
								{
									((BaseUnityPlugin)this).Logger.LogWarning((object)("Failed to invoke method " + methodInfo.Name + ": " + ex.Message));
								}
							}
						}
						catch (Exception ex2)
						{
							((BaseUnityPlugin)this).Logger.LogWarning((object)("Error processing method " + methodInfo.Name + " in type " + type.Name + ": " + ex2.Message));
						}
					}
				}
			}
			catch (Exception ex3)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)("An error occurred in NetcodePatcherAwake: " + ex3.Message));
			}
		}

		public void OnNewLevelLoaded()
		{
			EnemyNametagManager.Instance?.Reset();
		}
	}
	internal static class Utils
	{
		public static string GetPluginPersistentDataPath()
		{
			return Path.Combine(Application.persistentDataPath, "MonsterHotkeys");
		}

		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 void LogStackTrace()
		{
			StackTrace stackTrace = new StackTrace();
			for (int i = 1; i < stackTrace.FrameCount; i++)
			{
				StackFrame frame = stackTrace.GetFrame(i);
				MethodBase method = frame.GetMethod();
				Type declaringType = method.DeclaringType;
				string name = method.Name;
				Logger.LogInfo($"Call stack depth {i}: {declaringType}.{name}", extended: true);
			}
		}

		public static bool RandomPercent(float percent)
		{
			if (percent <= 0f)
			{
				return false;
			}
			if (percent >= 100f)
			{
				return true;
			}
			return Random.value * 100f <= percent;
		}

		public static string GetFormattedString(string text)
		{
			if (string.IsNullOrWhiteSpace(text))
			{
				return string.Empty;
			}
			return string.Join(" ", from word in text.Split(' ', StringSplitOptions.RemoveEmptyEntries)
				select $"{char.ToUpper(word[0])}{word.Substring(1).ToLower()}");
		}

		public static bool CanPerformHotkeys()
		{
			PlayerControllerB localPlayerScript = PlayerUtils.GetLocalPlayerScript();
			if ((Object)(object)localPlayerScript == (Object)null)
			{
				return false;
			}
			if (localPlayerScript.isPlayerDead)
			{
				return false;
			}
			if (localPlayerScript.isTypingChat)
			{
				return false;
			}
			if (localPlayerScript.quickMenuManager.isMenuOpen)
			{
				return false;
			}
			return true;
		}

		public static Coroutine StartCoroutine(IEnumerator routine)
		{
			if ((Object)(object)Plugin.Instance != (Object)null)
			{
				return ((MonoBehaviour)Plugin.Instance).StartCoroutine(routine);
			}
			if ((Object)(object)GameNetworkManager.Instance != (Object)null)
			{
				return ((MonoBehaviour)GameNetworkManager.Instance).StartCoroutine(routine);
			}
			Logger.LogError("Failed to start coroutine. " + routine);
			return null;
		}

		public static bool TryParseValue<T>(string value, out T result)
		{
			try
			{
				if (typeof(T) == typeof(int) && int.TryParse(value, out var result2))
				{
					result = (T)(object)result2;
					return true;
				}
				if (typeof(T) == typeof(float) && float.TryParse(value, out var result3))
				{
					result = (T)(object)result3;
					return true;
				}
				if (typeof(T) == typeof(double) && double.TryParse(value, out var result4))
				{
					result = (T)(object)result4;
					return true;
				}
				if (typeof(T) == typeof(bool) && bool.TryParse(value, out var result5))
				{
					result = (T)(object)result5;
					return true;
				}
				if (typeof(T) == typeof(string))
				{
					result = (T)(object)value;
					return true;
				}
			}
			catch
			{
			}
			result = default(T);
			return false;
		}

		public static string GetFormattedKeyValuePairMessage<T>(Dictionary<string, T> keyValuePair, int columns, string format, string separator = " ")
		{
			if (keyValuePair == null || keyValuePair.Count == 0)
			{
				return string.Empty;
			}
			int num = Mathf.CeilToInt((float)keyValuePair.Count / (float)columns);
			List<List<KeyValuePair<string, T>>> list = new List<List<KeyValuePair<string, T>>>();
			for (int i = 0; i < columns; i++)
			{
				list.Add(keyValuePair.Skip(i * num).Take(num).ToList());
			}
			List<int> list2 = list.Select((List<KeyValuePair<string, T>> column) => column.Any() ? column.Max((KeyValuePair<string, T> item) => item.Key.Length) : 0).ToList();
			List<int> list3 = list.Select((List<KeyValuePair<string, T>> column) => column.Any() ? column.Max((KeyValuePair<string, T> item) => item.Value.ToString().Length) : 0).ToList();
			StringBuilder stringBuilder = new StringBuilder();
			for (int j = 0; j < num; j++)
			{
				for (int k = 0; k < columns; k++)
				{
					if (k < list.Count && j < list[k].Count)
					{
						KeyValuePair<string, T> keyValuePair2 = list[k][j];
						string newValue = keyValuePair2.Key.PadRight(list2[k]);
						string newValue2 = keyValuePair2.Value.ToString().PadRight(list3[k]);
						string value = format.Replace("{key}", newValue).Replace("{value}", newValue2);
						stringBuilder.Append(value);
						if (k < columns - 1)
						{
							stringBuilder.Append(" | ");
						}
					}
				}
				stringBuilder.AppendLine();
			}
			return stringBuilder.ToString().TrimEnd();
		}

		public static bool IsChildOfComponent<T>(Transform transform, out T component) where T : Component
		{
			component = default(T);
			if ((Object)(object)transform == (Object)null || (Object)(object)transform.parent == (Object)null)
			{
				return false;
			}
			if (((Component)transform.parent).TryGetComponent<T>(ref component))
			{
				return true;
			}
			return IsChildOfComponent<T>(transform.parent, out component);
		}

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

		public static IEnumerable<T> StringToCollection<T>(string value)
		{
			if (string.IsNullOrEmpty(value))
			{
				return Enumerable.Empty<T>();
			}
			T result;
			return from x in value.Split(',', StringSplitOptions.RemoveEmptyEntries)
				where !string.IsNullOrWhiteSpace(x)
				select x.Trim() into x
				select (!TryConvertStringToType<T>(x, out result)) ? default(T) : result into x
				where x != null
				select x;
		}

		public static string CollectionToString<T>(IEnumerable<T> value)
		{
			if (value == null || !value.Any())
			{
				return string.Empty;
			}
			return string.Join(", ", from x in value
				where x != null && !string.IsNullOrWhiteSpace(x.ToString())
				select x.ToString().Trim());
		}

		public static bool TryConvertStringToType<T>(string value, out T result)
		{
			if (string.IsNullOrWhiteSpace(value))
			{
				result = default(T);
				return false;
			}
			try
			{
				Type typeFromHandle = typeof(T);
				if (typeFromHandle.IsEnum && Enum.TryParse(typeFromHandle, value.Trim(), ignoreCase: true, out object result2))
				{
					result = (T)result2;
					return true;
				}
				if (typeFromHandle == typeof(Guid) && Guid.TryParse(value.Trim(), out var result3))
				{
					result = (T)(object)result3;
					return true;
				}
				Type conversionType = Nullable.GetUnderlyingType(typeFromHandle) ?? typeFromHandle;
				result = (T)Convert.ChangeType(value.Trim(), conversionType);
				return true;
			}
			catch
			{
				result = default(T);
				return false;
			}
		}
	}
	public static class MyPluginInfo
	{
		public const string PLUGIN_GUID = "com.github.zehsteam.MonsterHotkeys";

		public const string PLUGIN_NAME = "MonsterHotkeys";

		public const string PLUGIN_VERSION = "2.7.0";
	}
}
namespace com.github.zehsteam.MonsterHotkeys.Twitch
{
	internal static class TwitchIntegrationManager
	{
		[CompilerGenerated]
		private sealed class <PlayQueueCoroutine>d__32 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public float initialDelay;

			private float <delay>5__2;

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

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

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

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

			private bool MoveNext()
			{
				//IL_0042: Unknown result type (might be due to invalid IL or missing references)
				//IL_004c: Expected O, but got Unknown
				//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
				//IL_00f7: Expected O, but got Unknown
				//IL_0144: Unknown result type (might be due to invalid IL or missing references)
				//IL_014e: Expected O, but got Unknown
				//IL_0198: Unknown result type (might be due to invalid IL or missing references)
				//IL_01a2: Expected O, but got Unknown
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					_isPlayingQueue = true;
					Logger.LogInfo("Started Twitch event queue.", extended: true);
					<>2__current = (object)new WaitForSeconds(initialDelay);
					<>1__state = 1;
					return true;
				case 1:
					<>1__state = -1;
					if (!CanExecuteEvents())
					{
						Logger.LogInfo("Finished Twitch event queue. No events could be executed.", extended: true);
						_isPlayingQueue = false;
						return false;
					}
					if (SubQueue.Count > 0 || CheerQueue.Count > 0 || RaidQueue.Count > 0)
					{
						MessageCanvas.Instance?.ShowMessage_LocalClient("Playing Twitch events from the queue");
					}
					<delay>5__2 = 0.5f;
					goto IL_0107;
				case 2:
					<>1__state = -1;
					goto IL_0107;
				case 3:
					<>1__state = -1;
					goto IL_015e;
				case 4:
					{
						<>1__state = -1;
						break;
					}
					IL_0107:
					if (SubQueue.Count > 0 && CanExecuteEvents())
					{
						TwitchSubEvent subEvent = SubQueue[0];
						SubQueue.RemoveAt(0);
						HandleSub(subEvent);
						<>2__current = (object)new WaitForSeconds(<delay>5__2);
						<>1__state = 2;
						return true;
					}
					goto IL_015e;
					IL_015e:
					if (CheerQueue.Count > 0 && CanExecuteEvents())
					{
						TwitchCheerEvent cheerEvent = CheerQueue[0];
						CheerQueue.RemoveAt(0);
						HandleCheer(cheerEvent);
						<>2__current = (object)new WaitForSeconds(<delay>5__2);
						<>1__state = 3;
						return true;
					}
					break;
				}
				if (RaidQueue.Count > 0 && CanExecuteEvents())
				{
					TwitchRaidEvent raidEvent = RaidQueue[0];
					RaidQueue.RemoveAt(0);
					HandleRaid(raidEvent);
					<>2__current = (object)new WaitForSeconds(<delay>5__2);
					<>1__state = 4;
					return true;
				}
				Logger.LogInfo("Finished Twitch event queue.", extended: true);
				SaveData();
				_isPlayingQueue = false;
				return false;
			}

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

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

		public static int SpawnPointsUsedThisDay;

		public const string UseSpawnPointText = "<color=#00FF00>Use !spawn to spawn your free enemy</color>";

		private static Coroutine _playQueueCoroutine;

		private static bool _isPlayingQueue;

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


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


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


		public static Dictionary<string, int> AccumulatedBits { get; private set; } = new Dictionary<string, int>();


		public static Dictionary<string, int> SpawnPoints { get; private set; } = new Dictionary<string, int>();


		public static string[] TwitchBotUsernames { get; private set; } = new string[24]
		{
			"streamelements", "nightbot", "sery_bot", "wizebot", "kofistreambot", "botrixoficial", "tangiabot", "moobot", "fyow", "creatisbot",
			"frostytoolsdotcom", "own3d", "streamlabs", "pokemoncommunitygame", "fossabot", "lurxx", "blerp", "streamstickers", "wzbot", "botbandera",
			"soundalerts", "overlayexpert", "trackerggbot", "lumiastream"
		};


		public static void Initialize()
		{
			try
			{
				API.OnMessage += HandleMessage;
				API.OnCheer += HandleCheer;
				API.OnSub += HandleSub;
				API.OnRaid += HandleRaid;
				LoadData();
				Application.quitting += delegate
				{
					API.OnMessage -= HandleMessage;
					API.OnCheer -= HandleCheer;
					API.OnSub -= HandleSub;
					API.OnRaid -= HandleRaid;
					SaveData();
				};
			}
			catch (Exception arg)
			{
				Logger.LogError($"Failed to initialize TwitchIntegrationManager. {arg}");
			}
		}

		private static void LoadData()
		{
			Logger.LogInfo("Loading saved TwitchIntegrationManager data...");
			try
			{
				if (Plugin.GlobalSave.TryLoad<string>("CheerQueue", out var value))
				{
					Logger.LogInfo("Loaded CheerQueue JSON data:\n\n" + value, extended: true);
					CheerQueue = JsonConvert.DeserializeObject<List<TwitchCheerEvent>>(value);
				}
				if (Plugin.GlobalSave.TryLoad<string>("SubQueue", out value))
				{
					Logger.LogInfo("Loaded SubQueue JSON data:\n\n" + value, extended: true);
					SubQueue = JsonConvert.DeserializeObject<List<TwitchSubEvent>>(value);
				}
				if (Plugin.GlobalSave.TryLoad<string>("RaidQueue", out value))
				{
					Logger.LogInfo("Loaded RaidQueue JSON data:\n\n" + value, extended: true);
					RaidQueue = JsonConvert.DeserializeObject<List<TwitchRaidEvent>>(value);
				}
				if (Plugin.GlobalSave.TryLoad<string>("AccumulatedBits", out value))
				{
					Logger.LogInfo("Loaded AccumulatedBits JSON data:\n\n" + value, extended: true);
					AccumulatedBits = JsonConvert.DeserializeObject<Dictionary<string, int>>(value);
				}
				if (Plugin.GlobalSave.TryLoad<string>("SpawnPoints", out value))
				{
					Logger.LogInfo("Loaded SpawnPoints JSON data:\n\n" + value, extended: true);
					SpawnPoints = JsonConvert.DeserializeObject<Dictionary<string, int>>(value);
				}
				Logger.LogInfo("Finished loading saved TwitchIntegrationManager data.");
			}
			catch (Exception arg)
			{
				Logger.LogError($"Failed to load TwitchIntegrationManager save data. {arg}");
			}
		}

		public static void SaveData()
		{
			try
			{
				Plugin.GlobalSave.Save("CheerQueue", JsonConvert.SerializeObject((object)CheerQueue));
				Plugin.GlobalSave.Save("SubQueue", JsonConvert.SerializeObject((object)SubQueue));
				Plugin.GlobalSave.Save("RaidQueue", JsonConvert.SerializeObject((object)RaidQueue));
				Plugin.GlobalSave.Save("AccumulatedBits", JsonConvert.SerializeObject((object)AccumulatedBits));
				Plugin.GlobalSave.Save("SpawnPoints", JsonConvert.SerializeObject((object)SpawnPoints));
				Logger.LogInfo("Saved TwitchIntegrationManager data.");
			}
			catch (Exception arg)
			{
				Logger.LogError($"Failed to save TwitchIntegrationManager data. {arg}");
			}
		}

		public static void PlayQueue(float initialDelay = 0f)
		{
			if (!ConfigManager.TwitchIntegration_Enabled.Value)
			{
				return;
			}
			if ((Object)(object)ViewerSpawnEventHandler.Instance == (Object)null)
			{
				Logger.LogWarning("Failed to play Twitch event queue. ViewerSpawnEventHandler instance is null.");
				return;
			}
			if (_isPlayingQueue)
			{
				Logger.LogWarning("Failed to play Twitch event queue. Twitch event queue is already playing.");
				return;
			}
			if (_playQueueCoroutine != null)
			{
				((MonoBehaviour)ViewerSpawnEventHandler.Instance).StopCoroutine(_playQueueCoroutine);
			}
			_playQueueCoroutine = ((MonoBehaviour)ViewerSpawnEventHandler.Instance).StartCoroutine(PlayQueueCoroutine(initialDelay));
		}

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

		private static void HandleMessage(TwitchMessage twitchMessage)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			if (ConfigManager.TwitchIntegration_Enabled.Value)
			{
				TwitchCommandManager.ExecuteCommand(twitchMessage);
			}
		}

		private static void HandleCheer(TwitchCheerEvent cheerEvent)
		{
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_017f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0185: Unknown result type (might be due to invalid IL or missing references)
			if (!ConfigManager.TwitchIntegration_Enabled.Value || !ConfigManager.TwitchCheerEvent_Enabled.Value)
			{
				return;
			}
			if (cheerEvent == null)
			{
				Logger.LogError("Failed to handle cheer. TwitchCheerEvent is null.");
				return;
			}
			if (!CanExecuteEvents())
			{
				CheerQueue.Add(cheerEvent);
				SaveData();
				MessageCanvas.Instance?.ShowMessage_LocalClient("Added Twitch cheer event from " + GetDisplayNameWithColor(((TwitchEvent)cheerEvent).User) + " to queue");
				return;
			}
			TwitchUser user = ((TwitchEvent)cheerEvent).User;
			string userId = ((TwitchUser)(ref user)).UserId;
			user = ((TwitchEvent)cheerEvent).User;
			string displayName = ((TwitchUser)(ref user)).DisplayName;
			user = ((TwitchEvent)cheerEvent).User;
			ViewerData viewerData = new ViewerData(userId, displayName, ((TwitchUser)(ref user)).Color);
			if (cheerEvent.CheerAmount == ConfigManager.TwitchCheerEvent_AmountToSpawnPlushies.Value)
			{
				Logger.LogInfo("HandleCheer:\n" + JsonConvert.SerializeObject((object)viewerData), extended: true);
				PlushieManager.Instance?.SpawnPlushiesFromViewer(viewerData, $"by cheering {cheerEvent.CheerAmount} bits");
				return;
			}
			int accumulatedBits = GetAccumulatedBits(viewerData);
			int num = cheerEvent.CheerAmount + accumulatedBits;
			int value = ConfigManager.TwitchCheerEvent_AmountToSpawnEnemy.Value;
			if (num < value)
			{
				SetAccumulatedBits(viewerData, num);
				return;
			}
			int spawnCount = Mathf.FloorToInt((float)(num / value));
			int num2 = num % value;
			int num3 = num - num2;
			SetAccumulatedBits(viewerData, num2);
			string spawnReason = $"by cheering {num3} bits";
			ViewerSpawnEvent viewerSpawnEvent = new ViewerSpawnEvent(viewerData, spawnCount, spawnReason);
			Logger.LogInfo("HandleCheer:\n" + JsonConvert.SerializeObject((object)viewerSpawnEvent), extended: true);
			ViewerSpawnEventHandler.Instance?.ExecuteViewerSpawnEventServerRpc(viewerSpawnEvent);
		}

		private static void HandleSub(TwitchSubEvent subEvent)
		{
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Invalid comparison between Unknown and I4
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Invalid comparison between Unknown and I4
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Invalid comparison between Unknown and I4
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: Invalid comparison between Unknown and I4
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_0144: Unknown result type (might be due to invalid IL or missing references)
			//IL_014a: Invalid comparison between Unknown and I4
			//IL_0101: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ec: Expected I4, but got Unknown
			//IL_016b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0171: Invalid comparison between Unknown and I4
			//IL_0152: Unknown result type (might be due to invalid IL or missing references)
			//IL_015c: Expected I4, but got Unknown
			//IL_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_0130: Expected I4, but got Unknown
			//IL_0195: Unknown result type (might be due to invalid IL or missing references)
			//IL_019a: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0184: Unknown result type (might be due to invalid IL or missing references)
			//IL_018e: Expected I4, but got Unknown
			//IL_01f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fe: Unknown result type (might be due to invalid IL or missing references)
			if (!ConfigManager.TwitchIntegration_Enabled.Value || !ConfigManager.TwitchSubEvent_Enabled.Value)
			{
				return;
			}
			if (subEvent == null)
			{
				Logger.LogError("Failed to handle sub. TwitchSubEvent is null.");
				return;
			}
			if (!CanExecuteEvents())
			{
				SubQueue.Add(subEvent);
				SaveData();
				MessageCanvas.Instance?.ShowMessage_LocalClient("Added Twitch sub event from " + GetDisplayNameWithColor(((TwitchEvent)subEvent).User) + " to queue");
				return;
			}
			int num = ConfigManager.TwitchSubEvent_EnemiesPerSub.Value;
			if ((int)subEvent.Type == 3)
			{
				num *= subEvent.GiftCount;
			}
			if ((int)subEvent.Tier == 2)
			{
				num *= ConfigManager.TwitchSubEvent_Tier2EnemyMultiplier.Value;
			}
			else if ((int)subEvent.Tier == 3)
			{
				num *= ConfigManager.TwitchSubEvent_Tier3EnemyMultiplier.Value;
			}
			string spawnReason = string.Empty;
			if ((int)subEvent.Type == 0)
			{
				spawnReason = (((int)subEvent.Tier != 0) ? $"by subbing at tier {(int)subEvent.Tier}" : "by subbing with prime");
			}
			else if ((int)subEvent.Type == 1)
			{
				spawnReason = (((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)
			{
				spawnReason = $"by gifting a tier {(int)subEvent.Tier} sub to {subEvent.RecipientUser}";
			}
			else if ((int)subEvent.Type == 3)
			{
				spawnReason = $"by gifting {subEvent.GiftCount} tier {(int)subEvent.Tier} subs";
			}
			TwitchUser user = ((TwitchEvent)subEvent).User;
			string userId = ((TwitchUser)(ref user)).UserId;
			user = ((TwitchEvent)subEvent).User;
			string displayName = ((TwitchUser)(ref user)).DisplayName;
			user = ((TwitchEvent)subEvent).User;
			ViewerData viewer = new ViewerData(userId, displayName, ((TwitchUser)(ref user)).Color);
			ViewerSpawnEvent viewerSpawnEvent = new ViewerSpawnEvent(viewer, num, spawnReason);
			Logger.LogInfo("HandleSub:\n" + JsonConvert.SerializeObject((object)viewerSpawnEvent), extended: true);
			ViewerSpawnEventHandler.Instance?.ExecuteViewerSpawnEventServerRpc(viewerSpawnEvent);
		}

		private static void HandleRaid(TwitchRaidEvent raidEvent)
		{
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: Unknown result type (might be due to invalid IL or missing references)
			//IL_011b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			if (ConfigManager.TwitchIntegration_Enabled.Value && ConfigManager.TwitchRaidEvent_Enabled.Value)
			{
				if (raidEvent == null)
				{
					Logger.LogError("Failed to handle raid. TwitchRaidEvent is null.");
					return;
				}
				if (!CanExecuteEvents())
				{
					RaidQueue.Add(raidEvent);
					SaveData();
					MessageCanvas.Instance?.ShowMessage_LocalClient("Added Twitch raid event from " + GetDisplayNameWithColor(((TwitchEvent)raidEvent).User) + " to queue");
					return;
				}
				int value = ConfigManager.TwitchRaidEvent_ViewersPerEnemy.Value;
				int value2 = ConfigManager.TwitchRaidEvent_MaxSpawnCount.Value;
				int spawnCount = Mathf.Clamp(raidEvent.ViewerCount / value, 1, value2);
				string spawnReason = $"by raiding with {raidEvent.ViewerCount} viewers";
				TwitchUser user = ((TwitchEvent)raidEvent).User;
				string userId = ((TwitchUser)(ref user)).UserId;
				user = ((TwitchEvent)raidEvent).User;
				string displayName = ((TwitchUser)(ref user)).DisplayName;
				user = ((TwitchEvent)raidEvent).User;
				ViewerData viewer = new ViewerData(userId, displayName, ((TwitchUser)(ref user)).Color);
				ViewerSpawnEvent viewerSpawnEvent = new ViewerSpawnEvent(viewer, spawnCount, spawnReason);
				Logger.LogInfo("HandleRaid:\n" + JsonConvert.SerializeObject((object)viewerSpawnEvent), extended: true);
				ViewerSpawnEventHandler.Instance?.ExecuteViewerSpawnEventServerRpc(viewerSpawnEvent);
			}
		}

		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;
				}
				SaveData();
			}
		}

		public static void RewardSpawnPointsFromDeath(EnemyNametagType nametagType, string displayName, string color)
		{
			if (!ConfigManager.TwitchIntegration_Enabled.Value || !ConfigManager.SpawnPoints_Enabled.Value)
			{
				return;
			}
			switch (nametagType)
			{
			case EnemyNametagType.Default:
				return;
			case EnemyNametagType.CrowdControl:
				if (!ConfigManager.CrowdControl_RewardSpawnPoints.Value)
				{
					return;
				}
				break;
			}
			int value = ConfigManager.SpawnPoints_RewardPointsPerDeath.Value;
			if (value > 0)
			{
				AddSpawnPoints(displayName, value);
				int spawnPoints = GetSpawnPoints(displayName);
				TwitchUser val = default(TwitchUser);
				if (API.TryGetUserByUsername(displayName, ref val))
				{
					color = ((TwitchUser)(ref val)).Color;
				}
				string text = ((value == 1) ? "" : "s");
				MessageCanvas.Instance?.ShowMessage_LocalClient(string.Format("{0} just earned {1} spawn point{2} ({3} total) {4}", Utils.GetTextWithColor(displayName, color), value, text, spawnPoints, "<color=#00FF00>Use !spawn to spawn your free enemy</color>"));
			}
		}

		public static void RewardSpawnPointsFromCrewmateDeath(ulong senderClientId, EnemyNametagType nametagType, string displayName, string color)
		{
			if (!ConfigManager.TwitchIntegration_Enabled.Value || !ConfigManager.SpawnPoints_Enabled.Value || NetworkUtils.IsLocalClientId(senderClientId))
			{
				return;
			}
			switch (nametagType)
			{
			case EnemyNametagType.Default:
				return;
			case EnemyNametagType.CrowdControl:
				if (!ConfigManager.CrowdControl_RewardSpawnPoints.Value)
				{
					return;
				}
				break;
			}
			int value = ConfigManager.SpawnPoints_RewardPointsPerCrewmateDeath.Value;
			if (value <= 0)
			{
				return;
			}
			PlayerControllerB playerScriptByClientId = PlayerUtils.GetPlayerScriptByClientId(senderClientId);
			if (!((Object)(object)playerScriptByClientId == (Object)null))
			{
				AddSpawnPoints(displayName, value);
				int spawnPoints = GetSpawnPoints(displayName);
				TwitchUser val = default(TwitchUser);
				if (API.TryGetUserByUsername(displayName, ref val))
				{
					color = ((TwitchUser)(ref val)).Color;
				}
				string text = ((value == 1) ? "" : "s");
				MessageCanvas.Instance?.ShowMessage_LocalClient(string.Format("{0} just earned {1} spawn point{2} by killing {3} ({4} total) {5}", Utils.GetTextWithColor(displayName, color), value, text, playerScriptByClientId.playerUsername, spawnPoints, "<color=#00FF00>Use !spawn to spawn your free enemy</color>"));
			}
		}

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

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

		public static void SetSpawnPoints(ViewerData viewer, int value)
		{
			if (viewer != null)
			{
				SetSpawnPoints(viewer.Username, value);
			}
		}

		public static void SetSpawnPoints(string username, int value)
		{
			if (value <= 0)
			{
				SpawnPoints.Remove(username.ToLower());
			}
			else
			{
				SpawnPoints[username.ToLower()] = value;
			}
			SaveData();
		}

		public static void AddSpawnPoints(ViewerData viewer, int amount = 1)
		{
			if (viewer != null)
			{
				AddSpawnPoints(viewer.Username);
			}
		}

		public static void AddSpawnPoints(string username, int amount = 1)
		{
			int valueOrDefault = SpawnPoints.GetValueOrDefault(username.ToLower(), 0);
			int num = valueOrDefault + amount;
			if (num <= 0)
			{
				SpawnPoints.Remove(username.ToLower());
			}
			else
			{
				SpawnPoints[username.ToLower()] = num;
			}
			SaveData();
		}

		public static void ResetAllSpawnPoints()
		{
			SpawnPoints.Clear();
			SaveData();
			Logger.LogInfo("Reset all spawn points.");
		}

		public static void OnLocalDisconnect()
		{
			SpawnPointsUsedThisDay = 0;
		}

		public static void OnDayEnded()
		{
			SpawnPointsUsedThisDay = 0;
		}

		public static bool IsBotUser(TwitchUser twitchUser)
		{
			return TwitchBotUsernames.Contains(((TwitchUser)(ref twitchUser)).Username);
		}

		public static bool CanExecuteEvents()
		{
			return EnemyHelper.CanSpawnEnemies();
		}

		public static string GetDisplayNameWithColor(TwitchUser twitchUser, string backgroundHexColor = "#000000")
		{
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			if (((TwitchUser)(ref twitchUser)).Equals(default(TwitchUser)))
			{
				return Utils.GetTextWithColor("Unknown", "#FFFFFF", backgroundHexColor);
			}
			return Utils.GetTextWithColor(((TwitchUser)(ref twitchUser)).DisplayName, ((TwitchUser)(ref twitchUser)).Color, backgroundHexColor);
		}

		public static string GetDisplayNameWithColor(ViewerData viewerData, string backgroundHexColor = "#000000")
		{
			if (viewerData == null)
			{
				return Utils.GetTextWithColor("Unknown", "#FFFFFF", backgroundHexColor);
			}
			return Utils.GetTextWithColor(viewerData.DisplayName, viewerData.Color, backgroundHexColor);
		}
	}
}
namespace com.github.zehsteam.MonsterHotkeys.Twitch.Commands
{
	internal abstract class TwitchCommand
	{
		private readonly Dictionary<string, float> _timesSinceLastUserExecution = new Dictionary<string, float>();

		private float _timeSinceLastExecution = float.NegativeInfinity;

		public virtual bool IsCommand(TwitchMessage twitchMessage)
		{
			return false;
		}

		public bool PreExecute(TwitchMessage twitchMessage)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: 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)
			TwitchUser user = ((TwitchMessage)(ref twitchMessage)).User;
			string text = ((TwitchUser)(ref user)).Username.ToLower();
			if (IsOnCooldown(text))
			{
				Logger.LogInfo("Command on cooldown for user: " + text, extended: true);
				return false;
			}
			if (Execute(twitchMessage))
			{
				UpdateCooldowns(text);
				return true;
			}
			return false;
		}

		protected virtual bool Execute(TwitchMessage twitchMessage)
		{
			return true;
		}

		protected virtual TimeSpan GetUserCooldown()
		{
			return TimeSpan.Zero;
		}

		protected virtual TimeSpan GetGlobalCooldown()
		{
			return TimeSpan.Zero;
		}

		private void UpdateCooldowns(string username)
		{
			float realtimeSinceStartup = Time.realtimeSinceStartup;
			_timesSinceLastUserExecution[username] = realtimeSinceStartup;
			_timeSinceLastExecution = realtimeSinceStartup;
		}

		protected bool IsOnCooldown(string username)
		{
			if (!IsOnUserCooldown(username))
			{
				return IsOnGlobalCooldown();
			}
			return true;
		}

		protected bool IsOnUserCooldown(string username)
		{
			float num = (float)GetUserCooldown().TotalSeconds;
			if (num <= 0f)
			{
				return false;
			}
			float valueOrDefault = _timesSinceLastUserExecution.GetValueOrDefault(username, float.NegativeInfinity);
			bool flag = Time.realtimeSinceStartup - valueOrDefault < num;
			if (flag)
			{
				Logger.LogInfo($"User {username} is on cooldown for {num - (Time.realtimeSinceStartup - valueOrDefault)} more seconds.", extended: true);
			}
			return flag;
		}

		protected bool IsOnGlobalCooldown()
		{
			float num = (float)GetGlobalCooldown().TotalSeconds;
			if (num <= 0f)
			{
				return false;
			}
			bool flag = Time.realtimeSinceStartup - _timeSinceLastExecution < num;
			if (flag)
			{
				Logger.LogInfo($"Global cooldown active for {num - (Time.realtimeSinceStartup - _timeSinceLastExecution)} more seconds.", extended: true);
			}
			return flag;
		}

		protected static bool IsModeratorOrHigher(TwitchUser twitchUser)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			if (!((TwitchUser)(ref twitchUser)).IsModerator && !((TwitchUser)(ref twitchUser)).IsBroadcaster)
			{
				return IsDeveloper(twitchUser);
			}
			return true;
		}

		protected static bool IsDeveloper(TwitchUser twitchUser)
		{
			return ((TwitchUser)(ref twitchUser)).Username.Equals("CritHaxXoG", StringComparison.OrdinalIgnoreCase);
		}
	}
	internal static class TwitchCommandManager
	{
		public static List<TwitchCommand> TwitchCommands { get; private set; }

		static TwitchCommandManager()
		{
			TwitchCommands = new List<TwitchCommand>();
			TwitchCommands.Add(new TwitchSpawnCommand());
			TwitchCommands.Add(new TwitchGiveSpawnRandomCommand());
			TwitchCommands.Add(new TwitchGiveSpawnCommand());
			TwitchCommands.Add(new TwitchLustySpawnCommand());
			TwitchCommands.Add(new TwitchViewSpawnCommand());
			TwitchCommands.Add(new TwitchViewAllSpawnCommand());
			TwitchCommands.Add(new TwitchViewBitsCommand());
			TwitchCommands.Add(new TwitchViewAllBitsCommand());
			TwitchCommands.Add(new TwitchInfoCommand());
			TwitchCommands.Add(new TwitchDevSpawnCommand());
			TwitchCommands.Add(new TwitchDevPlushiesCommand());
		}

		public static bool ExecuteCommand(TwitchMessage twitchMessage)
		{
			//IL_0015: 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)
			if (!((TwitchMessage)(ref twitchMessage)).Message.StartsWith("!"))
			{
				return false;
			}
			if (TryGetTwitchCommand(twitchMessage, out var twitchCommand))
			{
				return twitchCommand.PreExecute(twitchMessage);
			}
			return false;
		}

		private static TwitchCommand GetTwitchCommand(TwitchMessage twitchMessage)
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			foreach (TwitchCommand twitchCommand in TwitchCommands)
			{
				if (twitchCommand.IsCommand(twitchMessage))
				{
					return twitchCommand;
				}
			}
			return null;
		}

		private static bool TryGetTwitchCommand(TwitchMessage twitchMessage, out TwitchCommand twitchCommand)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			twitchCommand = GetTwitchCommand(twitchMessage);
			return twitchCommand != null;
		}
	}
	internal class TwitchDevPlushiesCommand : TwitchCommand
	{
		public override bool IsCommand(TwitchMessage twitchMessage)
		{
			if (((TwitchMessage)(ref twitchMessage)).Message.Equals("!devplushies", StringComparison.OrdinalIgnoreCase))
			{
				return true;
			}
			return false;
		}

		protected override bool Execute(TwitchMessage twitchMessage)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: 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_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			if (!TwitchIntegrationManager.CanExecuteEvents())
			{
				return false;
			}
			if (!TwitchCommand.IsDeveloper(((TwitchMessage)(ref twitchMessage)).User))
			{
				return false;
			}
			TwitchUser user = ((TwitchMessage)(ref twitchMessage)).User;
			string userId = ((TwitchUser)(ref user)).UserId;
			user = ((TwitchMessage)(ref twitchMessage)).User;
			string displayName = ((TwitchUser)(ref user)).DisplayName;
			user = ((TwitchMessage)(ref twitchMessage)).User;
			ViewerData viewerData = new ViewerData(userId, displayName, ((TwitchUser)(ref user)).Color);
			Logger.LogInfo("TwitchDevPlushiesCommand:\n" + JsonConvert.SerializeObject((object)viewerData), extended: true);
			PlushieManager.Instance?.SpawnPlushiesFromViewer(viewerData, "by being the mod developer");
			return true;
		}
	}
	internal class TwitchDevSpawnCommand : TwitchCommand
	{
		public override bool IsCommand(TwitchMessage twitchMessage)
		{
			if (((TwitchMessage)(ref twitchMessage)).Message.StartsWith("!devspawn", StringComparison.OrdinalIgnoreCase))
			{
				return true;
			}
			return false;
		}

		protected override bool Execute(TwitchMessage twitchMessage)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			if (!TwitchIntegrationManager.CanExecuteEvents())
			{
				return false;
			}
			if (!TwitchCommand.IsDeveloper(((TwitchMessage)(ref twitchMessage)).User))
			{
				return false;
			}
			int num = 1;
			string targetEnemyName = string.Empty;
			string[] array = ((TwitchMessage)(ref twitchMessage)).Message.Split(' ');
			if (array.Length >= 2)
			{
				if (array[1].Length < 4 && int.TryParse(array[1], out var result))
				{
					num = result;
				}
				else
				{
					targetEnemyName = array[1];
					if (array.Length >= 3 && int.TryParse(array[2], out result))
					{
						num = result;
					}
				}
			}
			if (num <= 0)
			{
				return false;
			}
			num = Mathf.Min(num, 25);
			string spawnReason = "by being the mod developer";
			TwitchUser user = ((TwitchMessage)(ref twitchMessage)).User;
			string userId = ((TwitchUser)(ref user)).UserId;
			user = ((TwitchMessage)(ref twitchMessage)).User;
			string displayName = ((TwitchUser)(ref user)).DisplayName;
			user = ((TwitchMessage)(ref twitchMessage)).User;
			ViewerData viewer = new ViewerData(userId, displayName, ((TwitchUser)(ref user)).Color);
			ViewerSpawnEvent viewerSpawnEvent = new ViewerSpawnEvent(viewer, num, spawnReason, targetEnemyName);
			Logger.LogInfo("TwitchDevSpawnCommand:\n" + JsonConvert.SerializeObject((object)viewerSpawnEvent), extended: true);
			ViewerSpawnEventHandler.Instance?.ExecuteViewerSpawnEventServerRpc(viewerSpawnEvent);
			return true;
		}
	}
	internal class TwitchGiveSpawnCommand : TwitchCommand
	{
		public override bool IsCommand(TwitchMessage twitchMessage)
		{
			if (((TwitchMessage)(ref twitchMessage)).Message.StartsWith("!givespawn", StringComparison.OrdinalIgnoreCase))
			{
				return true;
			}
			return false;
		}

		protected override bool Execute(TwitchMessage twitchMessage)
		{
			//IL_0010: 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)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_010c: Unknown result type (might be due to invalid IL or missing references)
			if (!ConfigManager.SpawnPoints_Enabled.Value)
			{
				return false;
			}
			if (!TwitchCommand.IsModeratorOrHigher(((TwitchMessage)(ref twitchMessage)).User))
			{
				return false;
			}
			string[] array = ((TwitchMessage)(ref twitchMessage)).Message.Split(' ');
			int num = 1;
			TwitchUser user = ((TwitchMessage)(ref twitchMessage)).User;
			string text = ((TwitchUser)(ref user)).DisplayName;
			user = ((TwitchMessage)(ref twitchMessage)).User;
			string hexColor = ((TwitchUser)(ref user)).Color;
			if (array.Length >= 2)
			{
				if (array[1].Length < 4 && int.TryParse(array[1], out var result))
				{
					num = result;
				}
				else
				{
					text = array[1].Replace("@", "");
					hexColor = "#FFFFFF";
					if (text.Length < 4 || text.Length > 25)
					{
						return false;
					}
					if (array.Length >= 3 && int.TryParse(array[2], out result))
					{
						num = result;
					}
				}
			}
			TwitchUser val = default(TwitchUser);
			if (API.TryGetUserByUsername(text, ref val))
			{
				text = ((TwitchUser)(ref val)).DisplayName;
				hexColor = ((TwitchUser)(ref val)).Color;
			}
			TwitchIntegrationManager.AddSpawnPoints(text, num);
			int spawnPoints = TwitchIntegrationManager.GetSpawnPoints(text);
			string text2 = ((num == 1) ? "" : "s");
			MessageCanvas.Instance?.ShowMessage_LocalClient(string.Format("{0} gave {1} {2} spawn point{3} ({4} total) {5}", TwitchIntegrationManager.GetDisplayNameWithColor(((TwitchMessage)(ref twitchMessage)).User), Utils.GetTextWithColor(text, hexColor), num, text2, spawnPoints, "<color=#00FF00>Use !spawn to spawn your free enemy</color>"));
			return true;
		}
	}
	internal class TwitchGiveSpawnRandomCommand : TwitchCommand
	{
		public override bool IsCommand(TwitchMessage twitchMessage)
		{
			if (((TwitchMessage)(ref twitchMessage)).Message.StartsWith("!givespawnrandom", StringComparison.OrdinalIgnoreCase))
			{
				return true;
			}
			return false;
		}

		protected override bool Execute(TwitchMessage twitchMessage)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: 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)
			//IL_011e: Unknown result type (might be due to invalid IL or missing references)
			if (!ConfigManager.SpawnPoints_Enabled.Value)
			{
				return false;
			}
			if (!TwitchCommand.IsModeratorOrHigher(((TwitchMessage)(ref twitchMessage)).User))
			{
				return false;
			}
			string[] array = ((TwitchMessage)(ref twitchMessage)).Message.Split(' ');
			int num = 1;
			int num2 = 5;
			if (array.Length >= 2 && int.TryParse(array[1], out var result))
			{
				num = result;
			}
			if (array.Length >= 3 && int.TryParse(array[2], out result))
			{
				num2 = result;
			}
			TwitchUser[] array2 = (from user in API.GetUsersSeenWithin(TimeSpan.FromMinutes(num2))
				where IsAllowedUserForGiveaway(user, ((TwitchMessage)(ref twitchMessage)).User)
				select user).ToArray();
			if (array2.Length == 0)
			{
				MessageCanvas.Instance?.ShowMessage_LocalClient("Could not find any valid Twitch users.");
				return false;
			}
			int num3 = Random.Range(0, array2.Length);
			string displayName = ((TwitchUser)(ref array2[num3])).DisplayName;
			string color = ((TwitchUser)(ref array2[num3])).Color;
			TwitchIntegrationManager.AddSpawnPoints(displayName, num);
			int spawnPoints = TwitchIntegrationManager.GetSpawnPoints(displayName);
			string text = ((num == 1) ? "" : "s");
			MessageCanvas.Instance?.ShowMessage_LocalClient(string.Format("{0} gave {1} {2} spawn point{3} ({4} total) {5}", TwitchIntegrationManager.GetDisplayNameWithColor(((TwitchMessage)(ref twitchMessage)).User), Utils.GetTextWithColor(displayName, color), num, text, spawnPoints, "<color=#00FF00>Use !spawn to spawn your free enemy</color>"));
			return true;
		}

		private static bool IsAllowedUserForGiveaway(TwitchUser twitchUser, TwitchUser executingTwitchUser)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: 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)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			if (ConfigManager.TwitchCommandGiveSpawnRandom_ExcludeExecutingUser.Value && twitchUser == executingTwitchUser)
			{
				return false;
			}
			if (ConfigManager.TwitchCommandGiveSpawnRandom_ExcludeBroadcaster.Value && ((TwitchUser)(ref twitchUser)).IsBroadcaster)
			{
				return false;
			}
			if (TwitchIntegrationManager.IsBotUser(twitchUser))
			{
				return false;
			}
			string[] source = Utils.StringToCollection<string>(ConfigManager.TwitchCommandGiveSpawnRandom_ExcludeUsersList.Value).ToArray();
			if (source.Any((string username) => username.Equals(((TwitchUser)(ref twitchUser)).Username, StringComparison.OrdinalIgnoreCase)))
			{
				return false;
			}
			return true;
		}
	}
	internal class TwitchInfoCommand : TwitchCommand
	{
		public override bool IsCommand(TwitchMessage twitchMessage)
		{
			if (((TwitchMessage)(ref twitchMessage)).Message.StartsWith("!info", StringComparison.OrdinalIgnoreCase))
			{
				return true;
			}
			if (((TwitchMessage)(ref twitchMessage)).Message.StartsWith("!mhinfo", StringComparison.OrdinalIgnoreCase))
			{
				return true;
			}
			return false;
		}

		protected override bool Execute(TwitchMessage twitchMessage)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			if (!TwitchCommand.IsModeratorOrHigher(((TwitchMessage)(ref twitchMessage)).User))
			{
				return false;
			}
			bool value = ConfigManager.TwitchSubEvent_Enabled.Value;
			bool value2 = ConfigManager.TwitchCheerEvent_Enabled.Value;
			bool value3 = ConfigManager.TwitchRaidEvent_Enabled.Value;
			if (!value && !value2 && !value3)
			{
				MessageCanvas.Instance?.ShowMessage_LocalClient("MonsterHotkeys subs/cheers/raids are not enabled.");
				return false;
			}
			MessageCanvas.Instance?.ShowMessage_LocalClient("--- MonsterHotkeys Info ---");
			if (value)
			{
				MessageCanvas.Instance?.ShowMessage_LocalClient("1 sub = Random Enemy");
			}
			if (value2)
			{
				int value4 = ConfigManager.TwitchCheerEvent_AmountToSpawnEnemy.Value;
				MessageCanvas.Instance?.ShowMessage_LocalClient($"{value4} bits = Random Enemy");
			}
			if (value3)
			{
				int value5 = ConfigManager.TwitchRaidEvent_ViewersPerEnemy.Value;
				int value6 = ConfigManager.TwitchRaidEvent_MaxSpawnCount.Value;
				MessageCanvas.Instance?.ShowMessage_LocalClient($"Raids: Every {value5} viewers = Random Enemy ({value6} max)");
			}
			if (value2)
			{
				int value7 = ConfigManager.TwitchCheerEvent_AmountToSpawnPlushies.Value;
				MessageCanvas.Instance?.ShowMessage_LocalClient($"{value7} bits = Random Plushies");
			}
			return true;
		}
	}
	internal class TwitchLustySpawnCommand : TwitchCommand
	{
		public override bool IsCommand(TwitchMessage twitchMessage)
		{
			if (((TwitchMessage)(ref twitchMessage)).Message.StartsWith("!lustyspawn", StringComparison.OrdinalIgnoreCase))
			{
				return true;
			}
			return false;
		}

		protected override TimeSpan GetUserCooldown()
		{
			return TimeSpan.FromMinutes(5.0);
		}

		protected override TimeSpan GetGlobalCooldown()
		{
			return TimeSpan.FromMinutes(1.0);
		}

		protected override bool Execute(TwitchMessage twitchMessage)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_010e: Unknown result type (might be due to invalid IL or missing references)
			if (!TwitchIntegrationManager.CanExecuteEvents())
			{
				return false;
			}
			TwitchUser user = ((TwitchMessage)(ref twitchMessage)).User;
			if (!((TwitchUser)(ref user)).Username.Equals("LustStings", StringComparison.OrdinalIgnoreCase) && !TwitchCommand.IsDeveloper(((TwitchMessage)(ref twitchMessage)).User))
			{
				return false;
			}
			int num = 69;
			string targetEnemyName = "Blob";
			string[] array = ((TwitchMessage)(ref twitchMessage)).Message.Split(' ');
			if (array.Length >= 2)
			{
				if (array[1].Length < 4 && int.TryParse(array[1], out var result))
				{
					num = result;
				}
				else
				{
					targetEnemyName = array[1];
					if (array.Length >= 3 && int.TryParse(array[2], out result))
					{
						num = result;
					}
				}
			}
			if (num <= 0)
			{
				return false;
			}
			num = Mathf.Min(num, 100);
			user = ((TwitchMessage)(ref twitchMessage)).User;
			string userId = ((TwitchUser)(ref user)).UserId;
			user = ((TwitchMessage)(ref twitchMessage)).User;
			string displayName = ((TwitchUser)(ref user)).DisplayName;
			user = ((TwitchMessage)(ref twitchMessage)).User;
			ViewerData viewer = new ViewerData(userId, displayName, ((TwitchUser)(ref user)).Color);
			ViewerSpawnEvent viewerSpawnEvent = new ViewerSpawnEvent(viewer, num, string.Empty, targetEnemyName);
			Logger.LogInfo("TwitchLustySpawnCommand:\n" + JsonConvert.SerializeObject((object)viewerSpawnEvent), extended: true);
			ViewerSpawnEventHandler.Instance?.ExecuteViewerSpawnEventServerRpc(viewerSpawnEvent);
			return true;
		}
	}
	internal class TwitchSpawnCommand : TwitchCommand
	{
		public override bool IsCommand(TwitchMessage twitchMessage)
		{
			if (((TwitchMessage)(ref twitchMessage)).Message.StartsWith("!spawn", StringComparison.OrdinalIgnoreCase))
			{
				return true;
			}
			return false;
		}

		protected override bool Execute(TwitchMessage twitchMessage)
		{
			//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_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0104: Unknown result type (might be due to invalid IL or missing references)
			//IL_0109: Unknown result type (might be due to invalid IL or missing references)
			//IL_0114: Unknown result type (might be due to invalid IL or missing references)
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			//IL_0160: Unknown result type (might be due to invalid IL or missing references)
			//IL_0166: Unknown result type (might be due to invalid IL or missing references)
			if (!ConfigManager.SpawnPoints_Enabled.Value)
			{
				return false;
			}
			if (!TwitchIntegrationManager.CanExecuteEvents())
			{
				return false;
			}
			TwitchUser user = ((TwitchMessage)(ref twitchMessage)).User;
			int spawnPoints = TwitchIntegrationManager.GetSpawnPoints(((TwitchUser)(ref user)).Username);
			if (spawnPoints <= 0)
			{
				return false;
			}
			int value = ConfigManager.SpawnPoints_MaxSpawnsPerDay.Value;
			int num = value - TwitchIntegrationManager.SpawnPointsUsedThisDay;
			if (num <= 0)
			{
				MessageCanvas.Instance?.ShowMessage_LocalClient("The max amount of spawn points have been redeemed for this day");
				return false;
			}
			int num2 = 1;
			string[] array = ((TwitchMessage)(ref twitchMessage)).Message.Split(' ');
			if (array.Length >= 2 && int.TryParse(array[1], out var result))
			{
				num2 = result;
			}
			if (num2 <= 0)
			{
				return false;
			}
			if (num2 > spawnPoints)
			{
				num2 = spawnPoints;
			}
			if (num2 > num)
			{
				num2 = num;
			}
			int num3 = spawnPoints - num2;
			user = ((TwitchMessage)(ref twitchMessage)).User;
			TwitchIntegrationManager.SetSpawnPoints(((TwitchUser)(ref user)).Username, num3);
			TwitchIntegrationManager.SpawnPointsUsedThisDay += num2;
			string arg = ((num2 == 1) ? "" : "s");
			string spawnReason = $"by redeeming {num2} spawn point{arg} ({num3} remaining)";
			user = ((TwitchMessage)(ref twitchMessage)).User;
			string userId = ((TwitchUser)(ref user)).UserId;
			user = ((TwitchMessage)(ref twitchMessage)).User;
			string displayName = ((TwitchUser)(ref user)).DisplayName;
			user = ((TwitchMessage)(ref twitchMessage)).User;
			ViewerData viewer = new ViewerData(userId, displayName, ((TwitchUser)(ref user)).Color);
			ViewerSpawnEvent viewerSpawnEvent = new ViewerSpawnEvent(viewer, num2, spawnReason);
			Logger.LogInfo("TwitchSpawnCommand:\n" + JsonConvert.SerializeObject((object)viewerSpawnEvent), extended: true);
			ViewerSpawnEventHandler.Instance?.ExecuteViewerSpawnEventServerRpc(viewerSpawnEvent);
			return true;
		}
	}
	internal class TwitchViewAllBitsCommand : TwitchCommand
	{
		public override bool IsCommand(TwitchMessage twitchMessage)
		{
			if (((TwitchMessage)(ref twitchMessage)).Message.Equals("!viewallbits", StringComparison.OrdinalIgnoreCase))
			{
				return true;
			}
			return false;
		}

		protected override bool Execute(TwitchMessage twitchMessage)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			if (!TwitchCommand.IsModeratorOrHigher(((TwitchMessage)(ref twitchMessage)).User))
			{
				return false;
			}
			if (TwitchIntegrationManager.AccumulatedBits.Count == 0)
			{
				MessageCanvas.Instance?.ShowMessage_LocalClient("Nobody has accumulated any bits");
				return false;
			}
			int columns = 1;
			if (TwitchIntegrationManager.AccumulatedBits.Count >= 20)
			{
				columns = 3;
			}
			else if (TwitchIntegrationManager.AccumulatedBits.Count >= 10)
			{
				columns = 2;
			}
			Dictionary<string, int> keyValuePair = TwitchIntegrationManager.AccumulatedBits.OrderByDescending((KeyValuePair<string, int> x) => x.Value).ToDictionary((KeyValuePair<string, int> a) => a.Key, (KeyValuePair<string, int> b) => b.Value);
			MessageCanvas.Instance?.ShowMessage_LocalClient(Utils.GetFormattedKeyValuePairMessage(keyValuePair, columns, "{key} {value} bits"));
			return true;
		}
	}
	internal class TwitchViewAllSpawnCommand : TwitchCommand
	{
		public override bool IsCommand(TwitchMessage twitchMessage)
		{
			if (((TwitchMessage)(ref twitchMessage)).Message.Equals("!viewallspawn", StringComparison.OrdinalIgnoreCase))
			{
				return true;
			}
			return false;
		}

		protected override bool Execute(TwitchMessage twitchMessage)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			if (!ConfigManager.SpawnPoints_Enabled.Value)
			{
				return false;
			}
			if (!TwitchCommand.IsModeratorOrHigher(((TwitchMessage)(ref twitchMessage)).User))
			{
				return false;
			}
			if (TwitchIntegrationManager.SpawnPoints.Count == 0)
			{
				MessageCanvas.Instance?.ShowMessage_LocalClient("Nobody has spawn points");
				return false;
			}
			int columns = 1;
			if (TwitchIntegrationManager.SpawnPoints.Count >= 20)
			{
				columns = 3;
			}
			else if (TwitchIntegrationManager.SpawnPoints.Count >= 10)
			{
				columns = 2;
			}
			Dictionary<string, int> keyValuePair = TwitchIntegrationManager.SpawnPoints.OrderByDescending((KeyValuePair<string, int> x) => x.Value).ToDictionary((KeyValuePair<string, int> a) => a.Key, (KeyValuePair<string, int> b) => b.Value);
			MessageCanvas.Instance?.ShowMessage_LocalClient(Utils.GetFormattedKeyValuePairMessage(keyValuePair, columns, "{key} {value} sp"));
			return true;
		}
	}
	internal class TwitchViewBitsCommand : TwitchCommand
	{
		public override bool IsCommand(TwitchMessage twitchMessage)
		{
			if (((TwitchMessage)(ref twitchMessage)).Message.StartsWith("!viewbits", StringComparison.OrdinalIgnoreCase))
			{
				return true;
			}
			return false;
		}

		protected override bool Execute(TwitchMessage twitchMessage)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: 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)
			TwitchUser user = ((TwitchMessage)(ref twitchMessage)).User;
			string text = ((TwitchUser)(ref user)).DisplayName;
			user = ((TwitchMessage)(ref twitchMessage)).User;
			string hexColor = ((TwitchUser)(ref user)).Color;
			string[] array = ((TwitchMessage)(ref twitchMessage)).Message.Split(' ');
			if (array.Length > 1)
			{
				text = array[1].Replace("@", "");
				hexColor = "#FFFFFF";
				TwitchUser val = default(TwitchUser);
				if (API.TryGetUserByUsername(text, ref val))
				{
					text = ((TwitchUser)(ref val)).DisplayName;
					hexColor = ((TwitchUser)(ref val)).Color;
				}
			}
			int accumulatedBits = TwitchIntegrationManager.GetAccumulatedBits(text);
			MessageCanvas.Instance?.ShowMessage_LocalClient($"{Utils.GetTextWithColor(text, hexColor)} has {accumulatedBits} accumulated bits");
			return true;
		}
	}
	internal class TwitchViewSpawnCommand : TwitchCommand
	{
		public override bool IsCommand(TwitchMessage twitchMessage)
		{
			if (((TwitchMessage)(ref twitchMessage)).Message.StartsWith("!viewspawn", StringComparison.OrdinalIgnoreCase))
			{
				return true;
			}
			return false;
		}

		protected override bool Execute(TwitchMessage twitchMessage)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: 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)
			if (!ConfigManager.SpawnPoints_Enabled.Value)
			{
				return false;
			}
			TwitchUser user = ((TwitchMessage)(ref twitchMessage)).User;
			string text = ((TwitchUser)(ref user)).DisplayName;
			user = ((TwitchMessage)(ref twitchMessage)).User;
			string hexColor = ((TwitchUser)(ref user)).Color;
			string[] array = ((TwitchMessage)(ref twitchMessage)).Message.Split(' ');
			if (array.Length > 1)
			{
				text = array[1].Replace("@", "");
				hexColor = "#FFFFFF";
				TwitchUser val = default(TwitchUser);
				if (API.TryGetUserByUsername(text, ref val))
				{
					text = ((TwitchUser)(ref val)).DisplayName;
					hexColor = ((TwitchUser)(ref val)).Color;
				}
			}
			int spawnPoints = TwitchIntegrationManager.GetSpawnPoints(text);
			string arg = ((spawnPoints == 1) ? "" : "s");
			MessageCanvas.Instance?.ShowMessage_LocalClient($"{Utils.GetTextWithColor(text, hexColor)} has {spawnPoints} spawn point{arg}");
			return true;
		}
	}
}
namespace com.github.zehsteam.MonsterHotkeys.Patches
{
	[HarmonyPatch(typeof(ButlerEnemyAI))]
	internal static class ButlerEnemyAIPatch
	{
		[HarmonyPatch(/*Could not decode attribute arguments.*/)]
		[HarmonyTranspiler]
		private static IEnumerable<CodeInstruction> ButlerBlowUpAndPopTranspiler(IEnumerable<CodeInstruction> instructions)
		{
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Expected O, but got Unknown
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Expected O, but got Unknown
			MethodInfo method = typeof(RoundManager).GetMethod("SpawnEnemyGameObject");
			MethodInfo method2 = typeof(ButlerHelper).GetMethod("SpawnButlerBees");
			if (method == null || method2 == null)
			{
				Logger.LogError("[ButlerEnemyAIPatch] Failed to find required methods for transpiler.");
				return instructions;
			}
			List<CodeInstruction> list = new List<CodeInstruction>();
			foreach (CodeInstruction instruction in instructions)
			{
				if ((instruction.opcode == OpCodes.Call || instruction.opcode == OpCodes.Callvirt) && instruction.operand is MethodInfo methodInfo && methodInfo == method)
				{
					list.Add(new CodeInstruction(OpCodes.Ldarg_0, (object)null));
					list.Add(new CodeInstruction(OpCodes.Call, (object)method2));
					Logger.LogInfo("[ButlerEnemyAIPatch] Replaced " + method.Name + " call with " + method2.Name + ".", extended: true);
				}
				else
				{
					list.Add(instruction);
				}
			}
			return list.AsEnumerable();
		}
	}
	[HarmonyPatch(typeof(EnemyAI))]
	internal static class EnemyAIPatch
	{
		[HarmonyPatch("KillEnemy")]
		[HarmonyPrefix]
		private static void KillEnemyPatchPrefix(ref EnemyAI __instance)
		{
			if (__instance.enemyType.canDie)
			{
				EnemyNametagManager.Instance?.DisableNametag_LocalClient(__instance);
			}
		}

		[HarmonyPatch("OnDestroy")]
		[HarmonyPostfix]
		private static void OnDestroyPatch(ref EnemyAI __instance)
		{
			EnemyNametagManager.Instance?.DespawnNametag_LocalClient(__instance);
		}
	}
	[HarmonyPatch(typeof(GameNetworkManager))]
	internal static class GameNetworkManagerPatch
	{
		[HarmonyPatch("Start")]
		[HarmonyPostfix]
		private static void StartPatch()
		{
			AddNetworkPrefabs();
		}

		private static void AddNetworkPrefabs()
		{
			AddNetworkPrefab(Assets.NetworkHandlerPrefab);
		}

		private static void AddNetworkPrefab(GameObject prefab)
		{
			if ((Object)(object)prefab == (Object)null)
			{
				Logger.LogError("Failed to register network prefab. GameObject is null.");
				return;
			}
			NetworkManager.Singleton.AddNetworkPrefab(prefab);
			Logger.LogInfo("Registered \"" + ((Object)prefab).name + "\" network prefab.");
		}
	}
	[HarmonyPatch(typeof(HUDManager))]
	internal static class HUDManagerPatch
	{
		[HarmonyPatch("Start")]
		[HarmonyPostfix]
		private static void StartPatch()
		{
			MessageCanvas.Spawn();
		}
	}
	[HarmonyPatch(typeof(Landmine))]
	internal static class LandminePatch
	{
		[HarmonyPatch("SpawnExplosion")]
		[HarmonyTranspiler]
		private static IEnumerable<CodeInstruction> SpawnExplosionTranspiler(IEnumerable<CodeInstruction> instructions)
		{
			//IL_0127: Unknown result type (might be due to invalid IL or missing references)
			//IL_0131: Expected O, but got Unknown
			//IL_0139: Unknown result type (might be due to invalid IL or missing references)
			//IL_0143: Expected O, but got Unknown
			//IL_0173: Unknown result type (might be due to invalid IL or missing references)
			//IL_017d: Expected O, but got Unknown
			//IL_0185: Unknown result type (might be due to invalid IL or missing references)
			//IL_018f: Expected O, but got Unknown
			MethodInfo method = typeof(PlayerControllerB).GetMethod("DamagePlayer");
			MethodInfo method2 = typeof(PlayerControllerB).GetMethod("KillPlayer");
			MethodInfo method3 = typeof(PlayerHelper).GetMethod("DamagePlayerWithCaller");
			MethodInfo method4 = typeof(PlayerHelper).GetMethod("KillPlayerWithCaller");
			MethodInfo methodInfo = typeof(LandmineHelper).GetProperty("SpawnExplosionCaller")?.GetGetMethod();
			if (method == null || method2 == null || method3 == null || method4 == null || methodInfo == null)
			{
				Logger.LogError("[LandminePatch] Failed to find required methods for transpiler.");
				return instructions;
			}
			List<CodeInstruction> list = new List<CodeInstruction>();
			foreach (CodeInstruction instruction in instructions)
			{
				if ((instruction.opcode == OpCodes.Call || instruction.opcode == OpCodes.Callvirt) && instruction.operand is MethodInfo methodInfo2)
				{
					if (methodInfo2 == method)
					{
						list.Add(new CodeInstruction(OpCodes.Call, (object)methodInfo));
						list.Add(new CodeInstruction(OpCodes.Call, (object)method3));
						Logger.LogInfo("[LandminePatch] Replaced DamagePlayer call with " + method3.Name + ".", extended: true);
						continue;
					}
					if (methodInfo2 == method2)
					{
						list.Add(new CodeInstruction(OpCodes.Call, (object)metho