Decompiled source of TwitchChat v1.5.3
TwitchChat.dll
Decompiled 2 weeks ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.Linq; using System.Net.Http; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; using System.Web; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using MenuLib; using MenuLib.MonoBehaviors; using Microsoft.CodeAnalysis; using Newtonsoft.Json; using Photon.Pun; using REPOLib.Modules; using TMPro; using TwitchChatAPI; using TwitchChatAPI.Enums; using TwitchChatAPI.Objects; using TwitchIntegration.Commands; using TwitchIntegration.Core; using TwitchIntegration.Core.Utils; using TwitchIntegration.Game; using TwitchIntegration.Game.Commands; using TwitchIntegration.Game.Utils; using TwitchIntegration.Twitch; using TwitchIntegration.Twitch.ChannelPoints.Commands; using TwitchIntegration.UI; using TwitchRepoIntegration.Core; using UnityEngine; using UnityEngine.Networking; using UnityEngine.SceneManagement; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("TwitchChat")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyDescription("Twitch chat integration for REPO Game")] [assembly: AssemblyFileVersion("1.5.3.0")] [assembly: AssemblyInformationalVersion("1.5.3-alpha.0.3+1a317d6c56219e06e8399799fc4d8814b7b5d784")] [assembly: AssemblyProduct("TwitchRepoIntegration")] [assembly: AssemblyTitle("TwitchChat")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace TwitchRepoIntegration { public static class MyPluginInfo { public const string PLUGIN_GUID = "TwitchChat"; public const string PLUGIN_NAME = "TwitchRepoIntegration"; public const string PLUGIN_VERSION = "1.5.1"; } } namespace TwitchRepoIntegration.Core { [HarmonyPatch(typeof(RunManager))] public static class RunManagerPatch { [HarmonyPatch("ChangeLevel")] [HarmonyPostfix] public static void ChangeLevel_Postfix() { EnemyUtil.Init(); } } [HarmonyPatch(typeof(EnemyParent))] public static class EnemyParentPatch { public static bool spawning; [HarmonyPatch("Despawn")] [HarmonyPrefix] private static bool Despawn_Prefix(float ___SpawnedTimeMin, float ___SpawnedTimeMax, ref float ___SpawnedTimer) { if (spawning) { spawning = false; ___SpawnedTimer = Random.Range(___SpawnedTimeMin, ___SpawnedTimeMax); return false; } return true; } } [HarmonyPatch(typeof(ChatManager), "MessageSend")] public static class ChatMessageSendPatch { [HarmonyPrefix] private static bool Prefix(ChatManager __instance, bool _possessed = false) { try { string chatMessage = __instance.chatMessage; GameChatMessage gameChatMessage = new GameChatMessage("", chatMessage); if (gameChatMessage.IsValidCommand && GameCommandProcessor.Instance.ProcessCommand(gameChatMessage)) { __instance.chatMessage = ""; } return true; } catch (Exception ex) { LogManagerWrapper.LogError("Error processing chat command: " + ex.Message); return true; } } } } namespace TwitchIntegration { public static class ConfigManager { public delegate void ConfigValueChangedHandler<T>(T oldValue, T newValue); public delegate void ConfigChangedHandler(); public enum PositionPreset { TopRight, TopLeft, MiddleRight, MiddleLeft, BottomLeft, BottomRight, Manual } public const float DEFAULT_FONT_SIZE = 8f; public const float DEFAULT_OPACITY = 1f; public const PositionPreset DEFAULT_POSITION_PRESET = PositionPreset.BottomRight; public static readonly Vector2 DEFAULT_MANUAL_POSITION = new Vector2(0f, 0f); public const float DEFAULT_WIDTH = 200f; public const float DEFAULT_HEIGHT = 300f; public const float DEFAULT_BUFFER = 20f; public const bool DEFAULT_CHAT_WINDOW_VISIBLE = true; public const bool DEFAULT_SHOW_LABELS = true; public const float DEFAULT_BACKGROUND_OPACITY = 0.2f; public const float DEFAULT_MESSAGE_TTL = 0f; public const bool DEFAULT_ENABLE_LOGGER = false; public const bool DEFAULT_SHOW_TELEMETRY_UI = false; public const bool DEFAULT_CHANNEL_POINTS_TTS = true; public const bool DEFAULT_SUBSCRIBER_TTS = true; public const bool DEFAULT_CHATCOMMAND_ENABLED = true; public const string DEFAULT_TWITCH_USERNAME = "justinfan3102"; public const string DEFAULT_TWITCH_OAUTH = "SCHMOOPIIE"; public const string DEFAULT_TWITCH_CHANNEL = ""; public const KeyCode DEFAULT_SETTINGS_MENU_KEY = 292; public const KeyCode DEFAULT_MANUAL_POSITION_KEY = 290; public const bool DEFAULT_REQUIRE_CHANNEL_POINTS = false; public const bool DEFAULT_SE_COMMAND_ENABLED = true; public const bool DEFAULT_REVIVE_COMMAND_ENABLED = true; internal static ConfigEntry<float> FontSizeConfig; internal static ConfigEntry<float> OpacityConfig; internal static ConfigEntry<PositionPreset> PresetConfig; internal static ConfigEntry<Vector2> ManualPositionConfig; internal static ConfigEntry<float> WidthConfig; internal static ConfigEntry<float> HeightConfig; internal static ConfigEntry<float> BufferConfig; internal static ConfigEntry<KeyCode> SettingsMenuKeyConfig; internal static ConfigEntry<KeyCode> ManualPositionKeyConfig; internal static ConfigEntry<bool> ChatWindowVisibleConfig; internal static ConfigEntry<bool> ShowLabelsConfig; internal static ConfigEntry<float> BackgroundOpacityConfig; internal static ConfigEntry<float> MessageTTLConfig; internal static ConfigEntry<bool> EnableLoggerConfig; internal static ConfigEntry<bool> ShowTelemetryUIConfig; internal static ConfigEntry<bool> ChannelPointsTTSConfig; internal static ConfigEntry<bool> SubscriberTTSConfig; internal static ConfigEntry<bool> ChatCommandsEnabledConfig; internal static ConfigEntry<string> TwitchUsernameConfig; internal static ConfigEntry<string> TwitchOAuthConfig; internal static ConfigEntry<string> TwitchChannelConfig; internal static ConfigEntry<bool> RequireChannelPointsConfig; internal static ConfigEntry<bool> SECommandEnabledConfig; internal static ConfigEntry<bool> ReviveCommandEnabledConfig; public static Dictionary<string, float> ttlOptions = new Dictionary<string, float> { { "Disabled", 0f }, { "5 seconds", 5f }, { "15 seconds", 15f }, { "30 seconds", 30f }, { "1 minute", 60f }, { "3 minute", 180f } }; public static float FontSize { get { return FontSizeConfig?.Value ?? 8f; } set { if (FontSizeConfig != null) { float value2 = FontSizeConfig.Value; FontSizeConfig.Value = value; NotifyValueChanged(ConfigManager.OnFontSizeChanged, value2, value); } } } public static float Opacity { get { return OpacityConfig?.Value ?? 1f; } set { if (OpacityConfig != null) { float value2 = OpacityConfig.Value; OpacityConfig.Value = value; NotifyValueChanged(ConfigManager.OnOpacityChanged, value2, value); } } } public static PositionPreset Preset { get { return PresetConfig?.Value ?? PositionPreset.BottomRight; } set { if (PresetConfig != null) { PositionPreset value2 = PresetConfig.Value; PresetConfig.Value = value; NotifyValueChanged(ConfigManager.OnPresetChanged, value2, value); } } } public static Vector2 ManualPosition { get { //IL_0011: 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) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) return ManualPositionConfig?.Value ?? DEFAULT_MANUAL_POSITION; } set { //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) //IL_001e: 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_002b: Unknown result type (might be due to invalid IL or missing references) if (ManualPositionConfig != null) { Vector2 value2 = ManualPositionConfig.Value; ManualPositionConfig.Value = value; NotifyValueChanged(ConfigManager.OnManualPositionChanged, value2, value); } } } public static float Width { get { return WidthConfig?.Value ?? 200f; } set { if (WidthConfig != null) { float value2 = WidthConfig.Value; WidthConfig.Value = value; NotifyValueChanged(ConfigManager.OnWidthChanged, value2, value); } } } public static float Height { get { return HeightConfig?.Value ?? 300f; } set { if (HeightConfig != null) { float value2 = HeightConfig.Value; HeightConfig.Value = value; NotifyValueChanged(ConfigManager.OnHeightChanged, value2, value); } } } public static float Buffer { get { return BufferConfig?.Value ?? 20f; } set { if (BufferConfig != null) { float value2 = BufferConfig.Value; BufferConfig.Value = value; NotifyValueChanged(ConfigManager.OnBufferChanged, value2, value); } } } public static KeyCode SettingsMenuKey { get { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) ConfigEntry<KeyCode> settingsMenuKeyConfig = SettingsMenuKeyConfig; return (KeyCode)((settingsMenuKeyConfig == null) ? 292 : ((int)settingsMenuKeyConfig.Value)); } set { //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) //IL_001e: 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_002b: Unknown result type (might be due to invalid IL or missing references) if (SettingsMenuKeyConfig != null) { KeyCode value2 = SettingsMenuKeyConfig.Value; SettingsMenuKeyConfig.Value = value; NotifyValueChanged(ConfigManager.OnSettingsMenuKeyChanged, value2, value); } } } public static KeyCode ManualPositionKey { get { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) ConfigEntry<KeyCode> manualPositionKeyConfig = ManualPositionKeyConfig; return (KeyCode)((manualPositionKeyConfig == null) ? 290 : ((int)manualPositionKeyConfig.Value)); } set { //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) //IL_001e: 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_002b: Unknown result type (might be due to invalid IL or missing references) if (ManualPositionKeyConfig != null) { KeyCode value2 = ManualPositionKeyConfig.Value; ManualPositionKeyConfig.Value = value; NotifyValueChanged(ConfigManager.OnManualPositionKeyChanged, value2, value); } } } public static bool ChatWindowVisible { get { return ChatWindowVisibleConfig?.Value ?? true; } set { if (ChatWindowVisibleConfig != null) { bool value2 = ChatWindowVisibleConfig.Value; ChatWindowVisibleConfig.Value = value; NotifyValueChanged(ConfigManager.OnChatWindowVisibleChanged, value2, value); } } } public static bool ShowLabels { get { return ShowLabelsConfig?.Value ?? true; } set { if (ShowLabelsConfig != null) { bool value2 = ShowLabelsConfig.Value; ShowLabelsConfig.Value = value; NotifyValueChanged(ConfigManager.OnShowLabelsChanged, value2, value); } } } public static float BackgroundOpacity { get { return BackgroundOpacityConfig?.Value ?? 0.2f; } set { if (BackgroundOpacityConfig != null) { float value2 = BackgroundOpacityConfig.Value; BackgroundOpacityConfig.Value = value; NotifyValueChanged(ConfigManager.OnBackgroundOpacityChanged, value2, value); } } } public static float MessageTTL { get { return MessageTTLConfig?.Value ?? 0f; } set { if (MessageTTLConfig != null) { float value2 = MessageTTLConfig.Value; MessageTTLConfig.Value = value; NotifyValueChanged(ConfigManager.OnMessageTTLChanged, value2, value); } } } public static bool EnableLogger { get { return EnableLoggerConfig?.Value ?? false; } set { if (EnableLoggerConfig != null) { bool value2 = EnableLoggerConfig.Value; EnableLoggerConfig.Value = value; NotifyValueChanged(ConfigManager.OnEnableLoggerChanged, value2, value); LogManagerWrapper.enableLogger = value; } } } public static bool ShowTelemetryUI { get { return ShowTelemetryUIConfig?.Value ?? false; } set { if (ShowTelemetryUIConfig != null) { bool value2 = ShowTelemetryUIConfig.Value; ShowTelemetryUIConfig.Value = value; NotifyValueChanged(ConfigManager.OnShowTelemetryUIChanged, value2, value); } } } public static bool ChannelPointsTTS { get { return ChannelPointsTTSConfig?.Value ?? true; } set { if (ChannelPointsTTSConfig != null) { bool value2 = ChannelPointsTTSConfig.Value; ChannelPointsTTSConfig.Value = value; NotifyValueChanged(ConfigManager.OnChannelPointsTTSChanged, value2, value); } } } public static bool SubscriberTTS { get { return SubscriberTTSConfig?.Value ?? true; } set { if (SubscriberTTSConfig != null) { bool value2 = SubscriberTTSConfig.Value; SubscriberTTSConfig.Value = value; NotifyValueChanged(ConfigManager.OnSubscriberTTSChanged, value2, value); } } } public static bool ChatCommandsEnabled { get { return ChatCommandsEnabledConfig?.Value ?? true; } set { if (ChatCommandsEnabledConfig != null) { bool value2 = ChatCommandsEnabledConfig.Value; ChatCommandsEnabledConfig.Value = value; NotifyValueChanged(ConfigManager.OnChatCommandsEnabledChanged, value2, value); } } } public static string TwitchUsername { get { return TwitchUsernameConfig?.Value ?? "justinfan3102"; } set { if (TwitchUsernameConfig != null) { string value2 = TwitchUsernameConfig.Value; TwitchUsernameConfig.Value = value; NotifyValueChanged(ConfigManager.OnTwitchUsernameChanged, value2, value); } } } public static string TwitchOAuth { get { return TwitchOAuthConfig?.Value ?? "SCHMOOPIIE"; } set { if (TwitchOAuthConfig != null) { string value2 = TwitchOAuthConfig.Value; TwitchOAuthConfig.Value = value; NotifyValueChanged(ConfigManager.OnTwitchOAuthChanged, value2, value); } } } public static string TwitchChannel { get { return TwitchChannelConfig?.Value ?? ""; } set { if (TwitchChannelConfig != null) { string value2 = TwitchChannelConfig.Value; TwitchChannelConfig.Value = value; NotifyValueChanged(ConfigManager.OnTwitchChannelChanged, value2, value); } } } public static bool RequireChannelPoints { get { return RequireChannelPointsConfig?.Value ?? false; } set { if (RequireChannelPointsConfig != null) { bool value2 = RequireChannelPointsConfig.Value; RequireChannelPointsConfig.Value = value; NotifyValueChanged(ConfigManager.OnRequireChannelPointsChanged, value2, value); } } } public static bool SECommandEnabled { get { return SECommandEnabledConfig?.Value ?? true; } set { if (SECommandEnabledConfig != null) { bool value2 = SECommandEnabledConfig.Value; SECommandEnabledConfig.Value = value; NotifyValueChanged(ConfigManager.OnSECommandEnabledChanged, value2, value); } } } public static bool ReviveCommandEnabled { get { return ReviveCommandEnabledConfig?.Value ?? true; } set { if (ReviveCommandEnabledConfig != null) { bool value2 = ReviveCommandEnabledConfig.Value; ReviveCommandEnabledConfig.Value = value; NotifyValueChanged(ConfigManager.OnReviveCommandEnabledChanged, value2, value); } } } public static event ConfigChangedHandler OnAnyConfigChanged; public static event ConfigValueChangedHandler<float> OnFontSizeChanged; public static event ConfigValueChangedHandler<float> OnOpacityChanged; public static event ConfigValueChangedHandler<PositionPreset> OnPresetChanged; public static event ConfigValueChangedHandler<Vector2> OnManualPositionChanged; public static event ConfigValueChangedHandler<float> OnWidthChanged; public static event ConfigValueChangedHandler<float> OnHeightChanged; public static event ConfigValueChangedHandler<float> OnBufferChanged; public static event ConfigValueChangedHandler<KeyCode> OnSettingsMenuKeyChanged; public static event ConfigValueChangedHandler<KeyCode> OnManualPositionKeyChanged; public static event ConfigValueChangedHandler<bool> OnChatWindowVisibleChanged; public static event ConfigValueChangedHandler<bool> OnShowLabelsChanged; public static event ConfigValueChangedHandler<float> OnBackgroundOpacityChanged; public static event ConfigValueChangedHandler<float> OnMessageTTLChanged; public static event ConfigValueChangedHandler<bool> OnEnableLoggerChanged; public static event ConfigValueChangedHandler<bool> OnShowTelemetryUIChanged; public static event ConfigValueChangedHandler<bool> OnChannelPointsTTSChanged; public static event ConfigValueChangedHandler<bool> OnSubscriberTTSChanged; public static event ConfigValueChangedHandler<bool> OnChatCommandsEnabledChanged; public static event ConfigValueChangedHandler<string> OnTwitchUsernameChanged; public static event ConfigValueChangedHandler<string> OnTwitchOAuthChanged; public static event ConfigValueChangedHandler<string> OnTwitchChannelChanged; public static event ConfigValueChangedHandler<bool> OnRequireChannelPointsChanged; public static event ConfigValueChangedHandler<bool> OnSECommandEnabledChanged; public static event ConfigValueChangedHandler<bool> OnReviveCommandEnabledChanged; internal static void Configure(BaseUnityPlugin plugin) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Expected O, but got Unknown //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Expected O, but got Unknown //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Expected O, but got Unknown //IL_0106: Unknown result type (might be due to invalid IL or missing references) //IL_0116: Unknown result type (might be due to invalid IL or missing references) //IL_0120: Expected O, but got Unknown //IL_0169: Unknown result type (might be due to invalid IL or missing references) //IL_0173: Expected O, but got Unknown //IL_01bc: Unknown result type (might be due to invalid IL or missing references) //IL_01c6: Expected O, but got Unknown //IL_020f: Unknown result type (might be due to invalid IL or missing references) //IL_0219: Expected O, but got Unknown //IL_0262: Unknown result type (might be due to invalid IL or missing references) //IL_026c: Expected O, but got Unknown //IL_02b5: Unknown result type (might be due to invalid IL or missing references) //IL_02bf: Expected O, but got Unknown //IL_0304: Unknown result type (might be due to invalid IL or missing references) //IL_030e: Expected O, but got Unknown //IL_0353: Unknown result type (might be due to invalid IL or missing references) //IL_035d: Expected O, but got Unknown //IL_03a6: Unknown result type (might be due to invalid IL or missing references) //IL_03b0: Expected O, but got Unknown //IL_03f5: Unknown result type (might be due to invalid IL or missing references) //IL_03ff: Expected O, but got Unknown //IL_0444: Unknown result type (might be due to invalid IL or missing references) //IL_044e: Expected O, but got Unknown //IL_0493: Unknown result type (might be due to invalid IL or missing references) //IL_049d: Expected O, but got Unknown //IL_04e2: Unknown result type (might be due to invalid IL or missing references) //IL_04ec: Expected O, but got Unknown //IL_0535: Unknown result type (might be due to invalid IL or missing references) //IL_053f: Expected O, but got Unknown //IL_0588: Unknown result type (might be due to invalid IL or missing references) //IL_0592: Expected O, but got Unknown //IL_05db: Unknown result type (might be due to invalid IL or missing references) //IL_05e5: Expected O, but got Unknown //IL_062e: Unknown result type (might be due to invalid IL or missing references) //IL_0638: Expected O, but got Unknown //IL_067d: Unknown result type (might be due to invalid IL or missing references) //IL_0687: Expected O, but got Unknown //IL_06cc: Unknown result type (might be due to invalid IL or missing references) //IL_06d6: Expected O, but got Unknown //IL_071b: Unknown result type (might be due to invalid IL or missing references) //IL_0725: Expected O, but got Unknown FontSizeConfig = CreateConfigEntry(plugin.Config.Bind<float>("General", "FontSize", 8f, new ConfigDescription("The font size for chat messages in pixels. (Range: 6-24 pixels)", (AcceptableValueBase)null, Array.Empty<object>())), delegate(float oldValue, float newValue) { ConfigManager.OnFontSizeChanged?.Invoke(oldValue, newValue); }); OpacityConfig = CreateConfigEntry(plugin.Config.Bind<float>("General", "Opacity", 1f, new ConfigDescription("The twitch chat opacity. (Recommended value = 0.85)", (AcceptableValueBase)null, Array.Empty<object>())), delegate(float oldValue, float newValue) { ConfigManager.OnOpacityChanged?.Invoke(oldValue, newValue); }); PresetConfig = CreateConfigEntry(plugin.Config.Bind<PositionPreset>("Position", "Preset", PositionPreset.BottomRight, new ConfigDescription("The twitch chat position preset. (Recommended value = TopRight)", (AcceptableValueBase)null, Array.Empty<object>())), delegate(PositionPreset oldValue, PositionPreset newValue) { ConfigManager.OnPresetChanged?.Invoke(oldValue, newValue); }); ManualPositionConfig = CreateConfigEntry(plugin.Config.Bind<Vector2>("Position", "Manual Position", DEFAULT_MANUAL_POSITION, new ConfigDescription("The position of the twitch chat as X, Y coordinates when using Manual position preset.", (AcceptableValueBase)null, Array.Empty<object>())), delegate(Vector2 oldValue, Vector2 newValue) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) ConfigManager.OnManualPositionChanged?.Invoke(oldValue, newValue); }); WidthConfig = CreateConfigEntry(plugin.Config.Bind<float>("Dimensions", "Width", 200f, new ConfigDescription("The width of the twitch chat window. (Recommended value = 375)", (AcceptableValueBase)null, Array.Empty<object>())), delegate(float oldValue, float newValue) { ConfigManager.OnWidthChanged?.Invoke(oldValue, newValue); }); HeightConfig = CreateConfigEntry(plugin.Config.Bind<float>("Dimensions", "Height", 300f, new ConfigDescription("The height of the twitch chat window. (Recommended value = 375)", (AcceptableValueBase)null, Array.Empty<object>())), delegate(float oldValue, float newValue) { ConfigManager.OnHeightChanged?.Invoke(oldValue, newValue); }); BufferConfig = CreateConfigEntry(plugin.Config.Bind<float>("Dimensions", "Buffer", 20f, new ConfigDescription("The buffer between edge of screen added to presets. (Recommended value = 20)", (AcceptableValueBase)null, Array.Empty<object>())), delegate(float oldValue, float newValue) { ConfigManager.OnBufferChanged?.Invoke(oldValue, newValue); }); SettingsMenuKeyConfig = CreateConfigEntry(plugin.Config.Bind<KeyCode>("Key Bindings", "SettingsMenu", (KeyCode)292, new ConfigDescription("The key to toggle the Twitch settings menu", (AcceptableValueBase)null, Array.Empty<object>())), delegate(KeyCode oldValue, KeyCode newValue) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) ConfigManager.OnSettingsMenuKeyChanged?.Invoke(oldValue, newValue); }); ManualPositionKeyConfig = CreateConfigEntry(plugin.Config.Bind<KeyCode>("Key Bindings", "ManualPosition", (KeyCode)290, new ConfigDescription("The key to enable manual positioning of the chat window", (AcceptableValueBase)null, Array.Empty<object>())), delegate(KeyCode oldValue, KeyCode newValue) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) ConfigManager.OnManualPositionKeyChanged?.Invoke(oldValue, newValue); }); ChatWindowVisibleConfig = CreateConfigEntry(plugin.Config.Bind<bool>("Chat Window", "Visible", true, new ConfigDescription("Whether the chat window is visible", (AcceptableValueBase)null, Array.Empty<object>())), delegate(bool oldValue, bool newValue) { ConfigManager.OnChatWindowVisibleChanged?.Invoke(oldValue, newValue); }); ShowLabelsConfig = CreateConfigEntry(plugin.Config.Bind<bool>("Chat Window", "Show Labels", true, new ConfigDescription("Whether to show the channel and toggle key labels", (AcceptableValueBase)null, Array.Empty<object>())), delegate(bool oldValue, bool newValue) { ConfigManager.OnShowLabelsChanged?.Invoke(oldValue, newValue); }); BackgroundOpacityConfig = CreateConfigEntry(plugin.Config.Bind<float>("Chat Window", "Background Opacity", 0.2f, new ConfigDescription("The opacity of the chat window background (range: 0-1)", (AcceptableValueBase)null, Array.Empty<object>())), delegate(float oldValue, float newValue) { ConfigManager.OnBackgroundOpacityChanged?.Invoke(oldValue, newValue); }); EnableLoggerConfig = CreateConfigEntry(plugin.Config.Bind<bool>("Logger", "Enable Logger", false, new ConfigDescription("Whether to enable logging functionality", (AcceptableValueBase)null, Array.Empty<object>())), delegate(bool oldValue, bool newValue) { ConfigManager.OnEnableLoggerChanged?.Invoke(oldValue, newValue); }); ChannelPointsTTSConfig = CreateConfigEntry(plugin.Config.Bind<bool>("Twitch Connection", "Channel Points TTS", true, new ConfigDescription("Whether to play TTS for Channel Points messages", (AcceptableValueBase)null, Array.Empty<object>())), delegate(bool oldValue, bool newValue) { ConfigManager.OnChannelPointsTTSChanged?.Invoke(oldValue, newValue); }); SubscriberTTSConfig = CreateConfigEntry(plugin.Config.Bind<bool>("Twitch Connection", "Subscriber TTS", true, new ConfigDescription("Whether to play TTS for Subscriber messages", (AcceptableValueBase)null, Array.Empty<object>())), delegate(bool oldValue, bool newValue) { ConfigManager.OnSubscriberTTSChanged?.Invoke(oldValue, newValue); }); ChatCommandsEnabledConfig = CreateConfigEntry(plugin.Config.Bind<bool>("Twitch Connection", "Chat Commands", true, new ConfigDescription("Whether to allow chat to send in-game commands", (AcceptableValueBase)null, Array.Empty<object>())), delegate(bool oldValue, bool newValue) { ConfigManager.OnChatCommandsEnabledChanged?.Invoke(oldValue, newValue); }); TwitchUsernameConfig = CreateConfigEntry(plugin.Config.Bind<string>("Twitch Connection", "Username", "justinfan3102", new ConfigDescription("Your Twitch username. Use 'justinfan3102' for anonymous viewing. Can be changed via config file.", (AcceptableValueBase)null, Array.Empty<object>())), delegate(string oldValue, string newValue) { ConfigManager.OnTwitchUsernameChanged?.Invoke(oldValue, newValue); }); TwitchOAuthConfig = CreateConfigEntry(plugin.Config.Bind<string>("Twitch Connection", "OAuth Token", "SCHMOOPIIE", new ConfigDescription("Your Twitch OAuth token. Use 'SCHMOOPIIE' for anonymous viewing. Can be changed via config file.", (AcceptableValueBase)null, Array.Empty<object>())), delegate(string oldValue, string newValue) { ConfigManager.OnTwitchOAuthChanged?.Invoke(oldValue, newValue); }); TwitchChannelConfig = CreateConfigEntry(plugin.Config.Bind<string>("Twitch Connection", "Channel", "", new ConfigDescription("The Twitch channel to connect to. Can be changed in-game with the /channel command.", (AcceptableValueBase)null, Array.Empty<object>())), delegate(string oldValue, string newValue) { ConfigManager.OnTwitchChannelChanged?.Invoke(oldValue, newValue); }); MessageTTLConfig = CreateConfigEntry(plugin.Config.Bind<float>("Chat Window", "Message TTL", 0f, new ConfigDescription("The time in seconds that messages should be displayed before fading out. Set to 0 to disable message fading.", (AcceptableValueBase)null, Array.Empty<object>())), delegate(float oldValue, float newValue) { ConfigManager.OnMessageTTLChanged?.Invoke(oldValue, newValue); }); RequireChannelPointsConfig = CreateConfigEntry(plugin.Config.Bind<bool>("Twitch Connection", "Require Channel Points", false, new ConfigDescription("Whether channel points are required for commands.", (AcceptableValueBase)null, Array.Empty<object>())), delegate(bool oldValue, bool newValue) { ConfigManager.OnRequireChannelPointsChanged?.Invoke(oldValue, newValue); }); SECommandEnabledConfig = CreateConfigEntry(plugin.Config.Bind<bool>("Commands", "SE Command Enabled", true, new ConfigDescription("Whether the '!se' command is enabled.", (AcceptableValueBase)null, Array.Empty<object>())), delegate(bool oldValue, bool newValue) { ConfigManager.OnSECommandEnabledChanged?.Invoke(oldValue, newValue); }); ReviveCommandEnabledConfig = CreateConfigEntry(plugin.Config.Bind<bool>("Commands", "Revive Command Enabled", true, new ConfigDescription("Whether the '!revive' command is enabled.", (AcceptableValueBase)null, Array.Empty<object>())), delegate(bool oldValue, bool newValue) { ConfigManager.OnReviveCommandEnabledChanged?.Invoke(oldValue, newValue); }); } private static ConfigEntry<T> CreateConfigEntry<T>(ConfigEntry<T> entry, Action<T, T> changeCallback) { entry.SettingChanged += delegate { changeCallback?.Invoke(default(T), entry.Value); ConfigManager.OnAnyConfigChanged?.Invoke(); }; return entry; } internal static void ResetDefaultValues() { //IL_0034: Unknown result type (might be due to invalid IL or missing references) bool flag = ConfigManager.OnAnyConfigChanged != null; ConfigChangedHandler onAnyConfigChanged = ConfigManager.OnAnyConfigChanged; ConfigManager.OnAnyConfigChanged = null; try { FontSize = 8f; Opacity = 1f; Preset = PositionPreset.BottomRight; ManualPosition = DEFAULT_MANUAL_POSITION; Width = 200f; Height = 300f; Buffer = 20f; SettingsMenuKey = (KeyCode)292; ManualPositionKey = (KeyCode)290; ChatWindowVisible = true; ShowLabels = true; BackgroundOpacity = 0.2f; EnableLogger = false; TwitchUsername = "justinfan3102"; TwitchOAuth = "SCHMOOPIIE"; MessageTTL = 0f; RequireChannelPoints = false; SECommandEnabled = true; ReviveCommandEnabled = true; } finally { ConfigManager.OnAnyConfigChanged = onAnyConfigChanged; if (flag) { ConfigManager.OnAnyConfigChanged?.Invoke(); } } } private static void NotifyValueChanged<T>(ConfigValueChangedHandler<T> handler, T oldValue, T newValue) { if (handler != null) { try { handler(oldValue, newValue); } catch (Exception ex) { LogManagerWrapper.LogError("Error in config change handler: " + ex.Message); } } } } internal static class StateUtil { internal static bool HasLocalMapToolActive() { PlayerAvatar instance = PlayerAvatar.instance; return (Object)(object)instance != (Object)null && (Object)(object)instance.playerAvatarVisuals.playerAvatarRightArm.mapToolController != (Object)null && instance.playerAvatarVisuals.playerAvatarRightArm.mapToolController.Active; } internal static bool IsInLevel() { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Invalid comparison between Unknown and I4 return SemiFunc.RunIsLevel() && (Object)(object)GameDirector.instance != (Object)null && (int)GameDirector.instance.currentState == 2; } internal static bool IsChatActive() { return (Object)(object)ChatManager.instance != (Object)null && ChatManager.instance.chatActive; } internal static bool IsSpectating() { return (Object)(object)PlayerAvatar.instance != (Object)null && PlayerAvatar.instance.spectating && (Object)(object)SpectateCamera.instance != (Object)null; } internal static bool IsInMainMenu() { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Invalid comparison between Unknown and I4 return (Object)(object)GameDirector.instance != (Object)null && (int)GameDirector.instance.currentState == 2; } } public static class MyPluginInfo { public const string PLUGIN_GUID = "TwitchChat"; public const string PLUGIN_NAME = "TwitchChat"; public const string PLUGIN_VERSION = "1.5.3"; } [BepInPlugin("TwitchChat", "TwitchChat", "1.5.3")] [BepInDependency(/*Could not decode attribute arguments.*/)] public class Plugin : BaseUnityPlugin { private Harmony harmony; public ChatWindow chatWindow; private bool isInitialized = false; internal TelemetryUI telemetryUI; internal static List<TwitchChatMessage> messages = new List<TwitchChatMessage>(25); private const int MaxStoredMessages = 25; internal static Plugin Instance { get; private set; } public static int MessageCount => messages.Count; private void Awake() { try { Instance = this; ConfigManager.Configure((BaseUnityPlugin)(object)this); LogManagerWrapper.Initialize(((BaseUnityPlugin)this).Logger); ((Component)this).gameObject.transform.parent = null; Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject); ((Object)((Component)this).gameObject).hideFlags = (HideFlags)61; SceneManager.sceneLoaded += OnSceneLoaded; API.OnMessage += API_OnMessageReceived; API.OnConnect += API_OnConnect; API.OnDisconnect += API_OnDisconnect; InitializePatches(); InitializeTelemetryUI(); InitializeChatWindow(); SettingsMenu.Initialize(); Task.Run((Func<Task?>)TwitchBadges.LoadAllBadges); LogManagerWrapper.LogInfo("Twitch Chat Window initialized successfully!!"); } catch (Exception ex) { LogManagerWrapper.LogError("Error during plugin initialization: " + ex.Message + "\n" + ex.StackTrace); } } private void API_OnMessageReceived(TwitchMessage e) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) try { PostChannelMessageInMemory(Mappers.ToTwitchChatMessage(e)); TwitchCommandProcessor.ProcessCommand(Mappers.ToTwitchChatMessage(e)); } catch (Exception ex) { LogManagerWrapper.LogError("Error processing message: " + ex.Message); } } private void API_OnDisconnect() { PostChannelMessageInMemory(new TwitchChatMessage("", "Disconnected from channel: " + API.Channel)); } private void API_OnConnect() { PostChannelMessageInMemory(new TwitchChatMessage("", "Joined channel: " + API.Channel)); } private void PostChannelMessageInMemory(TwitchChatMessage chatMessage) { if (!string.IsNullOrEmpty(chatMessage.FullText)) { messages.Add(chatMessage); if (messages.Count > 25) { messages.RemoveAt(0); } } } private void Update() { SettingsMenu.Update(); } private void InitializePatches() { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected O, but got Unknown try { harmony = new Harmony("0cahlo.TwitchIntegration"); harmony.PatchAll(); LogManagerWrapper.LogInfo("Harmony patches applied successfully"); } catch (Exception ex) { LogManagerWrapper.LogError("Error applying Harmony patches: " + ex.Message + "\n" + ex.StackTrace); } } private bool InitializeChatWindow() { //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Expected O, but got Unknown //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Expected O, but got Unknown try { ChatWindow obj = chatWindow; if ((Object)(object)((obj != null) ? ((Component)obj).gameObject : null) != (Object)null) { return true; } Canvas[] source = Object.FindObjectsOfType<Canvas>(); Canvas val = ((IEnumerable<Canvas>)source).FirstOrDefault((Func<Canvas, bool>)((Canvas w) => ((Object)w).name == "HUD Canvas")); if ((Object)(object)val == (Object)null) { GameObject val2 = new GameObject("TwitchChatCanvas"); val = val2.AddComponent<Canvas>(); val.renderMode = (RenderMode)0; CanvasScaler val3 = val2.AddComponent<CanvasScaler>(); val3.uiScaleMode = (ScaleMode)1; val3.referenceResolution = new Vector2(1920f, 1080f); val3.screenMatchMode = (ScreenMatchMode)0; val2.AddComponent<GraphicRaycaster>(); Object.DontDestroyOnLoad((Object)(object)val2); LogManagerWrapper.LogInfo("Canvas marked with DontDestroyOnLoad"); } else { Object.DontDestroyOnLoad((Object)(object)((Component)val).gameObject); LogManagerWrapper.LogInfo("Using existing canvas and marking with DontDestroyOnLoad"); } GameObject val4 = new GameObject("TwitchChatWindow"); val4.transform.SetParent(((Component)val).transform, false); chatWindow = val4.AddComponent<ChatWindow>(); if ((Object)(object)val != (Object)null && (Object)(object)((Component)val).gameObject != (Object)null) { Object.DontDestroyOnLoad((Object)(object)((Component)val).gameObject); } ChatWindow obj2 = chatWindow; isInitialized = (Object)(object)((obj2 != null) ? ((Component)obj2).gameObject : null) != (Object)null; if (isInitialized) { LogManagerWrapper.LogInfo("Chat window initialized successfully"); } } catch (Exception ex) { LogManagerWrapper.LogWarning("Error initializing chat window: " + ex.Message + "\n" + ex.StackTrace); isInitialized = false; } return isInitialized; } private void OnErrorOccurred(object sender, string error) { LogManagerWrapper.LogError("Twitch error occurred: " + error); } private void OnSceneLoaded(Scene scene, LoadSceneMode mode) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) LogManagerWrapper.LogInfo($"Scene changed to: {((Scene)(ref scene)).name}, Load mode: {mode}"); try { InitializeChatWindow(); } catch (Exception ex) { LogManagerWrapper.LogWarning("Error handling scene change: " + ex.Message + "\n" + ex.StackTrace); } } private void OnDisable() { try { SceneManager.sceneLoaded -= OnSceneLoaded; API.OnMessage -= API_OnMessageReceived; LogManagerWrapper.LogInfo("Plugin OnDestroy called - plugin is being destroyed"); LogManagerWrapper.LogWarning("Plugin OnDestroy called - plugin is being DESTROYED"); if ((Object)(object)telemetryUI != (Object)null) { Object.Destroy((Object)(object)((Component)telemetryUI).gameObject); telemetryUI = null; } } catch (Exception ex) { LogManagerWrapper.LogError("Error during plugin cleanup: " + ex.Message); } } public void OnChatWindowDestroyed() { LogManagerWrapper.LogWarning("Plugin notified that ChatWindow was destroyed"); chatWindow = null; } private void InitializeTelemetryUI() { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Expected O, but got Unknown try { GameObject val = new GameObject("TelemetryUI"); val.transform.SetParent(((Component)this).gameObject.transform, false); telemetryUI = val.AddComponent<TelemetryUI>(); Object.DontDestroyOnLoad((Object)(object)val); LogManagerWrapper.LogInfo("Telemetry UI initialized successfully"); } catch (Exception ex) { LogManagerWrapper.LogError("Error initializing telemetry UI: " + ex.Message + "\n" + ex.StackTrace); } } } } namespace TwitchIntegration.Game { public class GameChatMessage : IChatMessage { private static readonly Regex CommandRegex = new Regex("^\\/([\\w\\d]+) (.*)"); public string DisplayName { get; private set; } public string FullText { get; private set; } public bool IsValidCommand { get; private set; } public string CommandName { get; private set; } public string CommandArgs { get; private set; } public GameChatMessage(string username, string text) { DisplayName = username; FullText = text; Match match = CommandRegex.Match(text); if (match.Groups.Count > 0) { IsValidCommand = true; CommandName = match.Groups[1]?.Value; CommandArgs = match.Groups[2]?.Value; } } } public class GameCommandProcessor { private static GameCommandProcessor singleton; private List<ICommand> commands; public static GameCommandProcessor Instance { get { if (singleton == null) { singleton = new GameCommandProcessor(); } return singleton; } } public GameCommandProcessor() { commands = new List<ICommand>(); RegisterCommands(); } private void RegisterCommands() { commands.Add(new ChannelCommand()); LogManagerWrapper.LogInfo($"Registered {commands.Count} game chat commands"); foreach (ICommand command in commands) { LogManagerWrapper.LogInfo(" - " + command.CommandName); } } public bool ProcessCommand(IChatMessage message) { LogManagerWrapper.LogInfo("ProcessGameCommand(): " + message.FullText); if (!message.IsValidCommand) { return false; } ICommand command = commands.FirstOrDefault((ICommand cmd) => cmd.CanHandle(message)); if (command != null) { try { command.Execute(message); return true; } catch (Exception ex) { LogManagerWrapper.LogError("Error executing command " + command.CommandName + ": " + ex.Message); } } return false; } } } namespace TwitchIntegration.Game.Utils { public class EnemyUtil { [CompilerGenerated] private sealed class <SpawnEnemy>d__10 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public EnemySetup enemySetup; public Vector3 position; private GameObject <val>5__1; private EnemyParent <component>5__2; private List<PlayerAvatar>.Enumerator <>s__3; private PlayerAvatar <item>5__4; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <SpawnEnemy>d__10(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <val>5__1 = null; <component>5__2 = null; <>s__3 = default(List<PlayerAvatar>.Enumerator); <item>5__4 = null; <>1__state = -2; } private bool MoveNext() { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Expected O, but got Unknown //IL_0088: 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_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Expected O, but got Unknown //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Unknown result type (might be due to invalid IL or missing references) switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = (object)new WaitForSeconds(3f); <>1__state = 1; return true; case 1: <>1__state = -1; if (SemiFunc.IsMultiplayer()) { Enemies.SpawnEnemy(enemySetup, position, Quaternion.identity, false); return false; } EnemyParentPatch.spawning = true; LevelGenerator.Instance.EnemiesSpawned = -1; <val>5__1 = Object.Instantiate<GameObject>(enemySetup.spawnObjects[0], position, Quaternion.identity); <component>5__2 = <val>5__1.GetComponent<EnemyParent>(); if (!((Object)<component>5__2 != (Object)null)) { return false; } <component>5__2.SetupDone = true; <val>5__1.GetComponentInChildren<Enemy>().EnemyTeleported(position); EnemyDirector.instance.FirstSpawnPointAdd(<component>5__2); EnemyDirector.instance.enemiesSpawned.Add(<component>5__2); <>s__3 = SemiFunc.PlayerGetAll().GetEnumerator(); try { while (<>s__3.MoveNext()) { <item>5__4 = <>s__3.Current; <component>5__2.Enemy.PlayerAdded(<item>5__4.photonView.ViewID); <item>5__4 = null; } } finally { ((IDisposable)<>s__3).Dispose(); } <>s__3 = default(List<PlayerAvatar>.Enumerator); return false; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } private static SortedDictionary<string, EnemySetup> enemySetups = new SortedDictionary<string, EnemySetup>(); private static SortedDictionary<string, EnemySetup> modEnemySetups = new SortedDictionary<string, EnemySetup>(); public static void Init() { enemySetups.Clear(); modEnemySetups.Clear(); List<EnemySetup> list = new List<EnemySetup>(); LogManagerWrapper.LogInfo("loading all enemies:"); LogManagerWrapper.LogInfo("difficult1:"); list.AddRange(EnemyDirector.instance.enemiesDifficulty1); LogManagerWrapper.LogInfo("difficult2:"); list.AddRange(EnemyDirector.instance.enemiesDifficulty2); LogManagerWrapper.LogInfo("difficult3:"); list.AddRange(EnemyDirector.instance.enemiesDifficulty3); foreach (EnemySetup item in list) { LogManagerWrapper.LogInfo($"iterating through enemy list: {item}"); if (!((Object)item).name.StartsWith("Enemy Group")) { string text = ((Object)item).name.Replace("Enemy - ", string.Empty); switch (text) { case "Ceiling Eye": enemySetups.Add("Peeper", item); break; case "Thin Man": enemySetups.Add("ShadowChild", item); break; case "Gnome": enemySetups.Add("Gnome", item); break; case "Duck": enemySetups.Add("ApexPredator", item); break; case "Slow Mouth": enemySetups.Add("Spewer", item); break; case "Valuable Thrower": enemySetups.Add("Rugrat", item); break; case "Animal": enemySetups.Add("Animal", item); break; case "Upscream": enemySetups.Add("Upscream", item); break; case "Hidden": enemySetups.Add("Hidden", item); break; case "Tumbler": enemySetups.Add("Chef", item); break; case "Bowtie": enemySetups.Add("Bowtie", item); break; case "Floater": enemySetups.Add("Mentalist", item); break; case "Bang": enemySetups.Add("Bang", item); break; case "Head": enemySetups.Add("Headman", item); break; case "Robe": enemySetups.Add("Robe", item); break; case "Hunter": enemySetups.Add("Huntsman", item); break; case "Runner": enemySetups.Add("Reaper", item); break; case "Beamer": enemySetups.Add("Clown", item); break; case "Slow Walker": enemySetups.Add("Trudge", item); break; default: modEnemySetups.Add(text, item); break; } } } } public static SortedDictionary<string, EnemySetup> getEnemies() { return enemySetups; } public static SortedDictionary<string, EnemySetup> getModEnemies() { return modEnemySetups; } private static EnemySetup getRandomEnemySetup() { EnemySetup[] array = enemySetups.Select((KeyValuePair<string, EnemySetup> s) => s.Value).ToArray(); int num = Random.Range(0, array.Length - 1); return array[num]; } private static EnemySetup getEnemySetup(string name) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Expected O, but got Unknown EnemySetup valueOrDefault = enemySetups.GetValueOrDefault(name, null); if ((Object)valueOrDefault == (Object)null) { valueOrDefault = modEnemySetups.GetValueOrDefault(name, null); } return valueOrDefault; } public static void spawnRandomEnemy(IChatMessage message) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) if (EnemyParentPatch.spawning) { MissionUI.instance.MissionText("Already spawning enemy!", Color.red, Color.red, 3f); Task.Run(delegate { Thread.Sleep(1000); spawnRandomEnemy(message); }); } else { EnemySetup randomEnemySetup = getRandomEnemySetup(); spawnEnemyAtCurrentPlayerPosition(message, randomEnemySetup); } } public static void spawnEnemyAtCurrentPlayerPosition(IChatMessage message, EnemySetup enemySetup) { //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_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) Vector3 position = ((Component)PlayerAvatar.instance).transform.position; ((MonoBehaviour)EnemyDirector.instance).StartCoroutine(SpawnEnemy(enemySetup, position)); MissionUI.instance.MissionText(message.DisplayName + " spawned an enemy... Run...!", Color.red, Color.red, 6f); } public static void spawnEnemy(IChatMessage message, string enemy) { //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Expected O, but got Unknown //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) if (EnemyParentPatch.spawning) { MissionUI.instance.MissionText("Already spawning enemy '" + enemy + "'!", Color.red, Color.red, 3f); return; } EnemySetup enemySetup = getEnemySetup(enemy); if ((Object)enemySetup != (Object)null) { spawnEnemyAtCurrentPlayerPosition(message, enemySetup); } else { MissionUI.instance.MissionText("Could not find enemy named '" + enemy + "'", Color.red, Color.red, 3f); } } [IteratorStateMachine(typeof(<SpawnEnemy>d__10))] private static IEnumerator SpawnEnemy(EnemySetup enemySetup, Vector3 position) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <SpawnEnemy>d__10(0) { enemySetup = enemySetup, position = position }; } } public class PlayerUtil { public static void killPlayer(PlayerAvatar avatar) { avatar.PlayerDeath(-1); LogManagerWrapper.LogInfo(SemiFunc.PlayerGetName(avatar) + " Killed!"); } public static bool canRevicePlayer(PlayerAvatar avatar) { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Expected O, but got Unknown FieldInfo fieldInfo = AccessTools.Field(typeof(PlayerAvatar), "deadSet"); if (fieldInfo != null && (bool)fieldInfo.GetValue(avatar) && (Object)avatar.playerDeathHead != (Object)null) { PlayerDeathHead playerDeathHead = avatar.playerDeathHead; FieldInfo fieldInfo2 = AccessTools.Field(typeof(PlayerDeathHead), "inExtractionPoint"); if (fieldInfo2 != null) { return true; } return false; } return false; } public static bool revivePlayer(PlayerAvatar avatar) { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Expected O, but got Unknown FieldInfo fieldInfo = AccessTools.Field(typeof(PlayerAvatar), "deadSet"); if (fieldInfo != null && (bool)fieldInfo.GetValue(avatar) && (Object)avatar.playerDeathHead != (Object)null) { PlayerDeathHead playerDeathHead = avatar.playerDeathHead; FieldInfo fieldInfo2 = AccessTools.Field(typeof(PlayerDeathHead), "inExtractionPoint"); if (fieldInfo2 != null) { fieldInfo2.SetValue(playerDeathHead, true); avatar.Revive(false); fieldInfo2.SetValue(playerDeathHead, false); LogManagerWrapper.LogInfo(SemiFunc.PlayerGetName(avatar) + " Revived!"); return true; } LogManagerWrapper.LogError("Failed to grab field 'PlayerDeathHead->inExtractionPoint'!"); return false; } LogManagerWrapper.LogInfo(SemiFunc.PlayerGetName(avatar) + " is not dead. Cannot be revived!"); return false; } public static bool reviveRandomPlayer(IChatMessage message) { //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) List<PlayerAvatar> list = new List<PlayerAvatar>(); foreach (PlayerAvatar player in GameDirector.instance.PlayerList) { if (canRevicePlayer(player)) { list.Add(player); } } if (list.Count == 0) { return false; } list.ToArray(); int index = Random.Range(0, list.Count); PlayerAvatar val = list[index]; val.Revive(true); MissionUI.instance.MissionText(val.playerName + " was revived by " + message.DisplayName + "!", Color.green, Color.green, 3f); return true; } public static void healPlayer(PlayerAvatar avatar) { PlayerHealth playerHealth = avatar.playerHealth; FieldInfo fieldInfo = AccessTools.Field(typeof(PlayerHealth), "maxHealth"); FieldInfo fieldInfo2 = AccessTools.Field(typeof(PlayerHealth), "health"); if (fieldInfo != null && fieldInfo2 != null) { avatar.playerHealth.Heal((int)fieldInfo.GetValue(playerHealth), true); StatsManager.instance.SetPlayerHealth(SemiFunc.PlayerGetSteamID(avatar), (int)fieldInfo2.GetValue(playerHealth), false); LogManagerWrapper.LogInfo(SemiFunc.PlayerGetName(avatar) + " Healed!"); } else { LogManagerWrapper.LogError("Failed to grab field 'PlayerHealth->maxHealth' or 'PlayerHealth->health'!"); } } public static void HandleTTSCommand(IChatMessage message) { ChatManager.instance.ForceSendMessage(message.FullText); LogManagerWrapper.LogInfo("Handling TTS: " + message.FullText + " requested by " + message.DisplayName); } public static void giveCrown(PlayerAvatar avatar) { SessionManager.instance.crownedPlayerSteamID = SemiFunc.PlayerGetSteamID(avatar); SessionManager.instance.CrownPlayer(); } public static void teleportTo(PlayerAvatar avatar) { teleport(PlayerAvatar.instance, avatar); } public static void summon(PlayerAvatar avatar) { teleport(avatar, PlayerAvatar.instance); } private static void teleport(PlayerAvatar from, PlayerAvatar to) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: 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) //IL_0034: 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_004a: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Expected O, but got Unknown //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) Vector3 position = ((Component)to).transform.position; Quaternion rotation = ((Component)to).transform.rotation; if (to.deadSet) { position = ((Component)to.playerDeathHead.physGrabObject).transform.position; rotation = ((Component)to.playerDeathHead.physGrabObject).transform.rotation; } if (!SemiFunc.IsMultiplayer()) { from.Spawn(position, rotation); } else if ((Object)from.photonView != (Object)null) { if (from.deadSet) { from.playerDeathHead.physGrabObject.Teleport(position, rotation); return; } from.photonView.RPC("SpawnRPC", (RpcTarget)1, new object[2] { position, rotation }); } } } } namespace TwitchIntegration.Game.Commands { public class ChannelCommand : InGameCommand { public ChannelCommand() : base("channel") { } public override void Execute(IChatMessage message) { LogManagerWrapper.LogInfo("ChannelCommand(" + string.Join(" ", message.CommandArgs) + ")"); string text = string.Join(" ", message.CommandArgs); Plugin instance = Plugin.Instance; if ((Object)(object)instance == (Object)null) { LogManagerWrapper.LogError("Plugin instance is null"); return; } ((BaseUnityPlugin)instance).Config.Save(); try { API.Connect(text); } catch (Exception ex) { LogManagerWrapper.LogError("Error switching Twitch channel: " + ex.Message); } } } public abstract class InGameCommand : ICommand { public string CommandName { get; } public InGameCommand(string name) { CommandName = name; } public bool CanHandle(IChatMessage message) { if (!(message is GameChatMessage)) { return false; } return message.IsValidCommand && message.CommandName.Equals(CommandName, StringComparison.OrdinalIgnoreCase); } public abstract void Execute(IChatMessage message); } } namespace TwitchIntegration.UI { public class CoroutineRunner : MonoBehaviour { private void Awake() { ((Object)this).hideFlags = (HideFlags)61; } } public class MessageUI { public GameObject container; public TextMeshProUGUI text; public Image background; public bool isVisible = true; private float messageFadeAlpha = 1f; private CanvasGroup messageCanvasGroup; private GameObject badgeContainer; private HorizontalLayoutGroup badgeLayout; private List<Image> badgeImages = new List<Image>(); private List<Image> emoteImages = new List<Image>(); public TwitchChatMessage twitchChatMessage; private CoroutineRunner coroutineRunner; public DateTime timestamp => twitchChatMessage.Timestamp; public MessageUI(GameObject parent, TwitchChatMessage chatMessage) { //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Expected O, but got Unknown //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Expected O, but got Unknown //IL_012e: Unknown result type (might be due to invalid IL or missing references) //IL_014b: Unknown result type (might be due to invalid IL or missing references) //IL_0161: Unknown result type (might be due to invalid IL or missing references) //IL_0177: Unknown result type (might be due to invalid IL or missing references) //IL_018d: Unknown result type (might be due to invalid IL or missing references) //IL_01a3: Unknown result type (might be due to invalid IL or missing references) //IL_01b4: Unknown result type (might be due to invalid IL or missing references) //IL_01be: Expected O, but got Unknown //IL_01f2: Unknown result type (might be due to invalid IL or missing references) //IL_0208: 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) //IL_0234: Unknown result type (might be due to invalid IL or missing references) //IL_024a: Unknown result type (might be due to invalid IL or missing references) //IL_0260: Unknown result type (might be due to invalid IL or missing references) //IL_0270: Unknown result type (might be due to invalid IL or missing references) //IL_0277: Expected O, but got Unknown //IL_02af: Unknown result type (might be due to invalid IL or missing references) //IL_02c5: Unknown result type (might be due to invalid IL or missing references) //IL_02d2: Unknown result type (might be due to invalid IL or missing references) //IL_02df: Unknown result type (might be due to invalid IL or missing references) //IL_02ec: Unknown result type (might be due to invalid IL or missing references) //IL_02f9: Unknown result type (might be due to invalid IL or missing references) //IL_0357: Unknown result type (might be due to invalid IL or missing references) //IL_0361: Expected O, but got Unknown //IL_0386: Unknown result type (might be due to invalid IL or missing references) //IL_038d: Expected O, but got Unknown //IL_03ca: Unknown result type (might be due to invalid IL or missing references) //IL_0422: Unknown result type (might be due to invalid IL or missing references) //IL_0439: Unknown result type (might be due to invalid IL or missing references) //IL_0446: Unknown result type (might be due to invalid IL or missing references) //IL_045d: Unknown result type (might be due to invalid IL or missing references) //IL_0474: Unknown result type (might be due to invalid IL or missing references) //IL_0556: Unknown result type (might be due to invalid IL or missing references) //IL_058e: Unknown result type (might be due to invalid IL or missing references) //IL_05c3: Unknown result type (might be due to invalid IL or missing references) //IL_0600: Unknown result type (might be due to invalid IL or missing references) container = new GameObject("MessageContainer"); container.transform.SetParent(parent.transform, false); RectTransform val = container.AddComponent<RectTransform>(); val.anchorMin = new Vector2(0f, 0f); val.anchorMax = new Vector2(1f, 0f); val.pivot = new Vector2(0.5f, 0f); val.sizeDelta = new Vector2(0f, 0f); messageCanvasGroup = container.AddComponent<CanvasGroup>(); messageCanvasGroup.alpha = messageFadeAlpha * ConfigManager.Opacity; GameObject val2 = new GameObject("Background"); val2.transform.SetParent(container.transform, false); background = val2.AddComponent<Image>(); ((Graphic)background).color = new Color(0.1f, 0.1f, 0.1f, 0f); RectTransform component = val2.GetComponent<RectTransform>(); component.anchorMin = new Vector2(0f, 0f); component.anchorMax = new Vector2(1f, 1f); component.sizeDelta = new Vector2(-8f, -2f); component.offsetMin = new Vector2(0f, 0f); component.offsetMax = new Vector2(0f, 0f); badgeContainer = new GameObject("BadgeContainer"); badgeContainer.transform.SetParent(container.transform, false); RectTransform val3 = badgeContainer.AddComponent<RectTransform>(); val3.anchorMin = new Vector2(0f, 1f); val3.anchorMax = new Vector2(0f, 1f); val3.pivot = new Vector2(0f, 1f); val3.sizeDelta = new Vector2(0f, 0f); val3.offsetMin = new Vector2(2f, -2f); val3.offsetMax = new Vector2(2f, -2f); GameObject val4 = new GameObject("BadgeContainerBackground"); val4.transform.SetParent(badgeContainer.transform, false); Image val5 = val4.AddComponent<Image>(); ((Graphic)val5).color = new Color(0f, 0f, 0f, 0.1f); RectTransform component2 = val4.GetComponent<RectTransform>(); component2.anchorMin = Vector2.zero; component2.anchorMax = Vector2.one; component2.sizeDelta = Vector2.zero; component2.offsetMin = Vector2.zero; component2.offsetMax = Vector2.zero; badgeLayout = badgeContainer.AddComponent<HorizontalLayoutGroup>(); ((HorizontalOrVerticalLayoutGroup)badgeLayout).spacing = 1f; ((LayoutGroup)badgeLayout).childAlignment = (TextAnchor)0; ((HorizontalOrVerticalLayoutGroup)badgeLayout).childForceExpandWidth = false; ((HorizontalOrVerticalLayoutGroup)badgeLayout).childForceExpandHeight = false; ((LayoutGroup)badgeLayout).padding = new RectOffset(0, 0, 0, 0); ContentSizeFitter val6 = badgeContainer.AddComponent<ContentSizeFitter>(); val6.horizontalFit = (FitMode)2; val6.verticalFit = (FitMode)2; GameObject val7 = new GameObject("Text"); val7.transform.SetParent(container.transform, false); this.text = val7.AddComponent<TextMeshProUGUI>(); ((TMP_Text)this.text).fontSize = ConfigManager.FontSize; ((Graphic)this.text).color = Color.white; ((Graphic)this.text).raycastTarget = false; ((TMP_Text)this.text).richText = true; ((TMP_Text)this.text).alignment = (TextAlignmentOptions)513; ((TMP_Text)this.text).overflowMode = (TextOverflowModes)0; RectTransform component3 = val7.GetComponent<RectTransform>(); component3.anchorMin = new Vector2(0f, 0f); component3.anchorMax = new Vector2(1f, 1f); component3.sizeDelta = Vector2.zero; component3.offsetMin = new Vector2(5f, 1f); component3.offsetMax = new Vector2(-5f, -1f); coroutineRunner = container.AddComponent<CoroutineRunner>(); twitchChatMessage = chatMessage; foreach (TwitchChatMessage.Badge badge in chatMessage.Badges) { AddBadge(badge.Id); } string text = MessageUtilities.FormatMessageText(chatMessage); ((TMP_Text)this.text).text = text; foreach (TwitchChatMessage.Emote emote in chatMessage.Emotes) { AddEmote(emote.Code); } if (chatMessage.IsHighlightedMessage) { ((Graphic)background).color = new Color(0.1f, 0.29f, 0.35f, 0.3f); } else if (chatMessage.IsUserNotice) { ((Graphic)background).color = new Color(0.54f, 0.17f, 0.89f, 0.3f); } else if (chatMessage.IsFirstMessage) { ((Graphic)background).color = new Color(0.2f, 0.8f, 0.2f, 0.3f); } else if (!string.IsNullOrEmpty(chatMessage.CustomRewardId)) { ((Graphic)background).color = new Color(1f, 0.84f, 0f, 0.3f); } } private void AddEmote(string emoteCode) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Expected O, but got Unknown //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Unknown result type (might be due to invalid IL or missing references) if (!string.IsNullOrEmpty(emoteCode) && TwitchEmotes.TryGetEmoteSprite(ConfigManager.TwitchChannel, emoteCode, out var sprite)) { GameObject val = new GameObject("Emote"); val.transform.SetParent(((TMP_Text)text).transform.parent, false); LayoutElement val2 = val.AddComponent<LayoutElement>(); float num5 = (val2.minHeight = (val2.minWidth = (val2.preferredHeight = (val2.preferredWidth = ConfigManager.FontSize * 1.2f)))); Image val3 = val.AddComponent<Image>(); val3.preserveAspect = true; ((Graphic)val3).raycastTarget = false; val3.sprite = sprite; ((Behaviour)val3).enabled = true; RectTransform component = val.GetComponent<RectTransform>(); component.anchorMin = new Vector2(0f, 0f); component.anchorMax = new Vector2(0f, 0f); component.pivot = new Vector2(0.5f, 0.5f); component.sizeDelta = new Vector2(num5, num5); emoteImages.Add(val3); LayoutRebuilder.ForceRebuildLayoutImmediate(container.GetComponent<RectTransform>()); } } public void ClearEmotes() { foreach (Image emoteImage in emoteImages) { if ((Object)(object)emoteImage != (Object)null && (Object)(object)((Component)emoteImage).gameObject != (Object)null) { Object.Destroy((Object)(object)((Component)emoteImage).gameObject); } } emoteImages.Clear(); } public void AddBadge(string badgeId) { //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Expected O, but got Unknown //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Expected O, but got Unknown //IL_010f: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_0129: Unknown result type (might be due to invalid IL or missing references) //IL_0140: Unknown result type (might be due to invalid IL or missing references) //IL_0157: Unknown result type (might be due to invalid IL or missing references) if (string.IsNullOrEmpty(badgeId)) { return; } Sprite badgeSprite = TwitchBadges.GetBadgeSprite(badgeId); if (!((Object)(object)badgeSprite == (Object)null)) { if ((Object)(object)coroutineRunner == (Object)null) { LogManagerWrapper.LogError("CoroutineRunner is null! Creating new one..."); coroutineRunner = container.AddComponent<CoroutineRunner>(); } GameObject val = new GameObject("Badge_" + badgeId); val.transform.SetParent(badgeContainer.transform, false); LayoutElement val2 = val.AddComponent<LayoutElement>(); float minHeight = (val2.minWidth = (val2.preferredHeight = (val2.preferredWidth = ConfigManager.FontSize * 1.2f))); val2.minHeight = minHeight; GameObject val3 = new GameObject("BadgeImage"); val3.transform.SetParent(val.transform, false); Image val4 = val3.AddComponent<Image>(); val4.preserveAspect = true; ((Graphic)val4).raycastTarget = false; val4.sprite = badgeSprite; ((Behaviour)val4).enabled = true; RectTransform component = val3.GetComponent<RectTransform>(); component.anchorMin = Vector2.zero; component.anchorMax = Vector2.one; component.sizeDelta = Vector2.zero; component.offsetMin = new Vector2(2f, 0f); component.offsetMax = new Vector2(0f, 0f); badgeImages.Add(val4); LayoutRebuilder.ForceRebuildLayoutImmediate(badgeContainer.GetComponent<RectTransform>()); LayoutRebuilder.ForceRebuildLayoutImmediate(container.GetComponent<RectTransform>()); } } public void ClearBadges() { foreach (Image badgeImage in badgeImages) { if ((Object)(object)badgeImage != (Object)null && (Object)(object)((Component)badgeImage).gameObject != (Object)null) { Object.Destroy((Object)(object)((Component)badgeImage).gameObject); } } badgeImages.Clear(); } public void Destroy() { if ((Object)(object)container != (Object)null) { ClearBadges(); ClearEmotes(); Object.Destroy((Object)(object)container); } } public void UpdateFontSize() { ((TMP_Text)text).fontSize = ConfigManager.FontSize; UpdateOpacity(); } public void UpdateOpacity() { messageCanvasGroup.alpha = messageFadeAlpha * ConfigManager.Opacity; } public void SetFadeAlpha(float alpha) { messageFadeAlpha = alpha; UpdateOpacity(); } } public static class MessageUtilities { private static readonly Regex sanitizeRegex = new Regex("[^a-zA-Z0-9\\s.,;:!?\\-()]", RegexOptions.Compiled); private static readonly Regex whitespaceRegex = new Regex("\\s+", RegexOptions.Compiled); private static readonly Regex colorRegex = new Regex("^#?([0-9A-Fa-f]{6})([0-9A-Fa-f]{2})?$", RegexOptions.Compiled); internal static string FormatMessageText(TwitchChatMessage message) { if (message == null) { return "[Message formatting error]"; } string text = message.DisplayName ?? "Anonymous"; string input = message.FullText ?? ""; string text2 = Sanitize(input); string text3 = FormatColor(message.Color); string text4 = ""; int count = message.Badges.Count; text4 = new string(' ', count * 5); if (message.IsHighlightedMessage) { return text4 + "<color=" + text3 + ">" + text + "</color> <color=#FFA500>★</color> " + text2; } return string.IsNullOrEmpty(text) ? text2 : (text4 + "<color=" + text3 + ">" + text + "</color> " + text2); } internal static string Sanitize(string input) { if (string.IsNullOrWhiteSpace(input)) { return string.Empty; } try { if (input.Length > 500) { input = input.Substring(0, 500) + "..."; } string text = HttpUtility.HtmlDecode(input).Replace("<", "<").Replace(">", ">"); string text2 = text.Normalize(NormalizationForm.FormD); StringBuilder stringBuilder = new StringBuilder(text2.Length); foreach (char c in text2) { if (CharUnicodeInfo.GetUnicodeCategory(c) != UnicodeCategory.NonSpacingMark) { stringBuilder.Append(c); } } string input2 = Regex.Replace(stringBuilder.ToString(), "[\\p{C}]", ""); return whitespaceRegex.Replace(input2, " ").Trim(); } catch (Exception ex) { LogManagerWrapper.LogError("Sanitize error: " + ex.Message); return "[Text processing error]"; } } internal static string FormatColor(string color) { if (string.IsNullOrEmpty(color)) { return "#FF6B6B"; } color = color.TrimStart('#'); Match match = colorRegex.Match(color); if (!match.Success) { return "#FF6B6B"; } string value = match.Groups[1].Value; string text = (match.Groups[2].Success ? match.Groups[2].Value : "FF"); return "#" + value + text; } } public class ChatWindow : MonoBehaviour { [CompilerGenerated] private sealed class <DelayedInitialization>d__41 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public ChatWindow <>4__this; private Transform <parent>5__1; private GameObject <container>5__2; private GameObject <labelsContainer>5__3; private RectTransform <labelsRect>5__4; private GameObject <toggleKeyObj>5__5; private RectTransform <toggleKeyRect>5__6; private GameObject <channelObj>5__7; private RectTransform <channelRect>5__8; private Image <background>5__9; private GameObject <scrollView>5__10; private RectTransform <scrollViewRect>5__11; private GameObject <viewport>5__12; private RectTransform <viewportRect>5__13; private GameObject <content>5__14; private RectTransform <messagesRect>5__15; private float <initialWidth>5__16; private float <initialHeight>5__17; private Exception <ex>5__18; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <DelayedInitialization>d__41(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <parent>5__1 = null; <container>5__2 = null; <labelsContainer>5__3 = null; <labelsRect>5__4 = null; <toggleKeyObj>5__5 = null; <toggleKeyRect>5__6 = null; <channelObj>5__7 = null; <channelRect>5__8 = null; <background>5__9 = null; <scrollView>5__10 = null; <scrollViewRect>5__11 = null; <viewport>5__12 = null; <viewportRect>5__13 = null; <content>5__14 = null; <messagesRect>5__15 = null; <ex>5__18 = null; <>1__state = -2; } private bool MoveNext() { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Expected O, but got Unknown //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Expected O, but got Unknown //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Expected O, but got Unknown //IL_00f8: 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_012e: Unknown result type (might be due to invalid IL or missing references) //IL_0149: Unknown result type (might be due to invalid IL or missing references) //IL_0164: Unknown result type (might be due to invalid IL or missing references) //IL_0175: Unknown result type (might be due to invalid IL or missing references) //IL_017f: Expected O, but got Unknown //IL_01ce: Unknown result type (might be due to invalid IL or missing references) //IL_01ff: Unknown result type (might be due to invalid IL or missing references) //IL_023a: Unknown result type (might be due to invalid IL or missing references) //IL_0255: Unknown result type (might be due to invalid IL or missing references) //IL_0270: Unknown result type (might be due to invalid IL or missing references) //IL_028b: Unknown result type (might be due to invalid IL or missing references) //IL_02a6: Unknown result type (might be due to invalid IL or missing references) //IL_02e2: Unknown result type (might be due to invalid IL or missing references) //IL_02ec: Expected O, but got Unknown //IL_033b: Unknown result type (might be due to invalid IL or missing references) //IL_0393: Unknown result type (might be due to invalid IL or missing references) //IL_03ae: Unknown result type (might be due to invalid IL or missing references) //IL_03c9: Unknown result type (might be due to invalid IL or missing references) //IL_03e4: Unknown result type (might be due to invalid IL or missing references) //IL_03ff: Unknown result type (might be due to invalid IL or missing references) //IL_0460: Unknown result type (might be due to invalid IL or missing references) //IL_047e: Unknown result type (might be due to invalid IL or missing references) //IL_0488: Expected O, but got Unknown //IL_04d2: Unknown result type (might be due to invalid IL or missing references) //IL_04e3: Unknown result type (might be due to invalid IL or missing references) //IL_04f4: Unknown result type (might be due to invalid IL or missing references) //IL_0505: Unknown result type (might be due to invalid IL or missing references) //IL_0516: Unknown result type (might be due to invalid IL or missing references) //IL_0527: Unknown result type (might be due to invalid IL or missing references) //IL_0531: Expected O, but got Unknown //IL_0565: Unknown result type (might be due to invalid IL or missing references) //IL_0576: Unknown result type (might be due to invalid IL or missing references) //IL_0587: Unknown result type (might be due to invalid IL or missing references) //IL_0598: Unknown result type (might be due to invalid IL or missing references) //IL_05a9: Unknown result type (might be due to invalid IL or missing references) //IL_05d1: Unknown result type (might be due to invalid IL or missing references) //IL_05e2: Unknown result type (might be due to invalid IL or missing references) //IL_05ec: Expected O, but got Unknown //IL_0634: Unknown result type (might be due to invalid IL or missing references) //IL_0654: Unknown result type (might be due to invalid IL or missing references) //IL_0674: Unknown result type (might be due to invalid IL or missing references) //IL_0694: Unknown result type (might be due to invalid IL or missing references) //IL_06aa: Unknown result type (might be due to invalid IL or missing references) //IL_06b4: Expected O, but got Unknown //IL_06f2: Unknown result type (might be due to invalid IL or missing references) //IL_0703: Unknown result type (might be due to invalid IL or missing references) //IL_0714: Unknown result type (might be due to invalid IL or missing references) //IL_072f: Unknown result type (might be due to invalid IL or missing references) //IL_074a: Unknown result type (might be due to invalid IL or missing references) //IL_07fd: Unknown result type (might be due to invalid IL or missing references) switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = (object)new WaitForEndOfFrame(); <>1__state = 1; return true; case 1: <>1__state = -1; try { LogManagerWrapper.LogInfo("Starting DelayedInitialization"); <parent>5__1 = ((Component)<>4__this).transform.parent ?? ((Component)<>4__this).transform; <container>5__2 = new GameObject("ChatWindowContainer"); <container>5__2.transform.SetParent(<parent>5__1, false); <>4__this.containerRect = <container>5__2.AddComponent<RectTransform>(); <labelsContainer>5__3 = new GameObject("LabelsContainer"); <labelsContainer>5__3.transform.SetParent(<container>5__2.transform, false); <labelsRect>5__4 = <labelsContainer>5__3.AddComponent<RectTransform>(); <labelsRect>5__4.anchorMin = new Vector2(0f, 0f); <labelsRect>5__4.anchorMax = new Vector2(1f, 0f); <labelsRect>5__4.pivot = new Vector2(0.5f, 0f); <labelsRect>5__4.sizeDelta = new Vector2(0f, 48f); <labelsRect>5__4.anchoredPosition = new Vector2(0f, -30f); <toggleKeyObj>5__5 = new GameObject("ToggleKeyLabel"); <toggleKeyObj>5__5.transform.SetParent((Transform)(object)<labelsRect>5__4, false); <>4__this.toggleKeyLabel = <toggleKeyObj>5__5.AddComponent<TextMeshProUGUI>(); ((TMP_Text)<>4__this.toggleKeyLabel).fontSize = 8f; ((Graphic)<>4__this.toggleKeyLabel).color = Color.white; ((TMP_Text)<>4__this.toggleKeyLabel).alignment = (TextAlignmentOptions)513; ((TMP_Text)<>4__this.toggleKeyLabel).text = $"[{ConfigManager.SettingsMenuKey}] Channel: {ConfigManager.TwitchChannel}"; <toggleKeyRect>5__6 = <toggleKeyObj>5__5.GetComponent<RectTransform>(); <toggleKeyRect>5__6.anchorMin = new Vector2(0f, 0.5f); <toggleKeyRect>5__6.anchorMax = new Vector2(1f, 0.5f); <toggleKeyRect>5__6.pivot = new Vector2(0f, 0.5f); <toggleKeyRect>5__6.sizeDelta = new Vector2(0f, 24f); <toggleKeyRect>5__6.anchoredPosition = new Vector2(10f, 0f); LogManagerWrapper.LogInfo($"Setting initial toggleKeyLabel visibility to: {ConfigManager.ShowLabels}"); <toggleKeyObj>5__5.SetActive(ConfigManager.ShowLabels); <channelObj>5__7 = new GameObject("ChannelLabel"); <channelObj>5__7.transform.SetParent((Transform)(object)<labelsRect>5__4, false); <>4__this.channelLabel = <channelObj>5__7.AddComponent<TextMeshProUGUI>(); ((TMP_Text)<>4__this.channelLabel).fontSize = 8f; ((Graphic)<>4__this.channelLabel).color = Color.white; ((TMP_Text)<>4__this.channelLabel).alignment = (TextAlignmentOptions)516; ((TMP_Text)<>4__this.channelLabel).text = ""; <channelRect>5__8 = <channelObj>5__7.GetComponent<RectTransform>(); <channelRect>5__8.anchorMin = new Vector2(0f, 0.5f); <channelRect>5__8.anchorMax = new Vector2(1f, 0.5f); <channelRect>5__8.pivot = new Vector2(1f, 0.5f); <channelRect>5__8.sizeDelta = new Vector2(0f, 24f); <channelRect>5__8.anchoredPosition = new Vector2(-10f, 0f); LogManagerWrapper.LogInfo($"Setting initial channelLabel visibility to: {ConfigManager.ShowLabels}"); <channelObj>5__7.SetActive(ConfigManager.ShowLabels); <background>5__9 = <container>5__2.AddComponent<Image>(); ((Graphic)<background>5__9).color = new Color(0f, 0f, 0f, ConfigManager.BackgroundOpacity); ((Behaviour)<background>5__9).enabled = true; <scrollView>5__10 = new GameObject("ScrollView"); <scrollView>5__10.transform.SetParent(<container>5__2.transform, false); <>4__this.scrollRect = <scrollView>5__10.AddComponent<ScrollRect>(); <scrollViewRect>5__11 = <scrollView>5__10.GetComponent<RectTransform>(); <scrollViewRect>5__11.anchorMin = Vector2.zero; <scrollViewRect>5__11.anchorMax = Vector2.one; <scrollViewRect>5__11.sizeDelta = Vector2.zero; <scrollViewRect>5__11.offsetMin = Vector2.zero; <scrollViewRect>5__11.offsetMax = Vector2.zero; <viewport>5__12 = new GameObject("Viewport"); <viewport>5__12.transform.SetParent(<scrollView>5__10.transform, false); <viewportRect>5__13 = <viewport>5__12.AddComponent<RectTransform>(); <viewportRect>5__13.anchorMin = Vector2.zero; <viewportRect>5__13.anchorMax = Vector2.one; <viewportRect>5__13.sizeDelta = Vector2.zero; <viewportRect>5__13.offsetMin = Vector2.zero; <viewportRect>5__13.offsetMax = Vector2.zero; <viewport>5__12.AddComponent<Mask>().showMaskGraphic = false; ((Graphic)<viewport>5__12.AddComponent<Image>()).color = Color.white; <content>5__14 = new GameObject("Content"); <content>5__14.transform.SetParent(<viewport>5__12.transform, false); <>4__this.contentRect = <content>5__14.AddComponent<RectTransform>(); <>4__this.contentRect.anchorMin = new Vector2(0f, 0f); <>4__this.contentRect.anchorMax = new Vector2(1f, 1f); <>4__this.contentRect.pivot = new Vector2(0.5f, 0f); <>4__this.contentRect.sizeDelta = new Vector2(0f, 0f); <>4__this.messagesContainer = new GameObject("MessagesContainer"); <>4__this.messagesContainer.transform.SetParent(<content>5__14.transform, false); <messagesRect>5__15 = <>4__this.messagesContainer.AddComponent<RectTransform>(); <messagesRect>5__15.anchorMin = Vector2.zero; <messagesRect>5__15.anchorMax = Vector2.one; <messagesRect>5__15.sizeDelta = Vector2.zero; <messagesRect>5__15.offsetMin = new Vector2(5f, 10f); <messagesRect>5__15.offsetMax = new Vector2(-5f, -10f); <>4__this.scrollRect.viewport = <viewportRect>5__13; <>4__this.scrollRect.content = <>4__this.contentRect; <>4__this.scrollRect.horizontal = false; <>4__this.scrollRect.vertical = true; <>4__this.scrollRect.scrollSensitivity = 20f; <initialWidth>5__16 = ConfigManager.Width; <initialHeight>5__17 = ConfigManager.Height; <>4__this.containerRect.sizeDelta = new Vector2(<initialWidth>5__16, ConfigManager.ChatWindowVisible ? <initialHeight>5__17 : 0f); <>4__this.originalHeight = <initialHeight>5__17; <>4__this.UpdateWindowPosition(); SceneManager.activeSceneChanged += delegate { <>4__this.UpdateWindowPosition(); LogManagerWrapper.LogInfo("Scene changed, updating UI position"); }; <>4__this.RegisterConfigListeners(); <>4__this.isInitialized = true; LogManagerWrapper.LogInfo("DelayedInitialization completed successfully"); <>4__this.RestoreMessages(); <>4__this.UpdateWindowPosition(); <parent>5__1 = null; <container>5__2 = null; <labelsContainer>5__3 = null; <labelsRect>5__4 = null; <toggleKeyObj>5__5 = null; <toggleKeyRect>5__6 = null; <channelObj>5__7 = null; <channelRect>5__8 = null; <background>5__9 = null; <scrollView>5__10 = null; <scrollViewRect>5__11 = null; <viewport>5__12 = null; <viewportRect>5__13 = null; <content>5__14 = null; <messagesRect>5__15 = null; } catch (Exception ex) { <ex>5__18 = ex; LogManagerWrapper.LogError("DelayedInitialization error: " + <ex>5__18.Message + "\n" + <ex>5__18.StackTrace); <>4__this.isInitialized = 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(); } } [CompilerGenerated] private sealed class <FadeRoutine>d__49 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public ChatWindow <>4__this; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <FadeRoutine>d__49(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; break; case 1: <>1__state = -1; break; } <>4__this.UpdateFadeAffectOfAllMessages(); <>2__current = (object)new WaitForSeconds(0.1f); <>1__state = 1; return true; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class <ProcessMessageQueueRoutine>d__35 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public ChatWindow <>4__this; private WaitForSeconds <waitTime>5__1; private Exception <ex>5__2; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <ProcessMessageQueueRoutine>d__35(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <waitTime>5__1 = null; <ex>5__2 = null; <>1__state = -2; } private bool MoveNext() { //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Expected O, but got Unknown //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; LogManagerWrapper.LogWarning("ProcessMessageQueueRoutine triggered"); <>2__current = (object)new WaitUntil((Func<bool>)(() => <>4__this.isInitialized)); <>1__state = 1; return true; case 1: <>1__state = -1; <waitTime>5__1 = new WaitForSeconds(0.1f); break; case 2: <>1__state = -1; break; } try { if (<>4__this.messageQueue.Count > 0 && !<>4__this.isProcessingMessages) { <>4__this.ProcessMessageBatch(); if ((Object)(object)<>4__this.scrollRect != (Object)null && (Object)(object)<>4__this.contentRect != (Object)null) { <>4__this.scrollRect.verticalNormalizedPosition = 0f; } } } catch (Exception ex) { <ex>5__2 = ex; LogManagerWrapper.LogError("Error in message queue processing: " + <ex>5__2.Message); } <>4__this.messageProcessedCount = 0; <>4__this.messageProcessingTime = 0f; <>4__this.lastPerformanceLog = DateTime.Now; <>2__current = <waitTime>5__1; <>1__state = 2; return true; } 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 RectTransform containerRect; public ScrollRect scrollRect; public RectTransform contentRect; private int maxMessages = 25; public bool isInitialized = false; private const float FadeOutDuration = 5f; private float lastFadeUpdate = 0f; private const float FadeUpdateInterval = 0.1f; public readonly Queue<TwitchChatMessage> messageQueue = new Queue<TwitchChatMessage>(100); private const int MaxQueueSize = 100; private bool isUpdatingPosition = false; private bool isProcessingMessages = false; private int lastScreenWidth; private int lastScreenHeight; private const string MessageTemplate = "<color=#FF6B6B>{0}</color>: {1}"; public int messageProcessedCount = 0; public float messageProcessingTime = 0f; public DateTime lastPerformanceLog = DateTime.MinValue; private TextMeshProUGUI toggleKeyLabel; private TextMeshProUGUI channelLabel; private float originalHeight; private Coroutine heightAnimationCoroutine; internal List<MessageUI> messageUIs = new List<MessageUI>(); private GameObject messagesContainer; private bool updatingFromToggle = false; private List<TwitchChatMessage> currentMessages = new List<TwitchChatMessage>(); private Coroutine fadeCoroutine; public int MessageQueueCount => messageQueue.Count; private void Awake() { try { ConfigManager.ChatWindowVisible = true; ((MonoBehaviour)this).StartCoroutine(DelayedInitialization()); lastScreenWidth = Screen.width; lastScreenHeight = Screen.height; LogManagerWrapper.LogInfo("Starting ProcessMessageQueueRoutine"); ((MonoBehaviour)this).StartCoroutine(ProcessMessageQueueRoutine()); API.OnMessage += API_OnMessageReceived; API.OnDisconnect += API_OnDisconnect; API.OnConnect += API_OnConnect; UpdateWindowPosition(); } catch (Exception ex) { LogManagerWrapper.LogError("ChatWindow Awake error: " + ex.Message); } } private void OnDestroy() { try { API.OnMessage -= API_OnMessageReceived; API.OnDisconnect -= API_OnDisconnect; foreach (MessageUI messageUI in messageUIs) { messageUI.Destroy(); } messageUIs.Clear(); LogManagerWrapper.LogInfo("ChatWindow OnDestroy called - component is being destroyed"); LogManagerWrapper.LogWarning("ChatWindow OnDestroy called - component is being DESTROYED"); if ((Object)(object)Plugin.Instance != (Object)null) { Plugin.Instance.OnChatWindowDestroyed(); } isInitialized = false; isUpdatingPosition = false; isProcessingMessages = false; if (heightAnimationCoroutine != null) { ((MonoBehaviour)this).StopCoroutine(heightAnimationCoroutine); } toggleKeyLabel = null; channelLabel = null; } catch (Exception ex) { LogManagerWrapper.LogError("OnDestroy error: " + ex.Message); } } private void OnEnable() { fadeCoroutine = ((MonoBehaviour)this).StartCoroutine(FadeRoutine()); } private void OnDisable() { isUpdatingPosition = false; isProcessingMessages = false; if (fadeCoroutine != null) { ((MonoBehaviour)this).StopCoroutine(fadeCoroutine); } } private void API_OnMessageReceived(TwitchMessage e) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) try { TwitchChatMessage item = Mappers.ToTwitchChatMessage(e); if (messageQueue.Count >= 100) { messageQueue.Dequeue(); } messageQueue.Enqueue(item); } catch (Exception ex) { LogManagerWrapper.LogError("OnMessageReceived error: " + ex.Message); } } private void API_OnDisconnect() { UpdateLabels(); } private void API_OnConnect() { UpdateLabels(); } [IteratorStateMachine(typeof(<ProcessMessageQueueRoutine>d__35))] private IEnumerator ProcessMessageQueueRoutine() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <ProcessMessageQueueRoutine>d__35(0) { <>4__this = this }; } private void ProcessMessageBatch() { if (messageQueue.Count == 0 || isProcessingMessages) { return; } isProcessingMessages = true; DateTime now = DateTime.Now; try { int num = Math.Min(messageQueue.Count, 20); List<TwitchChatMessage> list = new List<TwitchChatMessage>(); for (int i = 0; i < num; i++) { if (messageQueue.Count == 0) { break; } list.Add(messageQueue.Dequeue()); } foreach (TwitchChatMessage item in list) { CreateMessageUI(item); messageProcessedCount++; } } catch (Exception ex) { LogManagerWrapper.LogError("ProcessMessageBatch error: " + ex.Message); } finally { isProcessingMessages = false; messageProcessingTime += (float)(DateTime.Now - now).TotalMilliseconds; } } public void AddMessage(TwitchChatMessage message) { if (message == null) { return; } try { if (messageQueue.Count >= 100) { messageQueue.Dequeue(); } messageQueue.Enqueue(message); } catch (Exception ex) { LogManagerWrapper.LogError("AddMessage error: " + ex.Message); } } private void CreateMessageUI(TwitchChatMessage message) { try { if (message != null) { if (messageUIs.Count >= maxMessages) { messageUIs[0].Destroy(); messageUIs.RemoveAt(0); } messageUIs.Add(new MessageUI(messagesContainer, message)); LogManagerWrapper.LogInfo("CREATING NEW MESSAGE UI"); UpdateMessageOrderAndPositions(); } } catch (Exception ex) { LogManagerWrapper.LogError("CreateMessageUI error: " + ex.Message + "\n" + ex.StackTrace); } } public void ClearAllMessages() { try { messageQueue.Clear(); foreach (MessageUI messageUI in messageUIs) { messageUI.Destroy(); } messageUIs.Clear(); LogManagerWrapper.LogInfo($"Cleared {messageUIs.Count} messages from chat window"); } catch (Exception ex) { LogManagerWrapper.LogError("ClearAllMessages error: " + ex.Message); } } private void UpdateMessageOrderAndPositions() { //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) LogManagerWrapper.LogWarning("UpdateMessageOrderAndPositions"); if (!((Object)(object)contentRect != (Object)null) || messageUIs.Count == 0) { return; } float num = 0f; for (int num2 = messageUIs.Count - 1; num2 >= 0; num2--) { MessageUI messageUI = messageUIs[num2]; if (messageUI.isVisible) { RectTransform component = messageUI.container.GetComponent<RectTransform>(); float num3 = ((TMP_Text)messageUI.text).preferredHeight + 4f; componen