Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of MonsterHotkeys v3.2.0
BepInEx/plugins/com.github.zehsteam.MonsterHotkeys.dll
Decompiled 2 weeks ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.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 Steamworks; using TMPro; using TwitchChatAPI; using TwitchChatAPI.Enums; using TwitchChatAPI.Objects; using Unity.Netcode; using UnityEngine; using UnityEngine.AI; using UnityEngine.InputSystem; using UnityEngine.UI; using Zeekerss.Core.Singletons; using com.github.zehsteam.ImmersiveEntrance.MonoBehaviours; using com.github.zehsteam.MonsterHotkeys.Dependencies; using com.github.zehsteam.MonsterHotkeys.Dependencies.CrowdControlMod; using com.github.zehsteam.MonsterHotkeys.Dependencies.CrowdControlMod.Patches; using com.github.zehsteam.MonsterHotkeys.Dependencies.ImmersiveEntranceMod; using com.github.zehsteam.MonsterHotkeys.Enums; using com.github.zehsteam.MonsterHotkeys.Extensions; using com.github.zehsteam.MonsterHotkeys.Helpers; using com.github.zehsteam.MonsterHotkeys.Managers; using com.github.zehsteam.MonsterHotkeys.MonoBehaviours; using com.github.zehsteam.MonsterHotkeys.MonoBehaviours.Audio; using com.github.zehsteam.MonsterHotkeys.MonoBehaviours.UI; using com.github.zehsteam.MonsterHotkeys.MonoBehaviours.Utils; using com.github.zehsteam.MonsterHotkeys.NetcodePatcher; using com.github.zehsteam.MonsterHotkeys.Objects; using com.github.zehsteam.MonsterHotkeys.Objects.Enemies; using com.github.zehsteam.MonsterHotkeys.Objects.Network; using com.github.zehsteam.MonsterHotkeys.Patches; using com.github.zehsteam.MonsterHotkeys.Twitch; using com.github.zehsteam.MonsterHotkeys.Twitch.ChatCommands; using com.github.zehsteam.MonsterHotkeys.Twitch.ChatCommands.Commands.Developer; using com.github.zehsteam.MonsterHotkeys.Twitch.ChatCommands.Commands.Moderator; using com.github.zehsteam.MonsterHotkeys.Twitch.ChatCommands.Commands.Public; using com.github.zehsteam.MonsterHotkeys.Twitch.ChatCommands.Commands.Special; using com.github.zehsteam.MonsterHotkeys.Twitch.Managers; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: IgnoresAccessChecksTo("Assembly-CSharp-firstpass")] [assembly: IgnoresAccessChecksTo("Assembly-CSharp")] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("Zehs")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyCopyright("Copyright © 2026 Zehs")] [assembly: AssemblyDescription("Let Twitch chat spawn monsters with subs, bits, raids, and spawn points. Highly configurable, easy to use, no extension or app needed. (Twitch and CrowdControl integration)")] [assembly: AssemblyFileVersion("3.2.0.0")] [assembly: AssemblyInformationalVersion("3.2.0+4bae85c51a3e8f63a1762b26436a14cfccb9ca8f")] [assembly: AssemblyProduct("MonsterHotkeys")] [assembly: AssemblyTitle("com.github.zehsteam.MonsterHotkeys")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("3.2.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] [module: NetcodePatchedAssembly] [CompilerGenerated] internal sealed class <>z__ReadOnlyList<T> : IEnumerable, ICollection, IList, IEnumerable<T>, IReadOnlyCollection<T>, IReadOnlyList<T>, ICollection<T>, IList<T> { int ICollection.Count => _items.Count; bool ICollection.IsSynchronized => false; object ICollection.SyncRoot => this; object IList.this[int index] { get { return _items[index]; } set { throw new NotSupportedException(); } } bool IList.IsFixedSize => true; bool IList.IsReadOnly => true; int IReadOnlyCollection<T>.Count => _items.Count; T IReadOnlyList<T>.this[int index] => _items[index]; int ICollection<T>.Count => _items.Count; bool ICollection<T>.IsReadOnly => true; T IList<T>.this[int index] { get { return _items[index]; } set { throw new NotSupportedException(); } } public <>z__ReadOnlyList(List<T> items) { _items = items; } IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable)_items).GetEnumerator(); } void ICollection.CopyTo(Array array, int index) { ((ICollection)_items).CopyTo(array, index); } int IList.Add(object value) { throw new NotSupportedException(); } void IList.Clear() { throw new NotSupportedException(); } bool IList.Contains(object value) { return ((IList)_items).Contains(value); } int IList.IndexOf(object value) { return ((IList)_items).IndexOf(value); } void IList.Insert(int index, object value) { throw new NotSupportedException(); } void IList.Remove(object value) { throw new NotSupportedException(); } void IList.RemoveAt(int index) { throw new NotSupportedException(); } IEnumerator<T> IEnumerable<T>.GetEnumerator() { return ((IEnumerable<T>)_items).GetEnumerator(); } void ICollection<T>.Add(T item) { throw new NotSupportedException(); } void ICollection<T>.Clear() { throw new NotSupportedException(); } bool ICollection<T>.Contains(T item) { return _items.Contains(item); } void ICollection<T>.CopyTo(T[] array, int arrayIndex) { _items.CopyTo(array, arrayIndex); } bool ICollection<T>.Remove(T item) { throw new NotSupportedException(); } int IList<T>.IndexOf(T item) { return _items.IndexOf(item); } void IList<T>.Insert(int index, T item) { throw new NotSupportedException(); } void IList<T>.RemoveAt(int index) { throw new NotSupportedException(); } } [CompilerGenerated] internal sealed class <>z__ReadOnlySingleElementList<T> : IEnumerable, ICollection, IList, IEnumerable<T>, IReadOnlyCollection<T>, IReadOnlyList<T>, ICollection<T>, IList<T> { private sealed class Enumerator : IDisposable, IEnumerator, IEnumerator<T> { object IEnumerator.Current => _item; T IEnumerator<T>.Current => _item; public Enumerator(T item) { _item = item; } bool IEnumerator.MoveNext() { if (!_moveNextCalled) { return _moveNextCalled = true; } return false; } void IEnumerator.Reset() { _moveNextCalled = false; } void IDisposable.Dispose() { } } int ICollection.Count => 1; bool ICollection.IsSynchronized => false; object ICollection.SyncRoot => this; object IList.this[int index] { get { if (index != 0) { throw new IndexOutOfRangeException(); } return _item; } set { throw new NotSupportedException(); } } bool IList.IsFixedSize => true; bool IList.IsReadOnly => true; int IReadOnlyCollection<T>.Count => 1; T IReadOnlyList<T>.this[int index] { get { if (index != 0) { throw new IndexOutOfRangeException(); } return _item; } } int ICollection<T>.Count => 1; bool ICollection<T>.IsReadOnly => true; T IList<T>.this[int index] { get { if (index != 0) { throw new IndexOutOfRangeException(); } return _item; } set { throw new NotSupportedException(); } } public <>z__ReadOnlySingleElementList(T item) { _item = item; } IEnumerator IEnumerable.GetEnumerator() { return new Enumerator(_item); } void ICollection.CopyTo(Array array, int index) { array.SetValue(_item, index); } int IList.Add(object value) { throw new NotSupportedException(); } void IList.Clear() { throw new NotSupportedException(); } bool IList.Contains(object value) { return EqualityComparer<T>.Default.Equals(_item, (T)value); } int IList.IndexOf(object value) { if (!EqualityComparer<T>.Default.Equals(_item, (T)value)) { return -1; } return 0; } void IList.Insert(int index, object value) { throw new NotSupportedException(); } void IList.Remove(object value) { throw new NotSupportedException(); } void IList.RemoveAt(int index) { throw new NotSupportedException(); } IEnumerator<T> IEnumerable<T>.GetEnumerator() { return new Enumerator(_item); } void ICollection<T>.Add(T item) { throw new NotSupportedException(); } void ICollection<T>.Clear() { throw new NotSupportedException(); } bool ICollection<T>.Contains(T item) { return EqualityComparer<T>.Default.Equals(_item, item); } void ICollection<T>.CopyTo(T[] array, int arrayIndex) { array[arrayIndex] = _item; } bool ICollection<T>.Remove(T item) { throw new NotSupportedException(); } int IList<T>.IndexOf(T item) { if (!EqualityComparer<T>.Default.Equals(_item, item)) { return -1; } return 0; } void IList<T>.Insert(int index, T item) { throw new NotSupportedException(); } void IList<T>.RemoveAt(int index) { throw new NotSupportedException(); } } namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace com.github.zehsteam.MonsterHotkeys { internal static class Assets { public static readonly string AssetBundleFileName = "monsterhotkeys_assets"; public static AssetBundle AssetBundle { get; private set; } public static bool IsLoaded { get; private set; } public static GameObject PluginNetworkHandlerPrefab { get; private set; } public static GameObject PluginHUDPrefab { get; private set; } public static EnemyDatabase EnemyDatabase { get; private set; } public static void Load() { string directoryName = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); string text = Path.Combine(directoryName, AssetBundleFileName); if (!File.Exists(text)) { Logger.LogFatal("Failed to load assets. AssetBundle file could not be found at path \"" + text + "\". Make sure the \"" + AssetBundleFileName + "\" file is in the same folder as the mod's DLL file."); } else { AssetBundle = AssetBundle.LoadFromFile(text); if ((Object)(object)AssetBundle == (Object)null) { Logger.LogFatal("Failed to load assets. AssetBundle is null."); return; } OnAssetBundleLoaded(AssetBundle); IsLoaded = true; } } private static void OnAssetBundleLoaded(AssetBundle assetBundle) { PluginNetworkHandlerPrefab = LoadAsset<GameObject>("PluginNetworkHandler", assetBundle); PluginHUDPrefab = LoadAsset<GameObject>("PluginHUD", assetBundle); EnemyDatabase = LoadAsset<EnemyDatabase>("EnemyDatabase", 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 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_0057: Unknown result type (might be due to invalid IL or missing references) if (!((CallbackContext)(ref context)).performed || !CanPerformHotkeys()) { return; } string name = ((CallbackContext)(ref context)).action.name; Logger.LogInfo(name + " key pressed.", extended: true); if (DisableHotkeys && (IsMonsterPrefixKeyPressed || IsPlushiePrefixKeyPressed)) { MessageManger instance = MessageManger.Instance; if (instance != null) { Color? color = Color.red; instance.ShowMessage_LocalClient("Hotkeys have been disabled by another mod", new MessageSettings(null, color)); } Logger.LogInfo("Hotkeys have been disabled by another mod."); return; } string name2 = name.Replace("Spawn", "").Replace("Key", ""); if (!Assets.EnemyDatabase.TryGetDataByName(name2, out var enemyData)) { Logger.LogError("Failed to find EnemyData from key name \"" + name + "\""); return; } if (Plugin.InputActionsInstance.MonsterPrefixKey.IsPressed()) { EnemyHelper.SpawnEnemy(enemyData); } if (Plugin.InputActionsInstance.PlushiePrefixKey.IsPressed()) { PlushieManager.Instance.SpawnPlushies(enemyData.Name, PlayerUtils.LocalPlayerScript); } } private static void OnSpawnRandomKeyPressed(CallbackContext context) { //IL_0055: Unknown result type (might be due to invalid IL or missing references) if (!((CallbackContext)(ref context)).performed || !CanPerformHotkeys()) { return; } Logger.LogInfo(((CallbackContext)(ref context)).action.name + " key pressed.", extended: true); if (DisableHotkeys && (IsMonsterPrefixKeyPressed || IsPlushiePrefixKeyPressed)) { MessageManger instance = MessageManger.Instance; if (instance != null) { Color? color = Color.red; instance.ShowMessage_LocalClient("Hotkeys have been disabled by another mod", new MessageSettings(null, color)); } Logger.LogInfo("Hotkeys have been disabled by another mod."); } else { if (IsMonsterPrefixKeyPressed) { EnemyHelper.SpawnRandomEnemy(); } if (IsPlushiePrefixKeyPressed) { PlushieManager.Instance?.SpawnRandomPlushies(PlayerUtils.LocalPlayerScript); } } } public static bool CanPerformHotkeys() { PlayerControllerB localPlayerScript = PlayerUtils.LocalPlayerScript; 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; } } internal static class Logger { public static ManualLogSource ManualLogSource { get; private set; } public static bool IsExtendedLoggingEnabled => ConfigManager.Misc_ExtendedLogging?.Value ?? false; public static void Initialize(ManualLogSource manualLogSource) { ManualLogSource = manualLogSource; } public static void LogDebug(object data) { Log((LogLevel)32, data); } public static void LogInfo(object data, bool extended = false) { Log((LogLevel)16, data, extended); } public static void LogMessage(object data, bool extended = false) { Log((LogLevel)8, data, extended); } public static void LogWarning(object data, bool extended = false) { Log((LogLevel)4, data, extended); } public static void LogError(object data, bool extended = false) { Log((LogLevel)2, data, extended); } 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); } } } } [BepInPlugin("com.github.zehsteam.MonsterHotkeys", "MonsterHotkeys", "3.2.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!"); ((Object)this).hideFlags = (HideFlags)61; Object.DontDestroyOnLoad((Object)(object)this); _harmony.PatchAll(typeof(GameNetworkManager_Patches)); _harmony.PatchAll(typeof(StartOfRound_Patches)); _harmony.PatchAll(typeof(RoundManager_Patches)); _harmony.PatchAll(typeof(HUDManager_Patches)); _harmony.PatchAll(typeof(EnemyAI_Patches)); _harmony.PatchAll(typeof(RadMechAI_Patches)); _harmony.PatchAll(typeof(ButlerEnemyAI_Patches)); _harmony.PatchAll(typeof(Landmine_Patches)); if (CrowdControlProxy.IsInstalled) { CrowdControlProxy.PatchAll(_harmony); } GlobalSave = new JsonSave(Utils.GetPluginPersistentDataPath(), "GlobalSave"); LocalSave = new JsonSave(Paths.ConfigPath, "MonsterHotkeys_Save.json"); Assets.Load(); ConfigManager.Initialize(((BaseUnityPlugin)this).Config); InputActionsInstance = new HotkeyInputClass(); HotkeyListener.SetupKeybindCallbacks(); TwitchIntegrationManager.Initialize(); NetworkUtils.NetcodePatcherAwake(); PluginHelper.OnStart = (Action)Delegate.Combine(PluginHelper.OnStart, (Action)delegate { PlayerDamagePatcher.PatchAll(_harmony); }); PluginHelper.Spawn(); } private void Start() { PlayerDamagePatcher.PatchAll(_harmony); } } public static class MyPluginInfo { public const string PLUGIN_GUID = "com.github.zehsteam.MonsterHotkeys"; public const string PLUGIN_NAME = "MonsterHotkeys"; public const string PLUGIN_VERSION = "3.2.0"; } } namespace com.github.zehsteam.MonsterHotkeys.Twitch { internal static class TwitchIntegrationManager { public static bool IsEnabled => ConfigManager.TwitchIntegration_Enabled.Value; public static bool IsCheerEventEnabled { get { if (IsEnabled) { return ConfigManager.TwitchCheerEvent_Enabled.Value; } return false; } } public static bool IsSubEventEnabled { get { if (IsEnabled) { return ConfigManager.TwitchSubEvent_Enabled.Value; } return false; } } public static bool IsRaidEventEnabled { get { if (IsEnabled) { return ConfigManager.TwitchRaidEvent_Enabled.Value; } return false; } } public static 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() { TwitchEventHandler.Initialize(); TwitchEventQueue.Initialize(); AccumulatedBitManger.Initialize(); SpawnPointManager.Initialize(); TwitchCommandManager.Initialize(); } public static void OnDayEnded() { SpawnPointManager.OnDayEnded(); } public static void OnLocalDisconnect() { SpawnPointManager.OnLocalDisconnect(); } public static bool IsBotUser(TwitchUser twitchUser) { return TwitchBotUsernames.Contains(((TwitchUser)(ref twitchUser)).Username); } } } namespace com.github.zehsteam.MonsterHotkeys.Twitch.Managers { internal static class AccumulatedBitManger { private static Dictionary<string, int> _accumulatedBits = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase); public static IReadOnlyDictionary<string, int> AccumulatedBits => _accumulatedBits; public static void Initialize() { LoadData(); Application.quitting += SaveData; } private static void LoadData() { try { if (Plugin.GlobalSave.TryLoad<string>("AccumulatedBits", out var value)) { Logger.LogInfo("[AccumulatedBitManger] Loaded JSON data:\n\n" + value, extended: true); _accumulatedBits = JsonConvert.DeserializeObject<Dictionary<string, int>>(value); } } catch (Exception arg) { Logger.LogError(string.Format("[{0}] Failed to load JSON data: {1}", "AccumulatedBitManger", arg)); } } private static void SaveData() { if (Plugin.GlobalSave.Save("AccumulatedBits", JsonConvert.SerializeObject((object)_accumulatedBits))) { Logger.LogInfo("[AccumulatedBitManger] Saved JSON data.", extended: true); } else { Logger.LogError("[AccumulatedBitManger] Failed to save JSON data."); } } public static int Get(string username) { return _accumulatedBits.GetValueOrDefault(username.ToLower(), 0); } public static int Get(ViewerData viewer) { if (viewer == null) { return 0; } return Get(viewer.Username); } public static void Set(string username, int value) { if (value <= 0) { _accumulatedBits.Remove(username.ToLower()); } else { _accumulatedBits[username.ToLower()] = value; } SaveData(); } public static void Set(ViewerData viewer, int value) { if (viewer != null) { Set(viewer.Username, value); } } public static void Add(string username, int amount) { int num = Get(username); int value = num + amount; Set(username, value); } public static void Add(ViewerData viewer, int amount) { if (viewer != null) { Add(viewer.Username, amount); } } public static void Remove(string username, int amount) { Add(username, -amount); } public static void Remove(ViewerData viewer, int amount) { Add(viewer, -amount); } } internal static class SpawnPointManager { private static Dictionary<string, float> _spawnPoints = new Dictionary<string, float>(StringComparer.OrdinalIgnoreCase); public static int EnemiesSpawnedUsingPointsThisDay; public static bool IsEnabled { get { if (TwitchIntegrationManager.IsEnabled) { return ConfigManager.SpawnPoints_Enabled.Value; } return false; } } public static IReadOnlyDictionary<string, float> SpawnPoints => _spawnPoints; public static string UseSpawnPointText => $"Use !spawn = {PriceForEnemy}, !plushies = {PriceForPlushies}".RichColor("#00FF00"); public static float PriceForEnemy => ConfigManager.SpawnPoints_PriceForEnemy.Value; public static float PriceForPlushies => ConfigManager.SpawnPoints_PriceForPlushies.Value; public static int MaxEnemySpawnsPerDay => ConfigManager.SpawnPoints_MaxEnemySpawnsPerDay.Value; public static float RewardPointsPerDeath => ConfigManager.SpawnPoints_RewardPointsPerDeath.Value; public static float RewardPointsPerCrewmateDeath => ConfigManager.SpawnPoints_RewardPointsPerCrewmateDeath.Value; public static void Initialize() { LoadData(); Application.quitting += SaveData; } private static void LoadData() { try { if (Plugin.GlobalSave.TryLoad<string>("SpawnPoints", out var value)) { Logger.LogInfo("[SpawnPointManager] Loaded JSON data:\n\n" + value, extended: true); _spawnPoints = JsonConvert.DeserializeObject<Dictionary<string, float>>(value); } } catch (Exception arg) { Logger.LogError(string.Format("[{0}] Failed to load JSON data: {1}", "SpawnPointManager", arg)); } } private static void SaveData() { if (Plugin.GlobalSave.Save("SpawnPoints", JsonConvert.SerializeObject((object)_spawnPoints))) { Logger.LogInfo("[SpawnPointManager] Saved JSON data.", extended: true); } else { Logger.LogError("[SpawnPointManager] Failed to save JSON data."); } } public static float Get(string username) { return _spawnPoints.GetValueOrDefault(username.ToLower(), 0f); } public static float Get(ViewerData viewer) { if (viewer == null) { return 0f; } return Get(viewer.Username); } public static void Set(string username, float value, bool saveImmediately = true) { if (value <= 0f) { _spawnPoints.Remove(username.ToLower()); } else { _spawnPoints[username.ToLower()] = value; } if (saveImmediately) { SaveData(); } } public static void Set(ViewerData viewer, float value, bool saveImmediately = true) { if (viewer != null) { Set(viewer.Username, value, saveImmediately); } } public static void Add(string username, float amount, bool saveImmediately = true) { float num = Get(username); float value = num + amount; Set(username, value, saveImmediately); } public static void Add(ViewerData viewer, float amount, bool saveImmediately = true) { if (viewer != null) { Add(viewer.Username, amount, saveImmediately); } } public static void Remove(string username, float amount, bool saveImmediately = false) { Add(username, 0f - amount, saveImmediately); } public static void Remove(ViewerData viewer, float amount, bool saveImmediately = false) { Add(viewer, 0f - amount, saveImmediately); } public static void ResetAllSpawnPoints() { _spawnPoints.Clear(); SaveData(); Logger.LogInfo("Reset all spawn points."); } public static void OnDayEnded() { EnemiesSpawnedUsingPointsThisDay = 0; SaveData(); } public static void OnLocalDisconnect() { EnemiesSpawnedUsingPointsThisDay = 0; LoadData(); } public static void SpawnEnemiesUsingPoints(ViewerData viewer, int requestedSpawnCount, PlayerControllerB targetPlayerScript) { //IL_0129: Unknown result type (might be due to invalid IL or missing references) //IL_012f: Unknown result type (might be due to invalid IL or missing references) if (!IsEnabled || viewer == null || requestedSpawnCount <= 0 || !TwitchEventHandler.CanPlayEventsOnPlayer(targetPlayerScript)) { return; } float num = Get(viewer); if (num <= 0f) { return; } int maxEnemySpawnsPerDay = MaxEnemySpawnsPerDay; int num2 = maxEnemySpawnsPerDay - EnemiesSpawnedUsingPointsThisDay; if (num2 <= 0) { MessageManger.Instance?.ShowMessage_LocalClient($"The max amount of enemies ({maxEnemySpawnsPerDay}) have been spawned using spawn points for this day"); return; } if (requestedSpawnCount > maxEnemySpawnsPerDay) { requestedSpawnCount = maxEnemySpawnsPerDay; } if (requestedSpawnCount > num2) { requestedSpawnCount = num2; } float num3 = PriceForEnemy * (float)requestedSpawnCount; float num4; if (num3 > num) { requestedSpawnCount = (int)Mathf.Floor(num / PriceForEnemy); if (requestedSpawnCount <= 1) { return; } if (requestedSpawnCount > num2) { requestedSpawnCount = num2; } num4 = PriceForEnemy * (float)requestedSpawnCount; } else { num4 = num3; } Remove(viewer, num4); EnemiesSpawnedUsingPointsThisDay += requestedSpawnCount; float num5 = Get(viewer); string arg = ((num4 == 1f) ? "" : "s"); string spawnReason = $"by redeeming {num4} spawn point{arg} ({num5} remaining)"; int spawnCount = requestedSpawnCount; ulong? spawnedOnClientId = targetPlayerScript.actualClientId; SpawnEnemyData spawnEnemyData = new SpawnEnemyData(viewer, SpawnSource.Twitch, spawnCount, spawnReason, "", null, spawnedOnClientId); SpawnEventHandler.Instance?.ExecuteSpawnEnemyData_ServerRpc(spawnEnemyData); } public static void SpawnPlusheisUsingPoints(ViewerData viewer, PlayerControllerB targetPlayerScript) { //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) if (IsEnabled && viewer != null && !((Object)(object)PlushieManager.Instance == (Object)null) && PlushieManager.Instance.CanSpawnPlushiesOnPlayer(targetPlayerScript)) { float num = Get(viewer); if (!(num <= 0f) && !(num < PriceForPlushies)) { Remove(viewer, PriceForPlushies); float num2 = Get(viewer); string arg = ((PriceForPlushies == 1f) ? "" : "s"); string spawnReason = $"by redeeming {PriceForPlushies} spawn point{arg} ({num2} remaining)"; ulong? spawnedOnClientId = targetPlayerScript.actualClientId; SpawnPlushiesData spawnPlushiesData = new SpawnPlushiesData(viewer, SpawnSource.Twitch, spawnReason, "", null, spawnedOnClientId); SpawnEventHandler.Instance?.ExecuteSpawnPlushiesData_ServerRpc(spawnPlushiesData); } } } public static void RewardFromDeath(NametagData nametagData) { if (!IsEnabled) { return; } SpawnEnemyData spawnEnemyData = nametagData.SpawnEnemyData; if (!spawnEnemyData.IsFromViewer) { return; } bool value = ConfigManager.CrowdControl_RewardSpawnPoints.Value; if (spawnEnemyData.SpawnSource != SpawnSource.CrowdControl || value) { float rewardPointsPerDeath = RewardPointsPerDeath; if (!(rewardPointsPerDeath <= 0f)) { ViewerData viewer = spawnEnemyData.Viewer; Add(viewer, rewardPointsPerDeath); float num = Get(viewer); string displayNameWithReadableColor = viewer.GetDisplayNameWithReadableColor(); string text = ((rewardPointsPerDeath == 1f) ? "" : "s"); string message = $"{displayNameWithReadableColor} just earned {rewardPointsPerDeath} spawn point{text} ({num} total) {UseSpawnPointText}"; MessageManger.Instance?.ShowMessage_LocalClient(message); } } } public static void RewardFromCrewmateDeath(ulong crewmateClientId, NametagData nametagData) { if (!IsEnabled) { return; } SpawnEnemyData spawnEnemyData = nametagData.SpawnEnemyData; if (!spawnEnemyData.IsFromViewer || NetworkUtils.IsLocalClientId(crewmateClientId) || !NetworkUtils.IsLocalClientId(spawnEnemyData.SpawnedFromClientId)) { return; } bool value = ConfigManager.CrowdControl_RewardSpawnPoints.Value; if (spawnEnemyData.SpawnSource == SpawnSource.CrowdControl && !value) { return; } float rewardPointsPerCrewmateDeath = RewardPointsPerCrewmateDeath; if (!(rewardPointsPerCrewmateDeath <= 0f)) { PlayerControllerB playerScriptByClientId = PlayerUtils.GetPlayerScriptByClientId(crewmateClientId); if (!((Object)(object)playerScriptByClientId == (Object)null)) { ViewerData viewer = spawnEnemyData.Viewer; Add(viewer, rewardPointsPerCrewmateDeath); float num = Get(viewer); string displayNameWithReadableColor = viewer.GetDisplayNameWithReadableColor(); string text = ((rewardPointsPerCrewmateDeath == 1f) ? "" : "s"); string message = $"{displayNameWithReadableColor} just earned {rewardPointsPerCrewmateDeath} spawn point{text} by killing {playerScriptByClientId.playerUsername} ({num} total) {UseSpawnPointText}"; MessageManger.Instance?.ShowMessage_LocalClient(message); } } } } internal static class TargetPlayerManager { private static readonly Dictionary<string, PlayerControllerB> _targets = new Dictionary<string, PlayerControllerB>(StringComparer.OrdinalIgnoreCase); public static IReadOnlyDictionary<string, PlayerControllerB> Targets => _targets; public static PlayerControllerB GetTarget(string username) { return _targets.GetValueOrDefault(username.ToLower()); } public static bool TryGetTarget(string username, out PlayerControllerB playerScript) { return _targets.TryGetValue(username.ToLower(), out playerScript); } public static void SetTarget(string username, PlayerControllerB playerScript) { _targets[username.ToLower()] = playerScript; } public static void RemoveTarget(string username) { _targets.Remove(username.ToLower()); } } internal static class TwitchCheerHandler { public static int PriceForEnemy => ConfigManager.TwitchCheerEvent_AmountToSpawnEnemy.Value; public static int PriceForPlushies => ConfigManager.TwitchCheerEvent_AmountToSpawnPlushies.Value; public static void HandleCheer(TwitchCheerEvent cheerEvent) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) if (!TwitchIntegrationManager.IsCheerEventEnabled) { return; } if (cheerEvent == null) { Logger.LogError("[TwitchCheerHandler] Failed to handle cheer. TwitchCheerEvent is null."); return; } if (!TwitchEventHandler.CanPlayEventsOnLocalPlayer()) { TwitchEventQueue.Enqueue(cheerEvent); return; } int cheerAmount = cheerEvent.CheerAmount; ViewerData viewer = new ViewerData(((TwitchEvent)cheerEvent).User); if (PriceForEnemy == PriceForPlushies && cheerAmount == PriceForEnemy) { if (Utils.RollPercentChance(50f)) { SpawnEnemyFromExactAmount(cheerEvent, viewer); } else { SpawnPlushiesFromExactAmount(cheerEvent, viewer); } } else if (cheerAmount == PriceForEnemy) { SpawnEnemyFromExactAmount(cheerEvent, viewer); } else if (cheerAmount == PriceForPlushies) { SpawnPlushiesFromExactAmount(cheerEvent, viewer); } else { TrySpawnEnemies(cheerEvent, viewer); } } private static void SpawnPlushiesFromExactAmount(TwitchCheerEvent cheerEvent, ViewerData viewer) { SpawnPlushiesData spawnPlushiesData = new SpawnPlushiesData(viewer, SpawnSource.Twitch, $"by cheering {cheerEvent.CheerAmount} bits"); PlushieManager.Instance?.SpawnPlushiesFromData(spawnPlushiesData); } private static void SpawnEnemyFromExactAmount(TwitchCheerEvent cheerEvent, ViewerData viewer) { //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) string spawnReason = $"by cheering {cheerEvent.CheerAmount} bits"; SpawnEnemyData spawnEnemyData = new SpawnEnemyData(viewer, SpawnSource.Twitch, 1, spawnReason); SpawnEventHandler.Instance?.ExecuteSpawnEnemyData_ServerRpc(spawnEnemyData); } private static void TrySpawnEnemies(TwitchCheerEvent cheerEvent, ViewerData viewer) { int cheerAmount = cheerEvent.CheerAmount; int num = Mathf.FloorToInt((float)(cheerAmount / PriceForEnemy)); int num2 = AccumulatedBitManger.Get(viewer); int num3 = cheerAmount + num2; int num4 = Mathf.FloorToInt((float)(num3 / PriceForEnemy)); if (num4 > num) { SpawnEnemiesWithAccumulatedBits(cheerEvent, viewer); return; } if (num >= 1) { SpawnEnemiesFromExactOrExtraBits(cheerEvent, viewer); return; } AccumulatedBitManger.Add(viewer, cheerAmount); num2 = AccumulatedBitManger.Get(viewer); MessageManger.Instance?.ShowMessage_LocalClient($"{viewer.GetDisplayNameWithReadableColor()} didn't cheer enough to spawn anything. {cheerAmount} bits have been added to their accumulation pool ({num2} total / {PriceForEnemy})"); } private static void SpawnEnemiesFromExactOrExtraBits(TwitchCheerEvent cheerEvent, ViewerData viewer) { //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) int cheerAmount = cheerEvent.CheerAmount; int spawnCount = Mathf.FloorToInt((float)(cheerAmount / PriceForEnemy)); int num = cheerAmount % PriceForEnemy; int num2 = cheerAmount - num; string spawnReason = ((num <= 0) ? $"by cheering {num2} bits" : $"by cheering {num2} bits + {num} extra bits"); SpawnEnemyData spawnEnemyData = new SpawnEnemyData(viewer, SpawnSource.Twitch, spawnCount, spawnReason); SpawnEventHandler.Instance?.ExecuteSpawnEnemyData_ServerRpc(spawnEnemyData); if (num > 0) { AccumulatedBitManger.Add(viewer, num); int num3 = AccumulatedBitManger.Get(viewer); MessageManger.Instance?.ShowMessage_LocalClient($"{num} extra bits have been added to {viewer.GetDisplayNameWithReadableColor()}'s accumulation pool ({num3} total / {PriceForEnemy})"); } } private static void SpawnEnemiesWithAccumulatedBits(TwitchCheerEvent cheerEvent, ViewerData viewer) { //IL_0082: 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) int cheerAmount = cheerEvent.CheerAmount; int num = AccumulatedBitManger.Get(viewer); int num2 = cheerAmount + num; int spawnCount = Mathf.FloorToInt((float)(num2 / PriceForEnemy)); int num3 = num2 % PriceForEnemy; int num4 = Mathf.Max(num - num3, 0); string spawnReason = $"by cheering {cheerAmount} bits + {num4} accumulated bits"; SpawnEnemyData spawnEnemyData = new SpawnEnemyData(viewer, SpawnSource.Twitch, spawnCount, spawnReason); SpawnEventHandler.Instance?.ExecuteSpawnEnemyData_ServerRpc(spawnEnemyData); AccumulatedBitManger.Remove(viewer, num4); int num5 = AccumulatedBitManger.Get(viewer); MessageManger.Instance?.ShowMessage_LocalClient($"{viewer.GetDisplayNameWithReadableColor()} has {num5} / {PriceForEnemy} accumulated bits remaining"); } } internal static class TwitchEventHandler { public static void Initialize() { try { API.OnMessage += HandleMessage; API.OnCheer += HandleCheer; API.OnSub += HandleSub; API.OnRaid += HandleRaid; Application.quitting += delegate { API.OnMessage -= HandleMessage; API.OnCheer -= HandleCheer; API.OnSub -= HandleSub; API.OnRaid -= HandleRaid; }; } catch (Exception arg) { Logger.LogError(string.Format("[{0}] Failed to initialize. {1}", "TwitchEventHandler", arg)); } } public static void HandleMessage(TwitchMessage twitchMessage) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) if (TwitchIntegrationManager.IsEnabled) { TwitchCommandManager.Dispatch(twitchMessage); } } public static void HandleCheer(TwitchCheerEvent cheerEvent) { TwitchCheerHandler.HandleCheer(cheerEvent); } public static void HandleSub(TwitchSubEvent subEvent) { //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Invalid comparison between Unknown and I4 //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Invalid comparison between Unknown and I4 //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Invalid comparison between Unknown and I4 //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) if (!TwitchIntegrationManager.IsSubEventEnabled) { return; } if (subEvent == null) { Logger.LogError("[TwitchEventHandler] Failed to handle sub. TwitchSubEvent is null."); return; } if (!CanPlayEventsOnLocalPlayer()) { TwitchEventQueue.Enqueue(subEvent); 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; } ViewerData viewer = new ViewerData(((TwitchEvent)subEvent).User); string spawnReason = GetSpawnReason(subEvent); SpawnEnemyData spawnEnemyData = new SpawnEnemyData(viewer, SpawnSource.Twitch, num, spawnReason); SpawnEventHandler.Instance?.ExecuteSpawnEnemyData_ServerRpc(spawnEnemyData); } public static void HandleRaid(TwitchRaidEvent raidEvent) { //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) if (TwitchIntegrationManager.IsRaidEventEnabled) { if (raidEvent == null) { Logger.LogError("[TwitchEventHandler] Failed to handle raid. TwitchRaidEvent is null."); return; } if (!CanPlayEventsOnLocalPlayer()) { TwitchEventQueue.Enqueue(raidEvent); return; } int value = ConfigManager.TwitchRaidEvent_ViewersPerEnemy.Value; int value2 = ConfigManager.TwitchRaidEvent_MaxSpawnCount.Value; int spawnCount = Mathf.Clamp(raidEvent.ViewerCount / value, 1, value2); ViewerData viewer = new ViewerData(((TwitchEvent)raidEvent).User); string spawnReason = $"by raiding with {raidEvent.ViewerCount} viewers"; SpawnEnemyData spawnEnemyData = new SpawnEnemyData(viewer, SpawnSource.Twitch, spawnCount, spawnReason); SpawnEventHandler.Instance?.ExecuteSpawnEnemyData_ServerRpc(spawnEnemyData); } } private static string GetSpawnReason(TwitchSubEvent subEvent) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Invalid comparison between Unknown and I4 //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Invalid comparison between Unknown and I4 //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Expected I4, but got Unknown //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Invalid comparison between Unknown and I4 //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Expected I4, but got Unknown //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Expected I4, but got Unknown //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Expected I4, but got Unknown if (subEvent == null) { return string.Empty; } string result = string.Empty; if ((int)subEvent.Type == 0) { result = (((int)subEvent.Tier != 0) ? $"by subbing at tier {(int)subEvent.Tier}" : "by subbing with prime"); } else if ((int)subEvent.Type == 1) { result = (((int)subEvent.Tier != 0) ? $"by resubbing at tier {(int)subEvent.Tier} for {subEvent.CumulativeMonths} months" : $"by resubbing with prime for {subEvent.CumulativeMonths} months"); } else if ((int)subEvent.Type == 2) { result = $"by gifting a tier {(int)subEvent.Tier} sub to {subEvent.RecipientUser}"; } else if ((int)subEvent.Type == 3) { result = $"by gifting {subEvent.GiftCount} tier {(int)subEvent.Tier} subs"; } return result; } public static bool CanPlayEventsOnPlayer(PlayerControllerB playerScript) { if (!TwitchIntegrationManager.IsEnabled) { return false; } return EnemyHelper.CanSpawnEnemiesOnPlayer(playerScript); } public static bool CanPlayEventsOnLocalPlayer() { return CanPlayEventsOnPlayer(PlayerUtils.LocalPlayerScript); } } internal static class TwitchEventQueue { [CompilerGenerated] private sealed class <PlayQueuedEventsCoroutine>d__18 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public TimeSpan initialDelay; private TimeSpan <delayBetweenEvents>5__2; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <PlayQueuedEventsCoroutine>d__18(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Expected O, but got Unknown //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_0103: Expected O, but got Unknown //IL_0146: Unknown result type (might be due to invalid IL or missing references) //IL_0150: Expected O, but got Unknown //IL_0193: Unknown result type (might be due to invalid IL or missing references) //IL_019d: Expected O, but got Unknown TwitchSubEvent result; TwitchCheerEvent result2; switch (<>1__state) { default: return false; case 0: <>1__state = -1; Logger.LogInfo(string.Format("[{0}] Playing queued events after {1} seconds.", "TwitchEventQueue", (float)initialDelay.TotalSeconds), extended: true); <>2__current = (object)new WaitForSeconds((float)initialDelay.TotalSeconds); <>1__state = 1; return true; case 1: <>1__state = -1; if (!TwitchEventHandler.CanPlayEventsOnLocalPlayer()) { Logger.LogWarning("[TwitchEventQueue] Failed to play queued events. You are not allowed to play events at this time."); return false; } if (!HasQueuedEvents()) { Logger.LogInfo("[TwitchEventQueue] No events in the queue to play.", extended: true); return false; } MessageManger.Instance?.ShowMessage_LocalClient("Playing Twitch events from the queue"); <delayBetweenEvents>5__2 = TimeSpan.FromSeconds(0.5); goto IL_00c8; case 2: <>1__state = -1; goto IL_00c8; case 3: <>1__state = -1; goto IL_0115; case 4: { <>1__state = -1; break; } IL_0115: if (TwitchIntegrationManager.IsSubEventEnabled && _subQueue.TryDequeue(out result)) { if (!TwitchEventHandler.CanPlayEventsOnLocalPlayer()) { return false; } TwitchEventHandler.HandleSub(result); <>2__current = (object)new WaitForSeconds((float)<delayBetweenEvents>5__2.TotalSeconds); <>1__state = 3; return true; } break; IL_00c8: if (TwitchIntegrationManager.IsCheerEventEnabled && _cheerQueue.TryDequeue(out result2)) { if (!TwitchEventHandler.CanPlayEventsOnLocalPlayer()) { return false; } TwitchEventHandler.HandleCheer(result2); <>2__current = (object)new WaitForSeconds((float)<delayBetweenEvents>5__2.TotalSeconds); <>1__state = 2; return true; } goto IL_0115; } if (TwitchIntegrationManager.IsRaidEventEnabled && _raidQueue.TryDequeue(out var result3)) { if (!TwitchEventHandler.CanPlayEventsOnLocalPlayer()) { return false; } TwitchEventHandler.HandleRaid(result3); <>2__current = (object)new WaitForSeconds((float)<delayBetweenEvents>5__2.TotalSeconds); <>1__state = 4; return true; } Logger.LogInfo("[TwitchEventQueue] Finished plyaing queued events.", extended: true); SaveData(); _playQueuedEventsCoroutine = null; return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } private static Queue<TwitchCheerEvent> _cheerQueue = new Queue<TwitchCheerEvent>(); private static Queue<TwitchSubEvent> _subQueue = new Queue<TwitchSubEvent>(); private static Queue<TwitchRaidEvent> _raidQueue = new Queue<TwitchRaidEvent>(); private static Coroutine _playQueuedEventsCoroutine; public static IReadOnlyCollection<TwitchCheerEvent> CheerQueue => _cheerQueue; public static IReadOnlyCollection<TwitchSubEvent> SubQueue => _subQueue; public static IReadOnlyCollection<TwitchRaidEvent> RaidQueue => _raidQueue; public static void Initialize() { LoadData(); Application.quitting += SaveData; } private static void LoadData() { Logger.LogInfo("[TwitchEventQueue] Loading saved data..."); try { if (Plugin.GlobalSave.TryLoad<string>("CheerQueue", out var value)) { _cheerQueue = QueueJsonConverterHelper.DeserializeQueue<TwitchCheerEvent>(value); Logger.LogInfo("[TwitchEventQueue] Loaded CheerQueue JSON data:\n\n" + value, extended: true); } if (Plugin.GlobalSave.TryLoad<string>("SubQueue", out value)) { _subQueue = QueueJsonConverterHelper.DeserializeQueue<TwitchSubEvent>(value); Logger.LogInfo("[TwitchEventQueue] Loaded SubQueue JSON data:\n\n" + value, extended: true); } if (Plugin.GlobalSave.TryLoad<string>("RaidQueue", out value)) { _raidQueue = QueueJsonConverterHelper.DeserializeQueue<TwitchRaidEvent>(value); Logger.LogInfo("[TwitchEventQueue] Loaded RaidQueue JSON data:\n\n" + value, extended: true); } Logger.LogInfo("[TwitchEventQueue] Finished loading saved data."); } catch (Exception arg) { Logger.LogError(string.Format("[{0}] Failed to load saved data. {1}", "TwitchEventQueue", arg)); } } private static void SaveData() { Logger.LogInfo("[TwitchEventQueue] Saving data...", extended: true); try { SaveCheerQueue(); SaveSubQueue(); SaveRaidQueue(); Logger.LogInfo("[TwitchEventQueue] Saved data.", extended: true); } catch (Exception arg) { Logger.LogError(string.Format("[{0}] Failed to save data. {1}", "TwitchEventQueue", arg)); } } private static void SaveCheerQueue() { try { Plugin.GlobalSave.Save("CheerQueue", QueueJsonConverterHelper.SerializeQueue(_cheerQueue)); } catch (Exception arg) { Logger.LogError(string.Format("[{0}] {1}: Failed to save data. {2}", "TwitchEventQueue", "SaveCheerQueue", arg)); } } private static void SaveSubQueue() { try { Plugin.GlobalSave.Save("SubQueue", QueueJsonConverterHelper.SerializeQueue(_subQueue)); } catch (Exception arg) { Logger.LogError(string.Format("[{0}] {1}: Failed to save data. {2}", "TwitchEventQueue", "SaveSubQueue", arg)); } } private static void SaveRaidQueue() { try { Plugin.GlobalSave.Save("RaidQueue", QueueJsonConverterHelper.SerializeQueue(_raidQueue)); } catch (Exception arg) { Logger.LogError(string.Format("[{0}] {1}: Failed to save data. {2}", "TwitchEventQueue", "SaveRaidQueue", arg)); } } public static void PlayQueuedEvents() { PlayQueuedEvents(TimeSpan.Zero); } public static void PlayQueuedEvents(TimeSpan initialDelay) { if (!TwitchIntegrationManager.IsEnabled) { Logger.LogWarning("[TwitchEventQueue] Failed to play queued events. Twitch integration is not enabled."); return; } if ((Object)(object)SpawnEventHandler.Instance == (Object)null) { Logger.LogWarning("[TwitchEventQueue] Failed to play queued events. ViewerSpawnEventHandler instance is null."); return; } if (_playQueuedEventsCoroutine != null) { CoroutineRunner.Stop(_playQueuedEventsCoroutine); } _playQueuedEventsCoroutine = CoroutineRunner.Start(PlayQueuedEventsCoroutine(initialDelay)); } [IteratorStateMachine(typeof(<PlayQueuedEventsCoroutine>d__18))] private static IEnumerator PlayQueuedEventsCoroutine(TimeSpan initialDelay) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <PlayQueuedEventsCoroutine>d__18(0) { initialDelay = initialDelay }; } public static bool HasQueuedEvents() { if (_cheerQueue.Count <= 0 && _subQueue.Count <= 0) { return _raidQueue.Count > 0; } return true; } public static void Enqueue(TwitchCheerEvent cheerEvent) { if (!_cheerQueue.Contains(cheerEvent)) { _cheerQueue.Enqueue(cheerEvent); SaveCheerQueue(); ShowEnqueueMessage((TwitchEvent)(object)cheerEvent, "cheer"); } } public static void Enqueue(TwitchSubEvent subEvent) { if (!_subQueue.Contains(subEvent)) { _subQueue.Enqueue(subEvent); SaveSubQueue(); ShowEnqueueMessage((TwitchEvent)(object)subEvent, "sub"); } } public static void Enqueue(TwitchRaidEvent raidEvent) { if (!_raidQueue.Contains(raidEvent)) { _raidQueue.Enqueue(raidEvent); SaveRaidQueue(); ShowEnqueueMessage((TwitchEvent)(object)raidEvent, "raid"); } } private static void ShowEnqueueMessage(TwitchEvent twitchEvent, string eventName) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) string displayNameWithReadableColor = twitchEvent.User.GetDisplayNameWithReadableColor(); string message = "Added Twitch " + eventName + " event from " + displayNameWithReadableColor + " to queue"; MessageManger.Instance?.ShowMessage_LocalClient(message); } } } namespace com.github.zehsteam.MonsterHotkeys.Twitch.ChatCommands { public class ParsedArgs { private readonly Dictionary<string, string> _named; private readonly List<string> _positional; public IReadOnlyDictionary<string, string> Named => _named; public IReadOnlyList<string> Positional => _positional; public ParsedArgs(Dictionary<string, string> named, List<string> positional) { _named = named; _positional = positional; } public bool HasFlag(string key) { return _named.ContainsKey(key); } public bool TryGet(string key, out string value) { return _named.TryGetValue(key, out value); } public string Get(string key, string defaultValue = "") { if (!TryGet(key, out var value)) { return defaultValue; } return value; } public bool TryGetInt(string key, out int value) { return int.TryParse(Get(key), out value); } public int GetInt(string key, int defaultValue = 0) { if (!TryGetInt(key, out var value)) { return defaultValue; } return value; } public bool TryGetFloat(string key, out float value) { return float.TryParse(Get(key), out value); } public float GetFloat(string key, float defaultValue = 0f) { if (!TryGetFloat(key, out var value)) { return defaultValue; } return value; } public bool TryGetPositional(int index, out string value) { if (index >= _positional.Count) { value = null; return false; } value = _positional[index]; return true; } public string GetPositional(int index, string defaultValue = "") { if (!TryGetPositional(index, out var value)) { return defaultValue; } return value; } public bool TryGetPositionalInt(int index, out int value) { if (!TryGetPositional(index, out var value2)) { value = 0; return false; } return int.TryParse(value2, out value); } public int GetPositionalInt(int index, int defaultValue = 0) { if (!TryGetPositionalInt(index, out var value)) { return defaultValue; } return value; } public bool TryGetPositionalFloat(int index, out float value) { if (!TryGetPositional(index, out var value2)) { value = 0f; return false; } return float.TryParse(value2, out value); } public float GetPositionalFloat(int index, float defaultValue = 0f) { if (!TryGetPositionalFloat(index, out var value)) { return defaultValue; } return value; } public static ParsedArgs Parse(string[] args) { Dictionary<string, string> dictionary = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); List<string> list = new List<string>(); int num = 0; while (num < args.Length) { string text = args[num]; if (text.StartsWith("--")) { string text2 = text; string key = text2.Substring(2, text2.Length - 2); if (num + 1 >= args.Length || args[num + 1].StartsWith("--")) { dictionary[key] = "true"; num++; } else { dictionary[key] = args[num + 1]; num += 2; } } else { list.Add(text); num++; } } return new ParsedArgs(dictionary, list); } } internal abstract class TwitchCommand { private ConfigEntry<bool> _enabled; private bool _boundConfigs; public abstract string Name { get; } public abstract bool EnabledByDefault { get; } public abstract bool EnableConfigs { get; } public bool IsEnabled => _enabled?.Value ?? EnabledByDefault; public abstract void Execute(TwitchMessage twitchMessage, string[] args); public void PreBindConfigs() { if (!_boundConfigs) { _boundConfigs = true; string section = "Command: " + Name; _enabled = ConfigHelper.Bind(section, "Enabled", EnabledByDefault, "Enable " + Name + " Twitch chat command."); BindConfigs(section); } } protected virtual void BindConfigs(string section) { } protected string ParseUsername(string input) { return input.Replace("@", ""); } } internal static class TwitchCommandManager { private static readonly Dictionary<string, TwitchCommand> _commands = new Dictionary<string, TwitchCommand>(StringComparer.OrdinalIgnoreCase); public static bool IsEnabled => ConfigManager.TwitchChatCommands_Enabled.Value; public static string Prefix => ConfigManager.TwitchChatCommands_Prefix.Value; public static IReadOnlyDictionary<string, TwitchCommand> Commands => _commands; public static void Initialize() { Register(new DevSpawnCommand()); Register(new DevPlushiesCommand()); Register(new DevCheerCommand()); Register(new DevSubCommand()); Register(new DevRaidCommand()); Register(new PlayQueueCommand()); Register(new ViewConfigCommand()); Register(new SetConfigCommand()); Register(new GiveSpawnCommand()); Register(new GiveSpawnRandomCommand()); Register(new InfoCommand()); Register(new ViewPlayersCommand()); Register(new ViewAllSpawnCommand()); Register(new ViewAllBitsCommand()); Register(new LustySpawnCommand()); Register(new SpawnCommand()); Register(new CrewSpawnCommand()); Register(new PlushiesCommand()); Register(new CrewPlushiesCommand()); Register(new ViewSpawnCommand()); Register(new ViewBitsCommand()); Register(new TargetCommand()); Register(new ClearTargetCommand()); Register(new ViewTargetCommand()); } public static void Register(TwitchCommand command) { _commands[command.Name] = command; if (command.EnableConfigs) { command.PreBindConfigs(); } } public static void Dispatch(TwitchMessage twitchMessage) { //IL_0078: Unknown result type (might be due to invalid IL or missing references) if (!IsEnabled) { return; } string message = ((TwitchMessage)(ref twitchMessage)).Message; if (string.IsNullOrWhiteSpace(message) || !message.StartsWith(Prefix)) { return; } string[] array = Tokenize(message.Trim()); if (array.Length == 0) { return; } string key = array[0].Substring(Prefix.Length); if (!_commands.TryGetValue(key, out var value) || !value.IsEnabled) { return; } string[] subArray = array[1..]; try { value.Execute(twitchMessage, subArray); } catch (Exception arg) { Logger.LogError(string.Format("[{0}] Error running command \"{1}\". {2}", "TwitchCommandManager", value.GetType().Name, arg)); } } private static string[] Tokenize(string input) { List<string> list = new List<string>(); StringBuilder stringBuilder = new StringBuilder(); bool flag = false; char c = '"'; foreach (char c2 in input) { if (flag) { if (c2 == c) { flag = false; } else { stringBuilder.Append(c2); } } else if (c2 == '"' || c2 == '\'') { flag = true; c = c2; } else if (char.IsWhiteSpace(c2)) { if (stringBuilder.Length > 0) { list.Add(stringBuilder.ToString()); stringBuilder.Clear(); } } else { stringBuilder.Append(c2); } } if (stringBuilder.Length > 0) { list.Add(stringBuilder.ToString()); } return list.ToArray(); } } } namespace com.github.zehsteam.MonsterHotkeys.Twitch.ChatCommands.Commands.Special { internal class LustySpawnCommand : TwitchCommand { public override string Name => "lustyspawn"; public override bool EnabledByDefault => true; public override bool EnableConfigs => false; public override void Execute(TwitchMessage twitchMessage, string[] args) { //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_0020: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) TwitchUser user = ((TwitchMessage)(ref twitchMessage)).User; if (((TwitchUser)(ref user)).Username.Equals_OrdinalIgnoreCase("LustStings") || ((TwitchMessage)(ref twitchMessage)).User.IsDeveloper()) { ParsedArgs parsedArgs = ParsedArgs.Parse(args); string targetEnemyName = parsedArgs.GetPositional(0, "Blob"); int spawnCount = parsedArgs.GetPositionalInt(1, 69); string targetPlayerUsername = parsedArgs.GetPositional(2); string spawnReason = "by being susty"; if (parsedArgs.TryGet("enemy", out var value)) { targetEnemyName = value; } if (parsedArgs.TryGetInt("count", out var value2)) { spawnCount = value2; } if (parsedArgs.TryGetInt("amount", out value2)) { spawnCount = value2; } if (parsedArgs.TryGet("target", out value)) { targetPlayerUsername = value; } if (parsedArgs.TryGet("reason", out value)) { spawnReason = value; } ViewerData viewer = new ViewerData(((TwitchMessage)(ref twitchMessage)).User); DevSpawnCommand.SpawnEnemy(viewer, spawnCount, spawnReason, targetEnemyName, targetPlayerUsername, null, 69); } } } } namespace com.github.zehsteam.MonsterHotkeys.Twitch.ChatCommands.Commands.Public { internal class ClearTargetCommand : TwitchCommand { public override string Name => "cleartarget"; public override bool EnabledByDefault => true; public override bool EnableConfigs => false; public override void Execute(TwitchMessage twitchMessage, string[] args) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) string displayNameWithReadableColor = ((TwitchMessage)(ref twitchMessage)).User.GetDisplayNameWithReadableColor(); TwitchUser user = ((TwitchMessage)(ref twitchMessage)).User; PlayerControllerB target = TargetPlayerManager.GetTarget(((TwitchUser)(ref user)).Username); if ((Object)(object)target == (Object)null) { MessageManger.Instance?.ShowMessage_LocalClient(displayNameWithReadableColor + " is not targeting anyone"); return; } user = ((TwitchMessage)(ref twitchMessage)).User; TargetPlayerManager.RemoveTarget(((TwitchUser)(ref user)).Username); MessageManger.Instance?.ShowMessage_LocalClient(displayNameWithReadableColor + " has stopped targeting " + target.playerUsername); } } internal class CrewPlushiesCommand : TwitchCommand { public override string Name => "crewplushies"; public override bool EnabledByDefault => true; public override bool EnableConfigs => true; public override void Execute(TwitchMessage twitchMessage, string[] args) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) if (!SpawnPointManager.IsEnabled) { return; } ParsedArgs parsedArgs = ParsedArgs.Parse(args); string positional = parsedArgs.GetPositional(0); string displayNameWithReadableColor = ((TwitchMessage)(ref twitchMessage)).User.GetDisplayNameWithReadableColor(); PlayerControllerB playerScript; if (!string.IsNullOrWhiteSpace(positional)) { if (!PlayerUtils.TryGetPlayerScriptByUsername(positional, out playerScript)) { MessageManger.Instance?.ShowMessage_LocalClient(displayNameWithReadableColor + " no player was found with the name \"" + positional + "\""); return; } if (PlayerUtils.IsLocalPlayer(playerScript)) { MessageManger.Instance?.ShowMessage_LocalClient(displayNameWithReadableColor + " you can not target the local player"); return; } } else { TwitchUser user = ((TwitchMessage)(ref twitchMessage)).User; if (!TargetPlayerManager.TryGetTarget(((TwitchUser)(ref user)).Username, out playerScript)) { playerScript = PlayerUtils.GetRandomPlayerScript(PlayerUtils.AlivePlayerScripts, excludeLocal: true); } } if (!((Object)(object)playerScript == (Object)null)) { ViewerData viewer = new ViewerData(((TwitchMessage)(ref twitchMessage)).User); SpawnPointManager.SpawnPlusheisUsingPoints(viewer, playerScript); } } } internal class CrewSpawnCommand : TwitchCommand { public override string Name => "crewspawn"; public override bool EnabledByDefault => true; public override bool EnableConfigs => true; public override void Execute(TwitchMessage twitchMessage, string[] args) { //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Unknown result type (might be due to invalid IL or missing references) if (!SpawnPointManager.IsEnabled) { return; } int num = 1; string text = string.Empty; ParsedArgs parsedArgs = ParsedArgs.Parse(args); if (parsedArgs.TryGetPositionalInt(0, out var value)) { num = value; } else { text = ParseUsername(parsedArgs.GetPositional(0)); } string value2; if (parsedArgs.TryGetPositionalInt(1, out value)) { num = value; } else if (string.IsNullOrWhiteSpace(text) && parsedArgs.TryGetPositional(1, out value2)) { text = value2; } if (num <= 0) { return; } string displayNameWithReadableColor = ((TwitchMessage)(ref twitchMessage)).User.GetDisplayNameWithReadableColor(); PlayerControllerB playerScript; if (!string.IsNullOrWhiteSpace(text)) { if (!PlayerUtils.TryGetPlayerScriptByUsername(text, out playerScript)) { MessageManger.Instance?.ShowMessage_LocalClient(displayNameWithReadableColor + " no player was found with the name \"" + text + "\""); return; } if (PlayerUtils.IsLocalPlayer(playerScript)) { MessageManger.Instance?.ShowMessage_LocalClient(displayNameWithReadableColor + " you can not target the local player"); return; } } else { TwitchUser user = ((TwitchMessage)(ref twitchMessage)).User; if (!TargetPlayerManager.TryGetTarget(((TwitchUser)(ref user)).Username, out playerScript)) { playerScript = PlayerUtils.GetRandomPlayerScript(PlayerUtils.AlivePlayerScripts, excludeLocal: true); } } if (!((Object)(object)playerScript == (Object)null)) { ViewerData viewer = new ViewerData(((TwitchMessage)(ref twitchMessage)).User); SpawnPointManager.SpawnEnemiesUsingPoints(viewer, num, playerScript); } } } internal class PlushiesCommand : TwitchCommand { public override string Name => "plushies"; public override bool EnabledByDefault => true; public override bool EnableConfigs => true; public override void Execute(TwitchMessage twitchMessage, string[] args) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) if (SpawnPointManager.IsEnabled) { ViewerData viewer = new ViewerData(((TwitchMessage)(ref twitchMessage)).User); SpawnPointManager.SpawnPlusheisUsingPoints(viewer, PlayerUtils.LocalPlayerScript); } } } internal class SpawnCommand : TwitchCommand { public override string Name => "spawn"; public override bool EnabledByDefault => true; public override bool EnableConfigs => true; public override void Execute(TwitchMessage twitchMessage, string[] args) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) if (SpawnPointManager.IsEnabled) { ParsedArgs parsedArgs = ParsedArgs.Parse(args); int positionalInt = parsedArgs.GetPositionalInt(0, 1); if (positionalInt > 0) { ViewerData viewer = new ViewerData(((TwitchMessage)(ref twitchMessage)).User); SpawnPointManager.SpawnEnemiesUsingPoints(viewer, positionalInt, PlayerUtils.LocalPlayerScript); } } } } internal class TargetCommand : TwitchCommand { private ConfigEntry<string> _excludePlayers; public override string Name => "target"; public override bool EnabledByDefault => true; public override bool EnableConfigs => true; public string[] ExcludePlayersArray => _excludePlayers.Value.StringToCollection<string>().ToArray(); public override void Execute(TwitchMessage twitchMessage, string[] args) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Unknown result type (might be due to invalid IL or missing references) string displayNameWithReadableColor = ((TwitchMessage)(ref twitchMessage)).User.GetDisplayNameWithReadableColor(); if (args.Length < 1) { MessageManger.Instance?.ShowMessage_LocalClient(displayNameWithReadableColor + " must specify a target username in the command. Partial usernames will work too. " + TwitchCommandManager.Prefix + Name + " <username>"); return; } string text = ParseUsername(args[0]); if (!PlayerUtils.TryGetPlayerScriptByUsername(text, out var playerScript)) { MessageManger.Instance?.ShowMessage_LocalClient(displayNameWithReadableColor + " no player was found with the name \"" + text + "\""); return; } if (ExcludePlayersArray.Contains<string>(playerScript.playerUsername, StringComparer.OrdinalIgnoreCase)) { MessageManger.Instance?.ShowMessage_LocalClient(displayNameWithReadableColor + " you are not able to target " + playerScript.playerUsername); return; } if (PlayerUtils.IsLocalPlayer(playerScript)) { MessageManger.Instance?.ShowMessage_LocalClient(displayNameWithReadableColor + " you can not target the local player"); return; } TwitchUser user = ((TwitchMessage)(ref twitchMessage)).User; TargetPlayerManager.SetTarget(((TwitchUser)(ref user)).Username, playerScript); string message = displayNameWithReadableColor + " is now targeting " + playerScript.playerUsername; MessageManger.Instance?.ShowMessage_LocalClient(message); } protected override void BindConfigs(string section) { _excludePlayers = ConfigHelper.Bind(section, "ExcludePlayers", "", "List of players to exclude from being targeted. Comma-separated list of player usernames."); } } internal class ViewBitsCommand : TwitchCommand { public override string Name => "viewbits"; public override bool EnabledByDefault => true; public override bool EnableConfigs => false; public override void Execute(TwitchMessage twitchMessage, string[] args) { //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) ParsedArgs parsedArgs = ParsedArgs.Parse(args); string text = ParseUsername(parsedArgs.GetPositional(0)); string text2; string colorHex; if (!string.IsNullOrWhiteSpace(text) && text.Length >= 4) { TwitchUser val = default(TwitchUser); if (API.TryGetUserByUsername(text, ref val)) { text2 = ((TwitchUser)(ref val)).DisplayName; colorHex = ((TwitchUser)(ref val)).Color; } else { text2 = text; colorHex = "#FFFFFF"; } } else { TwitchUser user = ((TwitchMessage)(ref twitchMessage)).User; text2 = ((TwitchUser)(ref user)).DisplayName; user = ((TwitchMessage)(ref twitchMessage)).User; colorHex = ((TwitchUser)(ref user)).Color; } int num = AccumulatedBitManger.Get(text2); string arg = ((num == 1) ? "" : "s"); MessageManger.Instance?.ShowMessage_LocalClient($"{text2.RichReadableColor(colorHex)} has {num} accumulated bit{arg}"); } } internal class ViewSpawnCommand : TwitchCommand { public override string Name => "viewspawn"; public override bool EnabledByDefault => true; public override bool EnableConfigs => false; public override void Execute(TwitchMessage twitchMessage, string[] args) { //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) if (!SpawnPointManager.IsEnabled) { return; } ParsedArgs parsedArgs = ParsedArgs.Parse(args); string text = ParseUsername(parsedArgs.GetPositional(0)); string text2; string colorHex; if (!string.IsNullOrWhiteSpace(text) && text.Length >= 4) { TwitchUser val = default(TwitchUser); if (API.TryGetUserByUsername(text, ref val)) { text2 = ((TwitchUser)(ref val)).DisplayName; colorHex = ((TwitchUser)(ref val)).Color; } else { text2 = text; colorHex = "#FFFFFF"; } } else { TwitchUser user = ((TwitchMessage)(ref twitchMessage)).User; text2 = ((TwitchUser)(ref user)).DisplayName; user = ((TwitchMessage)(ref twitchMessage)).User; colorHex = ((TwitchUser)(ref user)).Color; } float num = SpawnPointManager.Get(text2); string arg = ((num == 1f) ? "" : "s"); MessageManger.Instance?.ShowMessage_LocalClient($"{text2.RichReadableColor(colorHex)} has {num} spawn point{arg}"); } } internal class ViewTargetCommand : TwitchCommand { public override string Name => "viewtarget"; public override bool EnabledByDefault => true; public override bool EnableConfigs => false; public override void Execute(TwitchMessage twitchMessage, string[] args) { //IL_0018: 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_0007: Unknown result type (might be due to invalid IL or missing references) if (args.Length > 1) { ExecuteForViewer(twitchMessage, ParseUsername(args[0])); return; } TwitchMessage twitchMessage2 = twitchMessage; TwitchUser user = ((TwitchMessage)(ref twitchMessage)).User; ExecuteForViewer(twitchMessage2, ((TwitchUser)(ref user)).Username); } private void ExecuteForViewer(TwitchMessage twitchMessage, string targetViewerUsername) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) string s = targetViewerUsername; string colorHex = "#FFFFFF"; TwitchUser user = ((TwitchMessage)(ref twitchMessage)).User; TwitchUser val = default(TwitchUser); if (((TwitchUser)(ref user)).Username == targetViewerUsername) { user = ((TwitchMessage)(ref twitchMessage)).User; s = ((TwitchUser)(ref user)).DisplayName; user = ((TwitchMessage)(ref twitchMessage)).User; colorHex = ((TwitchUser)(ref user)).Color; } else if (API.TryGetUserByUsername(targetViewerUsername, ref val)) { s = ((TwitchUser)(ref val)).DisplayName; colorHex = ((TwitchUser)(ref val)).Color; } string text = s.RichReadableColor(colorHex); PlayerControllerB target = TargetPlayerManager.GetTarget(targetViewerUsername); if ((Object)(object)target == (Object)null) { MessageManger.Instance?.ShowMessage_LocalClient(text + " is not targeting anyone"); } else { MessageManger.Instance?.ShowMessage_LocalClient(text + " is targeting " + target.playerUsername); } } } } namespace com.github.zehsteam.MonsterHotkeys.Twitch.ChatCommands.Commands.Moderator { internal class GiveSpawnCommand : TwitchCommand { public override string Name => "givespawn"; public override bool EnabledByDefault => true; public override bool EnableConfigs => false; public override void Execute(TwitchMessage twitchMessage, string[] args) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) if (!SpawnPointManager.IsEnabled || !((TwitchMessage)(ref twitchMessage)).User.IsModeratorOrHigher()) { return; } string displayNameWithReadableColor = ((TwitchMessage)(ref twitchMessage)).User.GetDisplayNameWithReadableColor(); ParsedArgs parsedArgs = ParsedArgs.Parse(args); string text = ParseUsername(parsedArgs.GetPositional(0)); if (string.IsNullOrWhiteSpace(text) || text.Length < 4) { MessageManger.Instance?.ShowMessage_LocalClient(displayNameWithReadableColor + " command usage is " + TwitchCommandManager.Prefix + Name + " <target_username> <amount>"); return; } float positionalFloat = parsedArgs.GetPositionalFloat(1, SpawnPointManager.PriceForEnemy); string s = text; string colorHex = "#FFFFFF"; TwitchUser val = default(TwitchUser); if (API.TryGetUserByUsername(text, ref val)) { s = ((TwitchUser)(ref val)).DisplayName; colorHex = ((TwitchUser)(ref val)).Color; } string text2 = s.RichReadableColor(colorHex); SpawnPointManager.Add(text, positionalFloat); float num = SpawnPointManager.Get(text); string text3 = ((positionalFloat > 0f) ? "gave" : "removed"); string text4 = ((positionalFloat == 1f) ? "" : "s"); MessageManger.Instance?.ShowMessage_LocalClient($"{displayNameWithReadableColor} {text3} {text2} {Mathf.Abs(positionalFloat)} spawn point{text4} ({num} total) {SpawnPointManager.UseSpawnPointText}"); } } internal class GiveSpawnRandomCommand : TwitchCommand { public override string Name => "givespawnrandom"; public override bool EnabledByDefault => true; public override bool EnableConfigs => false; public override void Execute(TwitchMessage twitchMessage, string[] args) { //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_001b: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_0134: Unknown result type (might be due to invalid IL or missing references) if (SpawnPointManager.IsEnabled && ((TwitchMessage)(ref twitchMessage)).User.IsModeratorOrHigher()) { string displayNameWithReadableColor = ((TwitchMessage)(ref twitchMessage)).User.GetDisplayNameWithReadableColor(); ParsedArgs parsedArgs = ParsedArgs.Parse(args); float positionalFloat = parsedArgs.GetPositionalFloat(0, SpawnPointManager.PriceForEnemy); int positionalInt = parsedArgs.GetPositionalInt(1, 1); TwitchUser[] array = (from user in API.GetUsersSeenWithin(TimeSpan.FromMinutes(positionalInt)) where IsUserAllowedForGiveaway(user, ((TwitchMessage)(ref twitchMessage)).User) select user).ToArray(); if (array.Length == 0) { string arg = ((positionalInt == 1) ? "" : "s"); MessageManger.Instance?.ShowMessage_LocalClient($"Could not find any active Twitch users within {positionalInt} minute{arg} for the giveaway"); return; } TwitchUser twitchUser = array[Random.Range(0, array.Length)]; MessageManger.Instance?.ShowMessage_LocalClient(twitchUser.GetDisplayNameWithReadableColor() + " won the spawn points giveaway!"); SpawnPointManager.Add(((TwitchUser)(ref twitchUser)).Username, positionalFloat); float num = SpawnPointManager.Get(((TwitchUser)(ref twitchUser)).Username); string text = ((positionalFloat == 1f) ? "" : "s"); MessageManger.Instance?.ShowMessage_LocalClient($"{twitchUser.GetDisplayNameWithReadableColor()} received {positionalFloat} spawn point{text} ({num} total) {SpawnPointManager.UseSpawnPointText}"); } } private static bool IsUserAllowedForGiveaway(TwitchUser twitchUser, TwitchUser executingTwitchUser) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0006: 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 (false && twitchUser == executingTwitchUser) { return false; } if (true && ((TwitchUser)(ref twitchUser)).IsBroadcaster) { return false; } if (TwitchIntegrationManager.IsBotUser(twitchUser)) { return false; } return true; } } internal class InfoCommand : TwitchCommand { public override string Name => "info"; public override bool EnabledByDefault => true; public override bool EnableConfigs => false; public override void Execute(TwitchMessage twitchMessage, string[] args) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) if (!((TwitchMessage)(ref twitchMessage)).User.IsModeratorOrHigher()) { return; } bool isSubEventEnabled = TwitchIntegrationManager.IsSubEventEnabled; bool isCheerEventEnabled = TwitchIntegrationManager.IsCheerEventEnabled; bool isRaidEventEnabled = TwitchIntegrationManager.IsRaidEventEnabled; bool isEnabled = SpawnPointManager.IsEnabled; MessageSettings messageSettings = new MessageSettings(25f); MessageManger.Instance?.ShowMessage_LocalClient("--- MonsterHotkeys v3.2.0 Info ---", messageSettings); if (!isSubEventEnabled && !isCheerEventEnabled && !isRaidEventEnabled && !isEnabled) { MessageManger.Instance?.ShowMessage_LocalClient("subs/cheers/raids/spawn-points are not enabled", messageSettings); return; } if (isSubEventEnabled) { int num = 1; int value = ConfigManager.TwitchSubEvent_Tier2EnemyMultiplier.Value; int value2 = ConfigManager.TwitchSubEvent_Tier3EnemyMultiplier.Value; MessageManger.Instance?.ShowMessage_LocalClient($"Tier 1 sub/gift = {num} Random Enemy", messageSettings); MessageManger.Instance?.ShowMessage_LocalClient($"Tier 2 sub/gift = {num * value} Random Enemy", messageSettings); MessageManger.Instance?.ShowMessage_LocalClient($"Tier 3 sub/gift = {num * value2} Random Enemy", messageSettings); } if (isCheerEventEnabled) { MessageManger.Instance?.ShowMessage_LocalClient($"{TwitchCheerHandler.PriceForEnemy} bits = Random Enemy", messageSettings); MessageManger.Instance?.ShowMessage_LocalClient($"{TwitchCheerHandler.PriceForPlushies} bits = Random Plushies", messageSettings); } if (isRaidEventEnabled) { int value3 = ConfigManager.TwitchRaidEvent_ViewersPerEnemy.Value; int value4 = ConfigManager.TwitchRaidEvent_MaxSpawnCount.Value; MessageManger.Instance?.ShowMessage_LocalClient($"Raids: Every {value3} viewers = Random Enemy ({value4} max)", messageSettings); } if (SpawnPointManager.IsEnabled) { MessageManger.Instance?.ShowMessage_LocalClient($"{SpawnPointManager.PriceForEnemy} spawn points = Random Enemy", messageSettings); MessageManger.Instance?.ShowMessage_LocalClient($"{SpawnPointManager.PriceForPlushies} spawn points = Random Plushies", messageSettings); MessageManger.Instance?.ShowMessage_LocalClient($"Death = {SpawnPointManager.RewardPointsPerDeath} spawn points reward", messageSettings); MessageManger.Instance?.ShowMessage_LocalClient($"Crewmate Death = {SpawnPointManager.RewardPointsPerCrewmateDeath} spawn points reward", messageSettings); MessageManger.Instance?.ShowMessage_LocalClient($"{SpawnPointManager.MaxEnemySpawnsPerDay} max enemy spawns from spawn points per in-game day", messageSettings); } MessageManger.Instance?.ShowMessage_LocalClient($"DEBUG: {PlayerDamagePatcher.TranspilersCreated} transpilers created", messageSettings); } } internal class ViewAllBitsCommand : TwitchCommand { public override string Name => "viewallbits"; public override bool EnabledByDefault => true; public override bool EnableConfigs => false; public override void Execute(TwitchMessage twitchMessage, string[] args) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) if (!((TwitchMessage)(ref twitchMessage)).User.IsModeratorOrHigher()) { return; } if (AccumulatedBitManger.AccumulatedBits.Count == 0) { MessageManger.Instance?.ShowMessage_LocalClient("Nobody has accumulated any bits"); return; } int columns = 1; if (AccumulatedBitManger.AccumulatedBits.Count >= 20) { columns = 3; } else if (AccumulatedBitManger.AccumulatedBits.Count >= 10) { columns = 2; } Dictionary<string, int> keyValuePair = AccumulatedBitManger.AccumulatedBits.OrderByDescending((KeyValuePair<string, int> x) => x.Value).ToDictionary((KeyValuePair<string, int> a) => a.Key, (KeyValuePair<string, int> b) => b.Value); MessageManger.Instance?.ShowMessage_LocalClient(Utils.GetFormattedKeyValuePairMessage(keyValuePair, columns, "{key} {value} bits")); } } internal class ViewAllSpawnCommand : TwitchCommand { public override string Name => "viewallspawn"; public override bool EnabledByDefault => true; public override bool EnableConfigs => false; public override void Execute(TwitchMessage twitchMessage, string[] args) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) if (!SpawnPointManager.IsEnabled || !((TwitchMessage)(ref twitchMessage)).User.IsModeratorOrHigher()) { return; } if (SpawnPointManager.SpawnPoints.Count == 0) { MessageManger.Instance?.ShowMessage_LocalClient("Nobody has spawn points"); return; } int columns = 1; if (SpawnPointManager.SpawnPoints.Count >= 20) { columns = 3; } else if (SpawnPointManager.SpawnPoints.Count >= 10) { columns = 2; } Dictionary<string, float> keyValuePair = SpawnPointManager.SpawnPoints.OrderByDescending((KeyValuePair<string, float> x) => x.Value).ToDictionary((KeyValuePair<string, float> a) => a.Key, (KeyValuePair<string, float> b) => b.Value); MessageManger.Instance?.ShowMessage_LocalClient(Utils.GetFormattedKeyValuePairMessage(keyValuePair, columns, "{key} {value} sp")); } } internal class ViewPlayersCommand : TwitchCommand { public override string Name => "viewplayers"; public override bool EnabledByDefault => true; public override bool EnableConfigs => false; public override void Execute(TwitchMessage twitchMessage, string[] args) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) if (!((TwitchMessage)(ref twitchMessage)).User.IsModeratorOrHigher()) { return; } PlayerControllerB[] connectedPlayerScripts = PlayerUtils.ConnectedPlayerScripts; if (connectedPlayerScripts.Length != 0) { MessageManger.Instance?.ShowMessage_LocalClient("Players in the lobby:"); PlayerControllerB[] array = connectedPlayerScripts; foreach (PlayerControllerB val in array) { MessageManger.Instance?.ShowMessage_LocalClient(val.playerUsername ?? ""); } } } } } namespace com.github.zehsteam.MonsterHotkeys.Twitch.ChatCommands.Commands.Developer { internal class DevCheerCommand : TwitchCommand { public override string Name => "devcheer"; public override bool EnabledByDefault => true; public override bool EnableConfigs => false; public override void Execute(TwitchMessage twitchMessage, string[] args) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_004c: 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_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Expected O, but got Unknown //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) if (!((TwitchMessage)(ref twitchMessage)).User.IsDeveloper()) { return; } ParsedArgs parsedArgs = ParsedArgs.Parse(args); int num = parsedArgs.GetPositionalInt(0, TwitchCheerHandler.PriceForEnemy); if (parsedArgs.TryGetInt("count", out var value)) { num = value; } if (parsedArgs.TryGetInt("amount", out value)) { num = value; } if (num <= 0) { return; } TwitchUser user = ((TwitchMessage)(ref twitchMessage)).User; if (parsedArgs.TryGet("viewer", out var value2)) { value2 = ParseUsername(value2); TwitchUser val = default(TwitchUser); if (!API.TryGetUserByUsername(value2, ref val)) { return; } user = val; } TwitchCheerEvent cheerEvent = new TwitchCheerEvent { Channel = ((TwitchMessage)(ref twitchMessage)).Channel, User = user, Message = $"cheer{num}", Tags = ((TwitchMessage)(ref twitchMessage)).Tags, CheerAmount = num }; TwitchEventHandler.HandleCheer(cheerEvent); } } internal class DevPlushiesCommand : TwitchCommand { public override string Name => "devplushies"; public override bool EnabledByDefault => true; public override bool EnableConfigs => false; public override void Execute(TwitchMessage twitchMessage, string[] args) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0180: Unknown result type (might be due to invalid IL or missing references) //IL_015f: Unknown result type (might be due to invalid IL or missing references) if (!((TwitchMessage)(ref twitchMessage)).User.IsDeveloper() || (Object)(object)PlushieManager.Instance == (Object)null) { return; } ParsedArgs parsedArgs = ParsedArgs.Parse(args); string text = parsedArgs.GetPositional(0); string text2 = parsedArgs.GetPositional(1); string text3 = "by being the mod developer"; if (parsedArgs.TryGet("id", out var value)) { text = value; } if (parsedArgs.TryGet("target", out value)) { text2 = value; } if (parsedArgs.TryGet("reason", out value)) { text3 = value; } string displayNameWithReadableColor = ((TwitchMessage)(ref twitchMessage)).User.GetDisplayNameWithReadableColor(); PlayerControllerB playerScript; if (!string.IsNullOrWhiteSpace(text2)) { if (!PlayerUtils.TryGetPlayerScriptByUsername(text2, out playerScript)) { MessageManger.Instance?.ShowMessage_LocalClient(displayNameWithReadableColor + " no player was found with the name \"" + text2 + "\""); return; } } else { playerScript = PlayerUtils.LocalPlayerScript; } if ((Object)(object)playerScript == (Object)null) { return; } if (!PlushieManager.Instance.CanSpawnPlushiesOnPlayer(playerScript)) { MessageManger.Instance?.ShowMessage_LocalClient(displayNameWithReadableColor + " cannot spawn plushies on " + playerScript.playerUsername + " right now"); return; } if (!string.IsNullOrWhiteSpace(text) && !PlushieManager.Instance.PoolExists(text)) { MessageManger.Instance?.ShowMessage_LocalClient(displayNameWithReadableColor + " there are no plushies with the id of \"" + text + "\""); return; } ViewerData viewerData; if (parsedArgs.TryGet("viewer", out var value2)) { value2 = ParseUsername(value2); TwitchUser user = default(TwitchUser); viewerData = ((!API.TryGetUserByUsername(value2, ref user)) ? new ViewerData(value2, value2, value2, "#FFFFFF") : new ViewerData(user)); } else { viewerData = new ViewerData(((TwitchMessage)(ref twitchMessage)).User); } ViewerData viewer = viewerData; string spawnReason = text3; string targetPoolId = text; ulong? spawnedOnClientId = playerScript.actualClientId; SpawnPlushiesData spawnPlushiesData = new SpawnPlushiesData(viewer, SpawnSource.Twitch, spawnReason, targetPoolId, null, spawnedOnClientId); PlushieManager.Instance?.SpawnPlushiesFromData(spawnPlushiesData); } } internal class DevRaidCommand : TwitchCommand { public override string Name => "devraid"; public override bool EnabledByDefault => true; public override bool EnableConfigs => false; public override void Execute(TwitchMessage twitchMessage, string[] args) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Expected O, but got Unknown //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) if (!((TwitchMessage)(ref twitchMessage)).User.IsDeveloper()) { return; } ParsedArgs parsedArgs = ParsedArgs.Parse(args); int num = parsedArgs.GetPositionalInt(0, 1); if (parsedArgs.TryGetInt("count", out var value)) { num = value; } if (parsedArgs.TryGetInt("amount", out value)) { num = value; } if (num <= 0) { return; } TwitchUser user = ((TwitchMessage)(ref twitchMessage)).User; if (parsedArgs.TryGet("viewer", out var value2)