Decompiled source of MonsterHotkeys v2.6.1
com.github.zehsteam.MonsterHotkeys.dll
Decompiled 5 days 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.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 ControlValley; using GameNetcodeStuff; using HarmonyLib; using LethalCompanyInputUtils.Api; using LethalCompanyTestMod; using LethalConfig; using LethalConfig.ConfigItems; using LethalConfig.ConfigItems.Options; using Microsoft.CodeAnalysis; using Mono.Cecil; using Mono.Cecil.Cil; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using TMPro; using TwitchChatAPI; using TwitchChatAPI.Objects; using Unity.Netcode; using UnityEngine; using UnityEngine.AI; using UnityEngine.InputSystem; using UnityEngine.UI; using com.github.zehsteam.MonsterHotkeys.Data; using com.github.zehsteam.MonsterHotkeys.Dependencies; using com.github.zehsteam.MonsterHotkeys.Dependencies.CrowdControl; using com.github.zehsteam.MonsterHotkeys.Dependencies.CrowdControl.Patches; using com.github.zehsteam.MonsterHotkeys.Enums; using com.github.zehsteam.MonsterHotkeys.Extensions; using com.github.zehsteam.MonsterHotkeys.Helpers; using com.github.zehsteam.MonsterHotkeys.MonoBehaviours; using com.github.zehsteam.MonsterHotkeys.NetcodePatcher; using com.github.zehsteam.MonsterHotkeys.Patches; using com.github.zehsteam.MonsterHotkeys.Twitch; using com.github.zehsteam.MonsterHotkeys.Twitch.Commands; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("Zehs")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyCopyright("Copyright © 2025 Zehs")] [assembly: AssemblyDescription("Spawn Monsters and Monster Plushies using Hotkeys or from Twitch Subs, Cheers, and Raids. Supports Modded Monsters. Highly Configurable. (Twitch and CrowdControl Integration)")] [assembly: AssemblyFileVersion("2.6.1.0")] [assembly: AssemblyInformationalVersion("2.6.1+d63073b833f73d3a306778f2b5eb7f667df7781f")] [assembly: AssemblyProduct("MonsterHotkeys")] [assembly: AssemblyTitle("com.github.zehsteam.MonsterHotkeys")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("2.6.1.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] [module: NetcodePatchedAssembly] internal class <Module> { static <Module>() { } } namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace com.github.zehsteam.MonsterHotkeys { public class ConfigManager { public ConfigEntry<bool> ExtendedLogging { get; private set; } public ConfigEntry<bool> Enemy_OnlyHostSpawnEnemies { get; private set; } public ConfigEntry<bool> Enemy_MuteSpawnSFX { get; private set; } public ConfigEntry<bool> Enemy_SpawnStunned { get; private set; } public ConfigEntry<float> Enemy_StunDuration { get; private set; } public SyncedConfigEntry<int> Plushie_SpawnCount { get; private set; } public SyncedConfigEntry<float> Plushie_DespawnDuration { get; private set; } public ConfigEntry<float> Plushie_SFXVolume { get; private set; } public ConfigEntry<bool> Plushie_PlaySFXOnCollision { get; private set; } public SyncedConfigEntry<bool> Plushie_AttractDogs { get; private set; } public SyncedConfigEntry<float> Plushie_Scale { get; private set; } public ConfigEntry<bool> Message_ShowMessages { get; private set; } public ConfigEntry<bool> Message_ShowSpawnEnemyMessages { get; private set; } public ConfigEntry<bool> Message_ShowLocalSpawnEnemyMessages { get; private set; } public ConfigEntry<bool> Message_ShowDetailedTwitchEventSpawnEnemyMessages { get; private set; } public ConfigEntry<float> Message_Duration { get; private set; } public ConfigEntry<int> Message_FontSize { get; private set; } public ConfigEntry<int> Message_BackgroundTransparency { get; private set; } public ConfigEntry<bool> CrowdControl_Enabled { get; private set; } public ConfigEntry<bool> CrowdControl_RewardSpawnPoints { get; private set; } public ConfigEntry<bool> TwitchIntegration_Enabled { get; private set; } public ConfigEntry<bool> TwitchIntegration_SpawnAllOfTheSameEnemy { get; private set; } public ConfigEntry<bool> TwitchSubEvent_Enabled { get; private set; } public ConfigEntry<int> TwitchSubEvent_EnemiesPerSub { get; private set; } public ConfigEntry<int> TwitchSubEvent_Tier2EnemyMultiplier { get; private set; } public ConfigEntry<int> TwitchSubEvent_Tier3EnemyMultiplier { get; private set; } public ConfigEntry<bool> TwitchCheerEvent_Enabled { get; private set; } public ConfigEntry<int> TwitchCheerEvent_AmountToSpawnEnemy { get; private set; } public ConfigEntry<int> TwitchCheerEvent_AmountToSpawnPlushies { get; private set; } public ConfigEntry<bool> TwitchRaidEvent_Enabled { get; private set; } public ConfigEntry<int> TwitchRaidEvent_ViewersPerEnemy { get; private set; } public ConfigEntry<int> TwitchRaidEvent_MaxSpawnCount { get; private set; } public ConfigEntry<bool> SpawnPoints_Enabled { get; private set; } public ConfigEntry<int> SpawnPoints_MaxSpawnsPerDay { get; private set; } public ConfigEntry<int> SpawnPoints_RewardPointsPerDeath { get; private set; } public ConfigEntry<int> SpawnPoints_RewardPointsPerCrewmateDeath { get; private set; } public ConfigEntry<bool> TwitchCommandGiveSpawnRandom_ExcludeBroadcaster { get; private set; } public ConfigEntry<bool> TwitchCommandGiveSpawnRandom_ExcludeExecutingUser { get; private set; } public ConfigEntry<string> TwitchCommandGiveSpawnRandom_ExcludeUsersList { get; private set; } public ConfigEntry<bool> EnemyNametag_Enabled { get; private set; } public ConfigEntry<bool> EnemyNametag_ShowPlatform { get; private set; } public ConfigEntry<float> EnemyNametag_ScaleMultiplier { get; private set; } public ConfigEntry<int> EnemyNametag_BackgroundTransparency { get; private set; } public ConfigManager() { BindConfigs(); MigrateOldConfigSettings(); } private void BindConfigs() { ConfigHelper.SkipAutoGen(); ExtendedLogging = ConfigHelper.Bind("General", "ExtendedLogging", defaultValue: false, "Enable extended logging."); Enemy_OnlyHostSpawnEnemies = ConfigHelper.Bind("Enemy", "OnlyHostSpawnEnemies", defaultValue: false, "If enabled, only the host can spawn enemies."); Enemy_MuteSpawnSFX = ConfigHelper.Bind("Enemy", "MuteSpawnSFX", defaultValue: false, "If enabled, the enemy spawn sfx will not play."); Enemy_SpawnStunned = ConfigHelper.Bind("Enemy", "SpawnStunned", defaultValue: false, "If enabled, spawned enemies will be stunned for StunDuration seconds."); Enemy_StunDuration = ConfigHelper.Bind("Enemy", "StunDuration", 6f, "The duration enemies will be stunned for in seconds."); Enemy_MuteSpawnSFX.SettingChanged += AudioPlayerManager.OnSettingsChanged; Plushie_SpawnCount = ConfigHelper.BindSynced("Plushie", "SpawnCount", 30, "The amount of plushies to spawn.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100)); Plushie_DespawnDuration = ConfigHelper.BindSynced("Plushie", "DespawnDuration", 15f, "The duration in seconds until a plushie gets despawned."); Plushie_SFXVolume = ConfigHelper.Bind("Plushie", "SFXVolume", 25f, "The volume of the plushie's squeak sound effect.", requiresRestart: false, (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f)); Plushie_PlaySFXOnCollision = ConfigHelper.Bind("Plushie", "PlaySFXOnCollision", defaultValue: true, "If enabled, the plushies will play a sound effect when colliding with the environment."); Plushie_AttractDogs = ConfigHelper.BindSynced("Plushie", "AttractDogs", defaultValue: true, "If enabled, the plushies will attract dogs when making noise."); Plushie_Scale = ConfigHelper.BindSynced("Plushie", "Scale", 4f, "The size of the plushies."); Message_ShowMessages = ConfigHelper.Bind("Message", "ShowMessages", defaultValue: true, "If enabled, will show messages in the bottom right."); Message_ShowSpawnEnemyMessages = ConfigHelper.Bind("Message", "ShowSpawnEnemyMessages", defaultValue: true, "If enabled, will show a message when someone else spawns an enemy."); Message_ShowLocalSpawnEnemyMessages = ConfigHelper.Bind("Message", "ShowLocalSpawnEnemyMessages", defaultValue: true, "If enabled, will show a message when you spawn an enemy."); Message_ShowDetailedTwitchEventSpawnEnemyMessages = ConfigHelper.Bind("Message", "ShowDetailedTwitchEventSpawnEnemyMessages", defaultValue: true, "If enabled, will show a detailed Twitch event spawn enemy messages."); Message_Duration = ConfigHelper.Bind("Message", "Duration", 8f, "The duration of a message in seconds."); Message_FontSize = ConfigHelper.Bind("Message", "FontSize", 25, "The font size of the messages."); Message_BackgroundTransparency = ConfigHelper.Bind("Message", "BackgroundTransparency", 192, "The transparency of the message background.", requiresRestart: false, (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 255)); Message_FontSize.SettingChanged += MessageItem.OnSettingsChanged; Message_BackgroundTransparency.SettingChanged += MessageItem.OnSettingsChanged; CrowdControl_Enabled = ConfigHelper.Bind("Crowd Control Integration", "Enabled", defaultValue: true, "If enabled, Crowd Control will be able to spawn enemies anywhere and spawned enemies will have a nametag with the name of the viewer that spawned that enemy."); CrowdControl_RewardSpawnPoints = ConfigHelper.Bind("Crowd Control Integration", "RewardSpawnPoints", defaultValue: true, "If you die to an enemy spawned by a viewer, they will gain a spawn point to spawn a free enemy by writing !spawn in your Twitch chat. (Requries Spawn Points to be enabled, Twitch Integration to be enabled, and the TwitchChatAPI mod)"); TwitchIntegration_Enabled = ConfigHelper.Bind("Twitch Integration", "Enabled", defaultValue: true, "If enabled, Twitch integration will be enabled to spawn enemies from Subs, Cheers, and Raids. (Requires the TwitchChatAPI mod)"); TwitchIntegration_SpawnAllOfTheSameEnemy = ConfigHelper.Bind("Twitch Integration", "SpawnAllOfTheSameEnemy", defaultValue: false, "If enabled, when spawning multiple enemies from a single event, all enemies spawned will be of the same type."); TwitchSubEvent_Enabled = ConfigHelper.Bind("Twitch Sub Event", "Enabled", defaultValue: true, "If enabled, Twitch subs will be able to spawn enemies. (Requires Twitch Integration to be enabled and the TwitchChatAPI mod)"); TwitchSubEvent_EnemiesPerSub = ConfigHelper.Bind("Twitch Sub Event", "EnemiesPerSub", 1, "The amount of enemies that will spawn per sub."); TwitchSubEvent_Tier2EnemyMultiplier = ConfigHelper.Bind("Twitch Sub Event", "Tier2EnemyMultiplier", 3, "The amount to multiply the enemy spawn count for tier 2 subs."); TwitchSubEvent_Tier3EnemyMultiplier = ConfigHelper.Bind("Twitch Sub Event", "Tier3EnemyMultiplier", 6, "The amount to multiply the enemy spawn count for tier 3 subs."); TwitchCheerEvent_Enabled = ConfigHelper.Bind("Twitch Cheer Event", "Enabled", defaultValue: true, "If enabled, Twitch cheers will be able to spawn enemies. (Requires Twitch Integration to be enabled and the TwitchChatAPI mod)"); TwitchCheerEvent_AmountToSpawnEnemy = ConfigHelper.Bind("Twitch Cheer Event", "AmountToSpawnEnemy", 350, "The amount of bits to spawn an enemy."); TwitchCheerEvent_AmountToSpawnPlushies = ConfigHelper.Bind("Twitch Cheer Event", "AmountToSpawnPlushies", 100, "The amount of bits to spawn plushies that create noise and block your view."); TwitchRaidEvent_Enabled = ConfigHelper.Bind("Twitch Raid Event", "Enabled", defaultValue: true, "If enabled, Twitch raids will be able to spawn enemies. (Requires Twitch Integration to be enabled and the TwitchChatAPI mod)"); TwitchRaidEvent_ViewersPerEnemy = ConfigHelper.Bind("Twitch Raid Event", "ViewersPerEnemy", 5, "The amount of viewers for each enemy spawn."); TwitchRaidEvent_MaxSpawnCount = ConfigHelper.Bind("Twitch Raid Event", "MaxSpawnCount", 20, "The max amount of enemies that can spawn."); SpawnPoints_Enabled = ConfigHelper.Bind("Spawn Points", "Enabled", defaultValue: true, "If you die to an enemy spawned by a viewer, they will gain a spawn point to spawn a free enemy by writing !spawn in your Twitch chat. (Requires Twitch Integration to be enabled and the TwitchChatAPI mod)"); SpawnPoints_MaxSpawnsPerDay = ConfigHelper.Bind("Spawn Points", "MaxSpawnsPerDay", 100, "The max amount of spawn points that can be redeemed per in-game day."); SpawnPoints_RewardPointsPerDeath = ConfigHelper.Bind("Spawn Points", "RewardPointsPerDeath", 1, "The amount of spawn points a viewer will receive from your death."); SpawnPoints_RewardPointsPerCrewmateDeath = ConfigHelper.Bind("Spawn Points", "RewardPointsPerCrewmateDeath", 0, "The amount of spawn points a viewer will receive from a crewmate's death."); ConfigHelper.AddButton("Spawn Points", "Reset all spawn points", "Reset", "Reset all viewers spawn points.", TwitchIntegrationManager.ResetAllSpawnPoints); TwitchCommandGiveSpawnRandom_ExcludeBroadcaster = ConfigHelper.Bind("Twitch Command !givespawnrandom", "ExcludeBroadcaster", defaultValue: true, "If enabled, the !givespawnrandom command will exclude the broadcaster from winning."); TwitchCommandGiveSpawnRandom_ExcludeExecutingUser = ConfigHelper.Bind("Twitch Command !givespawnrandom", "ExcludeExecutingUser", defaultValue: true, "If enabled, the !givespawnrandom command will exclude the user that wrote the command from winning."); TwitchCommandGiveSpawnRandom_ExcludeUsersList = ConfigHelper.Bind("Twitch Command !givespawnrandom", "ExcludeUsersList", "", "The list of Twitch users to exclude from winning the !givespawnrandom command."); EnemyNametag_Enabled = ConfigHelper.Bind("Enemy Nametag", "Enabled", defaultValue: true, "If enabled, enemies will spawn with a nametag of the viewer that spawned that enemy."); EnemyNametag_ShowPlatform = ConfigHelper.Bind("Enemy Nametag", "ShowPlatform", defaultValue: true, "If enabled, nametags will show which platform the enemy was spawned from."); EnemyNametag_ScaleMultiplier = ConfigHelper.Bind("Enemy Nametag", "ScaleMultiplier", 1f, "The scale multiplier for enemy nametags.", requiresRestart: false, (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.25f, 5f)); EnemyNametag_BackgroundTransparency = ConfigHelper.Bind("Enemy Nametag", "BackgroundTransparency", 192, "The transparency of the nametag background.", requiresRestart: false, (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 255)); EnemyNametag_ScaleMultiplier.SettingChanged += EnemyNametag.OnSettingsChanged; EnemyNametag_ShowPlatform.SettingChanged += EnemyNametag.OnSettingsChanged; EnemyNametag_BackgroundTransparency.SettingChanged += EnemyNametag.OnSettingsChanged; } private void MigrateOldConfigSettings() { foreach (KeyValuePair<ConfigDefinition, string> orphanedConfigEntry in ConfigHelper.GetOrphanedConfigEntries()) { MigrateOldConfigSetting(orphanedConfigEntry.Key.Section, orphanedConfigEntry.Key.Key, orphanedConfigEntry.Value); } } private void MigrateOldConfigSetting(string section, string key, string value) { StringComparison comparisonType = StringComparison.OrdinalIgnoreCase; if (section.Equals("General Settings", comparisonType) && key.Equals("ExtendedLogging", comparisonType)) { ConfigHelper.SetConfigEntryValue<bool>(ExtendedLogging, value); return; } if (section.Equals("Monster Settings", comparisonType)) { if (key.Equals("OnlyHostSpawnMonsters", comparisonType)) { ConfigHelper.SetConfigEntryValue<bool>(Enemy_OnlyHostSpawnEnemies, value); return; } if (key.Equals("MuteSpawnSFX", comparisonType)) { ConfigHelper.SetConfigEntryValue<bool>(Enemy_MuteSpawnSFX, value); return; } if (key.Equals("SpawnStunned", comparisonType)) { ConfigHelper.SetConfigEntryValue<bool>(Enemy_SpawnStunned, value); return; } if (key.Equals("StunDuration", comparisonType)) { ConfigHelper.SetConfigEntryValue<float>(Enemy_StunDuration, value); return; } } if (section.Equals("Plushie Settings", comparisonType)) { if (key.Equals("SpawnCount", comparisonType)) { ConfigHelper.SetConfigEntryValue(Plushie_SpawnCount, value); return; } if (key.Equals("DespawnDuration", comparisonType)) { ConfigHelper.SetConfigEntryValue(Plushie_DespawnDuration, value); return; } if (key.Equals("SFXVolume", comparisonType)) { ConfigHelper.SetConfigEntryValue<float>(Plushie_SFXVolume, value); return; } if (key.Equals("PlaySFXOnCollision", comparisonType)) { ConfigHelper.SetConfigEntryValue<bool>(Plushie_PlaySFXOnCollision, value); return; } if (key.Equals("AttractDogs", comparisonType)) { ConfigHelper.SetConfigEntryValue(Plushie_AttractDogs, value); return; } if (key.Equals("Scale", comparisonType)) { ConfigHelper.SetConfigEntryValue(Plushie_Scale, value); return; } } if (section.Equals("Message Settings", comparisonType)) { if (key.Equals("ShowMessages", comparisonType)) { ConfigHelper.SetConfigEntryValue<bool>(Message_ShowMessages, value); return; } if (key.Equals("ShowSpawnEnemyMessages", comparisonType)) { ConfigHelper.SetConfigEntryValue<bool>(Message_ShowSpawnEnemyMessages, value); return; } if (key.Equals("ShowLocalSpawnEnemyMessages", comparisonType)) { ConfigHelper.SetConfigEntryValue<bool>(Message_ShowLocalSpawnEnemyMessages, value); return; } if (key.Equals("ShowDetailedTwitchEventSpawnEnemyMessages", comparisonType)) { ConfigHelper.SetConfigEntryValue<bool>(Message_ShowDetailedTwitchEventSpawnEnemyMessages, value); return; } if (key.Equals("Duration", comparisonType)) { ConfigHelper.SetConfigEntryValue<float>(Message_Duration, value); return; } if (key.Equals("FontSize", comparisonType)) { ConfigHelper.SetConfigEntryValue<int>(Message_FontSize, value); return; } if (key.Equals("BackgroundTransparency", comparisonType)) { ConfigHelper.SetConfigEntryValue<int>(Message_BackgroundTransparency, value); return; } } if (section.Equals("Crowd Control Integration Settings", comparisonType) && key.Equals("Enabled", comparisonType)) { ConfigHelper.SetConfigEntryValue<bool>(CrowdControl_Enabled, value); return; } if (section.Equals("Twitch Integration Settings", comparisonType) && key.Equals("Enabled", comparisonType)) { ConfigHelper.SetConfigEntryValue<bool>(TwitchIntegration_Enabled, value); return; } if (section.Equals("Twitch Integration", comparisonType)) { if (key.Equals("SpawnPointsEnabled", comparisonType)) { ConfigHelper.SetConfigEntryValue<bool>(SpawnPoints_Enabled, value); return; } if (key.Equals("SpawnPointsPerDeath", comparisonType)) { ConfigHelper.SetConfigEntryValue<int>(SpawnPoints_RewardPointsPerDeath, value); return; } } if (section.Equals("Twitch Subs Event Settings", comparisonType)) { if (key.Equals("Enabled", comparisonType)) { ConfigHelper.SetConfigEntryValue<bool>(TwitchSubEvent_Enabled, value); return; } if (key.Equals("SpawnAllOfTheSameEnemy", comparisonType)) { ConfigHelper.SetConfigEntryValue<bool>(TwitchIntegration_SpawnAllOfTheSameEnemy, value); return; } } if (section.Equals("Twitch Bits Event Settings", comparisonType)) { if (key.Equals("Enabled", comparisonType)) { ConfigHelper.SetConfigEntryValue<bool>(TwitchCheerEvent_Enabled, value); return; } if (key.Equals("MinAmountToSpawnMonster", comparisonType)) { ConfigHelper.SetConfigEntryValue<int>(TwitchCheerEvent_AmountToSpawnEnemy, value); return; } if (key.Equals("MinAmountToSpawnPlushies", comparisonType)) { ConfigHelper.SetConfigEntryValue<int>(TwitchCheerEvent_AmountToSpawnPlushies, value); return; } } if (section.Equals("Enemy Nametag Settings", comparisonType)) { if (key.Equals("Enabled", comparisonType)) { ConfigHelper.SetConfigEntryValue<bool>(EnemyNametag_Enabled, value); } else if (key.Equals("ShowPlatform", comparisonType)) { ConfigHelper.SetConfigEntryValue<bool>(EnemyNametag_ShowPlatform, value); } else if (key.Equals("ScaleMultiplier", comparisonType)) { ConfigHelper.SetConfigEntryValue<float>(EnemyNametag_ScaleMultiplier, value); } else if (key.Equals("BackgroundTransparency", comparisonType)) { ConfigHelper.SetConfigEntryValue<int>(EnemyNametag_BackgroundTransparency, value); } } } } internal static class Content { public static GameObject NetworkHandlerPrefab { get; private set; } public static GameObject MessageCanvasPrefab { get; private set; } public static EnemyDataList EnemyDataList { get; private set; } public static void Load() { LoadAssetsFromAssetBundle(); } private static void LoadAssetsFromAssetBundle() { AssetBundle val = LoadAssetBundle("monsterhotkeys_assets"); if (!((Object)(object)val == (Object)null)) { NetworkHandlerPrefab = LoadAssetFromAssetBundle<GameObject>("NetworkHandler", val); MessageCanvasPrefab = LoadAssetFromAssetBundle<GameObject>("MonsterHotkeysCanvas", val); EnemyDataList = LoadAssetFromAssetBundle<EnemyDataList>("EnemyDataList", val); Plugin.Logger.LogInfo((object)"Successfully loaded assets from AssetBundle!"); } } private static AssetBundle LoadAssetBundle(string fileName) { try { string directoryName = Path.GetDirectoryName(((BaseUnityPlugin)Plugin.Instance).Info.Location); string text = Path.Combine(directoryName, fileName); return AssetBundle.LoadFromFile(text); } catch (Exception arg) { Plugin.Logger.LogError((object)$"Failed to load AssetBundle \"{fileName}\". {arg}"); } return null; } private static T LoadAssetFromAssetBundle<T>(string name, AssetBundle assetBundle) where T : Object { if (string.IsNullOrWhiteSpace(name)) { Plugin.Logger.LogError((object)("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) { Plugin.Logger.LogError((object)("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) { Plugin.Logger.LogError((object)("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; } } 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; Plugin.Logger.LogInfo((object)"Setup keybind callbacks."); } private static void OnSpawnKeyPressed(CallbackContext context) { //IL_0053: Unknown result type (might be due to invalid IL or missing references) if (!((CallbackContext)(ref context)).performed) { return; } string name = ((CallbackContext)(ref context)).action.name; Plugin.Instance.LogInfoExtended(name + " key pressed."); if (!Utils.CanPerformHotkeys()) { return; } if (DisableHotkeys && (IsMonsterPrefixKeyPressed || IsPlushiePrefixKeyPressed)) { MessageCanvas.Instance.ShowMessage_LocalClient("Hotkeys have been disabled by another mod", Color.red); Plugin.Logger.LogInfo((object)"Hotkeys have been disabled by another mod."); return; } string text = name.Replace("Spawn", "").Replace("Key", ""); switch (text) { case "BaboonHawk": text = "Baboon hawk"; break; case "BunkerSpider": text = "Bunker Spider"; break; case "Bracken": text = "Flowerman"; break; case "CoilHead": text = "Spring"; break; case "EarthLeviathan": text = "Earth Leviathan"; break; case "EyelessDog": text = "MouthDog"; break; case "GhostGirl": text = "Girl"; break; case "HoardingBug": text = "Hoarding bug"; break; case "OldBird": text = "RadMech"; break; case "SnareFlea": text = "Centipede"; break; case "SporeLizard": text = "Puffer"; break; case "Thumper": text = "Crawler"; break; case "TulipSnake": text = "Tulip Snake"; break; case "KidnapperFox": text = "Bush Wolf"; break; case "Barber": text = "Clay Surgeon"; break; } EnemyData byEnemyName = Content.EnemyDataList.GetByEnemyName(text); if (byEnemyName == null) { Plugin.Logger.LogError((object)("Failed to find EnemyData from key name \"" + name + "\".")); return; } if (Plugin.InputActionsInstance.MonsterPrefixKey.IsPressed()) { EnemyHelper.SpawnEnemy(byEnemyName); } if (Plugin.InputActionsInstance.PlushiePrefixKey.IsPressed()) { PlushieManager.Instance.SpawnPlushies(byEnemyName.EnemyName); } } private static void OnSpawnRandomKeyPressed(CallbackContext context) { //IL_0051: Unknown result type (might be due to invalid IL or missing references) if (!((CallbackContext)(ref context)).performed) { return; } Plugin.Instance.LogInfoExtended(((CallbackContext)(ref context)).action.name + " key pressed."); if (!Utils.CanPerformHotkeys()) { return; } if (DisableHotkeys && (IsMonsterPrefixKeyPressed || IsPlushiePrefixKeyPressed)) { MessageCanvas.Instance.ShowMessage_LocalClient("Hotkeys have been disabled by another mod", Color.red); Plugin.Logger.LogInfo((object)"Hotkeys have been disabled by another mod."); return; } if (IsMonsterPrefixKeyPressed) { EnemyHelper.SpawnRandomEnemy(); } if (IsPlushiePrefixKeyPressed) { PlushieManager.Instance.SpawnRandomPlushies(); } } } internal static class NetworkUtils { public static bool IsConnected { get { if ((Object)(object)NetworkManager.Singleton == (Object)null) { return false; } return NetworkManager.Singleton.IsConnectedClient; } } public static bool IsServer { get { if ((Object)(object)NetworkManager.Singleton == (Object)null) { return false; } return NetworkManager.Singleton.IsServer; } } public static bool IsHost { get { if ((Object)(object)NetworkManager.Singleton == (Object)null) { return false; } return NetworkManager.Singleton.IsHost; } } public static ulong GetLocalClientId() { return NetworkManager.Singleton.LocalClientId; } public static bool IsLocalClientId(ulong clientId) { return clientId == GetLocalClientId(); } public static bool IsNetworkPrefab(GameObject prefab) { foreach (NetworkPrefab prefab2 in NetworkManager.Singleton.NetworkConfig.Prefabs.Prefabs) { if ((Object)(object)prefab2.Prefab == (Object)(object)prefab) { return true; } } return false; } } internal static class PlayerUtils { public static PlayerControllerB GetLocalPlayerScript() { if ((Object)(object)GameNetworkManager.Instance == (Object)null) { return null; } return GameNetworkManager.Instance.localPlayerController; } public static bool IsLocalPlayer(PlayerControllerB playerScript) { return (Object)(object)playerScript == (Object)(object)GetLocalPlayerScript(); } public static PlayerControllerB GetPlayerScriptByClientId(ulong clientId) { PlayerControllerB[] allPlayerScripts = StartOfRound.Instance.allPlayerScripts; foreach (PlayerControllerB val in allPlayerScripts) { if (!((Object)(object)val == (Object)null) && val.actualClientId == clientId) { return val; } } return null; } public static List<PlayerControllerB> GetPlayerScripts() { List<PlayerControllerB> list = new List<PlayerControllerB>(); PlayerControllerB[] allPlayerScripts = StartOfRound.Instance.allPlayerScripts; foreach (PlayerControllerB val in allPlayerScripts) { if (!((Object)(object)val == (Object)null) && (val.isInHangarShipRoom || val.isInsideFactory || val.isInElevator)) { list.Add(val); } } return list; } public static PlayerControllerB GetRandomPlayerScript(bool onlyAlivePlayers = true, bool excludeLocalPlayer = false) { List<PlayerControllerB> list = new List<PlayerControllerB>(); foreach (PlayerControllerB playerScript in GetPlayerScripts()) { if ((!onlyAlivePlayers || !playerScript.isPlayerDead) && (!excludeLocalPlayer || !IsLocalPlayer(playerScript))) { list.Add(playerScript); } } if (list.Count == 0) { return null; } return list[Random.Range(0, list.Count)]; } } [BepInPlugin("com.github.zehsteam.MonsterHotkeys", "MonsterHotkeys", "2.6.1")] [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 ManualLogSource Logger { get; private set; } internal static ConfigManager ConfigManager { get; private set; } internal static HotkeyInputClass InputActionsInstance { get; private set; } private void Awake() { Instance = this; Logger = Logger.CreateLogSource("com.github.zehsteam.MonsterHotkeys"); Logger.LogInfo((object)"MonsterHotkeys has awoken!"); _harmony.PatchAll(typeof(GameNetworkManagerPatch)); _harmony.PatchAll(typeof(StartOfRoundPatch)); _harmony.PatchAll(typeof(RoundManagerPatch)); _harmony.PatchAll(typeof(HUDManagerPatch)); _harmony.PatchAll(typeof(EnemyAIPatch)); _harmony.PatchAll(typeof(RadMechAIPatch)); _harmony.PatchAll(typeof(ButlerEnemyAIPatch)); _harmony.PatchAll(typeof(LandminePatch)); if (CrowdControlProxy.Enabled) { CrowdControlProxy.PatchAll(_harmony); } Content.Load(); ConfigManager = new ConfigManager(); InputActionsInstance = new HotkeyInputClass(); HotkeyListener.SetupKeybindCallbacks(); Content.EnemyDataList.Initialize(); TwitchIntegrationManager.Initialize(); NetcodePatcherAwake(); } private void Start() { PlayerDamagePatcher.PatchAll(_harmony); } private void NetcodePatcherAwake() { try { Assembly executingAssembly = Assembly.GetExecutingAssembly(); Type[] types = executingAssembly.GetTypes(); Type[] array = types; foreach (Type type in array) { MethodInfo[] methods = type.GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic); MethodInfo[] array2 = methods; foreach (MethodInfo methodInfo in array2) { try { object[] customAttributes = methodInfo.GetCustomAttributes(typeof(RuntimeInitializeOnLoadMethodAttribute), inherit: false); if (customAttributes.Length != 0) { try { methodInfo.Invoke(null, null); } catch (TargetInvocationException ex) { Logger.LogWarning((object)("Failed to invoke method " + methodInfo.Name + ": " + ex.Message)); } } } catch (Exception ex2) { Logger.LogWarning((object)("Error processing method " + methodInfo.Name + " in type " + type.Name + ": " + ex2.Message)); } } } } catch (Exception ex3) { Logger.LogError((object)("An error occurred in NetcodePatcherAwake: " + ex3.Message)); } } public void OnNewLevelLoaded() { EnemyNametagManager.Instance?.Reset(); } public void SpawnMessageCanvas() { if (!((Object)(object)MessageCanvas.Instance != (Object)null)) { Object.Instantiate<GameObject>(Content.MessageCanvasPrefab); } } public void LogInfoExtended(object data) { LogExtended((LogLevel)16, data); } public void LogWarningExtended(object data) { LogExtended((LogLevel)4, data); } public void LogExtended(LogLevel level, object data) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) if (ConfigManager == null || ConfigManager.ExtendedLogging == null) { Logger.Log(level, data); } else if (ConfigManager.ExtendedLogging.Value) { Logger.Log(level, data); } } } internal static class Utils { public static string GetEnumName<T>(T e) where T : Enum { return Enum.GetName(typeof(T), e) ?? string.Empty; } public static string GetPluginDirectoryPath() { return Path.GetDirectoryName(((BaseUnityPlugin)Plugin.Instance).Info.Location); } public static string GetConfigDirectoryPath() { return Paths.ConfigPath; } public static string GetGlobalConfigDirectoryPath() { return Path.Combine(Application.persistentDataPath, "MonsterHotkeys"); } public static ConfigFile CreateConfigFile(string directoryPath, string name = null, bool saveOnInit = false) { //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Expected O, but got Unknown BepInPlugin metadata = MetadataHelper.GetMetadata((object)Plugin.Instance); if (name == null) { name = metadata.GUID; } name += ".cfg"; return new ConfigFile(Path.Combine(directoryPath, name), saveOnInit, metadata); } public static ConfigFile CreateLocalConfigFile(string name = null, bool saveOnInit = false) { if (name == null) { name = "com.github.zehsteam.MonsterHotkeys-" + name; } return CreateConfigFile(Paths.ConfigPath, name, saveOnInit); } public static ConfigFile CreateGlobalConfigFile(string name = null, bool saveOnInit = false) { if (name == null) { name = "global"; } return CreateConfigFile(GetGlobalConfigDirectoryPath(), name, saveOnInit); } public static void LogStackTrace() { StackTrace stackTrace = new StackTrace(); for (int i = 1; i < stackTrace.FrameCount; i++) { StackFrame frame = stackTrace.GetFrame(i); MethodBase method = frame.GetMethod(); Type declaringType = method.DeclaringType; string name = method.Name; Plugin.Instance.LogInfoExtended($"Call stack depth {i}: {declaringType}.{name}"); } } public static bool RandomPercent(float percent) { if (percent <= 0f) { return false; } if (percent >= 100f) { return true; } return Random.value * 100f <= percent; } public static string GetFormattedString(string text) { if (string.IsNullOrWhiteSpace(text)) { return string.Empty; } return string.Join(" ", from word in text.Split(' ', StringSplitOptions.RemoveEmptyEntries) select $"{char.ToUpper(word[0])}{word.Substring(1).ToLower()}"); } public static bool CanPerformHotkeys() { PlayerControllerB localPlayerScript = PlayerUtils.GetLocalPlayerScript(); if ((Object)(object)localPlayerScript == (Object)null) { return false; } if (localPlayerScript.isPlayerDead) { return false; } if (localPlayerScript.isTypingChat) { return false; } if (localPlayerScript.quickMenuManager.isMenuOpen) { return false; } return true; } public static Coroutine StartCoroutine(IEnumerator routine) { if ((Object)(object)Plugin.Instance != (Object)null) { return ((MonoBehaviour)Plugin.Instance).StartCoroutine(routine); } if ((Object)(object)GameNetworkManager.Instance != (Object)null) { return ((MonoBehaviour)GameNetworkManager.Instance).StartCoroutine(routine); } Plugin.Logger.LogError((object)("Failed to start coroutine. " + routine)); return null; } public static bool TryParseValue<T>(string value, out T result) { try { if (typeof(T) == typeof(int) && int.TryParse(value, out var result2)) { result = (T)(object)result2; return true; } if (typeof(T) == typeof(float) && float.TryParse(value, out var result3)) { result = (T)(object)result3; return true; } if (typeof(T) == typeof(double) && double.TryParse(value, out var result4)) { result = (T)(object)result4; return true; } if (typeof(T) == typeof(bool) && bool.TryParse(value, out var result5)) { result = (T)(object)result5; return true; } if (typeof(T) == typeof(string)) { result = (T)(object)value; return true; } } catch { } result = default(T); return false; } public static string GetFormattedKeyValuePairMessage<T>(Dictionary<string, T> keyValuePair, int columns, string format, string separator = " ") { if (keyValuePair == null || keyValuePair.Count == 0) { return string.Empty; } int num = Mathf.CeilToInt((float)keyValuePair.Count / (float)columns); List<List<KeyValuePair<string, T>>> list = new List<List<KeyValuePair<string, T>>>(); for (int i = 0; i < columns; i++) { list.Add(keyValuePair.Skip(i * num).Take(num).ToList()); } List<int> list2 = list.Select((List<KeyValuePair<string, T>> column) => column.Any() ? column.Max((KeyValuePair<string, T> item) => item.Key.Length) : 0).ToList(); List<int> list3 = list.Select((List<KeyValuePair<string, T>> column) => column.Any() ? column.Max((KeyValuePair<string, T> item) => item.Value.ToString().Length) : 0).ToList(); StringBuilder stringBuilder = new StringBuilder(); for (int j = 0; j < num; j++) { for (int k = 0; k < columns; k++) { if (k < list.Count && j < list[k].Count) { KeyValuePair<string, T> keyValuePair2 = list[k][j]; string newValue = keyValuePair2.Key.PadRight(list2[k]); string newValue2 = keyValuePair2.Value.ToString().PadRight(list3[k]); string value = format.Replace("{key}", newValue).Replace("{value}", newValue2); stringBuilder.Append(value); if (k < columns - 1) { stringBuilder.Append(" | "); } } } stringBuilder.AppendLine(); } return stringBuilder.ToString().TrimEnd(); } public static bool IsChildOfComponent<T>(Transform transform, out T component) where T : Component { component = default(T); if ((Object)(object)transform == (Object)null || (Object)(object)transform.parent == (Object)null) { return false; } if (((Component)transform.parent).TryGetComponent<T>(ref component)) { return true; } return IsChildOfComponent<T>(transform.parent, out component); } public static string GetTextWithColor(string text, string hexColor, string backgroundHexColor = "#000000") { if (string.IsNullOrWhiteSpace(hexColor)) { hexColor = "#FFFFFF"; } string readableColor = ColorHelper.GetReadableColor(hexColor, backgroundHexColor); return "<color=" + readableColor + ">" + text + "</color>"; } public static IEnumerable<T> StringToCollection<T>(string value) { if (string.IsNullOrEmpty(value)) { return Enumerable.Empty<T>(); } T result; return from x in value.Split(',', StringSplitOptions.RemoveEmptyEntries) where !string.IsNullOrWhiteSpace(x) select x.Trim() into x select (!TryConvertStringToType<T>(x, out result)) ? default(T) : result into x where x != null select x; } public static string CollectionToString<T>(IEnumerable<T> value) { if (value == null || !value.Any()) { return string.Empty; } return string.Join(", ", from x in value where x != null && !string.IsNullOrWhiteSpace(x.ToString()) select x.ToString().Trim()); } public static bool TryConvertStringToType<T>(string value, out T result) { if (string.IsNullOrWhiteSpace(value)) { result = default(T); return false; } try { Type typeFromHandle = typeof(T); if (typeFromHandle.IsEnum && Enum.TryParse(typeFromHandle, value.Trim(), ignoreCase: true, out object result2)) { result = (T)result2; return true; } if (typeFromHandle == typeof(Guid) && Guid.TryParse(value.Trim(), out var result3)) { result = (T)(object)result3; return true; } Type conversionType = Nullable.GetUnderlyingType(typeFromHandle) ?? typeFromHandle; result = (T)Convert.ChangeType(value.Trim(), conversionType); return true; } catch { result = default(T); return false; } } } public static class MyPluginInfo { public const string PLUGIN_GUID = "com.github.zehsteam.MonsterHotkeys"; public const string PLUGIN_NAME = "MonsterHotkeys"; public const string PLUGIN_VERSION = "2.6.1"; } } namespace com.github.zehsteam.MonsterHotkeys.Twitch { internal static class TwitchIntegrationManager { [CompilerGenerated] private sealed class <PlayQueueCoroutine>d__32 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public float initialDelay; private float <delay>5__2; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <PlayQueueCoroutine>d__32(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Expected O, but got Unknown //IL_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Expected O, but got Unknown //IL_014c: Unknown result type (might be due to invalid IL or missing references) //IL_0156: Expected O, but got Unknown //IL_01a0: Unknown result type (might be due to invalid IL or missing references) //IL_01aa: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; _isPlayingQueue = true; Plugin.Instance.LogInfoExtended("Started Twitch event queue."); <>2__current = (object)new WaitForSeconds(initialDelay); <>1__state = 1; return true; case 1: <>1__state = -1; if (!CanExecuteEvents()) { Plugin.Instance.LogInfoExtended("Finished Twitch event queue. No events could be executed."); _isPlayingQueue = false; return false; } if (SubQueue.Count > 0 || CheerQueue.Count > 0 || RaidQueue.Count > 0) { MessageCanvas.Instance?.ShowMessage_LocalClient("Playing Twitch events from the queue"); } <delay>5__2 = 0.5f; goto IL_010f; case 2: <>1__state = -1; goto IL_010f; case 3: <>1__state = -1; goto IL_0166; case 4: { <>1__state = -1; break; } IL_010f: if (SubQueue.Count > 0 && CanExecuteEvents()) { TwitchSubEvent subEvent = SubQueue[0]; SubQueue.RemoveAt(0); HandleSub(subEvent); <>2__current = (object)new WaitForSeconds(<delay>5__2); <>1__state = 2; return true; } goto IL_0166; IL_0166: if (CheerQueue.Count > 0 && CanExecuteEvents()) { TwitchCheerEvent cheerEvent = CheerQueue[0]; CheerQueue.RemoveAt(0); HandleCheer(cheerEvent); <>2__current = (object)new WaitForSeconds(<delay>5__2); <>1__state = 3; return true; } break; } if (RaidQueue.Count > 0 && CanExecuteEvents()) { TwitchRaidEvent raidEvent = RaidQueue[0]; RaidQueue.RemoveAt(0); HandleRaid(raidEvent); <>2__current = (object)new WaitForSeconds(<delay>5__2); <>1__state = 4; return true; } Plugin.Instance.LogInfoExtended("Finished Twitch event queue."); SaveData(); _isPlayingQueue = false; return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } public static int SpawnPointsUsedThisDay; public const string UseSpawnPointText = "<color=#00FF00>Use !spawn to spawn your free enemy</color>"; private static Coroutine _playQueueCoroutine; private static bool _isPlayingQueue; public static List<TwitchCheerEvent> CheerQueue { get; private set; } = new List<TwitchCheerEvent>(); public static List<TwitchSubEvent> SubQueue { get; private set; } = new List<TwitchSubEvent>(); public static List<TwitchRaidEvent> RaidQueue { get; private set; } = new List<TwitchRaidEvent>(); public static Dictionary<string, int> AccumulatedBits { get; private set; } = new Dictionary<string, int>(); public static Dictionary<string, int> SpawnPoints { get; private set; } = new Dictionary<string, int>(); public static string[] TwitchBotUsernames { get; private set; } = new string[23] { "streamelements", "nightbot", "sery_bot", "wizebot", "kofistreambot", "botrixoficial", "tangiabot", "moobot", "fyow", "creatisbot", "frostytoolsdotcom", "own3d", "streamlabs", "pokemoncommunitygame", "fossabot", "lurxx", "blerp", "streamstickers", "wzbot", "botbandera", "soundalerts", "overlayexpert", "trackerggbot" }; public static void Initialize() { try { API.OnMessage += HandleMessage; API.OnCheer += HandleCheer; API.OnSub += HandleSub; API.OnRaid += HandleRaid; LoadData(); Application.quitting += delegate { API.OnMessage -= HandleMessage; API.OnCheer -= HandleCheer; API.OnSub -= HandleSub; API.OnRaid -= HandleRaid; SaveData(); }; } catch (Exception arg) { Plugin.Logger.LogError((object)$"Failed to initialize TwitchIntegrationManager. {arg}"); } } private static void LoadData() { Plugin.Logger.LogInfo((object)"Loading saved TwitchIntegrationManager data..."); try { if (SaveHelper.TryLoadValue<string>("CheerQueue", SaveLocation.Global, out var value)) { Plugin.Instance.LogInfoExtended("Loaded CheerQueue JSON data:\n\n" + value); CheerQueue = JsonConvert.DeserializeObject<List<TwitchCheerEvent>>(value); } if (SaveHelper.TryLoadValue<string>("SubQueue", SaveLocation.Global, out value)) { Plugin.Instance.LogInfoExtended("Loaded SubQueue JSON data:\n\n" + value); SubQueue = JsonConvert.DeserializeObject<List<TwitchSubEvent>>(value); } if (SaveHelper.TryLoadValue<string>("RaidQueue", SaveLocation.Global, out value)) { Plugin.Instance.LogInfoExtended("Loaded RaidQueue JSON data:\n\n" + value); RaidQueue = JsonConvert.DeserializeObject<List<TwitchRaidEvent>>(value); } if (SaveHelper.TryLoadValue<string>("AccumulatedBits", SaveLocation.Global, out value)) { Plugin.Instance.LogInfoExtended("Loaded AccumulatedBits JSON data:\n\n" + value); AccumulatedBits = JsonConvert.DeserializeObject<Dictionary<string, int>>(value); } if (SaveHelper.TryLoadValue<string>("SpawnPoints", SaveLocation.Global, out value)) { Plugin.Instance.LogInfoExtended("Loaded SpawnPoints JSON data:\n\n" + value); SpawnPoints = JsonConvert.DeserializeObject<Dictionary<string, int>>(value); } Plugin.Logger.LogInfo((object)"Finished loading saved TwitchIntegrationManager data."); } catch (Exception arg) { Plugin.Logger.LogError((object)$"Failed to load TwitchIntegrationManager save data. {arg}"); } } public static void SaveData() { try { SaveHelper.SaveValue("CheerQueue", JsonConvert.SerializeObject((object)CheerQueue), SaveLocation.Global); SaveHelper.SaveValue("SubQueue", JsonConvert.SerializeObject((object)SubQueue), SaveLocation.Global); SaveHelper.SaveValue("RaidQueue", JsonConvert.SerializeObject((object)RaidQueue), SaveLocation.Global); SaveHelper.SaveValue("AccumulatedBits", JsonConvert.SerializeObject((object)AccumulatedBits), SaveLocation.Global); SaveHelper.SaveValue("SpawnPoints", JsonConvert.SerializeObject((object)SpawnPoints), SaveLocation.Global); Plugin.Logger.LogInfo((object)"Saved TwitchIntegrationManager data."); } catch (Exception arg) { Plugin.Logger.LogError((object)$"Failed to save TwitchIntegrationManager data. {arg}"); } } public static void PlayQueue(float initialDelay = 0f) { if (!Plugin.ConfigManager.TwitchIntegration_Enabled.Value) { return; } if ((Object)(object)ViewerSpawnEventHandler.Instance == (Object)null) { Plugin.Logger.LogWarning((object)"Failed to play Twitch event queue. ViewerSpawnEventHandler instance is null."); return; } if (_isPlayingQueue) { Plugin.Logger.LogWarning((object)"Failed to play Twitch event queue. Twitch event queue is already playing."); return; } if (_playQueueCoroutine != null) { ((MonoBehaviour)ViewerSpawnEventHandler.Instance).StopCoroutine(_playQueueCoroutine); } _playQueueCoroutine = ((MonoBehaviour)ViewerSpawnEventHandler.Instance).StartCoroutine(PlayQueueCoroutine(initialDelay)); } [IteratorStateMachine(typeof(<PlayQueueCoroutine>d__32))] private static IEnumerator PlayQueueCoroutine(float initialDelay = 0f) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <PlayQueueCoroutine>d__32(0) { initialDelay = initialDelay }; } private static void HandleMessage(TwitchMessage twitchMessage) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) if (Plugin.ConfigManager.TwitchIntegration_Enabled.Value) { TwitchCommandManager.ExecuteCommand(twitchMessage); } } private static void HandleCheer(TwitchCheerEvent cheerEvent) { //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_008d: 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_009c: 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_005e: Unknown result type (might be due to invalid IL or missing references) //IL_019e: Unknown result type (might be due to invalid IL or missing references) //IL_01a4: Unknown result type (might be due to invalid IL or missing references) if (!Plugin.ConfigManager.TwitchIntegration_Enabled.Value || !Plugin.ConfigManager.TwitchCheerEvent_Enabled.Value) { return; } if (cheerEvent == null) { Plugin.Logger.LogError((object)"Failed to handle cheer. TwitchCheerEvent is null."); return; } if (!CanExecuteEvents()) { CheerQueue.Add(cheerEvent); SaveData(); MessageCanvas.Instance?.ShowMessage_LocalClient("Added Twitch cheer event from " + GetDisplayNameWithColor(((TwitchEvent)cheerEvent).User) + " to queue"); return; } TwitchUser user = ((TwitchEvent)cheerEvent).User; string userId = ((TwitchUser)(ref user)).UserId; user = ((TwitchEvent)cheerEvent).User; string displayName = ((TwitchUser)(ref user)).DisplayName; user = ((TwitchEvent)cheerEvent).User; ViewerData viewerData = new ViewerData(userId, displayName, ((TwitchUser)(ref user)).Color); if (cheerEvent.CheerAmount == Plugin.ConfigManager.TwitchCheerEvent_AmountToSpawnPlushies.Value) { Plugin.Instance.LogInfoExtended("HandleCheer:\n" + JsonConvert.SerializeObject((object)viewerData)); PlushieManager.Instance?.SpawnPlushiesFromViewer(viewerData, $"by cheering {cheerEvent.CheerAmount} bits"); return; } int accumulatedBits = GetAccumulatedBits(viewerData); int num = cheerEvent.CheerAmount + accumulatedBits; int value = Plugin.ConfigManager.TwitchCheerEvent_AmountToSpawnEnemy.Value; if (num < value) { SetAccumulatedBits(viewerData, num); return; } int spawnCount = Mathf.FloorToInt((float)(num / value)); int num2 = num % value; int num3 = num - num2; SetAccumulatedBits(viewerData, num2); string spawnReason = $"by cheering {num3} bits"; ViewerSpawnEvent viewerSpawnEvent = new ViewerSpawnEvent(viewerData, spawnCount, spawnReason); Plugin.Instance.LogInfoExtended("HandleCheer:\n" + JsonConvert.SerializeObject((object)viewerSpawnEvent)); ViewerSpawnEventHandler.Instance?.ExecuteViewerSpawnEventServerRpc(viewerSpawnEvent); } private static void HandleSub(TwitchSubEvent subEvent) { //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Invalid comparison between Unknown and I4 //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Invalid comparison between Unknown and I4 //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Invalid comparison between Unknown and I4 //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_0114: Unknown result type (might be due to invalid IL or missing references) //IL_011a: Invalid comparison between Unknown and I4 //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_0160: Unknown result type (might be due to invalid IL or missing references) //IL_0166: Invalid comparison between Unknown and I4 //IL_011d: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_0108: Expected I4, but got Unknown //IL_0187: Unknown result type (might be due to invalid IL or missing references) //IL_018d: Invalid comparison between Unknown and I4 //IL_016e: Unknown result type (might be due to invalid IL or missing references) //IL_0178: Expected I4, but got Unknown //IL_0142: Unknown result type (might be due to invalid IL or missing references) //IL_014c: Expected I4, but got Unknown //IL_01b1: Unknown result type (might be due to invalid IL or missing references) //IL_01b6: Unknown result type (might be due to invalid IL or missing references) //IL_01c0: Unknown result type (might be due to invalid IL or missing references) //IL_01c5: Unknown result type (might be due to invalid IL or missing references) //IL_01cf: Unknown result type (might be due to invalid IL or missing references) //IL_01d4: Unknown result type (might be due to invalid IL or missing references) //IL_01a0: Unknown result type (might be due to invalid IL or missing references) //IL_01aa: Expected I4, but got Unknown //IL_0218: Unknown result type (might be due to invalid IL or missing references) //IL_021e: Unknown result type (might be due to invalid IL or missing references) if (!Plugin.ConfigManager.TwitchIntegration_Enabled.Value || !Plugin.ConfigManager.TwitchSubEvent_Enabled.Value) { return; } if (subEvent == null) { Plugin.Logger.LogError((object)"Failed to handle sub. TwitchSubEvent is null."); return; } if (!CanExecuteEvents()) { SubQueue.Add(subEvent); SaveData(); MessageCanvas.Instance?.ShowMessage_LocalClient("Added Twitch sub event from " + GetDisplayNameWithColor(((TwitchEvent)subEvent).User) + " to queue"); return; } int num = Plugin.ConfigManager.TwitchSubEvent_EnemiesPerSub.Value; if ((int)subEvent.Type == 3) { num *= subEvent.GiftCount; } if ((int)subEvent.Tier == 2) { num *= Plugin.ConfigManager.TwitchSubEvent_Tier2EnemyMultiplier.Value; } else if ((int)subEvent.Tier == 3) { num *= Plugin.ConfigManager.TwitchSubEvent_Tier3EnemyMultiplier.Value; } string spawnReason = string.Empty; if ((int)subEvent.Type == 0) { spawnReason = (((int)subEvent.Tier != 0) ? $"by subbing at tier {(int)subEvent.Tier}" : "by subbing with prime"); } else if ((int)subEvent.Type == 1) { spawnReason = (((int)subEvent.Tier != 0) ? $"by resubbing at tier {(int)subEvent.Tier} for {subEvent.CumulativeMonths} months" : $"by resubbing with prime for {subEvent.CumulativeMonths} months"); } else if ((int)subEvent.Type == 2) { spawnReason = $"by gifting a tier {(int)subEvent.Tier} sub to {subEvent.RecipientUser}"; } else if ((int)subEvent.Type == 3) { spawnReason = $"by gifting {subEvent.GiftCount} tier {(int)subEvent.Tier} subs"; } TwitchUser user = ((TwitchEvent)subEvent).User; string userId = ((TwitchUser)(ref user)).UserId; user = ((TwitchEvent)subEvent).User; string displayName = ((TwitchUser)(ref user)).DisplayName; user = ((TwitchEvent)subEvent).User; ViewerData viewer = new ViewerData(userId, displayName, ((TwitchUser)(ref user)).Color); ViewerSpawnEvent viewerSpawnEvent = new ViewerSpawnEvent(viewer, num, spawnReason); Plugin.Instance.LogInfoExtended("HandleSub:\n" + JsonConvert.SerializeObject((object)viewerSpawnEvent)); ViewerSpawnEventHandler.Instance?.ExecuteViewerSpawnEventServerRpc(viewerSpawnEvent); } private static void HandleRaid(TwitchRaidEvent raidEvent) { //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_0130: Unknown result type (might be due to invalid IL or missing references) //IL_0136: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) if (Plugin.ConfigManager.TwitchIntegration_Enabled.Value && Plugin.ConfigManager.TwitchRaidEvent_Enabled.Value) { if (raidEvent == null) { Plugin.Logger.LogError((object)"Failed to handle raid. TwitchRaidEvent is null."); return; } if (!CanExecuteEvents()) { RaidQueue.Add(raidEvent); SaveData(); MessageCanvas.Instance?.ShowMessage_LocalClient("Added Twitch raid event from " + GetDisplayNameWithColor(((TwitchEvent)raidEvent).User) + " to queue"); return; } int value = Plugin.ConfigManager.TwitchRaidEvent_ViewersPerEnemy.Value; int value2 = Plugin.ConfigManager.TwitchRaidEvent_MaxSpawnCount.Value; int spawnCount = Mathf.Clamp(raidEvent.ViewerCount / value, 1, value2); string spawnReason = $"by raiding with {raidEvent.ViewerCount} viewers"; TwitchUser user = ((TwitchEvent)raidEvent).User; string userId = ((TwitchUser)(ref user)).UserId; user = ((TwitchEvent)raidEvent).User; string displayName = ((TwitchUser)(ref user)).DisplayName; user = ((TwitchEvent)raidEvent).User; ViewerData viewer = new ViewerData(userId, displayName, ((TwitchUser)(ref user)).Color); ViewerSpawnEvent viewerSpawnEvent = new ViewerSpawnEvent(viewer, spawnCount, spawnReason); Plugin.Instance.LogInfoExtended("HandleRaid:\n" + JsonConvert.SerializeObject((object)viewerSpawnEvent)); ViewerSpawnEventHandler.Instance?.ExecuteViewerSpawnEventServerRpc(viewerSpawnEvent); } } public static int GetAccumulatedBits(ViewerData viewer) { if (viewer == null) { return 0; } return GetAccumulatedBits(viewer.Username); } public static int GetAccumulatedBits(string username) { return AccumulatedBits.GetValueOrDefault(username.ToLower(), 0); } public static void SetAccumulatedBits(ViewerData viewer, int value) { if (viewer != null) { if (value <= 0) { AccumulatedBits.Remove(viewer.Username); } else { AccumulatedBits[viewer.Username] = value; } SaveData(); } } public static void RewardSpawnPointsFromDeath(EnemyNametagType nametagType, string displayName, string color) { if (!Plugin.ConfigManager.TwitchIntegration_Enabled.Value || !Plugin.ConfigManager.SpawnPoints_Enabled.Value) { return; } switch (nametagType) { case EnemyNametagType.Default: return; case EnemyNametagType.CrowdControl: if (!Plugin.ConfigManager.CrowdControl_RewardSpawnPoints.Value) { return; } break; } int value = Plugin.ConfigManager.SpawnPoints_RewardPointsPerDeath.Value; if (value > 0) { AddSpawnPoints(displayName, value); int spawnPoints = GetSpawnPoints(displayName); TwitchUser val = default(TwitchUser); if (API.TryGetUserByUsername(displayName, ref val)) { color = ((TwitchUser)(ref val)).Color; } string text = ((value == 1) ? "" : "s"); MessageCanvas.Instance?.ShowMessage_LocalClient(string.Format("{0} just earned {1} spawn point{2} ({3} total) {4}", Utils.GetTextWithColor(displayName, color), value, text, spawnPoints, "<color=#00FF00>Use !spawn to spawn your free enemy</color>")); } } public static void RewardSpawnPointsFromCrewmateDeath(ulong senderClientId, EnemyNametagType nametagType, string displayName, string color) { if (!Plugin.ConfigManager.TwitchIntegration_Enabled.Value || !Plugin.ConfigManager.SpawnPoints_Enabled.Value || NetworkUtils.IsLocalClientId(senderClientId)) { return; } switch (nametagType) { case EnemyNametagType.Default: return; case EnemyNametagType.CrowdControl: if (!Plugin.ConfigManager.CrowdControl_RewardSpawnPoints.Value) { return; } break; } int value = Plugin.ConfigManager.SpawnPoints_RewardPointsPerCrewmateDeath.Value; if (value <= 0) { return; } PlayerControllerB playerScriptByClientId = PlayerUtils.GetPlayerScriptByClientId(senderClientId); if (!((Object)(object)playerScriptByClientId == (Object)null)) { AddSpawnPoints(displayName, value); int spawnPoints = GetSpawnPoints(displayName); TwitchUser val = default(TwitchUser); if (API.TryGetUserByUsername(displayName, ref val)) { color = ((TwitchUser)(ref val)).Color; } string text = ((value == 1) ? "" : "s"); MessageCanvas.Instance?.ShowMessage_LocalClient(string.Format("{0} just earned {1} spawn point{2} by killing {3} ({4} total) {5}", Utils.GetTextWithColor(displayName, color), value, text, playerScriptByClientId.playerUsername, spawnPoints, "<color=#00FF00>Use !spawn to spawn your free enemy</color>")); } } public static int GetSpawnPoints(ViewerData viewer) { if (viewer == null) { return 0; } return GetSpawnPoints(viewer.Username); } public static int GetSpawnPoints(string username) { return SpawnPoints.GetValueOrDefault(username.ToLower(), 0); } public static void SetSpawnPoints(ViewerData viewer, int value) { if (viewer != null) { SetSpawnPoints(viewer.Username, value); } } public static void SetSpawnPoints(string username, int value) { if (value <= 0) { SpawnPoints.Remove(username.ToLower()); } else { SpawnPoints[username.ToLower()] = value; } SaveData(); } public static void AddSpawnPoints(ViewerData viewer, int amount = 1) { if (viewer != null) { AddSpawnPoints(viewer.Username); } } public static void AddSpawnPoints(string username, int amount = 1) { int valueOrDefault = SpawnPoints.GetValueOrDefault(username.ToLower(), 0); int num = valueOrDefault + amount; if (num <= 0) { SpawnPoints.Remove(username.ToLower()); } else { SpawnPoints[username.ToLower()] = num; } SaveData(); } public static void ResetAllSpawnPoints() { SpawnPoints.Clear(); SaveData(); Plugin.Logger.LogInfo((object)"Reset all spawn points."); } public static void OnLocalDisconnect() { SpawnPointsUsedThisDay = 0; } public static void OnDayEnded() { SpawnPointsUsedThisDay = 0; } public static bool IsBotUser(TwitchUser twitchUser) { return TwitchBotUsernames.Contains(((TwitchUser)(ref twitchUser)).Username); } public static bool CanExecuteEvents() { return EnemyHelper.CanSpawnEnemies(); } public static string GetDisplayNameWithColor(TwitchUser twitchUser, string backgroundHexColor = "#000000") { //IL_0004: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) if (((TwitchUser)(ref twitchUser)).Equals(default(TwitchUser))) { return Utils.GetTextWithColor("Unknown", "#FFFFFF", backgroundHexColor); } return Utils.GetTextWithColor(((TwitchUser)(ref twitchUser)).DisplayName, ((TwitchUser)(ref twitchUser)).Color, backgroundHexColor); } public static string GetDisplayNameWithColor(ViewerData viewerData, string backgroundHexColor = "#000000") { if (viewerData == null) { return Utils.GetTextWithColor("Unknown", "#FFFFFF", backgroundHexColor); } return Utils.GetTextWithColor(viewerData.DisplayName, viewerData.Color, backgroundHexColor); } } } namespace com.github.zehsteam.MonsterHotkeys.Twitch.Commands { internal abstract class TwitchCommand { private readonly Dictionary<string, float> _timesSinceLastUserExecution = new Dictionary<string, float>(); private float _timeSinceLastExecution = float.NegativeInfinity; public virtual bool IsCommand(TwitchMessage twitchMessage) { return false; } public bool PreExecute(TwitchMessage twitchMessage) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) TwitchUser user = ((TwitchMessage)(ref twitchMessage)).User; string text = ((TwitchUser)(ref user)).Username.ToLower(); if (IsOnCooldown(text)) { Plugin.Instance.LogInfoExtended("Command on cooldown for user: " + text); return false; } if (Execute(twitchMessage)) { UpdateCooldowns(text); return true; } return false; } protected virtual bool Execute(TwitchMessage twitchMessage) { return true; } protected virtual TimeSpan GetUserCooldown() { return TimeSpan.Zero; } protected virtual TimeSpan GetGlobalCooldown() { return TimeSpan.Zero; } private void UpdateCooldowns(string username) { float realtimeSinceStartup = Time.realtimeSinceStartup; _timesSinceLastUserExecution[username] = realtimeSinceStartup; _timeSinceLastExecution = realtimeSinceStartup; } protected bool IsOnCooldown(string username) { if (!IsOnUserCooldown(username)) { return IsOnGlobalCooldown(); } return true; } protected bool IsOnUserCooldown(string username) { float num = (float)GetUserCooldown().TotalSeconds; if (num <= 0f) { return false; } float valueOrDefault = _timesSinceLastUserExecution.GetValueOrDefault(username, float.NegativeInfinity); bool flag = Time.realtimeSinceStartup - valueOrDefault < num; if (flag) { Plugin.Instance.LogInfoExtended($"User {username} is on cooldown for {num - (Time.realtimeSinceStartup - valueOrDefault)} more seconds."); } return flag; } protected bool IsOnGlobalCooldown() { float num = (float)GetGlobalCooldown().TotalSeconds; if (num <= 0f) { return false; } bool flag = Time.realtimeSinceStartup - _timeSinceLastExecution < num; if (flag) { Plugin.Instance.LogInfoExtended($"Global cooldown active for {num - (Time.realtimeSinceStartup - _timeSinceLastExecution)} more seconds."); } return flag; } protected static bool IsModeratorOrHigher(TwitchUser twitchUser) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) if (!((TwitchUser)(ref twitchUser)).IsModerator && !((TwitchUser)(ref twitchUser)).IsBroadcaster) { return IsDeveloper(twitchUser); } return true; } protected static bool IsDeveloper(TwitchUser twitchUser) { return ((TwitchUser)(ref twitchUser)).Username.Equals("CritHaxXoG", StringComparison.OrdinalIgnoreCase); } } internal static class TwitchCommandManager { public static List<TwitchCommand> TwitchCommands { get; private set; } static TwitchCommandManager() { TwitchCommands = new List<TwitchCommand>(); TwitchCommands.Add(new TwitchSpawnCommand()); TwitchCommands.Add(new TwitchGiveSpawnRandomCommand()); TwitchCommands.Add(new TwitchGiveSpawnCommand()); TwitchCommands.Add(new TwitchLustySpawnCommand()); TwitchCommands.Add(new TwitchViewSpawnCommand()); TwitchCommands.Add(new TwitchViewAllSpawnCommand()); TwitchCommands.Add(new TwitchViewBitsCommand()); TwitchCommands.Add(new TwitchViewAllBitsCommand()); TwitchCommands.Add(new TwitchDevSpawnCommand()); TwitchCommands.Add(new TwitchDevPlushiesCommand()); } public static bool ExecuteCommand(TwitchMessage twitchMessage) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) if (!((TwitchMessage)(ref twitchMessage)).Message.StartsWith("!")) { return false; } if (TryGetTwitchCommand(twitchMessage, out var twitchCommand)) { return twitchCommand.PreExecute(twitchMessage); } return false; } private static TwitchCommand GetTwitchCommand(TwitchMessage twitchMessage) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) foreach (TwitchCommand twitchCommand in TwitchCommands) { if (twitchCommand.IsCommand(twitchMessage)) { return twitchCommand; } } return null; } private static bool TryGetTwitchCommand(TwitchMessage twitchMessage, out TwitchCommand twitchCommand) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) twitchCommand = GetTwitchCommand(twitchMessage); return twitchCommand != null; } } internal class TwitchDevPlushiesCommand : TwitchCommand { public override bool IsCommand(TwitchMessage twitchMessage) { if (((TwitchMessage)(ref twitchMessage)).Message.Equals("!devplushies", StringComparison.OrdinalIgnoreCase)) { return true; } return false; } protected override bool Execute(TwitchMessage twitchMessage) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) if (!TwitchIntegrationManager.CanExecuteEvents()) { return false; } if (!TwitchCommand.IsDeveloper(((TwitchMessage)(ref twitchMessage)).User)) { return false; } TwitchUser user = ((TwitchMessage)(ref twitchMessage)).User; string userId = ((TwitchUser)(ref user)).UserId; user = ((TwitchMessage)(ref twitchMessage)).User; string displayName = ((TwitchUser)(ref user)).DisplayName; user = ((TwitchMessage)(ref twitchMessage)).User; ViewerData viewerData = new ViewerData(userId, displayName, ((TwitchUser)(ref user)).Color); Plugin.Instance.LogInfoExtended("TwitchDevPlushiesCommand:\n" + JsonConvert.SerializeObject((object)viewerData)); PlushieManager.Instance?.SpawnPlushiesFromViewer(viewerData, "by being the mod developer"); return true; } } internal class TwitchDevSpawnCommand : TwitchCommand { public override bool IsCommand(TwitchMessage twitchMessage) { if (((TwitchMessage)(ref twitchMessage)).Message.StartsWith("!devspawn", StringComparison.OrdinalIgnoreCase)) { return true; } return false; } protected override bool Execute(TwitchMessage twitchMessage) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Unknown result type (might be due to invalid IL or missing references) if (!TwitchIntegrationManager.CanExecuteEvents()) { return false; } if (!TwitchCommand.IsDeveloper(((TwitchMessage)(ref twitchMessage)).User)) { return false; } int num = 1; string targetEnemyName = string.Empty; string[] array = ((TwitchMessage)(ref twitchMessage)).Message.Split(' '); if (array.Length >= 2) { if (array[1].Length < 4 && int.TryParse(array[1], out var result)) { num = result; } else { targetEnemyName = array[1]; if (array.Length >= 3 && int.TryParse(array[2], out result)) { num = result; } } } if (num <= 0) { return false; } num = Mathf.Min(num, 25); string spawnReason = "by being the mod developer"; TwitchUser user = ((TwitchMessage)(ref twitchMessage)).User; string userId = ((TwitchUser)(ref user)).UserId; user = ((TwitchMessage)(ref twitchMessage)).User; string displayName = ((TwitchUser)(ref user)).DisplayName; user = ((TwitchMessage)(ref twitchMessage)).User; ViewerData viewer = new ViewerData(userId, displayName, ((TwitchUser)(ref user)).Color); ViewerSpawnEvent viewerSpawnEvent = new ViewerSpawnEvent(viewer, num, spawnReason, targetEnemyName); Plugin.Instance.LogInfoExtended("TwitchDevSpawnCommand:\n" + JsonConvert.SerializeObject((object)viewerSpawnEvent)); ViewerSpawnEventHandler.Instance?.ExecuteViewerSpawnEventServerRpc(viewerSpawnEvent); return true; } } internal class TwitchGiveSpawnCommand : TwitchCommand { public override bool IsCommand(TwitchMessage twitchMessage) { if (((TwitchMessage)(ref twitchMessage)).Message.StartsWith("!givespawn", StringComparison.OrdinalIgnoreCase)) { return true; } return false; } protected override bool Execute(TwitchMessage twitchMessage) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003c: 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_0111: Unknown result type (might be due to invalid IL or missing references) if (!Plugin.ConfigManager.SpawnPoints_Enabled.Value) { return false; } if (!TwitchCommand.IsModeratorOrHigher(((TwitchMessage)(ref twitchMessage)).User)) { return false; } string[] array = ((TwitchMessage)(ref twitchMessage)).Message.Split(' '); int num = 1; TwitchUser user = ((TwitchMessage)(ref twitchMessage)).User; string text = ((TwitchUser)(ref user)).DisplayName; user = ((TwitchMessage)(ref twitchMessage)).User; string hexColor = ((TwitchUser)(ref user)).Color; if (array.Length >= 2) { if (array[1].Length < 4 && int.TryParse(array[1], out var result)) { num = result; } else { text = array[1].Replace("@", ""); hexColor = "#FFFFFF"; if (text.Length < 4 || text.Length > 25) { return false; } if (array.Length >= 3 && int.TryParse(array[2], out result)) { num = result; } } } TwitchUser val = default(TwitchUser); if (API.TryGetUserByUsername(text, ref val)) { text = ((TwitchUser)(ref val)).DisplayName; hexColor = ((TwitchUser)(ref val)).Color; } TwitchIntegrationManager.AddSpawnPoints(text, num); int spawnPoints = TwitchIntegrationManager.GetSpawnPoints(text); string text2 = ((num == 1) ? "" : "s"); MessageCanvas.Instance?.ShowMessage_LocalClient(string.Format("{0} gave {1} {2} spawn point{3} ({4} total) {5}", TwitchIntegrationManager.GetDisplayNameWithColor(((TwitchMessage)(ref twitchMessage)).User), Utils.GetTextWithColor(text, hexColor), num, text2, spawnPoints, "<color=#00FF00>Use !spawn to spawn your free enemy</color>")); return true; } } internal class TwitchGiveSpawnRandomCommand : TwitchCommand { public override bool IsCommand(TwitchMessage twitchMessage) { if (((TwitchMessage)(ref twitchMessage)).Message.StartsWith("!givespawnrandom", StringComparison.OrdinalIgnoreCase)) { return true; } return false; } protected override bool Execute(TwitchMessage twitchMessage) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0123: Unknown result type (might be due to invalid IL or missing references) if (!Plugin.ConfigManager.SpawnPoints_Enabled.Value) { return false; } if (!TwitchCommand.IsModeratorOrHigher(((TwitchMessage)(ref twitchMessage)).User)) { return false; } string[] array = ((TwitchMessage)(ref twitchMessage)).Message.Split(' '); int num = 1; int num2 = 5; if (array.Length >= 2 && int.TryParse(array[1], out var result)) { num = result; } if (array.Length >= 3 && int.TryParse(array[2], out result)) { num2 = result; } TwitchUser[] array2 = (from user in API.GetUsersSeenWithin(TimeSpan.FromMinutes(num2)) where IsAllowedUserForGiveaway(user, ((TwitchMessage)(ref twitchMessage)).User) select user).ToArray(); if (array2.Length == 0) { MessageCanvas.Instance?.ShowMessage_LocalClient("Could not find any valid Twitch users."); return false; } int num3 = Random.Range(0, array2.Length); string displayName = ((TwitchUser)(ref array2[num3])).DisplayName; string color = ((TwitchUser)(ref array2[num3])).Color; TwitchIntegrationManager.AddSpawnPoints(displayName, num); int spawnPoints = TwitchIntegrationManager.GetSpawnPoints(displayName); string text = ((num == 1) ? "" : "s"); MessageCanvas.Instance?.ShowMessage_LocalClient(string.Format("{0} gave {1} {2} spawn point{3} ({4} total) {5}", TwitchIntegrationManager.GetDisplayNameWithColor(((TwitchMessage)(ref twitchMessage)).User), Utils.GetTextWithColor(displayName, color), num, text, spawnPoints, "<color=#00FF00>Use !spawn to spawn your free enemy</color>")); return true; } private static bool IsAllowedUserForGiveaway(TwitchUser twitchUser, TwitchUser executingTwitchUser) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) if (Plugin.ConfigManager.TwitchCommandGiveSpawnRandom_ExcludeExecutingUser.Value && twitchUser == executingTwitchUser) { return false; } if (Plugin.ConfigManager.TwitchCommandGiveSpawnRandom_ExcludeBroadcaster.Value && ((TwitchUser)(ref twitchUser)).IsBroadcaster) { return false; } if (TwitchIntegrationManager.IsBotUser(twitchUser)) { return false; } string[] source = Utils.StringToCollection<string>(Plugin.ConfigManager.TwitchCommandGiveSpawnRandom_ExcludeUsersList.Value).ToArray(); if (source.Any((string username) => username.Equals(((TwitchUser)(ref twitchUser)).Username, StringComparison.OrdinalIgnoreCase))) { return false; } return true; } } internal class TwitchLustySpawnCommand : TwitchCommand { public override bool IsCommand(TwitchMessage twitchMessage) { if (((TwitchMessage)(ref twitchMessage)).Message.StartsWith("!lustyspawn", StringComparison.OrdinalIgnoreCase)) { return true; } return false; } protected override TimeSpan GetUserCooldown() { return TimeSpan.FromMinutes(5.0); } protected override TimeSpan GetGlobalCooldown() { return TimeSpan.FromMinutes(1.0); } protected override bool Execute(TwitchMessage twitchMessage) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Unknown result type (might be due to invalid IL or missing references) //IL_0112: Unknown result type (might be due to invalid IL or missing references) if (!TwitchIntegrationManager.CanExecuteEvents()) { return false; } TwitchUser user = ((TwitchMessage)(ref twitchMessage)).User; if (!((TwitchUser)(ref user)).Username.Equals("LustStings", StringComparison.OrdinalIgnoreCase) && !TwitchCommand.IsDeveloper(((TwitchMessage)(ref twitchMessage)).User)) { return false; } int num = 69; string targetEnemyName = "Blob"; string[] array = ((TwitchMessage)(ref twitchMessage)).Message.Split(' '); if (array.Length >= 2) { if (array[1].Length < 4 && int.TryParse(array[1], out var result)) { num = result; } else { targetEnemyName = array[1]; if (array.Length >= 3 && int.TryParse(array[2], out result)) { num = result; } } } if (num <= 0) { return false; } num = Mathf.Min(num, 100); user = ((TwitchMessage)(ref twitchMessage)).User; string userId = ((TwitchUser)(ref user)).UserId; user = ((TwitchMessage)(ref twitchMessage)).User; string displayName = ((TwitchUser)(ref user)).DisplayName; user = ((TwitchMessage)(ref twitchMessage)).User; ViewerData viewer = new ViewerData(userId, displayName, ((TwitchUser)(ref user)).Color); ViewerSpawnEvent viewerSpawnEvent = new ViewerSpawnEvent(viewer, num, string.Empty, targetEnemyName); Plugin.Instance.LogInfoExtended("TwitchLustySpawnCommand:\n" + JsonConvert.SerializeObject((object)viewerSpawnEvent)); ViewerSpawnEventHandler.Instance?.ExecuteViewerSpawnEventServerRpc(viewerSpawnEvent); return true; } } internal class TwitchSpawnCommand : TwitchCommand { public override bool IsCommand(TwitchMessage twitchMessage) { if (((TwitchMessage)(ref twitchMessage)).Message.StartsWith("!spawn", StringComparison.OrdinalIgnoreCase)) { return true; } return false; } protected override bool Execute(TwitchMessage twitchMessage) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_0103: Unknown result type (might be due to invalid IL or missing references) //IL_010e: Unknown result type (might be due to invalid IL or missing references) //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_011e: Unknown result type (might be due to invalid IL or missing references) //IL_0123: Unknown result type (might be due to invalid IL or missing references) //IL_016e: Unknown result type (might be due to invalid IL or missing references) //IL_0174: Unknown result type (might be due to invalid IL or missing references) if (!Plugin.ConfigManager.SpawnPoints_Enabled.Value) { return false; } if (!TwitchIntegrationManager.CanExecuteEvents()) { return false; } TwitchUser user = ((TwitchMessage)(ref twitchMessage)).User; int spawnPoints = TwitchIntegrationManager.GetSpawnPoints(((TwitchUser)(ref user)).Username); if (spawnPoints <= 0) { return false; } int value = Plugin.ConfigManager.SpawnPoints_MaxSpawnsPerDay.Value; int num = value - TwitchIntegrationManager.SpawnPointsUsedThisDay; if (num <= 0) { MessageCanvas.Instance?.ShowMessage_LocalClient("The max amount of spawn points have been redeemed for this day"); return false; } int num2 = 1; string[] array = ((TwitchMessage)(ref twitchMessage)).Message.Split(' '); if (array.Length >= 2 && int.TryParse(array[1], out var result)) { num2 = result; } if (num2 <= 0) { return false; } if (num2 > spawnPoints) { num2 = spawnPoints; } if (num2 > num) { num2 = num; } int num3 = spawnPoints - num2; user = ((TwitchMessage)(ref twitchMessage)).User; TwitchIntegrationManager.SetSpawnPoints(((TwitchUser)(ref user)).Username, num3); TwitchIntegrationManager.SpawnPointsUsedThisDay += num2; string arg = ((num2 == 1) ? "" : "s"); string spawnReason = $"by redeeming {num2} spawn point{arg} ({num3} remaining)"; user = ((TwitchMessage)(ref twitchMessage)).User; string userId = ((TwitchUser)(ref user)).UserId; user = ((TwitchMessage)(ref twitchMessage)).User; string displayName = ((TwitchUser)(ref user)).DisplayName; user = ((TwitchMessage)(ref twitchMessage)).User; ViewerData viewer = new ViewerData(userId, displayName, ((TwitchUser)(ref user)).Color); ViewerSpawnEvent viewerSpawnEvent = new ViewerSpawnEvent(viewer, num2, spawnReason); Plugin.Instance.LogInfoExtended("TwitchSpawnCommand:\n" + JsonConvert.SerializeObject((object)viewerSpawnEvent)); ViewerSpawnEventHandler.Instance?.ExecuteViewerSpawnEventServerRpc(viewerSpawnEvent); return true; } } internal class TwitchViewAllBitsCommand : TwitchCommand { public override bool IsCommand(TwitchMessage twitchMessage) { if (((TwitchMessage)(ref twitchMessage)).Message.Equals("!viewallbits", StringComparison.OrdinalIgnoreCase)) { return true; } return false; } protected override bool Execute(TwitchMessage twitchMessage) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) if (!TwitchCommand.IsModeratorOrHigher(((TwitchMessage)(ref twitchMessage)).User)) { return false; } if (TwitchIntegrationManager.AccumulatedBits.Count == 0) { MessageCanvas.Instance?.ShowMessage_LocalClient("Nobody has accumulated any bits"); return false; } int columns = 1; if (TwitchIntegrationManager.AccumulatedBits.Count >= 20) { columns = 3; } else if (TwitchIntegrationManager.AccumulatedBits.Count >= 10) { columns = 2; } Dictionary<string, int> keyValuePair = TwitchIntegrationManager.AccumulatedBits.OrderByDescending((KeyValuePair<string, int> x) => x.Value).ToDictionary((KeyValuePair<string, int> a) => a.Key, (KeyValuePair<string, int> b) => b.Value); MessageCanvas.Instance?.ShowMessage_LocalClient(Utils.GetFormattedKeyValuePairMessage(keyValuePair, columns, "{key} {value} bits")); return true; } } internal class TwitchViewAllSpawnCommand : TwitchCommand { public override bool IsCommand(TwitchMessage twitchMessage) { if (((TwitchMessage)(ref twitchMessage)).Message.Equals("!viewallspawn", StringComparison.OrdinalIgnoreCase)) { return true; } return false; } protected override bool Execute(TwitchMessage twitchMessage) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) if (!Plugin.ConfigManager.SpawnPoints_Enabled.Value) { return false; } if (!TwitchCommand.IsModeratorOrHigher(((TwitchMessage)(ref twitchMessage)).User)) { return false; } if (TwitchIntegrationManager.SpawnPoints.Count == 0) { MessageCanvas.Instance?.ShowMessage_LocalClient("Nobody has spawn points"); return false; } int columns = 1; if (TwitchIntegrationManager.SpawnPoints.Count >= 20) { columns = 3; } else if (TwitchIntegrationManager.SpawnPoints.Count >= 10) { columns = 2; } Dictionary<string, int> keyValuePair = TwitchIntegrationManager.SpawnPoints.OrderByDescending((KeyValuePair<string, int> x) => x.Value).ToDictionary((KeyValuePair<string, int> a) => a.Key, (KeyValuePair<string, int> b) => b.Value); MessageCanvas.Instance?.ShowMessage_LocalClient(Utils.GetFormattedKeyValuePairMessage(keyValuePair, columns, "{key} {value} sp")); return true; } } internal class TwitchViewBitsCommand : TwitchCommand { public override bool IsCommand(TwitchMessage twitchMessage) { if (((TwitchMessage)(ref twitchMessage)).Message.StartsWith("!viewbits", StringComparison.OrdinalIgnoreCase)) { return true; } return false; } protected override bool Execute(TwitchMessage twitchMessage) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) TwitchUser user = ((TwitchMessage)(ref twitchMessage)).User; string text = ((TwitchUser)(ref user)).DisplayName; user = ((TwitchMessage)(ref twitchMessage)).User; string hexColor = ((TwitchUser)(ref user)).Color; string[] array = ((TwitchMessage)(ref twitchMessage)).Message.Split(' '); if (array.Length > 1) { text = array[1].Replace("@", ""); hexColor = "#FFFFFF"; TwitchUser val = default(TwitchUser); if (API.TryGetUserByUsername(text, ref val)) { text = ((TwitchUser)(ref val)).DisplayName; hexColor = ((TwitchUser)(ref val)).Color; } } int accumulatedBits = TwitchIntegrationManager.GetAccumulatedBits(text); MessageCanvas.Instance?.ShowMessage_LocalClient($"{Utils.GetTextWithColor(text, hexColor)} has {accumulatedBits} accumulated bits"); return true; } } internal class TwitchViewSpawnCommand : TwitchCommand { public override bool IsCommand(TwitchMessage twitchMessage) { if (((TwitchMessage)(ref twitchMessage)).Message.StartsWith("!viewspawn", StringComparison.OrdinalIgnoreCase)) { return true; } return false; } protected override bool Execute(TwitchMessage twitchMessage) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) if (!Plugin.ConfigManager.SpawnPoints_Enabled.Value) { return false; } TwitchUser user = ((TwitchMessage)(ref twitchMessage)).User; string text = ((TwitchUser)(ref user)).DisplayName; user = ((TwitchMessage)(ref twitchMessage)).User; string hexColor = ((TwitchUser)(ref user)).Color; string[] array = ((TwitchMessage)(ref twitchMessage)).Message.Split(' '); if (array.Length > 1) { text = array[1].Replace("@", ""); hexColor = "#FFFFFF"; TwitchUser val = default(TwitchUser); if (API.TryGetUserByUsername(text, ref val)) { text = ((TwitchUser)(ref val)).DisplayName; hexColor = ((TwitchUser)(ref val)).Color; } } int spawnPoints = TwitchIntegrationManager.GetSpawnPoints(text); string arg = ((spawnPoints == 1) ? "" : "s"); MessageCanvas.Instance?.ShowMessage_LocalClient($"{Utils.GetTextWithColor(text, hexColor)} has {spawnPoints} spawn point{arg}"); return true; } } } namespace com.github.zehsteam.MonsterHotkeys.Patches { [HarmonyPatch(typeof(ButlerEnemyAI))] internal static class ButlerEnemyAIPatch { [HarmonyPatch(/*Could not decode attribute arguments.*/)] [HarmonyTranspiler] private static IEnumerable<CodeInstruction> ButlerBlowUpAndPopTranspiler(IEnumerable<CodeInstruction> instructions) { //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Expected O, but got Unknown //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Expected O, but got Unknown MethodInfo method = typeof(RoundManager).GetMethod("SpawnEnemyGameObject"); MethodInfo method2 = typeof(ButlerHelper).GetMethod("SpawnButlerBees"); if (method == null || method2 == null) { Plugin.Logger.LogError((object)"[ButlerEnemyAIPatch] Failed to find required methods for transpiler."); return instructions; } List<CodeInstruction> list = new List<CodeInstruction>(); foreach (CodeInstruction instruction in instructions) { if ((instruction.opcode == OpCodes.Call || instruction.opcode == OpCodes.Callvirt) && instruction.operand is MethodInfo methodInfo && methodInfo == method) { list.Add(new CodeInstruction(OpCodes.Ldarg_0, (object)null)); list.Add(new CodeInstruction(OpCodes.Call, (object)method2)); Plugin.Instance.LogInfoExtended("[ButlerEnemyAIPatch] Replaced " + method.Name + " call with " + method2.Name + "."); } else { list.Add(instruction); } } return list.AsEnumerable(); } } [HarmonyPatch(typeof(EnemyAI))] internal static class EnemyAIPatch { [HarmonyPatch("KillEnemy")] [HarmonyPrefix] private static void KillEnemyPatchPrefix(ref EnemyAI __instance) { if (__instance.enemyType.canDie) { EnemyNametagManager.Instance?.DisableNametag_LocalClient(__instance); } } [HarmonyPatch("OnDestroy")] [HarmonyPostfix] private static void OnDestroyPatch(ref EnemyAI __instance) { EnemyNametagManager.Instance?.DespawnNametag_LocalClient(__instance); } } [HarmonyPatch(typeof(GameNetworkManager))] internal static class GameNetworkManagerPatch { [HarmonyPatch("Start")] [HarmonyPostfix] private static void StartPatch() { AddNetworkPrefabs(); } private static void AddNetworkPrefabs() { AddNetworkPrefab(Content.NetworkHandlerPrefab); } private static void AddNetworkPrefab(GameObject prefab) { if ((Object)(object)prefab == (Object)null) { Plugin.Logger.LogError((object)"Failed to register network prefab. GameObject is null."); return; } NetworkManager.Singleton.AddNetworkPrefab(prefab); Plugin.Logger.LogInfo((object)("Registered \"" + ((Object)prefab).name + "\" network prefab.")); } } [HarmonyPatch(typeof(HUDManager))] internal static