Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of TwitchChat v1.5.3
TwitchChat.dll
Decompiled 12 months 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